From b3e9c46c94dad0c81a5adcb9152521b5368c66a7 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 29 Aug 2012 22:50:56 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages further
 cleanup of LLStat removed llfloaterlagmeter

---
 indra/llcommon/llstat.cpp | 84 +++++++++--------------------------------------
 indra/llcommon/llstat.h   | 31 +++++------------
 2 files changed, 25 insertions(+), 90 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp
index 3678c8e1c1..b46d2e58b2 100644
--- a/indra/llcommon/llstat.cpp
+++ b/indra/llcommon/llstat.cpp
@@ -51,9 +51,10 @@ void LLStat::reset()
 	mNextBin = 0;
 }
 
-LLStat::LLStat(std::string name, S32 num_bins, BOOL use_frame_timer)
-:	mUseFrameTimer(use_frame_timer),
-	mNumBins(num_bins),
+LLStat::LLStat(std::string name, BOOL use_frame_timer)
+:	LLInstanceTracker<LLStat, std::string>(name),
+	mUseFrameTimer(use_frame_timer),
+	mNumBins(50),
 	mName(name),
 	mBins(NULL)
 {
@@ -61,48 +62,24 @@ LLStat::LLStat(std::string name, S32 num_bins, BOOL use_frame_timer)
 	mLastTime  = 0.f;
 
 	reset();
-
-	if (!mName.empty())
-	{
-		stat_map_t::iterator iter = getStatList().find(mName);
-		if (iter != getStatList().end())
-			llwarns << "LLStat with duplicate name: " << mName << llendl;
-		getStatList().insert(std::make_pair(mName, this));
-	}
-}
-
-LLStat::stat_map_t& LLStat::getStatList()
-{
-	static LLStat::stat_map_t stat_list;
-	return stat_list;
 }
 
-
 LLStat::~LLStat()
 {
 	delete[] mBins;
-
-	if (!mName.empty())
-	{
-		// handle multiple entries with the same name
-		stat_map_t::iterator iter = getStatList().find(mName);
-		while (iter != getStatList().end() && iter->second != this)
-			++iter;
-		getStatList().erase(iter);
-	}
-}
-
-void LLStat::start()
-{
-	if (mUseFrameTimer)
-	{
-		mBins[mNextBin].mBeginTime = sFrameTimer.getElapsedSeconds();
-	}
-	else
-	{
-		mBins[mNextBin].mBeginTime = sTimer.getElapsedTimeF64();
-	}
 }
+//
+//void LLStat::start()
+//{
+//	if (mUseFrameTimer)
+//	{
+//		mBins[mNextBin].mBeginTime = sFrameTimer.getElapsedSeconds();
+//	}
+//	else
+//	{
+//		mBins[mNextBin].mBeginTime = sTimer.getElapsedTimeF64();
+//	}
+//}
 
 void LLStat::addValue(const F32 value)
 {
@@ -299,31 +276,6 @@ F32 LLStat::getMeanPerSec() const
 	}
 }
 
-F32 LLStat::getMeanDuration() const
-{
-	F32 dur = 0.0f;
-	S32 count = 0;
-	for (S32 i=0; (i < mNumBins) && (i < mNumValues); i++)
-	{
-		if (i == mNextBin)
-		{
-			continue;
-		}
-		dur += mBins[i].mDT;
-		count++;
-	}
-
-	if (count > 0)
-	{
-		dur /= F32(count);
-		return dur;
-	}
-	else
-	{
-		return 0.f;
-	}
-}
-
 F32 LLStat::getMaxPerSec() const
 {
 	F32 value;
@@ -398,7 +350,3 @@ S32 LLStat::getNextBin() const
 	return mNextBin;
 }
 
-F64 LLStat::getLastTime() const
-{
-	return mLastTime;
-}
diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h
index 38377a010b..82a246275d 100644
--- a/indra/llcommon/llstat.h
+++ b/indra/llcommon/llstat.h
@@ -31,22 +31,18 @@
 
 #include "lltimer.h"
 #include "llframetimer.h"
+#include "llinstancetracker.h"
 
 class	LLSD;
 
 // ----------------------------------------------------------------------------
-class LL_COMMON_API LLStat
+class LL_COMMON_API LLStat : public LLInstanceTracker<LLStat, std::string>
 {
-private:
-	typedef std::multimap<std::string, LLStat*> stat_map_t;
-
-	static stat_map_t& getStatList();
-
 public:
-	LLStat(std::string name = std::string(), S32 num_bins = 32, BOOL use_frame_timer = FALSE);
+	LLStat(std::string name = std::string(), BOOL use_frame_timer = FALSE);
 	~LLStat();
 
-	void start();	// Start the timer for the current "frame", otherwise uses the time tracked from
+	//void start();	// Start the timer for the current "frame", otherwise uses the time tracked from
 					// the last addValue
 	void reset();
 	void addValue(const F32 value = 1.f); // Adds the current value being tracked, and tracks the DT.
@@ -57,23 +53,24 @@ public:
 	
 	F32 getPrev(S32 age) const;				// Age is how many "addValues" previously - zero is current
 	F32 getPrevPerSec(S32 age) const;		// Age is how many "addValues" previously - zero is current
+
 	F32 getCurrent() const;
 	F32 getCurrentPerSec() const;
 	
 	F32 getMin() const;
 	F32 getMinPerSec() const;
+
 	F32 getMean() const;
 	F32 getMeanPerSec() const;
-	F32 getMeanDuration() const;
+	
 	F32 getMax() const;
 	F32 getMaxPerSec() const;
 
 	U32 getNumValues() const;
 	S32 getNumBins() const;
 
-	F64 getLastTime() const;
 private:
-	BOOL mUseFrameTimer;
+	bool mUseFrameTimer;
 	U32 mNumValues;
 	U32 mNumBins;
 	F32 mLastValue;
@@ -93,6 +90,7 @@ private:
 		F32 mDT;
 	};
 	ValueEntry* mBins;
+
 	S32 mCurBin;
 	S32 mNextBin;
 	
@@ -100,17 +98,6 @@ private:
 
 	static LLTimer sTimer;
 	static LLFrameTimer sFrameTimer;
-	
-public:
-	static LLStat* getStat(const std::string& name)
-	{
-		// return the first stat that matches 'name'
-		stat_map_t::iterator iter = getStatList().find(name);
-		if (iter != getStatList().end())
-			return iter->second;
-		else
-			return NULL;
-	}
 };
 	
 #endif // LL_STAT_
-- 
cgit v1.2.3


From 62fcbb063a191fa4789145c3937e7bef6ce544bd Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 5 Sep 2012 18:49:28 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages first pass
 at LLTrace framework

---
 indra/llcommon/CMakeLists.txt  |   1 +
 indra/llcommon/llfasttimer.cpp |  12 +--
 indra/llcommon/llfasttimer.h   |   9 ++-
 indra/llcommon/lltrace.h       | 169 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 182 insertions(+), 9 deletions(-)
 create mode 100644 indra/llcommon/lltrace.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 87fffec0c3..05477c5fa6 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -238,6 +238,7 @@ set(llcommon_HEADER_FILES
     llthread.h
     llthreadsafequeue.h
     lltimer.h
+    lltrace.h
     lltreeiterators.h
     lltypeinfolookup.h
     lluri.h
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 6970c29092..939e332c3b 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -216,7 +216,7 @@ LLFastTimer::NamedTimer::NamedTimer(const std::string& name)
 :	mName(name),
 	mCollapsed(true),
 	mParent(NULL),
-	mTotalTimeCounter(0),
+	mTreeTimeCounter(0),
 	mCountAverage(0),
 	mCallAverage(0),
 	mNeedsSorting(false),
@@ -389,6 +389,8 @@ void LLFastTimer::NamedTimer::accumulateTimings()
 		U32 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
 		cur_data->mChildTime = 0;
 		cur_timer->mFrameState->mSelfTimeCounter += self_time_delta;
+		cur_timer->mFrameState->mTotalTimeCounter += cumulative_time_delta;
+
 		cur_timer->mStartTime = cur_time;
 
 		cur_data = &cur_timer->mLastTimerData;
@@ -403,10 +405,10 @@ void LLFastTimer::NamedTimer::accumulateTimings()
 		++it)
 	{
 		NamedTimer* timerp = (*it);
-		timerp->mTotalTimeCounter = timerp->getFrameState().mSelfTimeCounter;
+		timerp->mTreeTimeCounter = timerp->getFrameState().mSelfTimeCounter;
 		for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it)
 		{
-			timerp->mTotalTimeCounter += (*child_it)->mTotalTimeCounter;
+			timerp->mTreeTimeCounter += (*child_it)->mTreeTimeCounter;
 		}
 
 		S32 cur_frame = sCurFrameIndex;
@@ -415,8 +417,8 @@ void LLFastTimer::NamedTimer::accumulateTimings()
 			// update timer history
 			int hidx = cur_frame % HISTORY_NUM;
 
-			timerp->mCountHistory[hidx] = timerp->mTotalTimeCounter;
-			timerp->mCountAverage = ((U64)timerp->mCountAverage * cur_frame + timerp->mTotalTimeCounter) / (cur_frame+1);
+			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);
 		}
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index e42e549df5..061a37ae31 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -45,18 +45,17 @@ LL_COMMON_API void assert_main_thread();
 class LL_COMMON_API LLFastTimer
 {
 public:
-	class NamedTimer;
-
 	struct LL_COMMON_API FrameState
 	{
 		FrameState();
 		void setNamedTimer(NamedTimer* timerp) { mTimer = timerp; }
 
 		U32 				mSelfTimeCounter;
+		U32 				mTotalTimeCounter;
 		U32 				mCalls;
 		FrameState*			mParent;		// info for caller timer
 		FrameState*			mLastCaller;	// used to bootstrap tree construction
-		NamedTimer*			mTimer;
+		class NamedTimer*	mTimer;
 		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
 	};
@@ -120,7 +119,8 @@ public:
 
 		std::string	mName;
 
-		U32 		mTotalTimeCounter;
+		// 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; 
 
 		U32 		mCountAverage;
 		U32			mCallAverage;
@@ -186,6 +186,7 @@ public:
 		U32 total_time = getCPUClockCount32() - mStartTime;
 
 		frame_state->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime;
+		frame_state->mTotalTimeCounter += total_time;
 		frame_state->mActiveCount--;
 
 		// store last caller to bootstrap tree creation
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
new file mode 100644
index 0000000000..3d3ee18100
--- /dev/null
+++ b/indra/llcommon/lltrace.h
@@ -0,0 +1,169 @@
+/** 
+ * @file lltrace.h
+ * @brief Runtime statistics accumulation.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRACE_H
+#define LL_LLTRACE_H
+
+namespace LLTrace
+{
+	class Stat
+	{
+	public:
+		Stat(const char* name)
+		:	mName(name)
+		{}
+		void record() {}
+		void record(int value) {}
+		void record(float value) {}
+	private:
+		const std::string mName;
+	};
+
+	class BlockTimer
+	{
+	public:
+		BlockTimer(const char* name)
+		:	mName(name)
+		{}
+
+		struct Accumulator
+		{
+			U32 						mSelfTimeCounter;
+			U32 						mTotalTimeCounter;
+			U32 						mCalls;
+			Accumulator*				mParent;		// info for caller timer
+			Accumulator*				mLastCaller;	// used to bootstrap tree construction
+			const BlockTimer*			mTimer;			// points to block timer associated with this storage
+			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::vector<Accumulator*>	mChildren;		// currently assumed child timers
+		};
+
+		struct RecorderHead
+		{
+			struct Recorder*	mRecorder;
+			Accumulator*		mAccumulator;
+			U32					mChildTime;
+		};
+
+		struct Recorder
+		{
+			LL_FORCE_INLINE Recorder(BlockTimer& block_timer)
+			:	mLastHead(sRecorderHead)
+			{
+				mStartTime = getCPUClockCount32();
+				Accumulator* accumulator = ???; // get per-thread accumulator
+				accumulator->mActiveCount++;
+				accumulator->mCalls++;
+				accumulator->mMoveUpTree |= (accumulator->mParent->mActiveCount == 0);
+
+				// push new timer on stack
+				sRecorderHead->mRecorder = this;
+				sRecorderHead->mAccumulator = accumulator;
+				sRecorderHead->mChildTime = 0;
+			}
+
+			LL_FORCE_INLINE ~Recorder()
+			{
+				U32 total_time = getCPUClockCount32() - mStartTime;
+
+				Accumulator* accumulator = sRecorderHead->mAccumulator;
+				accumulator->mSelfTimeCounter += total_time- sRecorderHead.mChildTime;
+				accumulator->mTotalTimeCounter += total_time;
+				accumulator->mActiveCount--;
+
+				accumulator->mLastCaller = mLastHead->mAccumulator;
+				mLastHead->mChildTime += total_time;
+
+				// pop stack
+				sRecorderHead = mLastHead;
+			}
+
+			AccumulatorHead mLastHead;
+			U32 mStartTime;
+		};
+
+	private:
+		U32 getCPUClockCount32()
+		{
+			U32 ret_val;
+			__asm
+			{
+				_emit   0x0f
+					_emit   0x31
+					shr eax,8
+					shl edx,24
+					or eax, edx
+					mov dword ptr [ret_val], eax
+			}
+			return ret_val;
+		}
+
+		// return full timer value, *not* shifted by 8 bits
+		static U64 getCPUClockCount64()
+		{
+			U64 ret_val;
+			__asm
+			{
+				_emit   0x0f
+					_emit   0x31
+					mov eax,eax
+					mov edx,edx
+					mov dword ptr [ret_val+4], edx
+					mov dword ptr [ret_val], eax
+			}
+			return ret_val;
+		}
+
+		const std::string mName;
+		static RecorderHead* sRecorderHead;
+	};
+
+	BlockTimer::RecorderHead BlockTimer::sRecorderHead;
+
+	class TimeInterval 
+	{
+	public:
+		void start() {}
+		void stop() {}
+		void resume() {}
+	};
+
+	class SamplingTimeInterval
+	{
+	public:
+		void start() {}
+		void stop() {}
+		void resume() {}
+	};
+
+}
+
+#define TOKEN_PASTE_ACTUAL(x, y) x##y
+#define TOKEN_PASTE(x, y) TOKEN_PASTE_ACTUAL(x, y)
+#define RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder TOKEN_PASTE(block_time_recorder, __COUNTER__)(block_timer);
+
+#endif // LL_LLTRACE_H
-- 
cgit v1.2.3


From 6814906fec95aeb90dbc99605f74f241a72af12b Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 5 Sep 2012 18:54:26 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages build fix

---
 indra/llcommon/llfasttimer.cpp | 26 +++++++++++++-------------
 indra/llcommon/llfasttimer.h   | 12 ++++++------
 indra/llcommon/lltrace.h       |  8 ++++----
 3 files changed, 23 insertions(+), 23 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 939e332c3b..0abaf73063 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -388,8 +388,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_timer->mFrameState->mSelfTimeCounter += self_time_delta;
-		cur_timer->mFrameState->mTotalTimeCounter += cumulative_time_delta;
+		cur_data->mFrameState->mSelfTimeCounter += self_time_delta;
+		cur_data->mFrameState->mTotalTimeCounter += cumulative_time_delta;
 
 		cur_timer->mStartTime = cur_time;
 
@@ -643,16 +643,16 @@ const LLFastTimer::NamedTimer* LLFastTimer::getTimerByName(const std::string& na
 	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;
-}
+//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 061a37ae31..4660fad5e3 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -45,10 +45,12 @@ LL_COMMON_API void assert_main_thread();
 class LL_COMMON_API LLFastTimer
 {
 public:
+	class NamedTimer;
+
 	struct LL_COMMON_API FrameState
 	{
 		FrameState();
-		void setNamedTimer(NamedTimer* timerp) { mTimer = timerp; }
+		void setNamedTimer(class NamedTimer* timerp) { mTimer = timerp; }
 
 		U32 				mSelfTimeCounter;
 		U32 				mTotalTimeCounter;
@@ -152,13 +154,12 @@ public:
 	};
 
 public:
-	LLFastTimer(LLFastTimer::FrameState* state);
+	//LLFastTimer(LLFastTimer::FrameState* state);
 
 	LL_FORCE_INLINE LLFastTimer(LLFastTimer::DeclareTimer& timer)
-	:	mFrameState(&timer.mFrameState)
 	{
 #if FAST_TIMER_ON
-		LLFastTimer::FrameState* frame_state = mFrameState;
+		LLFastTimer::FrameState* frame_state = &timer.mFrameState;
 		mStartTime = getCPUClockCount32();
 
 		frame_state->mActiveCount++;
@@ -182,7 +183,7 @@ public:
 	LL_FORCE_INLINE ~LLFastTimer()
 	{
 #if FAST_TIMER_ON
-		LLFastTimer::FrameState* frame_state = mFrameState;
+		LLFastTimer::FrameState* frame_state = LLFastTimer::sCurTimerData.mFrameState;
 		U32 total_time = getCPUClockCount32() - mStartTime;
 
 		frame_state->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime;
@@ -380,7 +381,6 @@ private:
 	static U64				sLastFrameTime;
 
 	U32							mStartTime;
-	LLFastTimer::FrameState*	mFrameState;
 	LLFastTimer::CurTimerData	mLastTimerData;
 
 };
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 3d3ee18100..6323091cb8 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -81,16 +81,16 @@ namespace LLTrace
 				accumulator->mMoveUpTree |= (accumulator->mParent->mActiveCount == 0);
 
 				// push new timer on stack
-				sRecorderHead->mRecorder = this;
-				sRecorderHead->mAccumulator = accumulator;
-				sRecorderHead->mChildTime = 0;
+				sRecorderHead.mRecorder = this;
+				sRecorderHead.mAccumulator = accumulator;
+				sRecorderHead.mChildTime = 0;
 			}
 
 			LL_FORCE_INLINE ~Recorder()
 			{
 				U32 total_time = getCPUClockCount32() - mStartTime;
 
-				Accumulator* accumulator = sRecorderHead->mAccumulator;
+				Accumulator* accumulator = sRecorderHead.mAccumulator;
 				accumulator->mSelfTimeCounter += total_time- sRecorderHead.mChildTime;
 				accumulator->mTotalTimeCounter += total_time;
 				accumulator->mActiveCount--;
-- 
cgit v1.2.3


From 2cdfb170216c798c637081b0e28ec8921f0b777b Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 5 Sep 2012 19:04:53 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages renamed
 some variables in lltrace

---
 indra/llcommon/lltrace.h | 30 +++++++++++++++---------------
 1 file changed, 15 insertions(+), 15 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 6323091cb8..f3ee90a721 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -51,18 +51,18 @@ namespace LLTrace
 
 		struct Accumulator
 		{
-			U32 						mSelfTimeCounter;
 			U32 						mTotalTimeCounter;
+			U32 						mChildTimeCounter;
 			U32 						mCalls;
 			Accumulator*				mParent;		// info for caller timer
 			Accumulator*				mLastCaller;	// used to bootstrap tree construction
 			const BlockTimer*			mTimer;			// points to block timer associated with this storage
-			U16							mActiveCount;	// number of timers with this ID active on stack
+			U8							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::vector<Accumulator*>	mChildren;		// currently assumed child timers
 		};
 
-		struct RecorderHead
+		struct RecorderStackEntry
 		{
 			struct Recorder*	mRecorder;
 			Accumulator*		mAccumulator;
@@ -72,7 +72,7 @@ namespace LLTrace
 		struct Recorder
 		{
 			LL_FORCE_INLINE Recorder(BlockTimer& block_timer)
-			:	mLastHead(sRecorderHead)
+			:	mLastRecorder(sCurRecorder)
 			{
 				mStartTime = getCPUClockCount32();
 				Accumulator* accumulator = ???; // get per-thread accumulator
@@ -81,28 +81,28 @@ namespace LLTrace
 				accumulator->mMoveUpTree |= (accumulator->mParent->mActiveCount == 0);
 
 				// push new timer on stack
-				sRecorderHead.mRecorder = this;
-				sRecorderHead.mAccumulator = accumulator;
-				sRecorderHead.mChildTime = 0;
+				sCurRecorder.mRecorder = this;
+				sCurRecorder.mAccumulator = accumulator;
+				sCurRecorder.mChildTime = 0;
 			}
 
 			LL_FORCE_INLINE ~Recorder()
 			{
 				U32 total_time = getCPUClockCount32() - mStartTime;
 
-				Accumulator* accumulator = sRecorderHead.mAccumulator;
-				accumulator->mSelfTimeCounter += total_time- sRecorderHead.mChildTime;
+				Accumulator* accumulator = sCurRecorder.mAccumulator;
 				accumulator->mTotalTimeCounter += total_time;
+				accumulator->mChildTimeCounter += sCurRecorder.mChildTime;
 				accumulator->mActiveCount--;
 
-				accumulator->mLastCaller = mLastHead->mAccumulator;
-				mLastHead->mChildTime += total_time;
+				accumulator->mLastCaller = mLastRecorder->mAccumulator;
+				mLastRecorder->mChildTime += total_time;
 
 				// pop stack
-				sRecorderHead = mLastHead;
+				sCurRecorder = mLastRecorder;
 			}
 
-			AccumulatorHead mLastHead;
+			RecorderStackEntry mLastRecorder;
 			U32 mStartTime;
 		};
 
@@ -139,10 +139,10 @@ namespace LLTrace
 		}
 
 		const std::string mName;
-		static RecorderHead* sRecorderHead;
+		static RecorderStackEntry* sCurRecorder;
 	};
 
-	BlockTimer::RecorderHead BlockTimer::sRecorderHead;
+	BlockTimer::RecorderStackEntry BlockTimer::sCurRecorder;
 
 	class TimeInterval 
 	{
-- 
cgit v1.2.3


From d18a3f395fb2b29dbf83092896a5ed5eb9f75f16 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 6 Sep 2012 17:18:12 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages lltrace
 cleanup

---
 indra/llcommon/lltrace.h | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index f3ee90a721..1d2dcff9b7 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -27,6 +27,8 @@
 #ifndef LL_LLTRACE_H
 #define LL_LLTRACE_H
 
+#include <vector>
+
 namespace LLTrace
 {
 	class Stat
@@ -51,11 +53,11 @@ namespace LLTrace
 
 		struct Accumulator
 		{
-			U32 						mTotalTimeCounter;
-			U32 						mChildTimeCounter;
-			U32 						mCalls;
-			Accumulator*				mParent;		// info for caller timer
-			Accumulator*				mLastCaller;	// used to bootstrap tree construction
+			U32 						mTotalTimeCounter,
+										mChildTimeCounter,
+										mCalls;
+			Accumulator*				mParent,		// info for caller timer
+										mLastCaller;	// used to bootstrap tree construction
 			const BlockTimer*			mTimer;			// points to block timer associated with this storage
 			U8							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
-- 
cgit v1.2.3


From 8d4ceab6a34d58c5f4235baa870eb88d86df30f3 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 6 Sep 2012 23:00:32 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages further
 development of lltrace (accumulator and storage classes)

---
 indra/llcommon/lltrace.h | 111 ++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 95 insertions(+), 16 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 1d2dcff9b7..c6940c12a2 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -27,28 +27,108 @@
 #ifndef LL_LLTRACE_H
 #define LL_LLTRACE_H
 
+#include "stdtypes.h"
+#include "llpreprocessor.h"
+
 #include <vector>
+#include <boost/type_traits/alignment_of.hpp>
 
 namespace LLTrace
 {
-	class Stat
+	//TODO figure out best way to do this and proper naming convention
+	
+	static 
+	void init()
+	{
+
+	}
+
+	template<typename T>
+	class Accumulator
 	{
 	public:
-		Stat(const char* name)
-		:	mName(name)
+		Accumulator()
+		:	mSum(),
+			mMin(),
+			mMax(),
+			mNumSamples(0)
+		{}
+
+		void sample(T value)
+		{
+			mNumSamples++;
+			mSum += value;
+			if (value < mMin)
+			{
+				mMin = value;
+			}
+			else if (value > mMax)
+			{
+				mMax = value;
+			}
+		}
+
+	private:
+		T	mSum,
+			mMin,
+			mMax;
+
+		U32	mNumSamples;
+	};
+
+	class TraceStorage
+	{
+	protected:
+		TraceStorage(const size_t size, const size_t alignment)
+		{
+			mRecordOffset = sNextOffset + (alignment - 1);
+			mRecordOffset -= mRecordOffset % alignment;
+			sNextOffset = mRecordOffset + size;
+			sStorage.reserve((size_t)sNextOffset);
+		}
+
+		// this needs to be thread local
+		static std::vector<U8>	sStorage;
+		static ptrdiff_t		sNextOffset;
+
+		ptrdiff_t				mRecordOffset;
+	};
+
+	std::vector<U8> TraceStorage::sStorage;
+	ptrdiff_t TraceStorage::sNextOffset = 0;
+
+	template<typename T>
+	class Trace : public TraceStorage
+	{
+	public:
+		Trace(const std::string& name)
+		:	TraceStorage(sizeof(Accumulator<T>), boost::alignment_of<Accumulator<T> >::value),
+			mName(name)
 		{}
-		void record() {}
-		void record(int value) {}
-		void record(float value) {}
+
+		void record(T value)
+		{
+			(reinterpret_cast<Accumulator<T>* >(sStorage + mRecordOffset))->sample(value);
+		}
+
 	private:
-		const std::string mName;
+		std::string		mName;
+	};
+
+	template<typename T>
+	class Stat : public Trace<T>
+	{
+	public:
+		Stat(const char* name)
+		:	Trace(name)
+		{}
 	};
 
-	class BlockTimer
+	class BlockTimer : public Trace<U32>
 	{
 	public:
 		BlockTimer(const char* name)
-		:	mName(name)
+		:	Trace(name)
 		{}
 
 		struct Accumulator
@@ -56,8 +136,8 @@ namespace LLTrace
 			U32 						mTotalTimeCounter,
 										mChildTimeCounter,
 										mCalls;
-			Accumulator*				mParent,		// info for caller timer
-										mLastCaller;	// used to bootstrap tree construction
+			Accumulator*				mParent;		// info for caller timer
+			Accumulator*				mLastCaller;	// used to bootstrap tree construction
 			const BlockTimer*			mTimer;			// points to block timer associated with this storage
 			U8							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
@@ -97,8 +177,8 @@ namespace LLTrace
 				accumulator->mChildTimeCounter += sCurRecorder.mChildTime;
 				accumulator->mActiveCount--;
 
-				accumulator->mLastCaller = mLastRecorder->mAccumulator;
-				mLastRecorder->mChildTime += total_time;
+				accumulator->mLastCaller = mLastRecorder.mAccumulator;
+				mLastRecorder.mChildTime += total_time;
 
 				// pop stack
 				sCurRecorder = mLastRecorder;
@@ -109,7 +189,7 @@ namespace LLTrace
 		};
 
 	private:
-		U32 getCPUClockCount32()
+		static U32 getCPUClockCount32()
 		{
 			U32 ret_val;
 			__asm
@@ -140,8 +220,7 @@ namespace LLTrace
 			return ret_val;
 		}
 
-		const std::string mName;
-		static RecorderStackEntry* sCurRecorder;
+		static RecorderStackEntry sCurRecorder;
 	};
 
 	BlockTimer::RecorderStackEntry BlockTimer::sCurRecorder;
-- 
cgit v1.2.3


From a8c0d23bdeb009f6797f1dfa727e8c0cf4f6bc96 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 7 Sep 2012 18:51:38 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages created
 buffer type for storing trace data added merging logic for different trace
 types

---
 indra/llcommon/lltrace.h | 156 +++++++++++++++++++++++++++--------------------
 1 file changed, 90 insertions(+), 66 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index c6940c12a2..c5bde0330a 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -37,24 +37,57 @@ namespace LLTrace
 {
 	//TODO figure out best way to do this and proper naming convention
 	
-	static 
-	void init()
+	static void init()
 	{
 
 	}
 
+	template<typename ACCUMULATOR>
+	class Trace
+	{
+	public:
+		Trace(const std::string& name)
+		:	mName(name)
+		{
+			mStorageIndex = sNextIndex++;
+			sStorage.reserve(sNextIndex);
+		}
+
+		LL_FORCE_INLINE ACCUMULATOR& getAccumulator()
+		{
+			return sStorage[mStorageIndex];
+		}
+
+		void mergeFrom(const Trace<ACCUMULATOR>& other)
+		{
+			getAccumulator().mergeFrom(other.getAccumulator());
+		}
+
+
+	private:
+		std::string				mName;
+		ptrdiff_t				mStorageIndex;
+
+		// this needs to be thread local
+		static std::vector<ACCUMULATOR>	sStorage;
+		static size_t					sNextIndex;
+	};
+
+	template<typename ACCUMULATOR> std::vector<ACCUMULATOR> Trace<ACCUMULATOR>::sStorage;
+	template<typename ACCUMULATOR> size_t Trace<ACCUMULATOR>::sNextIndex = 0;
+
 	template<typename T>
 	class Accumulator
 	{
 	public:
 		Accumulator()
-		:	mSum(),
+			:	mSum(),
 			mMin(),
 			mMax(),
 			mNumSamples(0)
 		{}
 
-		void sample(T value)
+		LL_FORCE_INLINE void sample(T value)
 		{
 			mNumSamples++;
 			mSum += value;
@@ -68,6 +101,20 @@ namespace LLTrace
 			}
 		}
 
+		void mergeFrom(const Accumulator<T>& other)
+		{
+			mSum += other.mSum;
+			if (other.mMin < mMin)
+			{
+				mMin = other.mMin;
+			}
+			if (other.mMax > mMax)
+			{
+				mMax = other.mMax;
+			}
+			mNumSamples += other.mNumSamples;
+		}
+
 	private:
 		T	mSum,
 			mMin,
@@ -76,78 +123,55 @@ namespace LLTrace
 		U32	mNumSamples;
 	};
 
-	class TraceStorage
-	{
-	protected:
-		TraceStorage(const size_t size, const size_t alignment)
-		{
-			mRecordOffset = sNextOffset + (alignment - 1);
-			mRecordOffset -= mRecordOffset % alignment;
-			sNextOffset = mRecordOffset + size;
-			sStorage.reserve((size_t)sNextOffset);
-		}
-
-		// this needs to be thread local
-		static std::vector<U8>	sStorage;
-		static ptrdiff_t		sNextOffset;
-
-		ptrdiff_t				mRecordOffset;
-	};
-
-	std::vector<U8> TraceStorage::sStorage;
-	ptrdiff_t TraceStorage::sNextOffset = 0;
 
 	template<typename T>
-	class Trace : public TraceStorage
+	class Stat : public Trace<Accumulator<T> >
 	{
 	public:
-		Trace(const std::string& name)
-		:	TraceStorage(sizeof(Accumulator<T>), boost::alignment_of<Accumulator<T> >::value),
-			mName(name)
+		Stat(const char* name)
+		:	Trace(name)
 		{}
 
-		void record(T value)
+		void sample(T value)
 		{
-			(reinterpret_cast<Accumulator<T>* >(sStorage + mRecordOffset))->sample(value);
+			getAccumulator().sample(value);
 		}
 
-	private:
-		std::string		mName;
 	};
 
-	template<typename T>
-	class Stat : public Trace<T>
+	struct TimerAccumulator
 	{
-	public:
-		Stat(const char* name)
-		:	Trace(name)
-		{}
+		U32 							mTotalTimeCounter,
+										mChildTimeCounter,
+										mCalls;
+		TimerAccumulator*				mParent;		// info for caller timer
+		TimerAccumulator*				mLastCaller;	// used to bootstrap tree construction
+		const BlockTimer*				mTimer;			// points to block timer associated with this storage
+		U8								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::vector<TimerAccumulator*>	mChildren;		// currently assumed child timers
+
+		void mergeFrom(const TimerAccumulator& other)
+		{
+			mTotalTimeCounter += other.mTotalTimeCounter;
+			mChildTimeCounter += other.mChildTimeCounter;
+			mCalls += other.mCalls;
+		}
 	};
 
-	class BlockTimer : public Trace<U32>
+	class BlockTimer : public Trace<TimerAccumulator>
 	{
 	public:
 		BlockTimer(const char* name)
 		:	Trace(name)
 		{}
 
-		struct Accumulator
-		{
-			U32 						mTotalTimeCounter,
-										mChildTimeCounter,
-										mCalls;
-			Accumulator*				mParent;		// info for caller timer
-			Accumulator*				mLastCaller;	// used to bootstrap tree construction
-			const BlockTimer*			mTimer;			// points to block timer associated with this storage
-			U8							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::vector<Accumulator*>	mChildren;		// currently assumed child timers
-		};
+		struct Recorder;
 
 		struct RecorderStackEntry
 		{
-			struct Recorder*	mRecorder;
-			Accumulator*		mAccumulator;
+			Recorder*	mRecorder;
+			TimerAccumulator*	mAccumulator;
 			U32					mChildTime;
 		};
 
@@ -157,7 +181,7 @@ namespace LLTrace
 			:	mLastRecorder(sCurRecorder)
 			{
 				mStartTime = getCPUClockCount32();
-				Accumulator* accumulator = ???; // get per-thread accumulator
+				TimerAccumulator* accumulator = &block_timer.getAccumulator(); // get per-thread accumulator
 				accumulator->mActiveCount++;
 				accumulator->mCalls++;
 				accumulator->mMoveUpTree |= (accumulator->mParent->mActiveCount == 0);
@@ -172,7 +196,7 @@ namespace LLTrace
 			{
 				U32 total_time = getCPUClockCount32() - mStartTime;
 
-				Accumulator* accumulator = sCurRecorder.mAccumulator;
+				TimerAccumulator* accumulator = sCurRecorder.mAccumulator;
 				accumulator->mTotalTimeCounter += total_time;
 				accumulator->mChildTimeCounter += sCurRecorder.mChildTime;
 				accumulator->mActiveCount--;
@@ -195,11 +219,11 @@ namespace LLTrace
 			__asm
 			{
 				_emit   0x0f
-					_emit   0x31
-					shr eax,8
-					shl edx,24
-					or eax, edx
-					mov dword ptr [ret_val], eax
+				_emit   0x31
+				shr eax,8
+				shl edx,24
+				or eax, edx
+				mov dword ptr [ret_val], eax
 			}
 			return ret_val;
 		}
@@ -211,11 +235,11 @@ namespace LLTrace
 			__asm
 			{
 				_emit   0x0f
-					_emit   0x31
-					mov eax,eax
-					mov edx,edx
-					mov dword ptr [ret_val+4], edx
-					mov dword ptr [ret_val], eax
+				_emit   0x31
+				mov eax,eax
+				mov edx,edx
+				mov dword ptr [ret_val+4], edx
+				mov dword ptr [ret_val], eax
 			}
 			return ret_val;
 		}
@@ -233,7 +257,7 @@ namespace LLTrace
 		void resume() {}
 	};
 
-	class SamplingTimeInterval
+	class Sampler
 	{
 	public:
 		void start() {}
-- 
cgit v1.2.3


From fa91ea69cca32e0dabcfabe18070f57cc4a4cfd0 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 7 Sep 2012 19:12:41 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages added
 buffer merging and copying

---
 indra/llcommon/lltrace.h | 38 +++++++++++++++++++++++++++++++++-----
 1 file changed, 33 insertions(+), 5 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index c5bde0330a..6272492945 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -31,7 +31,6 @@
 #include "llpreprocessor.h"
 
 #include <vector>
-#include <boost/type_traits/alignment_of.hpp>
 
 namespace LLTrace
 {
@@ -42,6 +41,35 @@ namespace LLTrace
 
 	}
 
+	template<typename ACCUMULATOR>
+	struct AccumulatorStorage
+	{
+		std::vector<ACCUMULATOR> mStorage;
+		
+		ACCUMULATOR& operator[](size_t index) { return mStorage[index]; }
+
+		void mergeFrom(const AccumulatorStorage<ACCUMULATOR>& other)
+		{
+			llassert(mStorage.size() == other.mStorage.size());
+
+			for (size_t i = 0; i < mStorage.size(); i++)
+			{
+				mStorage[i].mergeFrom(other.mStorage[i]);
+			}
+		}
+
+		void copyFrom(const AccumulatorStorage<Accumulator>& other)
+		{
+			mStorage = other.mStorage;
+		}
+
+		void resize(size_t size)
+		{
+			//TODO: get this grow more rapidly (as if with push back)
+			mStorage.reserve(size);
+		}
+	};
+
 	template<typename ACCUMULATOR>
 	class Trace
 	{
@@ -50,7 +78,7 @@ namespace LLTrace
 		:	mName(name)
 		{
 			mStorageIndex = sNextIndex++;
-			sStorage.reserve(sNextIndex);
+			sStorage.resize(sNextIndex);
 		}
 
 		LL_FORCE_INLINE ACCUMULATOR& getAccumulator()
@@ -69,8 +97,8 @@ namespace LLTrace
 		ptrdiff_t				mStorageIndex;
 
 		// this needs to be thread local
-		static std::vector<ACCUMULATOR>	sStorage;
-		static size_t					sNextIndex;
+		static AccumulatorStorage<ACCUMULATOR>	sStorage;
+		static size_t							sNextIndex;
 	};
 
 	template<typename ACCUMULATOR> std::vector<ACCUMULATOR> Trace<ACCUMULATOR>::sStorage;
@@ -81,7 +109,7 @@ namespace LLTrace
 	{
 	public:
 		Accumulator()
-			:	mSum(),
+		:	mSum(),
 			mMin(),
 			mMax(),
 			mNumSamples(0)
-- 
cgit v1.2.3


From 917ed449daec0e0f91e2ff66a7d9b82866ed8b1e Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 14 Sep 2012 00:04:38 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages added
 multi-threaded sampling to LLTrace first pass at data aggregation

---
 indra/llcommon/lltrace.h | 305 +++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 256 insertions(+), 49 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 6272492945..1b9a8db1c0 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -30,45 +30,90 @@
 #include "stdtypes.h"
 #include "llpreprocessor.h"
 
-#include <vector>
+#include "llthread.h"
+
+#include <list>
 
 namespace LLTrace
 {
 	//TODO figure out best way to do this and proper naming convention
-	
 	static void init()
 	{
 
 	}
 
+	// one per thread per type
 	template<typename ACCUMULATOR>
-	struct AccumulatorStorage
+	struct AccumulatorBuffer : public AccumulatorBufferBase
 	{
-		std::vector<ACCUMULATOR> mStorage;
+		ACCUMULATOR*				mStorage;
+		size_t						mStorageSize;
+		size_t						mNextStorageSlot;
+		static S32					sStorageKey; // key used to access thread local storage pointer to accumulator values
 		
-		ACCUMULATOR& operator[](size_t index) { return mStorage[index]; }
+		AccumulatorBuffer()
+		:	mStorageSize(64),
+			mStorage(new ACCUMULATOR[64]),
+			mNextStorageSlot(0)
+		{}
+
+		AccumulatorBuffer(const AccumulatorBuffer& other)
+		:	mStorageSize(other.mStorageSize),
+			mStorage(new ACCUMULATOR[other.mStorageSize]),
+			mNextStorageSlot(other.mNextStorageSlot)
+		{
+
+		}
+
+		LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index) { return (*mStorage)[index]; }
 
-		void mergeFrom(const AccumulatorStorage<ACCUMULATOR>& other)
+		void mergeFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
 		{
-			llassert(mStorage.size() == other.mStorage.size());
+			llassert(mNextStorageSlot == other.mNextStorageSlot);
 
-			for (size_t i = 0; i < mStorage.size(); i++)
+			for (size_t i = 0; i < mNextStorageSlot; i++)
 			{
 				mStorage[i].mergeFrom(other.mStorage[i]);
 			}
 		}
 
-		void copyFrom(const AccumulatorStorage<Accumulator>& other)
+		void copyFrom(const AccumulatorBuffer<Accumulator>& other)
+		{
+			for (size_t i = 0; i < mNextStorageSlot; i++)
+			{
+				mStorage[i] = other.mStorage[i];
+			}
+		}
+
+		void reset()
+		{
+			for (size_t i = 0; i < mNextStorageSlot; i++)
+			{
+				mStorage[i].reset();
+			}
+		}
+
+		void makePrimary()
 		{
-			mStorage = other.mStorage;
+			//TODO: use sStorageKey to set mStorage as active buffer
 		}
 
-		void resize(size_t size)
+		// NOTE: this is not thread-safe.  We assume that slots are reserved in the main thread before any child threads are spawned
+		size_t reserveSlot()
 		{
-			//TODO: get this grow more rapidly (as if with push back)
-			mStorage.reserve(size);
+			size_t next_slot = mNextStorageSlot++;
+			if (next_slot >= mStorageSize)
+			{
+				size_t new_size = mStorageSize + (mStorageSize >> 2);
+				delete [] mStorage;
+				mStorage = new mStorage(new_size);
+				mStorageSize = new_size;
+			}
+			llassert(next_slot < mStorageSize);
+			return next_slot;
 		}
 	};
+	template<typename ACCUMULATOR> S32 AccumulatorBuffer<ACCUMULATOR>::sStorageKey;
 
 	template<typename ACCUMULATOR>
 	class Trace
@@ -77,38 +122,29 @@ namespace LLTrace
 		Trace(const std::string& name)
 		:	mName(name)
 		{
-			mStorageIndex = sNextIndex++;
-			sStorage.resize(sNextIndex);
+			mAccumulatorIndex = sAccumulatorBuffer.reserveSlot();
 		}
 
 		LL_FORCE_INLINE ACCUMULATOR& getAccumulator()
 		{
-			return sStorage[mStorageIndex];
-		}
-
-		void mergeFrom(const Trace<ACCUMULATOR>& other)
-		{
-			getAccumulator().mergeFrom(other.getAccumulator());
+			return sAccumulatorBuffer[mAccumulatorIndex];
 		}
 
-
 	private:
-		std::string				mName;
-		ptrdiff_t				mStorageIndex;
+		std::string	mName;
+		size_t		mAccumulatorIndex;
 
 		// this needs to be thread local
-		static AccumulatorStorage<ACCUMULATOR>	sStorage;
-		static size_t							sNextIndex;
+		static AccumulatorBuffer<ACCUMULATOR>	sAccumulatorBuffer;
 	};
 
-	template<typename ACCUMULATOR> std::vector<ACCUMULATOR> Trace<ACCUMULATOR>::sStorage;
-	template<typename ACCUMULATOR> size_t Trace<ACCUMULATOR>::sNextIndex = 0;
+	template<typename ACCUMULATOR> std::vector<ACCUMULATOR> Trace<ACCUMULATOR>::sAccumulatorBuffer;
 
 	template<typename T>
-	class Accumulator
+	class StatAccumulator
 	{
 	public:
-		Accumulator()
+		StatAccumulator()
 		:	mSum(),
 			mMin(),
 			mMax(),
@@ -129,7 +165,7 @@ namespace LLTrace
 			}
 		}
 
-		void mergeFrom(const Accumulator<T>& other)
+		void mergeFrom(const Stat<T>& other)
 		{
 			mSum += other.mSum;
 			if (other.mMin < mMin)
@@ -143,6 +179,14 @@ namespace LLTrace
 			mNumSamples += other.mNumSamples;
 		}
 
+		void reset()
+		{
+			mNumSamples = 0;
+			mSum = 0;
+			mMin = 0;
+			mMax = 0;
+		}
+
 	private:
 		T	mSum,
 			mMin,
@@ -151,12 +195,11 @@ namespace LLTrace
 		U32	mNumSamples;
 	};
 
-
-	template<typename T>
-	class Stat : public Trace<Accumulator<T> >
+	template <typename T>
+	class Stat : public Trace<StatAccumulator<T> >
 	{
 	public:
-		Stat(const char* name)
+		Stat(const std::string& name) 
 		:	Trace(name)
 		{}
 
@@ -164,7 +207,6 @@ namespace LLTrace
 		{
 			getAccumulator().sample(value);
 		}
-
 	};
 
 	struct TimerAccumulator
@@ -174,7 +216,7 @@ namespace LLTrace
 										mCalls;
 		TimerAccumulator*				mParent;		// info for caller timer
 		TimerAccumulator*				mLastCaller;	// used to bootstrap tree construction
-		const BlockTimer*				mTimer;			// points to block timer associated with this storage
+		const class BlockTimer*			mTimer;			// points to block timer associated with this storage
 		U8								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::vector<TimerAccumulator*>	mChildren;		// currently assumed child timers
@@ -185,6 +227,14 @@ namespace LLTrace
 			mChildTimeCounter += other.mChildTimeCounter;
 			mCalls += other.mCalls;
 		}
+
+		void reset()
+		{
+			mTotalTimeCounter = 0;
+			mChildTimeCounter = 0;
+			mCalls = 0;
+		}
+
 	};
 
 	class BlockTimer : public Trace<TimerAccumulator>
@@ -194,17 +244,15 @@ namespace LLTrace
 		:	Trace(name)
 		{}
 
-		struct Recorder;
-
-		struct RecorderStackEntry
-		{
-			Recorder*	mRecorder;
-			TimerAccumulator*	mAccumulator;
-			U32					mChildTime;
-		};
-
 		struct Recorder
 		{
+			struct StackEntry
+			{
+				Recorder*			mRecorder;
+				TimerAccumulator*	mAccumulator;
+				U32					mChildTime;
+			};
+
 			LL_FORCE_INLINE Recorder(BlockTimer& block_timer)
 			:	mLastRecorder(sCurRecorder)
 			{
@@ -236,7 +284,7 @@ namespace LLTrace
 				sCurRecorder = mLastRecorder;
 			}
 
-			RecorderStackEntry mLastRecorder;
+			StackEntry mLastRecorder;
 			U32 mStartTime;
 		};
 
@@ -272,10 +320,169 @@ namespace LLTrace
 			return ret_val;
 		}
 
-		static RecorderStackEntry sCurRecorder;
+		static Recorder::StackEntry sCurRecorder;
+	};
+
+	BlockTimer::Recorder::StackEntry BlockTimer::sCurRecorder;
+
+	class Sampler
+	{
+	public:
+		Sampler(const Sampler& other)
+		:	mF32Stats(other.mF32Stats),
+			mS32Stats(other.mS32Stats),
+			mTimers(other.mTimers)
+		{}
+
+		~Sampler()
+		{
+			stop();
+		}
+
+		void makePrimary()
+		{
+			mF32Stats.makePrimary();
+			mS32Stats.makePrimary();
+			mTimers.makePrimary();
+		}
+
+		void start()
+		{
+			reset();
+			resume();
+		}
+
+		void stop()
+		{
+			getThreadData()->deactivate(this);
+		}
+
+		void resume()
+		{
+			ThreadData* thread_data = getThreadData();
+			thread_data->flushPrimarySampler();
+			thread_data->activate(this);
+		}
+
+		void mergeFrom(const Sampler& other)
+		{
+			mF32Stats.mergeFrom(other.mF32Stats);
+			mS32Stats.mergeFrom(other.mS32Stats);
+			mTimers.mergeFrom(other.mTimers);
+		}
+
+		void reset()
+		{
+			mF32Stats.reset();
+			mS32Stats.reset();
+			mTimers.reset();
+		}
+
+	private:
+		// returns data for current thread
+		struct ThreadData* getThreadData() { return NULL; } 
+
+		AccumulatorBuffer<StatAccumulator<F32> >	mF32Stats;
+		AccumulatorBuffer<StatAccumulator<S32> >	mS32Stats;
+
+		AccumulatorBuffer<TimerAccumulator>			mTimers;
+	};
+
+	struct ThreadData
+	{
+		ThreadData(LLThread& this_thread, ThreadData& parent_data)
+		:	mPrimarySampler(parent_data.mPrimarySampler),
+			mSharedSampler(parent_data.mSharedSampler),
+			mSharedSamplerMutex(this_thread.getAPRPool()),
+			mParent(parent_data)
+		{
+			mPrimarySampler.makePrimary();
+			parent_data.addChildThread(this);
+		}
+
+		~ThreadData()
+		{
+			mParent.removeChildThread(this);
+		}
+
+		void addChildThread(ThreadData* child)
+		{
+			mChildThreadData.push_back(child);
+		}
+
+		void removeChildThread(ThreadData* child)
+		{
+			// TODO: replace with intrusive list
+			std::list<ThreadData*>::iterator found_it = std::find(mChildThreadData.begin(), mChildThreadData.end(), child);
+			if (found_it != mChildThreadData.end())
+			{
+				mChildThreadData.erase(found_it);
+			}
+		}
+
+		void flushPrimarySampler()
+		{
+			for (std::list<Sampler*>::iterator it = mActiveSamplers.begin(), end_it = mActiveSamplers.end();
+				it != end_it;
+				++it)
+			{
+				(*it)->mergeFrom(mPrimarySampler);
+			}
+			mPrimarySampler.reset();
+		}
+
+		void activate(Sampler* sampler)
+		{
+			mActiveSamplers.push_back(sampler);
+		}
+
+		void deactivate(Sampler* sampler)
+		{
+			// TODO: replace with intrusive list
+			std::list<Sampler*>::iterator found_it = std::find(mActiveSamplers.begin(), mActiveSamplers.end(), sampler);
+			if (found_it != mActiveSamplers.end())
+			{
+				mActiveSamplers.erase(found_it);
+			}
+		}
+		
+		// call this periodically to gather stats data in parent thread
+		void publishToParent()
+		{
+			mSharedSamplerMutex.lock();
+			{	
+				mSharedSampler.mergeFrom(mPrimarySampler);
+			}
+			mSharedSamplerMutex.unlock();
+		}
+
+		// call this periodically to gather stats data from children
+		void gatherChildData()
+		{
+			for (std::list<ThreadData*>::iterator child_it = mChildThreadData.begin(), end_it = mChildThreadData.end();
+				child_it != end_it;
+				++child_it)
+			{
+				(*child_it)->mSharedSamplerMutex.lock();
+				{
+					//TODO for now, just aggregate, later keep track of thread data independently
+					mPrimarySampler.mergeFrom((*child_it)->mSharedSampler);
+				}
+				(*child_it)->mSharedSamplerMutex.unlock();
+			}
+		}
+
+		Sampler	mPrimarySampler;
+
+		ThreadData&				mParent;
+		std::list<Sampler*>		mActiveSamplers;
+		std::list<ThreadData*>	mChildThreadData;
+
+		// TODO:  add unused space here to avoid false sharing?
+		LLMutex	mSharedSamplerMutex;
+		Sampler mSharedSampler;
 	};
 
-	BlockTimer::RecorderStackEntry BlockTimer::sCurRecorder;
 
 	class TimeInterval 
 	{
-- 
cgit v1.2.3


From d5fce3a8093bb101b7a536f3611d3135167b05c4 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 14 Sep 2012 00:08:20 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages renamed
 some variables/methods

---
 indra/llcommon/lltrace.h | 41 ++++++++++++++++++-----------------------
 1 file changed, 18 insertions(+), 23 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 1b9a8db1c0..7da182df1e 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -36,11 +36,6 @@
 
 namespace LLTrace
 {
-	//TODO figure out best way to do this and proper naming convention
-	static void init()
-	{
-
-	}
 
 	// one per thread per type
 	template<typename ACCUMULATOR>
@@ -354,13 +349,13 @@ namespace LLTrace
 
 		void stop()
 		{
-			getThreadData()->deactivate(this);
+			getThreadTracer()->deactivate(this);
 		}
 
 		void resume()
 		{
-			ThreadData* thread_data = getThreadData();
-			thread_data->flushPrimarySampler();
+			ThreadTracer* thread_data = getThreadTracer();
+			thread_data->flushData();
 			thread_data->activate(this);
 		}
 
@@ -380,7 +375,7 @@ namespace LLTrace
 
 	private:
 		// returns data for current thread
-		struct ThreadData* getThreadData() { return NULL; } 
+		struct ThreadTracer* getThreadTracer() { return NULL; } 
 
 		AccumulatorBuffer<StatAccumulator<F32> >	mF32Stats;
 		AccumulatorBuffer<StatAccumulator<S32> >	mS32Stats;
@@ -388,9 +383,9 @@ namespace LLTrace
 		AccumulatorBuffer<TimerAccumulator>			mTimers;
 	};
 
-	struct ThreadData
+	struct ThreadTracer
 	{
-		ThreadData(LLThread& this_thread, ThreadData& parent_data)
+		ThreadTracer(LLThread& this_thread, ThreadTracer& parent_data)
 		:	mPrimarySampler(parent_data.mPrimarySampler),
 			mSharedSampler(parent_data.mSharedSampler),
 			mSharedSamplerMutex(this_thread.getAPRPool()),
@@ -400,27 +395,27 @@ namespace LLTrace
 			parent_data.addChildThread(this);
 		}
 
-		~ThreadData()
+		~ThreadTracer()
 		{
 			mParent.removeChildThread(this);
 		}
 
-		void addChildThread(ThreadData* child)
+		void addChildThread(ThreadTracer* child)
 		{
-			mChildThreadData.push_back(child);
+			mChildThreadTracers.push_back(child);
 		}
 
-		void removeChildThread(ThreadData* child)
+		void removeChildThread(ThreadTracer* child)
 		{
 			// TODO: replace with intrusive list
-			std::list<ThreadData*>::iterator found_it = std::find(mChildThreadData.begin(), mChildThreadData.end(), child);
-			if (found_it != mChildThreadData.end())
+			std::list<ThreadTracer*>::iterator found_it = std::find(mChildThreadTracers.begin(), mChildThreadTracers.end(), child);
+			if (found_it != mChildThreadTracers.end())
 			{
-				mChildThreadData.erase(found_it);
+				mChildThreadTracers.erase(found_it);
 			}
 		}
 
-		void flushPrimarySampler()
+		void flushData()
 		{
 			for (std::list<Sampler*>::iterator it = mActiveSamplers.begin(), end_it = mActiveSamplers.end();
 				it != end_it;
@@ -459,7 +454,7 @@ namespace LLTrace
 		// call this periodically to gather stats data from children
 		void gatherChildData()
 		{
-			for (std::list<ThreadData*>::iterator child_it = mChildThreadData.begin(), end_it = mChildThreadData.end();
+			for (std::list<ThreadTracer*>::iterator child_it = mChildThreadTracers.begin(), end_it = mChildThreadTracers.end();
 				child_it != end_it;
 				++child_it)
 			{
@@ -474,9 +469,9 @@ namespace LLTrace
 
 		Sampler	mPrimarySampler;
 
-		ThreadData&				mParent;
-		std::list<Sampler*>		mActiveSamplers;
-		std::list<ThreadData*>	mChildThreadData;
+		ThreadTracer&				mParent;
+		std::list<Sampler*>			mActiveSamplers;
+		std::list<ThreadTracer*>	mChildThreadTracers;
 
 		// TODO:  add unused space here to avoid false sharing?
 		LLMutex	mSharedSamplerMutex;
-- 
cgit v1.2.3


From 735fde8c742188d019e41faf26ff67aab6a24d25 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 21 Sep 2012 18:52:08 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages added
 LLThreadLocalPtr broke llmutex out into llmutex.h got primary sampling buffer
 under thread local storage

---
 indra/llcommon/CMakeLists.txt     |   4 +
 indra/llcommon/llmemory.h         |   5 +
 indra/llcommon/llmutex.cpp        | 229 ++++++++++++++++++++++++++++++++
 indra/llcommon/llmutex.h          | 168 ++++++++++++++++++++++++
 indra/llcommon/llthread.cpp       | 214 +++---------------------------
 indra/llcommon/llthread.h         | 171 +++---------------------
 indra/llcommon/llthreadlocalptr.h | 141 ++++++++++++++++++++
 indra/llcommon/lltrace.cpp        |  95 ++++++++++++++
 indra/llcommon/lltrace.h          | 265 +++++++++++++++++++++-----------------
 9 files changed, 826 insertions(+), 466 deletions(-)
 create mode 100644 indra/llcommon/llmutex.cpp
 create mode 100644 indra/llcommon/llmutex.h
 create mode 100644 indra/llcommon/llthreadlocalptr.h
 create mode 100644 indra/llcommon/lltrace.cpp

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 1812e39b36..eec2695dde 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -74,6 +74,7 @@ set(llcommon_SOURCE_FILES
     llmetrics.cpp
     llmetricperformancetester.cpp
     llmortician.cpp
+    llmutex.cpp
     lloptioninterface.cpp
     llptrto.cpp 
     llprocess.cpp
@@ -99,6 +100,7 @@ set(llcommon_SOURCE_FILES
     llthread.cpp
     llthreadsafequeue.cpp
     lltimer.cpp
+    lltrace.cpp
     lluri.cpp
     lluuid.cpp
     llworkerthread.cpp
@@ -197,6 +199,7 @@ set(llcommon_HEADER_FILES
     llmetrics.h
     llmetricperformancetester.h
     llmortician.h
+    llmutex.h
     llnametable.h
     lloptioninterface.h
     llpointer.h
@@ -237,6 +240,7 @@ set(llcommon_HEADER_FILES
     llstringtable.h
     llsys.h
     llthread.h
+    llthreadlocalptr.h
     llthreadsafequeue.h
     lltimer.h
     lltrace.h
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 6a2323e7d8..4480e381e8 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -30,6 +30,11 @@
 
 class LLMutex ;
 
+#ifdef LL_WINDOWS
+#define LL_ALIGNED(x) __declspec(align(x))
+#else
+#define LL_ALIGNED(x) __attribute__ ((aligned (16)))
+#endif
 inline void* ll_aligned_malloc( size_t size, int align )
 {
 	void* mem = malloc( size + (align - 1) + sizeof(void*) );
diff --git a/indra/llcommon/llmutex.cpp b/indra/llcommon/llmutex.cpp
new file mode 100644
index 0000000000..2ce14b3a2e
--- /dev/null
+++ b/indra/llcommon/llmutex.cpp
@@ -0,0 +1,229 @@
+/** 
+ * @file llmutex.cpp
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llapr.h"
+
+#include "apr_portable.h"
+
+#include "llmutex.h"
+#include "llthread.h"
+
+//============================================================================
+
+LLMutex::LLMutex(apr_pool_t *poolp) :
+	mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD)
+{
+	//if (poolp)
+	//{
+	//	mIsLocalPool = FALSE;
+	//	mAPRPoolp = poolp;
+	//}
+	//else
+	{
+		mIsLocalPool = TRUE;
+		apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
+	}
+	apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
+}
+
+
+LLMutex::~LLMutex()
+{
+#if MUTEX_DEBUG
+	//bad assertion, the subclass LLSignal might be "locked", and that's OK
+	//llassert_always(!isLocked()); // better not be locked!
+#endif
+	apr_thread_mutex_destroy(mAPRMutexp);
+	mAPRMutexp = NULL;
+	if (mIsLocalPool)
+	{
+		apr_pool_destroy(mAPRPoolp);
+	}
+}
+
+
+void LLMutex::lock()
+{
+	if(isSelfLocked())
+	{ //redundant lock
+		mCount++;
+		return;
+	}
+	
+	apr_thread_mutex_lock(mAPRMutexp);
+	
+#if MUTEX_DEBUG
+	// Have to have the lock before we can access the debug info
+	U32 id = LLThread::currentID();
+	if (mIsLocked[id] != FALSE)
+		llerrs << "Already locked in Thread: " << id << llendl;
+	mIsLocked[id] = TRUE;
+#endif
+
+#if LL_DARWIN
+	mLockingThread = LLThread::currentID();
+#else
+	mLockingThread = LLThread::sThreadIndex;
+#endif
+}
+
+void LLMutex::unlock()
+{
+	if (mCount > 0)
+	{ //not the root unlock
+		mCount--;
+		return;
+	}
+	
+#if MUTEX_DEBUG
+	// Access the debug info while we have the lock
+	U32 id = LLThread::currentID();
+	if (mIsLocked[id] != TRUE)
+		llerrs << "Not locked in Thread: " << id << llendl;	
+	mIsLocked[id] = FALSE;
+#endif
+
+	mLockingThread = NO_THREAD;
+	apr_thread_mutex_unlock(mAPRMutexp);
+}
+
+bool LLMutex::isLocked()
+{
+	apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
+	if (APR_STATUS_IS_EBUSY(status))
+	{
+		return true;
+	}
+	else
+	{
+		apr_thread_mutex_unlock(mAPRMutexp);
+		return false;
+	}
+}
+
+bool LLMutex::isSelfLocked()
+{
+#if LL_DARWIN
+	return mLockingThread == LLThread::currentID();
+#else
+	return mLockingThread == LLThread::sThreadIndex;
+#endif
+}
+
+U32 LLMutex::lockingThread() const
+{
+	return mLockingThread;
+}
+
+//============================================================================
+
+LLCondition::LLCondition(apr_pool_t *poolp) :
+	LLMutex(poolp)
+{
+	// base class (LLMutex) has already ensured that mAPRPoolp is set up.
+
+	apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
+}
+
+
+LLCondition::~LLCondition()
+{
+	apr_thread_cond_destroy(mAPRCondp);
+	mAPRCondp = NULL;
+}
+
+
+void LLCondition::wait()
+{
+	if (!isLocked())
+	{ //mAPRMutexp MUST be locked before calling apr_thread_cond_wait
+		apr_thread_mutex_lock(mAPRMutexp);
+#if MUTEX_DEBUG
+		// avoid asserts on destruction in non-release builds
+		U32 id = LLThread::currentID();
+		mIsLocked[id] = TRUE;
+#endif
+	}
+	apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
+}
+
+void LLCondition::signal()
+{
+	apr_thread_cond_signal(mAPRCondp);
+}
+
+void LLCondition::broadcast()
+{
+	apr_thread_cond_broadcast(mAPRCondp);
+}
+
+
+//============================================================================
+
+//----------------------------------------------------------------------------
+
+//static
+LLMutex* LLThreadSafeRefCount::sMutex = 0;
+
+//static
+void LLThreadSafeRefCount::initThreadSafeRefCount()
+{
+	if (!sMutex)
+	{
+		sMutex = new LLMutex(0);
+	}
+}
+
+//static
+void LLThreadSafeRefCount::cleanupThreadSafeRefCount()
+{
+	delete sMutex;
+	sMutex = NULL;
+}
+
+
+//----------------------------------------------------------------------------
+
+LLThreadSafeRefCount::LLThreadSafeRefCount() :
+mRef(0)
+{
+}
+
+LLThreadSafeRefCount::~LLThreadSafeRefCount()
+{ 
+	if (mRef != 0)
+	{
+		llerrs << "deleting non-zero reference" << llendl;
+	}
+}
+
+//============================================================================
+
+LLResponder::~LLResponder()
+{
+}
+
+//============================================================================
diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h
new file mode 100644
index 0000000000..bd0a59b577
--- /dev/null
+++ b/indra/llcommon/llmutex.h
@@ -0,0 +1,168 @@
+/** 
+ * @file llmutex.h
+ * @brief Base classes for mutex and condition handling.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMUTEX_H
+#define LL_LLMUTEX_H
+
+#include "llapr.h"
+#include "apr_thread_cond.h"
+
+//============================================================================
+
+#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
+
+class LL_COMMON_API LLMutex
+{
+public:
+	typedef enum
+	{
+		NO_THREAD = 0xFFFFFFFF
+	} e_locking_thread;
+
+	LLMutex(apr_pool_t *apr_poolp = NULL); // NULL pool constructs a new pool for the mutex
+	virtual ~LLMutex();
+	
+	void lock();		// blocks
+	void unlock();
+	bool isLocked(); 	// non-blocking, but does do a lock/unlock so not free
+	bool isSelfLocked(); //return true if locked in a same thread
+	U32 lockingThread() const; //get ID of locking thread
+	
+protected:
+	apr_thread_mutex_t *mAPRMutexp;
+	mutable U32			mCount;
+	mutable U32			mLockingThread;
+	
+	apr_pool_t			*mAPRPoolp;
+	BOOL				mIsLocalPool;
+	
+#if MUTEX_DEBUG
+	std::map<U32, BOOL> mIsLocked;
+#endif
+};
+
+// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
+class LL_COMMON_API LLCondition : public LLMutex
+{
+public:
+	LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well.
+	~LLCondition();
+	
+	void wait();		// blocks
+	void signal();
+	void broadcast();
+	
+protected:
+	apr_thread_cond_t *mAPRCondp;
+};
+
+class LLMutexLock
+{
+public:
+	LLMutexLock(LLMutex* mutex)
+	{
+		mMutex = mutex;
+		
+		if(mMutex)
+			mMutex->lock();
+	}
+	~LLMutexLock()
+	{
+		if(mMutex)
+			mMutex->unlock();
+	}
+private:
+	LLMutex* mMutex;
+};
+
+
+//============================================================================
+
+// see llmemory.h for LLPointer<> definition
+
+class LL_COMMON_API LLThreadSafeRefCount
+{
+public:
+	static void initThreadSafeRefCount(); // creates sMutex
+	static void cleanupThreadSafeRefCount(); // destroys sMutex
+
+private:
+	static LLMutex* sMutex;
+
+private:
+	LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented
+	LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented
+
+protected:
+	virtual ~LLThreadSafeRefCount(); // use unref()
+
+public:
+	LLThreadSafeRefCount();
+
+	void ref()
+	{
+		if (sMutex) sMutex->lock();
+		mRef++; 
+		if (sMutex) sMutex->unlock();
+	} 
+
+	S32 unref()
+	{
+		llassert(mRef >= 1);
+		if (sMutex) sMutex->lock();
+		S32 res = --mRef;
+		if (sMutex) sMutex->unlock();
+		if (0 == res) 
+		{
+			delete this; 
+			return 0;
+		}
+		return res;
+	}	
+	S32 getNumRefs() const
+	{
+		return mRef;
+	}
+
+private: 
+	S32	mRef; 
+};
+
+
+//============================================================================
+
+// Simple responder for self destructing callbacks
+// Pure virtual class
+class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
+{
+protected:
+	virtual ~LLResponder();
+public:
+	virtual void completed(bool success) = 0;
+};
+
+
+#endif // LL_LLTHREAD_H
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index a6ad6b125c..f3ab8aa40c 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -29,6 +29,7 @@
 #include "apr_portable.h"
 
 #include "llthread.h"
+#include "llmutex.h"
 
 #include "lltimer.h"
 
@@ -56,12 +57,20 @@
 // 
 //----------------------------------------------------------------------------
 
-#if !LL_DARWIN
-U32 ll_thread_local sThreadID = 0;
-#endif 
+#if LL_DARWIN
+// statically allocated thread local storage not supported in Darwin executable formats
+#elif LL_WINDOWS
+U32 __declspec(thread) LLThread::sThreadIndex = 0;
+#elif LL_LINUX
+U32 __thread LLThread::sThreadID = 0;
+#endif
 
 U32 LLThread::sIDIter = 0;
 
+LLTrace::MasterThreadTrace gMasterThreadTrace;
+LLThreadLocalPtr<LLTrace::ThreadTraceData> LLThread::sTraceData(&gMasterThreadTrace);
+
+
 LL_COMMON_API void assert_main_thread()
 {
 	static U32 s_thread_id = LLThread::currentID();
@@ -78,8 +87,10 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 {
 	LLThread *threadp = (LLThread *)datap;
 
+	sTraceData = new LLTrace::SlaveThreadTrace(gMasterThreadTrace);
+
 #if !LL_DARWIN
-	sThreadID = threadp->mID;
+	sThreadIndex = threadp->mID;
 #endif
 
 	// Run the user supplied function
@@ -93,7 +104,6 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 	return NULL;
 }
 
-
 LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
 	mPaused(FALSE),
 	mName(name),
@@ -301,198 +311,12 @@ void LLThread::wakeLocked()
 	}
 }
 
-//============================================================================
-
-LLMutex::LLMutex(apr_pool_t *poolp) :
-	mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD)
-{
-	//if (poolp)
-	//{
-	//	mIsLocalPool = FALSE;
-	//	mAPRPoolp = poolp;
-	//}
-	//else
-	{
-		mIsLocalPool = TRUE;
-		apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
-	}
-	apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
-}
-
-
-LLMutex::~LLMutex()
-{
-#if MUTEX_DEBUG
-	//bad assertion, the subclass LLSignal might be "locked", and that's OK
-	//llassert_always(!isLocked()); // better not be locked!
-#endif
-	apr_thread_mutex_destroy(mAPRMutexp);
-	mAPRMutexp = NULL;
-	if (mIsLocalPool)
-	{
-		apr_pool_destroy(mAPRPoolp);
-	}
-}
-
-
-void LLMutex::lock()
-{
-	if(isSelfLocked())
-	{ //redundant lock
-		mCount++;
-		return;
-	}
-	
-	apr_thread_mutex_lock(mAPRMutexp);
-	
-#if MUTEX_DEBUG
-	// Have to have the lock before we can access the debug info
-	U32 id = LLThread::currentID();
-	if (mIsLocked[id] != FALSE)
-		llerrs << "Already locked in Thread: " << id << llendl;
-	mIsLocked[id] = TRUE;
-#endif
-
-#if LL_DARWIN
-	mLockingThread = LLThread::currentID();
-#else
-	mLockingThread = sThreadID;
-#endif
-}
-
-void LLMutex::unlock()
-{
-	if (mCount > 0)
-	{ //not the root unlock
-		mCount--;
-		return;
-	}
-	
-#if MUTEX_DEBUG
-	// Access the debug info while we have the lock
-	U32 id = LLThread::currentID();
-	if (mIsLocked[id] != TRUE)
-		llerrs << "Not locked in Thread: " << id << llendl;	
-	mIsLocked[id] = FALSE;
-#endif
-
-	mLockingThread = NO_THREAD;
-	apr_thread_mutex_unlock(mAPRMutexp);
-}
-
-bool LLMutex::isLocked()
-{
-	apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
-	if (APR_STATUS_IS_EBUSY(status))
-	{
-		return true;
-	}
-	else
-	{
-		apr_thread_mutex_unlock(mAPRMutexp);
-		return false;
-	}
-}
-
-bool LLMutex::isSelfLocked()
-{
-#if LL_DARWIN
-	return mLockingThread == LLThread::currentID();
-#else
-	return mLockingThread == sThreadID;
-#endif
-}
-
-U32 LLMutex::lockingThread() const
-{
-	return mLockingThread;
-}
-
-//============================================================================
-
-LLCondition::LLCondition(apr_pool_t *poolp) :
-	LLMutex(poolp)
-{
-	// base class (LLMutex) has already ensured that mAPRPoolp is set up.
-
-	apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
-}
-
-
-LLCondition::~LLCondition()
-{
-	apr_thread_cond_destroy(mAPRCondp);
-	mAPRCondp = NULL;
-}
-
-
-void LLCondition::wait()
-{
-	if (!isLocked())
-	{ //mAPRMutexp MUST be locked before calling apr_thread_cond_wait
-		apr_thread_mutex_lock(mAPRMutexp);
-#if MUTEX_DEBUG
-		// avoid asserts on destruction in non-release builds
-		U32 id = LLThread::currentID();
-		mIsLocked[id] = TRUE;
-#endif
-	}
-	apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
-}
-
-void LLCondition::signal()
-{
-	apr_thread_cond_signal(mAPRCondp);
-}
-
-void LLCondition::broadcast()
-{
-	apr_thread_cond_broadcast(mAPRCondp);
-}
-
-//============================================================================
-
-//----------------------------------------------------------------------------
-
-//static
-LLMutex* LLThreadSafeRefCount::sMutex = 0;
-
-//static
-void LLThreadSafeRefCount::initThreadSafeRefCount()
-{
-	if (!sMutex)
-	{
-		sMutex = new LLMutex(0);
-	}
-}
-
-//static
-void LLThreadSafeRefCount::cleanupThreadSafeRefCount()
+void LLThread::lockData()
 {
-	delete sMutex;
-	sMutex = NULL;
-}
-	
-
-//----------------------------------------------------------------------------
-
-LLThreadSafeRefCount::LLThreadSafeRefCount() :
-	mRef(0)
-{
-}
-
-LLThreadSafeRefCount::~LLThreadSafeRefCount()
-{ 
-	if (mRef != 0)
-	{
-		llerrs << "deleting non-zero reference" << llendl;
-	}
+	mRunCondition->lock();
 }
 
-//============================================================================
-
-LLResponder::~LLResponder()
+void LLThread::unlockData()
 {
+	mRunCondition->unlock();
 }
-
-//============================================================================
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index b52e70ab2e..e2de4c8b85 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -30,21 +30,21 @@
 #include "llapp.h"
 #include "llapr.h"
 #include "apr_thread_cond.h"
-
-class LLThread;
-class LLMutex;
-class LLCondition;
-
-#if LL_WINDOWS
-#define ll_thread_local __declspec(thread)
-#else
-#define ll_thread_local __thread
-#endif
+#include "lltrace.h"
+#include "llthreadlocalptr.h"
 
 class LL_COMMON_API LLThread
 {
 private:
+	friend class LLMutex;
 	static U32 sIDIter;
+#if LL_DARWIN
+	// statically allocated thread local storage not supported in Darwin executable formats
+#elif LL_WINDOWS
+	static U32 __declspec(thread) LLThread::sThreadIndex;
+#elif LL_LINUX
+	static U32 __thread LLThread::sThreadID ;
+#endif
 
 public:
 	typedef enum e_thread_status
@@ -88,6 +88,8 @@ public:
 
 	U32 getID() const { return mID; }
 
+	static LLTrace::ThreadTraceData* getTraceData() { return sTraceData.get(); }
+
 private:
 	BOOL				mPaused;
 	
@@ -96,7 +98,7 @@ private:
 
 protected:
 	std::string			mName;
-	LLCondition*		mRunCondition;
+	class LLCondition*	mRunCondition;
 
 	apr_thread_t		*mAPRThreadp;
 	apr_pool_t			*mAPRPoolp;
@@ -104,6 +106,8 @@ protected:
 	EThreadStatus		mStatus;
 	U32					mID;
 
+	static LLThreadLocalPtr<LLTrace::ThreadTraceData> sTraceData;
+
 	//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
 	//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
 	//      otherwise it will cause severe memory leaking!!! --bao
@@ -135,149 +139,4 @@ protected:
 
 //============================================================================
 
-#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
-
-class LL_COMMON_API LLMutex
-{
-public:
-	typedef enum
-	{
-		NO_THREAD = 0xFFFFFFFF
-	} e_locking_thread;
-
-	LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
-	virtual ~LLMutex();
-	
-	void lock();		// blocks
-	void unlock();
-	bool isLocked(); 	// non-blocking, but does do a lock/unlock so not free
-	bool isSelfLocked(); //return true if locked in a same thread
-	U32 lockingThread() const; //get ID of locking thread
-	
-protected:
-	apr_thread_mutex_t *mAPRMutexp;
-	mutable U32			mCount;
-	mutable U32			mLockingThread;
-	
-	apr_pool_t			*mAPRPoolp;
-	BOOL				mIsLocalPool;
-	
-#if MUTEX_DEBUG
-	std::map<U32, BOOL> mIsLocked;
-#endif
-};
-
-// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
-class LL_COMMON_API LLCondition : public LLMutex
-{
-public:
-	LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well.
-	~LLCondition();
-	
-	void wait();		// blocks
-	void signal();
-	void broadcast();
-	
-protected:
-	apr_thread_cond_t *mAPRCondp;
-};
-
-class LLMutexLock
-{
-public:
-	LLMutexLock(LLMutex* mutex)
-	{
-		mMutex = mutex;
-		
-		if(mMutex)
-			mMutex->lock();
-	}
-	~LLMutexLock()
-	{
-		if(mMutex)
-			mMutex->unlock();
-	}
-private:
-	LLMutex* mMutex;
-};
-
-//============================================================================
-
-void LLThread::lockData()
-{
-	mRunCondition->lock();
-}
-
-void LLThread::unlockData()
-{
-	mRunCondition->unlock();
-}
-
-
-//============================================================================
-
-// see llmemory.h for LLPointer<> definition
-
-class LL_COMMON_API LLThreadSafeRefCount
-{
-public:
-	static void initThreadSafeRefCount(); // creates sMutex
-	static void cleanupThreadSafeRefCount(); // destroys sMutex
-	
-private:
-	static LLMutex* sMutex;
-
-private:
-	LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented
-	LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented
-
-protected:
-	virtual ~LLThreadSafeRefCount(); // use unref()
-	
-public:
-	LLThreadSafeRefCount();
-	
-	void ref()
-	{
-		if (sMutex) sMutex->lock();
-		mRef++; 
-		if (sMutex) sMutex->unlock();
-	} 
-
-	S32 unref()
-	{
-		llassert(mRef >= 1);
-		if (sMutex) sMutex->lock();
-		S32 res = --mRef;
-		if (sMutex) sMutex->unlock();
-		if (0 == res) 
-		{
-			delete this; 
-			return 0;
-		}
-		return res;
-	}	
-	S32 getNumRefs() const
-	{
-		return mRef;
-	}
-
-private: 
-	S32	mRef; 
-};
-
-//============================================================================
-
-// Simple responder for self destructing callbacks
-// Pure virtual class
-class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
-{
-protected:
-	virtual ~LLResponder();
-public:
-	virtual void completed(bool success) = 0;
-};
-
-//============================================================================
-
 #endif // LL_LLTHREAD_H
diff --git a/indra/llcommon/llthreadlocalptr.h b/indra/llcommon/llthreadlocalptr.h
new file mode 100644
index 0000000000..f02f4849ca
--- /dev/null
+++ b/indra/llcommon/llthreadlocalptr.h
@@ -0,0 +1,141 @@
+/** 
+ * @file llthreadlocalptr.h
+ * @brief manage thread local storage through non-copyable pointer
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTHREAD_LOCAL_PTR_H
+#define LL_LLTHREAD_LOCAL_PTR_H
+
+#include "llapr.h"
+
+template <typename T>
+class LLThreadLocalPtr
+{
+public:
+	LLThreadLocalPtr(T* value = NULL, apr_pool_t* pool = NULL)
+	{
+		apr_status_t result = apr_threadkey_private_create(&mThreadKey, cleanup, pool);
+		if (result != APR_SUCCESS)
+		{
+			ll_apr_warn_status(result);
+			llerrs << "Failed to allocate thread local data" << llendl;
+		}
+		set(value);
+	}
+
+
+	~LLThreadLocalPtr()
+	{
+		apr_status_t result = apr_threadkey_private_delete(mThreadKey);
+		if (result != APR_SUCCESS)
+		{
+			ll_apr_warn_status(result);
+			llerrs << "Failed to delete thread local data" << llendl;
+		}
+	}
+
+	T* operator -> ()
+	{
+		return get();
+	}
+
+	const T* operator -> () const
+	{
+		return get();
+	}
+
+	T& operator*()
+	{
+		return *get();
+	}
+
+	const T& operator*() const
+	{
+		return *get();
+	}
+
+	LLThreadLocalPtr<T>& operator = (T* value)
+	{
+		set(value);
+		return *this;
+	}
+
+	void copyFrom(const LLThreadLocalPtr<T>& other)
+	{
+		set(other.get());
+	}
+
+	LL_FORCE_INLINE void set(T* value)
+	{
+		apr_status_t result = apr_threadkey_private_set((void*)value, mThreadKey);
+		if (result != APR_SUCCESS)
+		{
+			ll_apr_warn_status(result);
+			llerrs << "Failed to set thread local data" << llendl;
+		}
+	}
+
+	LL_FORCE_INLINE T* get()
+	{
+		T* ptr;
+		//apr_status_t result =
+		apr_threadkey_private_get((void**)&ptr, mThreadKey);
+		//if (result != APR_SUCCESS)
+		//{
+		//	ll_apr_warn_status(s);
+		//	llerrs << "Failed to get thread local data" << llendl;
+		//}
+		return ptr;
+	}
+
+	LL_FORCE_INLINE const T* get() const
+	{
+		T* ptr;
+		//apr_status_t result =
+		apr_threadkey_private_get((void**)&ptr, mThreadKey);
+		//if (result != APR_SUCCESS)
+		//{
+		//	ll_apr_warn_status(s);
+		//	llerrs << "Failed to get thread local data" << llendl;
+		//}
+		return ptr;
+	}
+
+
+private:
+	static void cleanup(void* ptr)
+	{
+		delete reinterpret_cast<T*>(ptr);
+	}
+
+	LLThreadLocalPtr(const LLThreadLocalPtr<T>& other)
+	{
+		// do not copy construct
+		llassert(false);
+	}
+
+	apr_threadkey_t* mThreadKey;
+};
+
+#endif // LL_LLTHREAD_LOCAL_PTR_H
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
new file mode 100644
index 0000000000..037c52f8c1
--- /dev/null
+++ b/indra/llcommon/lltrace.cpp
@@ -0,0 +1,95 @@
+/** 
+ * @file lltrace.cpp
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltrace.h"
+#include "llthread.h"
+
+namespace LLTrace
+{
+
+BlockTimer::Recorder::StackEntry BlockTimer::sCurRecorder;
+LLThreadLocalPtr<ThreadTraceData> ThreadTraceData::sCurThreadTrace;
+
+///////////////////////////////////////////////////////////////////////
+// Sampler
+///////////////////////////////////////////////////////////////////////
+
+void Sampler::stop()
+{
+	getThreadTrace()->deactivate(this);
+}
+
+void Sampler::resume()
+{
+	getThreadTrace()->activate(this);
+}
+
+class ThreadTraceData* Sampler::getThreadTrace()
+{
+	return LLThread::getTraceData();
+}
+
+///////////////////////////////////////////////////////////////////////
+// MasterThreadTrace
+///////////////////////////////////////////////////////////////////////
+
+void MasterThreadTrace::pullFromWorkerThreads()
+{
+	LLMutexLock lock(&mSlaveListMutex);
+
+	for (worker_thread_trace_list_t::iterator it = mSlaveThreadTraces.begin(), end_it = mSlaveThreadTraces.end();
+		it != end_it;
+		++it)
+	{
+		it->mWorkerTrace->mSharedData.copyTo(it->mSamplerStorage);
+	}
+}
+
+void MasterThreadTrace::addSlaveThread( class SlaveThreadTrace* child )
+{
+	LLMutexLock lock(&mSlaveListMutex);
+
+	mSlaveThreadTraces.push_back(WorkerThreadTraceProxy(child));
+}
+
+void MasterThreadTrace::removeSlaveThread( class SlaveThreadTrace* child )
+{
+	LLMutexLock lock(&mSlaveListMutex);
+
+	for (worker_thread_trace_list_t::iterator it = mSlaveThreadTraces.begin(), end_it = mSlaveThreadTraces.end();
+		it != end_it;
+		++it)
+	{
+		if (it->mWorkerTrace == child)
+		{
+			mSlaveThreadTraces.erase(it);
+			break;
+		}
+	}
+}
+
+}
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 7da182df1e..401ddfd6f3 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -30,25 +30,27 @@
 #include "stdtypes.h"
 #include "llpreprocessor.h"
 
-#include "llthread.h"
+#include "llmutex.h"
+#include "llmemory.h"
+#include "llthreadlocalptr.h"
 
 #include <list>
 
+#define TOKEN_PASTE_ACTUAL(x, y) x##y
+#define TOKEN_PASTE(x, y) TOKEN_PASTE_ACTUAL(x, y)
+#define RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder TOKEN_PASTE(block_time_recorder, __COUNTER__)(block_timer);
+
 namespace LLTrace
 {
-
 	// one per thread per type
 	template<typename ACCUMULATOR>
-	struct AccumulatorBuffer : public AccumulatorBufferBase
+	class AccumulatorBuffer
 	{
-		ACCUMULATOR*				mStorage;
-		size_t						mStorageSize;
-		size_t						mNextStorageSlot;
-		static S32					sStorageKey; // key used to access thread local storage pointer to accumulator values
-		
+		static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64;
+	public:
 		AccumulatorBuffer()
 		:	mStorageSize(64),
-			mStorage(new ACCUMULATOR[64]),
+			mStorage(new ACCUMULATOR[DEFAULT_ACCUMULATOR_BUFFER_SIZE]),
 			mNextStorageSlot(0)
 		{}
 
@@ -56,12 +58,13 @@ namespace LLTrace
 		:	mStorageSize(other.mStorageSize),
 			mStorage(new ACCUMULATOR[other.mStorageSize]),
 			mNextStorageSlot(other.mNextStorageSlot)
-		{
+		{}
 
+		LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index) 
+		{ 
+			return mStorage[index]; 
 		}
 
-		LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index) { return (*mStorage)[index]; }
-
 		void mergeFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
 		{
 			llassert(mNextStorageSlot == other.mNextStorageSlot);
@@ -72,7 +75,7 @@ namespace LLTrace
 			}
 		}
 
-		void copyFrom(const AccumulatorBuffer<Accumulator>& other)
+		void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
 		{
 			for (size_t i = 0; i < mNextStorageSlot; i++)
 			{
@@ -90,7 +93,12 @@ namespace LLTrace
 
 		void makePrimary()
 		{
-			//TODO: use sStorageKey to set mStorage as active buffer
+			sPrimaryStorage = mStorage;
+		}
+
+		LL_FORCE_INLINE static ACCUMULATOR* getPrimaryStorage() 
+		{ 
+			return sPrimaryStorage.get(); 
 		}
 
 		// NOTE: this is not thread-safe.  We assume that slots are reserved in the main thread before any child threads are spawned
@@ -101,14 +109,29 @@ namespace LLTrace
 			{
 				size_t new_size = mStorageSize + (mStorageSize >> 2);
 				delete [] mStorage;
-				mStorage = new mStorage(new_size);
+				mStorage = new ACCUMULATOR[new_size];
 				mStorageSize = new_size;
 			}
 			llassert(next_slot < mStorageSize);
 			return next_slot;
 		}
+
+	private:
+		ACCUMULATOR*							mStorage;
+		size_t									mStorageSize;
+		size_t									mNextStorageSlot;
+		static LLThreadLocalPtr<ACCUMULATOR>	sPrimaryStorage;
+	};
+	template<typename ACCUMULATOR> LLThreadLocalPtr<ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>::sPrimaryStorage;
+
+	template<typename ACCUMULATOR>
+	class PrimaryAccumulatorBuffer : public AccumulatorBuffer<ACCUMULATOR
+	{
+		PrimaryAccumulatorBuffer()
+		{
+			makePrimary();
+		}
 	};
-	template<typename ACCUMULATOR> S32 AccumulatorBuffer<ACCUMULATOR>::sStorageKey;
 
 	template<typename ACCUMULATOR>
 	class Trace
@@ -117,32 +140,34 @@ namespace LLTrace
 		Trace(const std::string& name)
 		:	mName(name)
 		{
-			mAccumulatorIndex = sAccumulatorBuffer.reserveSlot();
+			mAccumulatorIndex = getPrimaryBuffer().reserveSlot();
 		}
 
 		LL_FORCE_INLINE ACCUMULATOR& getAccumulator()
 		{
-			return sAccumulatorBuffer[mAccumulatorIndex];
+			return AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage()[mAccumulatorIndex];
+		}
+
+		static PrimaryAccumulatorBuffer& getPrimaryBuffer()
+		{
+			static PrimaryAccumulatorBuffer sBuffer;
+			return sBuffer;
 		}
 
 	private:
 		std::string	mName;
 		size_t		mAccumulatorIndex;
-
-		// this needs to be thread local
-		static AccumulatorBuffer<ACCUMULATOR>	sAccumulatorBuffer;
 	};
 
-	template<typename ACCUMULATOR> std::vector<ACCUMULATOR> Trace<ACCUMULATOR>::sAccumulatorBuffer;
 
 	template<typename T>
 	class StatAccumulator
 	{
 	public:
 		StatAccumulator()
-		:	mSum(),
-			mMin(),
-			mMax(),
+		:	mSum(0),
+			mMin(0),
+			mMax(0),
 			mNumSamples(0)
 		{}
 
@@ -160,7 +185,7 @@ namespace LLTrace
 			}
 		}
 
-		void mergeFrom(const Stat<T>& other)
+		void mergeFrom(const StatAccumulator<T>& other)
 		{
 			mSum += other.mSum;
 			if (other.mMin < mMin)
@@ -318,21 +343,13 @@ namespace LLTrace
 		static Recorder::StackEntry sCurRecorder;
 	};
 
-	BlockTimer::Recorder::StackEntry BlockTimer::sCurRecorder;
-
 	class Sampler
 	{
 	public:
-		Sampler(const Sampler& other)
-		:	mF32Stats(other.mF32Stats),
-			mS32Stats(other.mS32Stats),
-			mTimers(other.mTimers)
-		{}
+		Sampler() {}
+		Sampler(const Sampler& other);
 
-		~Sampler()
-		{
-			stop();
-		}
+		~Sampler();
 
 		void makePrimary()
 		{
@@ -347,17 +364,8 @@ namespace LLTrace
 			resume();
 		}
 
-		void stop()
-		{
-			getThreadTracer()->deactivate(this);
-		}
-
-		void resume()
-		{
-			ThreadTracer* thread_data = getThreadTracer();
-			thread_data->flushData();
-			thread_data->activate(this);
-		}
+		void stop();
+		void resume();
 
 		void mergeFrom(const Sampler& other)
 		{
@@ -375,7 +383,7 @@ namespace LLTrace
 
 	private:
 		// returns data for current thread
-		struct ThreadTracer* getThreadTracer() { return NULL; } 
+		class ThreadTraceData* getThreadTrace(); 
 
 		AccumulatorBuffer<StatAccumulator<F32> >	mF32Stats;
 		AccumulatorBuffer<StatAccumulator<S32> >	mS32Stats;
@@ -383,39 +391,39 @@ namespace LLTrace
 		AccumulatorBuffer<TimerAccumulator>			mTimers;
 	};
 
-	struct ThreadTracer
+	class ThreadTraceData
 	{
-		ThreadTracer(LLThread& this_thread, ThreadTracer& parent_data)
-		:	mPrimarySampler(parent_data.mPrimarySampler),
-			mSharedSampler(parent_data.mSharedSampler),
-			mSharedSamplerMutex(this_thread.getAPRPool()),
-			mParent(parent_data)
+	public:
+		ThreadTraceData()
 		{
 			mPrimarySampler.makePrimary();
-			parent_data.addChildThread(this);
 		}
 
-		~ThreadTracer()
+		ThreadTraceData(const ThreadTraceData& other)
+		:	mPrimarySampler(other.mPrimarySampler)
 		{
-			mParent.removeChildThread(this);
+			mPrimarySampler.makePrimary();
 		}
 
-		void addChildThread(ThreadTracer* child)
+		void activate(Sampler* sampler)
 		{
-			mChildThreadTracers.push_back(child);
+			flushPrimary();
+			mActiveSamplers.push_back(sampler);
 		}
 
-		void removeChildThread(ThreadTracer* child)
+		void deactivate(Sampler* sampler)
 		{
+			sampler->mergeFrom(mPrimarySampler);
+
 			// TODO: replace with intrusive list
-			std::list<ThreadTracer*>::iterator found_it = std::find(mChildThreadTracers.begin(), mChildThreadTracers.end(), child);
-			if (found_it != mChildThreadTracers.end())
+			std::list<Sampler*>::iterator found_it = std::find(mActiveSamplers.begin(), mActiveSamplers.end(), sampler);
+			if (found_it != mActiveSamplers.end())
 			{
-				mChildThreadTracers.erase(found_it);
+				mActiveSamplers.erase(found_it);
 			}
 		}
 
-		void flushData()
+		void flushPrimary()
 		{
 			for (std::list<Sampler*>::iterator it = mActiveSamplers.begin(), end_it = mActiveSamplers.end();
 				it != end_it;
@@ -426,56 +434,96 @@ namespace LLTrace
 			mPrimarySampler.reset();
 		}
 
-		void activate(Sampler* sampler)
+		Sampler* getPrimarySampler() { return &mPrimarySampler; }
+	protected:
+		Sampler					mPrimarySampler;
+		std::list<Sampler*>		mActiveSamplers;
+		static LLThreadLocalPtr<ThreadTraceData> sCurThreadTrace;
+	};
+
+	class MasterThreadTrace : public ThreadTraceData
+	{
+	public:
+		MasterThreadTrace()
+		{}
+
+		void addSlaveThread(class SlaveThreadTrace* child);
+		void removeSlaveThread(class SlaveThreadTrace* child);
+
+		// call this periodically to gather stats data from worker threads
+		void pullFromWorkerThreads();
+
+	private:
+		struct WorkerThreadTraceProxy
 		{
-			mActiveSamplers.push_back(sampler);
+			WorkerThreadTraceProxy(class SlaveThreadTrace* trace)
+				:	mWorkerTrace(trace)
+			{}
+			class SlaveThreadTrace*	mWorkerTrace;
+			Sampler				mSamplerStorage;
+		};
+		typedef std::list<WorkerThreadTraceProxy> worker_thread_trace_list_t;
+
+		worker_thread_trace_list_t		mSlaveThreadTraces;
+		LLMutex							mSlaveListMutex;
+	};
+
+	class SlaveThreadTrace : public ThreadTraceData
+	{
+	public:
+		explicit 
+		SlaveThreadTrace(MasterThreadTrace& master_trace)
+		:	mMaster(master_trace),
+			ThreadTraceData(master_trace),
+			mSharedData(mPrimarySampler)
+		{
+			master_trace.addSlaveThread(this);
 		}
 
-		void deactivate(Sampler* sampler)
+		~SlaveThreadTrace()
 		{
-			// TODO: replace with intrusive list
-			std::list<Sampler*>::iterator found_it = std::find(mActiveSamplers.begin(), mActiveSamplers.end(), sampler);
-			if (found_it != mActiveSamplers.end())
-			{
-				mActiveSamplers.erase(found_it);
-			}
+			mMaster.removeSlaveThread(this);
 		}
-		
-		// call this periodically to gather stats data in parent thread
-		void publishToParent()
+
+		// call this periodically to gather stats data for master thread to consume
+		void pushToParent()
 		{
-			mSharedSamplerMutex.lock();
-			{	
-				mSharedSampler.mergeFrom(mPrimarySampler);
-			}
-			mSharedSamplerMutex.unlock();
+			mSharedData.copyFrom(mPrimarySampler);
 		}
 
-		// call this periodically to gather stats data from children
-		void gatherChildData()
+		MasterThreadTrace& 	mMaster;
+
+		// this data is accessed by other threads, so give it a 64 byte alignment
+		// to avoid false sharing on most x86 processors
+		LL_ALIGNED(64) class SharedData
 		{
-			for (std::list<ThreadTracer*>::iterator child_it = mChildThreadTracers.begin(), end_it = mChildThreadTracers.end();
-				child_it != end_it;
-				++child_it)
+		public:
+			explicit 
+			SharedData(const Sampler& other_sampler) 
+			:	mSampler(other_sampler)
+			{}
+
+			void copyFrom(Sampler& source)
 			{
-				(*child_it)->mSharedSamplerMutex.lock();
-				{
-					//TODO for now, just aggregate, later keep track of thread data independently
-					mPrimarySampler.mergeFrom((*child_it)->mSharedSampler);
+				LLMutexLock lock(&mSamplerMutex);
+				{	
+					mSampler.mergeFrom(source);
 				}
-				(*child_it)->mSharedSamplerMutex.unlock();
 			}
-		}
 
-		Sampler	mPrimarySampler;
-
-		ThreadTracer&				mParent;
-		std::list<Sampler*>			mActiveSamplers;
-		std::list<ThreadTracer*>	mChildThreadTracers;
-
-		// TODO:  add unused space here to avoid false sharing?
-		LLMutex	mSharedSamplerMutex;
-		Sampler mSharedSampler;
+			void copyTo(Sampler& sink)
+			{
+				LLMutexLock lock(&mSamplerMutex);
+				{
+					sink.mergeFrom(mSampler);
+				}
+			}
+		private:
+			// add a cache line's worth of unused space to avoid any potential of false sharing
+			LLMutex					mSamplerMutex;
+			Sampler					mSampler;
+		};
+		SharedData					mSharedData;
 	};
 
 
@@ -486,19 +534,6 @@ namespace LLTrace
 		void stop() {}
 		void resume() {}
 	};
-
-	class Sampler
-	{
-	public:
-		void start() {}
-		void stop() {}
-		void resume() {}
-	};
-
 }
 
-#define TOKEN_PASTE_ACTUAL(x, y) x##y
-#define TOKEN_PASTE(x, y) TOKEN_PASTE_ACTUAL(x, y)
-#define RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder TOKEN_PASTE(block_time_recorder, __COUNTER__)(block_timer);
-
 #endif // LL_LLTRACE_H
-- 
cgit v1.2.3


From adeeabfc13c91dc99a1ea1949cd2f820c4150995 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 24 Sep 2012 18:56:01 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages moved
 LLThreadLocalPtr to llapr fixed various startup race conditions for
 LLThreadLocalPtr

---
 indra/llcommon/CMakeLists.txt     |   1 -
 indra/llcommon/llapr.cpp          |  82 ++++++++++++++++++++++
 indra/llcommon/llapr.h            | 117 +++++++++++++++++++++++++++++++
 indra/llcommon/llcommon.cpp       |   2 +
 indra/llcommon/llthread.cpp       |   8 +--
 indra/llcommon/llthread.h         |   1 -
 indra/llcommon/llthreadlocalptr.h | 141 --------------------------------------
 indra/llcommon/lltrace.cpp        |  16 ++++-
 indra/llcommon/lltrace.h          |  57 +++++++--------
 9 files changed, 249 insertions(+), 176 deletions(-)
 delete mode 100644 indra/llcommon/llthreadlocalptr.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index eec2695dde..f78751601c 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -240,7 +240,6 @@ set(llcommon_HEADER_FILES
     llstringtable.h
     llsys.h
     llthread.h
-    llthreadlocalptr.h
     llthreadsafequeue.h
     lltimer.h
     lltrace.h
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index d1c44c9403..76749f8a91 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -54,6 +54,8 @@ void ll_init_apr()
 	{
 		LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;
 	}
+
+	LLThreadLocalPtrBase::initAllThreadLocalStorage();
 }
 
 
@@ -476,6 +478,86 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
 	return LLAPRFile::seek(mFile, where, offset) ;
 }
 
+//
+//LLThreadLocalPtrBase
+//
+bool LLThreadLocalPtrBase::sInitialized = false;
+
+LLThreadLocalPtrBase::LLThreadLocalPtrBase(void (*cleanup_func)(void*))
+:	mCleanupFunc(cleanup_func),
+	mThreadKey(NULL)
+{
+	if (sInitialized)
+	{
+		initStorage();
+	}
+}
+
+LLThreadLocalPtrBase::LLThreadLocalPtrBase( const LLThreadLocalPtrBase& other)
+:	mCleanupFunc(other.mCleanupFunc),
+	mThreadKey(NULL)
+{
+	if (sInitialized)
+	{
+		initStorage();
+	}
+}
+
+LLThreadLocalPtrBase::~LLThreadLocalPtrBase()
+{
+	destroyStorage();
+}
+
+void LLThreadLocalPtrBase::set( void* value )
+{
+	llassert(sInitialized && mThreadKey);
+
+	apr_status_t result = apr_threadkey_private_set((void*)value, mThreadKey);
+	if (result != APR_SUCCESS)
+	{
+		ll_apr_warn_status(result);
+		llerrs << "Failed to set thread local data" << llendl;
+	}
+}
+
+void LLThreadLocalPtrBase::initStorage( )
+{
+	apr_status_t result = apr_threadkey_private_create(&mThreadKey, mCleanupFunc, gAPRPoolp);
+	if (result != APR_SUCCESS)
+	{
+		ll_apr_warn_status(result);
+		llerrs << "Failed to allocate thread local data" << llendl;
+	}
+}
+
+void LLThreadLocalPtrBase::destroyStorage()
+{
+	if (mThreadKey)
+	{
+		apr_status_t result = apr_threadkey_private_delete(mThreadKey);
+		if (result != APR_SUCCESS)
+		{
+			ll_apr_warn_status(result);
+			llerrs << "Failed to delete thread local data" << llendl;
+		}
+	}
+}
+
+void LLThreadLocalPtrBase::initAllThreadLocalStorage()
+{
+	if (!sInitialized)
+	{
+		sInitialized = true;
+		for (LLInstanceTracker<LLThreadLocalPtrBase>::instance_iter it = beginInstances(), end_it = endInstances();
+			it != end_it;
+			++it)
+		{
+			(*it).initStorage();
+		}
+	}
+}
+
+
 //
 //*******************************************************************************************************************************
 //static components of LLAPRFile
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index af33ce666f..eb0bf627a0 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -49,6 +49,7 @@
 #include "apr_signal.h"
 #include "apr_atomic.h"
 #include "llstring.h"
+#include "llinstancetracker.h"
 
 extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
 extern apr_thread_mutex_t* gCallStacksLogMutexp;
@@ -255,6 +256,122 @@ public:
 //*******************************************************************************************************************************
 };
 
+class LLThreadLocalPtrBase : LLInstanceTracker<LLThreadLocalPtrBase>
+{
+public:
+	LLThreadLocalPtrBase(void (*cleanup_func)(void*) );
+	LLThreadLocalPtrBase(const LLThreadLocalPtrBase& other);
+	~LLThreadLocalPtrBase();
+
+protected:
+	friend void LL_COMMON_API ll_init_apr();
+	void set(void* value);
+
+	LL_FORCE_INLINE void* get()
+	{
+		void* ptr;
+		//apr_status_t result =
+		apr_threadkey_private_get(&ptr, mThreadKey);
+		//if (result != APR_SUCCESS)
+		//{
+		//	ll_apr_warn_status(s);
+		//	llerrs << "Failed to get thread local data" << llendl;
+		//}
+		return ptr;
+	}
+
+	LL_FORCE_INLINE const void* get() const
+	{
+		void* ptr;
+		//apr_status_t result =
+		apr_threadkey_private_get(&ptr, mThreadKey);
+		//if (result != APR_SUCCESS)
+		//{
+		//	ll_apr_warn_status(s);
+		//	llerrs << "Failed to get thread local data" << llendl;
+		//}
+		return ptr;
+	}
+
+	void initStorage();
+
+	void destroyStorage();
+
+	static void initAllThreadLocalStorage();
+
+private:
+	void (*mCleanupFunc)(void*);
+	apr_threadkey_t* mThreadKey;
+	static bool		sInitialized;
+};
+
+template <typename T>
+class LLThreadLocalPtr : public LLThreadLocalPtrBase
+{
+public:
+
+	LLThreadLocalPtr()
+	:	LLThreadLocalPtrBase(&cleanup)
+	{}
+
+	LLThreadLocalPtr(T* value)
+		:	LLThreadLocalPtrBase(&cleanup)
+	{
+		set(value);
+	}
+
+
+	LLThreadLocalPtr(const LLThreadLocalPtr<T>& other)
+	:	LLThreadLocalPtrBase(other, &cleanup)
+	{
+		set(other.get());		
+	}
+
+	T* get()
+	{
+		return (T*)LLThreadLocalPtrBase::get();
+	}
+
+	const T* get() const
+	{
+		return (const T*)LLThreadLocalPtrBase::get();
+	}
+
+	T* operator -> ()
+	{
+		return (T*)get();
+	}
+
+	const T* operator -> () const
+	{
+		return (T*)get();
+	}
+
+	T& operator*()
+	{
+		return *(T*)get();
+	}
+
+	const T& operator*() const
+	{
+		return *(T*)get();
+	}
+
+	LLThreadLocalPtr<T>& operator = (T* value)
+	{
+		set((void*)value);
+		return *this;
+	}
+
+private:
+
+	static void cleanup(void* ptr)
+	{
+		delete reinterpret_cast<T*>(ptr);
+	}
+
+};
+
 /**
  * @brief Function which appropriately logs error or remains quiet on
  * APR_SUCCESS.
diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index 8be9e4f4de..512e7da840 100644
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -44,6 +44,7 @@ void LLCommon::initClass()
 	}
 	LLTimer::initClass();
 	LLThreadSafeRefCount::initThreadSafeRefCount();
+	LLTrace::init();
 // 	LLWorkerThread::initClass();
 // 	LLFrameCallbackManager::initClass();
 }
@@ -61,4 +62,5 @@ void LLCommon::cleanupClass()
 		sAprInitialized = FALSE;
 	}
 	LLMemory::cleanupClass();
+	LLTrace::cleanup();
 }
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index f3ab8aa40c..023004eedd 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -66,9 +66,7 @@ U32 __thread LLThread::sThreadID = 0;
 #endif
 
 U32 LLThread::sIDIter = 0;
-
-LLTrace::MasterThreadTrace gMasterThreadTrace;
-LLThreadLocalPtr<LLTrace::ThreadTraceData> LLThread::sTraceData(&gMasterThreadTrace);
+LLThreadLocalPtr<LLTrace::ThreadTraceData> LLThread::sTraceData;
 
 
 LL_COMMON_API void assert_main_thread()
@@ -87,7 +85,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 {
 	LLThread *threadp = (LLThread *)datap;
 
-	sTraceData = new LLTrace::SlaveThreadTrace(gMasterThreadTrace);
+	sTraceData = new LLTrace::SlaveThreadTrace();
 
 #if !LL_DARWIN
 	sThreadIndex = threadp->mID;
@@ -155,7 +153,7 @@ void LLThread::shutdown()
 			//llinfos << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << llendl;
 			// Now wait a bit for the thread to exit
 			// It's unclear whether I should even bother doing this - this destructor
-			// should netver get called unless we're already stopped, really...
+			// should never get called unless we're already stopped, really...
 			S32 counter = 0;
 			const S32 MAX_WAIT = 600;
 			while (counter < MAX_WAIT)
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index e2de4c8b85..e50fa7653d 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -31,7 +31,6 @@
 #include "llapr.h"
 #include "apr_thread_cond.h"
 #include "lltrace.h"
-#include "llthreadlocalptr.h"
 
 class LL_COMMON_API LLThread
 {
diff --git a/indra/llcommon/llthreadlocalptr.h b/indra/llcommon/llthreadlocalptr.h
deleted file mode 100644
index f02f4849ca..0000000000
--- a/indra/llcommon/llthreadlocalptr.h
+++ /dev/null
@@ -1,141 +0,0 @@
-/** 
- * @file llthreadlocalptr.h
- * @brief manage thread local storage through non-copyable pointer
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLTHREAD_LOCAL_PTR_H
-#define LL_LLTHREAD_LOCAL_PTR_H
-
-#include "llapr.h"
-
-template <typename T>
-class LLThreadLocalPtr
-{
-public:
-	LLThreadLocalPtr(T* value = NULL, apr_pool_t* pool = NULL)
-	{
-		apr_status_t result = apr_threadkey_private_create(&mThreadKey, cleanup, pool);
-		if (result != APR_SUCCESS)
-		{
-			ll_apr_warn_status(result);
-			llerrs << "Failed to allocate thread local data" << llendl;
-		}
-		set(value);
-	}
-
-
-	~LLThreadLocalPtr()
-	{
-		apr_status_t result = apr_threadkey_private_delete(mThreadKey);
-		if (result != APR_SUCCESS)
-		{
-			ll_apr_warn_status(result);
-			llerrs << "Failed to delete thread local data" << llendl;
-		}
-	}
-
-	T* operator -> ()
-	{
-		return get();
-	}
-
-	const T* operator -> () const
-	{
-		return get();
-	}
-
-	T& operator*()
-	{
-		return *get();
-	}
-
-	const T& operator*() const
-	{
-		return *get();
-	}
-
-	LLThreadLocalPtr<T>& operator = (T* value)
-	{
-		set(value);
-		return *this;
-	}
-
-	void copyFrom(const LLThreadLocalPtr<T>& other)
-	{
-		set(other.get());
-	}
-
-	LL_FORCE_INLINE void set(T* value)
-	{
-		apr_status_t result = apr_threadkey_private_set((void*)value, mThreadKey);
-		if (result != APR_SUCCESS)
-		{
-			ll_apr_warn_status(result);
-			llerrs << "Failed to set thread local data" << llendl;
-		}
-	}
-
-	LL_FORCE_INLINE T* get()
-	{
-		T* ptr;
-		//apr_status_t result =
-		apr_threadkey_private_get((void**)&ptr, mThreadKey);
-		//if (result != APR_SUCCESS)
-		//{
-		//	ll_apr_warn_status(s);
-		//	llerrs << "Failed to get thread local data" << llendl;
-		//}
-		return ptr;
-	}
-
-	LL_FORCE_INLINE const T* get() const
-	{
-		T* ptr;
-		//apr_status_t result =
-		apr_threadkey_private_get((void**)&ptr, mThreadKey);
-		//if (result != APR_SUCCESS)
-		//{
-		//	ll_apr_warn_status(s);
-		//	llerrs << "Failed to get thread local data" << llendl;
-		//}
-		return ptr;
-	}
-
-
-private:
-	static void cleanup(void* ptr)
-	{
-		delete reinterpret_cast<T*>(ptr);
-	}
-
-	LLThreadLocalPtr(const LLThreadLocalPtr<T>& other)
-	{
-		// do not copy construct
-		llassert(false);
-	}
-
-	apr_threadkey_t* mThreadKey;
-};
-
-#endif // LL_LLTHREAD_LOCAL_PTR_H
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 037c52f8c1..501414ebf3 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -32,7 +32,21 @@ namespace LLTrace
 {
 
 BlockTimer::Recorder::StackEntry BlockTimer::sCurRecorder;
-LLThreadLocalPtr<ThreadTraceData> ThreadTraceData::sCurThreadTrace;
+
+MasterThreadTrace *gMasterThreadTrace = NULL;
+LLThreadLocalPtr<ThreadTraceData> gCurThreadTrace;
+
+void init()
+{
+	gMasterThreadTrace = new MasterThreadTrace();
+	gCurThreadTrace = gMasterThreadTrace;
+}
+
+void cleanup()
+{
+	delete gMasterThreadTrace;
+}
+
 
 ///////////////////////////////////////////////////////////////////////
 // Sampler
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 401ddfd6f3..3af05d67f9 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -32,7 +32,6 @@
 
 #include "llmutex.h"
 #include "llmemory.h"
-#include "llthreadlocalptr.h"
 
 #include <list>
 
@@ -42,19 +41,29 @@
 
 namespace LLTrace
 {
+	void init();
+	void cleanup();
+
+	extern class MasterThreadTrace *gMasterThreadTrace;
+	extern LLThreadLocalPtr<class ThreadTraceData> gCurThreadTrace;
+
 	// one per thread per type
 	template<typename ACCUMULATOR>
 	class AccumulatorBuffer
 	{
 		static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64;
-	public:
-		AccumulatorBuffer()
+	private:
+		enum StaticAllocationMarker { STATIC_ALLOC };
+
+		AccumulatorBuffer(StaticAllocationMarker m)
 		:	mStorageSize(64),
-			mStorage(new ACCUMULATOR[DEFAULT_ACCUMULATOR_BUFFER_SIZE]),
-			mNextStorageSlot(0)
-		{}
+			mNextStorageSlot(0),
+			mStorage(new ACCUMULATOR[DEFAULT_ACCUMULATOR_BUFFER_SIZE])
+		{
+		}
+	public:
 
-		AccumulatorBuffer(const AccumulatorBuffer& other)
+		AccumulatorBuffer(const AccumulatorBuffer& other = getDefaultBuffer())
 		:	mStorageSize(other.mStorageSize),
 			mStorage(new ACCUMULATOR[other.mStorageSize]),
 			mNextStorageSlot(other.mNextStorageSlot)
@@ -116,6 +125,12 @@ namespace LLTrace
 			return next_slot;
 		}
 
+		static AccumulatorBuffer<ACCUMULATOR>& getDefaultBuffer()
+		{
+			static AccumulatorBuffer sBuffer;
+			return sBuffer;
+		}
+
 	private:
 		ACCUMULATOR*							mStorage;
 		size_t									mStorageSize;
@@ -124,15 +139,6 @@ namespace LLTrace
 	};
 	template<typename ACCUMULATOR> LLThreadLocalPtr<ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>::sPrimaryStorage;
 
-	template<typename ACCUMULATOR>
-	class PrimaryAccumulatorBuffer : public AccumulatorBuffer<ACCUMULATOR
-	{
-		PrimaryAccumulatorBuffer()
-		{
-			makePrimary();
-		}
-	};
-
 	template<typename ACCUMULATOR>
 	class Trace
 	{
@@ -140,7 +146,7 @@ namespace LLTrace
 		Trace(const std::string& name)
 		:	mName(name)
 		{
-			mAccumulatorIndex = getPrimaryBuffer().reserveSlot();
+			mAccumulatorIndex = AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer().reserveSlot();
 		}
 
 		LL_FORCE_INLINE ACCUMULATOR& getAccumulator()
@@ -148,12 +154,6 @@ namespace LLTrace
 			return AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage()[mAccumulatorIndex];
 		}
 
-		static PrimaryAccumulatorBuffer& getPrimaryBuffer()
-		{
-			static PrimaryAccumulatorBuffer sBuffer;
-			return sBuffer;
-		}
-
 	private:
 		std::string	mName;
 		size_t		mAccumulatorIndex;
@@ -347,9 +347,13 @@ namespace LLTrace
 	{
 	public:
 		Sampler() {}
-		Sampler(const Sampler& other);
+		Sampler(const Sampler& other)
+		:	mF32Stats(other.mF32Stats),
+			mS32Stats(other.mS32Stats),
+			mTimers(other.mTimers)
+		{}
 
-		~Sampler();
+		~Sampler() {}
 
 		void makePrimary()
 		{
@@ -438,7 +442,6 @@ namespace LLTrace
 	protected:
 		Sampler					mPrimarySampler;
 		std::list<Sampler*>		mActiveSamplers;
-		static LLThreadLocalPtr<ThreadTraceData> sCurThreadTrace;
 	};
 
 	class MasterThreadTrace : public ThreadTraceData
@@ -472,7 +475,7 @@ namespace LLTrace
 	{
 	public:
 		explicit 
-		SlaveThreadTrace(MasterThreadTrace& master_trace)
+		SlaveThreadTrace(MasterThreadTrace& master_trace = *gMasterThreadTrace)
 		:	mMaster(master_trace),
 			ThreadTraceData(master_trace),
 			mSharedData(mPrimarySampler)
-- 
cgit v1.2.3


From 308ff886c3ab2aa561477921bc0d92e1bd7d399a Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 24 Sep 2012 19:01:48 -0700
Subject: fixed build moved LLThread::lockData and unlockData back to header

---
 indra/llcommon/llthread.cpp | 10 ----------
 indra/llcommon/llthread.h   | 12 ++++++++++++
 2 files changed, 12 insertions(+), 10 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 023004eedd..de1f0801a1 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -308,13 +308,3 @@ void LLThread::wakeLocked()
 		mRunCondition->signal();
 	}
 }
-
-void LLThread::lockData()
-{
-	mRunCondition->lock();
-}
-
-void LLThread::unlockData()
-{
-	mRunCondition->unlock();
-}
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index e50fa7653d..fed111b0e4 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -136,6 +136,18 @@ protected:
 	// mRunCondition->unlock();
 };
 
+
+void LLThread::lockData()
+{
+	mRunCondition->lock();
+}
+
+void LLThread::unlockData()
+{
+	mRunCondition->unlock();
+}
+
+
 //============================================================================
 
 #endif // LL_LLTHREAD_H
-- 
cgit v1.2.3


From 05a3203d8274a0a0999faad128f629614b8d62c5 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 26 Sep 2012 17:04:57 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages fixed
 various issues related to unit tests and LLThreadLocalPtr initialization and
 teardown

---
 indra/llcommon/llapr.cpp    | 45 +++++++++++++++++++++++++++++--------------
 indra/llcommon/llapr.h      | 27 ++++++++++++--------------
 indra/llcommon/llcommon.cpp |  6 +-----
 indra/llcommon/llthread.cpp |  5 ++++-
 indra/llcommon/llthread.h   |  2 +-
 indra/llcommon/lltrace.cpp  | 33 ++++++++++++++++++++-----------
 indra/llcommon/lltrace.h    | 47 ++++++++++++++++++++++++++-------------------
 7 files changed, 98 insertions(+), 67 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 76749f8a91..e9930c10f7 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -52,7 +52,7 @@ void ll_init_apr()
 
 	if(!LLAPRFile::sAPRFilePoolp)
 	{
-		LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;
+		LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE);
 	}
 
 	LLThreadLocalPtrBase::initAllThreadLocalStorage();
@@ -79,6 +79,9 @@ void ll_cleanup_apr()
 		apr_thread_mutex_destroy(gCallStacksLogMutexp);
 		gCallStacksLogMutexp = NULL;
 	}
+
+	LLThreadLocalPtrBase::destroyAllThreadLocalStorage();
+
 	if (gAPRPoolp)
 	{
 		apr_pool_destroy(gAPRPoolp);
@@ -86,7 +89,7 @@ void ll_cleanup_apr()
 	}
 	if (LLAPRFile::sAPRFilePoolp)
 	{
-		delete LLAPRFile::sAPRFilePoolp ;
+		delete LLAPRFile::sAPRFilePoolp ;	
 		LLAPRFile::sAPRFilePoolp = NULL ;
 	}
 	apr_terminate();
@@ -483,9 +486,8 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
 //
 bool LLThreadLocalPtrBase::sInitialized = false;
 
-LLThreadLocalPtrBase::LLThreadLocalPtrBase(void (*cleanup_func)(void*))
-:	mCleanupFunc(cleanup_func),
-	mThreadKey(NULL)
+LLThreadLocalPtrBase::LLThreadLocalPtrBase()
+:	mThreadKey(NULL)
 {
 	if (sInitialized)
 	{
@@ -494,8 +496,7 @@ LLThreadLocalPtrBase::LLThreadLocalPtrBase(void (*cleanup_func)(void*))
 }
 
 LLThreadLocalPtrBase::LLThreadLocalPtrBase( const LLThreadLocalPtrBase& other)
-:	mCleanupFunc(other.mCleanupFunc),
-	mThreadKey(NULL)
+:	mThreadKey(NULL)
 {
 	if (sInitialized)
 	{
@@ -522,7 +523,7 @@ void LLThreadLocalPtrBase::set( void* value )
 
 void LLThreadLocalPtrBase::initStorage( )
 {
-	apr_status_t result = apr_threadkey_private_create(&mThreadKey, mCleanupFunc, gAPRPoolp);
+	apr_status_t result = apr_threadkey_private_create(&mThreadKey, NULL, gAPRPoolp);
 	if (result != APR_SUCCESS)
 	{
 		ll_apr_warn_status(result);
@@ -532,13 +533,16 @@ void LLThreadLocalPtrBase::initStorage( )
 
 void LLThreadLocalPtrBase::destroyStorage()
 {
-	if (mThreadKey)
+	if (sInitialized)
 	{
-		apr_status_t result = apr_threadkey_private_delete(mThreadKey);
-		if (result != APR_SUCCESS)
+		if (mThreadKey)
 		{
-			ll_apr_warn_status(result);
-			llerrs << "Failed to delete thread local data" << llendl;
+			apr_status_t result = apr_threadkey_private_delete(mThreadKey);
+			if (result != APR_SUCCESS)
+			{
+				ll_apr_warn_status(result);
+				llerrs << "Failed to delete thread local data" << llendl;
+			}
 		}
 	}
 }
@@ -547,16 +551,29 @@ void LLThreadLocalPtrBase::initAllThreadLocalStorage()
 {
 	if (!sInitialized)
 	{
-		sInitialized = true;
 		for (LLInstanceTracker<LLThreadLocalPtrBase>::instance_iter it = beginInstances(), end_it = endInstances();
 			it != end_it;
 			++it)
 		{
 			(*it).initStorage();
 		}
+		sInitialized = true;
 	}
 }
 
+void LLThreadLocalPtrBase::destroyAllThreadLocalStorage()
+{
+	if (sInitialized)
+	{
+		for (LLInstanceTracker<LLThreadLocalPtrBase>::instance_iter it = beginInstances(), end_it = endInstances();
+			it != end_it;
+			++it)
+		{
+			(*it).destroyStorage();
+		}
+		sInitialized = false;
+	}
+}
 
 //
 //*******************************************************************************************************************************
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index eb0bf627a0..830e0a33fa 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -259,16 +259,19 @@ public:
 class LLThreadLocalPtrBase : LLInstanceTracker<LLThreadLocalPtrBase>
 {
 public:
-	LLThreadLocalPtrBase(void (*cleanup_func)(void*) );
+	LLThreadLocalPtrBase();
 	LLThreadLocalPtrBase(const LLThreadLocalPtrBase& other);
 	~LLThreadLocalPtrBase();
 
+	static void initAllThreadLocalStorage();
+	static void destroyAllThreadLocalStorage();
+
 protected:
-	friend void LL_COMMON_API ll_init_apr();
 	void set(void* value);
 
 	LL_FORCE_INLINE void* get()
 	{
+		llassert(sInitialized);
 		void* ptr;
 		//apr_status_t result =
 		apr_threadkey_private_get(&ptr, mThreadKey);
@@ -294,13 +297,9 @@ protected:
 	}
 
 	void initStorage();
-
 	void destroyStorage();
 
-	static void initAllThreadLocalStorage();
-
-private:
-	void (*mCleanupFunc)(void*);
+protected:
 	apr_threadkey_t* mThreadKey;
 	static bool		sInitialized;
 };
@@ -311,10 +310,10 @@ class LLThreadLocalPtr : public LLThreadLocalPtrBase
 public:
 
 	LLThreadLocalPtr()
-	:	LLThreadLocalPtrBase(&cleanup)
+	:	LLThreadLocalPtrBase()
 	{}
 
-	LLThreadLocalPtr(T* value)
+	explicit LLThreadLocalPtr(T* value)
 		:	LLThreadLocalPtrBase(&cleanup)
 	{
 		set(value);
@@ -327,7 +326,7 @@ public:
 		set(other.get());		
 	}
 
-	T* get()
+	LL_FORCE_INLINE T* get()
 	{
 		return (T*)LLThreadLocalPtrBase::get();
 	}
@@ -363,13 +362,11 @@ public:
 		return *this;
 	}
 
-private:
-
-	static void cleanup(void* ptr)
+	bool operator ==(T* other)
 	{
-		delete reinterpret_cast<T*>(ptr);
+		if (!sInitialized) return false;
+		return get() == other;
 	}
-
 };
 
 /**
diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index 512e7da840..c149a1fe5c 100644
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -45,15 +45,12 @@ void LLCommon::initClass()
 	LLTimer::initClass();
 	LLThreadSafeRefCount::initThreadSafeRefCount();
 	LLTrace::init();
-// 	LLWorkerThread::initClass();
-// 	LLFrameCallbackManager::initClass();
 }
 
 //static
 void LLCommon::cleanupClass()
 {
-// 	LLFrameCallbackManager::cleanupClass();
-// 	LLWorkerThread::cleanupClass();
+	LLTrace::cleanup();
 	LLThreadSafeRefCount::cleanupThreadSafeRefCount();
 	LLTimer::cleanupClass();
 	if (sAprInitialized)
@@ -62,5 +59,4 @@ void LLCommon::cleanupClass()
 		sAprInitialized = FALSE;
 	}
 	LLMemory::cleanupClass();
-	LLTrace::cleanup();
 }
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index de1f0801a1..2e6eb085dc 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -66,7 +66,7 @@ U32 __thread LLThread::sThreadID = 0;
 #endif
 
 U32 LLThread::sIDIter = 0;
-LLThreadLocalPtr<LLTrace::ThreadTraceData> LLThread::sTraceData;
+LLThreadLocalPtr<LLTrace::SlaveThreadTrace> LLThread::sTraceData;
 
 
 LL_COMMON_API void assert_main_thread()
@@ -99,6 +99,8 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 	// We're done with the run function, this thread is done executing now.
 	threadp->mStatus = STOPPED;
 
+	delete sTraceData.get();
+
 	return NULL;
 }
 
@@ -108,6 +110,7 @@ LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
 	mAPRThreadp(NULL),
 	mStatus(STOPPED)
 {
+
 	mID = ++sIDIter;
 
 	// Thread creation probably CAN be paranoid about APR being initialized, if necessary
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index fed111b0e4..6889fab2c1 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -105,7 +105,7 @@ protected:
 	EThreadStatus		mStatus;
 	U32					mID;
 
-	static LLThreadLocalPtr<LLTrace::ThreadTraceData> sTraceData;
+	static LLThreadLocalPtr<LLTrace::SlaveThreadTrace> sTraceData;
 
 	//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
 	//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 501414ebf3..8cedcafd10 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -31,27 +31,37 @@
 namespace LLTrace
 {
 
-BlockTimer::Recorder::StackEntry BlockTimer::sCurRecorder;
-
-MasterThreadTrace *gMasterThreadTrace = NULL;
-LLThreadLocalPtr<ThreadTraceData> gCurThreadTrace;
+static MasterThreadTrace* gMasterThreadTrace = NULL;
 
 void init()
 {
 	gMasterThreadTrace = new MasterThreadTrace();
-	gCurThreadTrace = gMasterThreadTrace;
 }
 
 void cleanup()
 {
 	delete gMasterThreadTrace;
+	gMasterThreadTrace = NULL;
 }
 
 
+BlockTimer::Recorder::StackEntry BlockTimer::sCurRecorder;
+
+
+
+MasterThreadTrace& getMasterThreadTrace()
+{
+	llassert(gMasterThreadTrace != NULL);
+	return *gMasterThreadTrace;
+}
+
+
+
 ///////////////////////////////////////////////////////////////////////
 // Sampler
 ///////////////////////////////////////////////////////////////////////
 
+
 void Sampler::stop()
 {
 	getThreadTrace()->deactivate(this);
@@ -71,15 +81,15 @@ class ThreadTraceData* Sampler::getThreadTrace()
 // MasterThreadTrace
 ///////////////////////////////////////////////////////////////////////
 
-void MasterThreadTrace::pullFromWorkerThreads()
+void MasterThreadTrace::pullFromSlaveThreads()
 {
 	LLMutexLock lock(&mSlaveListMutex);
 
-	for (worker_thread_trace_list_t::iterator it = mSlaveThreadTraces.begin(), end_it = mSlaveThreadTraces.end();
+	for (slave_thread_trace_list_t::iterator it = mSlaveThreadTraces.begin(), end_it = mSlaveThreadTraces.end();
 		it != end_it;
 		++it)
 	{
-		it->mWorkerTrace->mSharedData.copyTo(it->mSamplerStorage);
+		it->mSlaveTrace->mSharedData.copyTo(it->mSamplerStorage);
 	}
 }
 
@@ -87,18 +97,18 @@ void MasterThreadTrace::addSlaveThread( class SlaveThreadTrace* child )
 {
 	LLMutexLock lock(&mSlaveListMutex);
 
-	mSlaveThreadTraces.push_back(WorkerThreadTraceProxy(child));
+	mSlaveThreadTraces.push_back(SlaveThreadTraceProxy(child));
 }
 
 void MasterThreadTrace::removeSlaveThread( class SlaveThreadTrace* child )
 {
 	LLMutexLock lock(&mSlaveListMutex);
 
-	for (worker_thread_trace_list_t::iterator it = mSlaveThreadTraces.begin(), end_it = mSlaveThreadTraces.end();
+	for (slave_thread_trace_list_t::iterator it = mSlaveThreadTraces.begin(), end_it = mSlaveThreadTraces.end();
 		it != end_it;
 		++it)
 	{
-		if (it->mWorkerTrace == child)
+		if (it->mSlaveTrace == child)
 		{
 			mSlaveThreadTraces.erase(it);
 			break;
@@ -107,3 +117,4 @@ void MasterThreadTrace::removeSlaveThread( class SlaveThreadTrace* child )
 }
 
 }
+
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 3af05d67f9..e4bec0a644 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -44,8 +44,7 @@ namespace LLTrace
 	void init();
 	void cleanup();
 
-	extern class MasterThreadTrace *gMasterThreadTrace;
-	extern LLThreadLocalPtr<class ThreadTraceData> gCurThreadTrace;
+	class MasterThreadTrace& getMasterThreadTrace();
 
 	// one per thread per type
 	template<typename ACCUMULATOR>
@@ -59,8 +58,8 @@ namespace LLTrace
 		:	mStorageSize(64),
 			mNextStorageSlot(0),
 			mStorage(new ACCUMULATOR[DEFAULT_ACCUMULATOR_BUFFER_SIZE])
-		{
-		}
+		{}
+
 	public:
 
 		AccumulatorBuffer(const AccumulatorBuffer& other = getDefaultBuffer())
@@ -69,6 +68,15 @@ namespace LLTrace
 			mNextStorageSlot(other.mNextStorageSlot)
 		{}
 
+		~AccumulatorBuffer()
+		{
+			if (sPrimaryStorage == mStorage)
+			{
+				//TODO pick another primary?
+				sPrimaryStorage = NULL;
+			}
+		}
+
 		LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index) 
 		{ 
 			return mStorage[index]; 
@@ -353,7 +361,8 @@ namespace LLTrace
 			mTimers(other.mTimers)
 		{}
 
-		~Sampler() {}
+		~Sampler()
+		{}
 
 		void makePrimary()
 		{
@@ -453,21 +462,21 @@ namespace LLTrace
 		void addSlaveThread(class SlaveThreadTrace* child);
 		void removeSlaveThread(class SlaveThreadTrace* child);
 
-		// call this periodically to gather stats data from worker threads
-		void pullFromWorkerThreads();
+		// call this periodically to gather stats data from slave threads
+		void pullFromSlaveThreads();
 
 	private:
-		struct WorkerThreadTraceProxy
+		struct SlaveThreadTraceProxy
 		{
-			WorkerThreadTraceProxy(class SlaveThreadTrace* trace)
-				:	mWorkerTrace(trace)
+			SlaveThreadTraceProxy(class SlaveThreadTrace* trace)
+				:	mSlaveTrace(trace)
 			{}
-			class SlaveThreadTrace*	mWorkerTrace;
+			class SlaveThreadTrace*	mSlaveTrace;
 			Sampler				mSamplerStorage;
 		};
-		typedef std::list<WorkerThreadTraceProxy> worker_thread_trace_list_t;
+		typedef std::list<SlaveThreadTraceProxy> slave_thread_trace_list_t;
 
-		worker_thread_trace_list_t		mSlaveThreadTraces;
+		slave_thread_trace_list_t		mSlaveThreadTraces;
 		LLMutex							mSlaveListMutex;
 	};
 
@@ -475,17 +484,16 @@ namespace LLTrace
 	{
 	public:
 		explicit 
-		SlaveThreadTrace(MasterThreadTrace& master_trace = *gMasterThreadTrace)
-		:	mMaster(master_trace),
-			ThreadTraceData(master_trace),
+		SlaveThreadTrace()
+		:	ThreadTraceData(getMasterThreadTrace()),
 			mSharedData(mPrimarySampler)
 		{
-			master_trace.addSlaveThread(this);
+			getMasterThreadTrace().addSlaveThread(this);
 		}
 
 		~SlaveThreadTrace()
 		{
-			mMaster.removeSlaveThread(this);
+			getMasterThreadTrace().removeSlaveThread(this);
 		}
 
 		// call this periodically to gather stats data for master thread to consume
@@ -494,7 +502,7 @@ namespace LLTrace
 			mSharedData.copyFrom(mPrimarySampler);
 		}
 
-		MasterThreadTrace& 	mMaster;
+		MasterThreadTrace* 	mMaster;
 
 		// this data is accessed by other threads, so give it a 64 byte alignment
 		// to avoid false sharing on most x86 processors
@@ -529,7 +537,6 @@ namespace LLTrace
 		SharedData					mSharedData;
 	};
 
-
 	class TimeInterval 
 	{
 	public:
-- 
cgit v1.2.3


From 07c4be092b276f0d7c14ba12872efb31c1f16764 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 26 Sep 2012 19:12:40 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages slave
 threads now pushing data to master thread

---
 indra/llcommon/llqueuedthread.cpp |  2 ++
 indra/llcommon/llthread.cpp       |  2 +-
 indra/llcommon/llthread.h         |  5 +--
 indra/llcommon/lltrace.cpp        | 71 ++++++++++++++++++++++++++++++++++++++-
 indra/llcommon/lltrace.h          | 63 +++++++++-------------------------
 5 files changed, 92 insertions(+), 51 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 1738c16dea..a741d342d3 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -111,6 +111,8 @@ void LLQueuedThread::shutdown()
 // virtual
 S32 LLQueuedThread::update(F32 max_time_ms)
 {
+	LLThread::getTraceData()->pushToMaster();
+
 	if (!mStarted)
 	{
 		if (!mThreaded)
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 2e6eb085dc..2ff524d9ba 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -66,7 +66,7 @@ U32 __thread LLThread::sThreadID = 0;
 #endif
 
 U32 LLThread::sIDIter = 0;
-LLThreadLocalPtr<LLTrace::SlaveThreadTrace> LLThread::sTraceData;
+LLThreadLocalPtr<LLTrace::ThreadTrace> LLThread::sTraceData;
 
 
 LL_COMMON_API void assert_main_thread()
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 6889fab2c1..5cd287ec39 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -87,7 +87,8 @@ public:
 
 	U32 getID() const { return mID; }
 
-	static LLTrace::ThreadTraceData* getTraceData() { return sTraceData.get(); }
+	static LLTrace::ThreadTrace* getTraceData() { return sTraceData.get(); }
+	static void setTraceData(LLTrace::ThreadTrace* data) { sTraceData = data;}
 
 private:
 	BOOL				mPaused;
@@ -105,7 +106,7 @@ protected:
 	EThreadStatus		mStatus;
 	U32					mID;
 
-	static LLThreadLocalPtr<LLTrace::SlaveThreadTrace> sTraceData;
+	static LLThreadLocalPtr<LLTrace::ThreadTrace> sTraceData;
 
 	//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
 	//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 8cedcafd10..24a2b33a5f 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -72,11 +72,69 @@ void Sampler::resume()
 	getThreadTrace()->activate(this);
 }
 
-class ThreadTraceData* Sampler::getThreadTrace()
+class ThreadTrace* Sampler::getThreadTrace()
 {
 	return LLThread::getTraceData();
 }
 
+///////////////////////////////////////////////////////////////////////
+// MasterThreadTrace
+///////////////////////////////////////////////////////////////////////
+
+ThreadTrace::ThreadTrace()
+{
+	mPrimarySampler.makePrimary();
+}
+
+ThreadTrace::ThreadTrace( const ThreadTrace& other ) :	mPrimarySampler(other.mPrimarySampler)
+{
+	mPrimarySampler.makePrimary();
+}
+
+void ThreadTrace::activate( Sampler* sampler )
+{
+	flushPrimary();
+	mActiveSamplers.push_back(sampler);
+}
+
+void ThreadTrace::deactivate( Sampler* sampler )
+{
+	sampler->mergeFrom(mPrimarySampler);
+
+	// TODO: replace with intrusive list
+	std::list<Sampler*>::iterator found_it = std::find(mActiveSamplers.begin(), mActiveSamplers.end(), sampler);
+	if (found_it != mActiveSamplers.end())
+	{
+		mActiveSamplers.erase(found_it);
+	}
+}
+
+void ThreadTrace::flushPrimary()
+{
+	for (std::list<Sampler*>::iterator it = mActiveSamplers.begin(), end_it = mActiveSamplers.end();
+		it != end_it;
+		++it)
+	{
+		(*it)->mergeFrom(mPrimarySampler);
+	}
+	mPrimarySampler.reset();
+}
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////
+// SlaveThreadTrace
+///////////////////////////////////////////////////////////////////////
+
+void SlaveThreadTrace::pushToMaster()
+{
+	mSharedData.copyFrom(mPrimarySampler);
+}
+
+
 ///////////////////////////////////////////////////////////////////////
 // MasterThreadTrace
 ///////////////////////////////////////////////////////////////////////
@@ -116,5 +174,16 @@ void MasterThreadTrace::removeSlaveThread( class SlaveThreadTrace* child )
 	}
 }
 
+void MasterThreadTrace::pushToMaster()
+{
+
+}
+
+MasterThreadTrace::MasterThreadTrace()
+{
+	LLThread::setTraceData(this);
+}
+
+
 }
 
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index e4bec0a644..601b5ed182 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -396,7 +396,7 @@ namespace LLTrace
 
 	private:
 		// returns data for current thread
-		class ThreadTraceData* getThreadTrace(); 
+		class ThreadTrace* getThreadTrace(); 
 
 		AccumulatorBuffer<StatAccumulator<F32> >	mF32Stats;
 		AccumulatorBuffer<StatAccumulator<S32> >	mS32Stats;
@@ -404,48 +404,19 @@ namespace LLTrace
 		AccumulatorBuffer<TimerAccumulator>			mTimers;
 	};
 
-	class ThreadTraceData
+	class ThreadTrace
 	{
 	public:
-		ThreadTraceData()
-		{
-			mPrimarySampler.makePrimary();
-		}
-
-		ThreadTraceData(const ThreadTraceData& other)
-		:	mPrimarySampler(other.mPrimarySampler)
-		{
-			mPrimarySampler.makePrimary();
-		}
+		ThreadTrace();
+		ThreadTrace(const ThreadTrace& other);
 
-		void activate(Sampler* sampler)
-		{
-			flushPrimary();
-			mActiveSamplers.push_back(sampler);
-		}
+		virtual ~ThreadTrace() {}
 
-		void deactivate(Sampler* sampler)
-		{
-			sampler->mergeFrom(mPrimarySampler);
-
-			// TODO: replace with intrusive list
-			std::list<Sampler*>::iterator found_it = std::find(mActiveSamplers.begin(), mActiveSamplers.end(), sampler);
-			if (found_it != mActiveSamplers.end())
-			{
-				mActiveSamplers.erase(found_it);
-			}
-		}
+		void activate(Sampler* sampler);
+		void deactivate(Sampler* sampler);
+		void flushPrimary();
 
-		void flushPrimary()
-		{
-			for (std::list<Sampler*>::iterator it = mActiveSamplers.begin(), end_it = mActiveSamplers.end();
-				it != end_it;
-				++it)
-			{
-				(*it)->mergeFrom(mPrimarySampler);
-			}
-			mPrimarySampler.reset();
-		}
+		virtual void pushToMaster() = 0;
 
 		Sampler* getPrimarySampler() { return &mPrimarySampler; }
 	protected:
@@ -453,15 +424,16 @@ namespace LLTrace
 		std::list<Sampler*>		mActiveSamplers;
 	};
 
-	class MasterThreadTrace : public ThreadTraceData
+	class MasterThreadTrace : public ThreadTrace
 	{
 	public:
-		MasterThreadTrace()
-		{}
+		MasterThreadTrace();
 
 		void addSlaveThread(class SlaveThreadTrace* child);
 		void removeSlaveThread(class SlaveThreadTrace* child);
 
+		/*virtual */ void pushToMaster();
+
 		// call this periodically to gather stats data from slave threads
 		void pullFromSlaveThreads();
 
@@ -480,12 +452,12 @@ namespace LLTrace
 		LLMutex							mSlaveListMutex;
 	};
 
-	class SlaveThreadTrace : public ThreadTraceData
+	class SlaveThreadTrace : public ThreadTrace
 	{
 	public:
 		explicit 
 		SlaveThreadTrace()
-		:	ThreadTraceData(getMasterThreadTrace()),
+		:	ThreadTrace(getMasterThreadTrace()),
 			mSharedData(mPrimarySampler)
 		{
 			getMasterThreadTrace().addSlaveThread(this);
@@ -497,10 +469,7 @@ namespace LLTrace
 		}
 
 		// call this periodically to gather stats data for master thread to consume
-		void pushToParent()
-		{
-			mSharedData.copyFrom(mPrimarySampler);
-		}
+		/*virtual*/ void pushToMaster();
 
 		MasterThreadTrace* 	mMaster;
 
-- 
cgit v1.2.3


From 38354e19063478c8cda0408547ad05023b457041 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 28 Sep 2012 10:45:14 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages created
 separate constructor for static allocation of sampler buffer fixed
 start/stop/resume semantics of samplers and added sampler time interval
 tracking

---
 indra/llcommon/llcommon.cpp       |   1 +
 indra/llcommon/llqueuedthread.cpp |   1 +
 indra/llcommon/llthread.cpp       |  14 ++++-
 indra/llcommon/llthread.h         |  10 +++-
 indra/llcommon/lltrace.cpp        | 117 ++++++++++++++++++++++++++++++++------
 indra/llcommon/lltrace.h          | 108 +++++++++++++++--------------------
 6 files changed, 167 insertions(+), 84 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index c149a1fe5c..c720df7555 100644
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -29,6 +29,7 @@
 
 #include "llmemory.h"
 #include "llthread.h"
+#include "lltrace.h"
 
 //static
 BOOL LLCommon::sAprInitialized = FALSE;
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index a741d342d3..0a35474b7f 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -28,6 +28,7 @@
 
 #include "llstl.h"
 #include "lltimer.h"	// ms_sleep()
+#include "lltrace.h"
 
 //============================================================================
 
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 2ff524d9ba..7384842627 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -32,6 +32,7 @@
 #include "llmutex.h"
 
 #include "lltimer.h"
+#include "lltrace.h"
 
 #if LL_LINUX || LL_SOLARIS
 #include <sched.h>
@@ -85,7 +86,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 {
 	LLThread *threadp = (LLThread *)datap;
 
-	sTraceData = new LLTrace::SlaveThreadTrace();
+	setTraceData(new LLTrace::SlaveThreadTrace());
 
 #if !LL_DARWIN
 	sThreadIndex = threadp->mID;
@@ -100,6 +101,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 	threadp->mStatus = STOPPED;
 
 	delete sTraceData.get();
+	sTraceData = NULL;
 
 	return NULL;
 }
@@ -311,3 +313,13 @@ void LLThread::wakeLocked()
 		mRunCondition->signal();
 	}
 }
+
+LLTrace::ThreadTrace* LLThread::getTraceData()
+{
+	return sTraceData.get();
+}
+
+void LLThread::setTraceData( LLTrace::ThreadTrace* data )
+{
+	sTraceData = data;
+}
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 5cd287ec39..334ea2f0da 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -30,8 +30,12 @@
 #include "llapp.h"
 #include "llapr.h"
 #include "apr_thread_cond.h"
-#include "lltrace.h"
+#include "llmutex.h"
 
+namespace LLTrace
+{
+	class ThreadTrace;
+}
 class LL_COMMON_API LLThread
 {
 private:
@@ -87,8 +91,8 @@ public:
 
 	U32 getID() const { return mID; }
 
-	static LLTrace::ThreadTrace* getTraceData() { return sTraceData.get(); }
-	static void setTraceData(LLTrace::ThreadTrace* data) { sTraceData = data;}
+	static LLTrace::ThreadTrace* getTraceData();
+	static void setTraceData(LLTrace::ThreadTrace* data);
 
 private:
 	BOOL				mPaused;
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 24a2b33a5f..2da4363b1d 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -55,40 +55,97 @@ MasterThreadTrace& getMasterThreadTrace()
 	return *gMasterThreadTrace;
 }
 
-
-
 ///////////////////////////////////////////////////////////////////////
 // Sampler
 ///////////////////////////////////////////////////////////////////////
 
+Sampler::Sampler(ThreadTrace* thread_trace) 
+:	mElapsedSeconds(0),
+	mIsStarted(false),
+	mThreadTrace(thread_trace)
+{
+}
 
-void Sampler::stop()
+Sampler::~Sampler()
 {
-	getThreadTrace()->deactivate(this);
+}
+
+void Sampler::start()
+{
+	reset();
+	resume();
+}
+
+void Sampler::reset()
+{
+	mF32Stats.reset();
+	mS32Stats.reset();
+	mStackTimers.reset();
+
+	mElapsedSeconds = 0.0;
+	mSamplingTimer.reset();
 }
 
 void Sampler::resume()
 {
-	getThreadTrace()->activate(this);
+	if (!mIsStarted)
+	{
+		mSamplingTimer.reset();
+		getThreadTrace()->activate(this);
+		mIsStarted = true;
+	}
+}
+
+void Sampler::stop()
+{
+	if (mIsStarted)
+	{
+		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+		getThreadTrace()->deactivate(this);
+		mIsStarted = false;
+	}
+}
+
+ThreadTrace* Sampler::getThreadTrace()
+{
+	return mThreadTrace;
+}
+
+void Sampler::makePrimary()
+{
+	mF32Stats.makePrimary();
+	mS32Stats.makePrimary();
+	mStackTimers.makePrimary();
 }
 
-class ThreadTrace* Sampler::getThreadTrace()
+void Sampler::mergeFrom( const Sampler* other )
 {
-	return LLThread::getTraceData();
+	mF32Stats.mergeFrom(other->mF32Stats);
+	mS32Stats.mergeFrom(other->mS32Stats);
+	mStackTimers.mergeFrom(other->mStackTimers);
 }
 
+
 ///////////////////////////////////////////////////////////////////////
 // MasterThreadTrace
 ///////////////////////////////////////////////////////////////////////
 
 ThreadTrace::ThreadTrace()
 {
-	mPrimarySampler.makePrimary();
+	mPrimarySampler = createSampler();
+	mPrimarySampler->makePrimary();
+	mPrimarySampler->start();
 }
 
-ThreadTrace::ThreadTrace( const ThreadTrace& other ) :	mPrimarySampler(other.mPrimarySampler)
+ThreadTrace::ThreadTrace( const ThreadTrace& other ) 
+:	mPrimarySampler(new Sampler(*(other.mPrimarySampler)))
 {
-	mPrimarySampler.makePrimary();
+	mPrimarySampler->makePrimary();
+}
+
+ThreadTrace::~ThreadTrace()
+{
+	delete mPrimarySampler;
 }
 
 void ThreadTrace::activate( Sampler* sampler )
@@ -117,11 +174,13 @@ void ThreadTrace::flushPrimary()
 	{
 		(*it)->mergeFrom(mPrimarySampler);
 	}
-	mPrimarySampler.reset();
+	mPrimarySampler->reset();
 }
 
-
-
+Sampler* ThreadTrace::createSampler()
+{
+	return new Sampler(this);
+}
 
 
 
@@ -129,12 +188,23 @@ void ThreadTrace::flushPrimary()
 // SlaveThreadTrace
 ///////////////////////////////////////////////////////////////////////
 
+SlaveThreadTrace::SlaveThreadTrace()
+:	ThreadTrace(getMasterThreadTrace()),
+	mSharedData(createSampler())
+{
+	getMasterThreadTrace().addSlaveThread(this);
+}
+
+SlaveThreadTrace::~SlaveThreadTrace()
+{
+	getMasterThreadTrace().removeSlaveThread(this);
+}
+
 void SlaveThreadTrace::pushToMaster()
 {
 	mSharedData.copyFrom(mPrimarySampler);
 }
 
-
 ///////////////////////////////////////////////////////////////////////
 // MasterThreadTrace
 ///////////////////////////////////////////////////////////////////////
@@ -155,7 +225,7 @@ void MasterThreadTrace::addSlaveThread( class SlaveThreadTrace* child )
 {
 	LLMutexLock lock(&mSlaveListMutex);
 
-	mSlaveThreadTraces.push_back(SlaveThreadTraceProxy(child));
+	mSlaveThreadTraces.push_back(SlaveThreadTraceProxy(child, createSampler()));
 }
 
 void MasterThreadTrace::removeSlaveThread( class SlaveThreadTrace* child )
@@ -175,15 +245,26 @@ void MasterThreadTrace::removeSlaveThread( class SlaveThreadTrace* child )
 }
 
 void MasterThreadTrace::pushToMaster()
-{
-
-}
+{}
 
 MasterThreadTrace::MasterThreadTrace()
 {
 	LLThread::setTraceData(this);
 }
 
+///////////////////////////////////////////////////////////////////////
+// MasterThreadTrace::SlaveThreadTraceProxy
+///////////////////////////////////////////////////////////////////////
+
+MasterThreadTrace::SlaveThreadTraceProxy::SlaveThreadTraceProxy( class SlaveThreadTrace* trace, Sampler* storage ) 
+:	mSlaveTrace(trace),
+	mSamplerStorage(storage)
+{}
 
+MasterThreadTrace::SlaveThreadTraceProxy::~SlaveThreadTraceProxy()
+{
+	delete mSamplerStorage;
 }
 
+
+}
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 601b5ed182..a443735e69 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -32,6 +32,7 @@
 
 #include "llmutex.h"
 #include "llmemory.h"
+#include "lltimer.h"
 
 #include <list>
 
@@ -39,6 +40,7 @@
 #define TOKEN_PASTE(x, y) TOKEN_PASTE_ACTUAL(x, y)
 #define RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder TOKEN_PASTE(block_time_recorder, __COUNTER__)(block_timer);
 
+
 namespace LLTrace
 {
 	void init();
@@ -135,7 +137,7 @@ namespace LLTrace
 
 		static AccumulatorBuffer<ACCUMULATOR>& getDefaultBuffer()
 		{
-			static AccumulatorBuffer sBuffer;
+			static AccumulatorBuffer sBuffer(STATIC_ALLOC);
 			return sBuffer;
 		}
 
@@ -354,54 +356,38 @@ namespace LLTrace
 	class Sampler
 	{
 	public:
-		Sampler() {}
-		Sampler(const Sampler& other)
-		:	mF32Stats(other.mF32Stats),
-			mS32Stats(other.mS32Stats),
-			mTimers(other.mTimers)
-		{}
-
-		~Sampler()
-		{}
+		~Sampler();
 
-		void makePrimary()
-		{
-			mF32Stats.makePrimary();
-			mS32Stats.makePrimary();
-			mTimers.makePrimary();
-		}
-
-		void start()
-		{
-			reset();
-			resume();
-		}
+		void makePrimary();
 
+		void start();
 		void stop();
 		void resume();
 
-		void mergeFrom(const Sampler& other)
-		{
-			mF32Stats.mergeFrom(other.mF32Stats);
-			mS32Stats.mergeFrom(other.mS32Stats);
-			mTimers.mergeFrom(other.mTimers);
-		}
+		void mergeFrom(const Sampler* other);
 
-		void reset()
-		{
-			mF32Stats.reset();
-			mS32Stats.reset();
-			mTimers.reset();
-		}
+		void reset();
+
+		bool isStarted() { return mIsStarted; }
 
 	private:
+		friend class ThreadTrace;
+		Sampler(class ThreadTrace* thread_trace);
+
+		// no copy
+		Sampler(const Sampler& other) {}
 		// returns data for current thread
 		class ThreadTrace* getThreadTrace(); 
 
 		AccumulatorBuffer<StatAccumulator<F32> >	mF32Stats;
 		AccumulatorBuffer<StatAccumulator<S32> >	mS32Stats;
 
-		AccumulatorBuffer<TimerAccumulator>			mTimers;
+		AccumulatorBuffer<TimerAccumulator>			mStackTimers;
+
+		bool										mIsStarted;
+		LLTimer										mSamplingTimer;
+		F64											mElapsedSeconds;
+		ThreadTrace*								mThreadTrace;
 	};
 
 	class ThreadTrace
@@ -410,17 +396,19 @@ namespace LLTrace
 		ThreadTrace();
 		ThreadTrace(const ThreadTrace& other);
 
-		virtual ~ThreadTrace() {}
+		virtual ~ThreadTrace();
 
 		void activate(Sampler* sampler);
 		void deactivate(Sampler* sampler);
 		void flushPrimary();
 
+		Sampler* createSampler();
+
 		virtual void pushToMaster() = 0;
 
-		Sampler* getPrimarySampler() { return &mPrimarySampler; }
+		Sampler* getPrimarySampler() { return mPrimarySampler; }
 	protected:
-		Sampler					mPrimarySampler;
+		Sampler*				mPrimarySampler;
 		std::list<Sampler*>		mActiveSamplers;
 	};
 
@@ -440,11 +428,11 @@ namespace LLTrace
 	private:
 		struct SlaveThreadTraceProxy
 		{
-			SlaveThreadTraceProxy(class SlaveThreadTrace* trace)
-				:	mSlaveTrace(trace)
-			{}
+			SlaveThreadTraceProxy(class SlaveThreadTrace* trace, Sampler* storage);
+
+			~SlaveThreadTraceProxy();
 			class SlaveThreadTrace*	mSlaveTrace;
-			Sampler				mSamplerStorage;
+			Sampler*				mSamplerStorage;
 		};
 		typedef std::list<SlaveThreadTraceProxy> slave_thread_trace_list_t;
 
@@ -455,18 +443,8 @@ namespace LLTrace
 	class SlaveThreadTrace : public ThreadTrace
 	{
 	public:
-		explicit 
-		SlaveThreadTrace()
-		:	ThreadTrace(getMasterThreadTrace()),
-			mSharedData(mPrimarySampler)
-		{
-			getMasterThreadTrace().addSlaveThread(this);
-		}
-
-		~SlaveThreadTrace()
-		{
-			getMasterThreadTrace().removeSlaveThread(this);
-		}
+		SlaveThreadTrace();
+		~SlaveThreadTrace();
 
 		// call this periodically to gather stats data for master thread to consume
 		/*virtual*/ void pushToMaster();
@@ -479,29 +457,35 @@ namespace LLTrace
 		{
 		public:
 			explicit 
-			SharedData(const Sampler& other_sampler) 
-			:	mSampler(other_sampler)
-			{}
+			SharedData(Sampler* sampler) 
+			:	mSampler(sampler)
+			{
+			}
+
+			~SharedData()
+			{
+				delete mSampler;
+			}
 
-			void copyFrom(Sampler& source)
+			void copyFrom(Sampler* source)
 			{
 				LLMutexLock lock(&mSamplerMutex);
 				{	
-					mSampler.mergeFrom(source);
+					mSampler->mergeFrom(source);
 				}
 			}
 
-			void copyTo(Sampler& sink)
+			void copyTo(Sampler* sink)
 			{
 				LLMutexLock lock(&mSamplerMutex);
 				{
-					sink.mergeFrom(mSampler);
+					sink->mergeFrom(mSampler);
 				}
 			}
 		private:
 			// add a cache line's worth of unused space to avoid any potential of false sharing
 			LLMutex					mSamplerMutex;
-			Sampler					mSampler;
+			Sampler*				mSampler;
 		};
 		SharedData					mSharedData;
 	};
-- 
cgit v1.2.3


From b1baf982b1bd41a150233d0a28d3601226924c65 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sun, 30 Sep 2012 10:41:29 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages factored
 out lltrace::sampler into separate file added rudimentary lltrace support to
 llstatgraph made llstatgraph use param blocks more effectively moves initial
 set of stats over to lltrace removed windows.h #defines for min and max

---
 indra/llcommon/CMakeLists.txt     |   2 +
 indra/llcommon/llapr.h            |   2 +
 indra/llcommon/lltrace.cpp        | 112 +++++++++++----------------------
 indra/llcommon/lltrace.h          | 127 ++++++++++++--------------------------
 indra/llcommon/lltracesampler.cpp | 103 +++++++++++++++++++++++++++++++
 indra/llcommon/lltracesampler.h   |  91 +++++++++++++++++++++++++++
 6 files changed, 275 insertions(+), 162 deletions(-)
 create mode 100644 indra/llcommon/lltracesampler.cpp
 create mode 100644 indra/llcommon/lltracesampler.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index f78751601c..e10dbb3e4d 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -101,6 +101,7 @@ set(llcommon_SOURCE_FILES
     llthreadsafequeue.cpp
     lltimer.cpp
     lltrace.cpp
+    lltracesampler.cpp
     lluri.cpp
     lluuid.cpp
     llworkerthread.cpp
@@ -243,6 +244,7 @@ set(llcommon_HEADER_FILES
     llthreadsafequeue.h
     lltimer.h
     lltrace.h
+    lltracesampler.h
     lltreeiterators.h
     lltypeinfolookup.h
     lluri.h
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 830e0a33fa..4e704998c2 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -39,6 +39,8 @@
 	#define WIN32_LEAN_AND_MEAN
 	#include <winsock2.h>
 	#include <windows.h>
+	#undef min
+	#undef max
 #endif
 
 #include <boost/noncopyable.hpp>
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 2da4363b1d..e487e450a9 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -26,6 +26,7 @@
 #include "linden_common.h"
 
 #include "lltrace.h"
+#include "lltracesampler.h"
 #include "llthread.h"
 
 namespace LLTrace
@@ -55,77 +56,6 @@ MasterThreadTrace& getMasterThreadTrace()
 	return *gMasterThreadTrace;
 }
 
-///////////////////////////////////////////////////////////////////////
-// Sampler
-///////////////////////////////////////////////////////////////////////
-
-Sampler::Sampler(ThreadTrace* thread_trace) 
-:	mElapsedSeconds(0),
-	mIsStarted(false),
-	mThreadTrace(thread_trace)
-{
-}
-
-Sampler::~Sampler()
-{
-}
-
-void Sampler::start()
-{
-	reset();
-	resume();
-}
-
-void Sampler::reset()
-{
-	mF32Stats.reset();
-	mS32Stats.reset();
-	mStackTimers.reset();
-
-	mElapsedSeconds = 0.0;
-	mSamplingTimer.reset();
-}
-
-void Sampler::resume()
-{
-	if (!mIsStarted)
-	{
-		mSamplingTimer.reset();
-		getThreadTrace()->activate(this);
-		mIsStarted = true;
-	}
-}
-
-void Sampler::stop()
-{
-	if (mIsStarted)
-	{
-		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
-		getThreadTrace()->deactivate(this);
-		mIsStarted = false;
-	}
-}
-
-ThreadTrace* Sampler::getThreadTrace()
-{
-	return mThreadTrace;
-}
-
-void Sampler::makePrimary()
-{
-	mF32Stats.makePrimary();
-	mS32Stats.makePrimary();
-	mStackTimers.makePrimary();
-}
-
-void Sampler::mergeFrom( const Sampler* other )
-{
-	mF32Stats.mergeFrom(other->mF32Stats);
-	mS32Stats.mergeFrom(other->mS32Stats);
-	mStackTimers.mergeFrom(other->mStackTimers);
-}
-
-
 ///////////////////////////////////////////////////////////////////////
 // MasterThreadTrace
 ///////////////////////////////////////////////////////////////////////
@@ -148,6 +78,11 @@ ThreadTrace::~ThreadTrace()
 	delete mPrimarySampler;
 }
 
+Sampler* ThreadTrace::getPrimarySampler()
+{
+	return mPrimarySampler;
+}
+
 void ThreadTrace::activate( Sampler* sampler )
 {
 	flushPrimary();
@@ -205,6 +140,34 @@ void SlaveThreadTrace::pushToMaster()
 	mSharedData.copyFrom(mPrimarySampler);
 }
 
+void SlaveThreadTrace::SharedData::copyFrom( Sampler* source )
+{
+	LLMutexLock lock(&mSamplerMutex);
+	{	
+		mSampler->mergeFrom(source);
+	}
+}
+
+void SlaveThreadTrace::SharedData::copyTo( Sampler* sink )
+{
+	LLMutexLock lock(&mSamplerMutex);
+	{
+		sink->mergeFrom(mSampler);
+	}
+}
+
+SlaveThreadTrace::SharedData::~SharedData()
+{
+	delete mSampler;
+}
+
+SlaveThreadTrace::SharedData::SharedData( Sampler* sampler ) :	mSampler(sampler)
+{}
+
+
+
+
+
 ///////////////////////////////////////////////////////////////////////
 // MasterThreadTrace
 ///////////////////////////////////////////////////////////////////////
@@ -217,7 +180,7 @@ void MasterThreadTrace::pullFromSlaveThreads()
 		it != end_it;
 		++it)
 	{
-		it->mSlaveTrace->mSharedData.copyTo(it->mSamplerStorage);
+		(*it)->mSlaveTrace->mSharedData.copyTo((*it)->mSamplerStorage);
 	}
 }
 
@@ -225,7 +188,7 @@ void MasterThreadTrace::addSlaveThread( class SlaveThreadTrace* child )
 {
 	LLMutexLock lock(&mSlaveListMutex);
 
-	mSlaveThreadTraces.push_back(SlaveThreadTraceProxy(child, createSampler()));
+	mSlaveThreadTraces.push_back(new SlaveThreadTraceProxy(child, createSampler()));
 }
 
 void MasterThreadTrace::removeSlaveThread( class SlaveThreadTrace* child )
@@ -236,7 +199,7 @@ void MasterThreadTrace::removeSlaveThread( class SlaveThreadTrace* child )
 		it != end_it;
 		++it)
 	{
-		if (it->mSlaveTrace == child)
+		if ((*it)->mSlaveTrace == child)
 		{
 			mSlaveThreadTraces.erase(it);
 			break;
@@ -266,5 +229,4 @@ MasterThreadTrace::SlaveThreadTraceProxy::~SlaveThreadTraceProxy()
 	delete mSamplerStorage;
 }
 
-
 }
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index a443735e69..c6f920b5e4 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -43,14 +43,16 @@
 
 namespace LLTrace
 {
+	class Sampler;
+
 	void init();
 	void cleanup();
 
-	class MasterThreadTrace& getMasterThreadTrace();
+	class LL_COMMON_API MasterThreadTrace& getMasterThreadTrace();
 
 	// one per thread per type
 	template<typename ACCUMULATOR>
-	class AccumulatorBuffer
+	class LL_COMMON_API AccumulatorBuffer
 	{
 		static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64;
 	private:
@@ -64,6 +66,8 @@ namespace LLTrace
 
 	public:
 
+		// copying an accumulator buffer does not copy the actual contents, but simply initializes the buffer size
+		// to be identical to the other buffer
 		AccumulatorBuffer(const AccumulatorBuffer& other = getDefaultBuffer())
 		:	mStorageSize(other.mStorageSize),
 			mStorage(new ACCUMULATOR[other.mStorageSize]),
@@ -150,28 +154,30 @@ namespace LLTrace
 	template<typename ACCUMULATOR> LLThreadLocalPtr<ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>::sPrimaryStorage;
 
 	template<typename ACCUMULATOR>
-	class Trace
+	class LL_COMMON_API TraceType
 	{
 	public:
-		Trace(const std::string& name)
+		TraceType(const std::string& name)
 		:	mName(name)
 		{
 			mAccumulatorIndex = AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer().reserveSlot();
 		}
 
-		LL_FORCE_INLINE ACCUMULATOR& getAccumulator()
+		LL_FORCE_INLINE ACCUMULATOR& getPrimaryAccumulator()
 		{
 			return AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage()[mAccumulatorIndex];
 		}
 
-	private:
+		ACCUMULATOR& getAccumulator(AccumulatorBuffer<ACCUMULATOR>& buffer) { return buffer[mAccumulatorIndex]; }
+
+	protected:
 		std::string	mName;
 		size_t		mAccumulatorIndex;
 	};
 
 
 	template<typename T>
-	class StatAccumulator
+	class LL_COMMON_API StatAccumulator
 	{
 	public:
 		StatAccumulator()
@@ -217,6 +223,11 @@ namespace LLTrace
 			mMax = 0;
 		}
 
+		T	getSum() { return mSum; }
+		T	getMin() { return mMin; }
+		T	getMax() { return mMax; }
+		T	getMean() { return mSum / (T)mNumSamples; }
+
 	private:
 		T	mSum,
 			mMin,
@@ -226,20 +237,23 @@ namespace LLTrace
 	};
 
 	template <typename T>
-	class Stat : public Trace<StatAccumulator<T> >
+	class LL_COMMON_API Stat 
+	:	public TraceType<StatAccumulator<T> >, 
+		public LLInstanceTracker<Stat<T>, std::string>
 	{
 	public:
 		Stat(const std::string& name) 
-		:	Trace(name)
+		:	TraceType(name),
+			LLInstanceTracker(name)
 		{}
 
 		void sample(T value)
 		{
-			getAccumulator().sample(value);
+			getPrimaryAccumulator().sample(value);
 		}
 	};
 
-	struct TimerAccumulator
+	struct LL_COMMON_API TimerAccumulator
 	{
 		U32 							mTotalTimeCounter,
 										mChildTimeCounter,
@@ -267,11 +281,11 @@ namespace LLTrace
 
 	};
 
-	class BlockTimer : public Trace<TimerAccumulator>
+	class LL_COMMON_API BlockTimer : public TraceType<TimerAccumulator>
 	{
 	public:
 		BlockTimer(const char* name)
-		:	Trace(name)
+		:	TraceType(name)
 		{}
 
 		struct Recorder
@@ -287,7 +301,7 @@ namespace LLTrace
 			:	mLastRecorder(sCurRecorder)
 			{
 				mStartTime = getCPUClockCount32();
-				TimerAccumulator* accumulator = &block_timer.getAccumulator(); // get per-thread accumulator
+				TimerAccumulator* accumulator = &block_timer.getPrimaryAccumulator(); // get per-thread accumulator
 				accumulator->mActiveCount++;
 				accumulator->mCalls++;
 				accumulator->mMoveUpTree |= (accumulator->mParent->mActiveCount == 0);
@@ -353,44 +367,7 @@ namespace LLTrace
 		static Recorder::StackEntry sCurRecorder;
 	};
 
-	class Sampler
-	{
-	public:
-		~Sampler();
-
-		void makePrimary();
-
-		void start();
-		void stop();
-		void resume();
-
-		void mergeFrom(const Sampler* other);
-
-		void reset();
-
-		bool isStarted() { return mIsStarted; }
-
-	private:
-		friend class ThreadTrace;
-		Sampler(class ThreadTrace* thread_trace);
-
-		// no copy
-		Sampler(const Sampler& other) {}
-		// returns data for current thread
-		class ThreadTrace* getThreadTrace(); 
-
-		AccumulatorBuffer<StatAccumulator<F32> >	mF32Stats;
-		AccumulatorBuffer<StatAccumulator<S32> >	mS32Stats;
-
-		AccumulatorBuffer<TimerAccumulator>			mStackTimers;
-
-		bool										mIsStarted;
-		LLTimer										mSamplingTimer;
-		F64											mElapsedSeconds;
-		ThreadTrace*								mThreadTrace;
-	};
-
-	class ThreadTrace
+	class LL_COMMON_API ThreadTrace
 	{
 	public:
 		ThreadTrace();
@@ -406,13 +383,13 @@ namespace LLTrace
 
 		virtual void pushToMaster() = 0;
 
-		Sampler* getPrimarySampler() { return mPrimarySampler; }
+		Sampler* getPrimarySampler();
 	protected:
 		Sampler*				mPrimarySampler;
 		std::list<Sampler*>		mActiveSamplers;
 	};
 
-	class MasterThreadTrace : public ThreadTrace
+	class LL_COMMON_API MasterThreadTrace : public ThreadTrace
 	{
 	public:
 		MasterThreadTrace();
@@ -433,14 +410,17 @@ namespace LLTrace
 			~SlaveThreadTraceProxy();
 			class SlaveThreadTrace*	mSlaveTrace;
 			Sampler*				mSamplerStorage;
+		private:
+			//no need to copy these and then have to duplicate the storage
+			SlaveThreadTraceProxy(const SlaveThreadTraceProxy& other) {}
 		};
-		typedef std::list<SlaveThreadTraceProxy> slave_thread_trace_list_t;
+		typedef std::list<SlaveThreadTraceProxy*> slave_thread_trace_list_t;
 
 		slave_thread_trace_list_t		mSlaveThreadTraces;
 		LLMutex							mSlaveListMutex;
 	};
 
-	class SlaveThreadTrace : public ThreadTrace
+	class LL_COMMON_API SlaveThreadTrace : public ThreadTrace
 	{
 	public:
 		SlaveThreadTrace();
@@ -457,31 +437,12 @@ namespace LLTrace
 		{
 		public:
 			explicit 
-			SharedData(Sampler* sampler) 
-			:	mSampler(sampler)
-			{
-			}
+			SharedData(Sampler* sampler);
 
-			~SharedData()
-			{
-				delete mSampler;
-			}
+			~SharedData();
 
-			void copyFrom(Sampler* source)
-			{
-				LLMutexLock lock(&mSamplerMutex);
-				{	
-					mSampler->mergeFrom(source);
-				}
-			}
-
-			void copyTo(Sampler* sink)
-			{
-				LLMutexLock lock(&mSamplerMutex);
-				{
-					sink->mergeFrom(mSampler);
-				}
-			}
+			void copyFrom(Sampler* source);
+			void copyTo(Sampler* sink);
 		private:
 			// add a cache line's worth of unused space to avoid any potential of false sharing
 			LLMutex					mSamplerMutex;
@@ -489,14 +450,6 @@ namespace LLTrace
 		};
 		SharedData					mSharedData;
 	};
-
-	class TimeInterval 
-	{
-	public:
-		void start() {}
-		void stop() {}
-		void resume() {}
-	};
 }
 
 #endif // LL_LLTRACE_H
diff --git a/indra/llcommon/lltracesampler.cpp b/indra/llcommon/lltracesampler.cpp
new file mode 100644
index 0000000000..0cf01d7a3a
--- /dev/null
+++ b/indra/llcommon/lltracesampler.cpp
@@ -0,0 +1,103 @@
+/** 
+ * @file lltracesampler.cpp
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltracesampler.h"
+
+namespace LLTrace
+{
+
+///////////////////////////////////////////////////////////////////////
+// Sampler
+///////////////////////////////////////////////////////////////////////
+
+Sampler::Sampler(ThreadTrace* thread_trace) 
+:	mElapsedSeconds(0),
+	mIsStarted(false),
+	mThreadTrace(thread_trace)
+{
+}
+
+Sampler::~Sampler()
+{
+}
+
+void Sampler::start()
+{
+	reset();
+	resume();
+}
+
+void Sampler::reset()
+{
+	mF32Stats.reset();
+	mS32Stats.reset();
+	mStackTimers.reset();
+
+	mElapsedSeconds = 0.0;
+	mSamplingTimer.reset();
+}
+
+void Sampler::resume()
+{
+	if (!mIsStarted)
+	{
+		mSamplingTimer.reset();
+		getThreadTrace()->activate(this);
+		mIsStarted = true;
+	}
+}
+
+void Sampler::stop()
+{
+	if (mIsStarted)
+	{
+		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+		getThreadTrace()->deactivate(this);
+		mIsStarted = false;
+	}
+}
+
+ThreadTrace* Sampler::getThreadTrace()
+{
+	return mThreadTrace;
+}
+
+void Sampler::makePrimary()
+{
+	mF32Stats.makePrimary();
+	mS32Stats.makePrimary();
+	mStackTimers.makePrimary();
+}
+
+void Sampler::mergeFrom( const Sampler* other )
+{
+	mF32Stats.mergeFrom(other->mF32Stats);
+	mS32Stats.mergeFrom(other->mS32Stats);
+	mStackTimers.mergeFrom(other->mStackTimers);
+}
+
+}
diff --git a/indra/llcommon/lltracesampler.h b/indra/llcommon/lltracesampler.h
new file mode 100644
index 0000000000..d1ca7fc9bb
--- /dev/null
+++ b/indra/llcommon/lltracesampler.h
@@ -0,0 +1,91 @@
+/** 
+ * @file lltracesampler.h
+ * @brief Sampling object for collecting runtime statistics originating from lltrace.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRACESAMPLER_H
+#define LL_LLTRACESAMPLER_H
+
+#include "stdtypes.h"
+#include "llpreprocessor.h"
+
+#include "lltrace.h"
+
+namespace LLTrace
+{
+	class LL_COMMON_API Sampler
+	{
+	public:
+		~Sampler();
+
+		void makePrimary();
+
+		void start();
+		void stop();
+		void resume();
+
+		void mergeFrom(const Sampler* other);
+
+		void reset();
+
+		bool isStarted() { return mIsStarted; }
+
+		F32 getSum(Stat<F32>& stat) { return stat.getAccumulator(mF32Stats).getSum(); }
+		F32 getMin(Stat<F32>& stat) { return stat.getAccumulator(mF32Stats).getMin(); }
+		F32 getMax(Stat<F32>& stat) { return stat.getAccumulator(mF32Stats).getMax(); }
+		F32 getMean(Stat<F32>& stat) { return stat.getAccumulator(mF32Stats).getMean(); }
+
+		S32 getSum(Stat<S32>& stat) { return stat.getAccumulator(mS32Stats).getSum(); }
+		S32 getMin(Stat<S32>& stat) { return stat.getAccumulator(mS32Stats).getMin(); }
+		S32 getMax(Stat<S32>& stat) { return stat.getAccumulator(mS32Stats).getMax(); }
+		S32 getMean(Stat<S32>& stat) { return stat.getAccumulator(mS32Stats).getMean(); }
+
+		F64 getSampleTime() { return mElapsedSeconds; }
+
+	private:
+		friend class ThreadTrace;
+		Sampler(class ThreadTrace* thread_trace);
+
+		// no copy
+		Sampler(const Sampler& other) {}
+		// returns data for current thread
+		class ThreadTrace* getThreadTrace(); 
+
+		//TODO: take snapshot at sampler start so we can simplify updates
+		//AccumulatorBuffer<StatAccumulator<F32> >	mF32StatsStart;
+		//AccumulatorBuffer<StatAccumulator<S32> >	mS32StatsStart;
+		//AccumulatorBuffer<TimerAccumulator>			mStackTimersStart;
+
+		AccumulatorBuffer<StatAccumulator<F32> >	mF32Stats;
+		AccumulatorBuffer<StatAccumulator<S32> >	mS32Stats;
+		AccumulatorBuffer<TimerAccumulator>			mStackTimers;
+
+		bool										mIsStarted;
+		LLTimer										mSamplingTimer;
+		F64											mElapsedSeconds;
+		ThreadTrace*								mThreadTrace;
+	};
+}
+
+#endif // LL_LLTRACESAMPLER_H
-- 
cgit v1.2.3


From 14b1b0b2bb6bac5bc688cc4d14c33f1b680dd3b4 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 1 Oct 2012 19:39:04 -0700
Subject: SH-3275 WIP Run viewer metrics for object update messages cleaned up
 API samplers are now value types with copy-on-write buffers under the hood
 removed coupling with LLThread

---
 indra/llcommon/llapr.cpp          |  28 +++---
 indra/llcommon/llapr.h            |  28 +++---
 indra/llcommon/llpointer.h        |  83 +++++++++++++-----
 indra/llcommon/llqueuedthread.cpp |   2 +-
 indra/llcommon/llthread.cpp       |  15 +---
 indra/llcommon/llthread.h         |   9 --
 indra/llcommon/lltrace.cpp        | 108 ++++++++++-------------
 indra/llcommon/lltrace.h          | 180 ++++++++++++++++++++++++++++++--------
 indra/llcommon/lltracesampler.cpp |  98 +++++++++++++++++----
 indra/llcommon/lltracesampler.h   |  59 +++++++------
 10 files changed, 398 insertions(+), 212 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index e9930c10f7..d23b70690d 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -55,7 +55,7 @@ void ll_init_apr()
 		LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE);
 	}
 
-	LLThreadLocalPtrBase::initAllThreadLocalStorage();
+	LLThreadLocalPointerBase::initAllThreadLocalStorage();
 }
 
 
@@ -80,7 +80,7 @@ void ll_cleanup_apr()
 		gCallStacksLogMutexp = NULL;
 	}
 
-	LLThreadLocalPtrBase::destroyAllThreadLocalStorage();
+	LLThreadLocalPointerBase::destroyAllThreadLocalStorage();
 
 	if (gAPRPoolp)
 	{
@@ -482,11 +482,11 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
 }
 
 //
-//LLThreadLocalPtrBase
+//LLThreadLocalPointerBase
 //
-bool LLThreadLocalPtrBase::sInitialized = false;
+bool LLThreadLocalPointerBase::sInitialized = false;
 
-LLThreadLocalPtrBase::LLThreadLocalPtrBase()
+LLThreadLocalPointerBase::LLThreadLocalPointerBase()
 :	mThreadKey(NULL)
 {
 	if (sInitialized)
@@ -495,7 +495,7 @@ LLThreadLocalPtrBase::LLThreadLocalPtrBase()
 	}
 }
 
-LLThreadLocalPtrBase::LLThreadLocalPtrBase( const LLThreadLocalPtrBase& other)
+LLThreadLocalPointerBase::LLThreadLocalPointerBase( const LLThreadLocalPointerBase& other)
 :	mThreadKey(NULL)
 {
 	if (sInitialized)
@@ -504,12 +504,12 @@ LLThreadLocalPtrBase::LLThreadLocalPtrBase( const LLThreadLocalPtrBase& other)
 	}
 }
 
-LLThreadLocalPtrBase::~LLThreadLocalPtrBase()
+LLThreadLocalPointerBase::~LLThreadLocalPointerBase()
 {
 	destroyStorage();
 }
 
-void LLThreadLocalPtrBase::set( void* value )
+void LLThreadLocalPointerBase::set( void* value )
 {
 	llassert(sInitialized && mThreadKey);
 
@@ -521,7 +521,7 @@ void LLThreadLocalPtrBase::set( void* value )
 	}
 }
 
-void LLThreadLocalPtrBase::initStorage( )
+void LLThreadLocalPointerBase::initStorage( )
 {
 	apr_status_t result = apr_threadkey_private_create(&mThreadKey, NULL, gAPRPoolp);
 	if (result != APR_SUCCESS)
@@ -531,7 +531,7 @@ void LLThreadLocalPtrBase::initStorage( )
 	}
 }
 
-void LLThreadLocalPtrBase::destroyStorage()
+void LLThreadLocalPointerBase::destroyStorage()
 {
 	if (sInitialized)
 	{
@@ -547,11 +547,11 @@ void LLThreadLocalPtrBase::destroyStorage()
 	}
 }
 
-void LLThreadLocalPtrBase::initAllThreadLocalStorage()
+void LLThreadLocalPointerBase::initAllThreadLocalStorage()
 {
 	if (!sInitialized)
 	{
-		for (LLInstanceTracker<LLThreadLocalPtrBase>::instance_iter it = beginInstances(), end_it = endInstances();
+		for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances();
 			it != end_it;
 			++it)
 		{
@@ -561,11 +561,11 @@ void LLThreadLocalPtrBase::initAllThreadLocalStorage()
 	}
 }
 
-void LLThreadLocalPtrBase::destroyAllThreadLocalStorage()
+void LLThreadLocalPointerBase::destroyAllThreadLocalStorage()
 {
 	if (sInitialized)
 	{
-		for (LLInstanceTracker<LLThreadLocalPtrBase>::instance_iter it = beginInstances(), end_it = endInstances();
+		for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances();
 			it != end_it;
 			++it)
 		{
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 4e704998c2..6efb44a663 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -258,12 +258,12 @@ public:
 //*******************************************************************************************************************************
 };
 
-class LLThreadLocalPtrBase : LLInstanceTracker<LLThreadLocalPtrBase>
+class LLThreadLocalPointerBase : LLInstanceTracker<LLThreadLocalPointerBase>
 {
 public:
-	LLThreadLocalPtrBase();
-	LLThreadLocalPtrBase(const LLThreadLocalPtrBase& other);
-	~LLThreadLocalPtrBase();
+	LLThreadLocalPointerBase();
+	LLThreadLocalPointerBase(const LLThreadLocalPointerBase& other);
+	~LLThreadLocalPointerBase();
 
 	static void initAllThreadLocalStorage();
 	static void destroyAllThreadLocalStorage();
@@ -307,35 +307,35 @@ protected:
 };
 
 template <typename T>
-class LLThreadLocalPtr : public LLThreadLocalPtrBase
+class LLThreadLocalPointer : public LLThreadLocalPointerBase
 {
 public:
 
-	LLThreadLocalPtr()
-	:	LLThreadLocalPtrBase()
+	LLThreadLocalPointer()
+	:	LLThreadLocalPointerBase()
 	{}
 
-	explicit LLThreadLocalPtr(T* value)
-		:	LLThreadLocalPtrBase(&cleanup)
+	explicit LLThreadLocalPointer(T* value)
+		:	LLThreadLocalPointerBase(&cleanup)
 	{
 		set(value);
 	}
 
 
-	LLThreadLocalPtr(const LLThreadLocalPtr<T>& other)
-	:	LLThreadLocalPtrBase(other, &cleanup)
+	LLThreadLocalPointer(const LLThreadLocalPointer<T>& other)
+	:	LLThreadLocalPointerBase(other, &cleanup)
 	{
 		set(other.get());		
 	}
 
 	LL_FORCE_INLINE T* get()
 	{
-		return (T*)LLThreadLocalPtrBase::get();
+		return (T*)LLThreadLocalPointerBase::get();
 	}
 
 	const T* get() const
 	{
-		return (const T*)LLThreadLocalPtrBase::get();
+		return (const T*)LLThreadLocalPointerBase::get();
 	}
 
 	T* operator -> ()
@@ -358,7 +358,7 @@ public:
 		return *(T*)get();
 	}
 
-	LLThreadLocalPtr<T>& operator = (T* value)
+	LLThreadLocalPointer<T>& operator = (T* value)
 	{
 		set((void*)value);
 		return *this;
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index 88c09c8dca..0fee4f0990 100644
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -97,24 +97,13 @@ public:
 
 	LLPointer<Type>& operator =(Type* ptr)                   
 	{ 
-		if( mPointer != ptr )
-		{
-			unref(); 
-			mPointer = ptr; 
-			ref();
-		}
-
+		assign(ptr);
 		return *this; 
 	}
 
 	LLPointer<Type>& operator =(const LLPointer<Type>& ptr)  
 	{ 
-		if( mPointer != ptr.mPointer )
-		{
-			unref(); 
-			mPointer = ptr.mPointer;
-			ref();
-		}
+		assign(ptr);
 		return *this; 
 	}
 
@@ -122,12 +111,7 @@ public:
 	template<typename Subclass>
 	LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)  
 	{ 
-		if( mPointer != ptr.get() )
-		{
-			unref(); 
-			mPointer = ptr.get();
-			ref();
-		}
+		assign(ptr.get());
 		return *this; 
 	}
 	
@@ -144,6 +128,16 @@ protected:
 	void ref();                             
 	void unref();
 #else
+
+	void assign(const LLPointer<Type>& ptr)
+	{
+		if( mPointer != ptr.mPointer )
+		{
+			unref(); 
+			mPointer = ptr.mPointer;
+			ref();
+		}
+	}
 	void ref()                             
 	{ 
 		if (mPointer)
@@ -156,9 +150,9 @@ protected:
 	{
 		if (mPointer)
 		{
-			Type *tempp = mPointer;
+			Type *temp = mPointer;
 			mPointer = NULL;
-			tempp->unref();
+			temp->unref();
 			if (mPointer != NULL)
 			{
 				llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
@@ -171,4 +165,51 @@ protected:
 	Type*	mPointer;
 };
 
+template<typename Type>
+class LLCopyOnWritePointer : public LLPointer<Type>
+{
+public:
+	typedef LLPointer<Type> ref_pointer_t;
+	typedef LLCopyOnWritePointer<Type> self_t;
+
+	LLCopyOnWritePointer() 
+	{
+	}
+
+	LLCopyOnWritePointer(Type* ptr) 
+	:	LLPointer(ptr)
+	{
+	}
+
+	Type* write()
+	{
+		makeUnique();
+		return mPointer;
+	}
+
+	void makeUnique()
+	{
+		if (mPointer && mPointer->getNumRefs() > 1)
+		{
+			ref_pointer_t::assign(new Type(*mPointer));
+		}
+	}
+
+	using ref_pointer_t::operator BOOL;
+	using ref_pointer_t::operator bool;
+	using ref_pointer_t::operator!;
+
+	using ref_pointer_t::operator !=;
+	using ref_pointer_t::operator ==;
+	using LLPointer<Type>::operator =;
+
+	using LLPointer<Type>::operator <;
+	using LLPointer<Type>::operator >;
+
+
+	operator const Type*()   const				{ return mPointer; }
+	const Type*	operator->() const				{ return mPointer; }
+
+};
+
 #endif
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 0a35474b7f..9aa449d037 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -112,7 +112,7 @@ void LLQueuedThread::shutdown()
 // virtual
 S32 LLQueuedThread::update(F32 max_time_ms)
 {
-	LLThread::getTraceData()->pushToMaster();
+	LLTrace::get_thread_trace()->pushToMaster();
 
 	if (!mStarted)
 	{
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 7384842627..c705e5103b 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -67,7 +67,6 @@ U32 __thread LLThread::sThreadID = 0;
 #endif
 
 U32 LLThread::sIDIter = 0;
-LLThreadLocalPtr<LLTrace::ThreadTrace> LLThread::sTraceData;
 
 
 LL_COMMON_API void assert_main_thread()
@@ -86,7 +85,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 {
 	LLThread *threadp = (LLThread *)datap;
 
-	setTraceData(new LLTrace::SlaveThreadTrace());
+	LLTrace::ThreadTrace* thread_trace = new LLTrace::SlaveThreadTrace();
 
 #if !LL_DARWIN
 	sThreadIndex = threadp->mID;
@@ -100,8 +99,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 	// We're done with the run function, this thread is done executing now.
 	threadp->mStatus = STOPPED;
 
-	delete sTraceData.get();
-	sTraceData = NULL;
+	delete thread_trace;
 
 	return NULL;
 }
@@ -314,12 +312,3 @@ void LLThread::wakeLocked()
 	}
 }
 
-LLTrace::ThreadTrace* LLThread::getTraceData()
-{
-	return sTraceData.get();
-}
-
-void LLThread::setTraceData( LLTrace::ThreadTrace* data )
-{
-	sTraceData = data;
-}
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 334ea2f0da..82ab5f47d2 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -32,10 +32,6 @@
 #include "apr_thread_cond.h"
 #include "llmutex.h"
 
-namespace LLTrace
-{
-	class ThreadTrace;
-}
 class LL_COMMON_API LLThread
 {
 private:
@@ -91,9 +87,6 @@ public:
 
 	U32 getID() const { return mID; }
 
-	static LLTrace::ThreadTrace* getTraceData();
-	static void setTraceData(LLTrace::ThreadTrace* data);
-
 private:
 	BOOL				mPaused;
 	
@@ -110,8 +103,6 @@ protected:
 	EThreadStatus		mStatus;
 	U32					mID;
 
-	static LLThreadLocalPtr<LLTrace::ThreadTrace> sTraceData;
-
 	//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
 	//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
 	//      otherwise it will cause severe memory leaking!!! --bao
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index e487e450a9..04817fd4f4 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -27,7 +27,6 @@
 
 #include "lltrace.h"
 #include "lltracesampler.h"
-#include "llthread.h"
 
 namespace LLTrace
 {
@@ -45,6 +44,12 @@ void cleanup()
 	gMasterThreadTrace = NULL;
 }
 
+LLThreadLocalPointer<ThreadTrace>& get_thread_trace()
+{
+	static LLThreadLocalPointer<ThreadTrace> s_trace_data;
+	return s_trace_data;
+
+}
 
 BlockTimer::Recorder::StackEntry BlockTimer::sCurRecorder;
 
@@ -62,36 +67,52 @@ MasterThreadTrace& getMasterThreadTrace()
 
 ThreadTrace::ThreadTrace()
 {
-	mPrimarySampler = createSampler();
-	mPrimarySampler->makePrimary();
-	mPrimarySampler->start();
+	get_thread_trace() = this;
+	mPrimarySampler.makePrimary();
+	mTotalSampler.start();
 }
 
 ThreadTrace::ThreadTrace( const ThreadTrace& other ) 
-:	mPrimarySampler(new Sampler(*(other.mPrimarySampler)))
+:	mPrimarySampler(other.mPrimarySampler),
+	mTotalSampler(other.mTotalSampler)
 {
-	mPrimarySampler->makePrimary();
+	get_thread_trace() = this;
+	mPrimarySampler.makePrimary();
+	mTotalSampler.start();
 }
 
 ThreadTrace::~ThreadTrace()
 {
-	delete mPrimarySampler;
+	get_thread_trace() = NULL;
 }
 
+//TODO: remove this and use llviewerstats sampler
 Sampler* ThreadTrace::getPrimarySampler()
 {
-	return mPrimarySampler;
+	return &mPrimarySampler;
 }
 
 void ThreadTrace::activate( Sampler* sampler )
 {
-	flushPrimary();
-	mActiveSamplers.push_back(sampler);
+	for (std::list<Sampler*>::iterator it = mActiveSamplers.begin(), end_it = mActiveSamplers.end();
+		it != end_it;
+		++it)
+	{
+		(*it)->mMeasurements.write()->mergeSamples(*mPrimarySampler.mMeasurements);
+	}
+	mPrimarySampler.mMeasurements.write()->reset();
+
+	sampler->initDeltas(mPrimarySampler);
+
+	mActiveSamplers.push_front(sampler);
 }
 
+//TODO: consider merging results down the list to one past the buffered item.
+// this would require 2 buffers per sampler, to separate current total from running total
+
 void ThreadTrace::deactivate( Sampler* sampler )
 {
-	sampler->mergeFrom(mPrimarySampler);
+	sampler->mergeDeltas(mPrimarySampler);
 
 	// TODO: replace with intrusive list
 	std::list<Sampler*>::iterator found_it = std::find(mActiveSamplers.begin(), mActiveSamplers.end(), sampler);
@@ -101,31 +122,12 @@ void ThreadTrace::deactivate( Sampler* sampler )
 	}
 }
 
-void ThreadTrace::flushPrimary()
-{
-	for (std::list<Sampler*>::iterator it = mActiveSamplers.begin(), end_it = mActiveSamplers.end();
-		it != end_it;
-		++it)
-	{
-		(*it)->mergeFrom(mPrimarySampler);
-	}
-	mPrimarySampler->reset();
-}
-
-Sampler* ThreadTrace::createSampler()
-{
-	return new Sampler(this);
-}
-
-
-
 ///////////////////////////////////////////////////////////////////////
 // SlaveThreadTrace
 ///////////////////////////////////////////////////////////////////////
 
 SlaveThreadTrace::SlaveThreadTrace()
-:	ThreadTrace(getMasterThreadTrace()),
-	mSharedData(createSampler())
+:	ThreadTrace(getMasterThreadTrace())
 {
 	getMasterThreadTrace().addSlaveThread(this);
 }
@@ -137,34 +139,26 @@ SlaveThreadTrace::~SlaveThreadTrace()
 
 void SlaveThreadTrace::pushToMaster()
 {
-	mSharedData.copyFrom(mPrimarySampler);
-}
-
-void SlaveThreadTrace::SharedData::copyFrom( Sampler* source )
-{
-	LLMutexLock lock(&mSamplerMutex);
-	{	
-		mSampler->mergeFrom(source);
+	mTotalSampler.stop();
+	{
+		LLMutexLock(getMasterThreadTrace().getSlaveListMutex());
+		mSharedData.copyFrom(mTotalSampler);
 	}
+	mTotalSampler.start();
 }
 
-void SlaveThreadTrace::SharedData::copyTo( Sampler* sink )
+void SlaveThreadTrace::SharedData::copyFrom( const Sampler& source )
 {
 	LLMutexLock lock(&mSamplerMutex);
-	{
-		sink->mergeFrom(mSampler);
-	}
+	mSampler.mergeSamples(source);
 }
 
-SlaveThreadTrace::SharedData::~SharedData()
+void SlaveThreadTrace::SharedData::copyTo( Sampler& sink )
 {
-	delete mSampler;
+	LLMutexLock lock(&mSamplerMutex);
+	sink.mergeSamples(mSampler);
 }
 
-SlaveThreadTrace::SharedData::SharedData( Sampler* sampler ) :	mSampler(sampler)
-{}
-
-
 
 
 
@@ -188,7 +182,7 @@ void MasterThreadTrace::addSlaveThread( class SlaveThreadTrace* child )
 {
 	LLMutexLock lock(&mSlaveListMutex);
 
-	mSlaveThreadTraces.push_back(new SlaveThreadTraceProxy(child, createSampler()));
+	mSlaveThreadTraces.push_back(new SlaveThreadTraceProxy(child));
 }
 
 void MasterThreadTrace::removeSlaveThread( class SlaveThreadTrace* child )
@@ -211,22 +205,14 @@ void MasterThreadTrace::pushToMaster()
 {}
 
 MasterThreadTrace::MasterThreadTrace()
-{
-	LLThread::setTraceData(this);
-}
+{}
 
 ///////////////////////////////////////////////////////////////////////
 // MasterThreadTrace::SlaveThreadTraceProxy
 ///////////////////////////////////////////////////////////////////////
 
-MasterThreadTrace::SlaveThreadTraceProxy::SlaveThreadTraceProxy( class SlaveThreadTrace* trace, Sampler* storage ) 
-:	mSlaveTrace(trace),
-	mSamplerStorage(storage)
+MasterThreadTrace::SlaveThreadTraceProxy::SlaveThreadTraceProxy( class SlaveThreadTrace* trace) 
+:	mSlaveTrace(trace)
 {}
 
-MasterThreadTrace::SlaveThreadTraceProxy::~SlaveThreadTraceProxy()
-{
-	delete mSamplerStorage;
-}
-
 }
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index c6f920b5e4..5ec1c821c3 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -33,6 +33,8 @@
 #include "llmutex.h"
 #include "llmemory.h"
 #include "lltimer.h"
+#include "llrefcount.h"
+#include "lltracesampler.h"
 
 #include <list>
 
@@ -48,11 +50,13 @@ namespace LLTrace
 	void init();
 	void cleanup();
 
+	LLThreadLocalPointer<class ThreadTrace>& get_thread_trace();
+
 	class LL_COMMON_API MasterThreadTrace& getMasterThreadTrace();
 
 	// one per thread per type
 	template<typename ACCUMULATOR>
-	class LL_COMMON_API AccumulatorBuffer
+	class LL_COMMON_API AccumulatorBuffer : public LLRefCount
 	{
 		static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64;
 	private:
@@ -88,13 +92,23 @@ namespace LLTrace
 			return mStorage[index]; 
 		}
 
-		void mergeFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
+		void mergeSamples(const AccumulatorBuffer<ACCUMULATOR>& other)
 		{
 			llassert(mNextStorageSlot == other.mNextStorageSlot);
 
 			for (size_t i = 0; i < mNextStorageSlot; i++)
 			{
-				mStorage[i].mergeFrom(other.mStorage[i]);
+				mStorage[i].mergeSamples(other.mStorage[i]);
+			}
+		}
+
+		void mergeDeltas(const AccumulatorBuffer<ACCUMULATOR>& start, const AccumulatorBuffer<ACCUMULATOR>& finish)
+		{
+			llassert(mNextStorageSlot == start.mNextStorageSlot && mNextStorageSlot == finish.mNextStorageSlot);
+
+			for (size_t i = 0; i < mNextStorageSlot; i++)
+			{
+				mStorage[i].mergeDeltas(start.mStorage[i], finish.mStorage[i]);
 			}
 		}
 
@@ -119,6 +133,11 @@ namespace LLTrace
 			sPrimaryStorage = mStorage;
 		}
 
+		bool isPrimary() const
+		{
+			return sPrimaryStorage == mStorage;
+		}
+
 		LL_FORCE_INLINE static ACCUMULATOR* getPrimaryStorage() 
 		{ 
 			return sPrimaryStorage.get(); 
@@ -149,9 +168,9 @@ namespace LLTrace
 		ACCUMULATOR*							mStorage;
 		size_t									mStorageSize;
 		size_t									mNextStorageSlot;
-		static LLThreadLocalPtr<ACCUMULATOR>	sPrimaryStorage;
+		static LLThreadLocalPointer<ACCUMULATOR>	sPrimaryStorage;
 	};
-	template<typename ACCUMULATOR> LLThreadLocalPtr<ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>::sPrimaryStorage;
+	template<typename ACCUMULATOR> LLThreadLocalPointer<ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>::sPrimaryStorage;
 
 	template<typename ACCUMULATOR>
 	class LL_COMMON_API TraceType
@@ -168,7 +187,7 @@ namespace LLTrace
 			return AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage()[mAccumulatorIndex];
 		}
 
-		ACCUMULATOR& getAccumulator(AccumulatorBuffer<ACCUMULATOR>& buffer) { return buffer[mAccumulatorIndex]; }
+		ACCUMULATOR& getAccumulator(AccumulatorBuffer<ACCUMULATOR>* buffer) { return (*buffer)[mAccumulatorIndex]; }
 
 	protected:
 		std::string	mName;
@@ -177,10 +196,10 @@ namespace LLTrace
 
 
 	template<typename T>
-	class LL_COMMON_API StatAccumulator
+	class LL_COMMON_API MeasurementAccumulator
 	{
 	public:
-		StatAccumulator()
+		MeasurementAccumulator()
 		:	mSum(0),
 			mMin(0),
 			mMax(0),
@@ -199,9 +218,12 @@ namespace LLTrace
 			{
 				mMax = value;
 			}
+			F32 old_mean = mMean;
+			mMean += ((F32)value - old_mean) / (F32)mNumSamples;
+			mStandardDeviation += ((F32)value - old_mean) * ((F32)value - mMean);
 		}
 
-		void mergeFrom(const StatAccumulator<T>& other)
+		void mergeSamples(const MeasurementAccumulator<T>& other)
 		{
 			mSum += other.mSum;
 			if (other.mMin < mMin)
@@ -213,6 +235,28 @@ namespace LLTrace
 				mMax = other.mMax;
 			}
 			mNumSamples += other.mNumSamples;
+			F32 weight = (F32)mNumSamples / (F32)(mNumSamples + other.mNumSamples);
+			mMean = mMean * weight + other.mMean * (1.f - weight);
+
+			F32 n_1 = (F32)mNumSamples,
+				n_2 = (F32)other.mNumSamples;
+			F32 m_1 = mMean,
+				m_2 = other.mMean;
+			F32 sd_1 = mStandardDeviation,
+				sd_2 = other.mStandardDeviation;
+			// combine variance (and hence standard deviation) of 2 different sized sample groups using
+			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+			F32 variance = ((((n_1 - 1.f) * sd_1 * sd_1)
+								+ ((n_2 - 1.f) * sd_2 * sd_2)
+								+ (((n_1 * n_2) / (n_1 + n_2))
+									* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+							/ (n_1 + n_2 - 1.f));
+			mStandardDeviation = sqrtf(variance);
+		}
+
+		void mergeDeltas(const MeasurementAccumulator<T>& start, const MeasurementAccumulator<T>& finish)
+		{
+			llerrs << "Delta merge invalid for measurement accumulators" << llendl;
 		}
 
 		void reset()
@@ -226,23 +270,68 @@ namespace LLTrace
 		T	getSum() { return mSum; }
 		T	getMin() { return mMin; }
 		T	getMax() { return mMax; }
-		T	getMean() { return mSum / (T)mNumSamples; }
+		F32	getMean() { return mMean; }
+		F32 getStandardDeviation() { return mStandardDeviation; }
 
 	private:
 		T	mSum,
 			mMin,
 			mMax;
 
+		F32 mMean,
+			mStandardDeviation;
+
+		U32	mNumSamples;
+	};
+
+	template<typename T>
+	class LL_COMMON_API RateAccumulator
+	{
+	public:
+		RateAccumulator()
+		:	mSum(0),
+			mNumSamples(0)
+		{}
+
+		LL_FORCE_INLINE void add(T value)
+		{
+			mNumSamples++;
+			mSum += value;
+		}
+
+		void mergeSamples(const RateAccumulator<T>& other)
+		{
+			mSum += other.mSum;
+			mNumSamples += other.mNumSamples;
+		}
+
+		void mergeDeltas(const RateAccumulator<T>& start, const RateAccumulator<T>& finish)
+		{
+			mSum += finish.mSum - start.mSum;
+			mNumSamples += finish.mNumSamples - start.mNumSamples;
+		}
+
+		void reset()
+		{
+			mNumSamples = 0;
+			mSum = 0;
+		}
+
+		T	getSum() { return mSum; }
+
+	private:
+		T	mSum;
+
 		U32	mNumSamples;
 	};
 
 	template <typename T>
-	class LL_COMMON_API Stat 
-	:	public TraceType<StatAccumulator<T> >, 
-		public LLInstanceTracker<Stat<T>, std::string>
+	class LL_COMMON_API Measurement
+	:	public TraceType<MeasurementAccumulator<T> >, 
+		public LLInstanceTracker<Measurement<T>, std::string>
 	{
 	public:
-		Stat(const std::string& name) 
+		Measurement(const std::string& name) 
 		:	TraceType(name),
 			LLInstanceTracker(name)
 		{}
@@ -253,11 +342,30 @@ namespace LLTrace
 		}
 	};
 
-	struct LL_COMMON_API TimerAccumulator
+	template <typename T>
+	class LL_COMMON_API Rate 
+		:	public TraceType<RateAccumulator<T> >, 
+		public LLInstanceTracker<Rate<T>, std::string>
 	{
+	public:
+		Rate(const std::string& name) 
+			:	TraceType(name),
+			LLInstanceTracker(name)
+		{}
+
+		void add(T value)
+		{
+			getPrimaryAccumulator().add(value);
+		}
+	};
+
+	class LL_COMMON_API TimerAccumulator
+	{
+	public:
 		U32 							mTotalTimeCounter,
 										mChildTimeCounter,
 										mCalls;
+
 		TimerAccumulator*				mParent;		// info for caller timer
 		TimerAccumulator*				mLastCaller;	// used to bootstrap tree construction
 		const class BlockTimer*			mTimer;			// points to block timer associated with this storage
@@ -265,13 +373,20 @@ namespace LLTrace
 		bool							mMoveUpTree;	// needs to be moved up the tree of timers at the end of frame
 		std::vector<TimerAccumulator*>	mChildren;		// currently assumed child timers
 
-		void mergeFrom(const TimerAccumulator& other)
+		void mergeSamples(const TimerAccumulator& other)
 		{
 			mTotalTimeCounter += other.mTotalTimeCounter;
 			mChildTimeCounter += other.mChildTimeCounter;
 			mCalls += other.mCalls;
 		}
 
+		void mergeDeltas(const TimerAccumulator& start, const TimerAccumulator& finish)
+		{
+			mTotalTimeCounter += finish.mTotalTimeCounter - start.mTotalTimeCounter;
+			mChildTimeCounter += finish.mChildTimeCounter - start.mChildTimeCounter;
+			mCalls += finish.mCalls - start.mCalls;
+		}
+
 		void reset()
 		{
 			mTotalTimeCounter = 0;
@@ -377,15 +492,13 @@ namespace LLTrace
 
 		void activate(Sampler* sampler);
 		void deactivate(Sampler* sampler);
-		void flushPrimary();
-
-		Sampler* createSampler();
 
 		virtual void pushToMaster() = 0;
 
 		Sampler* getPrimarySampler();
 	protected:
-		Sampler*				mPrimarySampler;
+		Sampler					mPrimarySampler;
+		Sampler					mTotalSampler;
 		std::list<Sampler*>		mActiveSamplers;
 	};
 
@@ -402,14 +515,15 @@ namespace LLTrace
 		// call this periodically to gather stats data from slave threads
 		void pullFromSlaveThreads();
 
+		LLMutex* getSlaveListMutex() { return &mSlaveListMutex; }
+
 	private:
 		struct SlaveThreadTraceProxy
 		{
-			SlaveThreadTraceProxy(class SlaveThreadTrace* trace, Sampler* storage);
+			SlaveThreadTraceProxy(class SlaveThreadTrace* trace);
 
-			~SlaveThreadTraceProxy();
 			class SlaveThreadTrace*	mSlaveTrace;
-			Sampler*				mSamplerStorage;
+			Sampler					mSamplerStorage;
 		private:
 			//no need to copy these and then have to duplicate the storage
 			SlaveThreadTraceProxy(const SlaveThreadTraceProxy& other) {}
@@ -431,24 +545,16 @@ namespace LLTrace
 
 		MasterThreadTrace* 	mMaster;
 
-		// this data is accessed by other threads, so give it a 64 byte alignment
-		// to avoid false sharing on most x86 processors
-		LL_ALIGNED(64) class SharedData
+		class SharedData
 		{
 		public:
-			explicit 
-			SharedData(Sampler* sampler);
-
-			~SharedData();
-
-			void copyFrom(Sampler* source);
-			void copyTo(Sampler* sink);
+			void copyFrom(const Sampler& source);
+			void copyTo(Sampler& sink);
 		private:
-			// add a cache line's worth of unused space to avoid any potential of false sharing
-			LLMutex					mSamplerMutex;
-			Sampler*				mSampler;
+			LLMutex		mSamplerMutex;
+			Sampler		mSampler;
 		};
-		SharedData					mSharedData;
+		SharedData		mSharedData;
 	};
 }
 
diff --git a/indra/llcommon/lltracesampler.cpp b/indra/llcommon/lltracesampler.cpp
index 0cf01d7a3a..17e58b96e2 100644
--- a/indra/llcommon/lltracesampler.cpp
+++ b/indra/llcommon/lltracesampler.cpp
@@ -26,6 +26,8 @@
 #include "linden_common.h"
 
 #include "lltracesampler.h"
+#include "lltrace.h"
+#include "llthread.h"
 
 namespace LLTrace
 {
@@ -34,10 +36,14 @@ namespace LLTrace
 // Sampler
 ///////////////////////////////////////////////////////////////////////
 
-Sampler::Sampler(ThreadTrace* thread_trace) 
+Sampler::Sampler() 
 :	mElapsedSeconds(0),
 	mIsStarted(false),
-	mThreadTrace(thread_trace)
+	mRatesStart(new AccumulatorBuffer<RateAccumulator<F32> >()),
+	mRates(new AccumulatorBuffer<RateAccumulator<F32> >()),
+	mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<F32> >()),
+	mStackTimers(new AccumulatorBuffer<TimerAccumulator>()),
+	mStackTimersStart(new AccumulatorBuffer<TimerAccumulator>())
 {
 }
 
@@ -53,9 +59,9 @@ void Sampler::start()
 
 void Sampler::reset()
 {
-	mF32Stats.reset();
-	mS32Stats.reset();
-	mStackTimers.reset();
+	mRates.write()->reset();
+	mMeasurements.write()->reset();
+	mStackTimers.write()->reset();
 
 	mElapsedSeconds = 0.0;
 	mSamplingTimer.reset();
@@ -66,7 +72,7 @@ void Sampler::resume()
 	if (!mIsStarted)
 	{
 		mSamplingTimer.reset();
-		getThreadTrace()->activate(this);
+		LLTrace::get_thread_trace()->activate(this);
 		mIsStarted = true;
 	}
 }
@@ -76,28 +82,86 @@ void Sampler::stop()
 	if (mIsStarted)
 	{
 		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
-		getThreadTrace()->deactivate(this);
+		LLTrace::get_thread_trace()->deactivate(this);
 		mIsStarted = false;
 	}
 }
 
-ThreadTrace* Sampler::getThreadTrace()
+
+void Sampler::makePrimary()
 {
-	return mThreadTrace;
+	mRates.write()->makePrimary();
+	mMeasurements.write()->makePrimary();
+	mStackTimers.write()->makePrimary();
 }
 
-void Sampler::makePrimary()
+bool Sampler::isPrimary()
+{
+	return mRates->isPrimary();
+}
+
+void Sampler::mergeSamples( const Sampler& other )
+{
+	mRates.write()->mergeSamples(*other.mRates);
+	mMeasurements.write()->mergeSamples(*other.mMeasurements);
+	mStackTimers.write()->mergeSamples(*other.mStackTimers);
+}
+
+void Sampler::initDeltas( const Sampler& other )
+{
+	mRatesStart.write()->copyFrom(*other.mRates);
+	mStackTimersStart.write()->copyFrom(*other.mStackTimers);
+}
+
+
+void Sampler::mergeDeltas( const Sampler& other )
+{
+	mRates.write()->mergeDeltas(*mRatesStart, *other.mRates);
+	mStackTimers.write()->mergeDeltas(*mStackTimersStart, *other.mStackTimers);
+	mMeasurements.write()->mergeSamples(*other.mMeasurements);
+}
+
+
+F32 Sampler::getSum( Rate<F32>& stat )
 {
-	mF32Stats.makePrimary();
-	mS32Stats.makePrimary();
-	mStackTimers.makePrimary();
+	return stat.getAccumulator(mRates).getSum();
 }
 
-void Sampler::mergeFrom( const Sampler* other )
+F32 Sampler::getSum( Measurement<F32>& stat )
 {
-	mF32Stats.mergeFrom(other->mF32Stats);
-	mS32Stats.mergeFrom(other->mS32Stats);
-	mStackTimers.mergeFrom(other->mStackTimers);
+	return stat.getAccumulator(mMeasurements).getSum();
 }
 
+
+F32 Sampler::getPerSec( Rate<F32>& stat )
+{
+	return stat.getAccumulator(mRates).getSum() / mElapsedSeconds;
+}
+
+F32 Sampler::getMin( Measurement<F32>& stat )
+{
+	return stat.getAccumulator(mMeasurements).getMin();
+}
+
+F32 Sampler::getMax( Measurement<F32>& stat )
+{
+	return stat.getAccumulator(mMeasurements).getMax();
+}
+
+F32 Sampler::getMean( Measurement<F32>& stat )
+{
+	return stat.getAccumulator(mMeasurements).getMean();
+}
+
+F32 Sampler::getStandardDeviation( Measurement<F32>& stat )
+{
+	return stat.getAccumulator(mMeasurements).getStandardDeviation();
+}
+
+
+
+
+
+
+
 }
diff --git a/indra/llcommon/lltracesampler.h b/indra/llcommon/lltracesampler.h
index d1ca7fc9bb..e3498fb39f 100644
--- a/indra/llcommon/lltracesampler.h
+++ b/indra/llcommon/lltracesampler.h
@@ -30,61 +30,70 @@
 #include "stdtypes.h"
 #include "llpreprocessor.h"
 
-#include "lltrace.h"
+#include "llpointer.h"
+#include "lltimer.h"
 
 namespace LLTrace
 {
+	template<typename T> class Rate;
+	template<typename T> class Measurement;
+	template<typename T> class AccumulatorBuffer;
+	template<typename T> class RateAccumulator;
+	template<typename T> class MeasurementAccumulator;
+	class TimerAccumulator;
+
 	class LL_COMMON_API Sampler
 	{
 	public:
+		Sampler();
+
 		~Sampler();
 
 		void makePrimary();
+		bool isPrimary();
 
 		void start();
 		void stop();
 		void resume();
 
-		void mergeFrom(const Sampler* other);
+		void mergeSamples(const Sampler& other);
+		void initDeltas(const Sampler& other);
+		void mergeDeltas(const Sampler& other);
 
 		void reset();
 
 		bool isStarted() { return mIsStarted; }
 
-		F32 getSum(Stat<F32>& stat) { return stat.getAccumulator(mF32Stats).getSum(); }
-		F32 getMin(Stat<F32>& stat) { return stat.getAccumulator(mF32Stats).getMin(); }
-		F32 getMax(Stat<F32>& stat) { return stat.getAccumulator(mF32Stats).getMax(); }
-		F32 getMean(Stat<F32>& stat) { return stat.getAccumulator(mF32Stats).getMean(); }
+		F32 getSum(Rate<F32>& stat);
+		F32 getPerSec(Rate<F32>& stat);
 
-		S32 getSum(Stat<S32>& stat) { return stat.getAccumulator(mS32Stats).getSum(); }
-		S32 getMin(Stat<S32>& stat) { return stat.getAccumulator(mS32Stats).getMin(); }
-		S32 getMax(Stat<S32>& stat) { return stat.getAccumulator(mS32Stats).getMax(); }
-		S32 getMean(Stat<S32>& stat) { return stat.getAccumulator(mS32Stats).getMean(); }
+		F32 getSum(Measurement<F32>& stat);
+		F32 getMin(Measurement<F32>& stat);
+		F32 getMax(Measurement<F32>& stat);
+		F32 getMean(Measurement<F32>& stat);
+		F32 getStandardDeviation(Measurement<F32>& stat);
 
 		F64 getSampleTime() { return mElapsedSeconds; }
 
 	private:
 		friend class ThreadTrace;
-		Sampler(class ThreadTrace* thread_trace);
-
-		// no copy
-		Sampler(const Sampler& other) {}
 		// returns data for current thread
 		class ThreadTrace* getThreadTrace(); 
 
-		//TODO: take snapshot at sampler start so we can simplify updates
-		//AccumulatorBuffer<StatAccumulator<F32> >	mF32StatsStart;
-		//AccumulatorBuffer<StatAccumulator<S32> >	mS32StatsStart;
-		//AccumulatorBuffer<TimerAccumulator>			mStackTimersStart;
+		LLCopyOnWritePointer<AccumulatorBuffer<RateAccumulator<F32> > >			mRatesStart;
+		LLCopyOnWritePointer<AccumulatorBuffer<RateAccumulator<F32> > >			mRates;
+		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F32> > >	mMeasurements;
+		LLCopyOnWritePointer<AccumulatorBuffer<TimerAccumulator> >				mStackTimersStart;
+		LLCopyOnWritePointer<AccumulatorBuffer<TimerAccumulator> >				mStackTimers;
 
-		AccumulatorBuffer<StatAccumulator<F32> >	mF32Stats;
-		AccumulatorBuffer<StatAccumulator<S32> >	mS32Stats;
-		AccumulatorBuffer<TimerAccumulator>			mStackTimers;
+		bool			mIsStarted;
+		LLTimer			mSamplingTimer;
+		F64				mElapsedSeconds;
+	};
+
+	class LL_COMMON_API PeriodicSampler
+	{
 
-		bool										mIsStarted;
-		LLTimer										mSamplingTimer;
-		F64											mElapsedSeconds;
-		ThreadTrace*								mThreadTrace;
 	};
 }
 
-- 
cgit v1.2.3


From dbe9742703cf14db85ec3d16c540efc68dce95a6 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 2 Oct 2012 15:37:16 -0700
Subject: SH-3404  create sampler class renamed LLTrace::ThreadTrace to
 LLTrace::ThreadRecorder renamed LLTrace::Sampler to LLTrace::Recording

---
 indra/llcommon/CMakeLists.txt       |   4 +-
 indra/llcommon/llapr.cpp            |  23 -----
 indra/llcommon/llapr.h              |  26 +++++-
 indra/llcommon/llqueuedthread.cpp   |   2 +-
 indra/llcommon/llthread.cpp         |   4 +-
 indra/llcommon/lltrace.cpp          | 143 +++++++++++++++---------------
 indra/llcommon/lltrace.h            |  66 +++++++-------
 indra/llcommon/lltracerecording.cpp | 167 ++++++++++++++++++++++++++++++++++++
 indra/llcommon/lltracerecording.h   | 100 +++++++++++++++++++++
 indra/llcommon/lltracesampler.cpp   | 167 ------------------------------------
 indra/llcommon/lltracesampler.h     | 100 ---------------------
 11 files changed, 397 insertions(+), 405 deletions(-)
 create mode 100644 indra/llcommon/lltracerecording.cpp
 create mode 100644 indra/llcommon/lltracerecording.h
 delete mode 100644 indra/llcommon/lltracesampler.cpp
 delete mode 100644 indra/llcommon/lltracesampler.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index e10dbb3e4d..1ccee23e1e 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -101,7 +101,7 @@ set(llcommon_SOURCE_FILES
     llthreadsafequeue.cpp
     lltimer.cpp
     lltrace.cpp
-    lltracesampler.cpp
+    lltracerecording.cpp
     lluri.cpp
     lluuid.cpp
     llworkerthread.cpp
@@ -244,7 +244,7 @@ set(llcommon_HEADER_FILES
     llthreadsafequeue.h
     lltimer.h
     lltrace.h
-    lltracesampler.h
+    lltracerecording.h
     lltreeiterators.h
     lltypeinfolookup.h
     lluri.h
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index d23b70690d..1db3aa9e89 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -486,29 +486,6 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
 //
 bool LLThreadLocalPointerBase::sInitialized = false;
 
-LLThreadLocalPointerBase::LLThreadLocalPointerBase()
-:	mThreadKey(NULL)
-{
-	if (sInitialized)
-	{
-		initStorage();
-	}
-}
-
-LLThreadLocalPointerBase::LLThreadLocalPointerBase( const LLThreadLocalPointerBase& other)
-:	mThreadKey(NULL)
-{
-	if (sInitialized)
-	{
-		initStorage();
-	}
-}
-
-LLThreadLocalPointerBase::~LLThreadLocalPointerBase()
-{
-	destroyStorage();
-}
-
 void LLThreadLocalPointerBase::set( void* value )
 {
 	llassert(sInitialized && mThreadKey);
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 6efb44a663..821274aeb3 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -261,9 +261,28 @@ public:
 class LLThreadLocalPointerBase : LLInstanceTracker<LLThreadLocalPointerBase>
 {
 public:
-	LLThreadLocalPointerBase();
-	LLThreadLocalPointerBase(const LLThreadLocalPointerBase& other);
-	~LLThreadLocalPointerBase();
+	LLThreadLocalPointerBase()
+	:	mThreadKey(NULL)
+	{
+		if (sInitialized)
+		{
+			initStorage();
+		}
+	}
+
+	LLThreadLocalPointerBase( const LLThreadLocalPointerBase& other)
+		:	mThreadKey(NULL)
+	{
+		if (sInitialized)
+		{
+			initStorage();
+		}
+	}
+
+	~LLThreadLocalPointerBase()
+	{
+		destroyStorage();
+	}
 
 	static void initAllThreadLocalStorage();
 	static void destroyAllThreadLocalStorage();
@@ -312,7 +331,6 @@ class LLThreadLocalPointer : public LLThreadLocalPointerBase
 public:
 
 	LLThreadLocalPointer()
-	:	LLThreadLocalPointerBase()
 	{}
 
 	explicit LLThreadLocalPointer(T* value)
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 9aa449d037..6e2a2b140f 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -112,7 +112,7 @@ void LLQueuedThread::shutdown()
 // virtual
 S32 LLQueuedThread::update(F32 max_time_ms)
 {
-	LLTrace::get_thread_trace()->pushToMaster();
+	LLTrace::get_thread_recorder()->pushToMaster();
 
 	if (!mStarted)
 	{
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index c705e5103b..6723e427f5 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -85,7 +85,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 {
 	LLThread *threadp = (LLThread *)datap;
 
-	LLTrace::ThreadTrace* thread_trace = new LLTrace::SlaveThreadTrace();
+	LLTrace::ThreadRecorder* thread_recorder = new LLTrace::SlaveThreadRecorder();
 
 #if !LL_DARWIN
 	sThreadIndex = threadp->mID;
@@ -99,7 +99,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 	// We're done with the run function, this thread is done executing now.
 	threadp->mStatus = STOPPED;
 
-	delete thread_trace;
+	delete thread_recorder;
 
 	return NULL;
 }
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 04817fd4f4..6b4c3aeb06 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -26,28 +26,28 @@
 #include "linden_common.h"
 
 #include "lltrace.h"
-#include "lltracesampler.h"
+#include "lltracerecording.h"
 
 namespace LLTrace
 {
 
-static MasterThreadTrace* gMasterThreadTrace = NULL;
+static MasterThreadRecorder* gMasterThreadRecorder = NULL;
 
 void init()
 {
-	gMasterThreadTrace = new MasterThreadTrace();
+	gMasterThreadRecorder = new MasterThreadRecorder();
 }
 
 void cleanup()
 {
-	delete gMasterThreadTrace;
-	gMasterThreadTrace = NULL;
+	delete gMasterThreadRecorder;
+	gMasterThreadRecorder = NULL;
 }
 
-LLThreadLocalPointer<ThreadTrace>& get_thread_trace()
+LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
 {
-	static LLThreadLocalPointer<ThreadTrace> s_trace_data;
-	return s_trace_data;
+	static LLThreadLocalPointer<ThreadRecorder> s_thread_recorder;
+	return s_thread_recorder;
 
 }
 
@@ -55,164 +55,161 @@ BlockTimer::Recorder::StackEntry BlockTimer::sCurRecorder;
 
 
 
-MasterThreadTrace& getMasterThreadTrace()
+MasterThreadRecorder& getMasterThreadRecorder()
 {
-	llassert(gMasterThreadTrace != NULL);
-	return *gMasterThreadTrace;
+	llassert(gMasterThreadRecorder != NULL);
+	return *gMasterThreadRecorder;
 }
 
 ///////////////////////////////////////////////////////////////////////
-// MasterThreadTrace
+// ThreadRecorder
 ///////////////////////////////////////////////////////////////////////
 
-ThreadTrace::ThreadTrace()
+ThreadRecorder::ThreadRecorder()
 {
-	get_thread_trace() = this;
-	mPrimarySampler.makePrimary();
-	mTotalSampler.start();
+	get_thread_recorder() = this;
+	mPrimaryRecording.makePrimary();
+	mFullRecording.start();
 }
 
-ThreadTrace::ThreadTrace( const ThreadTrace& other ) 
-:	mPrimarySampler(other.mPrimarySampler),
-	mTotalSampler(other.mTotalSampler)
+ThreadRecorder::ThreadRecorder( const ThreadRecorder& other ) 
+:	mPrimaryRecording(other.mPrimaryRecording),
+	mFullRecording(other.mFullRecording)
 {
-	get_thread_trace() = this;
-	mPrimarySampler.makePrimary();
-	mTotalSampler.start();
+	get_thread_recorder() = this;
+	mPrimaryRecording.makePrimary();
+	mFullRecording.start();
 }
 
-ThreadTrace::~ThreadTrace()
+ThreadRecorder::~ThreadRecorder()
 {
-	get_thread_trace() = NULL;
+	get_thread_recorder() = NULL;
 }
 
-//TODO: remove this and use llviewerstats sampler
-Sampler* ThreadTrace::getPrimarySampler()
+//TODO: remove this and use llviewerstats recording
+Recording* ThreadRecorder::getPrimaryRecording()
 {
-	return &mPrimarySampler;
+	return &mPrimaryRecording;
 }
 
-void ThreadTrace::activate( Sampler* sampler )
+void ThreadRecorder::activate( Recording* recorder )
 {
-	for (std::list<Sampler*>::iterator it = mActiveSamplers.begin(), end_it = mActiveSamplers.end();
+	for (std::list<Recording*>::iterator it = mActiveRecordings.begin(), end_it = mActiveRecordings.end();
 		it != end_it;
 		++it)
 	{
-		(*it)->mMeasurements.write()->mergeSamples(*mPrimarySampler.mMeasurements);
+		(*it)->mMeasurements.write()->mergeSamples(*mPrimaryRecording.mMeasurements);
 	}
-	mPrimarySampler.mMeasurements.write()->reset();
+	mPrimaryRecording.mMeasurements.write()->reset();
 
-	sampler->initDeltas(mPrimarySampler);
+	recorder->initDeltas(mPrimaryRecording);
 
-	mActiveSamplers.push_front(sampler);
+	mActiveRecordings.push_front(recorder);
 }
 
 //TODO: consider merging results down the list to one past the buffered item.
 // this would require 2 buffers per sampler, to separate current total from running total
 
-void ThreadTrace::deactivate( Sampler* sampler )
+void ThreadRecorder::deactivate( Recording* recorder )
 {
-	sampler->mergeDeltas(mPrimarySampler);
+	recorder->mergeDeltas(mPrimaryRecording);
 
 	// TODO: replace with intrusive list
-	std::list<Sampler*>::iterator found_it = std::find(mActiveSamplers.begin(), mActiveSamplers.end(), sampler);
-	if (found_it != mActiveSamplers.end())
+	std::list<Recording*>::iterator found_it = std::find(mActiveRecordings.begin(), mActiveRecordings.end(), recorder);
+	if (found_it != mActiveRecordings.end())
 	{
-		mActiveSamplers.erase(found_it);
+		mActiveRecordings.erase(found_it);
 	}
 }
 
 ///////////////////////////////////////////////////////////////////////
-// SlaveThreadTrace
+// SlaveThreadRecorder
 ///////////////////////////////////////////////////////////////////////
 
-SlaveThreadTrace::SlaveThreadTrace()
-:	ThreadTrace(getMasterThreadTrace())
+SlaveThreadRecorder::SlaveThreadRecorder()
+:	ThreadRecorder(getMasterThreadRecorder())
 {
-	getMasterThreadTrace().addSlaveThread(this);
+	getMasterThreadRecorder().addSlaveThread(this);
 }
 
-SlaveThreadTrace::~SlaveThreadTrace()
+SlaveThreadRecorder::~SlaveThreadRecorder()
 {
-	getMasterThreadTrace().removeSlaveThread(this);
+	getMasterThreadRecorder().removeSlaveThread(this);
 }
 
-void SlaveThreadTrace::pushToMaster()
+void SlaveThreadRecorder::pushToMaster()
 {
-	mTotalSampler.stop();
+	mFullRecording.stop();
 	{
-		LLMutexLock(getMasterThreadTrace().getSlaveListMutex());
-		mSharedData.copyFrom(mTotalSampler);
+		LLMutexLock(getMasterThreadRecorder().getSlaveListMutex());
+		mSharedData.copyFrom(mFullRecording);
 	}
-	mTotalSampler.start();
+	mFullRecording.start();
 }
 
-void SlaveThreadTrace::SharedData::copyFrom( const Sampler& source )
+void SlaveThreadRecorder::SharedData::copyFrom( const Recording& source )
 {
-	LLMutexLock lock(&mSamplerMutex);
-	mSampler.mergeSamples(source);
+	LLMutexLock lock(&mRecorderMutex);
+	mRecorder.mergeSamples(source);
 }
 
-void SlaveThreadTrace::SharedData::copyTo( Sampler& sink )
+void SlaveThreadRecorder::SharedData::copyTo( Recording& sink )
 {
-	LLMutexLock lock(&mSamplerMutex);
-	sink.mergeSamples(mSampler);
+	LLMutexLock lock(&mRecorderMutex);
+	sink.mergeSamples(mRecorder);
 }
 
-
-
-
 ///////////////////////////////////////////////////////////////////////
-// MasterThreadTrace
+// MasterThreadRecorder
 ///////////////////////////////////////////////////////////////////////
 
-void MasterThreadTrace::pullFromSlaveThreads()
+void MasterThreadRecorder::pullFromSlaveThreads()
 {
 	LLMutexLock lock(&mSlaveListMutex);
 
-	for (slave_thread_trace_list_t::iterator it = mSlaveThreadTraces.begin(), end_it = mSlaveThreadTraces.end();
+	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
 		it != end_it;
 		++it)
 	{
-		(*it)->mSlaveTrace->mSharedData.copyTo((*it)->mSamplerStorage);
+		(*it)->mRecorder->mSharedData.copyTo((*it)->mSlaveRecording);
 	}
 }
 
-void MasterThreadTrace::addSlaveThread( class SlaveThreadTrace* child )
+void MasterThreadRecorder::addSlaveThread( class SlaveThreadRecorder* child )
 {
 	LLMutexLock lock(&mSlaveListMutex);
 
-	mSlaveThreadTraces.push_back(new SlaveThreadTraceProxy(child));
+	mSlaveThreadRecorders.push_back(new SlaveThreadRecorderProxy(child));
 }
 
-void MasterThreadTrace::removeSlaveThread( class SlaveThreadTrace* child )
+void MasterThreadRecorder::removeSlaveThread( class SlaveThreadRecorder* child )
 {
 	LLMutexLock lock(&mSlaveListMutex);
 
-	for (slave_thread_trace_list_t::iterator it = mSlaveThreadTraces.begin(), end_it = mSlaveThreadTraces.end();
+	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
 		it != end_it;
 		++it)
 	{
-		if ((*it)->mSlaveTrace == child)
+		if ((*it)->mRecorder == child)
 		{
-			mSlaveThreadTraces.erase(it);
+			mSlaveThreadRecorders.erase(it);
 			break;
 		}
 	}
 }
 
-void MasterThreadTrace::pushToMaster()
+void MasterThreadRecorder::pushToMaster()
 {}
 
-MasterThreadTrace::MasterThreadTrace()
+MasterThreadRecorder::MasterThreadRecorder()
 {}
 
 ///////////////////////////////////////////////////////////////////////
-// MasterThreadTrace::SlaveThreadTraceProxy
+// MasterThreadRecorder::SlaveThreadTraceProxy
 ///////////////////////////////////////////////////////////////////////
 
-MasterThreadTrace::SlaveThreadTraceProxy::SlaveThreadTraceProxy( class SlaveThreadTrace* trace) 
-:	mSlaveTrace(trace)
+MasterThreadRecorder::SlaveThreadRecorderProxy::SlaveThreadRecorderProxy( class SlaveThreadRecorder* recorder) 
+:	mRecorder(recorder)
 {}
 
 }
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 5ec1c821c3..c5356777ae 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -34,7 +34,7 @@
 #include "llmemory.h"
 #include "lltimer.h"
 #include "llrefcount.h"
-#include "lltracesampler.h"
+#include "lltracerecording.h"
 
 #include <list>
 
@@ -45,14 +45,14 @@
 
 namespace LLTrace
 {
-	class Sampler;
+	class Recording;
 
 	void init();
 	void cleanup();
 
-	LLThreadLocalPointer<class ThreadTrace>& get_thread_trace();
+	LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder();
 
-	class LL_COMMON_API MasterThreadTrace& getMasterThreadTrace();
+	class LL_COMMON_API MasterThreadRecorder& getMasterThreadRecorder();
 
 	// one per thread per type
 	template<typename ACCUMULATOR>
@@ -482,33 +482,33 @@ namespace LLTrace
 		static Recorder::StackEntry sCurRecorder;
 	};
 
-	class LL_COMMON_API ThreadTrace
+	class LL_COMMON_API ThreadRecorder
 	{
 	public:
-		ThreadTrace();
-		ThreadTrace(const ThreadTrace& other);
+		ThreadRecorder();
+		ThreadRecorder(const ThreadRecorder& other);
 
-		virtual ~ThreadTrace();
+		virtual ~ThreadRecorder();
 
-		void activate(Sampler* sampler);
-		void deactivate(Sampler* sampler);
+		void activate(Recording* recording);
+		void deactivate(Recording* recording);
 
 		virtual void pushToMaster() = 0;
 
-		Sampler* getPrimarySampler();
+		Recording* getPrimaryRecording();
 	protected:
-		Sampler					mPrimarySampler;
-		Sampler					mTotalSampler;
-		std::list<Sampler*>		mActiveSamplers;
+		Recording					mPrimaryRecording;
+		Recording					mFullRecording;
+		std::list<Recording*>		mActiveRecordings;
 	};
 
-	class LL_COMMON_API MasterThreadTrace : public ThreadTrace
+	class LL_COMMON_API MasterThreadRecorder : public ThreadRecorder
 	{
 	public:
-		MasterThreadTrace();
+		MasterThreadRecorder();
 
-		void addSlaveThread(class SlaveThreadTrace* child);
-		void removeSlaveThread(class SlaveThreadTrace* child);
+		void addSlaveThread(class SlaveThreadRecorder* child);
+		void removeSlaveThread(class SlaveThreadRecorder* child);
 
 		/*virtual */ void pushToMaster();
 
@@ -518,41 +518,41 @@ namespace LLTrace
 		LLMutex* getSlaveListMutex() { return &mSlaveListMutex; }
 
 	private:
-		struct SlaveThreadTraceProxy
+		struct SlaveThreadRecorderProxy
 		{
-			SlaveThreadTraceProxy(class SlaveThreadTrace* trace);
+			SlaveThreadRecorderProxy(class SlaveThreadRecorder* recorder);
 
-			class SlaveThreadTrace*	mSlaveTrace;
-			Sampler					mSamplerStorage;
+			class SlaveThreadRecorder*	mRecorder;
+			Recording					mSlaveRecording;
 		private:
 			//no need to copy these and then have to duplicate the storage
-			SlaveThreadTraceProxy(const SlaveThreadTraceProxy& other) {}
+			SlaveThreadRecorderProxy(const SlaveThreadRecorderProxy& other) {}
 		};
-		typedef std::list<SlaveThreadTraceProxy*> slave_thread_trace_list_t;
+		typedef std::list<SlaveThreadRecorderProxy*> slave_thread_recorder_list_t;
 
-		slave_thread_trace_list_t		mSlaveThreadTraces;
+		slave_thread_recorder_list_t	mSlaveThreadRecorders;
 		LLMutex							mSlaveListMutex;
 	};
 
-	class LL_COMMON_API SlaveThreadTrace : public ThreadTrace
+	class LL_COMMON_API SlaveThreadRecorder : public ThreadRecorder
 	{
 	public:
-		SlaveThreadTrace();
-		~SlaveThreadTrace();
+		SlaveThreadRecorder();
+		~SlaveThreadRecorder();
 
 		// call this periodically to gather stats data for master thread to consume
 		/*virtual*/ void pushToMaster();
 
-		MasterThreadTrace* 	mMaster;
+		MasterThreadRecorder* 	mMaster;
 
 		class SharedData
 		{
 		public:
-			void copyFrom(const Sampler& source);
-			void copyTo(Sampler& sink);
+			void copyFrom(const Recording& source);
+			void copyTo(Recording& sink);
 		private:
-			LLMutex		mSamplerMutex;
-			Sampler		mSampler;
+			LLMutex		mRecorderMutex;
+			Recording	mRecorder;
 		};
 		SharedData		mSharedData;
 	};
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
new file mode 100644
index 0000000000..a792d40f9d
--- /dev/null
+++ b/indra/llcommon/lltracerecording.cpp
@@ -0,0 +1,167 @@
+/** 
+ * @file lltracesampler.cpp
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltracerecording.h"
+#include "lltrace.h"
+#include "llthread.h"
+
+namespace LLTrace
+{
+
+///////////////////////////////////////////////////////////////////////
+// Recording
+///////////////////////////////////////////////////////////////////////
+
+Recording::Recording() 
+:	mElapsedSeconds(0),
+	mIsStarted(false),
+	mRatesStart(new AccumulatorBuffer<RateAccumulator<F32> >()),
+	mRates(new AccumulatorBuffer<RateAccumulator<F32> >()),
+	mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<F32> >()),
+	mStackTimers(new AccumulatorBuffer<TimerAccumulator>()),
+	mStackTimersStart(new AccumulatorBuffer<TimerAccumulator>())
+{
+}
+
+Recording::~Recording()
+{
+}
+
+void Recording::start()
+{
+	reset();
+	resume();
+}
+
+void Recording::reset()
+{
+	mRates.write()->reset();
+	mMeasurements.write()->reset();
+	mStackTimers.write()->reset();
+
+	mElapsedSeconds = 0.0;
+	mSamplingTimer.reset();
+}
+
+void Recording::resume()
+{
+	if (!mIsStarted)
+	{
+		mSamplingTimer.reset();
+		LLTrace::get_thread_recorder()->activate(this);
+		mIsStarted = true;
+	}
+}
+
+void Recording::stop()
+{
+	if (mIsStarted)
+	{
+		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+		LLTrace::get_thread_recorder()->deactivate(this);
+		mIsStarted = false;
+	}
+}
+
+
+void Recording::makePrimary()
+{
+	mRates.write()->makePrimary();
+	mMeasurements.write()->makePrimary();
+	mStackTimers.write()->makePrimary();
+}
+
+bool Recording::isPrimary()
+{
+	return mRates->isPrimary();
+}
+
+void Recording::mergeSamples( const Recording& other )
+{
+	mRates.write()->mergeSamples(*other.mRates);
+	mMeasurements.write()->mergeSamples(*other.mMeasurements);
+	mStackTimers.write()->mergeSamples(*other.mStackTimers);
+}
+
+void Recording::initDeltas( const Recording& other )
+{
+	mRatesStart.write()->copyFrom(*other.mRates);
+	mStackTimersStart.write()->copyFrom(*other.mStackTimers);
+}
+
+
+void Recording::mergeDeltas( const Recording& other )
+{
+	mRates.write()->mergeDeltas(*mRatesStart, *other.mRates);
+	mStackTimers.write()->mergeDeltas(*mStackTimersStart, *other.mStackTimers);
+	mMeasurements.write()->mergeSamples(*other.mMeasurements);
+}
+
+
+F32 Recording::getSum( Rate<F32>& stat )
+{
+	return stat.getAccumulator(mRates).getSum();
+}
+
+F32 Recording::getSum( Measurement<F32>& stat )
+{
+	return stat.getAccumulator(mMeasurements).getSum();
+}
+
+
+F32 Recording::getPerSec( Rate<F32>& stat )
+{
+	return stat.getAccumulator(mRates).getSum() / mElapsedSeconds;
+}
+
+F32 Recording::getMin( Measurement<F32>& stat )
+{
+	return stat.getAccumulator(mMeasurements).getMin();
+}
+
+F32 Recording::getMax( Measurement<F32>& stat )
+{
+	return stat.getAccumulator(mMeasurements).getMax();
+}
+
+F32 Recording::getMean( Measurement<F32>& stat )
+{
+	return stat.getAccumulator(mMeasurements).getMean();
+}
+
+F32 Recording::getStandardDeviation( Measurement<F32>& stat )
+{
+	return stat.getAccumulator(mMeasurements).getStandardDeviation();
+}
+
+
+
+
+
+
+
+}
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
new file mode 100644
index 0000000000..83dc503ea6
--- /dev/null
+++ b/indra/llcommon/lltracerecording.h
@@ -0,0 +1,100 @@
+/** 
+ * @file lltracerecording.h
+ * @brief Sampling object for collecting runtime statistics originating from lltrace.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRACERECORDING_H
+#define LL_LLTRACERECORDING_H
+
+#include "stdtypes.h"
+#include "llpreprocessor.h"
+
+#include "llpointer.h"
+#include "lltimer.h"
+
+namespace LLTrace
+{
+	template<typename T> class Rate;
+	template<typename T> class Measurement;
+	template<typename T> class AccumulatorBuffer;
+	template<typename T> class RateAccumulator;
+	template<typename T> class MeasurementAccumulator;
+	class TimerAccumulator;
+
+	class LL_COMMON_API Recording
+	{
+	public:
+		Recording();
+
+		~Recording();
+
+		void makePrimary();
+		bool isPrimary();
+
+		void start();
+		void stop();
+		void resume();
+
+		void mergeSamples(const Recording& other);
+		void initDeltas(const Recording& other);
+		void mergeDeltas(const Recording& other);
+
+		void reset();
+
+		bool isStarted() { return mIsStarted; }
+
+		F32 getSum(Rate<F32>& stat);
+		F32 getPerSec(Rate<F32>& stat);
+
+		F32 getSum(Measurement<F32>& stat);
+		F32 getMin(Measurement<F32>& stat);
+		F32 getMax(Measurement<F32>& stat);
+		F32 getMean(Measurement<F32>& stat);
+		F32 getStandardDeviation(Measurement<F32>& stat);
+
+		F64 getSampleTime() { return mElapsedSeconds; }
+
+	private:
+		friend class ThreadRecorder;
+		// returns data for current thread
+		class ThreadRecorder* getThreadRecorder(); 
+
+		LLCopyOnWritePointer<AccumulatorBuffer<RateAccumulator<F32> > >			mRatesStart;
+		LLCopyOnWritePointer<AccumulatorBuffer<RateAccumulator<F32> > >			mRates;
+		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F32> > >	mMeasurements;
+		LLCopyOnWritePointer<AccumulatorBuffer<TimerAccumulator> >				mStackTimersStart;
+		LLCopyOnWritePointer<AccumulatorBuffer<TimerAccumulator> >				mStackTimers;
+
+		bool			mIsStarted;
+		LLTimer			mSamplingTimer;
+		F64				mElapsedSeconds;
+	};
+
+	class LL_COMMON_API PeriodicRecording
+	{
+
+	};
+}
+
+#endif // LL_LLTRACERECORDING_H
diff --git a/indra/llcommon/lltracesampler.cpp b/indra/llcommon/lltracesampler.cpp
deleted file mode 100644
index 17e58b96e2..0000000000
--- a/indra/llcommon/lltracesampler.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-/** 
- * @file lltracesampler.cpp
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "lltracesampler.h"
-#include "lltrace.h"
-#include "llthread.h"
-
-namespace LLTrace
-{
-
-///////////////////////////////////////////////////////////////////////
-// Sampler
-///////////////////////////////////////////////////////////////////////
-
-Sampler::Sampler() 
-:	mElapsedSeconds(0),
-	mIsStarted(false),
-	mRatesStart(new AccumulatorBuffer<RateAccumulator<F32> >()),
-	mRates(new AccumulatorBuffer<RateAccumulator<F32> >()),
-	mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<F32> >()),
-	mStackTimers(new AccumulatorBuffer<TimerAccumulator>()),
-	mStackTimersStart(new AccumulatorBuffer<TimerAccumulator>())
-{
-}
-
-Sampler::~Sampler()
-{
-}
-
-void Sampler::start()
-{
-	reset();
-	resume();
-}
-
-void Sampler::reset()
-{
-	mRates.write()->reset();
-	mMeasurements.write()->reset();
-	mStackTimers.write()->reset();
-
-	mElapsedSeconds = 0.0;
-	mSamplingTimer.reset();
-}
-
-void Sampler::resume()
-{
-	if (!mIsStarted)
-	{
-		mSamplingTimer.reset();
-		LLTrace::get_thread_trace()->activate(this);
-		mIsStarted = true;
-	}
-}
-
-void Sampler::stop()
-{
-	if (mIsStarted)
-	{
-		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
-		LLTrace::get_thread_trace()->deactivate(this);
-		mIsStarted = false;
-	}
-}
-
-
-void Sampler::makePrimary()
-{
-	mRates.write()->makePrimary();
-	mMeasurements.write()->makePrimary();
-	mStackTimers.write()->makePrimary();
-}
-
-bool Sampler::isPrimary()
-{
-	return mRates->isPrimary();
-}
-
-void Sampler::mergeSamples( const Sampler& other )
-{
-	mRates.write()->mergeSamples(*other.mRates);
-	mMeasurements.write()->mergeSamples(*other.mMeasurements);
-	mStackTimers.write()->mergeSamples(*other.mStackTimers);
-}
-
-void Sampler::initDeltas( const Sampler& other )
-{
-	mRatesStart.write()->copyFrom(*other.mRates);
-	mStackTimersStart.write()->copyFrom(*other.mStackTimers);
-}
-
-
-void Sampler::mergeDeltas( const Sampler& other )
-{
-	mRates.write()->mergeDeltas(*mRatesStart, *other.mRates);
-	mStackTimers.write()->mergeDeltas(*mStackTimersStart, *other.mStackTimers);
-	mMeasurements.write()->mergeSamples(*other.mMeasurements);
-}
-
-
-F32 Sampler::getSum( Rate<F32>& stat )
-{
-	return stat.getAccumulator(mRates).getSum();
-}
-
-F32 Sampler::getSum( Measurement<F32>& stat )
-{
-	return stat.getAccumulator(mMeasurements).getSum();
-}
-
-
-F32 Sampler::getPerSec( Rate<F32>& stat )
-{
-	return stat.getAccumulator(mRates).getSum() / mElapsedSeconds;
-}
-
-F32 Sampler::getMin( Measurement<F32>& stat )
-{
-	return stat.getAccumulator(mMeasurements).getMin();
-}
-
-F32 Sampler::getMax( Measurement<F32>& stat )
-{
-	return stat.getAccumulator(mMeasurements).getMax();
-}
-
-F32 Sampler::getMean( Measurement<F32>& stat )
-{
-	return stat.getAccumulator(mMeasurements).getMean();
-}
-
-F32 Sampler::getStandardDeviation( Measurement<F32>& stat )
-{
-	return stat.getAccumulator(mMeasurements).getStandardDeviation();
-}
-
-
-
-
-
-
-
-}
diff --git a/indra/llcommon/lltracesampler.h b/indra/llcommon/lltracesampler.h
deleted file mode 100644
index e3498fb39f..0000000000
--- a/indra/llcommon/lltracesampler.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/** 
- * @file lltracesampler.h
- * @brief Sampling object for collecting runtime statistics originating from lltrace.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLTRACESAMPLER_H
-#define LL_LLTRACESAMPLER_H
-
-#include "stdtypes.h"
-#include "llpreprocessor.h"
-
-#include "llpointer.h"
-#include "lltimer.h"
-
-namespace LLTrace
-{
-	template<typename T> class Rate;
-	template<typename T> class Measurement;
-	template<typename T> class AccumulatorBuffer;
-	template<typename T> class RateAccumulator;
-	template<typename T> class MeasurementAccumulator;
-	class TimerAccumulator;
-
-	class LL_COMMON_API Sampler
-	{
-	public:
-		Sampler();
-
-		~Sampler();
-
-		void makePrimary();
-		bool isPrimary();
-
-		void start();
-		void stop();
-		void resume();
-
-		void mergeSamples(const Sampler& other);
-		void initDeltas(const Sampler& other);
-		void mergeDeltas(const Sampler& other);
-
-		void reset();
-
-		bool isStarted() { return mIsStarted; }
-
-		F32 getSum(Rate<F32>& stat);
-		F32 getPerSec(Rate<F32>& stat);
-
-		F32 getSum(Measurement<F32>& stat);
-		F32 getMin(Measurement<F32>& stat);
-		F32 getMax(Measurement<F32>& stat);
-		F32 getMean(Measurement<F32>& stat);
-		F32 getStandardDeviation(Measurement<F32>& stat);
-
-		F64 getSampleTime() { return mElapsedSeconds; }
-
-	private:
-		friend class ThreadTrace;
-		// returns data for current thread
-		class ThreadTrace* getThreadTrace(); 
-
-		LLCopyOnWritePointer<AccumulatorBuffer<RateAccumulator<F32> > >			mRatesStart;
-		LLCopyOnWritePointer<AccumulatorBuffer<RateAccumulator<F32> > >			mRates;
-		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F32> > >	mMeasurements;
-		LLCopyOnWritePointer<AccumulatorBuffer<TimerAccumulator> >				mStackTimersStart;
-		LLCopyOnWritePointer<AccumulatorBuffer<TimerAccumulator> >				mStackTimers;
-
-		bool			mIsStarted;
-		LLTimer			mSamplingTimer;
-		F64				mElapsedSeconds;
-	};
-
-	class LL_COMMON_API PeriodicSampler
-	{
-
-	};
-}
-
-#endif // LL_LLTRACESAMPLER_H
-- 
cgit v1.2.3


From 7196619b4a0823a332e10b7f98464a1649e0dfd2 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 2 Oct 2012 17:14:12 -0700
Subject: SH-3275 WIP Update viewer metrics system to be more flexible
 implemented minimal merging logic made recordings ligher weight by moving
 live tracking data into threadrecorder

---
 indra/llcommon/lltrace.cpp          | 78 ++++++++++++++++++++++++++-----------
 indra/llcommon/lltrace.h            | 14 ++++++-
 indra/llcommon/lltracerecording.cpp | 24 +++---------
 indra/llcommon/lltracerecording.h   |  5 +--
 4 files changed, 75 insertions(+), 46 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 6b4c3aeb06..6d928721de 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -66,18 +66,17 @@ MasterThreadRecorder& getMasterThreadRecorder()
 ///////////////////////////////////////////////////////////////////////
 
 ThreadRecorder::ThreadRecorder()
+:	mPrimaryRecording(NULL)
 {
 	get_thread_recorder() = this;
-	mPrimaryRecording.makePrimary();
 	mFullRecording.start();
 }
 
 ThreadRecorder::ThreadRecorder( const ThreadRecorder& other ) 
-:	mPrimaryRecording(other.mPrimaryRecording),
-	mFullRecording(other.mFullRecording)
+:	mFullRecording(other.mFullRecording),
+	mPrimaryRecording(NULL)
 {
 	get_thread_recorder() = this;
-	mPrimaryRecording.makePrimary();
 	mFullRecording.start();
 }
 
@@ -89,39 +88,74 @@ ThreadRecorder::~ThreadRecorder()
 //TODO: remove this and use llviewerstats recording
 Recording* ThreadRecorder::getPrimaryRecording()
 {
-	return &mPrimaryRecording;
+	return mPrimaryRecording;
 }
 
-void ThreadRecorder::activate( Recording* recorder )
+void ThreadRecorder::activate( Recording* recording )
 {
-	for (std::list<Recording*>::iterator it = mActiveRecordings.begin(), end_it = mActiveRecordings.end();
+	mActiveRecordings.push_front(ActiveRecording(mPrimaryRecording, recording));
+	mActiveRecordings.front().mBaseline.makePrimary();
+	mPrimaryRecording = &mActiveRecordings.front().mBaseline;
+}
+
+//TODO: consider merging results down the list to one past the buffered item.
+// this would require 2 buffers per sampler, to separate current total from running total
+
+void ThreadRecorder::deactivate( Recording* recording )
+{
+	for (std::list<ActiveRecording>::iterator it = mActiveRecordings.begin(), end_it = mActiveRecordings.end();
 		it != end_it;
 		++it)
 	{
-		(*it)->mMeasurements.write()->mergeSamples(*mPrimaryRecording.mMeasurements);
-	}
-	mPrimaryRecording.mMeasurements.write()->reset();
+		std::list<ActiveRecording>::iterator next_it = it;
+		if (++next_it != mActiveRecordings.end())
+		{
+			next_it->mergeMeasurements((*it));
+		}
 
-	recorder->initDeltas(mPrimaryRecording);
+		it->flushAccumulators(mPrimaryRecording);
 
-	mActiveRecordings.push_front(recorder);
+		if (it->mTargetRecording == recording)
+		{
+			if (next_it != mActiveRecordings.end())
+			{
+				next_it->mBaseline.makePrimary();
+				mPrimaryRecording = &next_it->mBaseline;
+			}
+			mActiveRecordings.erase(it);
+			break;
+		}
+	}
 }
 
-//TODO: consider merging results down the list to one past the buffered item.
-// this would require 2 buffers per sampler, to separate current total from running total
-
-void ThreadRecorder::deactivate( Recording* recorder )
+ThreadRecorder::ActiveRecording::ActiveRecording( Recording* source, Recording* target ) 
+:	mTargetRecording(target)
 {
-	recorder->mergeDeltas(mPrimaryRecording);
-
-	// TODO: replace with intrusive list
-	std::list<Recording*>::iterator found_it = std::find(mActiveRecordings.begin(), mActiveRecordings.end(), recorder);
-	if (found_it != mActiveRecordings.end())
+	// take snapshots of current values rates and timers
+	if (source)
 	{
-		mActiveRecordings.erase(found_it);
+		mBaseline.mRates.write()->copyFrom(*source->mRates);
+		mBaseline.mStackTimers.write()->copyFrom(*source->mStackTimers);
 	}
 }
 
+void ThreadRecorder::ActiveRecording::mergeMeasurements(ThreadRecorder::ActiveRecording& other)
+{
+	mBaseline.mMeasurements.write()->mergeSamples(*other.mBaseline.mMeasurements);
+}
+
+void ThreadRecorder::ActiveRecording::flushAccumulators(Recording* current)
+{
+	// accumulate statistics-like measurements
+	mTargetRecording->mMeasurements.write()->mergeSamples(*mBaseline.mMeasurements);
+	// for rate-like measurements, merge total change since baseline
+	mTargetRecording->mRates.write()->mergeDeltas(*mBaseline.mRates, *current->mRates);
+	mTargetRecording->mStackTimers.write()->mergeDeltas(*mBaseline.mStackTimers, *current->mStackTimers);
+	// reset baselines
+	mBaseline.mRates.write()->copyFrom(*current->mRates);
+	mBaseline.mStackTimers.write()->copyFrom(*current->mStackTimers);
+}
+
 ///////////////////////////////////////////////////////////////////////
 // SlaveThreadRecorder
 ///////////////////////////////////////////////////////////////////////
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index c5356777ae..39de79e4c1 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -497,9 +497,19 @@ namespace LLTrace
 
 		Recording* getPrimaryRecording();
 	protected:
-		Recording					mPrimaryRecording;
+		struct ActiveRecording
+		{
+			ActiveRecording(Recording* source, Recording* target);
+
+			Recording*	mTargetRecording;
+			Recording	mBaseline;
+
+			void mergeMeasurements(ActiveRecording& other);
+			void flushAccumulators(Recording* current);
+		};
+		Recording*					mPrimaryRecording;
 		Recording					mFullRecording;
-		std::list<Recording*>		mActiveRecordings;
+		std::list<ActiveRecording>	mActiveRecordings;
 	};
 
 	class LL_COMMON_API MasterThreadRecorder : public ThreadRecorder
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index a792d40f9d..95cdb44e4b 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -39,17 +39,13 @@ namespace LLTrace
 Recording::Recording() 
 :	mElapsedSeconds(0),
 	mIsStarted(false),
-	mRatesStart(new AccumulatorBuffer<RateAccumulator<F32> >()),
 	mRates(new AccumulatorBuffer<RateAccumulator<F32> >()),
 	mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<F32> >()),
-	mStackTimers(new AccumulatorBuffer<TimerAccumulator>()),
-	mStackTimersStart(new AccumulatorBuffer<TimerAccumulator>())
-{
-}
+	mStackTimers(new AccumulatorBuffer<TimerAccumulator>())
+{}
 
 Recording::~Recording()
-{
-}
+{}
 
 void Recording::start()
 {
@@ -107,18 +103,10 @@ void Recording::mergeSamples( const Recording& other )
 	mStackTimers.write()->mergeSamples(*other.mStackTimers);
 }
 
-void Recording::initDeltas( const Recording& other )
+void Recording::mergeDeltas(const Recording& baseline, const Recording& target)
 {
-	mRatesStart.write()->copyFrom(*other.mRates);
-	mStackTimersStart.write()->copyFrom(*other.mStackTimers);
-}
-
-
-void Recording::mergeDeltas( const Recording& other )
-{
-	mRates.write()->mergeDeltas(*mRatesStart, *other.mRates);
-	mStackTimers.write()->mergeDeltas(*mStackTimersStart, *other.mStackTimers);
-	mMeasurements.write()->mergeSamples(*other.mMeasurements);
+	mRates.write()->mergeDeltas(*baseline.mRates, *target.mRates);
+	mStackTimers.write()->mergeDeltas(*baseline.mStackTimers, *target.mStackTimers);
 }
 
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 83dc503ea6..0a54e4cedf 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -57,8 +57,7 @@ namespace LLTrace
 		void resume();
 
 		void mergeSamples(const Recording& other);
-		void initDeltas(const Recording& other);
-		void mergeDeltas(const Recording& other);
+		void mergeDeltas(const Recording& baseline, const Recording& target);
 
 		void reset();
 
@@ -80,10 +79,8 @@ namespace LLTrace
 		// returns data for current thread
 		class ThreadRecorder* getThreadRecorder(); 
 
-		LLCopyOnWritePointer<AccumulatorBuffer<RateAccumulator<F32> > >			mRatesStart;
 		LLCopyOnWritePointer<AccumulatorBuffer<RateAccumulator<F32> > >			mRates;
 		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F32> > >	mMeasurements;
-		LLCopyOnWritePointer<AccumulatorBuffer<TimerAccumulator> >				mStackTimersStart;
 		LLCopyOnWritePointer<AccumulatorBuffer<TimerAccumulator> >				mStackTimers;
 
 		bool			mIsStarted;
-- 
cgit v1.2.3


From 8f5e83789254d19a1a31737b0d7515cd7e967b26 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 3 Oct 2012 19:32:59 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system SH-3403 FIX
 implement unit conversion LLUnit implements unit tracking and conversion
 added support for LLUnit to LLTrace duplicated most llstats into LLTrace
 equivalents

---
 indra/llcommon/CMakeLists.txt     |   1 +
 indra/llcommon/lltrace.h          |  62 +++++++++--
 indra/llcommon/lltracerecording.h |  18 +--
 indra/llcommon/llunit.h           | 226 ++++++++++++++++++++++++++++++++++++++
 4 files changed, 291 insertions(+), 16 deletions(-)
 create mode 100644 indra/llcommon/llunit.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 1ccee23e1e..471558ea01 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -247,6 +247,7 @@ set(llcommon_HEADER_FILES
     lltracerecording.h
     lltreeiterators.h
     lltypeinfolookup.h
+    llunit.h
     lluri.h
     lluuid.h
     lluuidhashmap.h
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 39de79e4c1..6a889f74df 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -35,6 +35,7 @@
 #include "lltimer.h"
 #include "llrefcount.h"
 #include "lltracerecording.h"
+#include "llunit.h"
 
 #include <list>
 
@@ -42,11 +43,8 @@
 #define TOKEN_PASTE(x, y) TOKEN_PASTE_ACTUAL(x, y)
 #define RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder TOKEN_PASTE(block_time_recorder, __COUNTER__)(block_timer);
 
-
 namespace LLTrace
 {
-	class Recording;
-
 	void init();
 	void cleanup();
 
@@ -325,10 +323,10 @@ namespace LLTrace
 		U32	mNumSamples;
 	};
 
-	template <typename T>
+	template <typename T, typename IS_UNIT = void>
 	class LL_COMMON_API Measurement
 	:	public TraceType<MeasurementAccumulator<T> >, 
-		public LLInstanceTracker<Measurement<T>, std::string>
+		public LLInstanceTracker<Measurement<T, IS_UNIT>, std::string>
 	{
 	public:
 		Measurement(const std::string& name) 
@@ -343,13 +341,37 @@ namespace LLTrace
 	};
 
 	template <typename T>
+	class LL_COMMON_API Measurement <T, typename T::is_unit_t>
+	:	public Measurement<typename T::value_t>
+	{
+	public:
+		typedef Measurement<typename T::value_t> base_measurement_t;
+		Measurement(const std::string& name) 
+		:	Measurement<typename T::value_t>(name)
+		{}
+
+		template<typename UNIT_T>
+		void sample(UNIT_T value)
+		{
+			base_measurement_t::sample(value.get());
+		}
+
+		template<typename UNIT_T>
+		typename T::value_t get()
+		{
+			UNIT_T value(*this);
+			return value.get();
+		}
+	};
+
+	template <typename T, typename IS_UNIT = void>
 	class LL_COMMON_API Rate 
-		:	public TraceType<RateAccumulator<T> >, 
+	:	public TraceType<RateAccumulator<T> >, 
 		public LLInstanceTracker<Rate<T>, std::string>
 	{
 	public:
 		Rate(const std::string& name) 
-			:	TraceType(name),
+		:	TraceType(name),
 			LLInstanceTracker(name)
 		{}
 
@@ -359,6 +381,30 @@ namespace LLTrace
 		}
 	};
 
+	template <typename T>
+	class LL_COMMON_API Rate <T, typename T::is_unit_t>
+	:	public Rate<typename T::value_t>
+	{
+	public:
+		Rate(const std::string& name) 
+		:	Rate<typename T::value_t>(name)
+		{}
+
+		template<typename UNIT_T>
+		void add(UNIT_T value)
+		{
+			getPrimaryAccumulator().add(value.get());
+		}
+
+		template<typename UNIT_T>
+		typename T::value_t get()
+		{
+			UNIT_T value(*this);
+			return value.get();
+		}
+
+	};
+
 	class LL_COMMON_API TimerAccumulator
 	{
 	public:
@@ -482,6 +528,8 @@ namespace LLTrace
 		static Recorder::StackEntry sCurRecorder;
 	};
 
+	class Recording;
+
 	class LL_COMMON_API ThreadRecorder
 	{
 	public:
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 0a54e4cedf..4d5793014f 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -35,8 +35,8 @@
 
 namespace LLTrace
 {
-	template<typename T> class Rate;
-	template<typename T> class Measurement;
+	template<typename T, typename IS_UNIT> class Rate;
+	template<typename T, typename IS_UNIT> class Measurement;
 	template<typename T> class AccumulatorBuffer;
 	template<typename T> class RateAccumulator;
 	template<typename T> class MeasurementAccumulator;
@@ -63,14 +63,14 @@ namespace LLTrace
 
 		bool isStarted() { return mIsStarted; }
 
-		F32 getSum(Rate<F32>& stat);
-		F32 getPerSec(Rate<F32>& stat);
+		F32 getSum(Rate<F32, void>& stat);
+		F32 getPerSec(Rate<F32, void>& stat);
 
-		F32 getSum(Measurement<F32>& stat);
-		F32 getMin(Measurement<F32>& stat);
-		F32 getMax(Measurement<F32>& stat);
-		F32 getMean(Measurement<F32>& stat);
-		F32 getStandardDeviation(Measurement<F32>& stat);
+		F32 getSum(Measurement<F32, void>& stat);
+		F32 getMin(Measurement<F32, void>& stat);
+		F32 getMax(Measurement<F32, void>& stat);
+		F32 getMean(Measurement<F32, void>& stat);
+		F32 getStandardDeviation(Measurement<F32, void>& stat);
 
 		F64 getSampleTime() { return mElapsedSeconds; }
 
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
new file mode 100644
index 0000000000..9d78df7cae
--- /dev/null
+++ b/indra/llcommon/llunit.h
@@ -0,0 +1,226 @@
+/** 
+ * @file llunit.h
+ * @brief Unit conversion classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLUNIT_H
+#define LL_LLUNIT_H
+
+#include "stdtypes.h"
+#include "llpreprocessor.h"
+
+template<typename BASE_UNIT, typename DERIVED_UNIT = BASE_UNIT>
+struct LLUnit : public BASE_UNIT
+{
+	typedef LLUnit<BASE_UNIT, DERIVED_UNIT> unit_t;
+	typedef typename BASE_UNIT::value_t value_t;
+	typedef void is_unit_t;
+
+	LLUnit()
+	{}
+
+	explicit LLUnit(value_t value)
+	:	BASE_UNIT(convertToBase(value))
+	{}
+
+	operator value_t() { return get(); }
+
+	value_t get() const
+	{
+		return convertToDerived(mValue);
+	}
+
+	static value_t convertToBase(value_t derived_value)
+	{
+		return (value_t)((F32)derived_value * DERIVED_UNIT::conversionToBaseFactor());
+	}
+
+	static value_t convertToDerived(value_t base_value)
+	{
+		return (value_t)((F32)base_value / DERIVED_UNIT::conversionToBaseFactor());
+	}
+
+};
+
+template<typename T>
+struct LLUnit<T, T>
+{
+	typedef LLUnit<T, T> unit_t;
+	typedef T value_t;
+	typedef void is_unit_t;
+
+	LLUnit()
+	:	mValue()
+	{}
+
+	explicit LLUnit(T value)
+	:	mValue(value)
+	{}
+
+	unit_t& operator=(T value)
+	{
+		setBaseValue(value);
+		return *this;
+	}
+
+	value_t get() { return mValue; }
+
+	static value_t convertToBase(value_t derived_value)
+	{
+		return (value_t)1;
+	}
+
+	static value_t convertToDerived(value_t base_value)
+	{
+		return (value_t)1;
+	}
+
+	unit_t operator + (const unit_t other) const
+	{
+		return unit_t(mValue + other.mValue);
+	}
+
+	void operator += (const unit_t other)
+	{
+		mValue += other.mValue;
+	}
+
+	unit_t operator - (const unit_t other) const
+	{
+		return unit_t(mValue - other.mValue);
+	}
+
+	void operator -= (const unit_t other)
+	{
+		mValue -= other.mValue;
+	}
+
+	unit_t operator * (value_t multiplicand) const
+	{
+		return unit_t(mValue * multiplicand);
+	}
+
+	void operator *= (value_t multiplicand)
+	{
+		mValue *= multiplicand;
+	}
+
+	unit_t operator / (value_t divisor) const
+	{
+		return unit_t(mValue / divisor);
+	}
+
+	void operator /= (value_t divisor)
+	{
+		mValue /= divisor;
+	}
+
+protected:
+	void setBaseValue(T value)
+	{
+		mValue = value;
+	}
+
+	T mValue;
+};
+
+#define LL_DECLARE_BASE_UNIT(unit_name)                 \
+	template<typename STORAGE_TYPE>                     \
+	struct unit_name : public LLUnit<STORAGE_TYPE>      \
+	{                                                   \
+		unit_name(STORAGE_TYPE value)                   \
+		:	LLUnit(value)                               \
+		{}                                              \
+		                                                \
+		unit_name()                                     \
+		{}                                              \
+		                                                \
+		template <typename T>                           \
+		unit_name(const LLUnit<unit_name, T>& other)    \
+		{                                               \
+			setBaseValue(other.unit_name::get());       \
+		}                                               \
+		                                                \
+		using LLUnit<STORAGE_TYPE>::operator +;	        \
+		using LLUnit<STORAGE_TYPE>::operator +=;        \
+		using LLUnit<STORAGE_TYPE>::operator -;         \
+		using LLUnit<STORAGE_TYPE>::operator -=;        \
+		using LLUnit<STORAGE_TYPE>::operator *;         \
+		using LLUnit<STORAGE_TYPE>::operator *=;        \
+		using LLUnit<STORAGE_TYPE>::operator /;         \
+		using LLUnit<STORAGE_TYPE>::operator /=;        \
+	};
+
+#define LL_DECLARE_DERIVED_UNIT(base_unit, derived_unit, conversion_factor)                   \
+	template<typename STORAGE_TYPE>                                                           \
+	struct derived_unit : public LLUnit<base_unit<STORAGE_TYPE>, derived_unit<STORAGE_TYPE> > \
+	{                                                                                         \
+		derived_unit(value_t value)                                                           \
+		:	LLUnit(value)                                                                     \
+		{}                                                                                    \
+		                                                                                      \
+		derived_unit()                                                                        \
+		{}                                                                                    \
+		                                                                                      \
+		template <typename T>                                                                 \
+		derived_unit(const LLUnit<base_unit<STORAGE_TYPE>, T>& other)                         \
+		{                                                                                     \
+			setBaseValue(other.base_unit<STORAGE_TYPE>::get());                               \
+		}                                                                                     \
+		                                                                                      \
+		static F32 conversionToBaseFactor() { return (F32)(conversion_factor); }              \
+		                                                                                      \
+	using LLUnit<STORAGE_TYPE>::operator +;	                                                  \
+	using LLUnit<STORAGE_TYPE>::operator +=;                                                  \
+	using LLUnit<STORAGE_TYPE>::operator -;                                                   \
+	using LLUnit<STORAGE_TYPE>::operator -=;                                                  \
+	using LLUnit<STORAGE_TYPE>::operator *;                                                   \
+	using LLUnit<STORAGE_TYPE>::operator *=;                                                  \
+	using LLUnit<STORAGE_TYPE>::operator /;                                                   \
+	using LLUnit<STORAGE_TYPE>::operator /=;                                                  \
+	};
+
+namespace LLUnits
+{
+	LL_DECLARE_BASE_UNIT(Bytes);
+	LL_DECLARE_DERIVED_UNIT(Bytes, Kilobytes, 1024);
+	LL_DECLARE_DERIVED_UNIT(Bytes, Megabytes, 1024 * 1024);
+	LL_DECLARE_DERIVED_UNIT(Bytes, Gigabytes, 1024 * 1024 * 1024);
+	LL_DECLARE_DERIVED_UNIT(Bytes, Bits,	  (1.f / 8.f));
+	LL_DECLARE_DERIVED_UNIT(Bytes, Kilobit,   (1024 / 8));
+	LL_DECLARE_DERIVED_UNIT(Bytes, Megabits,  (1024 / 8));
+	LL_DECLARE_DERIVED_UNIT(Bytes, Gigabits,  (1024 * 1024 * 1024 / 8));
+
+	LL_DECLARE_BASE_UNIT(Seconds);
+	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.f / 1000.f));
+	LL_DECLARE_DERIVED_UNIT(Seconds, Microseconds,	(1.f / (1000000.f)));
+	LL_DECLARE_DERIVED_UNIT(Seconds, Nanoseconds,	(1.f / (1000000000.f)));
+
+}
+
+#endif // LL_LLUNIT_H
-- 
cgit v1.2.3


From 3960fdf9e01619ddfd7903bcdd8d894f432752d0 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 4 Oct 2012 23:11:57 -0700
Subject: SH-3275 WIP Update viewer metrics system to be more flexible moved
 threadrecorder classes into separate file added Count trace type, which
 tracks value increases and decreases and can report churn as well as overall
 growth rate

---
 indra/llcommon/CMakeLists.txt            |   2 +
 indra/llcommon/lltrace.cpp               | 195 +--------------------------
 indra/llcommon/lltrace.h                 | 143 +++++---------------
 indra/llcommon/lltracerecording.cpp      |  54 ++++++--
 indra/llcommon/lltracerecording.h        |  30 +++--
 indra/llcommon/lltracethreadrecorder.cpp | 219 +++++++++++++++++++++++++++++++
 indra/llcommon/lltracethreadrecorder.h   | 124 +++++++++++++++++
 7 files changed, 450 insertions(+), 317 deletions(-)
 create mode 100644 indra/llcommon/lltracethreadrecorder.cpp
 create mode 100644 indra/llcommon/lltracethreadrecorder.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 471558ea01..c0e9266aa9 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -102,6 +102,7 @@ set(llcommon_SOURCE_FILES
     lltimer.cpp
     lltrace.cpp
     lltracerecording.cpp
+    lltracethreadrecorder.cpp
     lluri.cpp
     lluuid.cpp
     llworkerthread.cpp
@@ -245,6 +246,7 @@ set(llcommon_HEADER_FILES
     lltimer.h
     lltrace.h
     lltracerecording.h
+    lltracethreadrecorder.h
     lltreeiterators.h
     lltypeinfolookup.h
     llunit.h
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 6d928721de..2b1c8d8ce8 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -44,206 +44,19 @@ void cleanup()
 	gMasterThreadRecorder = NULL;
 }
 
-LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
-{
-	static LLThreadLocalPointer<ThreadRecorder> s_thread_recorder;
-	return s_thread_recorder;
-
-}
-
-BlockTimer::Recorder::StackEntry BlockTimer::sCurRecorder;
-
-
-
 MasterThreadRecorder& getMasterThreadRecorder()
 {
 	llassert(gMasterThreadRecorder != NULL);
 	return *gMasterThreadRecorder;
 }
 
-///////////////////////////////////////////////////////////////////////
-// ThreadRecorder
-///////////////////////////////////////////////////////////////////////
-
-ThreadRecorder::ThreadRecorder()
-:	mPrimaryRecording(NULL)
-{
-	get_thread_recorder() = this;
-	mFullRecording.start();
-}
-
-ThreadRecorder::ThreadRecorder( const ThreadRecorder& other ) 
-:	mFullRecording(other.mFullRecording),
-	mPrimaryRecording(NULL)
-{
-	get_thread_recorder() = this;
-	mFullRecording.start();
-}
-
-ThreadRecorder::~ThreadRecorder()
-{
-	get_thread_recorder() = NULL;
-}
-
-//TODO: remove this and use llviewerstats recording
-Recording* ThreadRecorder::getPrimaryRecording()
-{
-	return mPrimaryRecording;
-}
-
-void ThreadRecorder::activate( Recording* recording )
-{
-	mActiveRecordings.push_front(ActiveRecording(mPrimaryRecording, recording));
-	mActiveRecordings.front().mBaseline.makePrimary();
-	mPrimaryRecording = &mActiveRecordings.front().mBaseline;
-}
-
-//TODO: consider merging results down the list to one past the buffered item.
-// this would require 2 buffers per sampler, to separate current total from running total
-
-void ThreadRecorder::deactivate( Recording* recording )
-{
-	for (std::list<ActiveRecording>::iterator it = mActiveRecordings.begin(), end_it = mActiveRecordings.end();
-		it != end_it;
-		++it)
-	{
-		std::list<ActiveRecording>::iterator next_it = it;
-		if (++next_it != mActiveRecordings.end())
-		{
-			next_it->mergeMeasurements((*it));
-		}
-
-		it->flushAccumulators(mPrimaryRecording);
-
-		if (it->mTargetRecording == recording)
-		{
-			if (next_it != mActiveRecordings.end())
-			{
-				next_it->mBaseline.makePrimary();
-				mPrimaryRecording = &next_it->mBaseline;
-			}
-			mActiveRecordings.erase(it);
-			break;
-		}
-	}
-}
-
-ThreadRecorder::ActiveRecording::ActiveRecording( Recording* source, Recording* target ) 
-:	mTargetRecording(target)
-{
-	// take snapshots of current values rates and timers
-	if (source)
-	{
-		mBaseline.mRates.write()->copyFrom(*source->mRates);
-		mBaseline.mStackTimers.write()->copyFrom(*source->mStackTimers);
-	}
-}
-
-void ThreadRecorder::ActiveRecording::mergeMeasurements(ThreadRecorder::ActiveRecording& other)
-{
-	mBaseline.mMeasurements.write()->mergeSamples(*other.mBaseline.mMeasurements);
-}
-
-void ThreadRecorder::ActiveRecording::flushAccumulators(Recording* current)
-{
-	// accumulate statistics-like measurements
-	mTargetRecording->mMeasurements.write()->mergeSamples(*mBaseline.mMeasurements);
-	// for rate-like measurements, merge total change since baseline
-	mTargetRecording->mRates.write()->mergeDeltas(*mBaseline.mRates, *current->mRates);
-	mTargetRecording->mStackTimers.write()->mergeDeltas(*mBaseline.mStackTimers, *current->mStackTimers);
-	// reset baselines
-	mBaseline.mRates.write()->copyFrom(*current->mRates);
-	mBaseline.mStackTimers.write()->copyFrom(*current->mStackTimers);
-}
-
-///////////////////////////////////////////////////////////////////////
-// SlaveThreadRecorder
-///////////////////////////////////////////////////////////////////////
-
-SlaveThreadRecorder::SlaveThreadRecorder()
-:	ThreadRecorder(getMasterThreadRecorder())
-{
-	getMasterThreadRecorder().addSlaveThread(this);
-}
-
-SlaveThreadRecorder::~SlaveThreadRecorder()
-{
-	getMasterThreadRecorder().removeSlaveThread(this);
-}
-
-void SlaveThreadRecorder::pushToMaster()
-{
-	mFullRecording.stop();
-	{
-		LLMutexLock(getMasterThreadRecorder().getSlaveListMutex());
-		mSharedData.copyFrom(mFullRecording);
-	}
-	mFullRecording.start();
-}
-
-void SlaveThreadRecorder::SharedData::copyFrom( const Recording& source )
-{
-	LLMutexLock lock(&mRecorderMutex);
-	mRecorder.mergeSamples(source);
-}
-
-void SlaveThreadRecorder::SharedData::copyTo( Recording& sink )
-{
-	LLMutexLock lock(&mRecorderMutex);
-	sink.mergeSamples(mRecorder);
-}
-
-///////////////////////////////////////////////////////////////////////
-// MasterThreadRecorder
-///////////////////////////////////////////////////////////////////////
-
-void MasterThreadRecorder::pullFromSlaveThreads()
-{
-	LLMutexLock lock(&mSlaveListMutex);
-
-	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
-		it != end_it;
-		++it)
-	{
-		(*it)->mRecorder->mSharedData.copyTo((*it)->mSlaveRecording);
-	}
-}
-
-void MasterThreadRecorder::addSlaveThread( class SlaveThreadRecorder* child )
-{
-	LLMutexLock lock(&mSlaveListMutex);
-
-	mSlaveThreadRecorders.push_back(new SlaveThreadRecorderProxy(child));
-}
-
-void MasterThreadRecorder::removeSlaveThread( class SlaveThreadRecorder* child )
+LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
 {
-	LLMutexLock lock(&mSlaveListMutex);
+	static LLThreadLocalPointer<ThreadRecorder> s_thread_recorder;
+	return s_thread_recorder;
 
-	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
-		it != end_it;
-		++it)
-	{
-		if ((*it)->mRecorder == child)
-		{
-			mSlaveThreadRecorders.erase(it);
-			break;
-		}
-	}
 }
 
-void MasterThreadRecorder::pushToMaster()
-{}
-
-MasterThreadRecorder::MasterThreadRecorder()
-{}
-
-///////////////////////////////////////////////////////////////////////
-// MasterThreadRecorder::SlaveThreadTraceProxy
-///////////////////////////////////////////////////////////////////////
-
-MasterThreadRecorder::SlaveThreadRecorderProxy::SlaveThreadRecorderProxy( class SlaveThreadRecorder* recorder) 
-:	mRecorder(recorder)
-{}
+BlockTimer::Recorder::StackEntry BlockTimer::sCurRecorder;
 
 }
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 6a889f74df..d83ea77363 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -30,11 +30,10 @@
 #include "stdtypes.h"
 #include "llpreprocessor.h"
 
-#include "llmutex.h"
 #include "llmemory.h"
-#include "lltimer.h"
 #include "llrefcount.h"
 #include "lltracerecording.h"
+#include "lltracethreadrecorder.h"
 #include "llunit.h"
 
 #include <list>
@@ -171,7 +170,7 @@ namespace LLTrace
 	template<typename ACCUMULATOR> LLThreadLocalPointer<ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>::sPrimaryStorage;
 
 	template<typename ACCUMULATOR>
-	class LL_COMMON_API TraceType
+	class LL_COMMON_API TraceType 
 	{
 	public:
 		TraceType(const std::string& name)
@@ -186,6 +185,7 @@ namespace LLTrace
 		}
 
 		ACCUMULATOR& getAccumulator(AccumulatorBuffer<ACCUMULATOR>* buffer) { return (*buffer)[mAccumulatorIndex]; }
+		const ACCUMULATOR& getAccumulator(AccumulatorBuffer<ACCUMULATOR>* buffer) const { return (*buffer)[mAccumulatorIndex]; }
 
 	protected:
 		std::string	mName;
@@ -265,11 +265,11 @@ namespace LLTrace
 			mMax = 0;
 		}
 
-		T	getSum() { return mSum; }
-		T	getMin() { return mMin; }
-		T	getMax() { return mMax; }
-		F32	getMean() { return mMean; }
-		F32 getStandardDeviation() { return mStandardDeviation; }
+		T	getSum() const { return mSum; }
+		T	getMin() const { return mMin; }
+		T	getMax() const { return mMax; }
+		F32	getMean() const { return mMean; }
+		F32 getStandardDeviation() const { return mStandardDeviation; }
 
 	private:
 		T	mSum,
@@ -315,7 +315,7 @@ namespace LLTrace
 			mSum = 0;
 		}
 
-		T	getSum() { return mSum; }
+		T	getSum() const { return mSum; }
 
 	private:
 		T	mSum;
@@ -355,13 +355,6 @@ namespace LLTrace
 		{
 			base_measurement_t::sample(value.get());
 		}
-
-		template<typename UNIT_T>
-		typename T::value_t get()
-		{
-			UNIT_T value(*this);
-			return value.get();
-		}
 	};
 
 	template <typename T, typename IS_UNIT = void>
@@ -395,14 +388,35 @@ namespace LLTrace
 		{
 			getPrimaryAccumulator().add(value.get());
 		}
+	};
 
-		template<typename UNIT_T>
-		typename T::value_t get()
+	template <typename T>
+	class LL_COMMON_API Count 
+	{
+	public:
+		Count(const std::string& name) 
+		:	mIncrease(name + "_increase"),
+			mDecrease(name + "_decrease"),
+			mTotal(name)
+		{}
+
+		void count(T value)
 		{
-			UNIT_T value(*this);
-			return value.get();
+			if (value < 0)
+			{
+				mDecrease.add(value * -1);
+			}
+			else
+			{
+				mIncrease.add(value);
+			}
+			mTotal.add(value);
 		}
-
+	private:
+		friend class LLTrace::Recording;
+		Rate<T> mIncrease;
+		Rate<T> mDecrease;
+		Rate<T> mTotal;
 	};
 
 	class LL_COMMON_API TimerAccumulator
@@ -527,93 +541,6 @@ namespace LLTrace
 
 		static Recorder::StackEntry sCurRecorder;
 	};
-
-	class Recording;
-
-	class LL_COMMON_API ThreadRecorder
-	{
-	public:
-		ThreadRecorder();
-		ThreadRecorder(const ThreadRecorder& other);
-
-		virtual ~ThreadRecorder();
-
-		void activate(Recording* recording);
-		void deactivate(Recording* recording);
-
-		virtual void pushToMaster() = 0;
-
-		Recording* getPrimaryRecording();
-	protected:
-		struct ActiveRecording
-		{
-			ActiveRecording(Recording* source, Recording* target);
-
-			Recording*	mTargetRecording;
-			Recording	mBaseline;
-
-			void mergeMeasurements(ActiveRecording& other);
-			void flushAccumulators(Recording* current);
-		};
-		Recording*					mPrimaryRecording;
-		Recording					mFullRecording;
-		std::list<ActiveRecording>	mActiveRecordings;
-	};
-
-	class LL_COMMON_API MasterThreadRecorder : public ThreadRecorder
-	{
-	public:
-		MasterThreadRecorder();
-
-		void addSlaveThread(class SlaveThreadRecorder* child);
-		void removeSlaveThread(class SlaveThreadRecorder* child);
-
-		/*virtual */ void pushToMaster();
-
-		// call this periodically to gather stats data from slave threads
-		void pullFromSlaveThreads();
-
-		LLMutex* getSlaveListMutex() { return &mSlaveListMutex; }
-
-	private:
-		struct SlaveThreadRecorderProxy
-		{
-			SlaveThreadRecorderProxy(class SlaveThreadRecorder* recorder);
-
-			class SlaveThreadRecorder*	mRecorder;
-			Recording					mSlaveRecording;
-		private:
-			//no need to copy these and then have to duplicate the storage
-			SlaveThreadRecorderProxy(const SlaveThreadRecorderProxy& other) {}
-		};
-		typedef std::list<SlaveThreadRecorderProxy*> slave_thread_recorder_list_t;
-
-		slave_thread_recorder_list_t	mSlaveThreadRecorders;
-		LLMutex							mSlaveListMutex;
-	};
-
-	class LL_COMMON_API SlaveThreadRecorder : public ThreadRecorder
-	{
-	public:
-		SlaveThreadRecorder();
-		~SlaveThreadRecorder();
-
-		// call this periodically to gather stats data for master thread to consume
-		/*virtual*/ void pushToMaster();
-
-		MasterThreadRecorder* 	mMaster;
-
-		class SharedData
-		{
-		public:
-			void copyFrom(const Recording& source);
-			void copyTo(Recording& sink);
-		private:
-			LLMutex		mRecorderMutex;
-			Recording	mRecorder;
-		};
-		SharedData		mSharedData;
-	};
 }
 
 #endif // LL_LLTRACE_H
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 95cdb44e4b..e4cff551f9 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -110,46 +110,80 @@ void Recording::mergeDeltas(const Recording& baseline, const Recording& target)
 }
 
 
-F32 Recording::getSum( Rate<F32>& stat )
+F32 Recording::getSum(const Rate<F32>& stat)
 {
 	return stat.getAccumulator(mRates).getSum();
 }
 
-F32 Recording::getSum( Measurement<F32>& stat )
+F32 Recording::getPerSec(const Rate<F32>& stat)
 {
-	return stat.getAccumulator(mMeasurements).getSum();
+	return stat.getAccumulator(mRates).getSum() / mElapsedSeconds;
 }
 
-
-F32 Recording::getPerSec( Rate<F32>& stat )
+F32 Recording::getSum(const Measurement<F32>& stat)
 {
-	return stat.getAccumulator(mRates).getSum() / mElapsedSeconds;
+	return stat.getAccumulator(mMeasurements).getSum();
 }
 
-F32 Recording::getMin( Measurement<F32>& stat )
+F32 Recording::getMin(const Measurement<F32>& stat)
 {
 	return stat.getAccumulator(mMeasurements).getMin();
 }
 
-F32 Recording::getMax( Measurement<F32>& stat )
+F32 Recording::getMax(const Measurement<F32>& stat)
 {
 	return stat.getAccumulator(mMeasurements).getMax();
 }
 
-F32 Recording::getMean( Measurement<F32>& stat )
+F32 Recording::getMean(const Measurement<F32>& stat)
 {
 	return stat.getAccumulator(mMeasurements).getMean();
 }
 
-F32 Recording::getStandardDeviation( Measurement<F32>& stat )
+F32 Recording::getStandardDeviation(const Measurement<F32>& stat)
 {
 	return stat.getAccumulator(mMeasurements).getStandardDeviation();
 }
 
+F32 Recording::getSum(const Count<F32>& stat)
+{
+	return getSum(stat.mTotal);
+}
+
+F32 Recording::getPerSec(const Count<F32>& stat)
+{
+	return getPerSec(stat.mTotal);
+}
+
+F32 Recording::getIncrease(const Count<F32>& stat)
+{
+	return getSum(stat.mIncrease);
+}
+
+F32 Recording::getIncreasePerSec(const Count<F32>& stat)
+{
+	return getPerSec(stat.mIncrease);
+}
 
+F32 Recording::getDecrease(const Count<F32>& stat)
+{
+	return getSum(stat.mDecrease);
+}
 
+F32 Recording::getDecreasePerSec(const Count<F32>& stat)
+{
+	return getPerSec(stat.mDecrease);
+}
 
+F32 Recording::getChurn(const Count<F32>& stat)
+{
+	return getIncrease(stat) + getDecrease(stat);
+}
 
+F32 Recording::getChurnPerSec(const Count<F32>& stat)
+{
+	return getIncreasePerSec(stat) + getDecreasePerSec(stat);
+}
 
 
 }
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 4d5793014f..f9bc6b61b2 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -37,6 +37,7 @@ namespace LLTrace
 {
 	template<typename T, typename IS_UNIT> class Rate;
 	template<typename T, typename IS_UNIT> class Measurement;
+	template<typename T> class Count;
 	template<typename T> class AccumulatorBuffer;
 	template<typename T> class RateAccumulator;
 	template<typename T> class MeasurementAccumulator;
@@ -63,14 +64,27 @@ namespace LLTrace
 
 		bool isStarted() { return mIsStarted; }
 
-		F32 getSum(Rate<F32, void>& stat);
-		F32 getPerSec(Rate<F32, void>& stat);
-
-		F32 getSum(Measurement<F32, void>& stat);
-		F32 getMin(Measurement<F32, void>& stat);
-		F32 getMax(Measurement<F32, void>& stat);
-		F32 getMean(Measurement<F32, void>& stat);
-		F32 getStandardDeviation(Measurement<F32, void>& stat);
+		// Rate accessors
+		F32 getSum(const Rate<F32, void>& stat);
+		F32 getPerSec(const Rate<F32, void>& stat);
+
+		// Measurement accessors
+		F32 getSum(const Measurement<F32, void>& stat);
+		F32 getPerSec(const Measurement<F32, void>& stat);
+		F32 getMin(const Measurement<F32, void>& stat);
+		F32 getMax(const Measurement<F32, void>& stat);
+		F32 getMean(const Measurement<F32, void>& stat);
+		F32 getStandardDeviation(const Measurement<F32, void>& stat);
+
+		// Count accessors
+		F32 getSum(const Count<F32>& stat);
+		F32 getPerSec(const Count<F32>& stat);
+		F32 getIncrease(const Count<F32>& stat);
+		F32 getIncreasePerSec(const Count<F32>& stat);
+		F32 getDecrease(const Count<F32>& stat);
+		F32 getDecreasePerSec(const Count<F32>& stat);
+		F32 getChurn(const Count<F32>& stat);
+		F32 getChurnPerSec(const Count<F32>& stat);
 
 		F64 getSampleTime() { return mElapsedSeconds; }
 
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
new file mode 100644
index 0000000000..9115a52fd1
--- /dev/null
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -0,0 +1,219 @@
+/** 
+ * @file lltracethreadrecorder.cpp
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltrace.h"
+
+namespace LLTrace
+{
+
+
+///////////////////////////////////////////////////////////////////////
+// ThreadRecorder
+///////////////////////////////////////////////////////////////////////
+
+ThreadRecorder::ThreadRecorder()
+:	mPrimaryRecording(NULL)
+{
+	get_thread_recorder() = this;
+	mFullRecording.start();
+}
+
+ThreadRecorder::ThreadRecorder( const ThreadRecorder& other ) 
+:	mFullRecording(other.mFullRecording),
+	mPrimaryRecording(NULL)
+{
+	get_thread_recorder() = this;
+	mFullRecording.start();
+}
+
+ThreadRecorder::~ThreadRecorder()
+{
+	get_thread_recorder() = NULL;
+}
+
+//TODO: remove this and use llviewerstats recording
+Recording* ThreadRecorder::getPrimaryRecording()
+{
+	return mPrimaryRecording;
+}
+
+void ThreadRecorder::activate( Recording* recording )
+{
+	mActiveRecordings.push_front(ActiveRecording(mPrimaryRecording, recording));
+	mActiveRecordings.front().mBaseline.makePrimary();
+	mPrimaryRecording = &mActiveRecordings.front().mBaseline;
+}
+
+//TODO: consider merging results down the list to one past the buffered item.
+// this would require 2 buffers per sampler, to separate current total from running total
+
+void ThreadRecorder::deactivate( Recording* recording )
+{
+	for (std::list<ActiveRecording>::iterator it = mActiveRecordings.begin(), end_it = mActiveRecordings.end();
+		it != end_it;
+		++it)
+	{
+		std::list<ActiveRecording>::iterator next_it = it;
+		if (++next_it != mActiveRecordings.end())
+		{
+			next_it->mergeMeasurements((*it));
+		}
+
+		it->flushAccumulators(mPrimaryRecording);
+
+		if (it->mTargetRecording == recording)
+		{
+			if (next_it != mActiveRecordings.end())
+			{
+				next_it->mBaseline.makePrimary();
+				mPrimaryRecording = &next_it->mBaseline;
+			}
+			mActiveRecordings.erase(it);
+			break;
+		}
+	}
+}
+
+ThreadRecorder::ActiveRecording::ActiveRecording( Recording* source, Recording* target ) 
+:	mTargetRecording(target)
+{
+	// take snapshots of current values rates and timers
+	if (source)
+	{
+		mBaseline.mRates.write()->copyFrom(*source->mRates);
+		mBaseline.mStackTimers.write()->copyFrom(*source->mStackTimers);
+	}
+}
+
+void ThreadRecorder::ActiveRecording::mergeMeasurements(ThreadRecorder::ActiveRecording& other)
+{
+	mBaseline.mMeasurements.write()->mergeSamples(*other.mBaseline.mMeasurements);
+}
+
+void ThreadRecorder::ActiveRecording::flushAccumulators(Recording* current)
+{
+	// accumulate statistics-like measurements
+	mTargetRecording->mMeasurements.write()->mergeSamples(*mBaseline.mMeasurements);
+	// for rate-like measurements, merge total change since baseline
+	mTargetRecording->mRates.write()->mergeDeltas(*mBaseline.mRates, *current->mRates);
+	mTargetRecording->mStackTimers.write()->mergeDeltas(*mBaseline.mStackTimers, *current->mStackTimers);
+	// reset baselines
+	mBaseline.mRates.write()->copyFrom(*current->mRates);
+	mBaseline.mStackTimers.write()->copyFrom(*current->mStackTimers);
+}
+
+///////////////////////////////////////////////////////////////////////
+// SlaveThreadRecorder
+///////////////////////////////////////////////////////////////////////
+
+SlaveThreadRecorder::SlaveThreadRecorder()
+:	ThreadRecorder(getMasterThreadRecorder())
+{
+	getMasterThreadRecorder().addSlaveThread(this);
+}
+
+SlaveThreadRecorder::~SlaveThreadRecorder()
+{
+	getMasterThreadRecorder().removeSlaveThread(this);
+}
+
+void SlaveThreadRecorder::pushToMaster()
+{
+	mFullRecording.stop();
+	{
+		LLMutexLock(getMasterThreadRecorder().getSlaveListMutex());
+		mSharedData.copyFrom(mFullRecording);
+	}
+	mFullRecording.start();
+}
+
+void SlaveThreadRecorder::SharedData::copyFrom( const Recording& source )
+{
+	LLMutexLock lock(&mRecorderMutex);
+	mRecorder.mergeSamples(source);
+}
+
+void SlaveThreadRecorder::SharedData::copyTo( Recording& sink )
+{
+	LLMutexLock lock(&mRecorderMutex);
+	sink.mergeSamples(mRecorder);
+}
+
+///////////////////////////////////////////////////////////////////////
+// MasterThreadRecorder
+///////////////////////////////////////////////////////////////////////
+
+void MasterThreadRecorder::pullFromSlaveThreads()
+{
+	LLMutexLock lock(&mSlaveListMutex);
+
+	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
+		it != end_it;
+		++it)
+	{
+		(*it)->mRecorder->mSharedData.copyTo((*it)->mSlaveRecording);
+	}
+}
+
+void MasterThreadRecorder::addSlaveThread( class SlaveThreadRecorder* child )
+{
+	LLMutexLock lock(&mSlaveListMutex);
+
+	mSlaveThreadRecorders.push_back(new SlaveThreadRecorderProxy(child));
+}
+
+void MasterThreadRecorder::removeSlaveThread( class SlaveThreadRecorder* child )
+{
+	LLMutexLock lock(&mSlaveListMutex);
+
+	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
+		it != end_it;
+		++it)
+	{
+		if ((*it)->mRecorder == child)
+		{
+			mSlaveThreadRecorders.erase(it);
+			break;
+		}
+	}
+}
+
+void MasterThreadRecorder::pushToMaster()
+{}
+
+MasterThreadRecorder::MasterThreadRecorder()
+{}
+
+///////////////////////////////////////////////////////////////////////
+// MasterThreadRecorder::SlaveThreadTraceProxy
+///////////////////////////////////////////////////////////////////////
+
+MasterThreadRecorder::SlaveThreadRecorderProxy::SlaveThreadRecorderProxy( class SlaveThreadRecorder* recorder) 
+:	mRecorder(recorder)
+{}
+
+}
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
new file mode 100644
index 0000000000..40441d0447
--- /dev/null
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -0,0 +1,124 @@
+/** 
+ * @file lltrace.h
+ * @brief Runtime statistics accumulation.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRACETHREADRECORDER_H
+#define LL_LLTRACETHREADRECORDER_H
+
+#include "stdtypes.h"
+#include "llpreprocessor.h"
+
+#include "llmutex.h"
+#include "lltracerecording.h"
+
+namespace LLTrace
+{
+	class LL_COMMON_API ThreadRecorder
+	{
+	public:
+		ThreadRecorder();
+		ThreadRecorder(const ThreadRecorder& other);
+
+		virtual ~ThreadRecorder();
+
+		void activate(Recording* recording);
+		void deactivate(Recording* recording);
+
+		virtual void pushToMaster() = 0;
+
+		Recording* getPrimaryRecording();
+	protected:
+		struct ActiveRecording
+		{
+			ActiveRecording(Recording* source, Recording* target);
+
+			Recording*	mTargetRecording;
+			Recording	mBaseline;
+
+			void mergeMeasurements(ActiveRecording& other);
+			void flushAccumulators(Recording* current);
+		};
+		Recording*					mPrimaryRecording;
+		Recording					mFullRecording;
+		std::list<ActiveRecording>	mActiveRecordings;
+	};
+
+	class LL_COMMON_API MasterThreadRecorder : public ThreadRecorder
+	{
+	public:
+		MasterThreadRecorder();
+
+		void addSlaveThread(class SlaveThreadRecorder* child);
+		void removeSlaveThread(class SlaveThreadRecorder* child);
+
+		/*virtual */ void pushToMaster();
+
+		// call this periodically to gather stats data from slave threads
+		void pullFromSlaveThreads();
+
+		LLMutex* getSlaveListMutex() { return &mSlaveListMutex; }
+
+	private:
+		struct SlaveThreadRecorderProxy
+		{
+			SlaveThreadRecorderProxy(class SlaveThreadRecorder* recorder);
+
+			class SlaveThreadRecorder*	mRecorder;
+			Recording					mSlaveRecording;
+		private:
+			//no need to copy these and then have to duplicate the storage
+			SlaveThreadRecorderProxy(const SlaveThreadRecorderProxy& other) {}
+		};
+		typedef std::list<SlaveThreadRecorderProxy*> slave_thread_recorder_list_t;
+
+		slave_thread_recorder_list_t	mSlaveThreadRecorders;
+		LLMutex							mSlaveListMutex;
+	};
+
+	class LL_COMMON_API SlaveThreadRecorder : public ThreadRecorder
+	{
+	public:
+		SlaveThreadRecorder();
+		~SlaveThreadRecorder();
+
+		// call this periodically to gather stats data for master thread to consume
+		/*virtual*/ void pushToMaster();
+
+		MasterThreadRecorder* 	mMaster;
+
+		class SharedData
+		{
+		public:
+			void copyFrom(const Recording& source);
+			void copyTo(Recording& sink);
+		private:
+			LLMutex		mRecorderMutex;
+			Recording	mRecorder;
+		};
+		SharedData		mSharedData;
+	};
+}
+
+#endif // LL_LLTRACETHREADRECORDER_H
-- 
cgit v1.2.3


From 4dce574a8d604a501ec3c12eef3f5d03ee188473 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 5 Oct 2012 10:51:38 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system added update()
 method to trace recorders to allow mid-collection snapshots

---
 indra/llcommon/lltracerecording.cpp      |  6 ++++++
 indra/llcommon/lltracerecording.h        |  1 +
 indra/llcommon/lltracethreadrecorder.cpp | 19 +++++++++++++------
 indra/llcommon/lltracethreadrecorder.h   |  3 +++
 4 files changed, 23 insertions(+), 6 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index e4cff551f9..c44cc8a8a7 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -63,6 +63,12 @@ void Recording::reset()
 	mSamplingTimer.reset();
 }
 
+void Recording::update()
+{
+	mElapsedSeconds = 0.0;
+	mSamplingTimer.reset();
+}
+
 void Recording::resume()
 {
 	if (!mIsStarted)
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index f9bc6b61b2..4d53cd9600 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -61,6 +61,7 @@ namespace LLTrace
 		void mergeDeltas(const Recording& baseline, const Recording& target);
 
 		void reset();
+		void update();
 
 		bool isStarted() { return mIsStarted; }
 
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 9115a52fd1..b2c6fe3b80 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -68,10 +68,7 @@ void ThreadRecorder::activate( Recording* recording )
 	mPrimaryRecording = &mActiveRecordings.front().mBaseline;
 }
 
-//TODO: consider merging results down the list to one past the buffered item.
-// this would require 2 buffers per sampler, to separate current total from running total
-
-void ThreadRecorder::deactivate( Recording* recording )
+std::list<ThreadRecorder::ActiveRecording>::iterator ThreadRecorder::update( Recording* recording )
 {
 	for (std::list<ActiveRecording>::iterator it = mActiveRecordings.begin(), end_it = mActiveRecordings.end();
 		it != end_it;
@@ -92,10 +89,20 @@ void ThreadRecorder::deactivate( Recording* recording )
 				next_it->mBaseline.makePrimary();
 				mPrimaryRecording = &next_it->mBaseline;
 			}
-			mActiveRecordings.erase(it);
-			break;
+			return it;
 		}
 	}
+
+	return mActiveRecordings.end();
+}
+
+void ThreadRecorder::deactivate( Recording* recording )
+{
+	std::list<ActiveRecording>::iterator it = update(recording);
+	if (it != mActiveRecordings.end())
+	{
+		mActiveRecordings.erase(it);
+	}
 }
 
 ThreadRecorder::ActiveRecording::ActiveRecording( Recording* source, Recording* target ) 
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 40441d0447..42230087c0 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -37,6 +37,8 @@ namespace LLTrace
 {
 	class LL_COMMON_API ThreadRecorder
 	{
+	protected:
+		struct ActiveRecording;
 	public:
 		ThreadRecorder();
 		ThreadRecorder(const ThreadRecorder& other);
@@ -44,6 +46,7 @@ namespace LLTrace
 		virtual ~ThreadRecorder();
 
 		void activate(Recording* recording);
+		std::list<struct ActiveRecording>::iterator update(Recording* recording);
 		void deactivate(Recording* recording);
 
 		virtual void pushToMaster() = 0;
-- 
cgit v1.2.3


From 960f8764ad2407add941bc8650b295f1e77beb19 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 5 Oct 2012 11:44:36 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system added update()
 method to trace recorders to allow mid-collection snapshots

---
 indra/llcommon/lltracerecording.cpp | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index c44cc8a8a7..f0b17ef100 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -65,8 +65,12 @@ void Recording::reset()
 
 void Recording::update()
 {
-	mElapsedSeconds = 0.0;
-	mSamplingTimer.reset();
+	if (mIsStarted)
+	{
+		LLTrace::get_thread_recorder()->update(this);
+		mElapsedSeconds = 0.0;
+		mSamplingTimer.reset();
+	}
 }
 
 void Recording::resume()
-- 
cgit v1.2.3


From aff9654c1115b4a74fc3ee8f9ca2c2ffa07f8d73 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 9 Oct 2012 18:02:47 -0700
Subject: SH-3275 WIP Update viewer metrics system to be more flexible added
 PeriodicRecorder class for frame by frame stats accumulation

---
 indra/llcommon/lltrace.h            |   4 +-
 indra/llcommon/lltracerecording.cpp |  35 ++---
 indra/llcommon/lltracerecording.h   | 247 ++++++++++++++++++++++++++++++++++--
 indra/llcommon/llunit.h             |  12 +-
 4 files changed, 261 insertions(+), 37 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index d83ea77363..e655a3582e 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -353,7 +353,7 @@ namespace LLTrace
 		template<typename UNIT_T>
 		void sample(UNIT_T value)
 		{
-			base_measurement_t::sample(value.get());
+			base_measurement_t::sample(value.value());
 		}
 	};
 
@@ -386,7 +386,7 @@ namespace LLTrace
 		template<typename UNIT_T>
 		void add(UNIT_T value)
 		{
-			getPrimaryAccumulator().add(value.get());
+			getPrimaryAccumulator().add(value.value());
 		}
 	};
 
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index e4cff551f9..7cd6280f03 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -38,7 +38,6 @@ namespace LLTrace
 
 Recording::Recording() 
 :	mElapsedSeconds(0),
-	mIsStarted(false),
 	mRates(new AccumulatorBuffer<RateAccumulator<F32> >()),
 	mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<F32> >()),
 	mStackTimers(new AccumulatorBuffer<TimerAccumulator>())
@@ -47,13 +46,7 @@ Recording::Recording()
 Recording::~Recording()
 {}
 
-void Recording::start()
-{
-	reset();
-	resume();
-}
-
-void Recording::reset()
+void Recording::handleReset()
 {
 	mRates.write()->reset();
 	mMeasurements.write()->reset();
@@ -63,24 +56,22 @@ void Recording::reset()
 	mSamplingTimer.reset();
 }
 
-void Recording::resume()
+void Recording::handleStart()
+{
+	mSamplingTimer.reset();
+	LLTrace::get_thread_recorder()->activate(this);
+}
+
+void Recording::handleStop()
 {
-	if (!mIsStarted)
-	{
-		mSamplingTimer.reset();
-		LLTrace::get_thread_recorder()->activate(this);
-		mIsStarted = true;
-	}
+	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+	LLTrace::get_thread_recorder()->deactivate(this);
 }
 
-void Recording::stop()
+void Recording::handleSplitTo(Recording& other)
 {
-	if (mIsStarted)
-	{
-		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
-		LLTrace::get_thread_recorder()->deactivate(this);
-		mIsStarted = false;
-	}
+	stop();
+	other.restart();
 }
 
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index f9bc6b61b2..080007ba00 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -33,6 +33,147 @@
 #include "llpointer.h"
 #include "lltimer.h"
 
+template<typename DERIVED>
+class LL_COMMON_API LLVCRControlsMixinInterface
+{
+public:
+	virtual ~LLVCRControlsMixinInterface() {}
+	// trigger data accumulation (without reset)
+	virtual void handleStart() = 0;
+	// stop data accumulation, should put object in queryable state
+	virtual void handleStop() = 0;
+	// clear accumulated values, can be called while started
+	virtual void handleReset() = 0;
+	// atomically stop this object while starting the other
+	// no data can be missed in between stop and start
+	virtual void handleSplitTo(DERIVED& other) = 0;
+};
+
+template<typename DERIVED>
+class LL_COMMON_API LLVCRControlsMixin
+:	private LLVCRControlsMixinInterface<DERIVED>
+{
+public:
+	enum EPlayState
+	{
+		STOPPED,
+		PAUSED,
+		STARTED
+	};
+
+	void start()
+	{
+		switch (mPlayState)
+		{
+		case STOPPED:
+			handleReset();
+			handleStart();
+			break;
+		case PAUSED:
+			handleStart();
+			break;
+		case STARTED:
+			handleReset();
+			break;
+		}
+		mPlayState = STARTED;
+	}
+
+	void stop()
+	{
+		switch (mPlayState)
+		{
+		case STOPPED:
+			break;
+		case PAUSED:
+			handleStop();
+			break;
+		case STARTED:
+			break;
+		}
+		mPlayState = STOPPED;
+	}
+
+	void pause()
+	{
+		switch (mPlayState)
+		{
+		case STOPPED:
+			break;
+		case PAUSED:
+			break;
+		case STARTED:
+			handleStop();
+			break;
+		}
+		mPlayState = PAUSED;
+	}
+
+	void resume()
+	{
+		switch (mPlayState)
+		{
+		case STOPPED:
+			handleStart();
+			break;
+		case PAUSED:
+			handleStart();
+			break;
+		case STARTED:
+			break;
+		}
+		mPlayState = STARTED;
+	}
+
+	void restart()
+	{
+		switch (mPlayState)
+		{
+		case STOPPED:
+			handleReset();
+			handleStart();
+			break;
+		case PAUSED:
+			handleReset();
+			handleStart();
+			break;
+		case STARTED:
+			handleReset();
+			break;
+		}
+		mPlayState = STARTED;
+	}
+
+	void reset()
+	{
+		handleReset();
+	}
+
+	void splitTo(DERIVED& other)
+	{
+		onSplitTo(other);
+	}
+
+	void splitFrom(DERIVED& other)
+	{
+		other.onSplitTo(*this);
+	}
+
+	bool isStarted() { return mPlayState == STARTED; }
+	bool isPaused()  { return mPlayState == PAUSED; }
+	bool isStopped() { return mPlayState == STOPPED; }
+	EPlayState getPlayState() { return mPlayState; }
+
+protected:
+
+	LLVCRControlsMixin()
+	:	mPlayState(STOPPED)
+	{}
+
+private:
+	EPlayState mPlayState;
+};
+
 namespace LLTrace
 {
 	template<typename T, typename IS_UNIT> class Rate;
@@ -43,7 +184,7 @@ namespace LLTrace
 	template<typename T> class MeasurementAccumulator;
 	class TimerAccumulator;
 
-	class LL_COMMON_API Recording
+	class LL_COMMON_API Recording : public LLVCRControlsMixin<Recording>
 	{
 	public:
 		Recording();
@@ -53,16 +194,9 @@ namespace LLTrace
 		void makePrimary();
 		bool isPrimary();
 
-		void start();
-		void stop();
-		void resume();
-
 		void mergeSamples(const Recording& other);
 		void mergeDeltas(const Recording& baseline, const Recording& target);
 
-		void reset();
-
-		bool isStarted() { return mIsStarted; }
 
 		// Rate accessors
 		F32 getSum(const Rate<F32, void>& stat);
@@ -89,6 +223,14 @@ namespace LLTrace
 		F64 getSampleTime() { return mElapsedSeconds; }
 
 	private:
+		friend class PeriodicRecording;
+		// implementation for LLVCRControlsMixin
+		/*virtual*/ void handleStart();
+		/*virtual*/ void handleStop();
+		/*virtual*/ void handleReset();
+		/*virtual*/ void handleSplitTo(Recording& other);
+
+
 		friend class ThreadRecorder;
 		// returns data for current thread
 		class ThreadRecorder* getThreadRecorder(); 
@@ -97,14 +239,99 @@ namespace LLTrace
 		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F32> > >	mMeasurements;
 		LLCopyOnWritePointer<AccumulatorBuffer<TimerAccumulator> >				mStackTimers;
 
-		bool			mIsStarted;
 		LLTimer			mSamplingTimer;
 		F64				mElapsedSeconds;
 	};
 
-	class LL_COMMON_API PeriodicRecording
+	class LL_COMMON_API PeriodicRecording 
+	:	public LLVCRControlsMixin<PeriodicRecording>
 	{
+	public:
+		PeriodicRecording(S32 num_periods)
+		:	mNumPeriods(num_periods),
+			mCurPeriod(0),
+			mTotalValid(false),
+			mRecordingPeriods(new Recording[num_periods])
+		{
+			llassert(mNumPeriods > 0);
+		}
+
+		~PeriodicRecording()
+		{
+			delete[] mRecordingPeriods;
+		}
+
+		void nextPeriod()
+		{
+			EPlayState play_state = getPlayState();
+			getCurRecordingPeriod().stop();
+			mCurPeriod = (mCurPeriod + 1) % mNumPeriods;
+			switch(play_state)
+			{
+			case STOPPED:
+				break;
+			case PAUSED:
+				getCurRecordingPeriod().pause();
+				break;
+			case STARTED:
+				getCurRecordingPeriod().start();
+				break;
+			}
+			// new period, need to recalculate total
+			mTotalValid = false;
+		}
+
+		Recording& getCurRecordingPeriod()
+		{
+			return mRecordingPeriods[mCurPeriod];
+		}
+
+		const Recording& getCurRecordingPeriod() const
+		{
+			return mRecordingPeriods[mCurPeriod];
+		}
+
+		Recording& getTotalRecording()
+		{
+			if (!mTotalValid)
+			{
+				mTotalRecording.reset();
+				for (S32 i = (mCurPeriod + 1) % mNumPeriods; i < mCurPeriod; i++)
+				{
+					mTotalRecording.mergeSamples(mRecordingPeriods[i]);
+				}
+			}
+			mTotalValid = true;
+			return mTotalRecording;
+		}
+
+	private:
+		// implementation for LLVCRControlsMixin
+		/*virtual*/ void handleStart()
+		{
+			getCurRecordingPeriod().handleStart();
+		}
+
+		/*virtual*/ void handleStop()
+		{
+			getCurRecordingPeriod().handleStop();
+		}
+
+		/*virtual*/ void handleReset()
+		{
+			getCurRecordingPeriod().handleReset();
+		}
+
+		/*virtual*/ void handleSplitTo(PeriodicRecording& other)
+		{
+			getCurRecordingPeriod().handleSplitTo(other.getCurRecordingPeriod());
+		}
 
+		Recording*	mRecordingPeriods;
+		Recording	mTotalRecording;
+		bool		mTotalValid;
+		S32			mNumPeriods,
+					mCurPeriod;
 	};
 }
 
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 9d78df7cae..52b837fdc3 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -44,13 +44,19 @@ struct LLUnit : public BASE_UNIT
 	:	BASE_UNIT(convertToBase(value))
 	{}
 
-	operator value_t() { return get(); }
+	operator value_t() { return value(); }
 
-	value_t get() const
+	value_t value() const
 	{
 		return convertToDerived(mValue);
 	}
 
+	template<typename CONVERTED_TYPE>
+	value_t value() const
+	{
+		return CONVERTED_TYPE(*this).value();
+	}
+
 	static value_t convertToBase(value_t derived_value)
 	{
 		return (value_t)((F32)derived_value * DERIVED_UNIT::conversionToBaseFactor());
@@ -84,7 +90,7 @@ struct LLUnit<T, T>
 		return *this;
 	}
 
-	value_t get() { return mValue; }
+	value_t value() { return mValue; }
 
 	static value_t convertToBase(value_t derived_value)
 	{
-- 
cgit v1.2.3


From 8bb0a6ef737cb40c8f64f37fe64ecc7f6a87ae18 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 9 Oct 2012 18:07:31 -0700
Subject: post merge cleanup

---
 indra/llcommon/lltracerecording.cpp | 32 ++++++++++++++++----------------
 indra/llcommon/lltracerecording.h   |  2 +-
 2 files changed, 17 insertions(+), 17 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 93d2136e7f..d931c4ed29 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -46,6 +46,16 @@ Recording::Recording()
 Recording::~Recording()
 {}
 
+void Recording::update()
+{
+	if (isStarted())
+	{
+		LLTrace::get_thread_recorder()->update(this);
+		mElapsedSeconds = 0.0;
+		mSamplingTimer.reset();
+	}
+}
+
 void Recording::handleReset()
 {
 	mRates.write()->reset();
@@ -56,27 +66,17 @@ void Recording::handleReset()
 	mSamplingTimer.reset();
 }
 
-void Recording::update()
-{
-	if (mIsStarted)
-	{
-		LLTrace::get_thread_recorder()->update(this);
-		mElapsedSeconds = 0.0;
-		mSamplingTimer.reset();
-	}
-}
-
 void Recording::handleStart()
 {
-		mSamplingTimer.reset();
-		LLTrace::get_thread_recorder()->activate(this);
+	mSamplingTimer.reset();
+	LLTrace::get_thread_recorder()->activate(this);
 }
 
 void Recording::handleStop()
-	{
-		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
-		LLTrace::get_thread_recorder()->deactivate(this);
-	}
+{
+	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+	LLTrace::get_thread_recorder()->deactivate(this);
+}
 
 void Recording::handleSplitTo(Recording& other)
 {
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 6e5f118cf6..092dc7ff2c 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -254,7 +254,7 @@ namespace LLTrace
 			mCurPeriod(0),
 			mTotalValid(false),
 			mRecordingPeriods(new Recording[num_periods])
-	{
+		{
 			llassert(mNumPeriods > 0);
 		}
 
-- 
cgit v1.2.3


From 05510799e5a69eafcc919e72d25cf5b89c9274cf Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 9 Oct 2012 22:18:07 -0700
Subject: SH-3275 WIP Update viewer metrics system to be more flexible renamed
 mergeSamples to mergeRecording

---
 indra/llcommon/lltracerecording.cpp      | 2 +-
 indra/llcommon/lltracerecording.h        | 4 ++--
 indra/llcommon/lltracethreadrecorder.cpp | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index d931c4ed29..9a08770bd7 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -97,7 +97,7 @@ bool Recording::isPrimary()
 	return mRates->isPrimary();
 }
 
-void Recording::mergeSamples( const Recording& other )
+void Recording::mergeRecording( const Recording& other )
 {
 	mRates.write()->mergeSamples(*other.mRates);
 	mMeasurements.write()->mergeSamples(*other.mMeasurements);
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 092dc7ff2c..4399a65cfb 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -194,7 +194,7 @@ namespace LLTrace
 		void makePrimary();
 		bool isPrimary();
 
-		void mergeSamples(const Recording& other);
+		void mergeRecording(const Recording& other);
 		void mergeDeltas(const Recording& baseline, const Recording& target);
 
 		void reset();
@@ -300,7 +300,7 @@ namespace LLTrace
 				mTotalRecording.reset();
 				for (S32 i = (mCurPeriod + 1) % mNumPeriods; i < mCurPeriod; i++)
 				{
-					mTotalRecording.mergeSamples(mRecordingPeriods[i]);
+					mTotalRecording.mergeRecording(mRecordingPeriods[i]);
 				}
 			}
 			mTotalValid = true;
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index b2c6fe3b80..4d020f5650 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -161,13 +161,13 @@ void SlaveThreadRecorder::pushToMaster()
 void SlaveThreadRecorder::SharedData::copyFrom( const Recording& source )
 {
 	LLMutexLock lock(&mRecorderMutex);
-	mRecorder.mergeSamples(source);
+	mRecorder.mergeRecording(source);
 }
 
 void SlaveThreadRecorder::SharedData::copyTo( Recording& sink )
 {
 	LLMutexLock lock(&mRecorderMutex);
-	sink.mergeSamples(mRecorder);
+	sink.mergeRecording(mRecorder);
 }
 
 ///////////////////////////////////////////////////////////////////////
-- 
cgit v1.2.3


From 74ac0182ec8f7a0f6d0ea89f5814f0998ab90b62 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 10 Oct 2012 19:25:56 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system fixed units
 conversion so that trace getters return convertable units removed circular
 dependencies from lltrace* converted more stats to lltrace

---
 indra/llcommon/llqueuedthread.cpp        |   2 +-
 indra/llcommon/llthread.cpp              |   1 +
 indra/llcommon/lltrace.cpp               |   1 +
 indra/llcommon/lltrace.h                 |  88 ++++++++++------
 indra/llcommon/lltracerecording.cpp      |  96 ++---------------
 indra/llcommon/lltracerecording.h        | 145 +++++++++++++++++++------
 indra/llcommon/lltracethreadrecorder.cpp |  14 +--
 indra/llcommon/llunit.h                  | 176 ++++++++++++++++++-------------
 8 files changed, 295 insertions(+), 228 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 6e2a2b140f..218f6dbcd0 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -28,7 +28,7 @@
 
 #include "llstl.h"
 #include "lltimer.h"	// ms_sleep()
-#include "lltrace.h"
+#include "lltracethreadrecorder.h"
 
 //============================================================================
 
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 6723e427f5..cc661bab59 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -33,6 +33,7 @@
 
 #include "lltimer.h"
 #include "lltrace.h"
+#include "lltracethreadrecorder.h"
 
 #if LL_LINUX || LL_SOLARIS
 #include <sched.h>
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 2b1c8d8ce8..d5911ece25 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -27,6 +27,7 @@
 
 #include "lltrace.h"
 #include "lltracerecording.h"
+#include "lltracethreadrecorder.h"
 
 namespace LLTrace
 {
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index d83ea77363..539a37ce31 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -32,9 +32,9 @@
 
 #include "llmemory.h"
 #include "llrefcount.h"
-#include "lltracerecording.h"
-#include "lltracethreadrecorder.h"
+//#include "lltracethreadrecorder.h"
 #include "llunit.h"
+#include "llapr.h"
 
 #include <list>
 
@@ -44,6 +44,8 @@
 
 namespace LLTrace
 {
+	class Recording;
+
 	void init();
 	void cleanup();
 
@@ -89,23 +91,23 @@ namespace LLTrace
 			return mStorage[index]; 
 		}
 
-		void mergeSamples(const AccumulatorBuffer<ACCUMULATOR>& other)
+		void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other)
 		{
 			llassert(mNextStorageSlot == other.mNextStorageSlot);
 
 			for (size_t i = 0; i < mNextStorageSlot; i++)
 			{
-				mStorage[i].mergeSamples(other.mStorage[i]);
+				mStorage[i].addSamples(other.mStorage[i]);
 			}
 		}
 
-		void mergeDeltas(const AccumulatorBuffer<ACCUMULATOR>& start, const AccumulatorBuffer<ACCUMULATOR>& finish)
+		void addDeltas(const AccumulatorBuffer<ACCUMULATOR>& start, const AccumulatorBuffer<ACCUMULATOR>& finish)
 		{
 			llassert(mNextStorageSlot == start.mNextStorageSlot && mNextStorageSlot == finish.mNextStorageSlot);
 
 			for (size_t i = 0; i < mNextStorageSlot; i++)
 			{
-				mStorage[i].mergeDeltas(start.mStorage[i], finish.mStorage[i]);
+				mStorage[i].addDeltas(start.mStorage[i], finish.mStorage[i]);
 			}
 		}
 
@@ -173,8 +175,9 @@ namespace LLTrace
 	class LL_COMMON_API TraceType 
 	{
 	public:
-		TraceType(const std::string& name)
-		:	mName(name)
+		TraceType(const char* name, const char* description = NULL)
+		:	mName(name),
+			mDescription(description ? description : "")
 		{
 			mAccumulatorIndex = AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer().reserveSlot();
 		}
@@ -189,6 +192,7 @@ namespace LLTrace
 
 	protected:
 		std::string	mName;
+		std::string mDescription;
 		size_t		mAccumulatorIndex;
 	};
 
@@ -201,6 +205,8 @@ namespace LLTrace
 		:	mSum(0),
 			mMin(0),
 			mMax(0),
+			mMean(0),
+			mVarianceSum(0),
 			mNumSamples(0)
 		{}
 
@@ -218,10 +224,11 @@ namespace LLTrace
 			}
 			F32 old_mean = mMean;
 			mMean += ((F32)value - old_mean) / (F32)mNumSamples;
-			mStandardDeviation += ((F32)value - old_mean) * ((F32)value - mMean);
+			mVarianceSum += ((F32)value - old_mean) * ((F32)value - mMean);
+			mLastValue = value;
 		}
 
-		void mergeSamples(const MeasurementAccumulator<T>& other)
+		void addSamples(const MeasurementAccumulator<T>& other)
 		{
 			mSum += other.mSum;
 			if (other.mMin < mMin)
@@ -240,19 +247,20 @@ namespace LLTrace
 				n_2 = (F32)other.mNumSamples;
 			F32 m_1 = mMean,
 				m_2 = other.mMean;
-			F32 sd_1 = mStandardDeviation,
-				sd_2 = other.mStandardDeviation;
+			F32 sd_1 = getStandardDeviation(),
+				sd_2 = other.getStandardDeviation();
 			// combine variance (and hence standard deviation) of 2 different sized sample groups using
 			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
-			F32 variance = ((((n_1 - 1.f) * sd_1 * sd_1)
-								+ ((n_2 - 1.f) * sd_2 * sd_2)
-								+ (((n_1 * n_2) / (n_1 + n_2))
-									* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
-							/ (n_1 + n_2 - 1.f));
-			mStandardDeviation = sqrtf(variance);
+			mVarianceSum =  (F32)mNumSamples
+							* ((((n_1 - 1.f) * sd_1 * sd_1)
+									+ ((n_2 - 1.f) * sd_2 * sd_2)
+									+ (((n_1 * n_2) / (n_1 + n_2))
+										* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+								/ (n_1 + n_2 - 1.f));
+			mLastValue = other.mLastValue;
 		}
 
-		void mergeDeltas(const MeasurementAccumulator<T>& start, const MeasurementAccumulator<T>& finish)
+		void addDeltas(const MeasurementAccumulator<T>& start, const MeasurementAccumulator<T>& finish)
 		{
 			llerrs << "Delta merge invalid for measurement accumulators" << llendl;
 		}
@@ -268,16 +276,18 @@ namespace LLTrace
 		T	getSum() const { return mSum; }
 		T	getMin() const { return mMin; }
 		T	getMax() const { return mMax; }
+		T	getLastValue() const { return mLastValue; }
 		F32	getMean() const { return mMean; }
-		F32 getStandardDeviation() const { return mStandardDeviation; }
+		F32 getStandardDeviation() const { return sqrtf(mVarianceSum / mNumSamples); }
 
 	private:
 		T	mSum,
 			mMin,
-			mMax;
+			mMax,
+			mLastValue;
 
 		F32 mMean,
-			mStandardDeviation;
+			mVarianceSum;
 
 		U32	mNumSamples;
 	};
@@ -297,13 +307,13 @@ namespace LLTrace
 			mSum += value;
 		}
 
-		void mergeSamples(const RateAccumulator<T>& other)
+		void addSamples(const RateAccumulator<T>& other)
 		{
 			mSum += other.mSum;
 			mNumSamples += other.mNumSamples;
 		}
 
-		void mergeDeltas(const RateAccumulator<T>& start, const RateAccumulator<T>& finish)
+		void addDeltas(const RateAccumulator<T>& start, const RateAccumulator<T>& finish)
 		{
 			mSum += finish.mSum - start.mSum;
 			mNumSamples += finish.mNumSamples - start.mNumSamples;
@@ -329,7 +339,10 @@ namespace LLTrace
 		public LLInstanceTracker<Measurement<T, IS_UNIT>, std::string>
 	{
 	public:
-		Measurement(const std::string& name) 
+		typedef T storage_t;
+		typedef T base_unit_t;
+
+		Measurement(const char* name, const char* description = NULL) 
 		:	TraceType(name),
 			LLInstanceTracker(name)
 		{}
@@ -345,8 +358,11 @@ namespace LLTrace
 	:	public Measurement<typename T::value_t>
 	{
 	public:
+		typedef typename T::storage_t storage_t;
+		typedef typename T::base_unit_t base_unit_t;
+
 		typedef Measurement<typename T::value_t> base_measurement_t;
-		Measurement(const std::string& name) 
+		Measurement(const char* name, const char* description = NULL) 
 		:	Measurement<typename T::value_t>(name)
 		{}
 
@@ -363,7 +379,10 @@ namespace LLTrace
 		public LLInstanceTracker<Rate<T>, std::string>
 	{
 	public:
-		Rate(const std::string& name) 
+		typedef T storage_t;
+		typedef T base_unit_t;
+
+		Rate(const char* name, const char* description = NULL) 
 		:	TraceType(name),
 			LLInstanceTracker(name)
 		{}
@@ -379,7 +398,10 @@ namespace LLTrace
 	:	public Rate<typename T::value_t>
 	{
 	public:
-		Rate(const std::string& name) 
+		typedef typename T::storage_t storage_t;
+		typedef typename T::base_unit_t base_unit_t;
+
+		Rate(const char* name, const char* description = NULL) 
 		:	Rate<typename T::value_t>(name)
 		{}
 
@@ -394,7 +416,9 @@ namespace LLTrace
 	class LL_COMMON_API Count 
 	{
 	public:
-		Count(const std::string& name) 
+		typedef typename Rate<T>::base_unit_t base_unit_t;
+
+		Count(const char* name) 
 		:	mIncrease(name + "_increase"),
 			mDecrease(name + "_decrease"),
 			mTotal(name)
@@ -413,7 +437,7 @@ namespace LLTrace
 			mTotal.add(value);
 		}
 	private:
-		friend class LLTrace::Recording;
+		friend LLTrace::Recording;
 		Rate<T> mIncrease;
 		Rate<T> mDecrease;
 		Rate<T> mTotal;
@@ -433,14 +457,14 @@ namespace LLTrace
 		bool							mMoveUpTree;	// needs to be moved up the tree of timers at the end of frame
 		std::vector<TimerAccumulator*>	mChildren;		// currently assumed child timers
 
-		void mergeSamples(const TimerAccumulator& other)
+		void addSamples(const TimerAccumulator& other)
 		{
 			mTotalTimeCounter += other.mTotalTimeCounter;
 			mChildTimeCounter += other.mChildTimeCounter;
 			mCalls += other.mCalls;
 		}
 
-		void mergeDeltas(const TimerAccumulator& start, const TimerAccumulator& finish)
+		void addDeltas(const TimerAccumulator& start, const TimerAccumulator& finish)
 		{
 			mTotalTimeCounter += finish.mTotalTimeCounter - start.mTotalTimeCounter;
 			mChildTimeCounter += finish.mChildTimeCounter - start.mChildTimeCounter;
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index f0b17ef100..e20bf797e7 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -25,8 +25,9 @@
 
 #include "linden_common.h"
 
-#include "lltracerecording.h"
 #include "lltrace.h"
+#include "lltracerecording.h"
+#include "lltracethreadrecorder.h"
 #include "llthread.h"
 
 namespace LLTrace
@@ -101,99 +102,22 @@ void Recording::makePrimary()
 	mStackTimers.write()->makePrimary();
 }
 
-bool Recording::isPrimary()
+bool Recording::isPrimary() const
 {
 	return mRates->isPrimary();
 }
 
-void Recording::mergeSamples( const Recording& other )
+void Recording::addSamples( const Recording& other )
 {
-	mRates.write()->mergeSamples(*other.mRates);
-	mMeasurements.write()->mergeSamples(*other.mMeasurements);
-	mStackTimers.write()->mergeSamples(*other.mStackTimers);
+	mRates.write()->addSamples(*other.mRates);
+	mMeasurements.write()->addSamples(*other.mMeasurements);
+	mStackTimers.write()->addSamples(*other.mStackTimers);
 }
 
-void Recording::mergeDeltas(const Recording& baseline, const Recording& target)
+void Recording::addDeltas(const Recording& baseline, const Recording& target)
 {
-	mRates.write()->mergeDeltas(*baseline.mRates, *target.mRates);
-	mStackTimers.write()->mergeDeltas(*baseline.mStackTimers, *target.mStackTimers);
+	mRates.write()->addDeltas(*baseline.mRates, *target.mRates);
+	mStackTimers.write()->addDeltas(*baseline.mStackTimers, *target.mStackTimers);
 }
 
-
-F32 Recording::getSum(const Rate<F32>& stat)
-{
-	return stat.getAccumulator(mRates).getSum();
-}
-
-F32 Recording::getPerSec(const Rate<F32>& stat)
-{
-	return stat.getAccumulator(mRates).getSum() / mElapsedSeconds;
-}
-
-F32 Recording::getSum(const Measurement<F32>& stat)
-{
-	return stat.getAccumulator(mMeasurements).getSum();
-}
-
-F32 Recording::getMin(const Measurement<F32>& stat)
-{
-	return stat.getAccumulator(mMeasurements).getMin();
-}
-
-F32 Recording::getMax(const Measurement<F32>& stat)
-{
-	return stat.getAccumulator(mMeasurements).getMax();
-}
-
-F32 Recording::getMean(const Measurement<F32>& stat)
-{
-	return stat.getAccumulator(mMeasurements).getMean();
-}
-
-F32 Recording::getStandardDeviation(const Measurement<F32>& stat)
-{
-	return stat.getAccumulator(mMeasurements).getStandardDeviation();
-}
-
-F32 Recording::getSum(const Count<F32>& stat)
-{
-	return getSum(stat.mTotal);
-}
-
-F32 Recording::getPerSec(const Count<F32>& stat)
-{
-	return getPerSec(stat.mTotal);
-}
-
-F32 Recording::getIncrease(const Count<F32>& stat)
-{
-	return getSum(stat.mIncrease);
-}
-
-F32 Recording::getIncreasePerSec(const Count<F32>& stat)
-{
-	return getPerSec(stat.mIncrease);
-}
-
-F32 Recording::getDecrease(const Count<F32>& stat)
-{
-	return getSum(stat.mDecrease);
-}
-
-F32 Recording::getDecreasePerSec(const Count<F32>& stat)
-{
-	return getPerSec(stat.mDecrease);
-}
-
-F32 Recording::getChurn(const Count<F32>& stat)
-{
-	return getIncrease(stat) + getDecrease(stat);
-}
-
-F32 Recording::getChurnPerSec(const Count<F32>& stat)
-{
-	return getIncreasePerSec(stat) + getDecreasePerSec(stat);
-}
-
-
 }
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 4d53cd9600..d0c2e754f5 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -32,16 +32,17 @@
 
 #include "llpointer.h"
 #include "lltimer.h"
+#include "lltrace.h"
 
 namespace LLTrace
 {
-	template<typename T, typename IS_UNIT> class Rate;
-	template<typename T, typename IS_UNIT> class Measurement;
-	template<typename T> class Count;
-	template<typename T> class AccumulatorBuffer;
-	template<typename T> class RateAccumulator;
-	template<typename T> class MeasurementAccumulator;
-	class TimerAccumulator;
+	//template<typename T, typename IS_UNIT> class Rate;
+	//template<typename T, typename IS_UNIT> class Measurement;
+	//template<typename T> class Count;
+	//template<typename T> class AccumulatorBuffer;
+	//template<typename T> class RateAccumulator;
+	//template<typename T> class MeasurementAccumulator;
+	//class TimerAccumulator;
 
 	class LL_COMMON_API Recording
 	{
@@ -51,43 +52,125 @@ namespace LLTrace
 		~Recording();
 
 		void makePrimary();
-		bool isPrimary();
+		bool isPrimary() const;
 
 		void start();
 		void stop();
 		void resume();
-
-		void mergeSamples(const Recording& other);
-		void mergeDeltas(const Recording& baseline, const Recording& target);
-
 		void reset();
 		void update();
+		bool isStarted() const { return mIsStarted; }
 
-		bool isStarted() { return mIsStarted; }
+		void addSamples(const Recording& other);
+		void addDeltas(const Recording& baseline, const Recording& target);
 
 		// Rate accessors
-		F32 getSum(const Rate<F32, void>& stat);
-		F32 getPerSec(const Rate<F32, void>& stat);
+		template <typename T, typename IS_UNIT>
+		typename Rate<T, IS_UNIT>::base_unit_t getSum(const Rate<T, IS_UNIT>& stat) const
+		{
+			return (typename Rate<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mRates).getSum();
+		}
+
+		template <typename T, typename IS_UNIT>
+		typename Rate<T, IS_UNIT>::base_unit_t getPerSec(const Rate<T, IS_UNIT>& stat) const
+		{
+			return (typename Rate<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mRates).getSum() / mElapsedSeconds;
+		}
 
 		// Measurement accessors
-		F32 getSum(const Measurement<F32, void>& stat);
-		F32 getPerSec(const Measurement<F32, void>& stat);
-		F32 getMin(const Measurement<F32, void>& stat);
-		F32 getMax(const Measurement<F32, void>& stat);
-		F32 getMean(const Measurement<F32, void>& stat);
-		F32 getStandardDeviation(const Measurement<F32, void>& stat);
+		template <typename T, typename IS_UNIT>
+		typename Measurement<T, IS_UNIT>::base_unit_t getSum(const Measurement<T, IS_UNIT>& stat) const
+		{
+			return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getSum();
+
+		}
+
+		template <typename T, typename IS_UNIT>
+		typename Measurement<T, IS_UNIT>::base_unit_t getPerSec(const Measurement<T, IS_UNIT>& stat) const
+		{
+			return (typename Rate<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getSum() / mElapsedSeconds;
+		}
+
+		template <typename T, typename IS_UNIT>
+		typename Measurement<T, IS_UNIT>::base_unit_t getMin(const Measurement<T, IS_UNIT>& stat) const
+		{
+			return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getMin();
+		}
+
+		template <typename T, typename IS_UNIT>
+		typename Measurement<T, IS_UNIT>::base_unit_t getMax(const Measurement<T, IS_UNIT>& stat) const
+		{
+			return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getMax();
+		}
+
+		template <typename T, typename IS_UNIT>
+		typename Measurement<T, IS_UNIT>::base_unit_t getMean(const Measurement<T, IS_UNIT>& stat) const
+		{
+			return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getMean();
+		}
+
+		template <typename T, typename IS_UNIT>
+		typename Measurement<T, IS_UNIT>::base_unit_t getStandardDeviation(const Measurement<T, IS_UNIT>& stat) const
+		{
+			return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getStandardDeviation();
+		}
+
+		template <typename T, typename IS_UNIT>
+		typename Measurement<T, IS_UNIT>::base_unit_t getLastValue(const Measurement<T, IS_UNIT>& stat) const
+		{
+			return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getLastValue();
+		}
 
 		// Count accessors
-		F32 getSum(const Count<F32>& stat);
-		F32 getPerSec(const Count<F32>& stat);
-		F32 getIncrease(const Count<F32>& stat);
-		F32 getIncreasePerSec(const Count<F32>& stat);
-		F32 getDecrease(const Count<F32>& stat);
-		F32 getDecreasePerSec(const Count<F32>& stat);
-		F32 getChurn(const Count<F32>& stat);
-		F32 getChurnPerSec(const Count<F32>& stat);
-
-		F64 getSampleTime() { return mElapsedSeconds; }
+		template <typename T>
+		typename Count<T>::base_unit_t getSum(const Count<T>& stat) const
+		{
+			return getSum(stat.mTotal);
+		}
+
+		template <typename T>
+		typename Count<T>::base_unit_t getPerSec(const Count<T>& stat) const
+		{
+			return getPerSec(stat.mTotal);
+		}
+
+		template <typename T>
+		typename Count<T>::base_unit_t getIncrease(const Count<T>& stat) const
+		{
+			return getPerSec(stat.mTotal);
+		}
+
+		template <typename T>
+		typename Count<T>::base_unit_t getIncreasePerSec(const Count<T>& stat) const
+		{
+			return getPerSec(stat.mIncrease);
+		}
+
+		template <typename T>
+		typename Count<T>::base_unit_t getDecrease(const Count<T>& stat) const
+		{
+			return getPerSec(stat.mDecrease);
+		}
+
+		template <typename T>
+		typename Count<T>::base_unit_t getDecreasePerSec(const Count<T>& stat) const
+		{
+			return getPerSec(stat.mDecrease);
+		}
+
+		template <typename T>
+		typename Count<T>::base_unit_t getChurn(const Count<T>& stat) const
+		{
+			return getIncrease(stat) + getDecrease(stat);
+		}
+
+		template <typename T>
+		typename Count<T>::base_unit_t getChurnPerSec(const Count<T>& stat) const
+		{
+			return getIncreasePerSec(stat) + getDecreasePerSec(stat);
+		}
+
+		F64 getSampleTime() const { return mElapsedSeconds; }
 
 	private:
 		friend class ThreadRecorder;
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index b2c6fe3b80..78833835c2 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -25,7 +25,7 @@
 
 #include "linden_common.h"
 
-#include "lltrace.h"
+#include "lltracethreadrecorder.h"
 
 namespace LLTrace
 {
@@ -118,16 +118,16 @@ ThreadRecorder::ActiveRecording::ActiveRecording( Recording* source, Recording*
 
 void ThreadRecorder::ActiveRecording::mergeMeasurements(ThreadRecorder::ActiveRecording& other)
 {
-	mBaseline.mMeasurements.write()->mergeSamples(*other.mBaseline.mMeasurements);
+	mBaseline.mMeasurements.write()->addSamples(*other.mBaseline.mMeasurements);
 }
 
 void ThreadRecorder::ActiveRecording::flushAccumulators(Recording* current)
 {
 	// accumulate statistics-like measurements
-	mTargetRecording->mMeasurements.write()->mergeSamples(*mBaseline.mMeasurements);
+	mTargetRecording->mMeasurements.write()->addSamples(*mBaseline.mMeasurements);
 	// for rate-like measurements, merge total change since baseline
-	mTargetRecording->mRates.write()->mergeDeltas(*mBaseline.mRates, *current->mRates);
-	mTargetRecording->mStackTimers.write()->mergeDeltas(*mBaseline.mStackTimers, *current->mStackTimers);
+	mTargetRecording->mRates.write()->addDeltas(*mBaseline.mRates, *current->mRates);
+	mTargetRecording->mStackTimers.write()->addDeltas(*mBaseline.mStackTimers, *current->mStackTimers);
 	// reset baselines
 	mBaseline.mRates.write()->copyFrom(*current->mRates);
 	mBaseline.mStackTimers.write()->copyFrom(*current->mStackTimers);
@@ -161,13 +161,13 @@ void SlaveThreadRecorder::pushToMaster()
 void SlaveThreadRecorder::SharedData::copyFrom( const Recording& source )
 {
 	LLMutexLock lock(&mRecorderMutex);
-	mRecorder.mergeSamples(source);
+	mRecorder.addSamples(source);
 }
 
 void SlaveThreadRecorder::SharedData::copyTo( Recording& sink )
 {
 	LLMutexLock lock(&mRecorderMutex);
-	sink.mergeSamples(mRecorder);
+	sink.addSamples(mRecorder);
 }
 
 ///////////////////////////////////////////////////////////////////////
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 9d78df7cae..4663070c42 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -30,21 +30,24 @@
 #include "stdtypes.h"
 #include "llpreprocessor.h"
 
-template<typename BASE_UNIT, typename DERIVED_UNIT = BASE_UNIT>
-struct LLUnit : public BASE_UNIT
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT = BASE_UNIT>
+struct LLUnitType : public BASE_UNIT
 {
-	typedef LLUnit<BASE_UNIT, DERIVED_UNIT> unit_t;
+	typedef DERIVED_UNIT unit_t;
 	typedef typename BASE_UNIT::value_t value_t;
 	typedef void is_unit_t;
 
-	LLUnit()
+	LLUnitType()
 	{}
 
-	explicit LLUnit(value_t value)
+	explicit LLUnitType(value_t value)
 	:	BASE_UNIT(convertToBase(value))
 	{}
 
-	operator value_t() { return get(); }
+	operator unit_t& ()
+	{
+		return static_cast<unit_t&>(*this);
+	}
 
 	value_t get() const
 	{
@@ -53,47 +56,72 @@ struct LLUnit : public BASE_UNIT
 
 	static value_t convertToBase(value_t derived_value)
 	{
-		return (value_t)((F32)derived_value * DERIVED_UNIT::conversionToBaseFactor());
+		return (value_t)((F32)derived_value * unit_t::conversionToBaseFactor());
 	}
 
 	static value_t convertToDerived(value_t base_value)
 	{
-		return (value_t)((F32)base_value / DERIVED_UNIT::conversionToBaseFactor());
+		return (value_t)((F32)base_value / unit_t::conversionToBaseFactor());
+	}
+
+	unit_t operator + (const unit_t other) const
+	{
+		return unit_t(mValue + other.mValue);
+	}
+
+	unit_t operator - (const unit_t other) const
+	{
+		return unit_t(mValue - other.mValue);
+	}
+
+	unit_t operator * (value_t multiplicand) const
+	{
+		return unit_t(mValue * multiplicand);
+	}
+
+	unit_t operator / (value_t divisor) const
+	{
+		return unit_t(mValue / divisor);
 	}
 
 };
 
-template<typename T>
-struct LLUnit<T, T>
+template<typename STORAGE_TYPE, typename T>
+struct LLUnitType<STORAGE_TYPE, T, T>
 {
-	typedef LLUnit<T, T> unit_t;
-	typedef T value_t;
+	typedef T unit_t;
+	typedef typename STORAGE_TYPE value_t;
 	typedef void is_unit_t;
 
-	LLUnit()
+	LLUnitType()
 	:	mValue()
 	{}
 
-	explicit LLUnit(T value)
+	explicit LLUnitType(value_t value)
 	:	mValue(value)
 	{}
 
-	unit_t& operator=(T value)
+	unit_t& operator=(value_t value)
 	{
 		setBaseValue(value);
 		return *this;
 	}
 
+	operator unit_t& ()
+	{
+		return static_cast<unit_t&>(*this);
+	}
+
 	value_t get() { return mValue; }
 
 	static value_t convertToBase(value_t derived_value)
 	{
-		return (value_t)1;
+		return (value_t)derived_value;
 	}
 
 	static value_t convertToDerived(value_t base_value)
 	{
-		return (value_t)1;
+		return (value_t)base_value;
 	}
 
 	unit_t operator + (const unit_t other) const
@@ -137,68 +165,74 @@ struct LLUnit<T, T>
 	}
 
 protected:
-	void setBaseValue(T value)
+	void setBaseValue(value_t value)
 	{
 		mValue = value;
 	}
 
-	T mValue;
+	value_t mValue;
 };
 
-#define LL_DECLARE_BASE_UNIT(unit_name)                 \
-	template<typename STORAGE_TYPE>                     \
-	struct unit_name : public LLUnit<STORAGE_TYPE>      \
-	{                                                   \
-		unit_name(STORAGE_TYPE value)                   \
-		:	LLUnit(value)                               \
-		{}                                              \
-		                                                \
-		unit_name()                                     \
-		{}                                              \
-		                                                \
-		template <typename T>                           \
-		unit_name(const LLUnit<unit_name, T>& other)    \
-		{                                               \
-			setBaseValue(other.unit_name::get());       \
-		}                                               \
-		                                                \
-		using LLUnit<STORAGE_TYPE>::operator +;	        \
-		using LLUnit<STORAGE_TYPE>::operator +=;        \
-		using LLUnit<STORAGE_TYPE>::operator -;         \
-		using LLUnit<STORAGE_TYPE>::operator -=;        \
-		using LLUnit<STORAGE_TYPE>::operator *;         \
-		using LLUnit<STORAGE_TYPE>::operator *=;        \
-		using LLUnit<STORAGE_TYPE>::operator /;         \
-		using LLUnit<STORAGE_TYPE>::operator /=;        \
+#define LL_DECLARE_BASE_UNIT(unit_name)                                                     \
+	template<typename STORAGE_TYPE>                                                         \
+	struct unit_name : public LLUnitType<STORAGE_TYPE, unit_name<STORAGE_TYPE> >            \
+	{                                                                                       \
+		typedef unit_name<STORAGE_TYPE> base_unit_t;                                        \
+		typedef STORAGE_TYPE			storage_t;			                                \
+	                                                                                        \
+		unit_name(STORAGE_TYPE value)                                                       \
+		:	LLUnitType(value)                                                               \
+		{}                                                                                  \
+		                                                                                    \
+		unit_name()                                                                         \
+		{}                                                                                  \
+		                                                                                    \
+		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                       \
+		unit_name(const LLUnitType<SOURCE_STORAGE_TYPE, unit_name, SOURCE_TYPE>& source)    \
+		{                                                                                   \
+			setBaseValue(source.unit_t::get());												\
+		}                                                                                   \
+		                                                                                    \
+		using LLUnitType::operator +;	                                                    \
+		using LLUnitType::operator +=;														\
+		using LLUnitType::operator -;														\
+		using LLUnitType::operator -=;														\
+		using LLUnitType::operator *;														\
+		using LLUnitType::operator *=;														\
+		using LLUnitType::operator /;														\
+		using LLUnitType::operator /=;														\
 	};
 
-#define LL_DECLARE_DERIVED_UNIT(base_unit, derived_unit, conversion_factor)                   \
-	template<typename STORAGE_TYPE>                                                           \
-	struct derived_unit : public LLUnit<base_unit<STORAGE_TYPE>, derived_unit<STORAGE_TYPE> > \
-	{                                                                                         \
-		derived_unit(value_t value)                                                           \
-		:	LLUnit(value)                                                                     \
-		{}                                                                                    \
-		                                                                                      \
-		derived_unit()                                                                        \
-		{}                                                                                    \
-		                                                                                      \
-		template <typename T>                                                                 \
-		derived_unit(const LLUnit<base_unit<STORAGE_TYPE>, T>& other)                         \
-		{                                                                                     \
-			setBaseValue(other.base_unit<STORAGE_TYPE>::get());                               \
-		}                                                                                     \
-		                                                                                      \
-		static F32 conversionToBaseFactor() { return (F32)(conversion_factor); }              \
-		                                                                                      \
-	using LLUnit<STORAGE_TYPE>::operator +;	                                                  \
-	using LLUnit<STORAGE_TYPE>::operator +=;                                                  \
-	using LLUnit<STORAGE_TYPE>::operator -;                                                   \
-	using LLUnit<STORAGE_TYPE>::operator -=;                                                  \
-	using LLUnit<STORAGE_TYPE>::operator *;                                                   \
-	using LLUnit<STORAGE_TYPE>::operator *=;                                                  \
-	using LLUnit<STORAGE_TYPE>::operator /;                                                   \
-	using LLUnit<STORAGE_TYPE>::operator /=;                                                  \
+#define LL_DECLARE_DERIVED_UNIT(base_unit, derived_unit, conversion_factor)                                         \
+	template<typename STORAGE_TYPE>                                                                                 \
+	struct derived_unit : public LLUnitType<STORAGE_TYPE, base_unit<STORAGE_TYPE>, derived_unit<STORAGE_TYPE> >     \
+	{                                                                                                               \
+		typedef base_unit<STORAGE_TYPE> base_unit_t;                                                                \
+		typedef STORAGE_TYPE			storage_t;							                                        \
+		                                                                                                            \
+		derived_unit(value_t value)                                                                                 \
+		:	LLUnitType(value)                                                                                       \
+		{}                                                                                                          \
+		                                                                                                            \
+		derived_unit()                                                                                              \
+		{}                                                                                                          \
+		                                                                                                            \
+		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                                               \
+		derived_unit(const LLUnitType<SOURCE_STORAGE_TYPE, base_unit<STORAGE_TYPE>, SOURCE_TYPE>& source)           \
+		{                                                                                                           \
+			setBaseValue(source.base_unit_t::get());																\
+		}                                                                                                           \
+		                                                                                                            \
+		static F32 conversionToBaseFactor() { return (F32)(conversion_factor); }                                    \
+		                                                                                                            \
+		using LLUnitType::operator +;	                                                                            \
+		using LLUnitType::operator +=;                                                                              \
+		using LLUnitType::operator -;                                                                               \
+		using LLUnitType::operator -=;                                                                              \
+		using LLUnitType::operator *;                                                                               \
+		using LLUnitType::operator *=;                                                                              \
+		using LLUnitType::operator /;                                                                               \
+		using LLUnitType::operator /=;                                                                              \
 	};
 
 namespace LLUnits
-- 
cgit v1.2.3


From 0f58ca02cdec62711eadb82ba28fcff08faef2ee Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 12 Oct 2012 00:20:19 -0700
Subject: SH-3275 WIP Update viewer metrics system to be more flexible cleaned
 up accumulator merging logic introduced frame recording to LLTrace directly
 instead of going through LLViewerStats moved consumer code over to frame
 recording instead of whatever the current active recording was

---
 indra/llcommon/lltrace.h                 |  49 +++---
 indra/llcommon/lltracerecording.cpp      | 214 ++++++++++++++++++++++++--
 indra/llcommon/lltracerecording.h        | 251 +++++++++----------------------
 indra/llcommon/lltracethreadrecorder.cpp |  73 ++++-----
 indra/llcommon/lltracethreadrecorder.h   |   7 +-
 5 files changed, 321 insertions(+), 273 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index a6334e176b..0c618a2f4b 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -101,16 +101,6 @@ namespace LLTrace
 			}
 		}
 
-		void addDeltas(const AccumulatorBuffer<ACCUMULATOR>& start, const AccumulatorBuffer<ACCUMULATOR>& finish)
-		{
-			llassert(mNextStorageSlot == start.mNextStorageSlot && mNextStorageSlot == finish.mNextStorageSlot);
-
-			for (size_t i = 0; i < mNextStorageSlot; i++)
-			{
-				mStorage[i].addDeltas(start.mStorage[i], finish.mStorage[i]);
-			}
-		}
-
 		void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
 		{
 			for (size_t i = 0; i < mNextStorageSlot; i++)
@@ -203,11 +193,12 @@ namespace LLTrace
 	public:
 		MeasurementAccumulator()
 		:	mSum(0),
-			mMin(0),
-			mMax(0),
+			mMin(std::numeric_limits<T>::max()),
+			mMax(std::numeric_limits<T>::min()),
 			mMean(0),
 			mVarianceSum(0),
-			mNumSamples(0)
+			mNumSamples(0),
+			mLastValue(0)
 		{}
 
 		LL_FORCE_INLINE void sample(T value)
@@ -251,20 +242,27 @@ namespace LLTrace
 				sd_2 = other.getStandardDeviation();
 			// combine variance (and hence standard deviation) of 2 different sized sample groups using
 			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
-			mVarianceSum =  (F32)mNumSamples
+			if (n_1 == 0)
+			{
+				mVarianceSum = other.mVarianceSum;
+			}
+			else if (n_2 == 0)
+			{
+				// don't touch variance
+				// mVarianceSum = mVarianceSum;
+			}
+			else
+			{
+				mVarianceSum =  (F32)mNumSamples
 							* ((((n_1 - 1.f) * sd_1 * sd_1)
 								+ ((n_2 - 1.f) * sd_2 * sd_2)
 								+ (((n_1 * n_2) / (n_1 + n_2))
 									* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
 							/ (n_1 + n_2 - 1.f));
+			}
 			mLastValue = other.mLastValue;
 		}
 
-		void addDeltas(const MeasurementAccumulator<T>& start, const MeasurementAccumulator<T>& finish)
-		{
-			llerrs << "Delta merge invalid for measurement accumulators" << llendl;
-		}
-
 		void reset()
 		{
 			mNumSamples = 0;
@@ -313,12 +311,6 @@ namespace LLTrace
 			mNumSamples += other.mNumSamples;
 		}
 
-		void addDeltas(const RateAccumulator<T>& start, const RateAccumulator<T>& finish)
-		{
-			mSum += finish.mSum - start.mSum;
-			mNumSamples += finish.mNumSamples - start.mNumSamples;
-		}
-
 		void reset()
 		{
 			mNumSamples = 0;
@@ -464,13 +456,6 @@ namespace LLTrace
 			mCalls += other.mCalls;
 		}
 
-		void addDeltas(const TimerAccumulator& start, const TimerAccumulator& finish)
-		{
-			mTotalTimeCounter += finish.mTotalTimeCounter - start.mTotalTimeCounter;
-			mChildTimeCounter += finish.mChildTimeCounter - start.mChildTimeCounter;
-			mCalls += finish.mCalls - start.mCalls;
-		}
-
 		void reset()
 		{
 			mTotalTimeCounter = 0;
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 0883930319..5d7b231b7d 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -68,16 +68,16 @@ void Recording::handleReset()
 }
 
 void Recording::handleStart()
-	{
-		mSamplingTimer.reset();
-		LLTrace::get_thread_recorder()->activate(this);
+{
+	mSamplingTimer.reset();
+	LLTrace::get_thread_recorder()->activate(this);
 }
 
 void Recording::handleStop()
-	{
-		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
-		LLTrace::get_thread_recorder()->deactivate(this);
-	}
+{
+	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+	LLTrace::get_thread_recorder()->deactivate(this);
+}
 
 void Recording::handleSplitTo(Recording& other)
 {
@@ -105,10 +105,204 @@ void Recording::mergeRecording( const Recording& other )
 	mStackTimers.write()->addSamples(*other.mStackTimers);
 }
 
-void Recording::mergeRecordingDelta(const Recording& baseline, const Recording& target)
+///////////////////////////////////////////////////////////////////////
+// Recording
+///////////////////////////////////////////////////////////////////////
+
+PeriodicRecording::PeriodicRecording( S32 num_periods ) 
+:	mNumPeriods(num_periods),
+	mCurPeriod(0),
+	mTotalValid(false),
+	mRecordingPeriods( new Recording[num_periods])
+{
+	llassert(mNumPeriods > 0);
+}
+
+PeriodicRecording::~PeriodicRecording()
+{
+	delete[] mRecordingPeriods;
+}
+
+
+void PeriodicRecording::nextPeriod()
+{
+	EPlayState play_state = getPlayState();
+	getCurRecordingPeriod().stop();
+	mCurPeriod = (mCurPeriod + 1) % mNumPeriods;
+	switch(play_state)
+	{
+	case STOPPED:
+		break;
+	case PAUSED:
+		getCurRecordingPeriod().pause();
+		break;
+	case STARTED:
+		getCurRecordingPeriod().start();
+		break;
+	}
+	// new period, need to recalculate total
+	mTotalValid = false;
+}
+
+Recording& PeriodicRecording::getTotalRecording()
+{
+	if (!mTotalValid)
+	{
+		mTotalRecording.reset();
+		for (S32 i = (mCurPeriod + 1) % mNumPeriods; i < mCurPeriod; i++)
+		{
+			mTotalRecording.mergeRecording(mRecordingPeriods[i]);
+		}
+	}
+	mTotalValid = true;
+	return mTotalRecording;
+}
+
+void PeriodicRecording::handleStart()
+{
+	getCurRecordingPeriod().handleStart();
+}
+
+void PeriodicRecording::handleStop()
+{
+	getCurRecordingPeriod().handleStop();
+}
+
+void PeriodicRecording::handleReset()
+{
+	getCurRecordingPeriod().handleReset();
+}
+
+void PeriodicRecording::handleSplitTo( PeriodicRecording& other )
+{
+	getCurRecordingPeriod().handleSplitTo(other.getCurRecordingPeriod());
+}
+
+///////////////////////////////////////////////////////////////////////
+// ExtendableRecording
+///////////////////////////////////////////////////////////////////////
+
+void ExtendableRecording::extend()
 {
-	mRates.write()->addDeltas(*baseline.mRates, *target.mRates);
-	mStackTimers.write()->addDeltas(*baseline.mStackTimers, *target.mStackTimers);
+	mAcceptedRecording.mergeRecording(mPotentialRecording);
+	mPotentialRecording.reset();
 }
 
+void ExtendableRecording::handleStart()
+{
+	mPotentialRecording.handleStart();
+}
+
+void ExtendableRecording::handleStop()
+{
+	mPotentialRecording.handleStop();
+}
+
+void ExtendableRecording::handleReset()
+{
+	mAcceptedRecording.handleReset();
+	mPotentialRecording.handleReset();
+}
+
+void ExtendableRecording::handleSplitTo( ExtendableRecording& other )
+{
+	mPotentialRecording.handleSplitTo(other.mPotentialRecording);
+}
+
+PeriodicRecording& get_frame_recording()
+{
+	static PeriodicRecording sRecording(64);
+	sRecording.start();
+	return sRecording;
+}
+
+}
+
+void LLVCRControlsMixinCommon::start()
+{
+	switch (mPlayState)
+	{
+	case STOPPED:
+		handleReset();
+		handleStart();
+		break;
+	case PAUSED:
+		handleStart();
+		break;
+	case STARTED:
+		handleReset();
+		break;
+	}
+	mPlayState = STARTED;
+}
+
+void LLVCRControlsMixinCommon::stop()
+{
+	switch (mPlayState)
+	{
+	case STOPPED:
+		break;
+	case PAUSED:
+		handleStop();
+		break;
+	case STARTED:
+		handleStop();
+		break;
+	}
+	mPlayState = STOPPED;
+}
+
+void LLVCRControlsMixinCommon::pause()
+{
+	switch (mPlayState)
+	{
+	case STOPPED:
+		break;
+	case PAUSED:
+		break;
+	case STARTED:
+		handleStop();
+		break;
+	}
+	mPlayState = PAUSED;
+}
+
+void LLVCRControlsMixinCommon::resume()
+{
+	switch (mPlayState)
+	{
+	case STOPPED:
+		handleStart();
+		break;
+	case PAUSED:
+		handleStart();
+		break;
+	case STARTED:
+		break;
+	}
+	mPlayState = STARTED;
+}
+
+void LLVCRControlsMixinCommon::restart()
+{
+	switch (mPlayState)
+	{
+	case STOPPED:
+		handleReset();
+		handleStart();
+		break;
+	case PAUSED:
+		handleReset();
+		handleStart();
+		break;
+	case STARTED:
+		handleReset();
+		break;
+	}
+	mPlayState = STARTED;
+}
+
+void LLVCRControlsMixinCommon::reset()
+{
+	handleReset();
 }
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 0a1a02fa02..924a7bffd5 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -34,27 +34,11 @@
 #include "lltimer.h"
 #include "lltrace.h"
 
-template<typename DERIVED>
-class LL_COMMON_API LLVCRControlsMixinInterface
+class LL_COMMON_API LLVCRControlsMixinCommon
 {
 public:
-	virtual ~LLVCRControlsMixinInterface() {}
-	// trigger data accumulation (without reset)
-	virtual void handleStart() = 0;
-	// stop data accumulation, should put object in queryable state
-	virtual void handleStop() = 0;
-	// clear accumulated values, can be called while started
-	virtual void handleReset() = 0;
-	// atomically stop this object while starting the other
-	// no data can be missed in between stop and start
-	virtual void handleSplitTo(DERIVED& other) = 0;
-};
+	virtual ~LLVCRControlsMixinCommon() {}
 
-template<typename DERIVED>
-class LL_COMMON_API LLVCRControlsMixin
-:	private LLVCRControlsMixinInterface<DERIVED>
-{
-public:
 	enum EPlayState
 	{
 		STOPPED,
@@ -62,94 +46,39 @@ public:
 		STARTED
 	};
 
-	void start()
-	{
-		switch (mPlayState)
-		{
-		case STOPPED:
-			handleReset();
-			handleStart();
-			break;
-		case PAUSED:
-			handleStart();
-			break;
-		case STARTED:
-			handleReset();
-			break;
-		}
-		mPlayState = STARTED;
-	}
+	void start();
+	void stop();
+	void pause();
+	void resume();
+	void restart();
+	void reset();
 
-	void stop()
-	{
-		switch (mPlayState)
-		{
-		case STOPPED:
-			break;
-		case PAUSED:
-			handleStop();
-			break;
-		case STARTED:
-			break;
-		}
-		mPlayState = STOPPED;
-	}
-
-	void pause()
-	{
-		switch (mPlayState)
-		{
-		case STOPPED:
-			break;
-		case PAUSED:
-			break;
-		case STARTED:
-			handleStop();
-			break;
-		}
-		mPlayState = PAUSED;
-	}
+	bool isStarted() { return mPlayState == STARTED; }
+	bool isPaused()  { return mPlayState == PAUSED; }
+	bool isStopped() { return mPlayState == STOPPED; }
+	EPlayState getPlayState() { return mPlayState; }
 
-	void resume()
-	{
-		switch (mPlayState)
-		{
-		case STOPPED:
-			handleStart();
-			break;
-		case PAUSED:
-			handleStart();
-			break;
-		case STARTED:
-			break;
-		}
-		mPlayState = STARTED;
-	}
+protected:
+	LLVCRControlsMixinCommon()
+	:	mPlayState(STOPPED)
+	{}
 
-	void restart()
-	{
-		switch (mPlayState)
-		{
-		case STOPPED:
-			handleReset();
-			handleStart();
-			break;
-		case PAUSED:
-			handleReset();
-			handleStart();
-			break;
-		case STARTED:
-			handleReset();
-			break;
-		}
-		mPlayState = STARTED;
-	}
+private:
+	// trigger data accumulation (without reset)
+	virtual void handleStart() = 0;
+	// stop data accumulation, should put object in queryable state
+	virtual void handleStop() = 0;
+	// clear accumulated values, can be called while started
+	virtual void handleReset() = 0;
 
-	void reset()
-	{
-		handleReset();
-	}
+	EPlayState mPlayState;
+};
 
+template<typename DERIVED>
+class LLVCRControlsMixin
+:	public LLVCRControlsMixinCommon
+{
+public:
 	void splitTo(DERIVED& other)
 	{
 		onSplitTo(other);
@@ -159,32 +88,15 @@ public:
 	{
 		other.onSplitTo(*this);
 	}
-
-	bool isStarted() { return mPlayState == STARTED; }
-	bool isPaused()  { return mPlayState == PAUSED; }
-	bool isStopped() { return mPlayState == STOPPED; }
-	EPlayState getPlayState() { return mPlayState; }
-
-protected:
-
-	LLVCRControlsMixin()
-	:	mPlayState(STOPPED)
-	{}
-
 private:
-	EPlayState mPlayState;
+	// atomically stop this object while starting the other
+	// no data can be missed in between stop and start
+	virtual void handleSplitTo(DERIVED& other) = 0;
+
 };
 
 namespace LLTrace
 {
-	//template<typename T, typename IS_UNIT> class Rate;
-	//template<typename T, typename IS_UNIT> class Measurement;
-	//template<typename T> class Count;
-	//template<typename T> class AccumulatorBuffer;
-	//template<typename T> class RateAccumulator;
-	//template<typename T> class MeasurementAccumulator;
-	//class TimerAccumulator;
-
 	class LL_COMMON_API Recording : public LLVCRControlsMixin<Recording>
 	{
 	public:
@@ -196,7 +108,6 @@ namespace LLTrace
 		bool isPrimary() const;
 
 		void mergeRecording(const Recording& other);
-		void mergeRecordingDelta(const Recording& baseline, const Recording& target);
 
 		void update();
 
@@ -308,15 +219,13 @@ namespace LLTrace
 
 		F64 getSampleTime() const { return mElapsedSeconds; }
 
-	private:
-		friend class PeriodicRecording;
 		// implementation for LLVCRControlsMixin
 		/*virtual*/ void handleStart();
 		/*virtual*/ void handleStop();
 		/*virtual*/ void handleReset();
 		/*virtual*/ void handleSplitTo(Recording& other);
 
-
+	private:
 		friend class ThreadRecorder;
 		// returns data for current thread
 		class ThreadRecorder* getThreadRecorder(); 
@@ -333,38 +242,19 @@ namespace LLTrace
 	:	public LLVCRControlsMixin<PeriodicRecording>
 	{
 	public:
-		PeriodicRecording(S32 num_periods)
-		:	mNumPeriods(num_periods),
-			mCurPeriod(0),
-			mTotalValid(false),
-			mRecordingPeriods(new Recording[num_periods])
-	{
-			llassert(mNumPeriods > 0);
-		}
+		PeriodicRecording(S32 num_periods);
+		~PeriodicRecording();
+
+		void nextPeriod();
 
-		~PeriodicRecording()
+		Recording& getLastRecordingPeriod()
 		{
-			delete[] mRecordingPeriods;
+			return mRecordingPeriods[(mCurPeriod + mNumPeriods - 1) % mNumPeriods];
 		}
 
-		void nextPeriod()
+		const Recording& getLastRecordingPeriod() const
 		{
-			EPlayState play_state = getPlayState();
-			getCurRecordingPeriod().stop();
-			mCurPeriod = (mCurPeriod + 1) % mNumPeriods;
-			switch(play_state)
-			{
-			case STOPPED:
-				break;
-			case PAUSED:
-				getCurRecordingPeriod().pause();
-				break;
-			case STARTED:
-				getCurRecordingPeriod().start();
-				break;
-			}
-			// new period, need to recalculate total
-			mTotalValid = false;
+			return mRecordingPeriods[(mCurPeriod + mNumPeriods - 1) % mNumPeriods];
 		}
 
 		Recording& getCurRecordingPeriod()
@@ -377,41 +267,16 @@ namespace LLTrace
 			return mRecordingPeriods[mCurPeriod];
 		}
 
-		Recording& getTotalRecording()
-		{
-			if (!mTotalValid)
-			{
-				mTotalRecording.reset();
-				for (S32 i = (mCurPeriod + 1) % mNumPeriods; i < mCurPeriod; i++)
-				{
-					mTotalRecording.mergeRecording(mRecordingPeriods[i]);
-				}
-			}
-			mTotalValid = true;
-			return mTotalRecording;
-		}
+		Recording& getTotalRecording();
 
 	private:
-		// implementation for LLVCRControlsMixin
-		/*virtual*/ void handleStart()
-		{
-			getCurRecordingPeriod().handleStart();
-		}
-
-		/*virtual*/ void handleStop()
-		{
-			getCurRecordingPeriod().handleStop();
-		}
 
-		/*virtual*/ void handleReset()
-		{
-			getCurRecordingPeriod().handleReset();
-		}
+		// implementation for LLVCRControlsMixin
+		/*virtual*/ void handleStart();
+		/*virtual*/ void handleStop();
+		/*virtual*/ void handleReset();
 
-		/*virtual*/ void handleSplitTo(PeriodicRecording& other)
-		{
-			getCurRecordingPeriod().handleSplitTo(other.getCurRecordingPeriod());
-		}
+		/*virtual*/ void handleSplitTo(PeriodicRecording& other);
 
 		Recording*	mRecordingPeriods;
 		Recording	mTotalRecording;
@@ -419,6 +284,24 @@ namespace LLTrace
 		S32			mNumPeriods,
 					mCurPeriod;
 	};
+
+	PeriodicRecording& get_frame_recording();
+
+	class ExtendableRecording
+	:	public LLVCRControlsMixin<ExtendableRecording>
+	{
+		void extend();
+
+	private:
+		// implementation for LLVCRControlsMixin
+		/*virtual*/ void handleStart();
+		/*virtual*/ void handleStop();
+		/*virtual*/ void handleReset();
+		/*virtual*/ void handleSplitTo(ExtendableRecording& other);
+
+		Recording mAcceptedRecording;
+		Recording mPotentialRecording;
+	};
 }
 
 #endif // LL_LLTRACERECORDING_H
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 3acd06d553..48aa1a42f2 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -36,15 +36,13 @@ namespace LLTrace
 ///////////////////////////////////////////////////////////////////////
 
 ThreadRecorder::ThreadRecorder()
-:	mPrimaryRecording(NULL)
 {
 	get_thread_recorder() = this;
 	mFullRecording.start();
 }
 
 ThreadRecorder::ThreadRecorder( const ThreadRecorder& other ) 
-:	mFullRecording(other.mFullRecording),
-	mPrimaryRecording(NULL)
+:	mFullRecording(other.mFullRecording)
 {
 	get_thread_recorder() = this;
 	mFullRecording.start();
@@ -55,45 +53,40 @@ ThreadRecorder::~ThreadRecorder()
 	get_thread_recorder() = NULL;
 }
 
-//TODO: remove this and use llviewerstats recording
-Recording* ThreadRecorder::getPrimaryRecording()
-{
-	return mPrimaryRecording;
-}
-
 void ThreadRecorder::activate( Recording* recording )
 {
-	mActiveRecordings.push_front(ActiveRecording(mPrimaryRecording, recording));
+	mActiveRecordings.push_front(ActiveRecording(recording));
 	mActiveRecordings.front().mBaseline.makePrimary();
-	mPrimaryRecording = &mActiveRecordings.front().mBaseline;
 }
 
 std::list<ThreadRecorder::ActiveRecording>::iterator ThreadRecorder::update( Recording* recording )
 {
-	for (std::list<ActiveRecording>::iterator it = mActiveRecordings.begin(), end_it = mActiveRecordings.end();
+	std::list<ActiveRecording>::iterator it, end_it;
+	for (it = mActiveRecordings.begin(), end_it = mActiveRecordings.end();
 		it != end_it;
 		++it)
 	{
 		std::list<ActiveRecording>::iterator next_it = it;
-		if (++next_it != mActiveRecordings.end())
+		++next_it;
+
+		// if we have another recording further down in the stack...
+		if (next_it != mActiveRecordings.end())
 		{
-			next_it->mergeMeasurements((*it));
+			// ...push our gathered data down to it
+			next_it->mBaseline.mergeRecording(it->mBaseline);
 		}
 
-		it->flushAccumulators(mPrimaryRecording);
+		// copy accumulated measurements into result buffer and clear accumulator (mBaseline)
+		it->moveBaselineToTarget();
 
 		if (it->mTargetRecording == recording)
 		{
-			if (next_it != mActiveRecordings.end())
-			{
-				next_it->mBaseline.makePrimary();
-				mPrimaryRecording = &next_it->mBaseline;
-			}
-			return it;
+			// found the recording, so return it
+			break;
 		}
 	}
 
-	return mActiveRecordings.end();
+	return it;
 }
 
 void ThreadRecorder::deactivate( Recording* recording )
@@ -101,38 +94,34 @@ void ThreadRecorder::deactivate( Recording* recording )
 	std::list<ActiveRecording>::iterator it = update(recording);
 	if (it != mActiveRecordings.end())
 	{
+		// and if we've found the recording we wanted to update
+		std::list<ActiveRecording>::iterator next_it = it;
+		++next_it;
+		if (next_it != mActiveRecordings.end())
+		{
+			next_it->mTargetRecording->makePrimary();
+		}
+
 		mActiveRecordings.erase(it);
 	}
 }
 
-ThreadRecorder::ActiveRecording::ActiveRecording( Recording* source, Recording* target ) 
+ThreadRecorder::ActiveRecording::ActiveRecording( Recording* target ) 
 :	mTargetRecording(target)
 {
-	// take snapshots of current values rates and timers
-	if (source)
-	{
-		mBaseline.mRates.write()->copyFrom(*source->mRates);
-		mBaseline.mStackTimers.write()->copyFrom(*source->mStackTimers);
-	}
 }
 
-void ThreadRecorder::ActiveRecording::mergeMeasurements(ThreadRecorder::ActiveRecording& other)
+void ThreadRecorder::ActiveRecording::moveBaselineToTarget()
 {
-	mBaseline.mMeasurements.write()->addSamples(*other.mBaseline.mMeasurements);
-}
-
-void ThreadRecorder::ActiveRecording::flushAccumulators(Recording* current)
-{
-	// accumulate statistics-like measurements
 	mTargetRecording->mMeasurements.write()->addSamples(*mBaseline.mMeasurements);
-	// for rate-like measurements, merge total change since baseline
-	mTargetRecording->mRates.write()->addDeltas(*mBaseline.mRates, *current->mRates);
-	mTargetRecording->mStackTimers.write()->addDeltas(*mBaseline.mStackTimers, *current->mStackTimers);
-	// reset baselines
-	mBaseline.mRates.write()->copyFrom(*current->mRates);
-	mBaseline.mStackTimers.write()->copyFrom(*current->mStackTimers);
+	mTargetRecording->mRates.write()->addSamples(*mBaseline.mRates);
+	mTargetRecording->mStackTimers.write()->addSamples(*mBaseline.mStackTimers);
+	mBaseline.mMeasurements.write()->reset();
+	mBaseline.mRates.write()->reset();
+	mBaseline.mStackTimers.write()->reset();
 }
 
+
 ///////////////////////////////////////////////////////////////////////
 // SlaveThreadRecorder
 ///////////////////////////////////////////////////////////////////////
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 42230087c0..678b1a89f0 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -51,19 +51,16 @@ namespace LLTrace
 
 		virtual void pushToMaster() = 0;
 
-		Recording* getPrimaryRecording();
 	protected:
 		struct ActiveRecording
 		{
-			ActiveRecording(Recording* source, Recording* target);
+			ActiveRecording(Recording* target);
 
 			Recording*	mTargetRecording;
 			Recording	mBaseline;
 
-			void mergeMeasurements(ActiveRecording& other);
-			void flushAccumulators(Recording* current);
+			void moveBaselineToTarget();
 		};
-		Recording*					mPrimaryRecording;
 		Recording					mFullRecording;
 		std::list<ActiveRecording>	mActiveRecordings;
 	};
-- 
cgit v1.2.3


From 041dfccd1ea5b59c1b3c4e37e9a5495cad342c8f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 12 Oct 2012 20:17:52 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system default to
 double precision now fixed unit conversion logic for LLUnit renamed
 LLTrace::Rate to LLTrace::Count and got rid of the old count as it was
 confusing some const correctness changes

---
 indra/llcommon/llpointer.h               |   2 +
 indra/llcommon/lltrace.h                 |  93 ++++++++--------------
 indra/llcommon/lltracerecording.cpp      |  18 ++---
 indra/llcommon/lltracerecording.h        |  69 +++-------------
 indra/llcommon/lltracethreadrecorder.cpp |   4 +-
 indra/llcommon/llunit.h                  | 130 +++++++++++++++----------------
 6 files changed, 122 insertions(+), 194 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index 0fee4f0990..6a3bbeb768 100644
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -207,7 +207,9 @@ public:
 	using LLPointer<Type>::operator >;
 
 
+	operator Type*()							{ return mPointer; }
 	operator const Type*()   const				{ return mPointer; }
+	Type*	operator->()						{ return mPointer; }
 	const Type*	operator->() const				{ return mPointer; }
 
 };
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 0c618a2f4b..221c226ad1 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -91,6 +91,11 @@ namespace LLTrace
 			return mStorage[index]; 
 		}
 
+		LL_FORCE_INLINE const ACCUMULATOR& operator[](size_t index) const
+		{ 
+			return mStorage[index]; 
+		}
+
 		void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other)
 		{
 			llassert(mNextStorageSlot == other.mNextStorageSlot);
@@ -178,7 +183,7 @@ namespace LLTrace
 		}
 
 		ACCUMULATOR& getAccumulator(AccumulatorBuffer<ACCUMULATOR>* buffer) { return (*buffer)[mAccumulatorIndex]; }
-		const ACCUMULATOR& getAccumulator(AccumulatorBuffer<ACCUMULATOR>* buffer) const { return (*buffer)[mAccumulatorIndex]; }
+		const ACCUMULATOR& getAccumulator(const AccumulatorBuffer<ACCUMULATOR>* buffer) const { return (*buffer)[mAccumulatorIndex]; }
 
 	protected:
 		std::string	mName;
@@ -213,9 +218,9 @@ namespace LLTrace
 			{
 				mMax = value;
 			}
-			F32 old_mean = mMean;
-			mMean += ((F32)value - old_mean) / (F32)mNumSamples;
-			mVarianceSum += ((F32)value - old_mean) * ((F32)value - mMean);
+			F64 old_mean = mMean;
+			mMean += ((F64)value - old_mean) / (F64)mNumSamples;
+			mVarianceSum += ((F64)value - old_mean) * ((F64)value - mMean);
 			mLastValue = value;
 		}
 
@@ -231,14 +236,14 @@ namespace LLTrace
 				mMax = other.mMax;
 			}
 			mNumSamples += other.mNumSamples;
-			F32 weight = (F32)mNumSamples / (F32)(mNumSamples + other.mNumSamples);
+			F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
 			mMean = mMean * weight + other.mMean * (1.f - weight);
 
-			F32 n_1 = (F32)mNumSamples,
-				n_2 = (F32)other.mNumSamples;
-			F32 m_1 = mMean,
+			F64 n_1 = (F64)mNumSamples,
+				n_2 = (F64)other.mNumSamples;
+			F64 m_1 = mMean,
 				m_2 = other.mMean;
-			F32 sd_1 = getStandardDeviation(),
+			F64 sd_1 = getStandardDeviation(),
 				sd_2 = other.getStandardDeviation();
 			// combine variance (and hence standard deviation) of 2 different sized sample groups using
 			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
@@ -275,8 +280,8 @@ namespace LLTrace
 		T	getMin() const { return mMin; }
 		T	getMax() const { return mMax; }
 		T	getLastValue() const { return mLastValue; }
-		F32	getMean() const { return mMean; }
-		F32 getStandardDeviation() const { return sqrtf(mVarianceSum / mNumSamples); }
+		F64	getMean() const { return mMean; }
+		F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mNumSamples); }
 
 	private:
 		T	mSum,
@@ -284,17 +289,17 @@ namespace LLTrace
 			mMax,
 			mLastValue;
 
-		F32 mMean,
+		F64 mMean,
 			mVarianceSum;
 
 		U32	mNumSamples;
 	};
 
 	template<typename T>
-	class LL_COMMON_API RateAccumulator
+	class LL_COMMON_API CountAccumulator
 	{
 	public:
-		RateAccumulator()
+		CountAccumulator()
 		:	mSum(0),
 			mNumSamples(0)
 		{}
@@ -305,7 +310,7 @@ namespace LLTrace
 			mSum += value;
 		}
 
-		void addSamples(const RateAccumulator<T>& other)
+		void addSamples(const CountAccumulator<T>& other)
 		{
 			mSum += other.mSum;
 			mNumSamples += other.mNumSamples;
@@ -325,7 +330,7 @@ namespace LLTrace
 		U32	mNumSamples;
 	};
 
-	template <typename T, typename IS_UNIT = void>
+	template <typename T = F64, typename IS_UNIT = void>
 	class LL_COMMON_API Measurement
 	:	public TraceType<MeasurementAccumulator<T> >, 
 		public LLInstanceTracker<Measurement<T, IS_UNIT>, std::string>
@@ -352,8 +357,8 @@ namespace LLTrace
 	public:
 		typedef typename T::storage_t storage_t;
 		typedef typename T::base_unit_t base_unit_t;
-
 		typedef Measurement<typename T::value_t> base_measurement_t;
+
 		Measurement(const char* name, const char* description = NULL) 
 		:	Measurement<typename T::value_t>(name)
 		{}
@@ -361,20 +366,20 @@ namespace LLTrace
 		template<typename UNIT_T>
 		void sample(UNIT_T value)
 		{
-			base_measurement_t::sample(value.value());
+			base_measurement_t::sample(((T)value).value());
 		}
 	};
 
-	template <typename T, typename IS_UNIT = void>
-	class LL_COMMON_API Rate 
-	:	public TraceType<RateAccumulator<T> >, 
-		public LLInstanceTracker<Rate<T>, std::string>
+	template <typename T = F64, typename IS_UNIT = void>
+	class LL_COMMON_API Count 
+	:	public TraceType<CountAccumulator<T> >, 
+		public LLInstanceTracker<Count<T>, std::string>
 	{
 	public:
 		typedef T storage_t;
 		typedef T base_unit_t;
 
-		Rate(const char* name, const char* description = NULL) 
+		Count(const char* name, const char* description = NULL) 
 		:	TraceType(name),
 			LLInstanceTracker(name)
 		{}
@@ -386,53 +391,23 @@ namespace LLTrace
 	};
 
 	template <typename T>
-	class LL_COMMON_API Rate <T, typename T::is_unit_t>
-	:	public Rate<typename T::value_t>
+	class LL_COMMON_API Count <T, typename T::is_unit_t>
+	:	public Count<typename T::value_t>
 	{
 	public:
 		typedef typename T::storage_t storage_t;
 		typedef typename T::base_unit_t base_unit_t;
+		typedef Count<typename T::value_t> base_count_t;
 
-		Rate(const char* name, const char* description = NULL) 
-		:	Rate<typename T::value_t>(name)
+		Count(const char* name, const char* description = NULL) 
+		:	Count<typename T::value_t>(name)
 		{}
 
 		template<typename UNIT_T>
 		void add(UNIT_T value)
 		{
-			getPrimaryAccumulator().add(value.value());
-		}
-	};
-
-	template <typename T>
-	class LL_COMMON_API Count 
-	{
-	public:
-		typedef typename Rate<T>::base_unit_t base_unit_t;
-
-		Count(const char* name) 
-		:	mIncrease(name + "_increase"),
-			mDecrease(name + "_decrease"),
-			mTotal(name)
-		{}
-
-		void count(T value)
-		{
-			if (value < 0)
-			{
-				mDecrease.add(value * -1);
-			}
-			else
-			{
-				mIncrease.add(value);
-			}
-			mTotal.add(value);
+			base_count_t::add(((T)value).value());
 		}
-	private:
-		friend LLTrace::Recording;
-		Rate<T> mIncrease;
-		Rate<T> mDecrease;
-		Rate<T> mTotal;
 	};
 
 	class LL_COMMON_API TimerAccumulator
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 5d7b231b7d..9a769ff344 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -39,8 +39,8 @@ namespace LLTrace
 
 Recording::Recording() 
 :	mElapsedSeconds(0),
-	mRates(new AccumulatorBuffer<RateAccumulator<F32> >()),
-	mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<F32> >()),
+	mCounts(new AccumulatorBuffer<CountAccumulator<F64> >()),
+	mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<F64> >()),
 	mStackTimers(new AccumulatorBuffer<TimerAccumulator>())
 {}
 
@@ -59,7 +59,7 @@ void Recording::update()
 
 void Recording::handleReset()
 {
-	mRates.write()->reset();
+	mCounts.write()->reset();
 	mMeasurements.write()->reset();
 	mStackTimers.write()->reset();
 
@@ -88,21 +88,22 @@ void Recording::handleSplitTo(Recording& other)
 
 void Recording::makePrimary()
 {
-	mRates.write()->makePrimary();
+	mCounts.write()->makePrimary();
 	mMeasurements.write()->makePrimary();
 	mStackTimers.write()->makePrimary();
 }
 
 bool Recording::isPrimary() const
 {
-	return mRates->isPrimary();
+	return mCounts->isPrimary();
 }
 
 void Recording::mergeRecording( const Recording& other )
 {
-	mRates.write()->addSamples(*other.mRates);
+	mCounts.write()->addSamples(*other.mCounts);
 	mMeasurements.write()->addSamples(*other.mMeasurements);
 	mStackTimers.write()->addSamples(*other.mStackTimers);
+	mElapsedSeconds += other.mElapsedSeconds;
 }
 
 ///////////////////////////////////////////////////////////////////////
@@ -149,9 +150,9 @@ Recording& PeriodicRecording::getTotalRecording()
 	if (!mTotalValid)
 	{
 		mTotalRecording.reset();
-		for (S32 i = (mCurPeriod + 1) % mNumPeriods; i < mCurPeriod; i++)
+		for (S32 i = mCurPeriod + 1; i < mCurPeriod + mNumPeriods; i++)
 		{
-			mTotalRecording.mergeRecording(mRecordingPeriods[i]);
+			mTotalRecording.mergeRecording(mRecordingPeriods[i % mNumPeriods]);
 		}
 	}
 	mTotalValid = true;
@@ -212,7 +213,6 @@ void ExtendableRecording::handleSplitTo( ExtendableRecording& other )
 PeriodicRecording& get_frame_recording()
 {
 	static PeriodicRecording sRecording(64);
-	sRecording.start();
 	return sRecording;
 }
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 924a7bffd5..d9ac8c327a 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -111,17 +111,17 @@ namespace LLTrace
 
 		void update();
 
-		// Rate accessors
+		// Count accessors
 		template <typename T, typename IS_UNIT>
-		typename Rate<T, IS_UNIT>::base_unit_t getSum(const Rate<T, IS_UNIT>& stat) const
+		typename Count<T, IS_UNIT>::base_unit_t getSum(const Count<T, IS_UNIT>& stat) const
 		{
-			return (typename Rate<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mRates).getSum();
+			return (typename Count<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mCounts).getSum();
 		}
 
 		template <typename T, typename IS_UNIT>
-		typename Rate<T, IS_UNIT>::base_unit_t getPerSec(const Rate<T, IS_UNIT>& stat) const
+		typename Count<T, IS_UNIT>::base_unit_t getPerSec(const Count<T, IS_UNIT>& stat) const
 		{
-			return (typename Rate<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mRates).getSum() / mElapsedSeconds;
+			return (typename Count<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mCounts).getSum() / mElapsedSeconds;
 		}
 
 		// Measurement accessors
@@ -135,7 +135,7 @@ namespace LLTrace
 		template <typename T, typename IS_UNIT>
 		typename Measurement<T, IS_UNIT>::base_unit_t getPerSec(const Measurement<T, IS_UNIT>& stat) const
 		{
-			return (typename Rate<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getSum() / mElapsedSeconds;
+			return (typename Count<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getSum() / mElapsedSeconds;
 		}
 
 		template <typename T, typename IS_UNIT>
@@ -151,7 +151,7 @@ namespace LLTrace
 		}
 
 		template <typename T, typename IS_UNIT>
-		typename Measurement<T, IS_UNIT>::base_unit_t getMean(const Measurement<T, IS_UNIT>& stat) const
+		typename Measurement<T, IS_UNIT>::base_unit_t getMean(Measurement<T, IS_UNIT>& stat) const
 		{
 			return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getMean();
 		}
@@ -168,56 +168,7 @@ namespace LLTrace
 			return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getLastValue();
 		}
 
-		// Count accessors
-		template <typename T>
-		typename Count<T>::base_unit_t getSum(const Count<T>& stat) const
-		{
-			return getSum(stat.mTotal);
-		}
-
-		template <typename T>
-		typename Count<T>::base_unit_t getPerSec(const Count<T>& stat) const
-		{
-			return getPerSec(stat.mTotal);
-		}
-
-		template <typename T>
-		typename Count<T>::base_unit_t getIncrease(const Count<T>& stat) const
-		{
-			return getPerSec(stat.mTotal);
-		}
-
-		template <typename T>
-		typename Count<T>::base_unit_t getIncreasePerSec(const Count<T>& stat) const
-		{
-			return getPerSec(stat.mIncrease);
-		}
-
-		template <typename T>
-		typename Count<T>::base_unit_t getDecrease(const Count<T>& stat) const
-		{
-			return getPerSec(stat.mDecrease);
-		}
-
-		template <typename T>
-		typename Count<T>::base_unit_t getDecreasePerSec(const Count<T>& stat) const
-		{
-			return getPerSec(stat.mDecrease);
-		}
-
-		template <typename T>
-		typename Count<T>::base_unit_t getChurn(const Count<T>& stat) const
-		{
-			return getIncrease(stat) + getDecrease(stat);
-		}
-
-		template <typename T>
-		typename Count<T>::base_unit_t getChurnPerSec(const Count<T>& stat) const
-		{
-			return getIncreasePerSec(stat) + getDecreasePerSec(stat);
-		}
-
-		F64 getSampleTime() const { return mElapsedSeconds; }
+		F64 getDuration() const { return mElapsedSeconds; }
 
 		// implementation for LLVCRControlsMixin
 		/*virtual*/ void handleStart();
@@ -230,8 +181,8 @@ namespace LLTrace
 		// returns data for current thread
 		class ThreadRecorder* getThreadRecorder(); 
 
-		LLCopyOnWritePointer<AccumulatorBuffer<RateAccumulator<F32> > >			mRates;
-		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F32> > >	mMeasurements;
+		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<F64> > >		mCounts;
+		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > >	mMeasurements;
 		LLCopyOnWritePointer<AccumulatorBuffer<TimerAccumulator> >				mStackTimers;
 
 		LLTimer			mSamplingTimer;
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 48aa1a42f2..02dc55771b 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -114,10 +114,10 @@ ThreadRecorder::ActiveRecording::ActiveRecording( Recording* target )
 void ThreadRecorder::ActiveRecording::moveBaselineToTarget()
 {
 	mTargetRecording->mMeasurements.write()->addSamples(*mBaseline.mMeasurements);
-	mTargetRecording->mRates.write()->addSamples(*mBaseline.mRates);
+	mTargetRecording->mCounts.write()->addSamples(*mBaseline.mCounts);
 	mTargetRecording->mStackTimers.write()->addSamples(*mBaseline.mStackTimers);
 	mBaseline.mMeasurements.write()->reset();
-	mBaseline.mRates.write()->reset();
+	mBaseline.mCounts.write()->reset();
 	mBaseline.mStackTimers.write()->reset();
 }
 
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 2664bd77e9..090e42607e 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -51,7 +51,7 @@ struct LLUnitType : public BASE_UNIT
 
 	value_t value() const
 	{
-		return convertToDerived(mValue);
+		return convertToDerived(mBaseValue);
 	}
 
 	template<typename CONVERTED_TYPE>
@@ -72,22 +72,22 @@ struct LLUnitType : public BASE_UNIT
 
 	unit_t operator + (const unit_t other) const
 	{
-		return unit_t(mValue + other.mValue);
+		return unit_t(mBaseValue + other.mBaseValue);
 	}
 
 	unit_t operator - (const unit_t other) const
 	{
-		return unit_t(mValue - other.mValue);
+		return unit_t(mBaseValue - other.mBaseValue);
 	}
 
 	unit_t operator * (value_t multiplicand) const
 	{
-		return unit_t(mValue * multiplicand);
+		return unit_t(mBaseValue * multiplicand);
 	}
 
 	unit_t operator / (value_t divisor) const
 	{
-		return unit_t(mValue / divisor);
+		return unit_t(mBaseValue / divisor);
 	}
 
 };
@@ -100,11 +100,11 @@ struct LLUnitType<STORAGE_TYPE, T, T>
 	typedef void is_unit_t;
 
 	LLUnitType()
-	:	mValue()
+	:	mBaseValue()
 	{}
 
 	explicit LLUnitType(value_t value)
-	:	mValue(value)
+	:	mBaseValue(value)
 	{}
 
 	unit_t& operator=(value_t value)
@@ -118,7 +118,7 @@ struct LLUnitType<STORAGE_TYPE, T, T>
 		return static_cast<unit_t&>(*this);
 	}
 
-	value_t value() { return mValue; }
+	value_t value() const { return mBaseValue; }
 
 	static value_t convertToBase(value_t derived_value)
 	{
@@ -132,73 +132,73 @@ struct LLUnitType<STORAGE_TYPE, T, T>
 
 	unit_t operator + (const unit_t other) const
 	{
-		return unit_t(mValue + other.mValue);
+		return unit_t(mBaseValue + other.mBaseValue);
 	}
 
 	void operator += (const unit_t other)
 	{
-		mValue += other.mValue;
+		mBaseValue += other.mBaseValue;
 	}
 
 	unit_t operator - (const unit_t other) const
 	{
-		return unit_t(mValue - other.mValue);
+		return unit_t(mBaseValue - other.mBaseValue);
 	}
 
 	void operator -= (const unit_t other)
 	{
-		mValue -= other.mValue;
+		mBaseValue -= other.mBaseValue;
 	}
 
 	unit_t operator * (value_t multiplicand) const
 	{
-		return unit_t(mValue * multiplicand);
+		return unit_t(mBaseValue * multiplicand);
 	}
 
 	void operator *= (value_t multiplicand)
 	{
-		mValue *= multiplicand;
+		mBaseValue *= multiplicand;
 	}
 
 	unit_t operator / (value_t divisor) const
 	{
-		return unit_t(mValue / divisor);
+		return unit_t(mBaseValue / divisor);
 	}
 
 	void operator /= (value_t divisor)
 	{
-		mValue /= divisor;
+		mBaseValue /= divisor;
 	}
 
 protected:
 	void setBaseValue(value_t value)
 	{
-		mValue = value;
+		mBaseValue = value;
 	}
 
-	value_t mValue;
+	value_t mBaseValue;
 };
 
-#define LL_DECLARE_BASE_UNIT(unit_name)                 \
-	template<typename STORAGE_TYPE>                     \
-	struct unit_name : public LLUnitType<STORAGE_TYPE, unit_name<STORAGE_TYPE> >            \
-	{                                                   \
-		typedef unit_name<STORAGE_TYPE> base_unit_t;                                        \
-		typedef STORAGE_TYPE			storage_t;			                                \
+#define LL_DECLARE_BASE_UNIT(unit_name)                                                     \
+	struct unit_name : public LLUnitType<F64, unit_name>									\
+	{                                                                                       \
+		typedef unit_name base_unit_t;                                                      \
+		typedef LLUnitType<F64, unit_name> unit_t;						                    \
+		typedef F64			storage_t;			                                            \
 	                                                                                        \
-		unit_name(STORAGE_TYPE value)                   \
+		unit_name(F64 value)                                                                \
 		:	LLUnitType(value)                                                               \
-		{}                                              \
-		                                                \
-		unit_name()                                     \
-		{}                                              \
-		                                                \
+		{}                                                                                  \
+		                                                                                    \
+		unit_name()                                                                         \
+		{}                                                                                  \
+		                                                                                    \
 		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                       \
 		unit_name(const LLUnitType<SOURCE_STORAGE_TYPE, unit_name, SOURCE_TYPE>& source)    \
-		{                                               \
-			setBaseValue(source.unit_t::value());												\
-		}                                               \
-		                                                \
+		{                                                                                   \
+			setBaseValue((F64)source.unit_name::unit_t::value());				            \
+		}                                                                                   \
+		                                                                                    \
 		using LLUnitType::operator +;	                                                    \
 		using LLUnitType::operator +=;														\
 		using LLUnitType::operator -;														\
@@ -209,36 +209,36 @@ protected:
 		using LLUnitType::operator /=;														\
 	};
 
-#define LL_DECLARE_DERIVED_UNIT(base_unit, derived_unit, conversion_factor)                   \
-	template<typename STORAGE_TYPE>                                                           \
-	struct derived_unit : public LLUnitType<STORAGE_TYPE, base_unit<STORAGE_TYPE>, derived_unit<STORAGE_TYPE> >     \
-	{                                                                                         \
-		typedef base_unit<STORAGE_TYPE> base_unit_t;                                                                \
-		typedef STORAGE_TYPE			storage_t;							                                        \
-		                                                                                                            \
-		derived_unit(value_t value)                                                           \
-		:	LLUnitType(value)                                                                                       \
-		{}                                                                                    \
-		                                                                                      \
-		derived_unit()                                                                        \
-		{}                                                                                    \
-		                                                                                      \
-		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                                               \
-		derived_unit(const LLUnitType<SOURCE_STORAGE_TYPE, base_unit<STORAGE_TYPE>, SOURCE_TYPE>& source)           \
-		{                                                                                     \
-			setBaseValue(source.base_unit_t::value());																\
-		}                                                                                     \
-		                                                                                      \
-		static F32 conversionToBaseFactor() { return (F32)(conversion_factor); }              \
-		                                                                                      \
-		using LLUnitType::operator +;	                                                                            \
-		using LLUnitType::operator +=;                                                                              \
-		using LLUnitType::operator -;                                                                               \
-		using LLUnitType::operator -=;                                                                              \
-		using LLUnitType::operator *;                                                                               \
-		using LLUnitType::operator *=;                                                                              \
-		using LLUnitType::operator /;                                                                               \
-		using LLUnitType::operator /=;                                                                              \
+#define LL_DECLARE_DERIVED_UNIT(base_unit, derived_unit, conversion_factor)                 \
+	struct derived_unit : public LLUnitType<F64, base_unit, derived_unit>                   \
+	{                                                                                       \
+		typedef base_unit base_unit_t;                                                      \
+		typedef LLUnitType<F64, base_unit, derived_unit> unit_t;				            \
+		typedef F64			storage_t;							                            \
+		                                                                                    \
+		derived_unit(value_t value)                                                         \
+		:	LLUnitType(value)                                                               \
+		{}                                                                                  \
+		                                                                                    \
+		derived_unit()                                                                      \
+		{}                                                                                  \
+		                                                                                    \
+		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                       \
+		derived_unit(const LLUnitType<SOURCE_STORAGE_TYPE, base_unit, SOURCE_TYPE>& source) \
+		{                                                                                   \
+			setBaseValue((F64)source.base_unit::unit_t::value());						    \
+		}                                                                                   \
+		                                                                                    \
+		static F32 conversionToBaseFactor() { return (F32)(conversion_factor); }            \
+		                                                                                    \
+		using LLUnitType::operator +;	                                                    \
+		using LLUnitType::operator +=;                                                      \
+		using LLUnitType::operator -;                                                       \
+		using LLUnitType::operator -=;                                                      \
+		using LLUnitType::operator *;                                                       \
+		using LLUnitType::operator *=;                                                      \
+		using LLUnitType::operator /;                                                       \
+		using LLUnitType::operator /=;                                                      \
 	};
 
 namespace LLUnits
@@ -248,7 +248,7 @@ namespace LLUnits
 	LL_DECLARE_DERIVED_UNIT(Bytes, Megabytes, 1024 * 1024);
 	LL_DECLARE_DERIVED_UNIT(Bytes, Gigabytes, 1024 * 1024 * 1024);
 	LL_DECLARE_DERIVED_UNIT(Bytes, Bits,	  (1.f / 8.f));
-	LL_DECLARE_DERIVED_UNIT(Bytes, Kilobit,   (1024 / 8));
+	LL_DECLARE_DERIVED_UNIT(Bytes, Kilobits,  (1024 / 8));
 	LL_DECLARE_DERIVED_UNIT(Bytes, Megabits,  (1024 / 8));
 	LL_DECLARE_DERIVED_UNIT(Bytes, Gigabits,  (1024 * 1024 * 1024 / 8));
 
-- 
cgit v1.2.3


From 8d2f7a526545a10cd3669bf837a0b6f02cf5fe71 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 15 Oct 2012 19:43:35 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system converted all
 remaining LLViewerStats to lltrace

---
 indra/llcommon/llstatenums.h      |  2 +-
 indra/llcommon/lltrace.h          |  1 +
 indra/llcommon/lltracerecording.h | 15 ++++++++++++++-
 indra/llcommon/llunit.h           |  4 ++++
 4 files changed, 20 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llstatenums.h b/indra/llcommon/llstatenums.h
index 81c4085d16..ab9b6709e8 100644
--- a/indra/llcommon/llstatenums.h
+++ b/indra/llcommon/llstatenums.h
@@ -26,7 +26,7 @@
 #ifndef LL_LLSTATENUMS_H
 #define LL_LLSTATENUMS_H
 
-enum
+enum ESimStatID
 {
 	LL_SIM_STAT_TIME_DILATION         =  0,
 	LL_SIM_STAT_FPS                   =  1,
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 221c226ad1..3e19c83bd7 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -282,6 +282,7 @@ namespace LLTrace
 		T	getLastValue() const { return mLastValue; }
 		F64	getMean() const { return mMean; }
 		F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mNumSamples); }
+		U32 getSampleCount() const { return mNumSamples; }
 
 	private:
 		T	mSum,
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index d9ac8c327a..bd4b944e5a 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -168,6 +168,12 @@ namespace LLTrace
 			return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getLastValue();
 		}
 
+		template <typename T, typename IS_UNIT>
+		U32 getSampleCount(const Measurement<T, IS_UNIT>& stat) const
+		{
+			return stat.getAccumulator(mMeasurements).getSampleCount();
+		}
+
 		F64 getDuration() const { return mElapsedSeconds; }
 
 		// implementation for LLVCRControlsMixin
@@ -208,7 +214,7 @@ namespace LLTrace
 			return mRecordingPeriods[(mCurPeriod + mNumPeriods - 1) % mNumPeriods];
 		}
 
-		Recording& getCurRecordingPeriod()
+		Recording getCurRecordingPeriod()
 		{
 			return mRecordingPeriods[mCurPeriod];
 		}
@@ -218,6 +224,13 @@ namespace LLTrace
 			return mRecordingPeriods[mCurPeriod];
 		}
 
+		Recording snapshotCurRecordingPeriod() const
+		{
+			Recording recording_copy(getCurRecordingPeriod());
+			recording_copy.stop();
+			return recording_copy;
+		}
+
 		Recording& getTotalRecording();
 
 	private:
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 090e42607e..e8f6b2b2ba 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -261,6 +261,10 @@ namespace LLUnits
 	LL_DECLARE_DERIVED_UNIT(Seconds, Microseconds,	(1.f / (1000000.f)));
 	LL_DECLARE_DERIVED_UNIT(Seconds, Nanoseconds,	(1.f / (1000000000.f)));
 
+	LL_DECLARE_BASE_UNIT(Meters);
+	LL_DECLARE_DERIVED_UNIT(Meters, Kilometers, 1000);
+	LL_DECLARE_DERIVED_UNIT(Meters, Centimeters, 1 / 100);
+	LL_DECLARE_DERIVED_UNIT(Meters, Millimeters, 1 / 1000);
 }
 
 #endif // LL_LLUNIT_H
-- 
cgit v1.2.3


From e6ca5471a2a816a24888ae1b38332531b22b7254 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 17 Oct 2012 00:06:22 -0700
Subject: SH-3275  Update viewer metrics system to be more flexible put
 template parameter back in LLUnit units added free function operators for
 mathematical manipulation of unit values converted texture memory tracking to
 units

---
 indra/llcommon/lltrace.h          |  36 +++-
 indra/llcommon/lltracerecording.h |   2 +-
 indra/llcommon/llunit.h           | 376 ++++++++++++++++++++++++++------------
 3 files changed, 288 insertions(+), 126 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 3e19c83bd7..1c6726605a 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -46,6 +46,30 @@ namespace LLTrace
 {
 	class Recording;
 
+	typedef LLUnit::Bytes<F64>			Bytes;
+	typedef LLUnit::Kilobytes<F64>		Kilobytes;
+	typedef LLUnit::Megabytes<F64>		Megabytes;
+	typedef LLUnit::Gigabytes<F64>		Gigabytes;
+	typedef LLUnit::Bits<F64>			Bits;
+	typedef LLUnit::Kilobits<F64>		Kilobits;
+	typedef LLUnit::Megabits<F64>		Megabits;
+	typedef LLUnit::Gigabits<F64>		Gigabits;
+
+	typedef LLUnit::Seconds<F64>		Seconds;
+	typedef LLUnit::Milliseconds<F64>	Milliseconds;
+	typedef LLUnit::Minutes<F64>		Minutes;
+	typedef LLUnit::Hours<F64>			Hours;
+	typedef LLUnit::Days<F64>			Days;
+	typedef LLUnit::Weeks<F64>			Weeks;
+	typedef LLUnit::Milliseconds<F64>	Milliseconds;
+	typedef LLUnit::Microseconds<F64>	Microseconds;
+	typedef LLUnit::Nanoseconds<F64>	Nanoseconds;
+
+	typedef LLUnit::Meters<F64>			Meters;
+	typedef LLUnit::Kilometers<F64>		Kilometers;
+	typedef LLUnit::Centimeters<F64>	Centimeters;
+	typedef LLUnit::Millimeters<F64>	Millimeters;
+
 	void init();
 	void cleanup();
 
@@ -353,15 +377,15 @@ namespace LLTrace
 
 	template <typename T>
 	class LL_COMMON_API Measurement <T, typename T::is_unit_t>
-	:	public Measurement<typename T::value_t>
+	:	public Measurement<typename T::storage_t>
 	{
 	public:
 		typedef typename T::storage_t storage_t;
 		typedef typename T::base_unit_t base_unit_t;
-		typedef Measurement<typename T::value_t> base_measurement_t;
+		typedef Measurement<typename T::storage_t> base_measurement_t;
 
 		Measurement(const char* name, const char* description = NULL) 
-		:	Measurement<typename T::value_t>(name)
+		:	Measurement<typename T::storage_t>(name, description)
 		{}
 
 		template<typename UNIT_T>
@@ -393,15 +417,15 @@ namespace LLTrace
 
 	template <typename T>
 	class LL_COMMON_API Count <T, typename T::is_unit_t>
-	:	public Count<typename T::value_t>
+	:	public Count<typename T::storage_t>
 	{
 	public:
 		typedef typename T::storage_t storage_t;
 		typedef typename T::base_unit_t base_unit_t;
-		typedef Count<typename T::value_t> base_count_t;
+		typedef Count<typename T::storage_t> base_count_t;
 
 		Count(const char* name, const char* description = NULL) 
-		:	Count<typename T::value_t>(name)
+		:	Count<typename T::storage_t>(name)
 		{}
 
 		template<typename UNIT_T>
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index bd4b944e5a..5e7b0752c6 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -214,7 +214,7 @@ namespace LLTrace
 			return mRecordingPeriods[(mCurPeriod + mNumPeriods - 1) % mNumPeriods];
 		}
 
-		Recording getCurRecordingPeriod()
+		Recording& getCurRecordingPeriod()
 		{
 			return mRecordingPeriods[mCurPeriod];
 		}
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index e8f6b2b2ba..d980989c91 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -34,60 +34,43 @@ template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT = BASE
 struct LLUnitType : public BASE_UNIT
 {
 	typedef DERIVED_UNIT unit_t;
-	typedef typename BASE_UNIT::value_t value_t;
+
+	typedef typename STORAGE_TYPE storage_t;
 	typedef void is_unit_t;
 
 	LLUnitType()
 	{}
 
-	explicit LLUnitType(value_t value)
+	explicit LLUnitType(storage_t value)
 	:	BASE_UNIT(convertToBase(value))
 	{}
 
+	// implicit downcast
 	operator unit_t& ()
 	{
 		return static_cast<unit_t&>(*this);
 	}
 
-	value_t value() const
+	storage_t value() const
 	{
 		return convertToDerived(mBaseValue);
 	}
 
 	template<typename CONVERTED_TYPE>
-	value_t value() const
+	storage_t value() const
 	{
 		return CONVERTED_TYPE(*this).value();
 	}
 
-	static value_t convertToBase(value_t derived_value)
-	{
-		return (value_t)((F32)derived_value * unit_t::conversionToBaseFactor());
-	}
-
-	static value_t convertToDerived(value_t base_value)
-	{
-		return (value_t)((F32)base_value / unit_t::conversionToBaseFactor());
-	}
-
-	unit_t operator + (const unit_t other) const
-	{
-		return unit_t(mBaseValue + other.mBaseValue);
-	}
-
-	unit_t operator - (const unit_t other) const
-	{
-		return unit_t(mBaseValue - other.mBaseValue);
-	}
-
-	unit_t operator * (value_t multiplicand) const
+protected:
+	static storage_t convertToBase(storage_t derived_value)
 	{
-		return unit_t(mBaseValue * multiplicand);
+		return (storage_t)((F32)derived_value * unit_t::conversionToBaseFactor());
 	}
 
-	unit_t operator / (value_t divisor) const
+	static storage_t convertToDerived(storage_t base_value)
 	{
-		return unit_t(mBaseValue / divisor);
+		return (storage_t)((F32)base_value / unit_t::conversionToBaseFactor());
 	}
 
 };
@@ -96,43 +79,40 @@ template<typename STORAGE_TYPE, typename T>
 struct LLUnitType<STORAGE_TYPE, T, T>
 {
 	typedef T unit_t;
-	typedef typename STORAGE_TYPE value_t;
+	typedef STORAGE_TYPE storage_t;
 	typedef void is_unit_t;
+	typedef T base_unit_t;             
 
 	LLUnitType()
 	:	mBaseValue()
 	{}
 
-	explicit LLUnitType(value_t value)
+	explicit LLUnitType(storage_t value)
 	:	mBaseValue(value)
 	{}
 
-	unit_t& operator=(value_t value)
+	unit_t& operator=(storage_t value)
 	{
 		setBaseValue(value);
 		return *this;
 	}
 
+	//implicit downcast
 	operator unit_t& ()
 	{
 		return static_cast<unit_t&>(*this);
 	}
 
-	value_t value() const { return mBaseValue; }
+	storage_t value() const { return mBaseValue; }
 
-	static value_t convertToBase(value_t derived_value)
+	static storage_t convertToBase(storage_t derived_value)
 	{
-		return (value_t)derived_value;
+		return (storage_t)derived_value;
 	}
 
-	static value_t convertToDerived(value_t base_value)
+	static storage_t convertToDerived(storage_t base_value)
 	{
-		return (value_t)base_value;
-	}
-
-	unit_t operator + (const unit_t other) const
-	{
-		return unit_t(mBaseValue + other.mBaseValue);
+		return (storage_t)base_value;
 	}
 
 	void operator += (const unit_t other)
@@ -140,108 +120,266 @@ struct LLUnitType<STORAGE_TYPE, T, T>
 		mBaseValue += other.mBaseValue;
 	}
 
-	unit_t operator - (const unit_t other) const
-	{
-		return unit_t(mBaseValue - other.mBaseValue);
-	}
-
 	void operator -= (const unit_t other)
 	{
 		mBaseValue -= other.mBaseValue;
 	}
 
-	unit_t operator * (value_t multiplicand) const
-	{
-		return unit_t(mBaseValue * multiplicand);
-	}
-
-	void operator *= (value_t multiplicand)
+	void operator *= (storage_t multiplicand)
 	{
 		mBaseValue *= multiplicand;
 	}
 
-	unit_t operator / (value_t divisor) const
-	{
-		return unit_t(mBaseValue / divisor);
-	}
-
-	void operator /= (value_t divisor)
+	void operator /= (storage_t divisor)
 	{
 		mBaseValue /= divisor;
 	}
 
 protected:
-	void setBaseValue(value_t value)
+	void setBaseValue(storage_t value)
 	{
 		mBaseValue = value;
 	}
 
-	value_t mBaseValue;
+	storage_t mBaseValue;
 };
 
-#define LL_DECLARE_BASE_UNIT(unit_name)                                                     \
-	struct unit_name : public LLUnitType<F64, unit_name>									\
-	{                                                                                       \
-		typedef unit_name base_unit_t;                                                      \
-		typedef LLUnitType<F64, unit_name> unit_t;						                    \
-		typedef F64			storage_t;			                                            \
-	                                                                                        \
-		unit_name(F64 value)                                                                \
-		:	LLUnitType(value)                                                               \
-		{}                                                                                  \
-		                                                                                    \
-		unit_name()                                                                         \
-		{}                                                                                  \
-		                                                                                    \
-		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                       \
-		unit_name(const LLUnitType<SOURCE_STORAGE_TYPE, unit_name, SOURCE_TYPE>& source)    \
-		{                                                                                   \
-			setBaseValue((F64)source.unit_name::unit_t::value());				            \
-		}                                                                                   \
-		                                                                                    \
-		using LLUnitType::operator +;	                                                    \
-		using LLUnitType::operator +=;														\
-		using LLUnitType::operator -;														\
-		using LLUnitType::operator -=;														\
-		using LLUnitType::operator *;														\
-		using LLUnitType::operator *=;														\
-		using LLUnitType::operator /;														\
-		using LLUnitType::operator /=;														\
+//
+// operator +
+//
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+DERIVED_UNIT operator + (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+{
+	return DERIVED_UNIT(first + second.value());
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+DERIVED_UNIT operator + (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
+{
+	return DERIVED_UNIT(first.value() + second);
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
+DERIVED_UNIT operator + (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
+{
+	return DERIVED_UNIT(first.value() + second.value());
+}
+
+//
+// operator -
+//
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+DERIVED_UNIT operator - (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+{
+	return DERIVED_UNIT(first - second.value());
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+DERIVED_UNIT operator - (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
+{
+	return DERIVED_UNIT(first.value() - second);
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
+DERIVED_UNIT operator - (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
+{
+	return DERIVED_UNIT(first.value() - second.value());
+}
+
+//
+// operator *
+//
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+DERIVED_UNIT operator * (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+{
+	return DERIVED_UNIT(first * second.value());
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+DERIVED_UNIT operator * (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
+{
+	return DERIVED_UNIT(first.value() * second);
+}
+
+//
+// operator /
+//
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+DERIVED_UNIT operator / (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+{
+	return DERIVED_UNIT(first * second.value());
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+DERIVED_UNIT operator / (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
+{
+	return DERIVED_UNIT(first.value() * second);
+}
+
+//
+// operator <
+//
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+bool operator < (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+{
+	return first < second.value();
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+bool operator < (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
+{
+	return first.value() < second;
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
+bool operator < (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
+{
+	return first.value() < second.value();
+}
+
+//
+// operator <=
+//
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+bool operator <= (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+{
+	return first <= second.value();
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+bool operator <= (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
+{
+	return first.value() <= second;
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
+bool operator <= (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
+{
+	return first.value() <= second.value();
+}
+
+//
+// operator >
+//
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+bool operator > (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+{
+	return first > second.value();
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+bool operator > (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
+{
+	return first.value() > second;
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
+bool operator > (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
+{
+	return first.value() > second.value();
+}
+//
+// operator >=
+//
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+bool operator >= (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+{
+	return first >= second.value();
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+bool operator >= (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
+{
+	return first.value() >= second;
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
+bool operator >= (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
+{
+	return first.value() >= second.value();
+}
+
+//
+// operator ==
+//
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+bool operator == (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+{
+	return first == second.value();
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+bool operator == (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
+{
+	return first.value() == second;
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
+bool operator == (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
+{
+	return first.value() == second.value();
+}
+
+//
+// operator !=
+//
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+bool operator != (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+{
+	return first != second.value();
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+bool operator != (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
+{
+	return first.value() != second;
+}
+
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
+bool operator != (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
+{
+	return first.value() != second.value();
+}
+
+#define LL_DECLARE_BASE_UNIT(unit_name)                                                                          \
+	template<typename STORAGE>                                                                                   \
+	struct unit_name : public LLUnitType<STORAGE, unit_name<STORAGE>, unit_name<STORAGE> >						 \
+	{                                                                                                            \
+		typedef LLUnitType<STORAGE, unit_name> unit_t;						                                     \
+	                                                                                                             \
+		unit_name(storage_t value = 0)                                                                           \
+		:	LLUnitType(value)                                                                                    \
+		{}                                                                                                       \
+		                                                                                                         \
+		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                                            \
+		unit_name(LLUnitType<SOURCE_STORAGE_TYPE, unit_name<SOURCE_STORAGE_TYPE>, SOURCE_TYPE> source)			 \
+		{                                                                                                        \
+			setBaseValue((storage_t)source.unit_name<SOURCE_STORAGE_TYPE>::unit_t::value());			         \
+		}                                                                                                        \
+		                                                                                                         \
 	};
 
-#define LL_DECLARE_DERIVED_UNIT(base_unit, derived_unit, conversion_factor)                 \
-	struct derived_unit : public LLUnitType<F64, base_unit, derived_unit>                   \
-	{                                                                                       \
-		typedef base_unit base_unit_t;                                                      \
-		typedef LLUnitType<F64, base_unit, derived_unit> unit_t;				            \
-		typedef F64			storage_t;							                            \
-		                                                                                    \
-		derived_unit(value_t value)                                                         \
-		:	LLUnitType(value)                                                               \
-		{}                                                                                  \
-		                                                                                    \
-		derived_unit()                                                                      \
-		{}                                                                                  \
-		                                                                                    \
-		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                       \
-		derived_unit(const LLUnitType<SOURCE_STORAGE_TYPE, base_unit, SOURCE_TYPE>& source) \
-		{                                                                                   \
-			setBaseValue((F64)source.base_unit::unit_t::value());						    \
-		}                                                                                   \
-		                                                                                    \
-		static F32 conversionToBaseFactor() { return (F32)(conversion_factor); }            \
-		                                                                                    \
-		using LLUnitType::operator +;	                                                    \
-		using LLUnitType::operator +=;                                                      \
-		using LLUnitType::operator -;                                                       \
-		using LLUnitType::operator -=;                                                      \
-		using LLUnitType::operator *;                                                       \
-		using LLUnitType::operator *=;                                                      \
-		using LLUnitType::operator /;                                                       \
-		using LLUnitType::operator /=;                                                      \
+#define LL_DECLARE_DERIVED_UNIT(base_unit, derived_unit, conversion_factor)                                      \
+	template<typename STORAGE>	                                                                                 \
+	struct derived_unit : public LLUnitType<STORAGE, base_unit<STORAGE>, derived_unit<STORAGE> >                 \
+	{                                                                                                            \
+		typedef LLUnitType<STORAGE, base_unit<STORAGE>, derived_unit<STORAGE> > unit_t;				             \
+		                                                                                                         \
+		derived_unit(storage_t value = 0)                                                                        \
+		:	LLUnitType(value)                                                                                    \
+		{}                                                                                                       \
+		                                                                                                         \
+		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                                            \
+		derived_unit(LLUnitType<SOURCE_STORAGE_TYPE, base_unit<SOURCE_STORAGE_TYPE>, SOURCE_TYPE> source)		 \
+		{                                                                                                        \
+			setBaseValue((storage_t)source.base_unit<SOURCE_STORAGE_TYPE>::unit_t::value());					 \
+		}                                                                                                        \
+		                                                                                                         \
+		static F32 conversionToBaseFactor() { return (F32)(conversion_factor); }                                 \
+		                                                                                                         \
 	};
 
-namespace LLUnits
+namespace LLUnit
 {
 	LL_DECLARE_BASE_UNIT(Bytes);
 	LL_DECLARE_DERIVED_UNIT(Bytes, Kilobytes, 1024);
-- 
cgit v1.2.3


From a52d203a4f1d2988e8ffba16258f3f132f22f56d Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 17 Oct 2012 20:00:07 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system started
 conversion of llviewerassetstats removed old, dead LLViewerStats code made
 units tracing require units declaration clean up of units handling

---
 indra/llcommon/lltrace.h          | 44 +++++++++---------
 indra/llcommon/lltracerecording.h | 95 +++++++++++++++++++++++++++++++--------
 indra/llcommon/llunit.h           | 34 ++++++++++----
 3 files changed, 125 insertions(+), 48 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 1c6726605a..2a479b31d7 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -192,10 +192,12 @@ namespace LLTrace
 
 	template<typename ACCUMULATOR>
 	class LL_COMMON_API TraceType 
+	:	 public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
 	{
 	public:
 		TraceType(const char* name, const char* description = NULL)
-		:	mName(name),
+		:	LLInstanceTracker(name),
+			mName(name),
 			mDescription(description ? description : "")
 		{
 			mAccumulatorIndex = AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer().reserveSlot();
@@ -355,18 +357,17 @@ namespace LLTrace
 		U32	mNumSamples;
 	};
 
+	typedef TraceType<MeasurementAccumulator<F64> > measurement_common_t;
+
 	template <typename T = F64, typename IS_UNIT = void>
 	class LL_COMMON_API Measurement
-	:	public TraceType<MeasurementAccumulator<T> >, 
-		public LLInstanceTracker<Measurement<T, IS_UNIT>, std::string>
+	:	public TraceType<MeasurementAccumulator<T> >
 	{
 	public:
 		typedef T storage_t;
-		typedef T base_unit_t;
 
 		Measurement(const char* name, const char* description = NULL) 
-		:	TraceType(name),
-			LLInstanceTracker(name)
+		:	TraceType(name, description)
 		{}
 
 		void sample(T value)
@@ -376,37 +377,37 @@ namespace LLTrace
 	};
 
 	template <typename T>
-	class LL_COMMON_API Measurement <T, typename T::is_unit_t>
-	:	public Measurement<typename T::storage_t>
+	class LL_COMMON_API Measurement <T, typename T::is_unit_tag_t>
+	:	public TraceType<MeasurementAccumulator<typename T::storage_t> >
 	{
 	public:
 		typedef typename T::storage_t storage_t;
-		typedef typename T::base_unit_t base_unit_t;
 		typedef Measurement<typename T::storage_t> base_measurement_t;
 
 		Measurement(const char* name, const char* description = NULL) 
-		:	Measurement<typename T::storage_t>(name, description)
+		:	TraceType(name, description)
 		{}
 
 		template<typename UNIT_T>
 		void sample(UNIT_T value)
 		{
-			base_measurement_t::sample(((T)value).value());
+			T converted_value;
+			converted_value.assignFrom(value);
+			getPrimaryAccumulator().sample(converted_value.value());
 		}
 	};
 
+	typedef TraceType<CountAccumulator<F64> > count_common_t;
+
 	template <typename T = F64, typename IS_UNIT = void>
 	class LL_COMMON_API Count 
-	:	public TraceType<CountAccumulator<T> >, 
-		public LLInstanceTracker<Count<T>, std::string>
+	:	public TraceType<CountAccumulator<T> >
 	{
 	public:
 		typedef T storage_t;
-		typedef T base_unit_t;
 
 		Count(const char* name, const char* description = NULL) 
-		:	TraceType(name),
-			LLInstanceTracker(name)
+		:	TraceType(name)
 		{}
 
 		void add(T value)
@@ -416,22 +417,23 @@ namespace LLTrace
 	};
 
 	template <typename T>
-	class LL_COMMON_API Count <T, typename T::is_unit_t>
-	:	public Count<typename T::storage_t>
+	class LL_COMMON_API Count <T, typename T::is_unit_tag_t>
+	:	public TraceType<CountAccumulator<typename T::storage_t> >
 	{
 	public:
 		typedef typename T::storage_t storage_t;
-		typedef typename T::base_unit_t base_unit_t;
 		typedef Count<typename T::storage_t> base_count_t;
 
 		Count(const char* name, const char* description = NULL) 
-		:	Count<typename T::storage_t>(name)
+		:	TraceType(name)
 		{}
 
 		template<typename UNIT_T>
 		void add(UNIT_T value)
 		{
-			base_count_t::add(((T)value).value());
+			T converted_value;
+			converted_value.assignFrom(value);
+			getPrimaryAccumulator().add(converted_value.value());
 		}
 	};
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 5e7b0752c6..25f4f5c721 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -112,64 +112,121 @@ namespace LLTrace
 		void update();
 
 		// Count accessors
+		template <typename T>
+		T getSum(const TraceType<CountAccumulator<T> >& stat) const
+		{
+			return (T)stat.getAccumulator(mCounts).getSum();
+		}
+
 		template <typename T, typename IS_UNIT>
-		typename Count<T, IS_UNIT>::base_unit_t getSum(const Count<T, IS_UNIT>& stat) const
+		T getSum(const Count<T, IS_UNIT>& stat) const
+		{
+			return (T)stat.getAccumulator(mCounts).getSum();
+		}
+
+		template <typename T>
+		T getPerSec(const TraceType<CountAccumulator<T> >& stat) const
 		{
-			return (typename Count<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mCounts).getSum();
+			return (T)stat.getAccumulator(mCounts).getSum() / mElapsedSeconds;
 		}
 
 		template <typename T, typename IS_UNIT>
-		typename Count<T, IS_UNIT>::base_unit_t getPerSec(const Count<T, IS_UNIT>& stat) const
+		T getPerSec(const Count<T, IS_UNIT>& stat) const
 		{
-			return (typename Count<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mCounts).getSum() / mElapsedSeconds;
+			return (T)stat.getAccumulator(mCounts).getSum() / mElapsedSeconds;
 		}
 
 		// Measurement accessors
+		template <typename T>
+		T getSum(const TraceType<MeasurementAccumulator<T> >& stat) const
+		{
+			return (T)stat.getAccumulator(mMeasurements).getSum();
+
+		}
+
 		template <typename T, typename IS_UNIT>
-		typename Measurement<T, IS_UNIT>::base_unit_t getSum(const Measurement<T, IS_UNIT>& stat) const
+		T getSum(const Measurement<T, IS_UNIT>& stat) const
 		{
-			return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getSum();
+			return (T)stat.getAccumulator(mMeasurements).getSum();
+
+		}
 
+		template <typename T>
+		T getPerSec(const TraceType<MeasurementAccumulator<T> >& stat) const
+		{
+			return (T)stat.getAccumulator(mMeasurements).getSum() / mElapsedSeconds;
 		}
 
 		template <typename T, typename IS_UNIT>
-		typename Measurement<T, IS_UNIT>::base_unit_t getPerSec(const Measurement<T, IS_UNIT>& stat) const
+		T getPerSec(const Measurement<T, IS_UNIT>& stat) const
 		{
 			return (typename Count<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getSum() / mElapsedSeconds;
 		}
 
-		template <typename T, typename IS_UNIT>
-		typename Measurement<T, IS_UNIT>::base_unit_t getMin(const Measurement<T, IS_UNIT>& stat) const
+		template <typename T>
+		T getMin(const TraceType<MeasurementAccumulator<T> >& stat) const
 		{
-			return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getMin();
+			return (T)stat.getAccumulator(mMeasurements).getMin();
 		}
 
 		template <typename T, typename IS_UNIT>
-		typename Measurement<T, IS_UNIT>::base_unit_t getMax(const Measurement<T, IS_UNIT>& stat) const
+		T getMin(const Measurement<T, IS_UNIT>& stat) const
 		{
-			return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getMax();
+			return (T)stat.getAccumulator(mMeasurements).getMin();
+		}
+
+
+		template <typename T>
+		T getMax(const TraceType<MeasurementAccumulator<T> >& stat) const
+		{
+			return (T)stat.getAccumulator(mMeasurements).getMax();
 		}
 
 		template <typename T, typename IS_UNIT>
-		typename Measurement<T, IS_UNIT>::base_unit_t getMean(Measurement<T, IS_UNIT>& stat) const
+		T getMax(const Measurement<T, IS_UNIT>& stat) const
+		{
+			return (T)stat.getAccumulator(mMeasurements).getMax();
+		}
+
+		template <typename T>
+		T getMean(const TraceType<MeasurementAccumulator<T> >& stat) const
 		{
-			return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getMean();
+			return (T)stat.getAccumulator(mMeasurements).getMean();
 		}
 
 		template <typename T, typename IS_UNIT>
-		typename Measurement<T, IS_UNIT>::base_unit_t getStandardDeviation(const Measurement<T, IS_UNIT>& stat) const
+		T getMean(Measurement<T, IS_UNIT>& stat) const
+		{
+			return (T)stat.getAccumulator(mMeasurements).getMean();
+		}
+
+		template <typename T>
+		T getStandardDeviation(const TraceType<MeasurementAccumulator<T> >& stat) const
 		{
-			return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getStandardDeviation();
+			return (T)stat.getAccumulator(mMeasurements).getStandardDeviation();
 		}
 
 		template <typename T, typename IS_UNIT>
-		typename Measurement<T, IS_UNIT>::base_unit_t getLastValue(const Measurement<T, IS_UNIT>& stat) const
+		T getStandardDeviation(const Measurement<T, IS_UNIT>& stat) const
 		{
-			return (typename Measurement<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getLastValue();
+			return (T)stat.getAccumulator(mMeasurements).getStandardDeviation();
+		}
+
+		template <typename T>
+		T getLastValue(const TraceType<MeasurementAccumulator<T> >& stat) const
+		{
+			return (T)stat.getAccumulator(mMeasurements).getLastValue();
 		}
 
 		template <typename T, typename IS_UNIT>
-		U32 getSampleCount(const Measurement<T, IS_UNIT>& stat) const
+		T getLastValue(const Measurement<T, IS_UNIT>& stat) const
+		{
+			return (T)stat.getAccumulator(mMeasurements).getLastValue();
+		}
+
+
+		template <typename T>
+		U32 getSampleCount(const TraceType<MeasurementAccumulator<T> >& stat) const
 		{
 			return stat.getAccumulator(mMeasurements).getSampleCount();
 		}
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index d980989c91..e778383959 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -36,7 +36,7 @@ struct LLUnitType : public BASE_UNIT
 	typedef DERIVED_UNIT unit_t;
 
 	typedef typename STORAGE_TYPE storage_t;
-	typedef void is_unit_t;
+	typedef void is_unit_tag_t;
 
 	LLUnitType()
 	{}
@@ -57,7 +57,7 @@ struct LLUnitType : public BASE_UNIT
 	}
 
 	template<typename CONVERTED_TYPE>
-	storage_t value() const
+	storage_t as() const
 	{
 		return CONVERTED_TYPE(*this).value();
 	}
@@ -80,8 +80,7 @@ struct LLUnitType<STORAGE_TYPE, T, T>
 {
 	typedef T unit_t;
 	typedef STORAGE_TYPE storage_t;
-	typedef void is_unit_t;
-	typedef T base_unit_t;             
+	typedef void is_unit_tag_t;
 
 	LLUnitType()
 	:	mBaseValue()
@@ -105,6 +104,13 @@ struct LLUnitType<STORAGE_TYPE, T, T>
 
 	storage_t value() const { return mBaseValue; }
 
+	template<typename CONVERTED_TYPE>
+	storage_t as() const
+	{
+		return CONVERTED_TYPE(*this).value();
+	}
+
+
 	static storage_t convertToBase(storage_t derived_value)
 	{
 		return (storage_t)derived_value;
@@ -354,10 +360,16 @@ bool operator != (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUni
 		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                                            \
 		unit_name(LLUnitType<SOURCE_STORAGE_TYPE, unit_name<SOURCE_STORAGE_TYPE>, SOURCE_TYPE> source)			 \
 		{                                                                                                        \
-			setBaseValue((storage_t)source.unit_name<SOURCE_STORAGE_TYPE>::unit_t::value());			         \
+			assignFrom(source);			                                                                         \
 		}                                                                                                        \
 		                                                                                                         \
-	};
+		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                                            \
+		void assignFrom(LLUnitType<SOURCE_STORAGE_TYPE, unit_name<SOURCE_STORAGE_TYPE>, SOURCE_TYPE> source)     \
+		{                                                                                                        \
+			setBaseValue((storage_t)source.unit_name<SOURCE_STORAGE_TYPE>::unit_t::value());                     \
+		}                                                                                                        \
+	                                                                                                             \
+	};                                                                                                           \
 
 #define LL_DECLARE_DERIVED_UNIT(base_unit, derived_unit, conversion_factor)                                      \
 	template<typename STORAGE>	                                                                                 \
@@ -372,12 +384,18 @@ bool operator != (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUni
 		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                                            \
 		derived_unit(LLUnitType<SOURCE_STORAGE_TYPE, base_unit<SOURCE_STORAGE_TYPE>, SOURCE_TYPE> source)		 \
 		{                                                                                                        \
-			setBaseValue((storage_t)source.base_unit<SOURCE_STORAGE_TYPE>::unit_t::value());					 \
+			assignFrom(source);					                                                                 \
+		}                                                                                                        \
+		                                                                                                         \
+		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                                            \
+		void assignFrom(LLUnitType<SOURCE_STORAGE_TYPE, base_unit<SOURCE_STORAGE_TYPE>, SOURCE_TYPE> source)     \
+		{                                                                                                        \
+			setBaseValue((storage_t)source.base_unit<SOURCE_STORAGE_TYPE>::unit_t::value());                     \
 		}                                                                                                        \
 		                                                                                                         \
 		static F32 conversionToBaseFactor() { return (F32)(conversion_factor); }                                 \
 		                                                                                                         \
-	};
+	};                                                                                                           \
 
 namespace LLUnit
 {
-- 
cgit v1.2.3


From 1fadd6138eebf980776f80b9642f4c19279fcadd Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 18 Oct 2012 17:32:44 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system fixed trace
 recording on background threads hitting null pointer

---
 indra/llcommon/lltrace.h                 | 19 ++++++++++++++-----
 indra/llcommon/lltracethreadrecorder.cpp |  9 ++++-----
 indra/llcommon/lltracethreadrecorder.h   |  4 ++--
 3 files changed, 20 insertions(+), 12 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 2a479b31d7..2cdae4b0d2 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -167,15 +167,24 @@ namespace LLTrace
 			size_t next_slot = mNextStorageSlot++;
 			if (next_slot >= mStorageSize)
 			{
-				size_t new_size = mStorageSize + (mStorageSize >> 2);
-				delete [] mStorage;
-				mStorage = new ACCUMULATOR[new_size];
-				mStorageSize = new_size;
+				resize(mStorageSize + (mStorageSize >> 2));
 			}
-			llassert(next_slot < mStorageSize);
+			llassert(mStorage && next_slot < mStorageSize);
 			return next_slot;
 		}
 
+		void resize(size_t new_size)
+		{
+			ACCUMULATOR* old_storage = mStorage;
+			mStorage = new ACCUMULATOR[new_size];
+			for (S32 i = 0; i < mStorageSize; i++)
+			{
+				mStorage[i] = old_storage[i];
+			}
+			mStorageSize = new_size;
+			delete[] old_storage;
+		}
+
 		static AccumulatorBuffer<ACCUMULATOR>& getDefaultBuffer()
 		{
 			static AccumulatorBuffer sBuffer(STATIC_ALLOC);
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 02dc55771b..e81333f7f2 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -127,7 +127,6 @@ void ThreadRecorder::ActiveRecording::moveBaselineToTarget()
 ///////////////////////////////////////////////////////////////////////
 
 SlaveThreadRecorder::SlaveThreadRecorder()
-:	ThreadRecorder(getMasterThreadRecorder())
 {
 	getMasterThreadRecorder().addSlaveThread(this);
 }
@@ -149,14 +148,14 @@ void SlaveThreadRecorder::pushToMaster()
 
 void SlaveThreadRecorder::SharedData::copyFrom( const Recording& source )
 {
-	LLMutexLock lock(&mRecorderMutex);
-	mRecorder.mergeRecording(source);
+	LLMutexLock lock(&mRecordingMutex);
+	mRecording.mergeRecording(source);
 }
 
 void SlaveThreadRecorder::SharedData::copyTo( Recording& sink )
 {
-	LLMutexLock lock(&mRecorderMutex);
-	sink.mergeRecording(mRecorder);
+	LLMutexLock lock(&mRecordingMutex);
+	sink.mergeRecording(mRecording);
 }
 
 ///////////////////////////////////////////////////////////////////////
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 678b1a89f0..c9231265af 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -114,8 +114,8 @@ namespace LLTrace
 			void copyFrom(const Recording& source);
 			void copyTo(Recording& sink);
 		private:
-			LLMutex		mRecorderMutex;
-			Recording	mRecorder;
+			LLMutex		mRecordingMutex;
+			Recording	mRecording;
 		};
 		SharedData		mSharedData;
 	};
-- 
cgit v1.2.3


From 176ffa54b44f2ef73f23e3252dd439f52fab3265 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 19 Oct 2012 19:35:01 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system finished most of
 conversion of llviewerassetstats ported some param block fixes from
 viewer-chui converted viewer asset stats to param block format

---
 indra/llcommon/llinitparam.cpp    |  5 -----
 indra/llcommon/llinitparam.h      | 43 +++++++++++++++++++++++++++++++------
 indra/llcommon/llsdparam.cpp      | 45 +++++++++++++++++++--------------------
 indra/llcommon/lltracerecording.h |  2 +-
 4 files changed, 59 insertions(+), 36 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index db72aa19b9..54e98e66f3 100644
--- a/indra/llcommon/llinitparam.cpp
+++ b/indra/llcommon/llinitparam.cpp
@@ -196,12 +196,7 @@ namespace LLInitParam
 			if (serialize_func)
 			{
 				const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
-				// each param descriptor remembers its serial number
-				// so we can inspect the same param under different names
-				// and see that it has the same number
-				name_stack.push_back(std::make_pair("", true));
 				serialize_func(*param, parser, name_stack, diff_param);
-				name_stack.pop_back();
 			}
 		}
 
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index 9a6d1eff5c..b7607e91b9 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -1156,10 +1156,18 @@ namespace LLInitParam
 
 		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
 		{ 
+			Parser::name_stack_range_t new_name_stack_range(name_stack_range);
 			self_t& typed_param = static_cast<self_t&>(param);
 			value_t value;
+
+			// pop first element if empty string
+			if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty())
+			{
+				++new_name_stack_range.first;
+			}
+
 			// no further names in stack, attempt to parse value now
-			if (name_stack_range.first == name_stack_range.second)
+			if (new_name_stack_range.first == new_name_stack_range.second)
 			{
 				// attempt to read value directly
 				if (parser.readValue(value))
@@ -1192,14 +1200,14 @@ namespace LLInitParam
 		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
 		{
 			const self_t& typed_param = static_cast<const self_t&>(param);
-			if (!typed_param.isProvided() || name_stack.empty()) return;
+			if (!typed_param.isProvided()) return;
 
 			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
 				it != end_it;
 				++it)
 			{
 				std::string key = it->getValueName();
-				name_stack.back().second = true;
+				name_stack.push_back(std::make_pair(std::string(), true));
 
 				if(key.empty())
 				// not parsed via name values, write out value directly
@@ -1221,6 +1229,8 @@ namespace LLInitParam
 						break;
 					}
 				}
+
+				name_stack.pop_back();
 			}
 		}
 
@@ -1351,10 +1361,19 @@ namespace LLInitParam
 
 		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) 
 		{ 
+			Parser::name_stack_range_t new_name_stack_range(name_stack_range);
 			self_t& typed_param = static_cast<self_t&>(param);
 			bool new_value = false;
+			bool new_array_value = false;
+
+			// pop first element if empty string
+			if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty())
+			{
+				new_array_value = new_name_stack_range.first->second;
+				++new_name_stack_range.first;
+			}
 
-			if (new_name || typed_param.mValues.empty())
+			if (new_name || new_array_value || typed_param.mValues.empty())
 			{
 				new_value = true;
 				typed_param.mValues.push_back(value_t());
@@ -1363,9 +1382,13 @@ namespace LLInitParam
 			param_value_t& value = typed_param.mValues.back();
 
 			// attempt to parse block...
-			if(value.deserializeBlock(parser, name_stack_range, new_name))
+			if(value.deserializeBlock(parser, new_name_stack_range, new_name))
 			{
 				typed_param.setProvided();
+				if (new_array_value)
+				{
+					name_stack_range.first->second = false;
+				}
 				return true;
 			}
 			else if(name_value_lookup_t::valueNamesExist())
@@ -1379,6 +1402,10 @@ namespace LLInitParam
 					{
 						typed_param.mValues.back().setValueName(name);
 						typed_param.setProvided();
+						if (new_array_value)
+						{
+							name_stack_range.first->second = false;
+						}
 						return true;
 					}
 
@@ -1396,13 +1423,13 @@ namespace LLInitParam
 		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
 		{
 			const self_t& typed_param = static_cast<const self_t&>(param);
-			if (!typed_param.isProvided() || name_stack.empty()) return;
+			if (!typed_param.isProvided()) return;
 
 			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
 				it != end_it;
 				++it)
 			{
-				name_stack.back().second = true;
+				name_stack.push_back(std::make_pair(std::string(), true));
 
 				std::string key = it->getValueName();
 				if (!key.empty())
@@ -1415,6 +1442,8 @@ namespace LLInitParam
 				{
 					it->serializeBlock(parser, name_stack, NULL);
 				}
+
+				name_stack.pop_back();
 			}
 		}
 
diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp
index 0e29873bb0..4b8a8dba5c 100644
--- a/indra/llcommon/llsdparam.cpp
+++ b/indra/llcommon/llsdparam.cpp
@@ -223,10 +223,14 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser:
 	{
 		bool new_traversal = it->second;
 
-		LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first];
-
-		if (child_sd->isArray())
+		LLSD* child_sd;
+		if (it->first.empty())
+		{
+			child_sd = sd_to_write;
+			if (child_sd->isUndefined())
 		{
+				*child_sd = LLSD::emptyArray();
+			}
 			if (new_traversal)
 			{
 				// write to new element at end
@@ -240,22 +244,7 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser:
 		}
 		else
 		{
-			if (new_traversal 
-				&& child_sd->isDefined() 
-				&& !child_sd->isArray())
-			{
-				// copy child contents into first element of an array
-				LLSD new_array = LLSD::emptyArray();
-				new_array.append(*child_sd);
-				// assign array to slot that previously held the single value
-				*child_sd = new_array;
-				// return next element in that array
-				sd_to_write = &((*child_sd)[1]);
-			}
-			else
-			{
-				sd_to_write = child_sd;
-			}
+			sd_to_write = &(*sd_to_write)[it->first];
 		}
 		it->second = false;
 	}
@@ -283,8 +272,9 @@ void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLI
 			it != sd.endArray();
 			++it)
 		{
-			stack.back().second = true;
+			stack.push_back(make_pair(std::string(), true));
 			readSDValues(cb, *it, stack);
+			stack.pop_back();
 		}
 	}
 	else if (sd.isUndefined())
@@ -315,6 +305,12 @@ namespace LLInitParam
 	// block param interface
 	bool ParamValue<LLSD, TypeValues<LLSD>, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name)
 	{
+		if (name_stack.first == name_stack.second
+			&& p.readValue<LLSD>(mValue))
+		{
+			return true;
+		}
+
 		LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack);
 
 		LLSD::String string;
@@ -335,8 +331,11 @@ namespace LLInitParam
 
 	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const
 	{
-		// read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
-		Parser::name_stack_t stack;
-		LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack);
+		// attempt to write LLSD out directly
+		if (!p.writeValue<LLSD>(mValue, name_stack))
+		{
+			// otherwise read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
+			LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack);
+		}
 	}
 }
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 25f4f5c721..d3f001ab6a 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -231,7 +231,7 @@ namespace LLTrace
 			return stat.getAccumulator(mMeasurements).getSampleCount();
 		}
 
-		F64 getDuration() const { return mElapsedSeconds; }
+		LLUnit::Seconds<F64> getDuration() const { return mElapsedSeconds; }
 
 		// implementation for LLVCRControlsMixin
 		/*virtual*/ void handleStart();
-- 
cgit v1.2.3


From d6634fcd2433e18eea1a9bf31da6d7e531817d77 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 22 Oct 2012 19:54:10 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system sanitized param
 block code to accept isValid and isProvided at any point added predicates to
 control serialization

---
 indra/llcommon/CMakeLists.txt  |   2 +
 indra/llcommon/llinitparam.cpp |  35 +++++--
 indra/llcommon/llinitparam.h   | 221 ++++++++++++++++++++++++++---------------
 indra/llcommon/llpredicate.cpp |  33 ++++++
 indra/llcommon/llpredicate.h   | 173 ++++++++++++++++++++++++++++++++
 indra/llcommon/llsdparam.cpp   |   2 +-
 6 files changed, 376 insertions(+), 90 deletions(-)
 create mode 100644 indra/llcommon/llpredicate.cpp
 create mode 100644 indra/llcommon/llpredicate.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index c0e9266aa9..d876842cf1 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -77,6 +77,7 @@ set(llcommon_SOURCE_FILES
     llmutex.cpp
     lloptioninterface.cpp
     llptrto.cpp 
+    llpredicate.cpp
     llprocess.cpp
     llprocessor.cpp
     llqueuedthread.cpp
@@ -205,6 +206,7 @@ set(llcommon_HEADER_FILES
     llnametable.h
     lloptioninterface.h
     llpointer.h
+    llpredicate.h
     llpreprocessor.h
     llpriqueuemap.h
     llprocess.h
diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index 54e98e66f3..a63e792925 100644
--- a/indra/llcommon/llinitparam.cpp
+++ b/indra/llcommon/llinitparam.cpp
@@ -164,24 +164,37 @@ namespace LLInitParam
 
 	bool BaseBlock::validateBlock(bool emit_errors) const
 	{
-		const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
-		for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it)
+		// only validate block when it hasn't already passed validation with current data
+		if (!mValidated)
 		{
-			const Param* param = getParamFromHandle(it->first);
-			if (!it->second(param))
+			const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
+			for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it)
 			{
-				if (emit_errors)
+				const Param* param = getParamFromHandle(it->first);
+				if (!it->second(param))
 				{
-					llwarns << "Invalid param \"" << getParamName(block_data, param) << "\"" << llendl;
+					if (emit_errors)
+					{
+						llwarns << "Invalid param \"" << getParamName(block_data, param) << "\"" << llendl;
+					}
+					return false;
 				}
-				return false;
 			}
+			mValidated = true;
 		}
-		return true;
+		return mValidated;
 	}
 
-	void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const
+	void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const LLInitParam::BaseBlock* diff_block) const
 	{
+		if (!isProvided())
+		{
+			if ((~predicate_rule_t(PROVIDED) && predicate_rule).isTriviallyFalse())
+			{
+				return;
+			}
+		}
+
 		// named param is one like LLView::Params::follows
 		// unnamed param is like LLView::Params::rect - implicit
 		const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
@@ -196,7 +209,7 @@ namespace LLInitParam
 			if (serialize_func)
 			{
 				const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
-				serialize_func(*param, parser, name_stack, diff_param);
+				serialize_func(*param, parser, name_stack, predicate_rule, diff_param);
 			}
 		}
 
@@ -232,7 +245,7 @@ namespace LLInitParam
 
 				name_stack.push_back(std::make_pair(it->first, !duplicate));
 				const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
-				serialize_func(*param, parser, name_stack, diff_param);
+				serialize_func(*param, parser, name_stack, predicate_rule, diff_param);
 				name_stack.pop_back();
 			}
 		}
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index b7607e91b9..18c9669fba 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -32,10 +32,11 @@
 #include <boost/function.hpp>
 #include <boost/type_traits/is_convertible.hpp>
 #include <boost/unordered_map.hpp>
-#include <boost/shared_ptr.hpp>
+//#include <boost/shared_ptr.hpp>
 
 #include "llerror.h"
 #include "llstl.h"
+#include "llpredicate.h"
 
 namespace LLInitParam
 {
@@ -211,7 +212,6 @@ namespace LLInitParam
 		LOG_CLASS(Parser);
 
 	public:
-		
 		typedef std::vector<std::pair<std::string, bool> >					name_stack_t;
 		typedef std::pair<name_stack_t::iterator, name_stack_t::iterator>	name_stack_range_t;
 		typedef std::vector<std::string>									possible_values_t;
@@ -293,6 +293,17 @@ namespace LLInitParam
 
 	class Param;
 
+	enum ESerializePredicates
+	{
+		PROVIDED,
+		REQUIRED,
+		VALID,
+		NON_DEFAULT
+	};
+
+	typedef LLPredicate::Rule<ESerializePredicates> predicate_rule_t;
+
+
 	// various callbacks and constraints associated with an individual param
 	struct LL_COMMON_API ParamDescriptor
 	{
@@ -303,8 +314,8 @@ namespace LLInitParam
 
 		typedef bool(*merge_func_t)(Param&, const Param&, bool);
 		typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, bool);
-		typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param);
-		typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count);
+		typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const predicate_rule_t, const Param*);
+		typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32, S32);
 		typedef bool(*validation_func_t)(const Param*);
 
 		ParamDescriptor(param_handle_t p, 
@@ -331,7 +342,7 @@ namespace LLInitParam
 		UserData*			mUserData;
 	};
 
-	typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr;
+	typedef ParamDescriptor* ParamDescriptorPtr;
 
 	// each derived Block class keeps a static data structure maintaining offsets to various params
 	class LL_COMMON_API BlockDescriptor
@@ -484,12 +495,28 @@ namespace LLInitParam
 		LOG_CLASS(BaseBlock);
 		friend class Param;
 
+		BaseBlock()
+		:	mValidated(false),
+			mParamProvided(false)
+		{}
+
 		virtual ~BaseBlock() {}
 		bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false);
 
 		param_handle_t getHandleFromParam(const Param* param) const;
 		bool validateBlock(bool emit_errors = true) const;
 
+		bool isProvided() const
+		{
+			return mParamProvided;
+		}
+
+		bool isValid() const
+		{
+			return validateBlock(false);
+		}
+
+
 		Param* getParamFromHandle(const param_handle_t param_handle)
 		{
 			if (param_handle == 0) return NULL;
@@ -507,10 +534,19 @@ namespace LLInitParam
 		void addSynonym(Param& param, const std::string& synonym);
 
 		// Blocks can override this to do custom tracking of changes
-		virtual void paramChanged(const Param& changed_param, bool user_provided) {}
+		virtual void paramChanged(const Param& changed_param, bool user_provided) 
+		{
+			if (user_provided)
+			{
+				// a child param has been explicitly changed
+				// so *some* aspect of this block is now provided
+				mValidated = false;
+				mParamProvided = true;
+			}
+		}
 
 		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
-		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
+		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t rule = predicate_rule_t(), const BaseBlock* diff_block = NULL) const;
 		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const;
 
 		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
@@ -549,6 +585,9 @@ namespace LLInitParam
 			return sBlockDescriptor;
 		}
 
+		mutable bool 	mValidated; // lazy validation flag
+		bool			mParamProvided;
+
 	private:
 		const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const;
 	};
@@ -688,13 +727,11 @@ namespace LLInitParam
 		typedef ParamValue<T, NAME_VALUE_LOOKUP, true>	self_t;
 
 		ParamValue() 
-		:	T(),
-			mValidated(false)
+		:	T()
 		{}
 
 		ParamValue(value_assignment_t other)
-		:	T(other),
-			mValidated(false)
+		:	T(other)
 		{}
 
 		void setValue(value_assignment_t val)
@@ -736,9 +773,6 @@ namespace LLInitParam
 
 			return *this;
 		}
-
-	protected:
-		mutable bool 	mValidated; // lazy validation flag
 	};
 
 	template<typename NAME_VALUE_LOOKUP>
@@ -836,6 +870,8 @@ namespace LLInitParam
 
 		bool isProvided() const { return Param::anyProvided(); }
 
+		bool isValid() const { return true; }
+
 		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
 		{ 
 			self_t& typed_param = static_cast<self_t&>(param);
@@ -870,10 +906,26 @@ namespace LLInitParam
 			return false;
 		}
 
-		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
 		{
 			const self_t& typed_param = static_cast<const self_t&>(param);
-			if (!typed_param.isProvided()) return;
+			const self_t* diff_typed_param = static_cast<const self_t*>(diff_param);
+
+			LLPredicate::Value<ESerializePredicates> predicate;
+			if (!diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()))
+			{
+				predicate.set(NON_DEFAULT);
+			}
+			if (typed_param.isValid())
+			{
+				predicate.set(VALID);
+				if (typed_param.anyProvided())
+				{
+					predicate.set(PROVIDED);
+				}
+			}
+
+			if (!predicate_rule.check(predicate)) return;
 
 			if (!name_stack.empty())
 			{
@@ -886,18 +938,18 @@ namespace LLInitParam
 
 			if (!key.empty())
 			{
-				if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))
+				if (!diff_typed_param || !ParamCompare<std::string>::equals(diff_typed_param->getValueName(), key))
 				{
 					parser.writeValue(key, name_stack);
 				}
 			}
 			// then try to serialize value directly
-			else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), static_cast<const self_t*>(diff_param)->getValue()))
+			else if (!diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()))
 			{
 				if (!parser.writeValue(typed_param.getValue(), name_stack)) 
 				{
 					std::string calculated_key = typed_param.calcValueName(typed_param.getValue());
-					if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key))
+					if (!diff_typed_param || !ParamCompare<std::string>::equals(diff_typed_param->getValueName(), calculated_key))
 					{
 						parser.writeValue(calculated_key, name_stack);
 					}
@@ -1014,10 +1066,26 @@ namespace LLInitParam
 			return false;
 		}
 
-		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
 		{
 			const self_t& typed_param = static_cast<const self_t&>(param);
-			if (!typed_param.isProvided()) return;
+			const self_t* diff_typed_param = static_cast<const self_t*>(diff_param);
+
+			LLPredicate::Value<ESerializePredicates> predicate;
+			if (!diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()))
+			{
+				predicate.set(NON_DEFAULT);
+			}
+			if (typed_param.isValid())
+			{
+				predicate.set(VALID);
+				if (typed_param.anyProvided())
+				{
+					predicate.set(PROVIDED);
+				}
+			}
+
+			if (!predicate_rule.check(predicate)) return;
 
 			if (!name_stack.empty())
 			{
@@ -1034,7 +1102,7 @@ namespace LLInitParam
 			}
 			else
 			{
-				typed_param.serializeBlock(parser, name_stack, static_cast<const self_t*>(diff_param));
+				typed_param.serializeBlock(parser, name_stack, predicate_rule, static_cast<const self_t*>(diff_param));
 			}
 		}
 
@@ -1049,23 +1117,16 @@ namespace LLInitParam
 		// *and* the block as a whole validates
 		bool isProvided() const 
 		{ 
-			// only validate block when it hasn't already passed validation with current data
-			if (Param::anyProvided() && !param_value_t::mValidated)
-			{
-				// a sub-block is "provided" when it has been filled in enough to be valid
-				param_value_t::mValidated = param_value_t::validateBlock(false);
-			}
-			return Param::anyProvided() && param_value_t::mValidated;
+			return Param::anyProvided() && isValid();
 		}
 
+		using param_value_t::isValid;
+
 		// assign block contents to this param-that-is-a-block
 		void set(value_assignment_t val, bool flag_as_provided = true)
 		{
 			setValue(val);
 			param_value_t::clearValueName();
-			// force revalidation of block
-			// next call to isProvided() will update provision status based on validity
-			param_value_t::mValidated = false;
 			setProvided(flag_as_provided);
 		}
 
@@ -1080,9 +1141,6 @@ namespace LLInitParam
 			param_value_t::paramChanged(changed_param, user_provided);
 			if (user_provided)
 			{
-				// a child param has been explicitly changed
-				// so *some* aspect of this block is now provided
-				param_value_t::mValidated = false;
 				setProvided();
 				param_value_t::clearValueName();
 			}
@@ -1134,7 +1192,9 @@ namespace LLInitParam
 		typedef NAME_VALUE_LOOKUP											name_value_lookup_t;
 		
 		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) 
-		:	Param(block_descriptor.mCurrentBlockPtr)
+		:	Param(block_descriptor.mCurrentBlockPtr),
+			mMinCount(min_count),
+			mMaxCount(max_count)
 		{
 			std::copy(value.begin(), value.end(), std::back_inserter(mValues));
 
@@ -1152,7 +1212,13 @@ namespace LLInitParam
 			}
 		} 
 
-		bool isProvided() const { return Param::anyProvided(); }
+		bool isProvided() const { return Param::anyProvided() && isValid(); }
+
+		bool isValid() const 
+		{ 
+			size_t num_elements = numValidElements();
+			return mMinCount < num_elements && num_elements < mMaxCount;
+		}
 
 		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)
 		{ 
@@ -1197,7 +1263,7 @@ namespace LLInitParam
 			return false;
 		}
 
-		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
 		{
 			const self_t& typed_param = static_cast<const self_t&>(param);
 			if (!typed_param.isProvided()) return;
@@ -1293,7 +1359,7 @@ namespace LLInitParam
 		bool empty() const { return mValues.empty(); }
 		size_t size() const { return mValues.size(); }
 
-		U32 numValidElements() const
+		size_t numValidElements() const
 		{
 			return mValues.size();
 		}
@@ -1323,6 +1389,8 @@ namespace LLInitParam
 		}
 
 		container_t		mValues;
+		size_t			mMinCount,
+						mMaxCount;
 	};
 
 	// container of block parameters
@@ -1339,7 +1407,9 @@ namespace LLInitParam
 		typedef NAME_VALUE_LOOKUP										name_value_lookup_t;
 
 		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) 
-		:	Param(block_descriptor.mCurrentBlockPtr)
+		:	Param(block_descriptor.mCurrentBlockPtr),
+			mMinCount(min_count),
+			mMaxCount(max_count)
 		{
 			std::copy(value.begin(), value.end(), back_inserter(mValues));
 
@@ -1357,7 +1427,14 @@ namespace LLInitParam
 			}
 		} 
 
-		bool isProvided() const { return Param::anyProvided(); }
+		bool isProvided() const { return Param::anyProvided() && isValid(); }
+
+		bool isValid() const 
+		{ 
+			size_t num_elements = numValidElements();
+			return mMinCount < num_elements && num_elements < mMaxCount;
+		}
+
 
 		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) 
 		{ 
@@ -1420,9 +1497,13 @@ namespace LLInitParam
 			return false;
 		}
 
-		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
 		{
 			const self_t& typed_param = static_cast<const self_t&>(param);
+
+			LLPredicate::Value<ESerializePredicates> predicate_value;
+			if (typed_param.isProvided()) predicate_value.set(PROVIDED);
+			
 			if (!typed_param.isProvided()) return;
 
 			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
@@ -1437,10 +1518,10 @@ namespace LLInitParam
 					parser.writeValue(key, name_stack);
 				}
 				// Not parsed via named values, write out value directly
-				// NOTE: currently we don't worry about removing default values in Multiple
+				// NOTE: currently we don't do diffing of Multiples
 				else 
 				{
-					it->serializeBlock(parser, name_stack, NULL);
+					it->serializeBlock(parser, name_stack, predicate_rule, NULL);
 				}
 
 				name_stack.pop_back();
@@ -1500,14 +1581,14 @@ namespace LLInitParam
 		bool empty() const { return mValues.empty(); }
 		size_t size() const { return mValues.size(); }
 
-		U32 numValidElements() const
+		size_t numValidElements() const
 		{
-			U32 count = 0;
+			size_t count = 0;
 			for (const_iterator it = mValues.begin(), end_it = mValues.end();
 				it != end_it;
 				++it)
 			{
-				if(it->validateBlock(false)) count++;
+				if(it->isValid()) count++;
 			}
 			return count;
 		}
@@ -1539,6 +1620,8 @@ namespace LLInitParam
 		}
 
 		container_t			mValues;
+		size_t				mMinCount,
+							mMaxCount;
 	};
 
 	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock>
@@ -1826,7 +1909,7 @@ namespace LLInitParam
 
 			static bool validate(const Param* paramp) 
 			{
-				U32 num_valid = ((super_t*)paramp)->numValidElements();
+				size_t num_valid = ((super_t*)paramp)->numValidElements();
 				return RANGE::minCount <= num_valid && num_valid <= RANGE::maxCount;
 			}
 		};
@@ -1943,13 +2026,11 @@ namespace LLInitParam
 		typedef block_t value_t;
 
 		ParamValue()
-		:	block_t(),
-			mValidated(false)
+		:	block_t()
 		{}
 
 		ParamValue(value_assignment_t other)
-		:	block_t(other),
-			mValidated(false)
+		:	block_t(other)
 		{
 		}
 
@@ -1977,9 +2058,6 @@ namespace LLInitParam
 		{
 			return *this;
 		}
-
-	protected:
-		mutable bool 	mValidated; // lazy validation flag
 	};
 
 	template<typename T, bool IS_BLOCK>
@@ -1994,13 +2072,11 @@ namespace LLInitParam
 		typedef T value_t;
 	
 		ParamValue()
-		:	mValue(),
-			mValidated(false)
+		:	mValue()
 		{}
 
 		ParamValue(value_assignment_t other)
-		:	mValue(other),
-			mValidated(false)
+		:	mValue(other)
 		{}
 
 		void setValue(value_assignment_t val)
@@ -2033,11 +2109,11 @@ namespace LLInitParam
 			return mValue.get().deserializeBlock(p, name_stack_range, new_name);
 		}
 
-		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const
+		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block = NULL) const
 		{
 			if (mValue.empty()) return;
 			
-			mValue.get().serializeBlock(p, name_stack, diff_block);
+			mValue.get().serializeBlock(p, name_stack, predicate_rule, diff_block);
 		}
 
 		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
@@ -2047,9 +2123,6 @@ namespace LLInitParam
 			return mValue.get().inspectBlock(p, name_stack, min_count, max_count);
 		}
 
-	protected:
-		mutable bool 	mValidated; // lazy validation flag
-
 	private:
 		BaseBlock::Lazy<T>	mValue;
 	};
@@ -2066,12 +2139,10 @@ namespace LLInitParam
 		typedef const LLSD&	value_assignment_t;
 
 		ParamValue()
-		:	mValidated(false)
 		{}
 
 		ParamValue(value_assignment_t other)
-		:	mValue(other),
-			mValidated(false)
+		:	mValue(other)
 		{}
 
 		void setValue(value_assignment_t val) { mValue = val; }
@@ -2085,16 +2156,13 @@ namespace LLInitParam
 
 		// block param interface
 		LL_COMMON_API bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
-		LL_COMMON_API void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
+		LL_COMMON_API void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block = NULL) const;
 		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
 		{
 			//TODO: implement LLSD params as schema type Any
 			return true;
 		}
 
-	protected:
-		mutable bool 	mValidated; // lazy validation flag
-
 	private:
 		static void serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack);
 
@@ -2123,8 +2191,7 @@ namespace LLInitParam
 
 		CustomParamValue(const T& value = T())
 		:	mValue(value),
-			mValueAge(VALUE_AUTHORITATIVE),
-			mValidated(false)
+			mValueAge(VALUE_AUTHORITATIVE)
 		{}
 
 		bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack_range, bool new_name)
@@ -2148,7 +2215,7 @@ namespace LLInitParam
 			return typed_param.BaseBlock::deserializeBlock(parser, name_stack_range, new_name);
 		}
 
-		void serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const
+		void serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block = NULL) const
 		{
 			const derived_t& typed_param = static_cast<const derived_t&>(*this);
 			const derived_t* diff_param = static_cast<const derived_t*>(diff_block);
@@ -2184,11 +2251,11 @@ namespace LLInitParam
 						// and serialize those params
 						derived_t copy(typed_param);
 						copy.updateBlockFromValue(true);
-						copy.block_t::serializeBlock(parser, name_stack, NULL);
+						copy.block_t::serializeBlock(parser, name_stack, predicate_rule, NULL);
 					}
 					else
 					{
-						block_t::serializeBlock(parser, name_stack, NULL);
+						block_t::serializeBlock(parser, name_stack, predicate_rule, NULL);
 					}
 				}
 			}
@@ -2309,8 +2376,6 @@ namespace LLInitParam
 			return block_t::mergeBlock(block_data, source, overwrite);
 		}
 
-		mutable bool 		mValidated; // lazy validation flag
-
 	private:
 		mutable T			mValue;
 		mutable EValueAge	mValueAge;
diff --git a/indra/llcommon/llpredicate.cpp b/indra/llcommon/llpredicate.cpp
new file mode 100644
index 0000000000..8dcd9247b7
--- /dev/null
+++ b/indra/llcommon/llpredicate.cpp
@@ -0,0 +1,33 @@
+/** 
+ * @file llpredicate.cpp
+ * @brief abstraction for filtering objects by predicates, with arbitrary boolean expressions
+ *
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+#include "linden_common.h"
+
+#include "llpredicate.h"
+
+namespace LLPredicate
+{
+	EmptyRule make_rule() { return EmptyRule(); }
+}
diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h
new file mode 100644
index 0000000000..ad5ab363fa
--- /dev/null
+++ b/indra/llcommon/llpredicate.h
@@ -0,0 +1,173 @@
+/** 
+ * @file llpredicate.h
+ * @brief abstraction for filtering objects by predicates, with arbitrary boolean expressions
+ *
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPREDICATE_H
+#define LL_LLPREDICATE_H
+
+#include "llerror.h"
+
+namespace LLPredicate
+{
+	template<typename ENUM> class Rule;
+
+	template<typename ENUM>
+	struct Value
+	{
+		friend Rule<ENUM>;
+	public:
+		Value(ENUM e)
+		:	mPredicateFlags(0x1),
+			mPredicateCombinationFlags(0x1)
+		{
+			set(e);
+		}
+
+		Value()
+			:	mPredicateFlags(0x1),
+			mPredicateCombinationFlags(0x1)
+		{}
+
+		void set(ENUM predicate)
+		{
+			llassert(predicate <= 5);
+			int predicate_flag = 0x1 << (0x1 << (int)predicate);
+			if (!(mPredicateFlags & predicate_flag))
+			{
+				mPredicateCombinationFlags *= predicate_flag;
+				mPredicateFlags |= predicate_flag;
+			}
+		}
+
+		bool get(ENUM predicate)
+		{
+			int predicate_flag = 0x1 << (0x1 << (int)predicate);
+			return (mPredicateFlags & predicate_flag) != 0;
+		}
+
+		void clear(ENUM predicate)
+		{
+			llassert(predicate <= 5);
+			int predicate_flag = 0x1 << (0x1 << (int)predicate);
+			if (mPredicateFlags & predicate_flag)
+			{
+				mPredicateCombinationFlags /= predicate_flag;
+				mPredicateFlags &= ~predicate_flag;
+			}
+		}
+
+	private:
+		int mPredicateCombinationFlags;
+		int mPredicateFlags;
+	};
+
+	struct EmptyRule {};
+
+	template<typename ENUM>
+	class Rule
+	{
+	public:
+		Rule(EmptyRule e)
+			:	mPredicateRequirements(0x1)
+		{}
+
+		Rule(ENUM value)
+			:	mPredicateRequirements(predicateFromValue(value))
+		{}
+
+		Rule()
+			:	mPredicateRequirements(0x1)
+		{}
+
+		Rule operator~()
+		{
+			Rule new_rule;
+			new_rule.mPredicateRequirements = ~mPredicateRequirements;
+			return new_rule;
+		}
+
+		Rule operator &&(const Rule& other)
+		{
+			Rule new_rule;
+			new_rule.mPredicateRequirements = mPredicateRequirements & other.mPredicateRequirements;
+			return new_rule;
+		}
+
+		Rule operator ||(const Rule& other)
+		{
+			Rule new_rule;
+			new_rule.mPredicateRequirements = mPredicateRequirements | other.mPredicateRequirements;
+			return new_rule;
+		}
+
+		bool check(const Value<ENUM>& value) const
+		{
+			return ((value.mPredicateCombinationFlags | 0x1) & mPredicateRequirements) != 0;
+		}
+
+		static int predicateFromValue(ENUM value)
+		{
+			int countdown = value;
+			bool bit_val = false;
+
+			int predicate = 0x0;
+
+			for (int bit_index = 0; bit_index < 32; bit_index++)
+			{
+				if (bit_val)
+				{
+					predicate |= 0x1 << bit_index;
+				}
+
+				if (countdown-- == 0)
+				{
+					countdown = value;
+					bit_val = !bit_val;
+				}
+			}
+			return predicate;
+		}
+
+		bool isTriviallyTrue() const
+		{
+			return mPredicateRequirements & 0x1;
+		}
+
+		bool isTriviallyFalse() const
+		{
+			return mPredicateRequirements == 0;
+		}
+
+	private:
+		int mPredicateRequirements;
+	};
+
+	template<typename ENUM>
+	Rule<ENUM> make_rule(ENUM e) { return Rule<ENUM>(e);}
+
+	EmptyRule make_rule();
+
+}
+#endif // LL_LLPREDICATE_H
diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp
index 4b8a8dba5c..713f5ac605 100644
--- a/indra/llcommon/llsdparam.cpp
+++ b/indra/llcommon/llsdparam.cpp
@@ -329,7 +329,7 @@ namespace LLInitParam
 		p.writeValue<LLSD::String>(sd.asString(), name_stack);
 	}
 
-	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const
+	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block) const
 	{
 		// attempt to write LLSD out directly
 		if (!p.writeValue<LLSD>(mValue, name_stack))
-- 
cgit v1.2.3


From 50ad343366f5e18ced40e24e2a1cc2399411c7e5 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 22 Oct 2012 22:46:45 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system added return
 value to serialize function to track if any values were written

---
 indra/llcommon/llinitparam.cpp | 14 ++++---
 indra/llcommon/llinitparam.h   | 84 ++++++++++++++++++++++++++----------------
 indra/llcommon/llsdparam.cpp   |  3 +-
 3 files changed, 64 insertions(+), 37 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index 54e98e66f3..d6326a7c11 100644
--- a/indra/llcommon/llinitparam.cpp
+++ b/indra/llcommon/llinitparam.cpp
@@ -180,8 +180,9 @@ namespace LLInitParam
 		return true;
 	}
 
-	void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const
+	bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const
 	{
+		bool serialized = false;
 		// named param is one like LLView::Params::follows
 		// unnamed param is like LLView::Params::rect - implicit
 		const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
@@ -193,10 +194,10 @@ namespace LLInitParam
 			param_handle_t param_handle = (*it)->mParamHandle;
 			const Param* param = getParamFromHandle(param_handle);
 			ParamDescriptor::serialize_func_t serialize_func = (*it)->mSerializeFunc;
-			if (serialize_func)
+			if (serialize_func && param->anyProvided())
 			{
 				const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
-				serialize_func(*param, parser, name_stack, diff_param);
+				serialized |= serialize_func(*param, parser, name_stack, diff_param);
 			}
 		}
 
@@ -232,10 +233,13 @@ namespace LLInitParam
 
 				name_stack.push_back(std::make_pair(it->first, !duplicate));
 				const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
-				serialize_func(*param, parser, name_stack, diff_param);
+				serialized |= serialize_func(*param, parser, name_stack, diff_param);
 				name_stack.pop_back();
 			}
 		}
+
+		// was anything serialized in this block?
+		return serialized;
 	}
 
 	bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const
@@ -354,7 +358,7 @@ namespace LLInitParam
 	}
 
 	//static 
-	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name)
+	void BaseBlock::addParam(BlockDescriptor& block_data, ParamDescriptorPtr in_param, const char* char_name)
 	{
 		// create a copy of the param descriptor in mAllParams
 		// so other data structures can store a pointer to it
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index b7607e91b9..93e24d4040 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -32,10 +32,10 @@
 #include <boost/function.hpp>
 #include <boost/type_traits/is_convertible.hpp>
 #include <boost/unordered_map.hpp>
-#include <boost/shared_ptr.hpp>
 
 #include "llerror.h"
 #include "llstl.h"
+#include "llmemory.h"
 
 namespace LLInitParam
 {
@@ -303,7 +303,7 @@ namespace LLInitParam
 
 		typedef bool(*merge_func_t)(Param&, const Param&, bool);
 		typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, bool);
-		typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param);
+		typedef bool(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param);
 		typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count);
 		typedef bool(*validation_func_t)(const Param*);
 
@@ -331,7 +331,7 @@ namespace LLInitParam
 		UserData*			mUserData;
 	};
 
-	typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr;
+	typedef ParamDescriptor* ParamDescriptorPtr;
 
 	// each derived Block class keeps a static data structure maintaining offsets to various params
 	class LL_COMMON_API BlockDescriptor
@@ -510,7 +510,7 @@ namespace LLInitParam
 		virtual void paramChanged(const Param& changed_param, bool user_provided) {}
 
 		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
-		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
+		bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
 		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const;
 
 		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
@@ -870,10 +870,11 @@ namespace LLInitParam
 			return false;
 		}
 
-		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+		static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
 		{
+			bool serialized = false;
 			const self_t& typed_param = static_cast<const self_t&>(param);
-			if (!typed_param.isProvided()) return;
+			if (!typed_param.isProvided()) return false;
 
 			if (!name_stack.empty())
 			{
@@ -888,21 +889,23 @@ namespace LLInitParam
 			{
 				if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))
 				{
-					parser.writeValue(key, name_stack);
+					serialized = parser.writeValue(key, name_stack);
 				}
 			}
 			// then try to serialize value directly
 			else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), static_cast<const self_t*>(diff_param)->getValue()))
 			{
-				if (!parser.writeValue(typed_param.getValue(), name_stack)) 
+				serialized = parser.writeValue(typed_param.getValue(), name_stack);
+				if (!serialized) 
 				{
 					std::string calculated_key = typed_param.calcValueName(typed_param.getValue());
 					if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key))
 					{
-						parser.writeValue(calculated_key, name_stack);
+						serialized = parser.writeValue(calculated_key, name_stack);
 					}
 				}
 			}
+			return serialized;
 		}
 
 		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
@@ -1014,10 +1017,10 @@ namespace LLInitParam
 			return false;
 		}
 
-		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+		static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
 		{
 			const self_t& typed_param = static_cast<const self_t&>(param);
-			if (!typed_param.isProvided()) return;
+			if (!typed_param.isProvided()) return false;
 
 			if (!name_stack.empty())
 			{
@@ -1027,15 +1030,17 @@ namespace LLInitParam
 			std::string key = typed_param.getValueName();
 			if (!key.empty())
 			{
-				if (!parser.writeValue(key, name_stack))
+				if (parser.writeValue(key, name_stack))
 				{
-					return;
+					return true;
 				}
 			}
 			else
 			{
-				typed_param.serializeBlock(parser, name_stack, static_cast<const self_t*>(diff_param));
+				return typed_param.serializeBlock(parser, name_stack, static_cast<const self_t*>(diff_param));
 			}
+			
+			return false;
 		}
 
 		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
@@ -1197,10 +1202,11 @@ namespace LLInitParam
 			return false;
 		}
 
-		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+		static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
 		{
+			bool serialized = false;
 			const self_t& typed_param = static_cast<const self_t&>(param);
-			if (!typed_param.isProvided()) return;
+			if (!typed_param.isProvided()) return false;
 
 			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
 				it != end_it;
@@ -1216,7 +1222,11 @@ namespace LLInitParam
 					if (!value_written)
 					{
 						std::string calculated_key = it->calcValueName(it->getValue());
-						if (!parser.writeValue(calculated_key, name_stack))
+						if (parser.writeValue(calculated_key, name_stack))
+						{
+							serialized = true;
+						}
+						else
 						{
 							break;
 						}
@@ -1224,7 +1234,11 @@ namespace LLInitParam
 				}
 				else 
 				{
-					if(!parser.writeValue(key, name_stack))
+					if(parser.writeValue(key, name_stack))
+					{
+						serialized = true;
+					}
+					else
 					{
 						break;
 					}
@@ -1232,6 +1246,7 @@ namespace LLInitParam
 
 				name_stack.pop_back();
 			}
+			return serialized;
 		}
 
 		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
@@ -1420,10 +1435,11 @@ namespace LLInitParam
 			return false;
 		}
 
-		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+		static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
 		{
+			bool serialized = false;
 			const self_t& typed_param = static_cast<const self_t&>(param);
-			if (!typed_param.isProvided()) return;
+			if (!typed_param.isProvided()) return false;
 
 			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
 				it != end_it;
@@ -1434,17 +1450,18 @@ namespace LLInitParam
 				std::string key = it->getValueName();
 				if (!key.empty())
 				{
-					parser.writeValue(key, name_stack);
+					serialized |= parser.writeValue(key, name_stack);
 				}
 				// Not parsed via named values, write out value directly
 				// NOTE: currently we don't worry about removing default values in Multiple
 				else 
 				{
-					it->serializeBlock(parser, name_stack, NULL);
+					serialized = it->serializeBlock(parser, name_stack, NULL);
 				}
 
 				name_stack.pop_back();
 			}
+			return serialized;
 		}
 
 		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
@@ -2033,11 +2050,11 @@ namespace LLInitParam
 			return mValue.get().deserializeBlock(p, name_stack_range, new_name);
 		}
 
-		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const
+		bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const
 		{
-			if (mValue.empty()) return;
+			if (mValue.empty()) return false;
 			
-			mValue.get().serializeBlock(p, name_stack, diff_block);
+			return mValue.get().serializeBlock(p, name_stack, diff_block);
 		}
 
 		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
@@ -2085,7 +2102,7 @@ namespace LLInitParam
 
 		// block param interface
 		LL_COMMON_API bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
-		LL_COMMON_API void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
+		LL_COMMON_API bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
 		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
 		{
 			//TODO: implement LLSD params as schema type Any
@@ -2148,7 +2165,7 @@ namespace LLInitParam
 			return typed_param.BaseBlock::deserializeBlock(parser, name_stack_range, new_name);
 		}
 
-		void serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const
+		bool serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const
 		{
 			const derived_t& typed_param = static_cast<const derived_t&>(*this);
 			const derived_t* diff_param = static_cast<const derived_t*>(diff_block);
@@ -2160,14 +2177,18 @@ namespace LLInitParam
 			{
 				if (!diff_param || !ParamCompare<std::string>::equals(diff_param->getValueName(), key))
 				{
-					parser.writeValue(key, name_stack);
+					return parser.writeValue(key, name_stack);
 				}
 			}
 			// then try to serialize value directly
 			else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue()))
             {
 				
-				if (!parser.writeValue(typed_param.getValue(), name_stack)) 
+				if (parser.writeValue(typed_param.getValue(), name_stack)) 
+				{
+					return true;
+				}
+				else
 				{
 					//RN: *always* serialize provided components of BlockValue (don't pass diff_param on),
 					// since these tend to be viewed as the constructor arguments for the value T.  It seems
@@ -2184,14 +2205,15 @@ namespace LLInitParam
 						// and serialize those params
 						derived_t copy(typed_param);
 						copy.updateBlockFromValue(true);
-						copy.block_t::serializeBlock(parser, name_stack, NULL);
+						return copy.block_t::serializeBlock(parser, name_stack, NULL);
 					}
 					else
 					{
-						block_t::serializeBlock(parser, name_stack, NULL);
+						return block_t::serializeBlock(parser, name_stack, NULL);
 					}
 				}
 			}
+			return false;
 		}
 
 		bool inspectBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp
index 4b8a8dba5c..e25a966609 100644
--- a/indra/llcommon/llsdparam.cpp
+++ b/indra/llcommon/llsdparam.cpp
@@ -329,7 +329,7 @@ namespace LLInitParam
 		p.writeValue<LLSD::String>(sd.asString(), name_stack);
 	}
 
-	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const
+	bool ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const
 	{
 		// attempt to write LLSD out directly
 		if (!p.writeValue<LLSD>(mValue, name_stack))
@@ -337,5 +337,6 @@ namespace LLInitParam
 			// otherwise read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
 			LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack);
 		}
+		return true;
 	}
 }
-- 
cgit v1.2.3


From 638a16eedd12fe03b85703fb821bc05f40aab355 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 23 Oct 2012 22:35:47 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system improved
 predicate system, added uncertain/unknown predicates

---
 indra/llcommon/llinitparam.cpp |  2 +-
 indra/llcommon/llinitparam.h   | 69 +++++++++++++++++++++++++++++++---------
 indra/llcommon/llpredicate.h   | 71 ++++++++++++++++++++----------------------
 3 files changed, 88 insertions(+), 54 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index b4dcf3493c..69f97e87c4 100644
--- a/indra/llcommon/llinitparam.cpp
+++ b/indra/llcommon/llinitparam.cpp
@@ -185,7 +185,7 @@ namespace LLInitParam
 		return mValidated;
 	}
 
-	bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const
+	bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const LLInitParam::BaseBlock* diff_block) const
 	{
 		bool serialized = false;
 		if (!isProvided())
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index d3a0438d93..a3a5b3dc37 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -914,14 +914,15 @@ namespace LLInitParam
 			LLPredicate::Value<ESerializePredicates> predicate;
 			if (!diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()))
 			{
-				predicate.set(NON_DEFAULT);
+				predicate.add(NON_DEFAULT);
 			}
+			predicate.unknown(REQUIRED);
 			if (typed_param.isValid())
 			{
-				predicate.set(VALID);
+				predicate.add(VALID);
 				if (typed_param.anyProvided())
 				{
-					predicate.set(PROVIDED);
+					predicate.add(PROVIDED);
 				}
 			}
 
@@ -1071,19 +1072,17 @@ namespace LLInitParam
 		static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
 		{
 			const self_t& typed_param = static_cast<const self_t&>(param);
-			const self_t* diff_typed_param = static_cast<const self_t*>(diff_param);
 
 			LLPredicate::Value<ESerializePredicates> predicate;
-			if (!diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()))
-			{
-				predicate.set(NON_DEFAULT);
-			}
+			predicate.unknown(NON_DEFAULT);
+			predicate.unknown(REQUIRED);
+
 			if (typed_param.isValid())
 			{
-				predicate.set(VALID);
+				predicate.add(VALID);
 				if (typed_param.anyProvided())
 				{
-					predicate.set(PROVIDED);
+					predicate.add(PROVIDED);
 				}
 			}
 
@@ -1271,7 +1270,29 @@ namespace LLInitParam
 		{
 			bool serialized = false;
 			const self_t& typed_param = static_cast<const self_t&>(param);
-			if (!typed_param.isProvided()) return false;
+			
+			LLPredicate::Value<ESerializePredicates> predicate;
+			predicate.unknown(NON_DEFAULT);
+
+			if (typed_param.mMinCount > 0)
+			{
+				predicate.add(REQUIRED);
+			}
+			else
+			{
+				predicate.unknown(REQUIRED);
+			}
+
+			if (typed_param.isValid())
+			{
+				predicate.add(VALID);
+				if (typed_param.anyProvided())
+				{
+					predicate.add(PROVIDED);
+				}
+			}
+
+			if (!predicate_rule.check(predicate)) return false;
 
 			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
 				it != end_it;
@@ -1516,10 +1537,28 @@ namespace LLInitParam
 			bool serialized = false;
 			const self_t& typed_param = static_cast<const self_t&>(param);
 
-			LLPredicate::Value<ESerializePredicates> predicate_value;
-			if (typed_param.isProvided()) predicate_value.set(PROVIDED);
-			
-			if (!typed_param.isProvided()) return false;
+			LLPredicate::Value<ESerializePredicates> predicate;
+			predicate.unknown(NON_DEFAULT);
+
+			if (typed_param.mMinCount > 0)
+			{
+				predicate.add(REQUIRED);
+			}
+			else
+			{
+				predicate.unknown(REQUIRED);
+			}
+
+			if (typed_param.isValid())
+			{
+				predicate.add(VALID);
+				if (typed_param.anyProvided())
+				{
+					predicate.add(PROVIDED);
+				}
+			}
+
+			if (!predicate_rule.check(predicate)) return false;
 
 			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
 				it != end_it;
diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h
index ad5ab363fa..35ef22138c 100644
--- a/indra/llcommon/llpredicate.h
+++ b/indra/llcommon/llpredicate.h
@@ -42,34 +42,28 @@ namespace LLPredicate
 		:	mPredicateFlags(0x1),
 			mPredicateCombinationFlags(0x1)
 		{
-			set(e);
+			add(e);
 		}
 
 		Value()
-			:	mPredicateFlags(0x1),
+		:	mPredicateFlags(0x1),
 			mPredicateCombinationFlags(0x1)
 		{}
 
-		void set(ENUM predicate)
+		void add(ENUM predicate)
 		{
-			llassert(predicate <= 5);
-			int predicate_flag = 0x1 << (0x1 << (int)predicate);
-			if (!(mPredicateFlags & predicate_flag))
+			llassert(predicate < 5);
+			if (!has(predicate))
 			{
+				int predicate_flag = 0x1 << (0x1 << (int)predicate);
 				mPredicateCombinationFlags *= predicate_flag;
 				mPredicateFlags |= predicate_flag;
 			}
 		}
 
-		bool get(ENUM predicate)
-		{
-			int predicate_flag = 0x1 << (0x1 << (int)predicate);
-			return (mPredicateFlags & predicate_flag) != 0;
-		}
-
-		void clear(ENUM predicate)
+		void remove(ENUM predicate)
 		{
-			llassert(predicate <= 5);
+			llassert(predicate < 5);
 			int predicate_flag = 0x1 << (0x1 << (int)predicate);
 			if (mPredicateFlags & predicate_flag)
 			{
@@ -78,6 +72,19 @@ namespace LLPredicate
 			}
 		}
 
+		void unknown(ENUM predicate)
+		{
+			add(predicate);
+			int predicate_shift = 0x1 << (int)predicate;
+			mPredicateCombinationFlags |= mPredicateCombinationFlags << predicate_shift;
+		}
+
+		bool has(ENUM predicate)
+		{
+			int predicate_flag = 0x1 << (0x1 << (int)predicate);
+			return (mPredicateFlags & predicate_flag) != 0;
+		}
+
 	private:
 		int mPredicateCombinationFlags;
 		int mPredicateFlags;
@@ -89,16 +96,12 @@ namespace LLPredicate
 	class Rule
 	{
 	public:
-		Rule(EmptyRule e)
-			:	mPredicateRequirements(0x1)
-		{}
-
 		Rule(ENUM value)
-			:	mPredicateRequirements(predicateFromValue(value))
+		:	mPredicateRequirements(predicateFromValue(value))
 		{}
 
 		Rule()
-			:	mPredicateRequirements(0x1)
+		:	mPredicateRequirements(0x1)
 		{}
 
 		Rule operator~()
@@ -129,25 +132,16 @@ namespace LLPredicate
 
 		static int predicateFromValue(ENUM value)
 		{
-			int countdown = value;
-			bool bit_val = false;
-
-			int predicate = 0x0;
-
-			for (int bit_index = 0; bit_index < 32; bit_index++)
+			llassert(value < 5);
+			static const int predicates[5] = 
 			{
-				if (bit_val)
-				{
-					predicate |= 0x1 << bit_index;
-				}
-
-				if (countdown-- == 0)
-				{
-					countdown = value;
-					bit_val = !bit_val;
-				}
-			}
-			return predicate;
+				0xAAAAaaaa, //  10101010101010101010101010101010
+				0xCCCCcccc, //  11001100110011001100110011001100
+				0xF0F0F0F0, //  11110000111100001111000011110000
+				0xFF00FF00, //  11111111000000001111111100000000
+				0xFFFF0000  //  11111111111111110000000000000000 
+			};
+			return predicates[value];
 		}
 
 		bool isTriviallyTrue() const
@@ -167,6 +161,7 @@ namespace LLPredicate
 	template<typename ENUM>
 	Rule<ENUM> make_rule(ENUM e) { return Rule<ENUM>(e);}
 
+	// return generic empty rule class to avoid requiring template argument to create an empty rule
 	EmptyRule make_rule();
 
 }
-- 
cgit v1.2.3


From 28179ab0070a1c13193808bc1493761a8fed167f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 23 Oct 2012 23:12:33 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system cleaned up
 predicate system, made unknown work with remove

---
 indra/llcommon/llpredicate.cpp | 14 +++++++++++
 indra/llcommon/llpredicate.h   | 55 +++++++++++++++++-------------------------
 2 files changed, 36 insertions(+), 33 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llpredicate.cpp b/indra/llcommon/llpredicate.cpp
index 8dcd9247b7..1ab1ab08f1 100644
--- a/indra/llcommon/llpredicate.cpp
+++ b/indra/llcommon/llpredicate.cpp
@@ -30,4 +30,18 @@
 namespace LLPredicate
 {
 	EmptyRule make_rule() { return EmptyRule(); }
+
+	int predicateFlagsFromValue(int value)
+	{
+		llassert(value < 5);
+		static const int predicates[5] = 
+		{
+			0xAAAAaaaa, //  10101010101010101010101010101010
+			0xCCCCcccc, //  11001100110011001100110011001100
+			0xF0F0F0F0, //  11110000111100001111000011110000
+			0xFF00FF00, //  11111111000000001111111100000000
+			0xFFFF0000  //  11111111111111110000000000000000 
+		};
+		return predicates[value];
+	}
 }
diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h
index 35ef22138c..096238713c 100644
--- a/indra/llcommon/llpredicate.h
+++ b/indra/llcommon/llpredicate.h
@@ -33,21 +33,21 @@ namespace LLPredicate
 {
 	template<typename ENUM> class Rule;
 
+	int predicateFlagsFromValue(int value);
+
 	template<typename ENUM>
 	struct Value
 	{
 		friend Rule<ENUM>;
 	public:
 		Value(ENUM e)
-		:	mPredicateFlags(0x1),
-			mPredicateCombinationFlags(0x1)
+		:	mPredicateCombinationFlags(0x1)
 		{
 			add(e);
 		}
 
 		Value()
-		:	mPredicateFlags(0x1),
-			mPredicateCombinationFlags(0x1)
+		:	mPredicateCombinationFlags(0x1)
 		{}
 
 		void add(ENUM predicate)
@@ -55,39 +55,42 @@ namespace LLPredicate
 			llassert(predicate < 5);
 			if (!has(predicate))
 			{
-				int predicate_flag = 0x1 << (0x1 << (int)predicate);
-				mPredicateCombinationFlags *= predicate_flag;
-				mPredicateFlags |= predicate_flag;
+				int predicate_shift = 0x1 << (int)predicate;
+				mPredicateCombinationFlags <<= predicate_shift;
 			}
 		}
 
 		void remove(ENUM predicate)
 		{
 			llassert(predicate < 5);
-			int predicate_flag = 0x1 << (0x1 << (int)predicate);
-			if (mPredicateFlags & predicate_flag)
-			{
-				mPredicateCombinationFlags /= predicate_flag;
-				mPredicateFlags &= ~predicate_flag;
-			}
+			int predicate_shift = 0x1 << (int)predicate;
+			int flag_mask = predicateFlagsFromValue(predicate);
+			int flags_to_modify = mPredicateCombinationFlags & flag_mask;
+			// clear flags containing predicate to be removed
+			mPredicateCombinationFlags &= ~flag_mask;
+			// shift flags, in effect removing predicate
+			flags_to_modify >>= predicate_shift;
+			// put modified flags back
+			mPredicateCombinationFlags |= flags_to_modify;
 		}
 
 		void unknown(ENUM predicate)
 		{
 			add(predicate);
-			int predicate_shift = 0x1 << (int)predicate;
-			mPredicateCombinationFlags |= mPredicateCombinationFlags << predicate_shift;
+			int flags_with_predicate = mPredicateCombinationFlags;
+			remove(predicate);
+			// unknown is result of adding and removing predicate at the same time!
+			mPredicateCombinationFlags |= flags_with_predicate;
 		}
 
 		bool has(ENUM predicate)
 		{
-			int predicate_flag = 0x1 << (0x1 << (int)predicate);
-			return (mPredicateFlags & predicate_flag) != 0;
+			int flag_mask = predicateFlagsFromValue(predicate);
+			return (mPredicateCombinationFlags & flag_mask) != 0;
 		}
 
 	private:
 		int mPredicateCombinationFlags;
-		int mPredicateFlags;
 	};
 
 	struct EmptyRule {};
@@ -97,7 +100,7 @@ namespace LLPredicate
 	{
 	public:
 		Rule(ENUM value)
-		:	mPredicateRequirements(predicateFromValue(value))
+		:	mPredicateRequirements(predicateFlagsFromValue(value))
 		{}
 
 		Rule()
@@ -130,20 +133,6 @@ namespace LLPredicate
 			return ((value.mPredicateCombinationFlags | 0x1) & mPredicateRequirements) != 0;
 		}
 
-		static int predicateFromValue(ENUM value)
-		{
-			llassert(value < 5);
-			static const int predicates[5] = 
-			{
-				0xAAAAaaaa, //  10101010101010101010101010101010
-				0xCCCCcccc, //  11001100110011001100110011001100
-				0xF0F0F0F0, //  11110000111100001111000011110000
-				0xFF00FF00, //  11111111000000001111111100000000
-				0xFFFF0000  //  11111111111111110000000000000000 
-			};
-			return predicates[value];
-		}
-
 		bool isTriviallyTrue() const
 		{
 			return mPredicateRequirements & 0x1;
-- 
cgit v1.2.3


From 1de6ecb23851e0784016a2c4c9f691c976c6bda7 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 23 Oct 2012 23:35:15 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system converted "int"
 to "S32"

---
 indra/llcommon/llpredicate.cpp |  4 ++--
 indra/llcommon/llpredicate.h   | 34 +++++++++++++++++++---------------
 2 files changed, 21 insertions(+), 17 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llpredicate.cpp b/indra/llcommon/llpredicate.cpp
index 1ab1ab08f1..e3410ef3f6 100644
--- a/indra/llcommon/llpredicate.cpp
+++ b/indra/llcommon/llpredicate.cpp
@@ -31,10 +31,10 @@ namespace LLPredicate
 {
 	EmptyRule make_rule() { return EmptyRule(); }
 
-	int predicateFlagsFromValue(int value)
+	S32 predicateFlagsFromValue(S32 value)
 	{
 		llassert(value < 5);
-		static const int predicates[5] = 
+		static const S32 predicates[5] = 
 		{
 			0xAAAAaaaa, //  10101010101010101010101010101010
 			0xCCCCcccc, //  11001100110011001100110011001100
diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h
index 096238713c..5fd1d30295 100644
--- a/indra/llcommon/llpredicate.h
+++ b/indra/llcommon/llpredicate.h
@@ -33,7 +33,7 @@ namespace LLPredicate
 {
 	template<typename ENUM> class Rule;
 
-	int predicateFlagsFromValue(int value);
+	S32 predicateFlagsFromValue(S32 value);
 
 	template<typename ENUM>
 	struct Value
@@ -41,31 +41,35 @@ namespace LLPredicate
 		friend Rule<ENUM>;
 	public:
 		Value(ENUM e)
-		:	mPredicateCombinationFlags(0x1)
+		:	mPredicateCombinationFlags(0xFFFFffff)
 		{
 			add(e);
 		}
 
 		Value()
-		:	mPredicateCombinationFlags(0x1)
+		:	mPredicateCombinationFlags(0xFFFFffff)
 		{}
 
 		void add(ENUM predicate)
 		{
 			llassert(predicate < 5);
-			if (!has(predicate))
-			{
-				int predicate_shift = 0x1 << (int)predicate;
-				mPredicateCombinationFlags <<= predicate_shift;
-			}
+			S32 predicate_shift = 0x1 << (S32)predicate;
+			S32 flag_mask = predicateFlagsFromValue(predicate);
+			S32 flags_to_modify = mPredicateCombinationFlags & ~flag_mask;
+			// clear flags containing predicate to be removed
+			mPredicateCombinationFlags &= ~flag_mask;
+			// shift flags, in effect removing predicate
+			flags_to_modify <<= predicate_shift;
+			// put modified flags back
+			mPredicateCombinationFlags |= flags_to_modify;
 		}
 
 		void remove(ENUM predicate)
 		{
 			llassert(predicate < 5);
-			int predicate_shift = 0x1 << (int)predicate;
-			int flag_mask = predicateFlagsFromValue(predicate);
-			int flags_to_modify = mPredicateCombinationFlags & flag_mask;
+			S32 predicate_shift = 0x1 << (S32)predicate;
+			S32 flag_mask = predicateFlagsFromValue(predicate);
+			S32 flags_to_modify = mPredicateCombinationFlags & flag_mask;
 			// clear flags containing predicate to be removed
 			mPredicateCombinationFlags &= ~flag_mask;
 			// shift flags, in effect removing predicate
@@ -77,7 +81,7 @@ namespace LLPredicate
 		void unknown(ENUM predicate)
 		{
 			add(predicate);
-			int flags_with_predicate = mPredicateCombinationFlags;
+			S32 flags_with_predicate = mPredicateCombinationFlags;
 			remove(predicate);
 			// unknown is result of adding and removing predicate at the same time!
 			mPredicateCombinationFlags |= flags_with_predicate;
@@ -85,12 +89,12 @@ namespace LLPredicate
 
 		bool has(ENUM predicate)
 		{
-			int flag_mask = predicateFlagsFromValue(predicate);
+			S32 flag_mask = predicateFlagsFromValue(predicate);
 			return (mPredicateCombinationFlags & flag_mask) != 0;
 		}
 
 	private:
-		int mPredicateCombinationFlags;
+		S32 mPredicateCombinationFlags;
 	};
 
 	struct EmptyRule {};
@@ -144,7 +148,7 @@ namespace LLPredicate
 		}
 
 	private:
-		int mPredicateRequirements;
+		S32 mPredicateRequirements;
 	};
 
 	template<typename ENUM>
-- 
cgit v1.2.3


From 7f97aa2d5db0d1429136a40d04d2e4428cb184fe Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 25 Oct 2012 17:30:03 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system fixed crash on
 exit

---
 indra/llcommon/llinitparam.h | 13 -------------
 1 file changed, 13 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index a3a5b3dc37..9530e562f6 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -916,7 +916,6 @@ namespace LLInitParam
 			{
 				predicate.add(NON_DEFAULT);
 			}
-			predicate.unknown(REQUIRED);
 			if (typed_param.isValid())
 			{
 				predicate.add(VALID);
@@ -1074,8 +1073,6 @@ namespace LLInitParam
 			const self_t& typed_param = static_cast<const self_t&>(param);
 
 			LLPredicate::Value<ESerializePredicates> predicate;
-			predicate.unknown(NON_DEFAULT);
-			predicate.unknown(REQUIRED);
 
 			if (typed_param.isValid())
 			{
@@ -1272,16 +1269,11 @@ namespace LLInitParam
 			const self_t& typed_param = static_cast<const self_t&>(param);
 			
 			LLPredicate::Value<ESerializePredicates> predicate;
-			predicate.unknown(NON_DEFAULT);
 
 			if (typed_param.mMinCount > 0)
 			{
 				predicate.add(REQUIRED);
 			}
-			else
-			{
-				predicate.unknown(REQUIRED);
-			}
 
 			if (typed_param.isValid())
 			{
@@ -1538,16 +1530,11 @@ namespace LLInitParam
 			const self_t& typed_param = static_cast<const self_t&>(param);
 
 			LLPredicate::Value<ESerializePredicates> predicate;
-			predicate.unknown(NON_DEFAULT);
 
 			if (typed_param.mMinCount > 0)
 			{
 				predicate.add(REQUIRED);
 			}
-			else
-			{
-				predicate.unknown(REQUIRED);
-			}
 
 			if (typed_param.isValid())
 			{
-- 
cgit v1.2.3


From 3ffd0be53af0c5338e6fdc77d240e976aeb10451 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 26 Oct 2012 20:03:33 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system fixed
 llpredicate so that values and rules work uniformly with predicate logic
 and/or/negate works in parallel with set/clear

---
 indra/llcommon/llinitparam.cpp |   2 +-
 indra/llcommon/llinitparam.h   |  64 ++++++-------
 indra/llcommon/llpredicate.cpp |  22 ++---
 indra/llcommon/llpredicate.h   | 199 ++++++++++++++++++++++++++---------------
 4 files changed, 166 insertions(+), 121 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index 69f97e87c4..c66659a696 100644
--- a/indra/llcommon/llinitparam.cpp
+++ b/indra/llcommon/llinitparam.cpp
@@ -190,7 +190,7 @@ namespace LLInitParam
 		bool serialized = false;
 		if (!isProvided())
 		{
-			if ((~predicate_rule_t(PROVIDED) && predicate_rule).isTriviallyFalse())
+			if (predicate_rule_t(~ll_predicate(PROVIDED) && predicate_rule).isTriviallyFalse())
 			{
 				return false;
 			}
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index 9530e562f6..b52ac809e0 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -545,7 +545,7 @@ namespace LLInitParam
 		}
 
 		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
-		bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t rule = predicate_rule_t(), const BaseBlock* diff_block = NULL) const;
+		bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t rule = predicate_rule_t(ll_predicate(PROVIDED) && ll_predicate(NON_DEFAULT)), const BaseBlock* diff_block = NULL) const;
 		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const;
 
 		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
@@ -912,17 +912,17 @@ namespace LLInitParam
 			const self_t* diff_typed_param = static_cast<const self_t*>(diff_param);
 
 			LLPredicate::Value<ESerializePredicates> predicate;
-			if (!diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()))
+			predicate.set(NON_DEFAULT, !diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()));
+
+			if (typed_param.isValid())
 			{
-				predicate.add(NON_DEFAULT);
+				predicate.set(VALID, true);
+				predicate.set(PROVIDED, typed_param.anyProvided());
 			}
-			if (typed_param.isValid())
+			else
 			{
-				predicate.add(VALID);
-				if (typed_param.anyProvided())
-				{
-					predicate.add(PROVIDED);
-				}
+				predicate.set(VALID, false);
+				predicate.set(PROVIDED, false);
 			}
 
 			if (!predicate_rule.check(predicate)) return false;
@@ -1076,11 +1076,13 @@ namespace LLInitParam
 
 			if (typed_param.isValid())
 			{
-				predicate.add(VALID);
-				if (typed_param.anyProvided())
-				{
-					predicate.add(PROVIDED);
-				}
+				predicate.set(VALID, true);
+				predicate.set(PROVIDED, typed_param.anyProvided());
+			}
+			else
+			{
+				predicate.set(VALID, false);
+				predicate.set(PROVIDED, false);
 			}
 
 			if (!predicate_rule.check(predicate)) return false;
@@ -1270,19 +1272,18 @@ namespace LLInitParam
 			
 			LLPredicate::Value<ESerializePredicates> predicate;
 
-			if (typed_param.mMinCount > 0)
-			{
-				predicate.add(REQUIRED);
-			}
+			predicate.set(REQUIRED, typed_param.mMinCount > 0);
 
 			if (typed_param.isValid())
 			{
-				predicate.add(VALID);
-				if (typed_param.anyProvided())
-				{
-					predicate.add(PROVIDED);
-				}
+				predicate.set(VALID, true);
+				predicate.set(PROVIDED, typed_param.anyProvided());
 			}
+			else
+			{
+				predicate.set(VALID, false);
+				predicate.set(PROVIDED, false);
+			}			
 
 			if (!predicate_rule.check(predicate)) return false;
 
@@ -1531,19 +1532,18 @@ namespace LLInitParam
 
 			LLPredicate::Value<ESerializePredicates> predicate;
 
-			if (typed_param.mMinCount > 0)
-			{
-				predicate.add(REQUIRED);
-			}
+			predicate.set(REQUIRED, typed_param.mMinCount > 0);
 
 			if (typed_param.isValid())
 			{
-				predicate.add(VALID);
-				if (typed_param.anyProvided())
-				{
-					predicate.add(PROVIDED);
-				}
+				predicate.set(VALID, true);
+				predicate.set(PROVIDED, typed_param.anyProvided());
 			}
+			else
+			{
+				predicate.set(VALID, false);
+				predicate.set(PROVIDED, false);
+			}	
 
 			if (!predicate_rule.check(predicate)) return false;
 
diff --git a/indra/llcommon/llpredicate.cpp b/indra/llcommon/llpredicate.cpp
index e3410ef3f6..1278948e24 100644
--- a/indra/llcommon/llpredicate.cpp
+++ b/indra/llcommon/llpredicate.cpp
@@ -29,19 +29,13 @@
 
 namespace LLPredicate
 {
-	EmptyRule make_rule() { return EmptyRule(); }
-
-	S32 predicateFlagsFromValue(S32 value)
+	const U32 cPredicateFlagsFromEnum[5] = 
 	{
-		llassert(value < 5);
-		static const S32 predicates[5] = 
-		{
-			0xAAAAaaaa, //  10101010101010101010101010101010
-			0xCCCCcccc, //  11001100110011001100110011001100
-			0xF0F0F0F0, //  11110000111100001111000011110000
-			0xFF00FF00, //  11111111000000001111111100000000
-			0xFFFF0000  //  11111111111111110000000000000000 
-		};
-		return predicates[value];
-	}
+		0xAAAAaaaa, // 10101010101010101010101010101010
+		0xCCCCcccc, // 11001100110011001100110011001100
+		0xF0F0F0F0, // 11110000111100001111000011110000
+		0xFF00FF00, // 11111111000000001111111100000000
+		0xFFFF0000  // 11111111111111110000000000000000 
+	};
 }
+
diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h
index 5fd1d30295..3f1bf1c8e6 100644
--- a/indra/llcommon/llpredicate.h
+++ b/indra/llcommon/llpredicate.h
@@ -33,129 +33,180 @@ namespace LLPredicate
 {
 	template<typename ENUM> class Rule;
 
-	S32 predicateFlagsFromValue(S32 value);
+	extern const U32 cPredicateFlagsFromEnum[5];
 
 	template<typename ENUM>
-	struct Value
+	class Literal
 	{
 		friend Rule<ENUM>;
+
 	public:
-		Value(ENUM e)
-		:	mPredicateCombinationFlags(0xFFFFffff)
+		typedef U32 predicate_flag_t;
+		static const S32 cMaxEnum = 5;
+
+		Literal(ENUM e)
+		:	mPredicateFlags(cPredicateFlagsFromEnum[e])
 		{
-			add(e);
+			llassert(0 <= e && e < cMaxEnum);
 		}
 
-		Value()
-		:	mPredicateCombinationFlags(0xFFFFffff)
+		Literal()
+		:	mPredicateFlags(0xFFFFffff)
 		{}
 
-		void add(ENUM predicate)
+		Literal operator~()
 		{
-			llassert(predicate < 5);
-			S32 predicate_shift = 0x1 << (S32)predicate;
-			S32 flag_mask = predicateFlagsFromValue(predicate);
-			S32 flags_to_modify = mPredicateCombinationFlags & ~flag_mask;
-			// clear flags containing predicate to be removed
-			mPredicateCombinationFlags &= ~flag_mask;
-			// shift flags, in effect removing predicate
-			flags_to_modify <<= predicate_shift;
-			// put modified flags back
-			mPredicateCombinationFlags |= flags_to_modify;
+			Literal new_rule;
+			new_rule.mPredicateFlags = ~mPredicateFlags;
+			return new_rule;
 		}
 
-		void remove(ENUM predicate)
+		Literal operator &&(const Literal& other)
 		{
-			llassert(predicate < 5);
-			S32 predicate_shift = 0x1 << (S32)predicate;
-			S32 flag_mask = predicateFlagsFromValue(predicate);
-			S32 flags_to_modify = mPredicateCombinationFlags & flag_mask;
-			// clear flags containing predicate to be removed
-			mPredicateCombinationFlags &= ~flag_mask;
-			// shift flags, in effect removing predicate
-			flags_to_modify >>= predicate_shift;
-			// put modified flags back
-			mPredicateCombinationFlags |= flags_to_modify;
+			Literal new_rule;
+			new_rule.mPredicateFlags = mPredicateFlags & other.mPredicateFlags;
+			return new_rule;
 		}
 
-		void unknown(ENUM predicate)
+		Literal operator ||(const Literal& other)
 		{
-			add(predicate);
-			S32 flags_with_predicate = mPredicateCombinationFlags;
-			remove(predicate);
-			// unknown is result of adding and removing predicate at the same time!
-			mPredicateCombinationFlags |= flags_with_predicate;
+			Literal new_rule;
+			new_rule.mPredicateFlags = mPredicateFlags | other.mPredicateFlags;
+			return new_rule;
 		}
 
-		bool has(ENUM predicate)
+		void set(ENUM e, bool value)
 		{
-			S32 flag_mask = predicateFlagsFromValue(predicate);
-			return (mPredicateCombinationFlags & flag_mask) != 0;
+			llassert(0 <= e && e < cMaxEnum);
+			modifyPredicate(0x1 << (S32)e, cPredicateFlagsFromEnum[e], value);
+		}
+
+		void set(const Literal& other, bool value)
+		{
+			U32 predicate_flags = other.mPredicateFlags;
+			while(predicate_flags)
+			{
+				U32 next_flags = clearLSB(predicate_flags);
+				lsb_flag = predicate_flags ^ next_flags;
+				U32 mask = 0;
+				for (S32 i = 0; i < cMaxEnum; i++)
+				{
+					if (cPredicateFlagsFromEnum[i] & lsb_flag)
+					{
+						mask |= cPredicateFlagsFromEnum[i];
+					}
+				}
+
+				modifyPredicate(lsb_flag, mask, value);
+				
+				predicate_flags = next_flags;
+			} 
+		}
+
+		void forget(ENUM e)
+		{
+			set(e, true);
+			U32 flags_with_predicate = mPredicateFlags;
+			set(e, false);
+			// ambiguous value is result of adding and removing predicate at the same time!
+			mPredicateFlags |= flags_with_predicate;
+		}
+
+		void forget(const Literal& literal)
+		{
+			set(literal, true);
+			U32 flags_with_predicate = mPredicateFlags;
+			set(literal, false);
+			// ambiguous value is result of adding and removing predicate at the same time!
+			mPredicateFlags |= flags_with_predicate;
 		}
 
 	private:
-		S32 mPredicateCombinationFlags;
+
+		predicate_flag_t clearLSB(predicate_flag_t value)
+		{
+			return value & (value - 1);
+		}
+
+		void modifyPredicate(predicate_flag_t predicate_flag, predicate_flag_t mask, bool value)
+		{
+			llassert(clearLSB(predicate_flag) == 0);
+			predicate_flag_t flags_to_modify;
+
+			if (value)
+			{
+				flags_to_modify = (mPredicateFlags & ~mask);
+				// clear flags not containing predicate to be added
+				mPredicateFlags &= mask;
+				// shift flags, in effect adding predicate
+				flags_to_modify *= predicate_flag;
+			}
+			else
+			{
+				flags_to_modify = mPredicateFlags & mask;
+				// clear flags containing predicate to be removed
+				mPredicateFlags &= ~mask;
+				// shift flags, in effect removing predicate
+				flags_to_modify /= predicate_flag;
+			}
+			// put modified flags back
+			mPredicateFlags |= flags_to_modify;
+		}
+
+		predicate_flag_t mPredicateFlags;
 	};
 
-	struct EmptyRule {};
+	template<typename ENUM>
+	struct Value
+	:	public Literal<ENUM>
+	{
+	public:
+		Value(ENUM e)
+		:	Literal(e)
+		{}
+
+		Value()
+		{}
+	};
 
 	template<typename ENUM>
 	class Rule
+	:	public Literal<ENUM>
 	{
 	public:
 		Rule(ENUM value)
-		:	mPredicateRequirements(predicateFlagsFromValue(value))
+		:	Literal(value)
 		{}
 
-		Rule()
-		:	mPredicateRequirements(0x1)
+		Rule(const Literal other)
+		:	Literal(other)
 		{}
 
-		Rule operator~()
-		{
-			Rule new_rule;
-			new_rule.mPredicateRequirements = ~mPredicateRequirements;
-			return new_rule;
-		}
-
-		Rule operator &&(const Rule& other)
-		{
-			Rule new_rule;
-			new_rule.mPredicateRequirements = mPredicateRequirements & other.mPredicateRequirements;
-			return new_rule;
-		}
-
-		Rule operator ||(const Rule& other)
-		{
-			Rule new_rule;
-			new_rule.mPredicateRequirements = mPredicateRequirements | other.mPredicateRequirements;
-			return new_rule;
-		}
+		Rule()
+		{}
 
 		bool check(const Value<ENUM>& value) const
 		{
-			return ((value.mPredicateCombinationFlags | 0x1) & mPredicateRequirements) != 0;
+			return (value.mPredicateFlags & mPredicateFlags) != 0;
 		}
 
 		bool isTriviallyTrue() const
 		{
-			return mPredicateRequirements & 0x1;
+			return mPredicateFlags == 0xFFFFffff;
 		}
 
 		bool isTriviallyFalse() const
 		{
-			return mPredicateRequirements == 0;
+			return mPredicateFlags == 0;
 		}
-
-	private:
-		S32 mPredicateRequirements;
 	};
+}
 
-	template<typename ENUM>
-	Rule<ENUM> make_rule(ENUM e) { return Rule<ENUM>(e);}
+template<typename ENUM>
+LLPredicate::Literal<ENUM> ll_predicate(ENUM e)
+{
+	 return LLPredicate::Literal<ENUM>(e);
+}
 
-	// return generic empty rule class to avoid requiring template argument to create an empty rule
-	EmptyRule make_rule();
 
-}
 #endif // LL_LLPREDICATE_H
-- 
cgit v1.2.3


From b71e991c1860bbea0387f9434cc2b4b31a26469a Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 29 Oct 2012 18:44:37 -0700
Subject: SH-3405 WIP convert existing stats to lltrace system fixed predicate
 update logic and reduced to 2 classes

---
 indra/llcommon/llinitparam.cpp |   2 +-
 indra/llcommon/llpredicate.h   | 112 +++++++++++++++++++++++++----------------
 2 files changed, 69 insertions(+), 45 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index c66659a696..afeac0a905 100644
--- a/indra/llcommon/llinitparam.cpp
+++ b/indra/llcommon/llinitparam.cpp
@@ -190,7 +190,7 @@ namespace LLInitParam
 		bool serialized = false;
 		if (!isProvided())
 		{
-			if (predicate_rule_t(~ll_predicate(PROVIDED) && predicate_rule).isTriviallyFalse())
+			if ((predicate_rule && !ll_predicate(PROVIDED)).isTriviallyFalse())
 			{
 				return false;
 			}
diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h
index 3f1bf1c8e6..a13172da68 100644
--- a/indra/llcommon/llpredicate.h
+++ b/indra/llcommon/llpredicate.h
@@ -36,43 +36,41 @@ namespace LLPredicate
 	extern const U32 cPredicateFlagsFromEnum[5];
 
 	template<typename ENUM>
-	class Literal
+	class Value
 	{
-		friend Rule<ENUM>;
-
 	public:
 		typedef U32 predicate_flag_t;
 		static const S32 cMaxEnum = 5;
 
-		Literal(ENUM e)
+		Value(ENUM e)
 		:	mPredicateFlags(cPredicateFlagsFromEnum[e])
 		{
 			llassert(0 <= e && e < cMaxEnum);
 		}
 
-		Literal()
+		Value()
 		:	mPredicateFlags(0xFFFFffff)
 		{}
 
-		Literal operator~()
+		Value operator!() const
 		{
-			Literal new_rule;
-			new_rule.mPredicateFlags = ~mPredicateFlags;
-			return new_rule;
+			Value new_value;
+			new_value.mPredicateFlags = ~mPredicateFlags;
+			return new_value;
 		}
 
-		Literal operator &&(const Literal& other)
+		Value operator &&(const Value other) const
 		{
-			Literal new_rule;
-			new_rule.mPredicateFlags = mPredicateFlags & other.mPredicateFlags;
-			return new_rule;
+			Value new_value;
+			new_value.mPredicateFlags = mPredicateFlags & other.mPredicateFlags;
+			return new_value;
 		}
 
-		Literal operator ||(const Literal& other)
+		Value operator ||(const Value other) const
 		{
-			Literal new_rule;
-			new_rule.mPredicateFlags = mPredicateFlags | other.mPredicateFlags;
-			return new_rule;
+			Value new_value;
+			new_value.mPredicateFlags = mPredicateFlags | other.mPredicateFlags;
+			return new_value;
 		}
 
 		void set(ENUM e, bool value)
@@ -81,19 +79,21 @@ namespace LLPredicate
 			modifyPredicate(0x1 << (S32)e, cPredicateFlagsFromEnum[e], value);
 		}
 
-		void set(const Literal& other, bool value)
+		void set(const Value other, bool value)
 		{
 			U32 predicate_flags = other.mPredicateFlags;
 			while(predicate_flags)
 			{
 				U32 next_flags = clearLSB(predicate_flags);
 				lsb_flag = predicate_flags ^ next_flags;
+
 				U32 mask = 0;
 				for (S32 i = 0; i < cMaxEnum; i++)
 				{
 					if (cPredicateFlagsFromEnum[i] & lsb_flag)
 					{
 						mask |= cPredicateFlagsFromEnum[i];
+						modifyPredicate(0x1 << (0x1 << i ), cPredicateFlagsFromEnum[i], !value);
 					}
 				}
 
@@ -112,15 +112,25 @@ namespace LLPredicate
 			mPredicateFlags |= flags_with_predicate;
 		}
 
-		void forget(const Literal& literal)
+		void forget(const Value value)
 		{
-			set(literal, true);
+			set(value, true);
 			U32 flags_with_predicate = mPredicateFlags;
-			set(literal, false);
+			set(value, false);
 			// ambiguous value is result of adding and removing predicate at the same time!
 			mPredicateFlags |= flags_with_predicate;
 		}
 
+		bool allSet() const
+		{
+			return mPredicateFlags == ~0;
+		}
+
+		bool noneSet() const
+		{
+			return mPredicateFlags == 0;
+		}
+
 	private:
 
 		predicate_flag_t clearLSB(predicate_flag_t value)
@@ -156,56 +166,70 @@ namespace LLPredicate
 		predicate_flag_t mPredicateFlags;
 	};
 
-	template<typename ENUM>
-	struct Value
-	:	public Literal<ENUM>
-	{
-	public:
-		Value(ENUM e)
-		:	Literal(e)
-		{}
-
-		Value()
-		{}
-	};
-
 	template<typename ENUM>
 	class Rule
-	:	public Literal<ENUM>
 	{
 	public:
 		Rule(ENUM value)
-		:	Literal(value)
+		:	mRule(value)
+		{}
+
+		Rule(const Rule& other)
+		:	mRule(other.mRule)
 		{}
 
-		Rule(const Literal other)
-		:	Literal(other)
+		Rule(const Value<ENUM> other)
+		:	mRule(other)
 		{}
 
 		Rule()
 		{}
 
-		bool check(const Value<ENUM>& value) const
+		bool check(const Value<ENUM> value) const
 		{
-			return (value.mPredicateFlags & mPredicateFlags) != 0;
+			return !(mRule && value).noneSet();
 		}
 
 		bool isTriviallyTrue() const
 		{
-			return mPredicateFlags == 0xFFFFffff;
+			return mRule.allSet();
 		}
 
 		bool isTriviallyFalse() const
 		{
-			return mPredicateFlags == 0;
+			return mRule.noneSet();
+		}
+
+		Rule operator!() const
+		{
+			Rule new_rule;
+			new_rule.mRule = !mRule;
+			return new_rule;
 		}
+
+		Rule operator &&(const Rule other) const
+		{
+			Rule new_rule;
+			new_rule.mRule = mRule && other.mRule;
+			return new_rule;
+		}
+
+		Rule operator ||(const Rule other) const
+		{
+			Rule new_rule;
+			new_rule.mRule = mRule || other.mRule;
+			return new_rule;
+		}
+
+	private:
+		Value<ENUM> mRule;
 	};
 }
 
 template<typename ENUM>
-LLPredicate::Literal<ENUM> ll_predicate(ENUM e)
+LLPredicate::Value<ENUM> ll_predicate(ENUM e)
 {
-	 return LLPredicate::Literal<ENUM>(e);
+	 return LLPredicate::Value<ENUM>(e);
 }
 
 
-- 
cgit v1.2.3


From 819adb5eb4d7f982121f3dbd82750e05d26864d9 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 1 Nov 2012 00:26:44 -0700
Subject: SH-3405 FIX convert existing stats to lltrace system final removal of
 remaining LLStat code

---
 indra/llcommon/CMakeLists.txt                |   2 -
 indra/llcommon/llinstancetracker.h           |  10 +-
 indra/llcommon/llmetricperformancetester.cpp |   1 -
 indra/llcommon/llpredicate.h                 |   4 +
 indra/llcommon/llstat.cpp                    | 352 ---------------------------
 indra/llcommon/llstat.h                      | 103 --------
 indra/llcommon/lltrace.h                     |  90 ++++---
 indra/llcommon/lltracerecording.cpp          | 119 ++++++++-
 indra/llcommon/lltracerecording.h            | 216 +++++++++-------
 indra/llcommon/lltracethreadrecorder.cpp     |   4 +
 10 files changed, 319 insertions(+), 582 deletions(-)
 delete mode 100644 indra/llcommon/llstat.cpp
 delete mode 100644 indra/llcommon/llstat.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index d876842cf1..0f5ded86ed 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -91,7 +91,6 @@ set(llcommon_SOURCE_FILES
     llsdutil.cpp
     llsecondlifeurls.cpp
     llsingleton.cpp
-    llstat.cpp
     llstacktrace.cpp
     llstreamqueue.cpp
     llstreamtools.cpp
@@ -234,7 +233,6 @@ set(llcommon_HEADER_FILES
     llsortedvector.h
     llstack.h
     llstacktrace.h
-    llstat.h
     llstatenums.h
     llstl.h
     llstreamqueue.h
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 403df08990..3a1187a4c1 100644
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -77,8 +77,8 @@ protected:
 /// This mix-in class adds support for tracking all instances of the specified class parameter T
 /// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
 /// If KEY is not provided, then instances are stored in a simple set
-/// @NOTE: see explicit specialization below for default KEY==T* case
-template<typename T, typename KEY = T*>
+/// @NOTE: see explicit specialization below for default KEY==void case
+template<typename T, typename KEY = void>
 class LLInstanceTracker : public LLInstanceTrackerBase
 {
 	typedef LLInstanceTracker<T, KEY> MyT;
@@ -224,12 +224,12 @@ private:
 	KEY mInstanceKey;
 };
 
-/// explicit specialization for default case where KEY is T*
+/// explicit specialization for default case where KEY is void
 /// use a simple std::set<T*>
 template<typename T>
-class LLInstanceTracker<T, T*> : public LLInstanceTrackerBase
+class LLInstanceTracker<T, void> : public LLInstanceTrackerBase
 {
-	typedef LLInstanceTracker<T, T*> MyT;
+	typedef LLInstanceTracker<T, void> MyT;
 	typedef typename std::set<T*> InstanceSet;
 	struct StaticData: public StaticBase
 	{
diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp
index 41d3eb0bf3..a1b0a684c5 100644
--- a/indra/llcommon/llmetricperformancetester.cpp
+++ b/indra/llcommon/llmetricperformancetester.cpp
@@ -29,7 +29,6 @@
 #include "indra_constants.h"
 #include "llerror.h"
 #include "llsdserialize.h"
-#include "llstat.h"
 #include "lltreeiterators.h"
 #include "llmetricperformancetester.h"
 
diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h
index 3f1bf1c8e6..75744667d9 100644
--- a/indra/llcommon/llpredicate.h
+++ b/indra/llcommon/llpredicate.h
@@ -165,6 +165,10 @@ namespace LLPredicate
 		:	Literal(e)
 		{}
 
+		Value(const Literal other)
+		:	Literal(other)
+		{}
+
 		Value()
 		{}
 	};
diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp
deleted file mode 100644
index b46d2e58b2..0000000000
--- a/indra/llcommon/llstat.cpp
+++ /dev/null
@@ -1,352 +0,0 @@
-/** 
- * @file llstat.cpp
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llstat.h"
-#include "lllivefile.h"
-#include "llerrorcontrol.h"
-#include "llframetimer.h"
-#include "timing.h"
-#include "llsd.h"
-#include "llsdserialize.h"
-#include "llstl.h"
-#include "u64.h"
-
-
-// statics
-//------------------------------------------------------------------------
-LLTimer LLStat::sTimer;
-LLFrameTimer LLStat::sFrameTimer;
-
-void LLStat::reset()
-{
-	mNumValues = 0;
-	mLastValue = 0.f;
-	delete[] mBins;
-	mBins      = new ValueEntry[mNumBins];
-	mCurBin = mNumBins-1;
-	mNextBin = 0;
-}
-
-LLStat::LLStat(std::string name, BOOL use_frame_timer)
-:	LLInstanceTracker<LLStat, std::string>(name),
-	mUseFrameTimer(use_frame_timer),
-	mNumBins(50),
-	mName(name),
-	mBins(NULL)
-{
-	llassert(mNumBins > 0);
-	mLastTime  = 0.f;
-
-	reset();
-}
-
-LLStat::~LLStat()
-{
-	delete[] mBins;
-}
-//
-//void LLStat::start()
-//{
-//	if (mUseFrameTimer)
-//	{
-//		mBins[mNextBin].mBeginTime = sFrameTimer.getElapsedSeconds();
-//	}
-//	else
-//	{
-//		mBins[mNextBin].mBeginTime = sTimer.getElapsedTimeF64();
-//	}
-//}
-
-void LLStat::addValue(const F32 value)
-{
-	if (mNumValues < mNumBins)
-	{
-		mNumValues++;
-	}
-
-	// Increment the bin counters.
-	mCurBin++;
-	if (mCurBin >= mNumBins)
-	{
-		mCurBin = 0;
-	}
-	mNextBin++;
-	if (mNextBin >= mNumBins)
-	{
-		mNextBin = 0;
-	}
-
-	mBins[mCurBin].mValue = value;
-	if (mUseFrameTimer)
-	{
-		mBins[mCurBin].mTime = sFrameTimer.getElapsedSeconds();
-	}
-	else
-	{
-		mBins[mCurBin].mTime = sTimer.getElapsedTimeF64();
-	}
-	mBins[mCurBin].mDT = (F32)(mBins[mCurBin].mTime - mBins[mCurBin].mBeginTime);
-
-	//this value is used to prime the min/max calls
-	mLastTime = mBins[mCurBin].mTime;
-	mLastValue = value;
-
-	// Set the begin time for the next stat segment.
-	mBins[mNextBin].mBeginTime = mBins[mCurBin].mTime;
-	mBins[mNextBin].mTime = mBins[mCurBin].mTime;
-	mBins[mNextBin].mDT = 0.f;
-}
-
-
-F32 LLStat::getMax() const
-{
-	S32 i;
-	F32 current_max = mLastValue;
-	if (mNumBins == 0)
-	{
-		current_max = 0.f;
-	}
-	else
-	{
-		for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
-		{
-			// Skip the bin we're currently filling.
-			if (i == mNextBin)
-			{
-				continue;
-			}
-			if (mBins[i].mValue > current_max)
-			{
-				current_max = mBins[i].mValue;
-			}
-		}
-	}
-	return current_max;
-}
-
-F32 LLStat::getMean() const
-{
-	S32 i;
-	F32 current_mean = 0.f;
-	S32 samples = 0;
-	for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
-	{
-		// Skip the bin we're currently filling.
-		if (i == mNextBin)
-		{
-			continue;
-		}
-		current_mean += mBins[i].mValue;
-		samples++;
-	}
-
-	// There will be a wrap error at 2^32. :)
-	if (samples != 0)
-	{
-		current_mean /= samples;
-	}
-	else
-	{
-		current_mean = 0.f;
-	}
-	return current_mean;
-}
-
-F32 LLStat::getMin() const
-{
-	S32 i;
-	F32 current_min = mLastValue;
-
-	if (mNumBins == 0)
-	{
-		current_min = 0.f;
-	}
-	else
-	{
-		for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
-		{
-			// Skip the bin we're currently filling.
-			if (i == mNextBin)
-			{
-				continue;
-			}
-			if (mBins[i].mValue < current_min)
-			{
-				current_min = mBins[i].mValue;
-			}
-		}
-	}
-	return current_min;
-}
-
-F32 LLStat::getPrev(S32 age) const
-{
-	S32 bin;
-	bin = mCurBin - age;
-
-	while (bin < 0)
-	{
-		bin += mNumBins;
-	}
-
-	if (bin == mNextBin)
-	{
-		// Bogus for bin we're currently working on.
-		return 0.f;
-	}
-	return mBins[bin].mValue;
-}
-
-F32 LLStat::getPrevPerSec(S32 age) const
-{
-	S32 bin;
-	bin = mCurBin - age;
-
-	while (bin < 0)
-	{
-		bin += mNumBins;
-	}
-
-	if (bin == mNextBin)
-	{
-		// Bogus for bin we're currently working on.
-		return 0.f;
-	}
-	return mBins[bin].mValue / mBins[bin].mDT;
-}
-
-F32 LLStat::getCurrent() const
-{
-	return mBins[mCurBin].mValue;
-}
-
-F32 LLStat::getCurrentPerSec() const
-{
-	return mBins[mCurBin].mValue / mBins[mCurBin].mDT;
-}
-
-F32 LLStat::getMeanPerSec() const
-{
-	S32 i;
-	F32 value = 0.f;
-	F32 dt    = 0.f;
-
-	for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
-	{
-		// Skip the bin we're currently filling.
-		if (i == mNextBin)
-		{
-			continue;
-		}
-		value += mBins[i].mValue;
-		dt    += mBins[i].mDT;
-	}
-
-	if (dt > 0.f)
-	{
-		return value/dt;
-	}
-	else
-	{
-		return 0.f;
-	}
-}
-
-F32 LLStat::getMaxPerSec() const
-{
-	F32 value;
-
-	if (mNextBin != 0)
-	{
-		value = mBins[0].mValue/mBins[0].mDT;
-	}
-	else if (mNumValues > 0)
-	{
-		value = mBins[1].mValue/mBins[1].mDT;
-	}
-	else
-	{
-		value = 0.f;
-	}
-
-	for (S32 i = 0; (i < mNumBins) && (i < mNumValues); i++)
-	{
-		// Skip the bin we're currently filling.
-		if (i == mNextBin)
-		{
-			continue;
-		}
-		value = llmax(value, mBins[i].mValue/mBins[i].mDT);
-	}
-	return value;
-}
-
-F32 LLStat::getMinPerSec() const
-{
-	S32 i;
-	F32 value;
-	
-	if (mNextBin != 0)
-	{
-		value = mBins[0].mValue/mBins[0].mDT;
-	}
-	else if (mNumValues > 0)
-	{
-		value = mBins[1].mValue/mBins[0].mDT;
-	}
-	else
-	{
-		value = 0.f;
-	}
-
-	for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
-	{
-		// Skip the bin we're currently filling.
-		if (i == mNextBin)
-		{
-			continue;
-		}
-		value = llmin(value, mBins[i].mValue/mBins[i].mDT);
-	}
-	return value;
-}
-
-U32 LLStat::getNumValues() const
-{
-	return mNumValues;
-}
-
-S32 LLStat::getNumBins() const
-{
-	return mNumBins;
-}
-
-S32 LLStat::getNextBin() const
-{
-	return mNextBin;
-}
-
diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h
deleted file mode 100644
index 82a246275d..0000000000
--- a/indra/llcommon/llstat.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/** 
- * @file llstat.h
- * @brief Runtime statistics accumulation.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLSTAT_H
-#define LL_LLSTAT_H
-
-#include <map>
-
-#include "lltimer.h"
-#include "llframetimer.h"
-#include "llinstancetracker.h"
-
-class	LLSD;
-
-// ----------------------------------------------------------------------------
-class LL_COMMON_API LLStat : public LLInstanceTracker<LLStat, std::string>
-{
-public:
-	LLStat(std::string name = std::string(), BOOL use_frame_timer = FALSE);
-	~LLStat();
-
-	//void start();	// Start the timer for the current "frame", otherwise uses the time tracked from
-					// the last addValue
-	void reset();
-	void addValue(const F32 value = 1.f); // Adds the current value being tracked, and tracks the DT.
-	void addValue(const S32 value) { addValue((F32)value); }
-	void addValue(const U32 value) { addValue((F32)value); }
-
-	S32 getNextBin() const;
-	
-	F32 getPrev(S32 age) const;				// Age is how many "addValues" previously - zero is current
-	F32 getPrevPerSec(S32 age) const;		// Age is how many "addValues" previously - zero is current
-
-	F32 getCurrent() const;
-	F32 getCurrentPerSec() const;
-	
-	F32 getMin() const;
-	F32 getMinPerSec() const;
-
-	F32 getMean() const;
-	F32 getMeanPerSec() const;
-	
-	F32 getMax() const;
-	F32 getMaxPerSec() const;
-
-	U32 getNumValues() const;
-	S32 getNumBins() const;
-
-private:
-	bool mUseFrameTimer;
-	U32 mNumValues;
-	U32 mNumBins;
-	F32 mLastValue;
-	F64 mLastTime;
-
-	struct ValueEntry
-	{
-		ValueEntry()
-		:	mValue(0.f),
-			mBeginTime(0.0),
-			mTime(0.0),
-			mDT(0.f)
-		{}
-		F32 mValue;
-		F64 mBeginTime;
-		F64 mTime;
-		F32 mDT;
-	};
-	ValueEntry* mBins;
-
-	S32 mCurBin;
-	S32 mNextBin;
-	
-	std::string mName;
-
-	static LLTimer sTimer;
-	static LLFrameTimer sFrameTimer;
-};
-	
-#endif // LL_STAT_
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 2cdae4b0d2..2823db5cbb 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -227,10 +227,33 @@ namespace LLTrace
 	};
 
 
+	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
 	{
 	public:
+		typedef T value_t;
+		typedef MeasurementAccumulator<T> self_t;
+
 		MeasurementAccumulator()
 		:	mSum(0),
 			mMin(std::numeric_limits<T>::max()),
@@ -243,23 +266,24 @@ namespace LLTrace
 
 		LL_FORCE_INLINE void sample(T value)
 		{
+			T storage_value(value);
 			mNumSamples++;
-			mSum += value;
-			if (value < mMin)
+			mSum += storage_value;
+			if (storage_value < mMin)
 			{
-				mMin = value;
+				mMin = storage_value;
 			}
-			else if (value > mMax)
+			if (storage_value > mMax)
 			{
-				mMax = value;
+				mMax = storage_value;
 			}
 			F64 old_mean = mMean;
-			mMean += ((F64)value - old_mean) / (F64)mNumSamples;
-			mVarianceSum += ((F64)value - old_mean) * ((F64)value - mMean);
-			mLastValue = value;
+			mMean += ((F64)storage_value - old_mean) / (F64)mNumSamples;
+			mVarianceSum += ((F64)storage_value - old_mean) * ((F64)storage_value - mMean);
+			mLastValue = storage_value;
 		}
 
-		void addSamples(const MeasurementAccumulator<T>& other)
+		void addSamples(const self_t& other)
 		{
 			mSum += other.mSum;
 			if (other.mMin < mMin)
@@ -293,7 +317,7 @@ namespace LLTrace
 			}
 			else
 			{
-				mVarianceSum =  (F32)mNumSamples
+				mVarianceSum =  (F64)mNumSamples
 							* ((((n_1 - 1.f) * sd_1 * sd_1)
 								+ ((n_2 - 1.f) * sd_2 * sd_2)
 								+ (((n_1 * n_2) / (n_1 + n_2))
@@ -311,10 +335,10 @@ namespace LLTrace
 			mMax = 0;
 		}
 
-		T	getSum() const { return mSum; }
-		T	getMin() const { return mMin; }
-		T	getMax() const { return mMax; }
-		T	getLastValue() const { return mLastValue; }
+		T	getSum() const { return (T)mSum; }
+		T	getMin() const { return (T)mMin; }
+		T	getMax() const { return (T)mMax; }
+		T	getLastValue() const { return (T)mLastValue; }
 		F64	getMean() const { return mMean; }
 		F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mNumSamples); }
 		U32 getSampleCount() const { return mNumSamples; }
@@ -325,7 +349,7 @@ namespace LLTrace
 			mMax,
 			mLastValue;
 
-		F64 mMean,
+		F64	mMean,
 			mVarianceSum;
 
 		U32	mNumSamples;
@@ -335,6 +359,8 @@ namespace LLTrace
 	class LL_COMMON_API CountAccumulator
 	{
 	public:
+		typedef T value_t;
+
 		CountAccumulator()
 		:	mSum(0),
 			mNumSamples(0)
@@ -358,7 +384,7 @@ namespace LLTrace
 			mSum = 0;
 		}
 
-		T	getSum() const { return mSum; }
+		T	getSum() const { return (T)mSum; }
 
 	private:
 		T	mSum;
@@ -366,14 +392,15 @@ namespace LLTrace
 		U32	mNumSamples;
 	};
 
-	typedef TraceType<MeasurementAccumulator<F64> > measurement_common_t;
+	typedef TraceType<MeasurementAccumulator<F64> > measurement_common_float_t;
+	typedef TraceType<MeasurementAccumulator<S64> > measurement_common_int_t;
 
 	template <typename T = F64, typename IS_UNIT = void>
 	class LL_COMMON_API Measurement
-	:	public TraceType<MeasurementAccumulator<T> >
+	:	public TraceType<MeasurementAccumulator<typename StorageType<T>::type_t> >
 	{
 	public:
-		typedef T storage_t;
+		typedef typename StorageType<T>::type_t storage_t;
 
 		Measurement(const char* name, const char* description = NULL) 
 		:	TraceType(name, description)
@@ -381,17 +408,16 @@ namespace LLTrace
 
 		void sample(T value)
 		{
-			getPrimaryAccumulator().sample(value);
+			getPrimaryAccumulator().sample((storage_t)value);
 		}
 	};
 
 	template <typename T>
 	class LL_COMMON_API Measurement <T, typename T::is_unit_tag_t>
-	:	public TraceType<MeasurementAccumulator<typename T::storage_t> >
+	:	public TraceType<MeasurementAccumulator<typename StorageType<typename T::storage_t>::type_t> >
 	{
 	public:
-		typedef typename T::storage_t storage_t;
-		typedef Measurement<typename T::storage_t> base_measurement_t;
+		typedef typename StorageType<typename T::storage_t>::type_t storage_t;
 
 		Measurement(const char* name, const char* description = NULL) 
 		:	TraceType(name, description)
@@ -402,18 +428,19 @@ namespace LLTrace
 		{
 			T converted_value;
 			converted_value.assignFrom(value);
-			getPrimaryAccumulator().sample(converted_value.value());
+			getPrimaryAccumulator().sample((storage_t)converted_value.value());
 		}
 	};
 
-	typedef TraceType<CountAccumulator<F64> > count_common_t;
+	typedef TraceType<CountAccumulator<F64> > count_common_float_t;
+	typedef TraceType<CountAccumulator<S64> > count_common_int_t;
 
 	template <typename T = F64, typename IS_UNIT = void>
 	class LL_COMMON_API Count 
-	:	public TraceType<CountAccumulator<T> >
+	:	public TraceType<CountAccumulator<typename StorageType<T>::type_t> >
 	{
 	public:
-		typedef T storage_t;
+		typedef typename StorageType<T>::type_t storage_t;
 
 		Count(const char* name, const char* description = NULL) 
 		:	TraceType(name)
@@ -421,17 +448,16 @@ namespace LLTrace
 
 		void add(T value)
 		{
-			getPrimaryAccumulator().add(value);
+			getPrimaryAccumulator().add((storage_t)value);
 		}
 	};
 
 	template <typename T>
 	class LL_COMMON_API Count <T, typename T::is_unit_tag_t>
-	:	public TraceType<CountAccumulator<typename T::storage_t> >
+	:	public TraceType<CountAccumulator<typename StorageType<typename T::storage_t>::type_t> >
 	{
 	public:
-		typedef typename T::storage_t storage_t;
-		typedef Count<typename T::storage_t> base_count_t;
+		typedef typename StorageType<typename T::storage_t>::type_t storage_t;
 
 		Count(const char* name, const char* description = NULL) 
 		:	TraceType(name)
@@ -442,7 +468,7 @@ namespace LLTrace
 		{
 			T converted_value;
 			converted_value.assignFrom(value);
-			getPrimaryAccumulator().add(converted_value.value());
+			getPrimaryAccumulator().add((storage_t)converted_value.value());
 		}
 	};
 
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 9a769ff344..f44a0a2764 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -39,8 +39,10 @@ namespace LLTrace
 
 Recording::Recording() 
 :	mElapsedSeconds(0),
-	mCounts(new AccumulatorBuffer<CountAccumulator<F64> >()),
-	mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<F64> >()),
+	mCountsFloat(new AccumulatorBuffer<CountAccumulator<F64> >()),
+	mMeasurementsFloat(new AccumulatorBuffer<MeasurementAccumulator<F64> >()),
+	mCounts(new AccumulatorBuffer<CountAccumulator<S64> >()),
+	mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<S64> >()),
 	mStackTimers(new AccumulatorBuffer<TimerAccumulator>())
 {}
 
@@ -59,6 +61,8 @@ void Recording::update()
 
 void Recording::handleReset()
 {
+	mCountsFloat.write()->reset();
+	mMeasurementsFloat.write()->reset();
 	mCounts.write()->reset();
 	mMeasurements.write()->reset();
 	mStackTimers.write()->reset();
@@ -88,6 +92,8 @@ void Recording::handleSplitTo(Recording& other)
 
 void Recording::makePrimary()
 {
+	mCountsFloat.write()->makePrimary();
+	mMeasurementsFloat.write()->makePrimary();
 	mCounts.write()->makePrimary();
 	mMeasurements.write()->makePrimary();
 	mStackTimers.write()->makePrimary();
@@ -100,14 +106,120 @@ bool Recording::isPrimary() const
 
 void Recording::mergeRecording( const Recording& other )
 {
+	mCountsFloat.write()->addSamples(*other.mCountsFloat);
+	mMeasurementsFloat.write()->addSamples(*other.mMeasurementsFloat);
 	mCounts.write()->addSamples(*other.mCounts);
 	mMeasurements.write()->addSamples(*other.mMeasurements);
 	mStackTimers.write()->addSamples(*other.mStackTimers);
 	mElapsedSeconds += other.mElapsedSeconds;
 }
 
+F64 Recording::getSum( const TraceType<CountAccumulator<F64> >& stat ) const
+{
+	return stat.getAccumulator(mCountsFloat).getSum();
+}
+
+S64 Recording::getSum( const TraceType<CountAccumulator<S64> >& stat ) const
+{
+	return stat.getAccumulator(mCounts).getSum();
+}
+
+F64 Recording::getSum( const TraceType<MeasurementAccumulator<F64> >& stat ) const
+{
+	return (F64)stat.getAccumulator(mMeasurementsFloat).getSum();
+}
+
+S64 Recording::getSum( const TraceType<MeasurementAccumulator<S64> >& stat ) const
+{
+	return (S64)stat.getAccumulator(mMeasurements).getSum();
+}
+
+
+
+F64 Recording::getPerSec( const TraceType<CountAccumulator<F64> >& stat ) const
+{
+	return stat.getAccumulator(mCountsFloat).getSum() / mElapsedSeconds;
+}
+
+F64 Recording::getPerSec( const TraceType<CountAccumulator<S64> >& stat ) const
+{
+	return (F64)stat.getAccumulator(mCounts).getSum() / mElapsedSeconds;
+}
+
+F64 Recording::getPerSec( const TraceType<MeasurementAccumulator<F64> >& stat ) const
+{
+	return stat.getAccumulator(mMeasurementsFloat).getSum() / mElapsedSeconds;
+}
+
+F64 Recording::getPerSec( const TraceType<MeasurementAccumulator<S64> >& stat ) const
+{
+	return (F64)stat.getAccumulator(mMeasurements).getSum() / mElapsedSeconds;
+}
+
+F64 Recording::getMin( const TraceType<MeasurementAccumulator<F64> >& stat ) const
+{
+	return stat.getAccumulator(mMeasurementsFloat).getMin();
+}
+
+S64 Recording::getMin( const TraceType<MeasurementAccumulator<S64> >& stat ) const
+{
+	return stat.getAccumulator(mMeasurements).getMin();
+}
+
+F64 Recording::getMax( const TraceType<MeasurementAccumulator<F64> >& stat ) const
+{
+	return stat.getAccumulator(mMeasurementsFloat).getMax();
+}
+
+S64 Recording::getMax( const TraceType<MeasurementAccumulator<S64> >& stat ) const
+{
+	return stat.getAccumulator(mMeasurements).getMax();
+}
+
+F64 Recording::getMean( const TraceType<MeasurementAccumulator<F64> >& stat ) const
+{
+	return stat.getAccumulator(mMeasurementsFloat).getMean();
+}
+
+F64 Recording::getMean( const TraceType<MeasurementAccumulator<S64> >& stat ) const
+{
+	return stat.getAccumulator(mMeasurements).getMean();
+}
+
+F64 Recording::getStandardDeviation( const TraceType<MeasurementAccumulator<F64> >& stat ) const
+{
+	return stat.getAccumulator(mMeasurementsFloat).getStandardDeviation();
+}
+
+F64 Recording::getStandardDeviation( const TraceType<MeasurementAccumulator<S64> >& stat ) const
+{
+	return stat.getAccumulator(mMeasurements).getStandardDeviation();
+}
+
+F64 Recording::getLastValue( const TraceType<MeasurementAccumulator<F64> >& stat ) const
+{
+	return stat.getAccumulator(mMeasurementsFloat).getLastValue();
+}
+
+S64 Recording::getLastValue( const TraceType<MeasurementAccumulator<S64> >& stat ) const
+{
+	return stat.getAccumulator(mMeasurements).getLastValue();
+}
+
+U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<F64> >& stat ) const
+{
+	return stat.getAccumulator(mMeasurementsFloat).getSampleCount();
+}
+
+U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<S64> >& stat ) const
+{
+	return stat.getAccumulator(mMeasurements).getSampleCount();
+}
+
+
+
 ///////////////////////////////////////////////////////////////////////
-// Recording
+// PeriodicRecording
 ///////////////////////////////////////////////////////////////////////
 
 PeriodicRecording::PeriodicRecording( S32 num_periods ) 
@@ -179,6 +291,7 @@ void PeriodicRecording::handleSplitTo( PeriodicRecording& other )
 	getCurRecordingPeriod().handleSplitTo(other.getCurRecordingPeriod());
 }
 
+
 ///////////////////////////////////////////////////////////////////////
 // ExtendableRecording
 ///////////////////////////////////////////////////////////////////////
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index d3f001ab6a..4af973515d 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -112,124 +112,81 @@ namespace LLTrace
 		void update();
 
 		// Count accessors
+		F64 getSum(const TraceType<CountAccumulator<F64> >& stat) const;
+		S64 getSum(const TraceType<CountAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getSum(const TraceType<CountAccumulator<T> >& stat) const
+		T getSum(const Count<T, typename T::is_unit_tag_t>& stat) const
 		{
-			return (T)stat.getAccumulator(mCounts).getSum();
-		}
-
-		template <typename T, typename IS_UNIT>
-		T getSum(const Count<T, IS_UNIT>& stat) const
-		{
-			return (T)stat.getAccumulator(mCounts).getSum();
+			return (T)getSum(static_cast<const TraceType<CountAccumulator<StorageType<T>::type_t> >&> (stat));
 		}
 
+		F64 getPerSec(const TraceType<CountAccumulator<F64> >& stat) const;
+		F64 getPerSec(const TraceType<CountAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getPerSec(const TraceType<CountAccumulator<T> >& stat) const
+		T getPerSec(const Count<T, typename T::is_unit_tag_t>& stat) const
 		{
-			return (T)stat.getAccumulator(mCounts).getSum() / mElapsedSeconds;
-		}
-
-		template <typename T, typename IS_UNIT>
-		T getPerSec(const Count<T, IS_UNIT>& stat) const
-		{
-			return (T)stat.getAccumulator(mCounts).getSum() / mElapsedSeconds;
+			return (T)getPerSec(static_cast<const TraceType<CountAccumulator<StorageType<T>::type_t> >&> (stat));
 		}
 
 		// Measurement accessors
+		F64 getSum(const TraceType<MeasurementAccumulator<F64> >& stat) const;
+		S64 getSum(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getSum(const TraceType<MeasurementAccumulator<T> >& stat) const
+		T getSum(const Measurement<T, typename T::is_unit_tag_t>& stat) const
 		{
-			return (T)stat.getAccumulator(mMeasurements).getSum();
-
-		}
-
-		template <typename T, typename IS_UNIT>
-		T getSum(const Measurement<T, IS_UNIT>& stat) const
-		{
-			return (T)stat.getAccumulator(mMeasurements).getSum();
-
+			return (T)getSum(static_cast<const TraceType<MeasurementAccumulator<StorageType<T>::type_t> >&> (stat));
 		}
 
+		F64 getPerSec(const TraceType<MeasurementAccumulator<F64> >& stat) const;
+		F64 getPerSec(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getPerSec(const TraceType<MeasurementAccumulator<T> >& stat) const
-		{
-			return (T)stat.getAccumulator(mMeasurements).getSum() / mElapsedSeconds;
-		}
-
-		template <typename T, typename IS_UNIT>
-		T getPerSec(const Measurement<T, IS_UNIT>& stat) const
+		T getPerSec(const Measurement<T, typename T::is_unit_tag_t>& stat) const
 		{
-			return (typename Count<T, IS_UNIT>::base_unit_t)stat.getAccumulator(mMeasurements).getSum() / mElapsedSeconds;
+			return (T)getPerSec(static_cast<const TraceType<MeasurementAccumulator<StorageType<T>::type_t> >&> (stat));
 		}
 
+		F64 getMin(const TraceType<MeasurementAccumulator<F64> >& stat) const;
+		S64 getMin(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getMin(const TraceType<MeasurementAccumulator<T> >& stat) const
-		{
-			return (T)stat.getAccumulator(mMeasurements).getMin();
-		}
-
-		template <typename T, typename IS_UNIT>
-		T getMin(const Measurement<T, IS_UNIT>& stat) const
+		T getMin(const Measurement<T, typename T::is_unit_tag_t>& stat) const
 		{
-			return (T)stat.getAccumulator(mMeasurements).getMin();
+			return (T)getMin(static_cast<const TraceType<MeasurementAccumulator<StorageType<T>::type_t> >&> (stat));
 		}
 
-
+		F64 getMax(const TraceType<MeasurementAccumulator<F64> >& stat) const;
+		S64 getMax(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getMax(const TraceType<MeasurementAccumulator<T> >& stat) const
-		{
-			return (T)stat.getAccumulator(mMeasurements).getMax();
-		}
-
-		template <typename T, typename IS_UNIT>
-		T getMax(const Measurement<T, IS_UNIT>& stat) const
+		T getMax(const Measurement<T, typename T::is_unit_tag_t>& stat) const
 		{
-			return (T)stat.getAccumulator(mMeasurements).getMax();
+			return (T)getMax(static_cast<const TraceType<MeasurementAccumulator<StorageType<T>::type_t> >&> (stat));
 		}
 
+		F64 getMean(const TraceType<MeasurementAccumulator<F64> >& stat) const;
+		F64 getMean(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getMean(const TraceType<MeasurementAccumulator<T> >& stat) const
+		T getMean(Measurement<T, typename T::is_unit_tag_t>& stat) const
 		{
-			return (T)stat.getAccumulator(mMeasurements).getMean();
-		}
-
-		template <typename T, typename IS_UNIT>
-		T getMean(Measurement<T, IS_UNIT>& stat) const
-		{
-			return (T)stat.getAccumulator(mMeasurements).getMean();
+			return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<StorageType<T>::type_t> >&> (stat));
 		}
 
+		F64 getStandardDeviation(const TraceType<MeasurementAccumulator<F64> >& stat) const;
+		F64 getStandardDeviation(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getStandardDeviation(const TraceType<MeasurementAccumulator<T> >& stat) const
-		{
-			return (T)stat.getAccumulator(mMeasurements).getStandardDeviation();
-		}
-
-		template <typename T, typename IS_UNIT>
-		T getStandardDeviation(const Measurement<T, IS_UNIT>& stat) const
+		T getStandardDeviation(const Measurement<T, typename T::is_unit_tag_t>& stat) const
 		{
-			return (T)stat.getAccumulator(mMeasurements).getStandardDeviation();
+			return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<StorageType<T>::type_t> >&> (stat));
 		}
 
+		F64 getLastValue(const TraceType<MeasurementAccumulator<F64> >& stat) const;
+		S64 getLastValue(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getLastValue(const TraceType<MeasurementAccumulator<T> >& stat) const
-		{
-			return (T)stat.getAccumulator(mMeasurements).getLastValue();
-		}
-
-		template <typename T, typename IS_UNIT>
-		T getLastValue(const Measurement<T, IS_UNIT>& stat) const
+		T getLastValue(const Measurement<T, typename T::is_unit_tag_t>& stat) const
 		{
-			return (T)stat.getAccumulator(mMeasurements).getLastValue();
+			return (T)getLastValue(static_cast<const TraceType<MeasurementAccumulator<StorageType<T>::type_t> >&> (stat));
 		}
 
-
-		template <typename T>
-		U32 getSampleCount(const TraceType<MeasurementAccumulator<T> >& stat) const
-		{
-			return stat.getAccumulator(mMeasurements).getSampleCount();
-		}
+		U32 getSampleCount(const TraceType<MeasurementAccumulator<F64> >& stat) const;
+		U32 getSampleCount(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 
 		LLUnit::Seconds<F64> getDuration() const { return mElapsedSeconds; }
 
@@ -244,8 +201,10 @@ namespace LLTrace
 		// returns data for current thread
 		class ThreadRecorder* getThreadRecorder(); 
 
-		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<F64> > >		mCounts;
-		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > >	mMeasurements;
+		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<F64> > >		mCountsFloat;
+		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > >	mMeasurementsFloat;
+		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<S64> > >		mCounts;
+		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<S64> > >	mMeasurements;
 		LLCopyOnWritePointer<AccumulatorBuffer<TimerAccumulator> >				mStackTimers;
 
 		LLTimer			mSamplingTimer;
@@ -260,6 +219,7 @@ namespace LLTrace
 		~PeriodicRecording();
 
 		void nextPeriod();
+		S32 getNumPeriods() { return mNumPeriods; }
 
 		Recording& getLastRecordingPeriod()
 		{
@@ -268,7 +228,7 @@ namespace LLTrace
 
 		const Recording& getLastRecordingPeriod() const
 		{
-			return mRecordingPeriods[(mCurPeriod + mNumPeriods - 1) % mNumPeriods];
+			return getPrevRecordingPeriod(1);
 		}
 
 		Recording& getCurRecordingPeriod()
@@ -281,6 +241,16 @@ namespace LLTrace
 			return mRecordingPeriods[mCurPeriod];
 		}
 
+		Recording& getPrevRecordingPeriod(S32 offset)
+		{
+			return mRecordingPeriods[(mCurPeriod + mNumPeriods - offset) % mNumPeriods];
+		}
+
+		const Recording& getPrevRecordingPeriod(S32 offset) const
+		{
+			return mRecordingPeriods[(mCurPeriod + mNumPeriods - offset) % mNumPeriods];
+		}
+
 		Recording snapshotCurRecordingPeriod() const
 		{
 			Recording recording_copy(getCurRecordingPeriod());
@@ -290,6 +260,84 @@ namespace LLTrace
 
 		Recording& getTotalRecording();
 
+		template <typename T>
+		typename T getPeriodMin(const TraceType<CountAccumulator<T> >& stat) const
+		{
+			T min_val = std::numeric_limits<T>::max();
+			for (S32 i = 0; i < mNumPeriods; i++)
+			{
+				min_val = llmin(min_val, mRecordingPeriods[i].getSum(stat));
+			}
+			return (T)min_val;
+		}
+
+		template <typename T>
+		F64 getPeriodMinPerSec(const TraceType<CountAccumulator<T> >& stat) const
+		{
+			F64 min_val = std::numeric_limits<F64>::max();
+			for (S32 i = 0; i < mNumPeriods; i++)
+			{
+				min_val = llmin(min_val, mRecordingPeriods[i].getPerSec(stat));
+			}
+			return min_val;
+		}
+
+		template <typename T>
+		T getPeriodMax(const TraceType<CountAccumulator<T> >& stat) const
+		{
+			T max_val = std::numeric_limits<T>::min();
+			for (S32 i = 0; i < mNumPeriods; i++)
+			{
+				max_val = llmax(max_val, mRecordingPeriods[i].getSum(stat));
+			}
+			return max_val;
+		}
+
+		template <typename T>
+		F64 getPeriodMaxPerSec(const TraceType<CountAccumulator<T> >& stat) const
+		{
+			F64 max_val = std::numeric_limits<F64>::min();
+			for (S32 i = 0; i < mNumPeriods; i++)
+			{
+				max_val = llmax(max_val, mRecordingPeriods[i].getPerSec(stat));
+			}
+			return max_val;
+		}
+
+		template <typename T>
+		F64 getPeriodMean(const TraceType<CountAccumulator<T> >& stat) const
+		{
+			F64 mean = 0.0;
+			F64 count = 0;
+			for (S32 i = 0; i < mNumPeriods; i++)
+			{
+				if (mRecordingPeriods[i].getDuration() > 0.f)
+				{
+					count++;
+					mean += mRecordingPeriods[i].getSum(stat);
+				}
+			}
+			mean /= (F64)mNumPeriods;
+			return mean;
+		}
+
+		template <typename T>
+		F64 getPeriodMeanPerSec(const TraceType<CountAccumulator<T> >& stat) const
+		{
+			F64 mean = 0.0;
+			F64 count = 0;
+			for (S32 i = 0; i < mNumPeriods; i++)
+			{
+				if (mRecordingPeriods[i].getDuration() > 0.f)
+				{
+					count++;
+					mean += mRecordingPeriods[i].getPerSec(stat);
+				}
+			}
+			mean /= count;
+			return mean;
+		}
+
 	private:
 
 		// implementation for LLVCRControlsMixin
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index e81333f7f2..15056b80e4 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -113,9 +113,13 @@ ThreadRecorder::ActiveRecording::ActiveRecording( Recording* target )
 
 void ThreadRecorder::ActiveRecording::moveBaselineToTarget()
 {
+	mTargetRecording->mMeasurementsFloat.write()->addSamples(*mBaseline.mMeasurementsFloat);
+	mTargetRecording->mCountsFloat.write()->addSamples(*mBaseline.mCountsFloat);
 	mTargetRecording->mMeasurements.write()->addSamples(*mBaseline.mMeasurements);
 	mTargetRecording->mCounts.write()->addSamples(*mBaseline.mCounts);
 	mTargetRecording->mStackTimers.write()->addSamples(*mBaseline.mStackTimers);
+	mBaseline.mMeasurementsFloat.write()->reset();
+	mBaseline.mCountsFloat.write()->reset();
 	mBaseline.mMeasurements.write()->reset();
 	mBaseline.mCounts.write()->reset();
 	mBaseline.mStackTimers.write()->reset();
-- 
cgit v1.2.3


From 74fe126590fba03752d1d8d88dd3bb59c6900026 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 1 Nov 2012 17:52:11 -0700
Subject: SH-3405 FIX convert existing stats to lltrace system output of
 floater_stats is now identical to pre-lltrace system (with some tweaks)

---
 indra/llcommon/lltrace.h                 | 95 +++++++++++++++++---------------
 indra/llcommon/lltracerecording.cpp      | 34 +++++++++---
 indra/llcommon/lltracerecording.h        |  6 +-
 indra/llcommon/lltracethreadrecorder.cpp |  6 +-
 4 files changed, 83 insertions(+), 58 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 2823db5cbb..735c45754c 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -138,11 +138,11 @@ namespace LLTrace
 			}
 		}
 
-		void reset()
+		void reset(const AccumulatorBuffer<ACCUMULATOR>* other = NULL)
 		{
 			for (size_t i = 0; i < mNextStorageSlot; i++)
 			{
-				mStorage[i].reset();
+				mStorage[i].reset(other ? &other->mStorage[i] : NULL);
 			}
 		}
 
@@ -285,54 +285,60 @@ namespace LLTrace
 
 		void addSamples(const self_t& other)
 		{
-			mSum += other.mSum;
-			if (other.mMin < mMin)
-			{
-				mMin = other.mMin;
-			}
-			if (other.mMax > mMax)
-			{
-				mMax = other.mMax;
-			}
-			mNumSamples += other.mNumSamples;
-			F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
-			mMean = mMean * weight + other.mMean * (1.f - weight);
-
-			F64 n_1 = (F64)mNumSamples,
-				n_2 = (F64)other.mNumSamples;
-			F64 m_1 = mMean,
-				m_2 = other.mMean;
-			F64 sd_1 = getStandardDeviation(),
-				sd_2 = other.getStandardDeviation();
-			// combine variance (and hence standard deviation) of 2 different sized sample groups using
-			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
-			if (n_1 == 0)
+			if (other.mNumSamples)
 			{
-				mVarianceSum = other.mVarianceSum;
+				mSum += other.mSum;
+				if (other.mMin < mMin)
+				{
+					mMin = other.mMin;
+				}
+				if (other.mMax > mMax)
+				{
+					mMax = other.mMax;
+				}
+				F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
+				mNumSamples += other.mNumSamples;
+				mMean = mMean * weight + other.mMean * (1.f - weight);
+
+				F64 n_1 = (F64)mNumSamples,
+					n_2 = (F64)other.mNumSamples;
+				F64 m_1 = mMean,
+					m_2 = other.mMean;
+				F64 sd_1 = getStandardDeviation(),
+					sd_2 = other.getStandardDeviation();
+				// combine variance (and hence standard deviation) of 2 different sized sample groups using
+				// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+				if (n_1 == 0)
+				{
+					mVarianceSum = other.mVarianceSum;
+				}
+				else if (n_2 == 0)
+				{
+					// don't touch variance
+					// mVarianceSum = mVarianceSum;
+				}
+				else
+				{
+					mVarianceSum =  (F64)mNumSamples
+								* ((((n_1 - 1.f) * sd_1 * sd_1)
+									+ ((n_2 - 1.f) * sd_2 * sd_2)
+									+ (((n_1 * n_2) / (n_1 + n_2))
+										* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+								/ (n_1 + n_2 - 1.f));
+				}
+				mLastValue = other.mLastValue;
 			}
-			else if (n_2 == 0)
-			{
-				// don't touch variance
-				// mVarianceSum = mVarianceSum;
-			}
-			else
-			{
-				mVarianceSum =  (F64)mNumSamples
-							* ((((n_1 - 1.f) * sd_1 * sd_1)
-								+ ((n_2 - 1.f) * sd_2 * sd_2)
-								+ (((n_1 * n_2) / (n_1 + n_2))
-									* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
-							/ (n_1 + n_2 - 1.f));
-			}
-			mLastValue = other.mLastValue;
 		}
 
-		void reset()
+		void reset(const self_t* other)
 		{
 			mNumSamples = 0;
 			mSum = 0;
 			mMin = 0;
 			mMax = 0;
+			mMean = 0;
+			mVarianceSum = 0;
+			mLastValue = other ? other->mLastValue : 0;
 		}
 
 		T	getSum() const { return (T)mSum; }
@@ -359,6 +365,7 @@ namespace LLTrace
 	class LL_COMMON_API CountAccumulator
 	{
 	public:
+		typedef CountAccumulator<T> self_t;
 		typedef T value_t;
 
 		CountAccumulator()
@@ -378,7 +385,7 @@ namespace LLTrace
 			mNumSamples += other.mNumSamples;
 		}
 
-		void reset()
+		void reset(const self_t* other)
 		{
 			mNumSamples = 0;
 			mSum = 0;
@@ -475,6 +482,8 @@ namespace LLTrace
 	class LL_COMMON_API TimerAccumulator
 	{
 	public:
+		typedef TimerAccumulator self_t;
+
 		U32 							mTotalTimeCounter,
 										mChildTimeCounter,
 										mCalls;
@@ -493,7 +502,7 @@ namespace LLTrace
 			mCalls += other.mCalls;
 		}
 
-		void reset()
+		void reset(const self_t* other)
 		{
 			mTotalTimeCounter = 0;
 			mChildTimeCounter = 0;
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index f44a0a2764..a2733fd0e7 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -87,6 +87,8 @@ void Recording::handleSplitTo(Recording& other)
 {
 	stop();
 	other.restart();
+	other.mMeasurementsFloat.write()->reset(mMeasurementsFloat);
+	other.mMeasurements.write()->reset(mMeasurements);
 }
 
 
@@ -104,7 +106,7 @@ bool Recording::isPrimary() const
 	return mCounts->isPrimary();
 }
 
-void Recording::mergeRecording( const Recording& other )
+void Recording::appendRecording( const Recording& other )
 {
 	mCountsFloat.write()->addSamples(*other.mCountsFloat);
 	mMeasurementsFloat.write()->addSamples(*other.mMeasurementsFloat);
@@ -138,22 +140,34 @@ S64 Recording::getSum( const TraceType<MeasurementAccumulator<S64> >& stat ) con
 
 F64 Recording::getPerSec( const TraceType<CountAccumulator<F64> >& stat ) const
 {
-	return stat.getAccumulator(mCountsFloat).getSum() / mElapsedSeconds;
+	F64 sum = stat.getAccumulator(mCountsFloat).getSum();
+	return  (sum != 0.0) 
+		? (sum / mElapsedSeconds)
+		: 0.0;
 }
 
 F64 Recording::getPerSec( const TraceType<CountAccumulator<S64> >& stat ) const
 {
-	return (F64)stat.getAccumulator(mCounts).getSum() / mElapsedSeconds;
+	S64 sum = stat.getAccumulator(mCounts).getSum();
+	return (sum != 0) 
+		? ((F64)sum / mElapsedSeconds)
+		: 0.0;
 }
 
 F64 Recording::getPerSec( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return stat.getAccumulator(mMeasurementsFloat).getSum() / mElapsedSeconds;
+	F64 sum = stat.getAccumulator(mMeasurementsFloat).getSum();
+	return  (sum != 0.0) 
+		? (sum / mElapsedSeconds)
+		: 0.0;
 }
 
 F64 Recording::getPerSec( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (F64)stat.getAccumulator(mMeasurements).getSum() / mElapsedSeconds;
+	S64 sum = stat.getAccumulator(mMeasurements).getSum();
+	return (sum != 0) 
+		? ((F64)sum / mElapsedSeconds)
+		: 0.0;
 }
 
 F64 Recording::getMin( const TraceType<MeasurementAccumulator<F64> >& stat ) const
@@ -240,17 +254,19 @@ PeriodicRecording::~PeriodicRecording()
 void PeriodicRecording::nextPeriod()
 {
 	EPlayState play_state = getPlayState();
-	getCurRecordingPeriod().stop();
+	Recording& old_recording = getCurRecordingPeriod();
 	mCurPeriod = (mCurPeriod + 1) % mNumPeriods;
+	old_recording.splitTo(getCurRecordingPeriod());
+
 	switch(play_state)
 	{
 	case STOPPED:
+		getCurRecordingPeriod().stop();
 		break;
 	case PAUSED:
 		getCurRecordingPeriod().pause();
 		break;
 	case STARTED:
-		getCurRecordingPeriod().start();
 		break;
 	}
 	// new period, need to recalculate total
@@ -264,7 +280,7 @@ Recording& PeriodicRecording::getTotalRecording()
 		mTotalRecording.reset();
 		for (S32 i = mCurPeriod + 1; i < mCurPeriod + mNumPeriods; i++)
 		{
-			mTotalRecording.mergeRecording(mRecordingPeriods[i % mNumPeriods]);
+			mTotalRecording.appendRecording(mRecordingPeriods[i % mNumPeriods]);
 		}
 	}
 	mTotalValid = true;
@@ -298,7 +314,7 @@ void PeriodicRecording::handleSplitTo( PeriodicRecording& other )
 
 void ExtendableRecording::extend()
 {
-	mAcceptedRecording.mergeRecording(mPotentialRecording);
+	mAcceptedRecording.appendRecording(mPotentialRecording);
 	mPotentialRecording.reset();
 }
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 4af973515d..a11f04b14b 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -81,12 +81,12 @@ class LLVCRControlsMixin
 public:
 	void splitTo(DERIVED& other)
 	{
-		onSplitTo(other);
+		handleSplitTo(other);
 	}
 
 	void splitFrom(DERIVED& other)
 	{
-		other.onSplitTo(*this);
+		other.handleSplitTo(*this);
 	}
 private:
 	// atomically stop this object while starting the other
@@ -107,7 +107,7 @@ namespace LLTrace
 		void makePrimary();
 		bool isPrimary() const;
 
-		void mergeRecording(const Recording& other);
+		void appendRecording(const Recording& other);
 
 		void update();
 
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 15056b80e4..0feb3ab7af 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -73,7 +73,7 @@ std::list<ThreadRecorder::ActiveRecording>::iterator ThreadRecorder::update( Rec
 		if (next_it != mActiveRecordings.end())
 		{
 			// ...push our gathered data down to it
-			next_it->mBaseline.mergeRecording(it->mBaseline);
+			next_it->mBaseline.appendRecording(it->mBaseline);
 		}
 
 		// copy accumulated measurements into result buffer and clear accumulator (mBaseline)
@@ -153,13 +153,13 @@ void SlaveThreadRecorder::pushToMaster()
 void SlaveThreadRecorder::SharedData::copyFrom( const Recording& source )
 {
 	LLMutexLock lock(&mRecordingMutex);
-	mRecording.mergeRecording(source);
+	mRecording.appendRecording(source);
 }
 
 void SlaveThreadRecorder::SharedData::copyTo( Recording& sink )
 {
 	LLMutexLock lock(&mRecordingMutex);
-	sink.mergeRecording(mRecording);
+	sink.appendRecording(mRecording);
 }
 
 ///////////////////////////////////////////////////////////////////////
-- 
cgit v1.2.3


From bb6bda9eef48f5b08b56af46321b79fe7f1d49d7 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 1 Nov 2012 19:55:06 -0700
Subject: SH-3499  Ensure asset stats output is correct added support for
 specifying predicates for xui and llsd serialization

---
 indra/llcommon/llinitparam.cpp      | 11 ++++-------
 indra/llcommon/llinitparam.h        |  2 +-
 indra/llcommon/llpredicate.h        |  8 ++++----
 indra/llcommon/llsdparam.cpp        |  4 ++--
 indra/llcommon/llsdparam.h          |  2 +-
 indra/llcommon/lltracerecording.cpp | 12 ++++++------
 indra/llcommon/lltracerecording.h   | 22 +++++++++++-----------
 7 files changed, 29 insertions(+), 32 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index afeac0a905..53254c3b56 100644
--- a/indra/llcommon/llinitparam.cpp
+++ b/indra/llcommon/llinitparam.cpp
@@ -188,12 +188,9 @@ namespace LLInitParam
 	bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const LLInitParam::BaseBlock* diff_block) const
 	{
 		bool serialized = false;
-		if (!isProvided())
+		if (!predicate_rule.check(ll_make_predicate(PROVIDED, isProvided())))
 		{
-			if ((predicate_rule && !ll_predicate(PROVIDED)).isTriviallyFalse())
-			{
-				return false;
-			}
+			return false;
 		}
 		// named param is one like LLView::Params::follows
 		// unnamed param is like LLView::Params::rect - implicit
@@ -206,7 +203,7 @@ namespace LLInitParam
 			param_handle_t param_handle = (*it)->mParamHandle;
 			const Param* param = getParamFromHandle(param_handle);
 			ParamDescriptor::serialize_func_t serialize_func = (*it)->mSerializeFunc;
-			if (serialize_func && param->anyProvided())
+			if (serialize_func && predicate_rule.check(ll_make_predicate(PROVIDED, param->anyProvided())))
 			{
 				const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
 				serialized |= serialize_func(*param, parser, name_stack, predicate_rule, diff_param);
@@ -220,7 +217,7 @@ namespace LLInitParam
 			param_handle_t param_handle = it->second->mParamHandle;
 			const Param* param = getParamFromHandle(param_handle);
 			ParamDescriptor::serialize_func_t serialize_func = it->second->mSerializeFunc;
-			if (serialize_func && param->anyProvided())
+			if (serialize_func && predicate_rule.check(ll_make_predicate(PROVIDED, param->anyProvided())))
 			{
 				// Ensure this param has not already been serialized
 				// Prevents <rect> from being serialized as its own tag.
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index b52ac809e0..c82b1226ee 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -545,7 +545,7 @@ namespace LLInitParam
 		}
 
 		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name);
-		bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t rule = predicate_rule_t(ll_predicate(PROVIDED) && ll_predicate(NON_DEFAULT)), const BaseBlock* diff_block = NULL) const;
+		bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t rule, const BaseBlock* diff_block = NULL) const;
 		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const;
 
 		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); }
diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h
index a13172da68..3f7abe67f1 100644
--- a/indra/llcommon/llpredicate.h
+++ b/indra/llcommon/llpredicate.h
@@ -42,8 +42,8 @@ namespace LLPredicate
 		typedef U32 predicate_flag_t;
 		static const S32 cMaxEnum = 5;
 
-		Value(ENUM e)
-		:	mPredicateFlags(cPredicateFlagsFromEnum[e])
+		Value(ENUM e, bool predicate_value = true)
+		:	mPredicateFlags(predicate_value ? cPredicateFlagsFromEnum[e] : ~cPredicateFlagsFromEnum[e])
 		{
 			llassert(0 <= e && e < cMaxEnum);
 		}
@@ -227,9 +227,9 @@ namespace LLPredicate
 }
 
 template<typename ENUM>
-LLPredicate::Value<ENUM> ll_predicate(ENUM e)
+LLPredicate::Value<ENUM> ll_make_predicate(ENUM e, bool predicate_value = true)
 {
-	 return LLPredicate::Value<ENUM>(e);
+	 return LLPredicate::Value<ENUM>(e, predicate_value);
 }
 
 
diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp
index 42ecc9897d..c10e1b1e20 100644
--- a/indra/llcommon/llsdparam.cpp
+++ b/indra/llcommon/llsdparam.cpp
@@ -102,13 +102,13 @@ void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool
 	//readSDValues(sd, block);
 }
 
-void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)
+void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block, LLInitParam::predicate_rule_t rules)
 {
 	mNameStack.clear();
 	mWriteRootSD = &sd;
 
 	name_stack_t name_stack;
-	block.serializeBlock(*this, name_stack);
+	block.serializeBlock(*this, name_stack, rules);
 }
 
 /*virtual*/ std::string LLParamSDParser::getCurrentElementName()
diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h
index 6ef5debd7b..032e506fd8 100644
--- a/indra/llcommon/llsdparam.h
+++ b/indra/llcommon/llsdparam.h
@@ -50,7 +50,7 @@ typedef LLInitParam::Parser parser_t;
 public:
 	LLParamSDParser();
 	void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false);
-	void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block);
+	void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block, LLInitParam::predicate_rule_t rules = LLInitParam::predicate_rule_t(LLInitParam::PROVIDED) && LLInitParam::NON_DEFAULT);
 
 	/*virtual*/ std::string getCurrentElementName();
 
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index a2733fd0e7..a8e1a5eec9 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -347,7 +347,7 @@ PeriodicRecording& get_frame_recording()
 
 }
 
-void LLVCRControlsMixinCommon::start()
+void LLStopWatchControlsMixinCommon::start()
 {
 	switch (mPlayState)
 	{
@@ -365,7 +365,7 @@ void LLVCRControlsMixinCommon::start()
 	mPlayState = STARTED;
 }
 
-void LLVCRControlsMixinCommon::stop()
+void LLStopWatchControlsMixinCommon::stop()
 {
 	switch (mPlayState)
 	{
@@ -381,7 +381,7 @@ void LLVCRControlsMixinCommon::stop()
 	mPlayState = STOPPED;
 }
 
-void LLVCRControlsMixinCommon::pause()
+void LLStopWatchControlsMixinCommon::pause()
 {
 	switch (mPlayState)
 	{
@@ -396,7 +396,7 @@ void LLVCRControlsMixinCommon::pause()
 	mPlayState = PAUSED;
 }
 
-void LLVCRControlsMixinCommon::resume()
+void LLStopWatchControlsMixinCommon::resume()
 {
 	switch (mPlayState)
 	{
@@ -412,7 +412,7 @@ void LLVCRControlsMixinCommon::resume()
 	mPlayState = STARTED;
 }
 
-void LLVCRControlsMixinCommon::restart()
+void LLStopWatchControlsMixinCommon::restart()
 {
 	switch (mPlayState)
 	{
@@ -431,7 +431,7 @@ void LLVCRControlsMixinCommon::restart()
 	mPlayState = STARTED;
 }
 
-void LLVCRControlsMixinCommon::reset()
+void LLStopWatchControlsMixinCommon::reset()
 {
 	handleReset();
 }
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index a11f04b14b..3a786c1357 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -34,10 +34,10 @@
 #include "lltimer.h"
 #include "lltrace.h"
 
-class LL_COMMON_API LLVCRControlsMixinCommon
+class LL_COMMON_API LLStopWatchControlsMixinCommon
 {
 public:
-	virtual ~LLVCRControlsMixinCommon() {}
+	virtual ~LLStopWatchControlsMixinCommon() {}
 
 	enum EPlayState
 	{
@@ -59,7 +59,7 @@ public:
 	EPlayState getPlayState() { return mPlayState; }
 
 protected:
-	LLVCRControlsMixinCommon()
+	LLStopWatchControlsMixinCommon()
 	:	mPlayState(STOPPED)
 	{}
 
@@ -75,8 +75,8 @@ private:
 };
 
 template<typename DERIVED>
-class LLVCRControlsMixin
-:	public LLVCRControlsMixinCommon
+class LLStopWatchControlsMixin
+:	public LLStopWatchControlsMixinCommon
 {
 public:
 	void splitTo(DERIVED& other)
@@ -97,7 +97,7 @@ private:
 
 namespace LLTrace
 {
-	class LL_COMMON_API Recording : public LLVCRControlsMixin<Recording>
+	class LL_COMMON_API Recording : public LLStopWatchControlsMixin<Recording>
 	{
 	public:
 		Recording();
@@ -190,7 +190,7 @@ namespace LLTrace
 
 		LLUnit::Seconds<F64> getDuration() const { return mElapsedSeconds; }
 
-		// implementation for LLVCRControlsMixin
+		// implementation for LLStopWatchControlsMixin
 		/*virtual*/ void handleStart();
 		/*virtual*/ void handleStop();
 		/*virtual*/ void handleReset();
@@ -212,7 +212,7 @@ namespace LLTrace
 	};
 
 	class LL_COMMON_API PeriodicRecording
-	:	public LLVCRControlsMixin<PeriodicRecording>
+	:	public LLStopWatchControlsMixin<PeriodicRecording>
 	{
 	public:
 		PeriodicRecording(S32 num_periods);
@@ -340,7 +340,7 @@ namespace LLTrace
 
 	private:
 
-		// implementation for LLVCRControlsMixin
+		// implementation for LLStopWatchControlsMixin
 		/*virtual*/ void handleStart();
 		/*virtual*/ void handleStop();
 		/*virtual*/ void handleReset();
@@ -357,12 +357,12 @@ namespace LLTrace
 	PeriodicRecording& get_frame_recording();
 
 	class ExtendableRecording
-	:	public LLVCRControlsMixin<ExtendableRecording>
+	:	public LLStopWatchControlsMixin<ExtendableRecording>
 	{
 		void extend();
 
 	private:
-		// implementation for LLVCRControlsMixin
+		// implementation for LLStopWatchControlsMixin
 		/*virtual*/ void handleStart();
 		/*virtual*/ void handleStop();
 		/*virtual*/ void handleReset();
-- 
cgit v1.2.3


From f8eaee753174d0cab4e4edcf795f422706d6f302 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 2 Nov 2012 20:03:44 -0700
Subject: SH-3499  Ensure asset stats output is correct improvements to
 predicate API default rules encapsulated in LLInitParam removed empty flag
 from viewer asset stats

---
 indra/llcommon/llinitparam.cpp | 10 ++++++
 indra/llcommon/llinitparam.h   | 25 +++++++++++--
 indra/llcommon/llpredicate.h   | 80 +++++++++++++++++++++++++-----------------
 indra/llcommon/llsdparam.cpp   |  4 +--
 indra/llcommon/llsdparam.h     | 19 +++++++++-
 5 files changed, 101 insertions(+), 37 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index 53254c3b56..d20fc03227 100644
--- a/indra/llcommon/llinitparam.cpp
+++ b/indra/llcommon/llinitparam.cpp
@@ -32,6 +32,12 @@
 
 namespace LLInitParam
 {
+
+	predicate_rule_t default_parse_rules() 
+	{ 
+		return ll_make_predicate(PROVIDED) && !ll_make_predicate(EMPTY) && !ll_make_predicate(HAS_DEFAULT_VALUE); 
+	}
+
 	//
 	// Param
 	//
@@ -247,6 +253,10 @@ namespace LLInitParam
 			}
 		}
 
+		if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY)))
+		{
+			serialized |= parser.writeValue(Flag(), name_stack);
+		}
 		// was anything serialized in this block?
 		return serialized;
 	}
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index c82b1226ee..6177cc7d12 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -297,11 +297,13 @@ namespace LLInitParam
 		PROVIDED,
 		REQUIRED,
 		VALID,
-		NON_DEFAULT
+		HAS_DEFAULT_VALUE,
+		EMPTY
 	};
 
 	typedef LLPredicate::Rule<ESerializePredicates> predicate_rule_t;
 
+	predicate_rule_t default_parse_rules();
 
 	// various callbacks and constraints associated with an individual param
 	struct LL_COMMON_API ParamDescriptor
@@ -912,7 +914,10 @@ namespace LLInitParam
 			const self_t* diff_typed_param = static_cast<const self_t*>(diff_param);
 
 			LLPredicate::Value<ESerializePredicates> predicate;
-			predicate.set(NON_DEFAULT, !diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()));
+			if (diff_typed_param && ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()))
+			{
+				predicate.set(HAS_DEFAULT_VALUE);
+			}
 
 			if (typed_param.isValid())
 			{
@@ -925,6 +930,8 @@ namespace LLInitParam
 				predicate.set(PROVIDED, false);
 			}
 
+			predicate.set(EMPTY, false);
+
 			if (!predicate_rule.check(predicate)) return false;
 
 			if (!name_stack.empty())
@@ -1285,6 +1292,8 @@ namespace LLInitParam
 				predicate.set(PROVIDED, false);
 			}			
 
+			predicate.set(EMPTY, typed_param.mValues.empty());
+
 			if (!predicate_rule.check(predicate)) return false;
 
 			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
@@ -1325,6 +1334,12 @@ namespace LLInitParam
 
 				name_stack.pop_back();
 			}
+
+			if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY)))
+			{
+				serialized |= parser.writeValue(Flag(), name_stack);
+			}
+
 			return serialized;
 		}
 
@@ -1567,6 +1582,12 @@ namespace LLInitParam
 
 				name_stack.pop_back();
 			}
+
+			if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY)))
+			{
+				serialized |= parser.writeValue(Flag(), name_stack);
+			}
+
 			return serialized;
 		}
 
diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h
index 3f7abe67f1..6c9e5fc145 100644
--- a/indra/llcommon/llpredicate.h
+++ b/indra/llcommon/llpredicate.h
@@ -73,43 +73,37 @@ namespace LLPredicate
 			return new_value;
 		}
 
-		void set(ENUM e, bool value)
+		void set(ENUM e, bool value = true)
 		{
 			llassert(0 <= e && e < cMaxEnum);
-			modifyPredicate(0x1 << (S32)e, cPredicateFlagsFromEnum[e], value);
+			mPredicateFlags = modifyPredicate(0x1 << (S32)e, cPredicateFlagsFromEnum[e], value, mPredicateFlags);
 		}
 
 		void set(const Value other, bool value)
 		{
-			U32 predicate_flags = other.mPredicateFlags;
-			while(predicate_flags)
+			predicate_flag_t predicate_flags_to_set = other.mPredicateFlags;
+			predicate_flag_t cumulative_flags = 0;
+			while(predicate_flags_to_set)
 			{
-				U32 next_flags = clearLSB(predicate_flags);
-				lsb_flag = predicate_flags ^ next_flags;
+				predicate_flag_t next_flags = clearLSB(predicate_flags_to_set);
+				predicate_flag_t lsb_flag = predicate_flags_to_set ^ next_flags;
 
-				U32 mask = 0;
+				predicate_flag_t mask = 0;
+				predicate_flag_t cur_flags = mPredicateFlags;
 				for (S32 i = 0; i < cMaxEnum; i++)
 				{
 					if (cPredicateFlagsFromEnum[i] & lsb_flag)
 					{
 						mask |= cPredicateFlagsFromEnum[i];
-						modifyPredicate(0x1 << (0x1 << i ), cPredicateFlagsFromEnum[i], !value);
+						cur_flags = modifyPredicate(0x1 << (0x1 << i ), cPredicateFlagsFromEnum[i], !value, cur_flags);
 					}
 				}
 
-				modifyPredicate(lsb_flag, mask, value);
+				cumulative_flags |= modifyPredicate(lsb_flag, mask, value, cur_flags);
 				
-				predicate_flags = next_flags;
-			} 
-		}
-
-		void forget(ENUM e)
-		{
-			set(e, true);
-			U32 flags_with_predicate = mPredicateFlags;
-			set(e, false);
-			// ambiguous value is result of adding and removing predicate at the same time!
-			mPredicateFlags |= flags_with_predicate;
+				predicate_flags_to_set = next_flags;
+			}
+			mPredicateFlags = cumulative_flags;
 		}
 
 		void forget(const Value value)
@@ -131,6 +125,11 @@ namespace LLPredicate
 			return mPredicateFlags == 0;
 		}
 
+		bool someSet() const
+		{
+			return mPredicateFlags != 0;
+		}
+
 	private:
 
 		predicate_flag_t clearLSB(predicate_flag_t value)
@@ -138,16 +137,16 @@ namespace LLPredicate
 			return value & (value - 1);
 		}
 
-		void modifyPredicate(predicate_flag_t predicate_flag, predicate_flag_t mask, bool value)
+		predicate_flag_t modifyPredicate(predicate_flag_t predicate_flag, predicate_flag_t mask, predicate_flag_t value, bool set)
 		{
 			llassert(clearLSB(predicate_flag) == 0);
 			predicate_flag_t flags_to_modify;
 
-			if (value)
+			if (set)
 			{
 				flags_to_modify = (mPredicateFlags & ~mask);
 				// clear flags not containing predicate to be added
-				mPredicateFlags &= mask;
+				value &= mask;
 				// shift flags, in effect adding predicate
 				flags_to_modify *= predicate_flag;
 			}
@@ -155,12 +154,13 @@ namespace LLPredicate
 			{
 				flags_to_modify = mPredicateFlags & mask;
 				// clear flags containing predicate to be removed
-				mPredicateFlags &= ~mask;
+				value &= ~mask;
 				// shift flags, in effect removing predicate
 				flags_to_modify /= predicate_flag;
 			}
 			// put modified flags back
-			mPredicateFlags |= flags_to_modify;
+			value |= flags_to_modify;
+			return value;
 		}
 
 		predicate_flag_t mPredicateFlags;
@@ -174,10 +174,6 @@ namespace LLPredicate
 		:	mRule(value)
 		{}
 
-		Rule(const Rule& other)
-		:	mRule(other.mRule)
-		{}
-
 		Rule(const Value<ENUM> other)
 		:	mRule(other)
 		{}
@@ -185,17 +181,37 @@ namespace LLPredicate
 		Rule()
 		{}
 
+		void require(const Value<ENUM> value)
+		{
+			mRule.set(value, require);
+		}
+
+		void allow(const Value<ENUM> value)
+		{
+			mRule.forget(value);
+		}
+
 		bool check(const Value<ENUM> value) const
 		{
-			return !(mRule && value).noneSet();
+			return (mRule && value).someSet();
+		}
+
+		bool requires(const Value<ENUM> value) const
+		{
+			return (mRule && value).someSet() && (!mRule && value).noneSet();
+		}
+
+		bool isAmbivalent(const Value<ENUM> value) const
+		{
+			return (mRule && value).someSet() && (!mRule && value).someSet();
 		}
 
-		bool isTriviallyTrue() const
+		bool acceptsAll() const
 		{
 			return mRule.allSet();
 		}
 
-		bool isTriviallyFalse() const
+		bool acceptsNone() const
 		{
 			return mRule.noneSet();
 		}
diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp
index c10e1b1e20..345e30f4b4 100644
--- a/indra/llcommon/llsdparam.cpp
+++ b/indra/llcommon/llsdparam.cpp
@@ -102,13 +102,13 @@ void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool
 	//readSDValues(sd, block);
 }
 
-void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block, LLInitParam::predicate_rule_t rules)
+void LLParamSDParser::writeSDImpl(LLSD& sd, const LLInitParam::BaseBlock& block, const LLInitParam::predicate_rule_t rules, const LLInitParam::BaseBlock* diff_block)
 {
 	mNameStack.clear();
 	mWriteRootSD = &sd;
 
 	name_stack_t name_stack;
-	block.serializeBlock(*this, name_stack, rules);
+	block.serializeBlock(*this, name_stack, rules, diff_block);
 }
 
 /*virtual*/ std::string LLParamSDParser::getCurrentElementName()
diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h
index 032e506fd8..1181c2d433 100644
--- a/indra/llcommon/llsdparam.h
+++ b/indra/llcommon/llsdparam.h
@@ -50,11 +50,28 @@ typedef LLInitParam::Parser parser_t;
 public:
 	LLParamSDParser();
 	void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false);
-	void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block, LLInitParam::predicate_rule_t rules = LLInitParam::predicate_rule_t(LLInitParam::PROVIDED) && LLInitParam::NON_DEFAULT);
+	template<typename BLOCK>
+	void writeSD(LLSD& sd, 
+		const BLOCK& block, 
+		const LLInitParam::predicate_rule_t rules = LLInitParam::default_parse_rules(),
+		const LLInitParam::BaseBlock* diff_block = NULL)
+	{
+		if (!diff_block 
+			&& !rules.isAmbivalent(LLInitParam::HAS_DEFAULT_VALUE))
+		{
+			diff_block = &LLInitParam::defaultValue<BLOCK>();
+		}
+		writeSDImpl(sd, block, rules, diff_block);
+	}
 
 	/*virtual*/ std::string getCurrentElementName();
 
 private:
+	void writeSDImpl(LLSD& sd, 
+		const LLInitParam::BaseBlock& block, 
+		const LLInitParam::predicate_rule_t,
+		const LLInitParam::BaseBlock* diff_block);
+
 	void submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack);
 
 	template<typename T>
-- 
cgit v1.2.3


From 0007114cf5a60779319ab8cbd0a23a0d462b8010 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 5 Nov 2012 16:10:57 -0800
Subject: SH-3499 WIP Ensure asset stats output is correct fixed copy behavior
 of recordings and accumulator buffers

---
 indra/llcommon/llinitparam.cpp           |  2 +-
 indra/llcommon/llinitparam.h             | 81 ++++++++--------------------
 indra/llcommon/llpredicate.h             | 90 +++++++++-----------------------
 indra/llcommon/lltrace.h                 | 15 +++---
 indra/llcommon/lltracerecording.cpp      |  3 +-
 indra/llcommon/lltracerecording.h        | 29 ++++++++--
 indra/llcommon/lltracethreadrecorder.cpp |  5 ++
 7 files changed, 88 insertions(+), 137 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index d20fc03227..32d4eec607 100644
--- a/indra/llcommon/llinitparam.cpp
+++ b/indra/llcommon/llinitparam.cpp
@@ -35,7 +35,7 @@ namespace LLInitParam
 
 	predicate_rule_t default_parse_rules() 
 	{ 
-		return ll_make_predicate(PROVIDED) && !ll_make_predicate(EMPTY) && !ll_make_predicate(HAS_DEFAULT_VALUE); 
+		return ll_make_predicate(PROVIDED) && !ll_make_predicate(EMPTY);
 	}
 
 	//
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index 6177cc7d12..3d4e4331c0 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -919,17 +919,8 @@ namespace LLInitParam
 				predicate.set(HAS_DEFAULT_VALUE);
 			}
 
-			if (typed_param.isValid())
-			{
-				predicate.set(VALID, true);
-				predicate.set(PROVIDED, typed_param.anyProvided());
-			}
-			else
-			{
-				predicate.set(VALID, false);
-				predicate.set(PROVIDED, false);
-			}
-
+			predicate.set(VALID, typed_param.isValid());
+			predicate.set(PROVIDED, typed_param.anyProvided());
 			predicate.set(EMPTY, false);
 
 			if (!predicate_rule.check(predicate)) return false;
@@ -1014,15 +1005,15 @@ namespace LLInitParam
 	};
 
 	// parameter that is a block
-	template <typename T, typename NAME_VALUE_LOOKUP>
-	class TypedParam<T, NAME_VALUE_LOOKUP, false, true> 
+	template <typename BLOCK_T, typename NAME_VALUE_LOOKUP>
+	class TypedParam<BLOCK_T, NAME_VALUE_LOOKUP, false, true> 
 	:	public Param,
-		public ParamValue<T, NAME_VALUE_LOOKUP>
+		public ParamValue<BLOCK_T, NAME_VALUE_LOOKUP>
 	{
 	public:
-		typedef ParamValue<T, NAME_VALUE_LOOKUP>				param_value_t;
+		typedef ParamValue<BLOCK_T, NAME_VALUE_LOOKUP>				param_value_t;
 		typedef typename param_value_t::value_assignment_t		value_assignment_t;
-		typedef TypedParam<T, NAME_VALUE_LOOKUP, false, true>	self_t;
+		typedef TypedParam<BLOCK_T, NAME_VALUE_LOOKUP, false, true>	self_t;
 		typedef NAME_VALUE_LOOKUP								name_value_lookup_t;
 
 		using param_value_t::operator();
@@ -1081,16 +1072,8 @@ namespace LLInitParam
 
 			LLPredicate::Value<ESerializePredicates> predicate;
 
-			if (typed_param.isValid())
-			{
-				predicate.set(VALID, true);
-				predicate.set(PROVIDED, typed_param.anyProvided());
-			}
-			else
-			{
-				predicate.set(VALID, false);
-				predicate.set(PROVIDED, false);
-			}
+			predicate.set(VALID, typed_param.isValid());
+			predicate.set(PROVIDED, typed_param.anyProvided());
 
 			if (!predicate_rule.check(predicate)) return false;
 
@@ -1187,13 +1170,13 @@ namespace LLInitParam
 	};
 
 	// container of non-block parameters
-	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
-	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false> 
+	template <typename MULTI_VALUE_T, typename NAME_VALUE_LOOKUP>
+	class TypedParam<MULTI_VALUE_T, NAME_VALUE_LOOKUP, true, false> 
 	:	public Param
 	{
 	public:
-		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false>		self_t;
-		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>					param_value_t;
+		typedef TypedParam<MULTI_VALUE_T, NAME_VALUE_LOOKUP, true, false>		self_t;
+		typedef ParamValue<MULTI_VALUE_T, NAME_VALUE_LOOKUP>					param_value_t;
 		typedef typename std::vector<param_value_t>							container_t;
 		typedef const container_t&											value_assignment_t;
 
@@ -1280,18 +1263,8 @@ namespace LLInitParam
 			LLPredicate::Value<ESerializePredicates> predicate;
 
 			predicate.set(REQUIRED, typed_param.mMinCount > 0);
-
-			if (typed_param.isValid())
-			{
-				predicate.set(VALID, true);
-				predicate.set(PROVIDED, typed_param.anyProvided());
-			}
-			else
-			{
-				predicate.set(VALID, false);
-				predicate.set(PROVIDED, false);
-			}			
-
+			predicate.set(VALID, typed_param.isValid());
+			predicate.set(PROVIDED, typed_param.anyProvided());
 			predicate.set(EMPTY, typed_param.mValues.empty());
 
 			if (!predicate_rule.check(predicate)) return false;
@@ -1345,7 +1318,7 @@ namespace LLInitParam
 
 		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
 		{
-			parser.inspectValue<VALUE_TYPE>(name_stack, min_count, max_count, NULL);
+			parser.inspectValue<MULTI_VALUE_T>(name_stack, min_count, max_count, NULL);
 			if (name_value_lookup_t::getPossibleValues())
 			{
 				parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues());
@@ -1437,13 +1410,13 @@ namespace LLInitParam
 	};
 
 	// container of block parameters
-	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
-	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true> 
+	template <typename MULTI_BLOCK_T, typename NAME_VALUE_LOOKUP>
+	class TypedParam<MULTI_BLOCK_T, NAME_VALUE_LOOKUP, true, true> 
 	:	public Param
 	{
 	public:
-		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true>	self_t;
-		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>				param_value_t;
+		typedef TypedParam<MULTI_BLOCK_T, NAME_VALUE_LOOKUP, true, true>	self_t;
+		typedef ParamValue<MULTI_BLOCK_T, NAME_VALUE_LOOKUP>				param_value_t;
 		typedef typename std::vector<param_value_t>						container_t;
 		typedef const container_t&										value_assignment_t;
 		typedef typename param_value_t::value_t							value_t;
@@ -1548,17 +1521,9 @@ namespace LLInitParam
 			LLPredicate::Value<ESerializePredicates> predicate;
 
 			predicate.set(REQUIRED, typed_param.mMinCount > 0);
-
-			if (typed_param.isValid())
-			{
-				predicate.set(VALID, true);
-				predicate.set(PROVIDED, typed_param.anyProvided());
-			}
-			else
-			{
-				predicate.set(VALID, false);
-				predicate.set(PROVIDED, false);
-			}	
+			predicate.set(VALID, typed_param.isValid());
+			predicate.set(PROVIDED, typed_param.anyProvided());
+			predicate.set(EMPTY, typed_param.mValues.empty());
 
 			if (!predicate_rule.check(predicate)) return false;
 
diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h
index 6c9e5fc145..a0e970a799 100644
--- a/indra/llcommon/llpredicate.h
+++ b/indra/llcommon/llpredicate.h
@@ -76,41 +76,31 @@ namespace LLPredicate
 		void set(ENUM e, bool value = true)
 		{
 			llassert(0 <= e && e < cMaxEnum);
-			mPredicateFlags = modifyPredicate(0x1 << (S32)e, cPredicateFlagsFromEnum[e], value, mPredicateFlags);
-		}
-
-		void set(const Value other, bool value)
-		{
-			predicate_flag_t predicate_flags_to_set = other.mPredicateFlags;
-			predicate_flag_t cumulative_flags = 0;
-			while(predicate_flags_to_set)
-			{
-				predicate_flag_t next_flags = clearLSB(predicate_flags_to_set);
-				predicate_flag_t lsb_flag = predicate_flags_to_set ^ next_flags;
-
-				predicate_flag_t mask = 0;
-				predicate_flag_t cur_flags = mPredicateFlags;
-				for (S32 i = 0; i < cMaxEnum; i++)
-				{
-					if (cPredicateFlagsFromEnum[i] & lsb_flag)
-					{
-						mask |= cPredicateFlagsFromEnum[i];
-						cur_flags = modifyPredicate(0x1 << (0x1 << i ), cPredicateFlagsFromEnum[i], !value, cur_flags);
-					}
-				}
-
-				cumulative_flags |= modifyPredicate(lsb_flag, mask, value, cur_flags);
-				
-				predicate_flags_to_set = next_flags;
+			predicate_flag_t flags_to_modify;
+			predicate_flag_t mask = cPredicateFlagsFromEnum[e];
+			if (value)
+			{	// add predicate "e" to flags that don't contain it already
+				flags_to_modify = (mPredicateFlags & ~mask);
+				// clear flags not containing e
+				mPredicateFlags &= mask;
+				// add back flags shifted to contain e
+				mPredicateFlags |= flags_to_modify << (0x1 << e);
+			}
+			else
+			{	// remove predicate "e" from flags that contain it
+				flags_to_modify = (mPredicateFlags & mask);
+				// clear flags containing e
+				mPredicateFlags &= ~mask;
+				// add back flags shifted to not contain e
+				mPredicateFlags |= flags_to_modify >> (0x1 << e);
 			}
-			mPredicateFlags = cumulative_flags;
 		}
 
-		void forget(const Value value)
+		void forget(ENUM e)
 		{
-			set(value, true);
+			set(e, true);
 			U32 flags_with_predicate = mPredicateFlags;
-			set(value, false);
+			set(e, false);
 			// ambiguous value is result of adding and removing predicate at the same time!
 			mPredicateFlags |= flags_with_predicate;
 		}
@@ -131,38 +121,6 @@ namespace LLPredicate
 		}
 
 	private:
-
-		predicate_flag_t clearLSB(predicate_flag_t value)
-		{
-			return value & (value - 1);
-		}
-
-		predicate_flag_t modifyPredicate(predicate_flag_t predicate_flag, predicate_flag_t mask, predicate_flag_t value, bool set)
-		{
-			llassert(clearLSB(predicate_flag) == 0);
-			predicate_flag_t flags_to_modify;
-
-			if (set)
-			{
-				flags_to_modify = (mPredicateFlags & ~mask);
-				// clear flags not containing predicate to be added
-				value &= mask;
-				// shift flags, in effect adding predicate
-				flags_to_modify *= predicate_flag;
-			}
-			else
-			{
-				flags_to_modify = mPredicateFlags & mask;
-				// clear flags containing predicate to be removed
-				value &= ~mask;
-				// shift flags, in effect removing predicate
-				flags_to_modify /= predicate_flag;
-			}
-			// put modified flags back
-			value |= flags_to_modify;
-			return value;
-		}
-
 		predicate_flag_t mPredicateFlags;
 	};
 
@@ -181,14 +139,14 @@ namespace LLPredicate
 		Rule()
 		{}
 
-		void require(const Value<ENUM> value)
+		void require(ENUM e)
 		{
-			mRule.set(value, require);
+			mRule.set(e, require);
 		}
 
-		void allow(const Value<ENUM> value)
+		void allow(ENUM e)
 		{
-			mRule.forget(value);
+			mRule.forget(e);
 		}
 
 		bool check(const Value<ENUM> value) const
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 735c45754c..8ad391e6e5 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -38,9 +38,9 @@
 
 #include <list>
 
-#define TOKEN_PASTE_ACTUAL(x, y) x##y
-#define TOKEN_PASTE(x, y) TOKEN_PASTE_ACTUAL(x, y)
-#define RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder TOKEN_PASTE(block_time_recorder, __COUNTER__)(block_timer);
+#define LL_TOKEN_PASTE_ACTUAL(x, y) x##y
+#define LL_TOKEN_PASTE(x, y) LL_TOKEN_PASTE_ACTUAL(x, y)
+#define LL_RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder LL_TOKEN_PASTE(block_time_recorder, __COUNTER__)(block_timer);
 
 namespace LLTrace
 {
@@ -93,13 +93,16 @@ namespace LLTrace
 
 	public:
 
-		// copying an accumulator buffer does not copy the actual contents, but simply initializes the buffer size
-		// to be identical to the other buffer
 		AccumulatorBuffer(const AccumulatorBuffer& other = getDefaultBuffer())
 		:	mStorageSize(other.mStorageSize),
 			mStorage(new ACCUMULATOR[other.mStorageSize]),
 			mNextStorageSlot(other.mNextStorageSlot)
-		{}
+		{
+			for (S32 i = 0; i < mNextStorageSlot; i++)
+			{
+				mStorage[i] = other.mStorage[i];
+			}
+		}
 
 		~AccumulatorBuffer()
 		{
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index a8e1a5eec9..9cdd89c223 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -52,9 +52,8 @@ Recording::~Recording()
 void Recording::update()
 {
 	if (isStarted())
-{
+	{
 		LLTrace::get_thread_recorder()->update(this);
-		mElapsedSeconds = 0.0;
 		mSamplingTimer.reset();
 	}
 }
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 3a786c1357..e994949150 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -53,16 +53,20 @@ public:
 	void restart();
 	void reset();
 
-	bool isStarted() { return mPlayState == STARTED; }
-	bool isPaused()  { return mPlayState == PAUSED; }
-	bool isStopped() { return mPlayState == STOPPED; }
-	EPlayState getPlayState() { return mPlayState; }
+	bool isStarted() const { return mPlayState == STARTED; }
+	bool isPaused() const  { return mPlayState == PAUSED; }
+	bool isStopped() const { return mPlayState == STOPPED; }
+	EPlayState getPlayState() const { return mPlayState; }
 
 protected:
 	LLStopWatchControlsMixinCommon()
 	:	mPlayState(STOPPED)
 	{}
 
+	// derived classes can call this from their constructor in order
+	// to enforce invariants
+	void forceState(EPlayState state) { mPlayState = state; }
+
 private:
 	// trigger data accumulation (without reset)
 	virtual void handleStart() = 0;
@@ -102,6 +106,23 @@ namespace LLTrace
 	public:
 		Recording();
 
+		Recording(const Recording& other)
+		{
+			mSamplingTimer = other.mSamplingTimer;
+			mElapsedSeconds = other.mElapsedSeconds;
+			mCountsFloat = other.mCountsFloat;
+			mMeasurementsFloat = other.mMeasurementsFloat;
+			mCounts = other.mCounts;
+			mMeasurements = other.mMeasurements;
+			mStackTimers = other.mStackTimers;
+
+			if (other.isStarted())
+			{
+				handleStart();
+			}
+
+			forceState(other.getPlayState());
+		}
 		~Recording();
 
 		void makePrimary();
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 0feb3ab7af..af66a69492 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -86,6 +86,11 @@ std::list<ThreadRecorder::ActiveRecording>::iterator ThreadRecorder::update( Rec
 		}
 	}
 
+	if (it == end_it)
+	{
+		llerrs << "Recording not active on this thread" << llendl;
+	}
+
 	return it;
 }
 
-- 
cgit v1.2.3


From 860ff2f7e2a7fe932dfb7c148f0dbc0067018038 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 7 Nov 2012 00:38:21 -0800
Subject: SH-3499 WIP Ensure asset stats output is correct fixed trace data
 gathering and routing from background thread simplified slave->master thread
 communication (eliminated redundant recording and proxy object) improved
 performance of fast timer data gathering (slow iterators)

---
 indra/llcommon/llapr.h                   |   3 +-
 indra/llcommon/llfasttimer.cpp           |   8 +-
 indra/llcommon/llqueuedthread.cpp        |   5 +-
 indra/llcommon/lltrace.h                 |   5 +-
 indra/llcommon/lltracerecording.cpp      | 189 ++++++++++++++++++++++---------
 indra/llcommon/lltracerecording.h        | 112 +++++++++---------
 indra/llcommon/lltracethreadrecorder.cpp |  19 ++--
 indra/llcommon/lltracethreadrecorder.h   |  11 +-
 8 files changed, 219 insertions(+), 133 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 821274aeb3..510725ffc6 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -334,14 +334,13 @@ public:
 	{}
 
 	explicit LLThreadLocalPointer(T* value)
-		:	LLThreadLocalPointerBase(&cleanup)
 	{
 		set(value);
 	}
 
 
 	LLThreadLocalPointer(const LLThreadLocalPointer<T>& other)
-	:	LLThreadLocalPointerBase(other, &cleanup)
+	:	LLThreadLocalPointerBase(other)
 	{
 		set(other.get());		
 	}
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 0abaf73063..4f67004773 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -319,7 +319,7 @@ void LLFastTimer::NamedTimer::buildHierarchy()
 
 	// set up initial tree
 	{
-		for (instance_iter it = beginInstances(); it != endInstances(); ++it)
+		for (instance_iter it = beginInstances(), end_it = endInstances(); it != end_it; ++it)
 		{
 			NamedTimer& timer = *it;
 			if (&timer == NamedTimerFactory::instance().getRootTimer()) continue;
@@ -449,7 +449,7 @@ void LLFastTimer::NamedTimer::resetFrame()
 		LLSD sd;
 
 		{
-			for (instance_iter it = beginInstances(); it != endInstances(); ++it)
+			for (instance_iter it = beginInstances(), end_it = endInstances(); it != end_it; ++it)
 			{
 				NamedTimer& timer = *it;
 				FrameState& info = timer.getFrameState();
@@ -472,7 +472,7 @@ void LLFastTimer::NamedTimer::resetFrame()
 	}
 
 	// reset for next frame
-	for (instance_iter it = beginInstances(); it != endInstances(); ++it)
+	for (instance_iter it = beginInstances(), end_it = endInstances(); it != end_it; ++it)
 	{
 		NamedTimer& timer = *it;
 			
@@ -512,7 +512,7 @@ void LLFastTimer::NamedTimer::reset()
 
 	// reset all history
 	{
-		for (instance_iter it = beginInstances(); it != endInstances(); ++it)
+		for (instance_iter it = beginInstances(), end_it = endInstances(); it != end_it; ++it)
 		{
 			NamedTimer& timer = *it;
 			if (&timer != NamedTimerFactory::instance().getRootTimer()) 
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 218f6dbcd0..956642e97a 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -112,8 +112,6 @@ void LLQueuedThread::shutdown()
 // virtual
 S32 LLQueuedThread::update(F32 max_time_ms)
 {
-	LLTrace::get_thread_recorder()->pushToMaster();
-
 	if (!mStarted)
 	{
 		if (!mThreaded)
@@ -511,6 +509,9 @@ void LLQueuedThread::run()
 		threadedUpdate();
 		
 		int res = processNextRequest();
+
+		LLTrace::get_thread_recorder()->pushToMaster();
+
 		if (res == 0)
 		{
 			mIdleThread = TRUE;
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 8ad391e6e5..e2530a8a24 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -220,8 +220,7 @@ namespace LLTrace
 			return AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage()[mAccumulatorIndex];
 		}
 
-		ACCUMULATOR& getAccumulator(AccumulatorBuffer<ACCUMULATOR>* buffer) { return (*buffer)[mAccumulatorIndex]; }
-		const ACCUMULATOR& getAccumulator(const AccumulatorBuffer<ACCUMULATOR>* buffer) const { return (*buffer)[mAccumulatorIndex]; }
+		size_t getIndex() const { return mAccumulatorIndex; }
 
 	protected:
 		std::string	mName;
@@ -396,6 +395,8 @@ namespace LLTrace
 
 		T	getSum() const { return (T)mSum; }
 
+		U32 getSampleCount() const { return mNumSamples; }
+
 	private:
 		T	mSum;
 
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 9cdd89c223..435c49106f 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -117,29 +117,29 @@ void Recording::appendRecording( const Recording& other )
 
 F64 Recording::getSum( const TraceType<CountAccumulator<F64> >& stat ) const
 {
-	return stat.getAccumulator(mCountsFloat).getSum();
+	return (*mCountsFloat)[stat.getIndex()].getSum();
 }
 
 S64 Recording::getSum( const TraceType<CountAccumulator<S64> >& stat ) const
 {
-	return stat.getAccumulator(mCounts).getSum();
+	return (*mCounts)[stat.getIndex()].getSum();
 }
 
 F64 Recording::getSum( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return (F64)stat.getAccumulator(mMeasurementsFloat).getSum();
+	return (F64)(*mMeasurementsFloat)[stat.getIndex()].getSum();
 }
 
 S64 Recording::getSum( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (S64)stat.getAccumulator(mMeasurements).getSum();
+	return (S64)(*mMeasurements)[stat.getIndex()].getSum();
 }
 
 
 
 F64 Recording::getPerSec( const TraceType<CountAccumulator<F64> >& stat ) const
 {
-	F64 sum = stat.getAccumulator(mCountsFloat).getSum();
+	F64 sum = (*mCountsFloat)[stat.getIndex()].getSum();
 	return  (sum != 0.0) 
 		? (sum / mElapsedSeconds)
 		: 0.0;
@@ -147,15 +147,26 @@ F64 Recording::getPerSec( const TraceType<CountAccumulator<F64> >& stat ) const
 
 F64 Recording::getPerSec( const TraceType<CountAccumulator<S64> >& stat ) const
 {
-	S64 sum = stat.getAccumulator(mCounts).getSum();
+	S64 sum = (*mCounts)[stat.getIndex()].getSum();
 	return (sum != 0) 
 		? ((F64)sum / mElapsedSeconds)
 		: 0.0;
 }
 
+U32 Recording::getSampleCount( const TraceType<CountAccumulator<F64> >& stat ) const
+{
+	return (*mCountsFloat)[stat.getIndex()].getSampleCount();
+}
+
+U32 Recording::getSampleCount( const TraceType<CountAccumulator<S64> >& stat ) const
+{
+	return (*mMeasurementsFloat)[stat.getIndex()].getSampleCount();
+}
+
+
 F64 Recording::getPerSec( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	F64 sum = stat.getAccumulator(mMeasurementsFloat).getSum();
+	F64 sum = (*mMeasurementsFloat)[stat.getIndex()].getSum();
 	return  (sum != 0.0) 
 		? (sum / mElapsedSeconds)
 		: 0.0;
@@ -163,7 +174,7 @@ F64 Recording::getPerSec( const TraceType<MeasurementAccumulator<F64> >& stat )
 
 F64 Recording::getPerSec( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	S64 sum = stat.getAccumulator(mMeasurements).getSum();
+	S64 sum = (*mMeasurements)[stat.getIndex()].getSum();
 	return (sum != 0) 
 		? ((F64)sum / mElapsedSeconds)
 		: 0.0;
@@ -171,62 +182,62 @@ F64 Recording::getPerSec( const TraceType<MeasurementAccumulator<S64> >& stat )
 
 F64 Recording::getMin( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return stat.getAccumulator(mMeasurementsFloat).getMin();
+	return (*mMeasurementsFloat)[stat.getIndex()].getMin();
 }
 
 S64 Recording::getMin( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return stat.getAccumulator(mMeasurements).getMin();
+	return (*mMeasurements)[stat.getIndex()].getMin();
 }
 
 F64 Recording::getMax( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return stat.getAccumulator(mMeasurementsFloat).getMax();
+	return (*mMeasurementsFloat)[stat.getIndex()].getMax();
 }
 
 S64 Recording::getMax( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return stat.getAccumulator(mMeasurements).getMax();
+	return (*mMeasurements)[stat.getIndex()].getMax();
 }
 
 F64 Recording::getMean( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return stat.getAccumulator(mMeasurementsFloat).getMean();
+	return (*mMeasurementsFloat)[stat.getIndex()].getMean();
 }
 
 F64 Recording::getMean( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return stat.getAccumulator(mMeasurements).getMean();
+	return (*mMeasurements)[stat.getIndex()].getMean();
 }
 
 F64 Recording::getStandardDeviation( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return stat.getAccumulator(mMeasurementsFloat).getStandardDeviation();
+	return (*mMeasurementsFloat)[stat.getIndex()].getStandardDeviation();
 }
 
 F64 Recording::getStandardDeviation( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return stat.getAccumulator(mMeasurements).getStandardDeviation();
+	return (*mMeasurements)[stat.getIndex()].getStandardDeviation();
 }
 
 F64 Recording::getLastValue( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return stat.getAccumulator(mMeasurementsFloat).getLastValue();
+	return (*mMeasurementsFloat)[stat.getIndex()].getLastValue();
 }
 
 S64 Recording::getLastValue( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return stat.getAccumulator(mMeasurements).getLastValue();
+	return (*mMeasurements)[stat.getIndex()].getLastValue();
 }
 
 U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return stat.getAccumulator(mMeasurementsFloat).getSampleCount();
+	return (*mMeasurementsFloat)[stat.getIndex()].getSampleCount();
 }
 
 U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return stat.getAccumulator(mMeasurements).getSampleCount();
+	return (*mMeasurements)[stat.getIndex()].getSampleCount();
 }
 
 
@@ -235,13 +246,14 @@ U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<S64> >& st
 // PeriodicRecording
 ///////////////////////////////////////////////////////////////////////
 
-PeriodicRecording::PeriodicRecording( S32 num_periods ) 
+PeriodicRecording::PeriodicRecording( S32 num_periods, EStopWatchState state) 
 :	mNumPeriods(num_periods),
 	mCurPeriod(0),
 	mTotalValid(false),
 	mRecordingPeriods( new Recording[num_periods])
 {
 	llassert(mNumPeriods > 0);
+	initTo(state);
 }
 
 PeriodicRecording::~PeriodicRecording()
@@ -252,7 +264,7 @@ PeriodicRecording::~PeriodicRecording()
 
 void PeriodicRecording::nextPeriod()
 {
-	EPlayState play_state = getPlayState();
+	EStopWatchState play_state = getPlayState();
 	Recording& old_recording = getCurRecordingPeriod();
 	mCurPeriod = (mCurPeriod + 1) % mNumPeriods;
 	old_recording.splitTo(getCurRecordingPeriod());
@@ -286,24 +298,44 @@ Recording& PeriodicRecording::getTotalRecording()
 	return mTotalRecording;
 }
 
-void PeriodicRecording::handleStart()
+void PeriodicRecording::start()
+{
+	getCurRecordingPeriod().start();
+}
+
+void PeriodicRecording::stop()
+{
+	getCurRecordingPeriod().stop();
+}
+
+void PeriodicRecording::pause()
 {
-	getCurRecordingPeriod().handleStart();
+	getCurRecordingPeriod().pause();
 }
 
-void PeriodicRecording::handleStop()
+void PeriodicRecording::resume()
 {
-	getCurRecordingPeriod().handleStop();
+	getCurRecordingPeriod().resume();
 }
 
-void PeriodicRecording::handleReset()
+void PeriodicRecording::restart()
 {
-	getCurRecordingPeriod().handleReset();
+	getCurRecordingPeriod().restart();
 }
 
-void PeriodicRecording::handleSplitTo( PeriodicRecording& other )
+void PeriodicRecording::reset()
 {
-	getCurRecordingPeriod().handleSplitTo(other.getCurRecordingPeriod());
+	getCurRecordingPeriod().reset();
+}
+
+void PeriodicRecording::splitTo(PeriodicRecording& other)
+{
+	getCurRecordingPeriod().splitTo(other.getCurRecordingPeriod());
+}
+
+void PeriodicRecording::splitFrom(PeriodicRecording& other)
+{
+	getCurRecordingPeriod().splitFrom(other.getCurRecordingPeriod());
 }
 
 
@@ -317,38 +349,59 @@ void ExtendableRecording::extend()
 	mPotentialRecording.reset();
 }
 
-void ExtendableRecording::handleStart()
+void ExtendableRecording::start()
 {
-	mPotentialRecording.handleStart();
+	mPotentialRecording.start();
 }
 
-void ExtendableRecording::handleStop()
+void ExtendableRecording::stop()
 {
-	mPotentialRecording.handleStop();
+	mPotentialRecording.stop();
 }
 
-void ExtendableRecording::handleReset()
+void ExtendableRecording::pause()
 {
-	mAcceptedRecording.handleReset();
-	mPotentialRecording.handleReset();
+	mPotentialRecording.pause();
 }
 
-void ExtendableRecording::handleSplitTo( ExtendableRecording& other )
+void ExtendableRecording::resume()
 {
-	mPotentialRecording.handleSplitTo(other.mPotentialRecording);
+	mPotentialRecording.resume();
+}
+
+void ExtendableRecording::restart()
+{
+	mAcceptedRecording.reset();
+	mPotentialRecording.restart();
+}
+
+void ExtendableRecording::reset()
+{
+	mAcceptedRecording.reset();
+	mPotentialRecording.reset();
+}
+
+void ExtendableRecording::splitTo(ExtendableRecording& other)
+{
+	mPotentialRecording.splitTo(other.mPotentialRecording);
+}
+
+void ExtendableRecording::splitFrom(ExtendableRecording& other)
+{
+	mPotentialRecording.splitFrom(other.mPotentialRecording);
 }
 
 PeriodicRecording& get_frame_recording()
 {
-	static PeriodicRecording sRecording(64);
-	return sRecording;
+	static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(64, PeriodicRecording::STARTED));
+	return *sRecording;
 }
 
 }
 
 void LLStopWatchControlsMixinCommon::start()
 {
-	switch (mPlayState)
+	switch (mState)
 	{
 	case STOPPED:
 		handleReset();
@@ -360,13 +413,16 @@ void LLStopWatchControlsMixinCommon::start()
 	case STARTED:
 		handleReset();
 		break;
+	default:
+		llassert(false);
+		break;
 	}
-	mPlayState = STARTED;
+	mState = STARTED;
 }
 
 void LLStopWatchControlsMixinCommon::stop()
 {
-	switch (mPlayState)
+	switch (mState)
 	{
 	case STOPPED:
 		break;
@@ -376,13 +432,16 @@ void LLStopWatchControlsMixinCommon::stop()
 	case STARTED:
 		handleStop();
 		break;
+	default:
+		llassert(false);
+		break;
 	}
-	mPlayState = STOPPED;
+	mState = STOPPED;
 }
 
 void LLStopWatchControlsMixinCommon::pause()
 {
-	switch (mPlayState)
+	switch (mState)
 	{
 	case STOPPED:
 		break;
@@ -391,13 +450,16 @@ void LLStopWatchControlsMixinCommon::pause()
 	case STARTED:
 		handleStop();
 		break;
+	default:
+		llassert(false);
+		break;
 	}
-	mPlayState = PAUSED;
+	mState = PAUSED;
 }
 
 void LLStopWatchControlsMixinCommon::resume()
 {
-	switch (mPlayState)
+	switch (mState)
 	{
 	case STOPPED:
 		handleStart();
@@ -407,13 +469,16 @@ void LLStopWatchControlsMixinCommon::resume()
 		break;
 	case STARTED:
 		break;
+	default:
+		llassert(false);
+		break;
 	}
-	mPlayState = STARTED;
+	mState = STARTED;
 }
 
 void LLStopWatchControlsMixinCommon::restart()
 {
-	switch (mPlayState)
+	switch (mState)
 	{
 	case STOPPED:
 		handleReset();
@@ -426,11 +491,33 @@ void LLStopWatchControlsMixinCommon::restart()
 	case STARTED:
 		handleReset();
 		break;
+	default:
+		llassert(false);
+		break;
 	}
-	mPlayState = STARTED;
+	mState = STARTED;
 }
 
 void LLStopWatchControlsMixinCommon::reset()
 {
 	handleReset();
 }
+
+void LLStopWatchControlsMixinCommon::initTo( EStopWatchState state )
+{
+	switch(state)
+	{
+	case STOPPED:
+		break;
+	case PAUSED:
+		break;
+	case STARTED:
+		handleStart();
+		break;
+	default:
+		llassert(false);
+		break;
+	}
+
+	mState = state;
+}
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index e994949150..31901b599c 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -39,43 +39,42 @@ class LL_COMMON_API LLStopWatchControlsMixinCommon
 public:
 	virtual ~LLStopWatchControlsMixinCommon() {}
 
-	enum EPlayState
+	enum EStopWatchState
 	{
 		STOPPED,
 		PAUSED,
 		STARTED
 	};
 
-	void start();
-	void stop();
-	void pause();
-	void resume();
-	void restart();
-	void reset();
+	virtual void start();
+	virtual void stop();
+	virtual void pause();
+	virtual void resume();
+	virtual void restart();
+	virtual void reset();
 
-	bool isStarted() const { return mPlayState == STARTED; }
-	bool isPaused() const  { return mPlayState == PAUSED; }
-	bool isStopped() const { return mPlayState == STOPPED; }
-	EPlayState getPlayState() const { return mPlayState; }
+	bool isStarted() const { return mState == STARTED; }
+	bool isPaused() const  { return mState == PAUSED; }
+	bool isStopped() const { return mState == STOPPED; }
+	EStopWatchState getPlayState() const { return mState; }
 
 protected:
 	LLStopWatchControlsMixinCommon()
-	:	mPlayState(STOPPED)
+	:	mState(STOPPED)
 	{}
 
-	// derived classes can call this from their constructor in order
-	// to enforce invariants
-	void forceState(EPlayState state) { mPlayState = state; }
-
+	// derived classes can call this from their copy constructor in order
+	// to duplicate play state of source
+	void initTo(EStopWatchState state);
 private:
-	// trigger data accumulation (without reset)
-	virtual void handleStart() = 0;
-	// stop data accumulation, should put object in queryable state
-	virtual void handleStop() = 0;
-	// clear accumulated values, can be called while started
-	virtual void handleReset() = 0;
-
-	EPlayState mPlayState;
+	// trigger active behavior (without reset)
+	virtual void handleStart(){};
+	// stop active behavior
+	virtual void handleStop(){};
+	// clear accumulated state, can be called while started
+	virtual void handleReset(){};
+
+	EStopWatchState mState;
 };
 
 template<typename DERIVED>
@@ -83,19 +82,20 @@ class LLStopWatchControlsMixin
 :	public LLStopWatchControlsMixinCommon
 {
 public:
-	void splitTo(DERIVED& other)
+	typedef LLStopWatchControlsMixin<DERIVED> self_t;
+	virtual void splitTo(DERIVED& other)
 	{
 		handleSplitTo(other);
 	}
 
-	void splitFrom(DERIVED& other)
+	virtual void splitFrom(DERIVED& other)
 	{
-		other.handleSplitTo(*this);
+		static_cast<self_t&>(other).handleSplitTo(*static_cast<DERIVED*>(this));
 	}
 private:
 	// atomically stop this object while starting the other
 	// no data can be missed in between stop and start
-	virtual void handleSplitTo(DERIVED& other) = 0;
+	virtual void handleSplitTo(DERIVED& other) {};
 
 };
 
@@ -108,20 +108,20 @@ namespace LLTrace
 
 		Recording(const Recording& other)
 		{
-			mSamplingTimer = other.mSamplingTimer;
-			mElapsedSeconds = other.mElapsedSeconds;
-			mCountsFloat = other.mCountsFloat;
+			mSamplingTimer     = other.mSamplingTimer;
+			mElapsedSeconds    = other.mElapsedSeconds;
+			mCountsFloat       = other.mCountsFloat;
 			mMeasurementsFloat = other.mMeasurementsFloat;
-			mCounts = other.mCounts;
-			mMeasurements = other.mMeasurements;
-			mStackTimers = other.mStackTimers;
+			mCounts            = other.mCounts;
+			mMeasurements      = other.mMeasurements;
+			mStackTimers       = other.mStackTimers;
 
+			LLStopWatchControlsMixin::initTo(other.getPlayState());
 			if (other.isStarted())
 			{
 				handleStart();
 			}
 
-			forceState(other.getPlayState());
 		}
 		~Recording();
 
@@ -149,6 +149,10 @@ namespace LLTrace
 			return (T)getPerSec(static_cast<const TraceType<CountAccumulator<StorageType<T>::type_t> >&> (stat));
 		}
 
+		U32 getSampleCount(const TraceType<CountAccumulator<F64> >& stat) const;
+		U32 getSampleCount(const TraceType<CountAccumulator<S64> >& stat) const;
+
+
 		// Measurement accessors
 		F64 getSum(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		S64 getSum(const TraceType<MeasurementAccumulator<S64> >& stat) const;
@@ -211,14 +215,15 @@ namespace LLTrace
 
 		LLUnit::Seconds<F64> getDuration() const { return mElapsedSeconds; }
 
+	private:
+		friend class ThreadRecorder;
+
 		// implementation for LLStopWatchControlsMixin
 		/*virtual*/ void handleStart();
 		/*virtual*/ void handleStop();
 		/*virtual*/ void handleReset();
 		/*virtual*/ void handleSplitTo(Recording& other);
 
-	private:
-		friend class ThreadRecorder;
 		// returns data for current thread
 		class ThreadRecorder* getThreadRecorder(); 
 
@@ -236,7 +241,7 @@ namespace LLTrace
 	:	public LLStopWatchControlsMixin<PeriodicRecording>
 	{
 	public:
-		PeriodicRecording(S32 num_periods);
+		PeriodicRecording(S32 num_periods, EStopWatchState state = STOPPED);
 		~PeriodicRecording();
 
 		void nextPeriod();
@@ -359,15 +364,17 @@ namespace LLTrace
 			return mean;
 		}
 
-	private:
-
 		// implementation for LLStopWatchControlsMixin
-		/*virtual*/ void handleStart();
-		/*virtual*/ void handleStop();
-		/*virtual*/ void handleReset();
-
-		/*virtual*/ void handleSplitTo(PeriodicRecording& other);
+		/*virtual*/ void start();
+		/*virtual*/ void stop();
+		/*virtual*/ void pause();
+		/*virtual*/ void resume();
+		/*virtual*/ void restart();
+		/*virtual*/ void reset();
+		/*virtual*/ void splitTo(PeriodicRecording& other);
+		/*virtual*/ void splitFrom(PeriodicRecording& other);
 
+	private:
 		Recording*	mRecordingPeriods;
 		Recording	mTotalRecording;
 		bool		mTotalValid;
@@ -382,13 +389,16 @@ namespace LLTrace
 	{
 		void extend();
 
-	private:
 		// implementation for LLStopWatchControlsMixin
-		/*virtual*/ void handleStart();
-		/*virtual*/ void handleStop();
-		/*virtual*/ void handleReset();
-		/*virtual*/ void handleSplitTo(ExtendableRecording& other);
-
+		/*virtual*/ void start();
+		/*virtual*/ void stop();
+		/*virtual*/ void pause();
+		/*virtual*/ void resume();
+		/*virtual*/ void restart();
+		/*virtual*/ void reset();
+		/*virtual*/ void splitTo(ExtendableRecording& other);
+		/*virtual*/ void splitFrom(ExtendableRecording& other);
+	private:
 		Recording mAcceptedRecording;
 		Recording mPotentialRecording;
 	};
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index af66a69492..5a6ff14f97 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -171,15 +171,20 @@ void SlaveThreadRecorder::SharedData::copyTo( Recording& sink )
 // MasterThreadRecorder
 ///////////////////////////////////////////////////////////////////////
 
+LLFastTimer::DeclareTimer FTM_PULL_TRACE_DATA_FROM_SLAVES("Pull slave trace data");
 void MasterThreadRecorder::pullFromSlaveThreads()
 {
+	LLFastTimer _(FTM_PULL_TRACE_DATA_FROM_SLAVES);
+	if (mActiveRecordings.empty()) return;
+
 	LLMutexLock lock(&mSlaveListMutex);
 
+	Recording& target_recording = mActiveRecordings.front().mBaseline;
 	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
 		it != end_it;
 		++it)
 	{
-		(*it)->mRecorder->mSharedData.copyTo((*it)->mSlaveRecording);
+		(*it)->mSharedData.copyTo(target_recording);
 	}
 }
 
@@ -187,7 +192,7 @@ void MasterThreadRecorder::addSlaveThread( class SlaveThreadRecorder* child )
 {
 	LLMutexLock lock(&mSlaveListMutex);
 
-	mSlaveThreadRecorders.push_back(new SlaveThreadRecorderProxy(child));
+	mSlaveThreadRecorders.push_back(child);
 }
 
 void MasterThreadRecorder::removeSlaveThread( class SlaveThreadRecorder* child )
@@ -198,7 +203,7 @@ void MasterThreadRecorder::removeSlaveThread( class SlaveThreadRecorder* child )
 		it != end_it;
 		++it)
 	{
-		if ((*it)->mRecorder == child)
+		if ((*it) == child)
 		{
 			mSlaveThreadRecorders.erase(it);
 			break;
@@ -212,12 +217,4 @@ void MasterThreadRecorder::pushToMaster()
 MasterThreadRecorder::MasterThreadRecorder()
 {}
 
-///////////////////////////////////////////////////////////////////////
-// MasterThreadRecorder::SlaveThreadTraceProxy
-///////////////////////////////////////////////////////////////////////
-
-MasterThreadRecorder::SlaveThreadRecorderProxy::SlaveThreadRecorderProxy( class SlaveThreadRecorder* recorder) 
-:	mRecorder(recorder)
-{}
-
 }
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index c9231265af..44fe67384b 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -81,17 +81,8 @@ namespace LLTrace
 		LLMutex* getSlaveListMutex() { return &mSlaveListMutex; }
 
 	private:
-		struct SlaveThreadRecorderProxy
-		{
-			SlaveThreadRecorderProxy(class SlaveThreadRecorder* recorder);
 
-			class SlaveThreadRecorder*	mRecorder;
-			Recording					mSlaveRecording;
-		private:
-			//no need to copy these and then have to duplicate the storage
-			SlaveThreadRecorderProxy(const SlaveThreadRecorderProxy& other) {}
-		};
-		typedef std::list<SlaveThreadRecorderProxy*> slave_thread_recorder_list_t;
+		typedef std::list<class SlaveThreadRecorder*> slave_thread_recorder_list_t;
 
 		slave_thread_recorder_list_t	mSlaveThreadRecorders;
 		LLMutex							mSlaveListMutex;
-- 
cgit v1.2.3


From 9d70448a1275b80a829e16b6d08d29919748c823 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 7 Nov 2012 00:43:56 -0800
Subject: SH-3499 WIP Ensure asset stats output is correct removed explicit
 constructor of LLUnit from integral types, as C++ already guarantees that I
 can't convert from LLUnit<Bytes> to LLUnits<Seconds> (requires 2 user defined
 conversions).  Now this allows seamless replacement of existing integral
 types with Unit labeled types.

---
 indra/llcommon/llunit.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index e778383959..98e4de32fa 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -41,7 +41,7 @@ struct LLUnitType : public BASE_UNIT
 	LLUnitType()
 	{}
 
-	explicit LLUnitType(storage_t value)
+	LLUnitType(storage_t value)
 	:	BASE_UNIT(convertToBase(value))
 	{}
 
@@ -86,7 +86,7 @@ struct LLUnitType<STORAGE_TYPE, T, T>
 	:	mBaseValue()
 	{}
 
-	explicit LLUnitType(storage_t value)
+	LLUnitType(storage_t value)
 	:	mBaseValue(value)
 	{}
 
-- 
cgit v1.2.3


From ed17c181dd37f56b808838748d289ee7bb5567ec Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 7 Nov 2012 15:32:12 -0800
Subject: SH-3499 WIP Ensure asset stats output is correct further fixes to
 implicit conversion of unit types

---
 indra/llcommon/lldate.cpp           |  11 +--
 indra/llcommon/lldate.h             |   3 +-
 indra/llcommon/lltimer.cpp          |  15 ++--
 indra/llcommon/lltimer.h            |  21 +++---
 indra/llcommon/lltracerecording.cpp |  19 +++++
 indra/llcommon/lltracerecording.h   |  18 +----
 indra/llcommon/llunit.h             | 141 +++++++++---------------------------
 7 files changed, 80 insertions(+), 148 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp
index 030ef6a3c7..d8b3dfe6c6 100644
--- a/indra/llcommon/lldate.cpp
+++ b/indra/llcommon/lldate.cpp
@@ -48,18 +48,15 @@ static const F64 LL_APR_USEC_PER_SEC = 1000000.0;
 
 
 LLDate::LLDate() : mSecondsSinceEpoch(DATE_EPOCH)
-{
-}
+{}
 
 LLDate::LLDate(const LLDate& date) :
 	mSecondsSinceEpoch(date.mSecondsSinceEpoch)
-{
-}
+{}
 
-LLDate::LLDate(F64 seconds_since_epoch) :
+LLDate::LLDate(LLUnit::Seconds<F64> seconds_since_epoch) :
 	mSecondsSinceEpoch(seconds_since_epoch)
-{
-}
+{}
 
 LLDate::LLDate(const std::string& iso8601_date)
 {
diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h
index 7ff8b550ad..0500b1dcd8 100644
--- a/indra/llcommon/lldate.h
+++ b/indra/llcommon/lldate.h
@@ -33,6 +33,7 @@
 #include <string>
 
 #include "stdtypes.h"
+#include "llunit.h"
 
 /** 
  * @class LLDate
@@ -58,7 +59,7 @@ public:
 	 *
 	 * @pararm seconds_since_epoch The number of seconds since UTC epoch.
 	 */
-	LLDate(F64 seconds_since_epoch);
+	LLDate(LLUnit::Seconds<F64> seconds_since_epoch);
 
 	/** 
 	 * @brief Construct a date from a string representation
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 9ebc6de7f4..05f6b789e4 100644
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -287,14 +287,15 @@ LLTimer::~LLTimer()
 }
 
 // static
-U64 LLTimer::getTotalTime()
+LLUnit::Microseconds<U64> LLTimer::getTotalTime()
 {
+	LLUnit::Seconds<F64> sec = LLUnit::Milliseconds<U32>(2000) + LLUnit::Hours<F32>(1.f / 360.f);
 	// simply call into the implementation function.
 	return totalTime();
 }	
 
 // static
-F64 LLTimer::getTotalSeconds()
+LLUnit::Seconds<F64> LLTimer::getTotalSeconds()
 {
 	return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64;
 }
@@ -343,23 +344,23 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount)
 }
 
 
-F64 LLTimer::getElapsedTimeF64() const
+LLUnit::Seconds<F64> LLTimer::getElapsedTimeF64() const
 {
 	U64 last = mLastClockCount;
 	return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv;
 }
 
-F32 LLTimer::getElapsedTimeF32() const
+LLUnit::Seconds<F32> LLTimer::getElapsedTimeF32() const
 {
 	return (F32)getElapsedTimeF64();
 }
 
-F64 LLTimer::getElapsedTimeAndResetF64()
+LLUnit::Seconds<F64> LLTimer::getElapsedTimeAndResetF64()
 {
 	return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv;
 }
 
-F32 LLTimer::getElapsedTimeAndResetF32()
+LLUnit::Seconds<F32> LLTimer::getElapsedTimeAndResetF32()
 {
 	return (F32)getElapsedTimeAndResetF64();
 }
@@ -372,7 +373,7 @@ void  LLTimer::setTimerExpirySec(F32 expiration)
 		+ (U64)((F32)(expiration * gClockFrequency));
 }
 
-F32 LLTimer::getRemainingTimeF32() const
+LLUnit::Seconds<F32> 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 513de0605d..e0a880a346 100644
--- a/indra/llcommon/lltimer.h
+++ b/indra/llcommon/lltimer.h
@@ -37,6 +37,7 @@
 #include <string>
 #include <list>
 // units conversions
+#include "llunit.h"
 #ifndef USEC_PER_SEC
     const U32	USEC_PER_SEC	= 1000000;
 #endif
@@ -55,7 +56,7 @@ public:
 protected:	
 	U64 mLastClockCount;
 	U64 mExpirationTicks;
-	BOOL mStarted;
+	bool mStarted;
 
 public:
 	LLTimer();
@@ -66,16 +67,16 @@ public:
 
 	// Return a high precision number of seconds since the start of
 	// this application instance.
-	static F64 getElapsedSeconds()
+	static LLUnit::Seconds<F64> getElapsedSeconds()
 	{
 		return sTimer->getElapsedTimeF64();
 	}
 
 	// Return a high precision usec since epoch
-	static U64 getTotalTime();
+	static LLUnit::Microseconds<U64> getTotalTime();
 
 	// Return a high precision seconds since epoch
-	static F64 getTotalSeconds();
+	static LLUnit::Seconds<F64> getTotalSeconds();
 
 
 	// MANIPULATORS
@@ -86,18 +87,18 @@ public:
 	void setTimerExpirySec(F32 expiration);
 	BOOL checkExpirationAndReset(F32 expiration);
 	BOOL hasExpired() const;
-	F32 getElapsedTimeAndResetF32();	// Returns elapsed time in seconds with reset
-	F64 getElapsedTimeAndResetF64();
+	LLUnit::Seconds<F32> getElapsedTimeAndResetF32();	// Returns elapsed time in seconds with reset
+	LLUnit::Seconds<F64> getElapsedTimeAndResetF64();
 
-	F32 getRemainingTimeF32() const;
+	LLUnit::Seconds<F32> getRemainingTimeF32() const;
 
 	static BOOL knownBadTimer();
 
 	// ACCESSORS
-	F32 getElapsedTimeF32() const;			// Returns elapsed time in seconds
-	F64 getElapsedTimeF64() const;			// Returns elapsed time in seconds
+	LLUnit::Seconds<F32> getElapsedTimeF32() const;			// Returns elapsed time in seconds
+	LLUnit::Seconds<F64> getElapsedTimeF64() const;			// Returns elapsed time in seconds
 
-	BOOL getStarted() const { return mStarted; }
+	bool getStarted() const { return mStarted; }
 
 
 	static U64 getCurrentClockCount();		// Returns the raw clockticks
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 435c49106f..4252ed57dc 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -46,6 +46,25 @@ Recording::Recording()
 	mStackTimers(new AccumulatorBuffer<TimerAccumulator>())
 {}
 
+Recording::Recording( const Recording& other )
+{
+	llassert(other.mCountsFloat.get() != NULL);
+	mSamplingTimer     = other.mSamplingTimer;
+	mElapsedSeconds    = other.mElapsedSeconds;
+	mCountsFloat       = other.mCountsFloat;
+	mMeasurementsFloat = other.mMeasurementsFloat;
+	mCounts            = other.mCounts;
+	mMeasurements      = other.mMeasurements;
+	mStackTimers       = other.mStackTimers;
+
+	LLStopWatchControlsMixin::initTo(other.getPlayState());
+	if (other.isStarted())
+	{
+		handleStart();
+	}
+}
+
+
 Recording::~Recording()
 {}
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 31901b599c..fc96631ce0 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -106,23 +106,7 @@ namespace LLTrace
 	public:
 		Recording();
 
-		Recording(const Recording& other)
-		{
-			mSamplingTimer     = other.mSamplingTimer;
-			mElapsedSeconds    = other.mElapsedSeconds;
-			mCountsFloat       = other.mCountsFloat;
-			mMeasurementsFloat = other.mMeasurementsFloat;
-			mCounts            = other.mCounts;
-			mMeasurements      = other.mMeasurements;
-			mStackTimers       = other.mStackTimers;
-
-			LLStopWatchControlsMixin::initTo(other.getPlayState());
-			if (other.isStarted())
-			{
-				handleStart();
-			}
-
-		}
+		Recording(const Recording& other);
 		~Recording();
 
 		void makePrimary();
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 98e4de32fa..4519905707 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -51,6 +51,11 @@ struct LLUnitType : public BASE_UNIT
 		return static_cast<unit_t&>(*this);
 	}
 
+	operator storage_t () const
+	{
+		return value();
+	}
+
 	storage_t value() const
 	{
 		return convertToDerived(mBaseValue);
@@ -102,6 +107,11 @@ struct LLUnitType<STORAGE_TYPE, T, T>
 		return static_cast<unit_t&>(*this);
 	}
 
+	operator storage_t () const
+	{
+		return value();
+	}
+
 	storage_t value() const { return mBaseValue; }
 
 	template<typename CONVERTED_TYPE>
@@ -110,7 +120,6 @@ struct LLUnitType<STORAGE_TYPE, T, T>
 		return CONVERTED_TYPE(*this).value();
 	}
 
-
 	static storage_t convertToBase(storage_t derived_value)
 	{
 		return (storage_t)derived_value;
@@ -150,99 +159,77 @@ protected:
 	storage_t mBaseValue;
 };
 
-//
-// operator +
-//
 template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-DERIVED_UNIT operator + (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+struct LLUnitTypeWrapper
+:	public LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>
 {
-	return DERIVED_UNIT(first + second.value());
-}
+	typedef LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> unit_t;
+	LLUnitTypeWrapper(const unit_t& other)
+	:	unit_t(other)
+	{}
+};
 
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-DERIVED_UNIT operator + (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
-{
-	return DERIVED_UNIT(first.value() + second);
-}
 
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
-DERIVED_UNIT operator + (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
+//
+// operator +
+//
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename STORAGE_TYPE2, typename BASE_UNIT2, typename DERIVED_UNIT2>
+DERIVED_UNIT operator + (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE2, BASE_UNIT2, DERIVED_UNIT2> second)
 {
-	return DERIVED_UNIT(first.value() + second.value());
+	return DERIVED_UNIT(first + LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>(second).value());
 }
 
+
 //
 // operator -
 //
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename STORAGE_TYPE2, typename BASE_UNIT2, typename DERIVED_UNIT2>
 DERIVED_UNIT operator - (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
 {
-	return DERIVED_UNIT(first - second.value());
-}
-
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-DERIVED_UNIT operator - (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
-{
-	return DERIVED_UNIT(first.value() - second);
-}
-
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
-DERIVED_UNIT operator - (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
-{
-	return DERIVED_UNIT(first.value() - second.value());
+	return DERIVED_UNIT(first - LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>(second).value());
 }
 
 //
 // operator *
 //
 template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-DERIVED_UNIT operator * (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+DERIVED_UNIT operator * (STORAGE_TYPE first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
 {
 	return DERIVED_UNIT(first * second.value());
 }
 
 template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-DERIVED_UNIT operator * (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
+DERIVED_UNIT operator * (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, STORAGE_TYPE second)
 {
 	return DERIVED_UNIT(first.value() * second);
 }
 
+
 //
 // operator /
 //
 template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-DERIVED_UNIT operator / (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+DERIVED_UNIT operator / (STORAGE_TYPE first, LLUnitTypeWrapper<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
 {
-	return DERIVED_UNIT(first * second.value());
+	return DERIVED_UNIT(first / second.value());
 }
 
 template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-DERIVED_UNIT operator / (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
+DERIVED_UNIT operator / (LLUnitTypeWrapper<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, STORAGE_TYPE second)
 {
-	return DERIVED_UNIT(first.value() * second);
+	return DERIVED_UNIT(first.value() / second);
 }
 
 //
 // operator <
 //
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
+template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename STORAGE_TYPE2, typename BASE_UNIT2, typename DERIVED_UNIT2>
+
 bool operator < (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
 {
 	return first < second.value();
 }
 
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-bool operator < (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
-{
-	return first.value() < second;
-}
-
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
-bool operator < (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
-{
-	return first.value() < second.value();
-}
-
 //
 // operator <=
 //
@@ -252,17 +239,6 @@ bool operator <= (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::st
 	return first <= second.value();
 }
 
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-bool operator <= (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
-{
-	return first.value() <= second;
-}
-
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
-bool operator <= (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
-{
-	return first.value() <= second.value();
-}
 
 //
 // operator >
@@ -273,17 +249,6 @@ bool operator > (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::sto
 	return first > second.value();
 }
 
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-bool operator > (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
-{
-	return first.value() > second;
-}
-
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
-bool operator > (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
-{
-	return first.value() > second.value();
-}
 //
 // operator >=
 //
@@ -293,18 +258,6 @@ bool operator >= (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::st
 	return first >= second.value();
 }
 
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-bool operator >= (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
-{
-	return first.value() >= second;
-}
-
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
-bool operator >= (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
-{
-	return first.value() >= second.value();
-}
-
 //
 // operator ==
 //
@@ -314,18 +267,6 @@ bool operator == (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::st
 	return first == second.value();
 }
 
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-bool operator == (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
-{
-	return first.value() == second;
-}
-
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
-bool operator == (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
-{
-	return first.value() == second.value();
-}
-
 //
 // operator !=
 //
@@ -335,18 +276,6 @@ bool operator != (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::st
 	return first != second.value();
 }
 
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-bool operator != (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t second)
-{
-	return first.value() != second;
-}
-
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename OTHER_DERIVED_UNIT>
-bool operator != (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, LLUnitType<STORAGE_TYPE, BASE_UNIT, OTHER_DERIVED_UNIT> second)
-{
-	return first.value() != second.value();
-}
-
 #define LL_DECLARE_BASE_UNIT(unit_name)                                                                          \
 	template<typename STORAGE>                                                                                   \
 	struct unit_name : public LLUnitType<STORAGE, unit_name<STORAGE>, unit_name<STORAGE> >						 \
-- 
cgit v1.2.3


From 0bb0bd514b235948c1a21c81ab0e8ab6223b1990 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 8 Nov 2012 23:42:18 -0800
Subject: SH-3499 WIP Ensure asset stats output is correct Finished making
 LLUnit implicitly convertible to/from scalar integer values cleaned up test
 code

---
 indra/llcommon/lldate.cpp         |   4 +-
 indra/llcommon/lldate.h           |   4 +-
 indra/llcommon/lldefs.h           |   3 +
 indra/llcommon/llerrorlegacy.h    |   7 +
 indra/llcommon/lltimer.cpp        |  15 +-
 indra/llcommon/lltimer.h          |  16 +-
 indra/llcommon/lltrace.h          |  54 +++--
 indra/llcommon/lltracerecording.h |   2 +-
 indra/llcommon/llunit.h           | 404 +++++++++++++++++---------------------
 9 files changed, 239 insertions(+), 270 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp
index d8b3dfe6c6..5569b4102d 100644
--- a/indra/llcommon/lldate.cpp
+++ b/indra/llcommon/lldate.cpp
@@ -54,8 +54,8 @@ LLDate::LLDate(const LLDate& date) :
 	mSecondsSinceEpoch(date.mSecondsSinceEpoch)
 {}
 
-LLDate::LLDate(LLUnit::Seconds<F64> seconds_since_epoch) :
-	mSecondsSinceEpoch(seconds_since_epoch)
+LLDate::LLDate(LLUnit<LLUnits::Seconds, F64> seconds_since_epoch) :
+	mSecondsSinceEpoch(seconds_since_epoch.value())
 {}
 
 LLDate::LLDate(const std::string& iso8601_date)
diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h
index 0500b1dcd8..b62a846147 100644
--- a/indra/llcommon/lldate.h
+++ b/indra/llcommon/lldate.h
@@ -57,9 +57,9 @@ public:
 	/** 
 	 * @brief Construct a date from a seconds since epoch value.
 	 *
-	 * @pararm seconds_since_epoch The number of seconds since UTC epoch.
+	 * @param seconds_since_epoch The number of seconds since UTC epoch.
 	 */
-	LLDate(LLUnit::Seconds<F64> seconds_since_epoch);
+	LLDate(LLUnit<LLUnits::Seconds, F64> seconds_since_epoch);
 
 	/** 
 	 * @brief Construct a date from a string representation
diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h
index 5a4b8325f4..d57b9dccff 100644
--- a/indra/llcommon/lldefs.h
+++ b/indra/llcommon/lldefs.h
@@ -244,5 +244,8 @@ inline void llswap(LLDATATYPE& lhs, LLDATATYPE& rhs)
 	rhs = tmp;
 }
 
+#define LL_GLUE_IMPL(x, y) x##y
+#define LL_GLUE_TOKENS(x, y) LL_GLUE_IMPL(x, y)
+
 #endif // LL_LLDEFS_H
 
diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h
index 37cee579cd..58cc2899af 100644
--- a/indra/llcommon/llerrorlegacy.h
+++ b/indra/llcommon/llerrorlegacy.h
@@ -29,6 +29,7 @@
 #define LL_LLERRORLEGACY_H
 
 #include "llpreprocessor.h"
+#include <boost/static_assert.hpp>
 
 /*
 	LEGACY -- DO NOT USE THIS STUFF ANYMORE
@@ -111,6 +112,12 @@ const int LL_ERR_PRICE_MISMATCH = -23018;
 #define llverify(func)			do {if (func) {}} while(0)
 #endif
 
+#ifdef LL_WINDOWS
+#define llstatic_assert(func, msg) static_assert(func, msg)
+#else
+#define llstatic_assert(func, msg) BOOST_STATIC_ASSERT(func)
+#endif
+
 // handy compile-time assert - enforce those template parameters! 
 #define cassert(expn) typedef char __C_ASSERT__[(expn)?1:-1]   /* Flawfinder: ignore */
 	//XXX: used in two places in llcommon/llskipmap.h
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 05f6b789e4..23cebf4336 100644
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -287,15 +287,14 @@ LLTimer::~LLTimer()
 }
 
 // static
-LLUnit::Microseconds<U64> LLTimer::getTotalTime()
+LLUnit<LLUnits::Microseconds, U64> LLTimer::getTotalTime()
 {
-	LLUnit::Seconds<F64> sec = LLUnit::Milliseconds<U32>(2000) + LLUnit::Hours<F32>(1.f / 360.f);
 	// simply call into the implementation function.
 	return totalTime();
 }	
 
 // static
-LLUnit::Seconds<F64> LLTimer::getTotalSeconds()
+LLUnit<LLUnits::Seconds, F64> LLTimer::getTotalSeconds()
 {
 	return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64;
 }
@@ -344,23 +343,23 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount)
 }
 
 
-LLUnit::Seconds<F64> LLTimer::getElapsedTimeF64() const
+LLUnit<LLUnits::Seconds, F64> LLTimer::getElapsedTimeF64() const
 {
 	U64 last = mLastClockCount;
 	return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv;
 }
 
-LLUnit::Seconds<F32> LLTimer::getElapsedTimeF32() const
+LLUnit<LLUnits::Seconds, F32> LLTimer::getElapsedTimeF32() const
 {
 	return (F32)getElapsedTimeF64();
 }
 
-LLUnit::Seconds<F64> LLTimer::getElapsedTimeAndResetF64()
+LLUnit<LLUnits::Seconds, F64> LLTimer::getElapsedTimeAndResetF64()
 {
 	return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv;
 }
 
-LLUnit::Seconds<F32> LLTimer::getElapsedTimeAndResetF32()
+LLUnit<LLUnits::Seconds, F32> LLTimer::getElapsedTimeAndResetF32()
 {
 	return (F32)getElapsedTimeAndResetF64();
 }
@@ -373,7 +372,7 @@ void  LLTimer::setTimerExpirySec(F32 expiration)
 		+ (U64)((F32)(expiration * gClockFrequency));
 }
 
-LLUnit::Seconds<F32> LLTimer::getRemainingTimeF32() const
+LLUnit<LLUnits::Seconds, F32> 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 e0a880a346..5cb2b18111 100644
--- 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 LLUnit::Seconds<F64> getElapsedSeconds()
+	static LLUnit<LLUnits::Seconds, F64> getElapsedSeconds()
 	{
 		return sTimer->getElapsedTimeF64();
 	}
 
 	// Return a high precision usec since epoch
-	static LLUnit::Microseconds<U64> getTotalTime();
+	static LLUnit<LLUnits::Microseconds, U64> getTotalTime();
 
 	// Return a high precision seconds since epoch
-	static LLUnit::Seconds<F64> getTotalSeconds();
+	static LLUnit<LLUnits::Seconds, F64> getTotalSeconds();
 
 
 	// MANIPULATORS
@@ -87,16 +87,16 @@ public:
 	void setTimerExpirySec(F32 expiration);
 	BOOL checkExpirationAndReset(F32 expiration);
 	BOOL hasExpired() const;
-	LLUnit::Seconds<F32> getElapsedTimeAndResetF32();	// Returns elapsed time in seconds with reset
-	LLUnit::Seconds<F64> getElapsedTimeAndResetF64();
+	LLUnit<LLUnits::Seconds, F32> getElapsedTimeAndResetF32();	// Returns elapsed time in seconds with reset
+	LLUnit<LLUnits::Seconds, F64> getElapsedTimeAndResetF64();
 
-	LLUnit::Seconds<F32> getRemainingTimeF32() const;
+	LLUnit<LLUnits::Seconds, F32> getRemainingTimeF32() const;
 
 	static BOOL knownBadTimer();
 
 	// ACCESSORS
-	LLUnit::Seconds<F32> getElapsedTimeF32() const;			// Returns elapsed time in seconds
-	LLUnit::Seconds<F64> getElapsedTimeF64() const;			// Returns elapsed time in seconds
+	LLUnit<LLUnits::Seconds, F32> getElapsedTimeF32() const;			// Returns elapsed time in seconds
+	LLUnit<LLUnits::Seconds, F64> 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 e2530a8a24..d289ea9a88 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -38,37 +38,35 @@
 
 #include <list>
 
-#define LL_TOKEN_PASTE_ACTUAL(x, y) x##y
-#define LL_TOKEN_PASTE(x, y) LL_TOKEN_PASTE_ACTUAL(x, y)
-#define LL_RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder LL_TOKEN_PASTE(block_time_recorder, __COUNTER__)(block_timer);
+#define LL_RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder LL_GLUE_TOKENS(block_time_recorder, __COUNTER__)(block_timer);
 
 namespace LLTrace
 {
 	class Recording;
 
-	typedef LLUnit::Bytes<F64>			Bytes;
-	typedef LLUnit::Kilobytes<F64>		Kilobytes;
-	typedef LLUnit::Megabytes<F64>		Megabytes;
-	typedef LLUnit::Gigabytes<F64>		Gigabytes;
-	typedef LLUnit::Bits<F64>			Bits;
-	typedef LLUnit::Kilobits<F64>		Kilobits;
-	typedef LLUnit::Megabits<F64>		Megabits;
-	typedef LLUnit::Gigabits<F64>		Gigabits;
-
-	typedef LLUnit::Seconds<F64>		Seconds;
-	typedef LLUnit::Milliseconds<F64>	Milliseconds;
-	typedef LLUnit::Minutes<F64>		Minutes;
-	typedef LLUnit::Hours<F64>			Hours;
-	typedef LLUnit::Days<F64>			Days;
-	typedef LLUnit::Weeks<F64>			Weeks;
-	typedef LLUnit::Milliseconds<F64>	Milliseconds;
-	typedef LLUnit::Microseconds<F64>	Microseconds;
-	typedef LLUnit::Nanoseconds<F64>	Nanoseconds;
-
-	typedef LLUnit::Meters<F64>			Meters;
-	typedef LLUnit::Kilometers<F64>		Kilometers;
-	typedef LLUnit::Centimeters<F64>	Centimeters;
-	typedef LLUnit::Millimeters<F64>	Millimeters;
+	typedef LLUnit<LLUnits::Bytes, F64>			Bytes;
+	typedef LLUnit<LLUnits::Kilobytes, F64>		Kilobytes;
+	typedef LLUnit<LLUnits::Megabytes, F64>		Megabytes;
+	typedef LLUnit<LLUnits::Gigabytes, F64>		Gigabytes;
+	typedef LLUnit<LLUnits::Bits, F64>			Bits;
+	typedef LLUnit<LLUnits::Kilobits, F64>		Kilobits;
+	typedef LLUnit<LLUnits::Megabits, F64>		Megabits;
+	typedef LLUnit<LLUnits::Gigabits, F64>		Gigabits;
+
+	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::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;
+
+	typedef LLUnit<LLUnits::Meters, F64>			Meters;
+	typedef LLUnit<LLUnits::Kilometers, F64>		Kilometers;
+	typedef LLUnit<LLUnits::Centimeters, F64>	Centimeters;
+	typedef LLUnit<LLUnits::Millimeters, F64>	Millimeters;
 
 	void init();
 	void cleanup();
@@ -438,7 +436,7 @@ namespace LLTrace
 		void sample(UNIT_T value)
 		{
 			T converted_value;
-			converted_value.assignFrom(value);
+			converted_value = value;
 			getPrimaryAccumulator().sample((storage_t)converted_value.value());
 		}
 	};
@@ -478,7 +476,7 @@ namespace LLTrace
 		void add(UNIT_T value)
 		{
 			T converted_value;
-			converted_value.assignFrom(value);
+			converted_value = value;
 			getPrimaryAccumulator().add((storage_t)converted_value.value());
 		}
 	};
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index fc96631ce0..ca9950b78d 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -197,7 +197,7 @@ namespace LLTrace
 		U32 getSampleCount(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		U32 getSampleCount(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 
-		LLUnit::Seconds<F64> getDuration() const { return mElapsedSeconds; }
+		LLUnit<LLUnits::Seconds, F64> getDuration() const { return mElapsedSeconds; }
 
 	private:
 		friend class ThreadRecorder;
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 4519905707..0dcafbe26e 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -30,326 +30,288 @@
 #include "stdtypes.h"
 #include "llpreprocessor.h"
 
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT = BASE_UNIT>
-struct LLUnitType : public BASE_UNIT
+namespace LLUnits
 {
-	typedef DERIVED_UNIT unit_t;
-
-	typedef typename STORAGE_TYPE storage_t;
-	typedef void is_unit_tag_t;
-
-	LLUnitType()
-	{}
-
-	LLUnitType(storage_t value)
-	:	BASE_UNIT(convertToBase(value))
-	{}
-
-	// implicit downcast
-	operator unit_t& ()
-	{
-		return static_cast<unit_t&>(*this);
-	}
-
-	operator storage_t () const
-	{
-		return value();
-	}
-
-	storage_t value() const
-	{
-		return convertToDerived(mBaseValue);
-	}
-
-	template<typename CONVERTED_TYPE>
-	storage_t as() const
-	{
-		return CONVERTED_TYPE(*this).value();
-	}
-
-protected:
-	static storage_t convertToBase(storage_t derived_value)
-	{
-		return (storage_t)((F32)derived_value * unit_t::conversionToBaseFactor());
-	}
-
-	static storage_t convertToDerived(storage_t base_value)
+template<typename DERIVED_UNITS_TAG, typename BASE_UNITS_TAG>
+struct ConversionFactor
+{
+	static F64 get()
 	{
-		return (storage_t)((F32)base_value / unit_t::conversionToBaseFactor());
+		llstatic_assert(sizeof(DERIVED_UNITS_TAG) == 0, "Cannot convert between types.");
 	}
+};
 
+template<typename BASE_UNITS_TAG>
+struct ConversionFactor<BASE_UNITS_TAG, BASE_UNITS_TAG>
+{
+	static F64 get() { return 1.0; }
 };
+}
 
-template<typename STORAGE_TYPE, typename T>
-struct LLUnitType<STORAGE_TYPE, T, T>
+template<typename UNIT_TYPE, typename STORAGE_TYPE>
+struct LLUnit
 {
-	typedef T unit_t;
-	typedef STORAGE_TYPE storage_t;
+	typedef LLUnit<UNIT_TYPE, STORAGE_TYPE> self_t;
+	typedef typename STORAGE_TYPE storage_t;
 	typedef void is_unit_tag_t;
 
-	LLUnitType()
-	:	mBaseValue()
+	LLUnit(storage_t value = storage_t())
+	:	mValue(value)
 	{}
 
-	LLUnitType(storage_t value)
-	:	mBaseValue(value)
+	template<typename OTHER_UNIT, typename OTHER_STORAGE>
+	LLUnit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
+	:	mValue(convert(other))
 	{}
 
-	unit_t& operator=(storage_t value)
+	LLUnit(self_t& other)
+	:	mValue(other.mValue)
+	{}
+
+	self_t& operator = (storage_t value)
 	{
-		setBaseValue(value);
+		mValue = value;
 		return *this;
 	}
 
-	//implicit downcast
-	operator unit_t& ()
+	template<typename OTHER_UNIT, typename OTHER_STORAGE>
+	self_t& operator = (LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
 	{
-		return static_cast<unit_t&>(*this);
+		mValue = convert(other);
+		return *this;
 	}
 
-	operator storage_t () const
+	operator storage_t() const
 	{
 		return value();
 	}
 
-	storage_t value() const { return mBaseValue; }
-
-	template<typename CONVERTED_TYPE>
-	storage_t as() const
+	storage_t value() const
 	{
-		return CONVERTED_TYPE(*this).value();
+		return mValue;
 	}
 
-	static storage_t convertToBase(storage_t derived_value)
+	void operator += (storage_t value)
 	{
-		return (storage_t)derived_value;
+		mValue += value;
 	}
 
-	static storage_t convertToDerived(storage_t base_value)
+	template<typename OTHER_UNIT, typename OTHER_STORAGE>
+	void operator += (LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
 	{
-		return (storage_t)base_value;
+		mValue += convert(other);
 	}
 
-	void operator += (const unit_t other)
+	void operator -= (storage_t value)
 	{
-		mBaseValue += other.mBaseValue;
+		mValue -= value;
 	}
 
-	void operator -= (const unit_t other)
+	template<typename OTHER_UNIT, typename OTHER_STORAGE>
+	void operator -= (LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
 	{
-		mBaseValue -= other.mBaseValue;
+		mValue -= convert(other);
 	}
 
 	void operator *= (storage_t multiplicand)
 	{
-		mBaseValue *= multiplicand;
+		mValue *= multiplicand;
+	}
+
+	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.");
 	}
 
 	void operator /= (storage_t divisor)
 	{
-		mBaseValue /= divisor;
+		mValue /= divisor;
 	}
 
-protected:
-	void setBaseValue(storage_t value)
+	template<typename OTHER_UNIT, typename OTHER_STORAGE>
+	void operator /= (LLUnit<OTHER_UNIT, OTHER_STORAGE> divisor)
 	{
-		mBaseValue = value;
+		llstatic_assert(sizeof(OTHER_UNIT) == false, "Division of unit types not supported.");
 	}
 
-	storage_t mBaseValue;
-};
+	template<typename SOURCE_UNITS, typename SOURCE_VALUE>
+	static storage_t convert(LLUnit<SOURCE_UNITS, SOURCE_VALUE> 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()); 
+	}
 
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-struct LLUnitTypeWrapper
-:	public LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>
-{
-	typedef LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> unit_t;
-	LLUnitTypeWrapper(const unit_t& other)
-	:	unit_t(other)
-	{}
-};
+protected:
 
+	storage_t mValue;
+};
 
 //
 // operator +
 //
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename STORAGE_TYPE2, typename BASE_UNIT2, typename DERIVED_UNIT2>
-DERIVED_UNIT operator + (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE2, BASE_UNIT2, DERIVED_UNIT2> 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)
 {
-	return DERIVED_UNIT(first + LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>(second).value());
+	LLUnit<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	result += second;
+	return result;
 }
 
+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<STORAGE_TYPE, UNIT_TYPE> result(first);
+	result += second;
+	return result;
+}
 
-//
-// operator -
-//
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename STORAGE_TYPE2, typename BASE_UNIT2, typename DERIVED_UNIT2>
-DERIVED_UNIT operator - (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> 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 DERIVED_UNIT(first - LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>(second).value());
+	LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first);
+	result += second;
+	return result;
 }
 
 //
-// operator *
+// operator -
 //
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-DERIVED_UNIT operator * (STORAGE_TYPE first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> 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)
 {
-	return DERIVED_UNIT(first * second.value());
+	LLUnit<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	result -= second;
+	return result;
 }
 
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-DERIVED_UNIT operator * (LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, STORAGE_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 DERIVED_UNIT(first.value() * second);
+	LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first);
+	result -= second;
+	return result;
 }
 
+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<STORAGE_TYPE, UNIT_TYPE> result(first);
+	result -= second;
+	return result;
+}
 
 //
-// operator /
+// operator *
 //
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-DERIVED_UNIT operator / (STORAGE_TYPE first, LLUnitTypeWrapper<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> 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 DERIVED_UNIT(first / second.value());
+	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(first * second.value());
 }
 
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-DERIVED_UNIT operator / (LLUnitTypeWrapper<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> first, STORAGE_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 DERIVED_UNIT(first.value() / second);
+	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(first.value() * second);
 }
 
-//
-// operator <
-//
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT, typename STORAGE_TYPE2, typename BASE_UNIT2, typename DERIVED_UNIT2>
-
-bool operator < (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+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>)
 {
-	return first < second.value();
+	llstatic_assert(sizeof(STORAGE_TYPE1) == false, "Multiplication of unit types results in new unit type - not supported.");
 }
 
 //
-// operator <=
+// operator /
 //
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-bool operator <= (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE>
+SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	return first <= second.value();
+	return SCALAR_TYPE(first / second.value());
 }
 
-
-//
-// operator >
-//
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-bool operator > (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> 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 first > second.value();
+	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(first.value() / second);
 }
 
-//
-// operator >=
-//
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-bool operator >= (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+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>)
 {
-	return first >= second.value();
+	llstatic_assert(sizeof(STORAGE_TYPE1) == false, "Multiplication of unit types results in new unit type - not supported.");
 }
 
-//
-// operator ==
-//
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-bool operator == (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
-{
-	return first == second.value();
+#define COMPARISON_OPERATORS(op)                                                                     \
+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 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 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);                                                   \
 }
 
-//
-// operator !=
-//
-template<typename STORAGE_TYPE, typename BASE_UNIT, typename DERIVED_UNIT>
-bool operator != (typename LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT>::storage_t first, LLUnitType<STORAGE_TYPE, BASE_UNIT, DERIVED_UNIT> second)
+COMPARISON_OPERATORS(<)
+COMPARISON_OPERATORS(<=)
+COMPARISON_OPERATORS(>)
+COMPARISON_OPERATORS(>=)
+COMPARISON_OPERATORS(==)
+COMPARISON_OPERATORS(!=)
+
+namespace LLUnits
 {
-	return first != second.value();
+#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_BASE_UNIT(unit_name)                                                                          \
-	template<typename STORAGE>                                                                                   \
-	struct unit_name : public LLUnitType<STORAGE, unit_name<STORAGE>, unit_name<STORAGE> >						 \
-	{                                                                                                            \
-		typedef LLUnitType<STORAGE, unit_name> unit_t;						                                     \
-	                                                                                                             \
-		unit_name(storage_t value = 0)                                                                           \
-		:	LLUnitType(value)                                                                                    \
-		{}                                                                                                       \
-		                                                                                                         \
-		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                                            \
-		unit_name(LLUnitType<SOURCE_STORAGE_TYPE, unit_name<SOURCE_STORAGE_TYPE>, SOURCE_TYPE> source)			 \
-		{                                                                                                        \
-			assignFrom(source);			                                                                         \
-		}                                                                                                        \
-		                                                                                                         \
-		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                                            \
-		void assignFrom(LLUnitType<SOURCE_STORAGE_TYPE, unit_name<SOURCE_STORAGE_TYPE>, SOURCE_TYPE> source)     \
-		{                                                                                                        \
-			setBaseValue((storage_t)source.unit_name<SOURCE_STORAGE_TYPE>::unit_t::value());                     \
-		}                                                                                                        \
-	                                                                                                             \
-	};                                                                                                           \
-
-#define LL_DECLARE_DERIVED_UNIT(base_unit, derived_unit, conversion_factor)                                      \
-	template<typename STORAGE>	                                                                                 \
-	struct derived_unit : public LLUnitType<STORAGE, base_unit<STORAGE>, derived_unit<STORAGE> >                 \
-	{                                                                                                            \
-		typedef LLUnitType<STORAGE, base_unit<STORAGE>, derived_unit<STORAGE> > unit_t;				             \
-		                                                                                                         \
-		derived_unit(storage_t value = 0)                                                                        \
-		:	LLUnitType(value)                                                                                    \
-		{}                                                                                                       \
-		                                                                                                         \
-		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                                            \
-		derived_unit(LLUnitType<SOURCE_STORAGE_TYPE, base_unit<SOURCE_STORAGE_TYPE>, SOURCE_TYPE> source)		 \
-		{                                                                                                        \
-			assignFrom(source);					                                                                 \
-		}                                                                                                        \
-		                                                                                                         \
-		template <typename SOURCE_STORAGE_TYPE, typename SOURCE_TYPE>                                            \
-		void assignFrom(LLUnitType<SOURCE_STORAGE_TYPE, base_unit<SOURCE_STORAGE_TYPE>, SOURCE_TYPE> source)     \
-		{                                                                                                        \
-			setBaseValue((storage_t)source.base_unit<SOURCE_STORAGE_TYPE>::unit_t::value());                     \
-		}                                                                                                        \
-		                                                                                                         \
-		static F32 conversionToBaseFactor() { return (F32)(conversion_factor); }                                 \
-		                                                                                                         \
-	};                                                                                                           \
-
-namespace LLUnit
-{
-	LL_DECLARE_BASE_UNIT(Bytes);
-	LL_DECLARE_DERIVED_UNIT(Bytes, Kilobytes, 1024);
-	LL_DECLARE_DERIVED_UNIT(Bytes, Megabytes, 1024 * 1024);
-	LL_DECLARE_DERIVED_UNIT(Bytes, Gigabytes, 1024 * 1024 * 1024);
-	LL_DECLARE_DERIVED_UNIT(Bytes, Bits,	  (1.f / 8.f));
-	LL_DECLARE_DERIVED_UNIT(Bytes, Kilobits,  (1024 / 8));
-	LL_DECLARE_DERIVED_UNIT(Bytes, Megabits,  (1024 / 8));
-	LL_DECLARE_DERIVED_UNIT(Bytes, Gigabits,  (1024 * 1024 * 1024 / 8));
-
-	LL_DECLARE_BASE_UNIT(Seconds);
-	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.f / 1000.f));
-	LL_DECLARE_DERIVED_UNIT(Seconds, Microseconds,	(1.f / (1000000.f)));
-	LL_DECLARE_DERIVED_UNIT(Seconds, Nanoseconds,	(1.f / (1000000000.f)));
-
-	LL_DECLARE_BASE_UNIT(Meters);
-	LL_DECLARE_DERIVED_UNIT(Meters, Kilometers, 1000);
-	LL_DECLARE_DERIVED_UNIT(Meters, Centimeters, 1 / 100);
-	LL_DECLARE_DERIVED_UNIT(Meters, Millimeters, 1 / 1000);
+struct Bytes { typedef Bytes base_unit_t; };
+LL_DECLARE_DERIVED_UNIT(Bytes, Kilobytes, 1024);
+LL_DECLARE_DERIVED_UNIT(Bytes, Megabytes, 1024 * 1024);
+LL_DECLARE_DERIVED_UNIT(Bytes, Gigabytes, 1024 * 1024 * 1024);
+LL_DECLARE_DERIVED_UNIT(Bytes, Bits,	  (1.0 / 8.0));
+LL_DECLARE_DERIVED_UNIT(Bytes, Kilobits,  (1024 / 8));
+LL_DECLARE_DERIVED_UNIT(Bytes, Megabits,  (1024 / 8));
+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));
 }
 
 #endif // LL_LLUNIT_H
-- 
cgit v1.2.3


From a3e3e8b4ccd96e98da73acf1c584bbfa5a8b2b56 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 12 Nov 2012 19:08:14 -0800
Subject: 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

---
 indra/llcommon/llfasttimer.cpp    | 270 ++++++++++++--------------------------
 indra/llcommon/llfasttimer.h      | 121 ++++++-----------
 indra/llcommon/llprocessor.cpp    |   2 +-
 indra/llcommon/llprocessor.h      |   4 +-
 indra/llcommon/lltrace.cpp        |   1 +
 indra/llcommon/lltrace.h          |  39 ++----
 indra/llcommon/lltracerecording.h |  18 +--
 indra/llcommon/llunit.h           | 127 +++++++++++++-----
 8 files changed, 245 insertions(+), 337 deletions(-)

(limited to 'indra/llcommon')

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
-- 
cgit v1.2.3


From c76ed72c609b80b08df6cebd68274c9da6d3de2c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 12 Nov 2012 19:12:20 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system removed remnants of
 LLFastTimer::FrameState

---
 indra/llcommon/llfasttimer.cpp | 16 ++++++----------
 indra/llcommon/llfasttimer.h   | 16 ----------------
 2 files changed, 6 insertions(+), 26 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index c4839fed77..66452fd02a 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -140,15 +140,6 @@ U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
 }
 #endif
 
-LLFastTimer::FrameState::FrameState()
-:	mActiveCount(0),
-	mCalls(0),
-	mSelfTimeCounter(0),
-	mLastCaller(NULL),
-	mMoveUpTree(false)
-{}
-
-
 LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name, bool open, DeclareTimer* parent)
 :	mName(name),
 	mCollapsed(true),
@@ -156,7 +147,12 @@ LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name, bool open, Decl
 	mTreeTimeCounter(0),
 	mCountAverage(0),
 	mCallAverage(0),
-	mNeedsSorting(false)
+	mNeedsSorting(false),
+	mActiveCount(0),
+	mCalls(0),
+	mSelfTimeCounter(0),
+	mLastCaller(NULL),
+	mMoveUpTree(false)
 {
 	setCollapsed(!open);
 
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 31872e4e65..40c2af34e8 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -38,25 +38,9 @@ class LLMutex;
 
 #define LL_FASTTIMER_USE_RDTSC 1
 
-
-LL_COMMON_API void assert_main_thread();
-
 class LL_COMMON_API LLFastTimer
 {
 public:
-	class DeclareTimer;
-	struct LL_COMMON_API FrameState
-	{
-		FrameState();
-
-		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
-	};
-
 	// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances
 	class LL_COMMON_API DeclareTimer
 	:	public LLInstanceTracker<DeclareTimer>
-- 
cgit v1.2.3


From 67ec47e6da389661934ed2ddfa55ca58455fa7e5 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 13 Nov 2012 17:10:10 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system moving fast timers
 into lltrace namespace and accumulation system

---
 indra/llcommon/llfasttimer.cpp    | 186 ++++++++++++++------------
 indra/llcommon/llfasttimer.h      | 268 ++++++++++++++++++++------------------
 indra/llcommon/lltrace.cpp        |   7 +-
 indra/llcommon/lltrace.h          | 194 +++------------------------
 indra/llcommon/lltracerecording.h |  18 +--
 indra/llcommon/llunit.h           |  84 ++++++------
 6 files changed, 322 insertions(+), 435 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 66452fd02a..cced0bdfa9 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -33,8 +33,10 @@
 #include "lltreeiterators.h"
 #include "llsdserialize.h"
 #include "llunit.h"
+#include "llsd.h"
 
 #include <boost/bind.hpp>
+#include <queue>
 
 
 #if LL_WINDOWS
@@ -50,37 +52,40 @@
 #error "architecture not supported"
 #endif
 
+namespace LLTrace
+{
+
 //////////////////////////////////////////////////////////////////////////////
 // statics
 
-S32 LLFastTimer::sCurFrameIndex = -1;
-S32 LLFastTimer::sLastFrameIndex = -1;
-U64 LLFastTimer::sLastFrameTime = LLFastTimer::getCPUClockCount64();
-bool LLFastTimer::sPauseHistory = 0;
-bool LLFastTimer::sResetHistory = 0;
-LLFastTimer::CurTimerData LLFastTimer::sCurTimerData;
-BOOL LLFastTimer::sLog = FALSE;
-std::string LLFastTimer::sLogName = "";
-BOOL LLFastTimer::sMetricLog = FALSE;
-LLMutex* LLFastTimer::sLogLock = NULL;
-std::queue<LLSD> LLFastTimer::sLogQueue;
+S32 Time::sCurFrameIndex = -1;
+S32 Time::sLastFrameIndex = -1;
+U64 Time::sLastFrameTime = Time::getCPUClockCount64();
+bool Time::sPauseHistory = 0;
+bool Time::sResetHistory = 0;
+LLThreadLocalPointer<Time::CurTimerData> Time::sCurTimerData;
+bool Time::sLog = FALSE;
+std::string Time::sLogName = "";
+bool Time::sMetricLog = FALSE;
+static LLMutex*			sLogLock = NULL;
+static std::queue<LLSD> sLogQueue;
 
 #if LL_LINUX || LL_SOLARIS
-U64 LLFastTimer::sClockResolution = 1000000000; // Nanosecond resolution
+U64 Time::sClockResolution = 1000000000; // Nanosecond resolution
 #else
-U64 LLFastTimer::sClockResolution = 1000000; // Microsecond resolution
+U64 Time::sClockResolution = 1000000; // Microsecond resolution
 #endif
 
 // FIXME: move these declarations to the relevant modules
 
 // helper functions
-typedef LLTreeDFSPostIter<LLFastTimer::DeclareTimer, LLFastTimer::DeclareTimer::child_const_iter> timer_tree_bottom_up_iterator_t;
+typedef LLTreeDFSPostIter<BlockTimer, BlockTimer::child_const_iter> timer_tree_bottom_up_iterator_t;
 
-static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(LLFastTimer::DeclareTimer& id) 
+static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(BlockTimer& id) 
 { 
 	return timer_tree_bottom_up_iterator_t(&id, 
-							boost::bind(boost::mem_fn(&LLFastTimer::DeclareTimer::beginChildren), _1), 
-							boost::bind(boost::mem_fn(&LLFastTimer::DeclareTimer::endChildren), _1));
+							boost::bind(boost::mem_fn(&BlockTimer::beginChildren), _1), 
+							boost::bind(boost::mem_fn(&BlockTimer::endChildren), _1));
 }
 
 static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up() 
@@ -88,14 +93,14 @@ static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up()
 	return timer_tree_bottom_up_iterator_t(); 
 }
 
-typedef LLTreeDFSIter<LLFastTimer::DeclareTimer, LLFastTimer::DeclareTimer::child_const_iter> timer_tree_dfs_iterator_t;
+typedef LLTreeDFSIter<BlockTimer, BlockTimer::child_const_iter> timer_tree_dfs_iterator_t;
 
 
-static timer_tree_dfs_iterator_t begin_timer_tree(LLFastTimer::DeclareTimer& id) 
+static timer_tree_dfs_iterator_t begin_timer_tree(BlockTimer& id) 
 { 
 	return timer_tree_dfs_iterator_t(&id, 
-		boost::bind(boost::mem_fn(&LLFastTimer::DeclareTimer::beginChildren), _1), 
-							boost::bind(boost::mem_fn(&LLFastTimer::DeclareTimer::endChildren), _1));
+		boost::bind(boost::mem_fn(&BlockTimer::beginChildren), _1), 
+							boost::bind(boost::mem_fn(&BlockTimer::endChildren), _1));
 }
 
 static timer_tree_dfs_iterator_t end_timer_tree() 
@@ -103,21 +108,21 @@ static timer_tree_dfs_iterator_t end_timer_tree()
 	return timer_tree_dfs_iterator_t(); 
 }
 
-LLFastTimer::DeclareTimer& LLFastTimer::DeclareTimer::getRootTimer()
+BlockTimer& BlockTimer::getRootTimer()
 {
-	static DeclareTimer root_timer("root", true, NULL);
+	static BlockTimer root_timer("root", true, NULL);
 	return root_timer;
 }
 
 
 //static
 #if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
-U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
+U64 Time::countsPerSecond() // counts per second for the *32-bit* timer
 {
 	return sClockResolution >> 8;
 }
 #else // windows or x86-mac or x86-linux or x86-solaris
-U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
+U64 Time::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
@@ -140,19 +145,14 @@ U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
 }
 #endif
 
-LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name, bool open, DeclareTimer* parent)
-:	mName(name),
+BlockTimer::BlockTimer(const char* name, bool open, BlockTimer* parent)
+:	TraceType(name),
 	mCollapsed(true),
 	mParent(NULL),
 	mTreeTimeCounter(0),
 	mCountAverage(0),
 	mCallAverage(0),
-	mNeedsSorting(false),
-	mActiveCount(0),
-	mCalls(0),
-	mSelfTimeCounter(0),
-	mLastCaller(NULL),
-	mMoveUpTree(false)
+	mNeedsSorting(false)
 {
 	setCollapsed(!open);
 
@@ -171,13 +171,13 @@ LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name, bool open, Decl
 	memset(mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
 }
 
-LLFastTimer::DeclareTimer::~DeclareTimer()
+BlockTimer::~BlockTimer()
 {
 	delete[] mCountHistory;
 	delete[] mCallHistory;
 }
 
-void LLFastTimer::DeclareTimer::setParent(DeclareTimer* parent)
+void BlockTimer::setParent(BlockTimer* parent)
 {
 	llassert_always(parent != this);
 	llassert_always(parent != NULL);
@@ -193,8 +193,8 @@ void LLFastTimer::DeclareTimer::setParent(DeclareTimer* parent)
 		// subtract average timing from previous parent
 		mParent->mCountAverage -= mCountAverage;
 
-		std::vector<DeclareTimer*>& children = mParent->getChildren();
-		std::vector<DeclareTimer*>::iterator found_it = std::find(children.begin(), children.end(), this);
+		std::vector<BlockTimer*>& children = mParent->getChildren();
+		std::vector<BlockTimer*>::iterator found_it = std::find(children.begin(), children.end(), this);
 		if (found_it != children.end())
 		{
 			children.erase(found_it);
@@ -209,10 +209,10 @@ void LLFastTimer::DeclareTimer::setParent(DeclareTimer* parent)
 	}
 }
 
-S32 LLFastTimer::DeclareTimer::getDepth()
+S32 BlockTimer::getDepth()
 {
 	S32 depth = 0;
-	DeclareTimer* timerp = mParent;
+	BlockTimer* timerp = mParent;
 	while(timerp)
 	{
 		depth++;
@@ -223,9 +223,9 @@ S32 LLFastTimer::DeclareTimer::getDepth()
 }
 
 // static
-void LLFastTimer::DeclareTimer::processTimes()
+void BlockTimer::processTimes()
 {
-	if (sCurFrameIndex < 0) return;
+	if (Time::getCurFrameIndex() < 0) return;
 
 	buildHierarchy();
 	accumulateTimings();
@@ -234,27 +234,27 @@ void LLFastTimer::DeclareTimer::processTimes()
 // sort child timers by name
 struct SortTimerByName
 {
-	bool operator()(const LLFastTimer::DeclareTimer* i1, const LLFastTimer::DeclareTimer* i2)
+	bool operator()(const BlockTimer* i1, const BlockTimer* i2)
 	{
 		return i1->getName() < i2->getName();
 	}
 };
 
 //static
-void LLFastTimer::DeclareTimer::buildHierarchy()
+void BlockTimer::buildHierarchy()
 {
-	if (sCurFrameIndex < 0 ) return;
+	if (Time::getCurFrameIndex() < 0 ) return;
 
 	// set up initial tree
 	{
-		for (instance_iter it = beginInstances(), end_it = endInstances(); it != end_it; ++it)
+		for (LLInstanceTracker<BlockTimer>::instance_iter it = LLInstanceTracker<BlockTimer>::beginInstances(), end_it = LLInstanceTracker<BlockTimer>::endInstances(); it != end_it; ++it)
 		{
-			DeclareTimer& timer = *it;
-			if (&timer == &DeclareTimer::getRootTimer()) continue;
+			BlockTimer& timer = *it;
+			if (&timer == &BlockTimer::getRootTimer()) continue;
 			
 			// bootstrap tree construction by attaching to last timer to be on stack
 			// when this timer was called
-			if (timer.mLastCaller && timer.mParent == &DeclareTimer::getRootTimer())
+			if (timer.mLastCaller && timer.mParent == &BlockTimer::getRootTimer())
 			{
 				timer.setParent(timer.mLastCaller);
 				// no need to push up tree on first use, flag can be set spuriously
@@ -266,13 +266,13 @@ void LLFastTimer::DeclareTimer::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(DeclareTimer::getRootTimer());
+	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(BlockTimer::getRootTimer());
 		it != end_timer_tree_bottom_up();
 		++it)
 	{
-		DeclareTimer* timerp = *it;
+		BlockTimer* timerp = *it;
 		// skip root timer
-		if (timerp == &DeclareTimer::getRootTimer()) continue;
+		if (timerp == &BlockTimer::getRootTimer()) continue;
 
 		if (timerp->mMoveUpTree)
 		{
@@ -289,11 +289,11 @@ void LLFastTimer::DeclareTimer::buildHierarchy()
 	}
 
 	// sort timers by time last called, so call graph makes sense
-	for(timer_tree_dfs_iterator_t it = begin_timer_tree(DeclareTimer::getRootTimer());
+	for(timer_tree_dfs_iterator_t it = begin_timer_tree(BlockTimer::getRootTimer());
 		it != end_timer_tree();
 		++it)
 	{
-		DeclareTimer* timerp = (*it);
+		BlockTimer* timerp = (*it);
 		if (timerp->mNeedsSorting)
 		{
 			std::sort(timerp->getChildren().begin(), timerp->getChildren().end(), SortTimerByName());
@@ -303,12 +303,12 @@ void LLFastTimer::DeclareTimer::buildHierarchy()
 }
 
 //static
-void LLFastTimer::DeclareTimer::accumulateTimings()
+void BlockTimer::accumulateTimings()
 {
 	U32 cur_time = getCPUClockCount32();
 
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
-	LLFastTimer* cur_timer = sCurTimerData.mCurTimer;
+	Time* cur_timer = sCurTimerData.mCurTimer;
 	// root defined by parent pointing to self
 	CurTimerData* cur_data = &sCurTimerData;
 	while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
@@ -328,11 +328,11 @@ void LLFastTimer::DeclareTimer::accumulateTimings()
 	}
 
 	// traverse tree in DFS post order, or bottom up
-	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(DeclareTimer::getRootTimer());
+	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(BlockTimer::getRootTimer());
 		it != end_timer_tree_bottom_up();
 		++it)
 	{
-		DeclareTimer* timerp = (*it);
+		BlockTimer* timerp = (*it);
 		timerp->mTreeTimeCounter = timerp->mSelfTimeCounter;
 		for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it)
 		{
@@ -354,7 +354,7 @@ void LLFastTimer::DeclareTimer::accumulateTimings()
 }
 
 // static
-void LLFastTimer::DeclareTimer::resetFrame()
+void BlockTimer::resetFrame()
 {
 	if (sLog)
 	{ //output current frame counts to performance log
@@ -379,7 +379,7 @@ void LLFastTimer::DeclareTimer::resetFrame()
 		{
 			for (instance_iter it = beginInstances(), end_it = endInstances(); it != end_it; ++it)
 			{
-				DeclareTimer& timer = *it;
+				BlockTimer& timer = *it;
 				sd[timer.getName()]["Time"] = (LLSD::Real) (timer.mSelfTimeCounter*iclock_freq);	
 				sd[timer.getName()]["Calls"] = (LLSD::Integer) timer.mCalls;
 				
@@ -401,7 +401,7 @@ void LLFastTimer::DeclareTimer::resetFrame()
 	// reset for next frame
 	for (instance_iter it = beginInstances(), end_it = endInstances(); it != end_it; ++it)
 	{
-		DeclareTimer& timer = *it;
+		BlockTimer& timer = *it;
 		timer.mSelfTimeCounter = 0;
 		timer.mCalls = 0;
 		timer.mLastCaller = NULL;
@@ -410,7 +410,7 @@ void LLFastTimer::DeclareTimer::resetFrame()
 }
 
 //static
-void LLFastTimer::DeclareTimer::reset()
+void BlockTimer::reset()
 {
 	resetFrame(); // reset frame data
 
@@ -420,7 +420,7 @@ void LLFastTimer::DeclareTimer::reset()
 
 	// root defined by parent pointing to self
 	CurTimerData* cur_data = &sCurTimerData;
-	LLFastTimer* cur_timer = cur_data->mCurTimer;
+	Time* cur_timer = cur_data->mCurTimer;
 	while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
 	{
 		cur_timer->mStartTime = cur_time;
@@ -434,10 +434,10 @@ void LLFastTimer::DeclareTimer::reset()
 	{
 		for (instance_iter it = beginInstances(), end_it = endInstances(); it != end_it; ++it)
 		{
-			DeclareTimer& timer = *it;
-			if (&timer != &DeclareTimer::getRootTimer()) 
+			BlockTimer& timer = *it;
+			if (&timer != &BlockTimer::getRootTimer()) 
 			{
-				timer.setParent(&DeclareTimer::getRootTimer());
+				timer.setParent(&BlockTimer::getRootTimer());
 			}
 			
 			timer.mCountAverage = 0;
@@ -451,35 +451,35 @@ void LLFastTimer::DeclareTimer::reset()
 	sCurFrameIndex = 0;
 }
 
-U32 LLFastTimer::DeclareTimer::getHistoricalCount(S32 history_index) const
+U32 BlockTimer::getHistoricalCount(S32 history_index) const
 {
-	S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::DeclareTimer::HISTORY_NUM;
+	S32 history_idx = (getLastFrameIndex() + history_index) % BlockTimer::HISTORY_NUM;
 	return mCountHistory[history_idx];
 }
 
-U32 LLFastTimer::DeclareTimer::getHistoricalCalls(S32 history_index ) const
+U32 BlockTimer::getHistoricalCalls(S32 history_index ) const
 {
-	S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::DeclareTimer::HISTORY_NUM;
+	S32 history_idx = (getLastFrameIndex() + history_index) % BlockTimer::HISTORY_NUM;
 	return mCallHistory[history_idx];
 }
 
-std::vector<LLFastTimer::DeclareTimer*>::const_iterator LLFastTimer::DeclareTimer::beginChildren()
+std::vector<BlockTimer*>::const_iterator BlockTimer::beginChildren()
 { 
 	return mChildren.begin(); 
 }
 
-std::vector<LLFastTimer::DeclareTimer*>::const_iterator LLFastTimer::DeclareTimer::endChildren()
+std::vector<BlockTimer*>::const_iterator BlockTimer::endChildren()
 {
 	return mChildren.end();
 }
 
-std::vector<LLFastTimer::DeclareTimer*>& LLFastTimer::DeclareTimer::getChildren()
+std::vector<BlockTimer*>& BlockTimer::getChildren()
 {
 	return mChildren;
 }
 
 //static
-void LLFastTimer::nextFrame()
+void Time::nextFrame()
 {
 	countsPerSecond(); // good place to calculate clock frequency
 	U64 frame_time = getCPUClockCount64();
@@ -490,30 +490,30 @@ void LLFastTimer::nextFrame()
 
 	if (!sPauseHistory)
 	{
-		DeclareTimer::processTimes();
+		BlockTimer::processTimes();
 		sLastFrameIndex = sCurFrameIndex++;
 	}
 	
 	// get ready for next frame
-	DeclareTimer::resetFrame();
+	BlockTimer::resetFrame();
 	sLastFrameTime = frame_time;
 }
 
 //static
-void LLFastTimer::dumpCurTimes()
+void Time::dumpCurTimes()
 {
 	// accumulate timings, etc.
-	DeclareTimer::processTimes();
+	BlockTimer::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(DeclareTimer::getRootTimer());
+	for(timer_tree_dfs_iterator_t it = begin_timer_tree(BlockTimer::getRootTimer());
 		it != end_timer_tree();
 		++it)
 	{
-		DeclareTimer* timerp = (*it);
+		BlockTimer* 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;
@@ -534,14 +534,14 @@ void LLFastTimer::dumpCurTimes()
 }
 
 //static 
-void LLFastTimer::reset()
+void Time::reset()
 {
-	DeclareTimer::reset();
+	BlockTimer::reset();
 }
 
 
 //static
-void LLFastTimer::writeLog(std::ostream& os)
+void Time::writeLog(std::ostream& os)
 {
 	while (!sLogQueue.empty())
 	{
@@ -552,3 +552,25 @@ void LLFastTimer::writeLog(std::ostream& os)
 	}
 }
 
+
+void LLTrace::TimerAccumulator::addSamples( const LLTrace::TimerAccumulator& other )
+{
+	mSelfTimeCounter += other.mSelfTimeCounter;
+	mTotalTimeCounter += other.mTotalTimeCounter;
+	mCalls += other.mCalls;
+	if (!mLastCaller)
+	{
+		mLastCaller = other.mLastCaller;
+	}
+
+	//mActiveCount stays the same;
+	mMoveUpTree |= other.mMoveUpTree;
+}
+
+void LLTrace::TimerAccumulator::reset( const LLTrace::TimerAccumulator* other )
+{
+	mTotalTimeCounter = 0;
+	mSelfTimeCounter = 0;
+	mCalls = 0;
+}
+}
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 40c2af34e8..f5e6d874a2 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -33,131 +33,26 @@
 
 class LLMutex;
 
-#include <queue>
-#include "llsd.h"
+#include "lltrace.h"
 
 #define LL_FASTTIMER_USE_RDTSC 1
 
-class LL_COMMON_API LLFastTimer
+namespace LLTrace
 {
-public:
-	// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances
-	class LL_COMMON_API DeclareTimer
-	:	public LLInstanceTracker<DeclareTimer>
-	{
-	public:
-		DeclareTimer(const std::string& name, bool open = false, DeclareTimer* parent = &getRootTimer());
-		~DeclareTimer();
-
-		enum { HISTORY_NUM = 300 };
-
-		const std::string& getName() const { return mName; }
-		DeclareTimer* getParent() const { return mParent; }
-		void setParent(DeclareTimer* parent);
-		S32 getDepth();
-
-		typedef std::vector<DeclareTimer*>::const_iterator child_const_iter;
-		child_const_iter beginChildren();
-		child_const_iter endChildren();
-		std::vector<DeclareTimer*>& getChildren();
-
-		void setCollapsed(bool collapsed)	{ mCollapsed = collapsed; }
-		bool getCollapsed() const			{ return mCollapsed; }
-
-		U32 getCountAverage() const { return mCountAverage; }
-		U32 getCallAverage() const	{ return mCallAverage; }
-
-		U32 getHistoricalCount(S32 history_index = 0) const;
-		U32 getHistoricalCalls(S32 history_index = 0) const;
-
-		static DeclareTimer& getRootTimer();
-
-	private:
-		friend class LLFastTimer;
-
-		// recursive call to gather total time from children
-		static void accumulateTimings();
-
-		// updates cumulative times and hierarchy,
-		// can be called multiple times in a frame, at any point
-		static void processTimes();
-
-		static void buildHierarchy();
-		static void resetFrame();
-		static void reset();
-
-		//
-		// members
-		//
-		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;
-
-		// 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*						mCountHistory;
-		U32*						mCallHistory;
-
-		// tree structure
-		DeclareTimer*				mParent;				// DeclareTimer of caller(parent)
-		std::vector<DeclareTimer*>	mChildren;
-		bool						mCollapsed;				// don't show children
-		bool						mNeedsSorting;			// sort children whenever child added
-	};
 
+class Time
+{
 public:
-	LL_FORCE_INLINE LLFastTimer(LLFastTimer::DeclareTimer& timer)
-	{
-#if FAST_TIMER_ON
-		mStartTime = getCPUClockCount32();
-
-		timer.mActiveCount++;
-		timer.mCalls++;
-		// keep current parent as long as it is active when we are
-		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->mTimerData = &timer;
-		cur_timer_data->mChildTime = 0;
-#endif
-	}
-
-	LL_FORCE_INLINE ~LLFastTimer()
-	{
-#if FAST_TIMER_ON
-		U32 total_time = getCPUClockCount32() - mStartTime;
-		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
-		timer_data->mLastCaller = mLastTimerData.mTimerData;
-
-		// we are only tracking self time, so subtract our total time delta from parents
-		mLastTimerData.mChildTime += total_time;
+	typedef Time self_t;
+	typedef class BlockTimer DeclareTimer;
 
-		LLFastTimer::sCurTimerData = mLastTimerData;
-#endif
-	}
+public:
+	Time(BlockTimer& timer);
+	~Time();
 
 public:
-	static LLMutex*			sLogLock;
-	static std::queue<LLSD> sLogQueue;
-	static BOOL				sLog;
-	static BOOL				sMetricLog;
+	static bool				sLog;
+	static bool				sMetricLog;
 	static std::string		sLogName;
 	static bool 			sPauseHistory;
 	static bool 			sResetHistory;
@@ -180,11 +75,11 @@ public:
 
 	struct CurTimerData
 	{
-		LLFastTimer*	mCurTimer;
-		DeclareTimer*	mTimerData;
-		U32				mChildTime;
+		Time*				mCurTimer;
+		BlockTimer*			mTimerData;
+		U64					mChildTime;
 	};
-	static CurTimerData		sCurTimerData;
+	static LLThreadLocalPointer<CurTimerData>	sCurTimerData;
 
 private:
 
@@ -211,14 +106,14 @@ private:
 	//#undef _interlockedbittestandset
 	//#undef _interlockedbittestandreset
 
-	//inline U32 LLFastTimer::getCPUClockCount32()
+	//inline U32 Time::getCPUClockCount32()
 	//{
 	//	U64 time_stamp = __rdtsc();
 	//	return (U32)(time_stamp >> 8);
 	//}
 	//
 	//// return full timer value, *not* shifted by 8 bits
-	//inline U64 LLFastTimer::getCPUClockCount64()
+	//inline U64 Time::getCPUClockCount64()
 	//{
 	//	return __rdtsc();
 	//}
@@ -258,7 +153,7 @@ private:
 	}
 
 #else
-	//LL_COMMON_API U64 get_clock_count(); // in lltimer.cpp
+	//U64 get_clock_count(); // in lltimer.cpp
 	// These use QueryPerformanceCounter, which is arguably fine and also works on AMD architectures.
 	static U32 getCPUClockCount32()
 	{
@@ -330,10 +225,131 @@ private:
 	static S32	sLastFrameIndex;
 	static U64	sLastFrameTime;
 
-	U32							mStartTime;
-	LLFastTimer::CurTimerData	mLastTimerData;
+	U64							mStartTime;
+	Time::CurTimerData	mLastTimerData;
+};
+
+struct TimerAccumulator
+{
+	void addSamples(const TimerAccumulator& other);
+	void reset(const TimerAccumulator* other);
+
+	//
+	// members
+	//
+	U64 						mSelfTimeCounter,
+								mTotalTimeCounter;
+	U32 						mCalls;
+	BlockTimer*					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 Time stack instances
+class BlockTimer 
+:	public TraceType<TimerAccumulator>,
+	public LLInstanceTracker<BlockTimer>
+{
+public:
+	BlockTimer(const char* name, bool open = false, BlockTimer* parent = &getRootTimer());
+	~BlockTimer();
+
+	enum { HISTORY_NUM = 300 };
+
+	BlockTimer* getParent() const { return mParent; }
+	void setParent(BlockTimer* parent);
+	S32 getDepth();
+
+	typedef std::vector<BlockTimer*>::const_iterator child_const_iter;
+	child_const_iter beginChildren();
+	child_const_iter endChildren();
+	std::vector<BlockTimer*>& getChildren();
+
+	void setCollapsed(bool collapsed)	{ mCollapsed = collapsed; }
+	bool getCollapsed() const			{ return mCollapsed; }
+
+	U32 getCountAverage() const { return mCountAverage; }
+	U32 getCallAverage() const	{ return mCallAverage; }
+
+	U32 getHistoricalCount(S32 history_index = 0) const;
+	U32 getHistoricalCalls(S32 history_index = 0) const;
+
+	static BlockTimer& getRootTimer();
+
+private:
+	friend class Time;
+
+	// recursive call to gather total time from children
+	static void accumulateTimings();
+
+	// updates cumulative times and hierarchy,
+	// can be called multiple times in a frame, at any point
+	static void processTimes();
+
+	static void buildHierarchy();
+	static void resetFrame();
+	static void reset();
+
+	// 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; 
+
+	U32 						mCountAverage;
+	U32							mCallAverage;
+
+	U32*						mCountHistory;
+	U32*						mCallHistory;
+
+	// tree structure
+	BlockTimer*					mParent;				// BlockTimer of caller(parent)
+	std::vector<BlockTimer*>	mChildren;
+	bool						mCollapsed;				// don't show children
+	bool						mNeedsSorting;			// sort children whenever child added
 };
 
-typedef class LLFastTimer LLFastTimer;
+LL_FORCE_INLINE Time::Time(BlockTimer& timer)
+{
+#if FAST_TIMER_ON
+	mStartTime = getCPUClockCount64();
+
+	TimerAccumulator& accumulator = timer.getPrimaryAccumulator();
+	accumulator.mActiveCount++;
+	accumulator.mCalls++;
+	// keep current parent as long as it is active when we are
+	accumulator.mMoveUpTree |= (timer.mParent->getPrimaryAccumulator().mActiveCount == 0);
+
+	CurTimerData* cur_timer_data = Time::sCurTimerData.get();
+	// store top of stack
+	mLastTimerData = *cur_timer_data;
+	// push new information
+	cur_timer_data->mCurTimer = this;
+	cur_timer_data->mTimerData = &timer;
+	cur_timer_data->mChildTime = 0;
+#endif
+}
+
+LL_FORCE_INLINE Time::~Time()
+{
+#if FAST_TIMER_ON
+	U64 total_time = getCPUClockCount64() - mStartTime;
+	CurTimerData* cur_timer_data = Time::sCurTimerData.get();
+	TimerAccumulator& accumulator = cur_timer_data->mTimerData->getPrimaryAccumulator();
+	accumulator.mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
+	accumulator.mTotalTimeCounter += total_time;
+	accumulator.mActiveCount--;
+
+	// store last caller to bootstrap tree creation
+	// do this in the destructor in case of recursion to get topmost caller
+	accumulator.mLastCaller = mLastTimerData.mTimerData;
+
+	// we are only tracking self time, so subtract our total time delta from parents
+	mLastTimerData.mChildTime += total_time;
+
+	*sCurTimerData = mLastTimerData;
+#endif
+}
+
+}
+
+typedef LLTrace::Time LLFastTimer;
 
 #endif // LL_LLFASTTIMER_H
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 3f605f2c74..afb175c398 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -28,6 +28,7 @@
 #include "lltrace.h"
 #include "lltracerecording.h"
 #include "lltracethreadrecorder.h"
+#include "llfasttimer.h"
 
 namespace LLTrace
 {
@@ -37,13 +38,15 @@ static MasterThreadRecorder* gMasterThreadRecorder = NULL;
 void init()
 {
 	gMasterThreadRecorder = new MasterThreadRecorder();
+	Time::sCurTimerData = new Time::CurTimerData();
 }
 
 void cleanup()
 {
 	delete gMasterThreadRecorder;
-	LLUnitStrict<LLUnits::Seconds, F32> seconds;
 	gMasterThreadRecorder = NULL;
+	delete Time::sCurTimerData.get();
+	Time::sCurTimerData = NULL;
 }
 
 MasterThreadRecorder& getMasterThreadRecorder()
@@ -59,6 +62,4 @@ LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
 
 }
 
-BlockTimer::Recorder::StackEntry BlockTimer::sCurRecorder;
-
 }
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 549e407822..fb9dca5e84 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -32,7 +32,6 @@
 
 #include "llmemory.h"
 #include "llrefcount.h"
-//#include "lltracethreadrecorder.h"
 #include "llunit.h"
 #include "llapr.h"
 
@@ -61,8 +60,8 @@ namespace LLTrace
 	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::Meters, F64>		Meters;
+	typedef LLUnit<LLUnits::Kilometers, F64>	Kilometers;
 	typedef LLUnit<LLUnits::Centimeters, F64>	Centimeters;
 	typedef LLUnit<LLUnits::Millimeters, F64>	Millimeters;
 
@@ -71,11 +70,11 @@ namespace LLTrace
 
 	LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder();
 
-	class LL_COMMON_API MasterThreadRecorder& getMasterThreadRecorder();
+	class MasterThreadRecorder& getMasterThreadRecorder();
 
 	// one per thread per type
 	template<typename ACCUMULATOR>
-	class LL_COMMON_API AccumulatorBuffer : public LLRefCount
+	class AccumulatorBuffer : public LLRefCount
 	{
 		static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64;
 	private:
@@ -199,7 +198,7 @@ namespace LLTrace
 	template<typename ACCUMULATOR> LLThreadLocalPointer<ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>::sPrimaryStorage;
 
 	template<typename ACCUMULATOR>
-	class LL_COMMON_API TraceType 
+	class TraceType 
 	:	 public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
 	{
 	public:
@@ -218,6 +217,9 @@ namespace LLTrace
 
 		size_t getIndex() const { return mAccumulatorIndex; }
 
+		std::string& getName() { return mName; }
+		const std::string& getName() const { return mName; }
+
 	protected:
 		std::string	mName;
 		std::string mDescription;
@@ -225,7 +227,7 @@ namespace LLTrace
 	};
 
 	template<typename T>
-	class LL_COMMON_API MeasurementAccumulator
+	class MeasurementAccumulator
 	{
 	public:
 		typedef T value_t;
@@ -339,7 +341,7 @@ namespace LLTrace
 	};
 
 	template<typename T>
-	class LL_COMMON_API CountAccumulator
+	class CountAccumulator
 	{
 	public:
 		typedef CountAccumulator<T> self_t;
@@ -378,11 +380,8 @@ namespace LLTrace
 		U32	mNumSamples;
 	};
 
-	typedef TraceType<MeasurementAccumulator<F64> > measurement_common_float_t;
-	typedef TraceType<MeasurementAccumulator<S64> > measurement_common_int_t;
-
-	template <typename T = F64, typename IS_UNIT = void>
-	class LL_COMMON_API Measurement
+	template <typename T = F64>
+	class Measurement
 	:	public TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
 	{
 	public:
@@ -392,37 +391,16 @@ namespace LLTrace
 		:	TraceType(name, description)
 		{}
 
-		void sample(T value)
-		{
-			getPrimaryAccumulator().sample((storage_t)value);
-		}
-	};
-
-	template <typename T>
-	class LL_COMMON_API Measurement <T, typename T::is_unit_tag_t>
-	:	public TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<typename T::storage_t>::type_t> >
-	{
-	public:
-		typedef typename LLUnits::HighestPrecisionType<typename T::storage_t>::type_t storage_t;
-
-		Measurement(const char* name, const char* description = NULL) 
-		:	TraceType(name, description)
-		{}
-
 		template<typename UNIT_T>
 		void sample(UNIT_T value)
 		{
-			T converted_value;
-			converted_value = value;
-			getPrimaryAccumulator().sample((storage_t)converted_value.value());
+			T converted_value(value);
+			getPrimaryAccumulator().sample((storage_t)converted_value);
 		}
 	};
 
-	typedef TraceType<CountAccumulator<F64> > count_common_float_t;
-	typedef TraceType<CountAccumulator<S64> > count_common_int_t;
-
-	template <typename T = F64, typename IS_UNIT = void>
-	class LL_COMMON_API Count 
+	template <typename T = F64>
+	class Count 
 	:	public TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
 	{
 	public:
@@ -432,148 +410,12 @@ namespace LLTrace
 		:	TraceType(name)
 		{}
 
-		void add(T value)
-		{
-			getPrimaryAccumulator().add((storage_t)value);
-		}
-	};
-
-	template <typename T>
-	class LL_COMMON_API Count <T, typename T::is_unit_tag_t>
-	:	public TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<typename T::storage_t>::type_t> >
-	{
-	public:
-		typedef typename LLUnits::HighestPrecisionType<typename T::storage_t>::type_t storage_t;
-
-		Count(const char* name, const char* description = NULL) 
-		:	TraceType(name)
-		{}
-
 		template<typename UNIT_T>
 		void add(UNIT_T value)
 		{
-			T converted_value;
-			converted_value = value;
-			getPrimaryAccumulator().add((storage_t)converted_value.value());
-		}
-	};
-
-	class LL_COMMON_API TimerAccumulator
-	{
-	public:
-		typedef TimerAccumulator self_t;
-
-		U32 							mTotalTimeCounter,
-										mChildTimeCounter,
-										mCalls;
-
-		TimerAccumulator*				mParent;		// info for caller timer
-		TimerAccumulator*				mLastCaller;	// used to bootstrap tree construction
-		const class BlockTimer*			mTimer;			// points to block timer associated with this storage
-		U8								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::vector<TimerAccumulator*>	mChildren;		// currently assumed child timers
-
-		void addSamples(const TimerAccumulator& other)
-		{
-			mTotalTimeCounter += other.mTotalTimeCounter;
-			mChildTimeCounter += other.mChildTimeCounter;
-			mCalls += other.mCalls;
-		}
-
-		void reset(const self_t* other)
-		{
-			mTotalTimeCounter = 0;
-			mChildTimeCounter = 0;
-			mCalls = 0;
+			T converted_value(value);
+			getPrimaryAccumulator().add((storage_t)converted_value);
 		}
-
-	};
-
-	class LL_COMMON_API BlockTimer : public TraceType<TimerAccumulator>
-	{
-	public:
-		BlockTimer(const char* name)
-		:	TraceType(name)
-		{}
-
-		struct Recorder
-		{
-			struct StackEntry
-			{
-				Recorder*			mRecorder;
-				TimerAccumulator*	mAccumulator;
-				U32					mChildTime;
-			};
-
-			LL_FORCE_INLINE Recorder(BlockTimer& block_timer)
-			:	mLastRecorder(sCurRecorder)
-			{
-				mStartTime = getCPUClockCount32();
-				TimerAccumulator* accumulator = &block_timer.getPrimaryAccumulator(); // get per-thread accumulator
-				accumulator->mActiveCount++;
-				accumulator->mCalls++;
-				accumulator->mMoveUpTree |= (accumulator->mParent->mActiveCount == 0);
-
-				// push new timer on stack
-				sCurRecorder.mRecorder = this;
-				sCurRecorder.mAccumulator = accumulator;
-				sCurRecorder.mChildTime = 0;
-			}
-
-			LL_FORCE_INLINE ~Recorder()
-			{
-				U32 total_time = getCPUClockCount32() - mStartTime;
-
-				TimerAccumulator* accumulator = sCurRecorder.mAccumulator;
-				accumulator->mTotalTimeCounter += total_time;
-				accumulator->mChildTimeCounter += sCurRecorder.mChildTime;
-				accumulator->mActiveCount--;
-
-				accumulator->mLastCaller = mLastRecorder.mAccumulator;
-				mLastRecorder.mChildTime += total_time;
-
-				// pop stack
-				sCurRecorder = mLastRecorder;
-			}
-
-			StackEntry mLastRecorder;
-			U32 mStartTime;
-		};
-
-	private:
-		static U32 getCPUClockCount32()
-		{
-			U32 ret_val;
-			__asm
-			{
-				_emit   0x0f
-				_emit   0x31
-				shr eax,8
-				shl edx,24
-				or eax, edx
-				mov dword ptr [ret_val], eax
-			}
-			return ret_val;
-		}
-
-		// return full timer value, *not* shifted by 8 bits
-		static U64 getCPUClockCount64()
-		{
-			U64 ret_val;
-			__asm
-			{
-				_emit   0x0f
-				_emit   0x31
-				mov eax,eax
-				mov edx,edx
-				mov dword ptr [ret_val+4], edx
-				mov dword ptr [ret_val], eax
-			}
-			return ret_val;
-		}
-
-		static Recorder::StackEntry sCurRecorder;
 	};
 }
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 16b80fd1d8..4dcadfdf29 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -120,7 +120,7 @@ namespace LLTrace
 		F64 getSum(const TraceType<CountAccumulator<F64> >& stat) const;
 		S64 getSum(const TraceType<CountAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getSum(const Count<T, typename T::is_unit_tag_t>& stat) const
+		T getSum(const Count<T>& stat) const
 		{
 			return (T)getSum(static_cast<const TraceType<CountAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -128,7 +128,7 @@ namespace LLTrace
 		F64 getPerSec(const TraceType<CountAccumulator<F64> >& stat) const;
 		F64 getPerSec(const TraceType<CountAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getPerSec(const Count<T, typename T::is_unit_tag_t>& stat) const
+		T getPerSec(const Count<T>& stat) const
 		{
 			return (T)getPerSec(static_cast<const TraceType<CountAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -141,7 +141,7 @@ namespace LLTrace
 		F64 getSum(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		S64 getSum(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getSum(const Measurement<T, typename T::is_unit_tag_t>& stat) const
+		T getSum(const Measurement<T>& stat) const
 		{
 			return (T)getSum(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -149,7 +149,7 @@ namespace LLTrace
 		F64 getPerSec(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		F64 getPerSec(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getPerSec(const Measurement<T, typename T::is_unit_tag_t>& stat) const
+		T getPerSec(const Measurement<T>& stat) const
 		{
 			return (T)getPerSec(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -157,7 +157,7 @@ namespace LLTrace
 		F64 getMin(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		S64 getMin(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getMin(const Measurement<T, typename T::is_unit_tag_t>& stat) const
+		T getMin(const Measurement<T>& stat) const
 		{
 			return (T)getMin(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -165,7 +165,7 @@ namespace LLTrace
 		F64 getMax(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		S64 getMax(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getMax(const Measurement<T, typename T::is_unit_tag_t>& stat) const
+		T getMax(const Measurement<T>& stat) const
 		{
 			return (T)getMax(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -173,7 +173,7 @@ namespace LLTrace
 		F64 getMean(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		F64 getMean(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getMean(Measurement<T, typename T::is_unit_tag_t>& stat) const
+		T getMean(Measurement<T>& stat) const
 		{
 			return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -181,7 +181,7 @@ namespace LLTrace
 		F64 getStandardDeviation(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		F64 getStandardDeviation(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getStandardDeviation(const Measurement<T, typename T::is_unit_tag_t>& stat) const
+		T getStandardDeviation(const Measurement<T>& stat) const
 		{
 			return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -189,7 +189,7 @@ namespace LLTrace
 		F64 getLastValue(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		S64 getLastValue(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getLastValue(const Measurement<T, typename T::is_unit_tag_t>& stat) const
+		T getLastValue(const Measurement<T>& stat) const
 		{
 			return (T)getLastValue(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 54ba1d67db..4ac2197c11 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -209,26 +209,26 @@ private:
 //
 // operator +
 //
-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)
+template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2>
+LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator + (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second)
 {
-	LLUnit<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	LLUnit<UNIT_TYPE1, STORAGE_TYPE1> result(first);
 	result += second;
 	return result;
 }
 
-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)
+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)
 {
-	LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first);
+	LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first);
 	result += second;
 	return result;
 }
 
-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)
+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)
 {
-	LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first);
+	LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first);
 	result += second;
 	return result;
 }
@@ -236,27 +236,27 @@ LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (SCALAR_TYPE first, LLUnit<STORAGE_TY
 //
 // operator -
 //
-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)
+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)
 {
-	LLUnit<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	LLUnit<UNIT_TYPE1, STORAGE_TYPE1> result(first);
 	result -= second;
 	return result;
 }
 
 
-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)
+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)
 {
-	LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first);
+	LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first);
 	result -= second;
 	return result;
 }
 
-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)
+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)
 {
-	LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first);
+	LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first);
 	result -= second;
 	return result;
 }
@@ -264,20 +264,20 @@ LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (SCALAR_TYPE first, LLUnit<STORAGE_TY
 //
 // operator *
 //
-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)
+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)
 {
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(first * second.value());
+	return LLUnit<UNIT_TYPE, STORAGE_TYPE>(first * second.value());
 }
 
-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)
+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)
 {
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(first.value() * second);
+	return LLUnit<UNIT_TYPE, STORAGE_TYPE>(first.value() * second);
 }
 
-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>)
+template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2>
+void operator * (LLUnit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnit<UNIT_TYPE2, STORAGE_TYPE2>)
 {
 	// 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.");
@@ -286,40 +286,40 @@ void operator * (LLUnit<STORAGE_TYPE1, UNIT_TYPE1>, LLUnit<STORAGE_TYPE2, UNIT_T
 //
 // operator /
 //
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE>
-SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
+template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE>
+SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second)
 {
 	return SCALAR_TYPE(first / second.value());
 }
 
-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)
+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)
 {
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(first.value() / second);
+	return LLUnit<UNIT_TYPE, STORAGE_TYPE>(first.value() / second);
 }
 
-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>)
+template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2>
+void operator / (LLUnit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnit<UNIT_TYPE2, STORAGE_TYPE2>)
 {
 	// 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)                                                                     \
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE>                            \
-bool operator op (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)                         \
+template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE>                            \
+bool operator op (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second)                         \
 {                                                                                                    \
 	return first op second.value();                                                                  \
 }                                                                                                    \
 	                                                                                                 \
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE>                            \
-bool operator op (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second)                         \
+template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE>                            \
+bool operator op (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second)                         \
 {                                                                                                    \
 	return first.value() op 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) \
+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) \
 {                                                                                                    \
 	return first.value() op first.convert(second);                                                   \
 }
@@ -333,6 +333,12 @@ COMPARISON_OPERATORS(!=)
 
 namespace LLUnits
 {
+template<typename UNIT_TYPE, typename STORAGE_TYPE> 
+struct HighestPrecisionType<LLUnit<UNIT_TYPE, STORAGE_TYPE> >
+{
+	typedef typename HighestPrecisionType<STORAGE_TYPE>::type_t type_t;
+};
+
 #define LL_DECLARE_DERIVED_UNIT(base_unit_name, unit_name, conversion_factor)                                                                                   \
 struct unit_name                                                                                                                                                \
 {                                                                                                                                                               \
-- 
cgit v1.2.3


From 9d77e030d9a0d23cebce616631677459eec1612c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 14 Nov 2012 23:52:27 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system cleaning up build
 moved most includes of windows.h to llwin32headers.h to disable min/max
 macros, etc streamlined Time class and consolidated functionality in
 BlockTimer class llfasttimer is no longer included via llstring.h, so had to
 add it manually in several places

---
 indra/llcommon/llapr.h                       |  12 +-
 indra/llcommon/lldate.cpp                    |   1 +
 indra/llcommon/llfasttimer.cpp               | 120 ++++++++++---------
 indra/llcommon/llfasttimer.h                 | 165 ++++++++++++---------------
 indra/llcommon/llfile.cpp                    |   2 +-
 indra/llcommon/llfindlocale.cpp              |   2 +-
 indra/llcommon/llinitparam.cpp               |   1 +
 indra/llcommon/llinitparam.h                 |   1 +
 indra/llcommon/llmemory.cpp                  |   1 -
 indra/llcommon/llmetricperformancetester.cpp |   6 +-
 indra/llcommon/llmortician.h                 |   1 +
 indra/llcommon/llprocess.h                   |   3 +-
 indra/llcommon/llprocessor.cpp               |   4 +-
 indra/llcommon/llsdparam.h                   |   1 +
 indra/llcommon/llstacktrace.cpp              |   2 +-
 indra/llcommon/llstring.cpp                  |   5 +-
 indra/llcommon/llstring.h                    |   3 +-
 indra/llcommon/llsys.cpp                     |   5 +-
 indra/llcommon/lltimer.cpp                   |   6 +-
 indra/llcommon/lltrace.cpp                   |   6 +-
 indra/llcommon/lltrace.h                     |  22 +++-
 indra/llcommon/lltracerecording.h            |   8 +-
 indra/llcommon/lltracethreadrecorder.cpp     |   1 +
 indra/llcommon/llunit.h                      |   9 +-
 indra/llcommon/lluuid.cpp                    |   4 +-
 indra/llcommon/llwin32headers.h              |  38 ++++++
 indra/llcommon/llwin32headerslean.h          |  37 ++++++
 27 files changed, 266 insertions(+), 200 deletions(-)
 create mode 100644 indra/llcommon/llwin32headers.h
 create mode 100644 indra/llcommon/llwin32headerslean.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 510725ffc6..c77d96c1c9 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -32,16 +32,6 @@
 #if LL_LINUX || LL_SOLARIS
 #include <sys/param.h>  // Need PATH_MAX in APR headers...
 #endif
-#if LL_WINDOWS
-	// Limit Windows API to small and manageable set.
-	// If you get undefined symbols, find the appropriate
-	// Windows header file and include that in your .cpp file.
-	#define WIN32_LEAN_AND_MEAN
-	#include <winsock2.h>
-	#include <windows.h>
-	#undef min
-	#undef max
-#endif
 
 #include <boost/noncopyable.hpp>
 
@@ -340,7 +330,7 @@ public:
 
 
 	LLThreadLocalPointer(const LLThreadLocalPointer<T>& other)
-	:	LLThreadLocalPointerBase(other)
+		:	LLThreadLocalPointerBase(other)
 	{
 		set(other.get());		
 	}
diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp
index 5569b4102d..2efe39e158 100644
--- a/indra/llcommon/lldate.cpp
+++ b/indra/llcommon/lldate.cpp
@@ -39,6 +39,7 @@
 
 #include "lltimer.h"
 #include "llstring.h"
+#include "llfasttimer.h"
 
 static const F64 DATE_EPOCH = 0.0;
 
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index cced0bdfa9..d007f76e5f 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -58,22 +58,22 @@ namespace LLTrace
 //////////////////////////////////////////////////////////////////////////////
 // statics
 
-S32 Time::sCurFrameIndex = -1;
-S32 Time::sLastFrameIndex = -1;
-U64 Time::sLastFrameTime = Time::getCPUClockCount64();
-bool Time::sPauseHistory = 0;
-bool Time::sResetHistory = 0;
-LLThreadLocalPointer<Time::CurTimerData> Time::sCurTimerData;
-bool Time::sLog = FALSE;
-std::string Time::sLogName = "";
-bool Time::sMetricLog = FALSE;
+S32 BlockTimer::sCurFrameIndex = -1;
+S32 BlockTimer::sLastFrameIndex = -1;
+U64 BlockTimer::sLastFrameTime = BlockTimer::getCPUClockCount64();
+bool BlockTimer::sPauseHistory = 0;
+bool BlockTimer::sResetHistory = 0;
+LLThreadLocalPointer<CurTimerData> BlockTimer::sCurTimerData;
+bool BlockTimer::sLog = false;
+std::string BlockTimer::sLogName = "";
+bool BlockTimer::sMetricLog = false;
 static LLMutex*			sLogLock = NULL;
 static std::queue<LLSD> sLogQueue;
 
 #if LL_LINUX || LL_SOLARIS
-U64 Time::sClockResolution = 1000000000; // Nanosecond resolution
+U64 BlockTimer::sClockResolution = 1000000000; // Nanosecond resolution
 #else
-U64 Time::sClockResolution = 1000000; // Microsecond resolution
+U64 BlockTimer::sClockResolution = 1000000; // Microsecond resolution
 #endif
 
 // FIXME: move these declarations to the relevant modules
@@ -114,15 +114,22 @@ BlockTimer& BlockTimer::getRootTimer()
 	return root_timer;
 }
 
+void BlockTimer::pushLog(LLSD log)
+{
+	LLMutexLock lock(sLogLock);
+
+	sLogQueue.push(log);
+}
+
 
 //static
 #if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
-U64 Time::countsPerSecond() // counts per second for the *32-bit* timer
+U64 BlockTimer::countsPerSecond() // counts per second for the *32-bit* timer
 {
 	return sClockResolution >> 8;
 }
 #else // windows or x86-mac or x86-linux or x86-solaris
-U64 Time::countsPerSecond() // counts per second for the *32-bit* timer
+U64 BlockTimer::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
@@ -225,7 +232,7 @@ S32 BlockTimer::getDepth()
 // static
 void BlockTimer::processTimes()
 {
-	if (Time::getCurFrameIndex() < 0) return;
+	if (getCurFrameIndex() < 0) return;
 
 	buildHierarchy();
 	accumulateTimings();
@@ -243,7 +250,7 @@ struct SortTimerByName
 //static
 void BlockTimer::buildHierarchy()
 {
-	if (Time::getCurFrameIndex() < 0 ) return;
+	if (getCurFrameIndex() < 0 ) return;
 
 	// set up initial tree
 	{
@@ -254,11 +261,11 @@ void BlockTimer::buildHierarchy()
 			
 			// bootstrap tree construction by attaching to last timer to be on stack
 			// when this timer was called
-			if (timer.mLastCaller && timer.mParent == &BlockTimer::getRootTimer())
+			if (timer.getPrimaryAccumulator().mLastCaller && timer.mParent == &BlockTimer::getRootTimer())
 			{
-				timer.setParent(timer.mLastCaller);
+				timer.setParent(timer.getPrimaryAccumulator().mLastCaller);
 				// no need to push up tree on first use, flag can be set spuriously
-				timer.mMoveUpTree = false;
+				timer.getPrimaryAccumulator().mMoveUpTree = false;
 			}
 		}
 	}
@@ -274,14 +281,14 @@ void BlockTimer::buildHierarchy()
 		// skip root timer
 		if (timerp == &BlockTimer::getRootTimer()) continue;
 
-		if (timerp->mMoveUpTree)
+		if (timerp->getPrimaryAccumulator().mMoveUpTree)
 		{
-			// since ancestors have already been visited, reparenting won't affect tree traversal
+			// since ancestors have already been visited, re-parenting 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->mMoveUpTree = false;
+			timerp->getPrimaryAccumulator().mMoveUpTree = false;
 
 			// don't bubble up any ancestors until descendants are done bubbling up
 			it.skipAncestors();
@@ -308,21 +315,23 @@ void BlockTimer::accumulateTimings()
 	U32 cur_time = getCPUClockCount32();
 
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
-	Time* cur_timer = sCurTimerData.mCurTimer;
+	Time* cur_timer = sCurTimerData->mCurTimer;
 	// root defined by parent pointing to self
-	CurTimerData* cur_data = &sCurTimerData;
+	CurTimerData* cur_data = sCurTimerData.get();
+	TimerAccumulator& accumulator = sCurTimerData->mTimerData->getPrimaryAccumulator();
 	while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
 	{
 		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->mTimerData->mSelfTimeCounter += self_time_delta;
-		cur_data->mTimerData->mTotalTimeCounter += cumulative_time_delta;
+		accumulator.mSelfTimeCounter += self_time_delta;
+		accumulator.mTotalTimeCounter += cumulative_time_delta;
 
 		cur_timer->mStartTime = cur_time;
 
 		cur_data = &cur_timer->mLastTimerData;
 		cur_data->mChildTime += cumulative_time_delta;
+		accumulator = cur_data->mTimerData->getPrimaryAccumulator();
 
 		cur_timer = cur_timer->mLastTimerData.mCurTimer;
 	}
@@ -333,13 +342,14 @@ void BlockTimer::accumulateTimings()
 		++it)
 	{
 		BlockTimer* timerp = (*it);
-		timerp->mTreeTimeCounter = timerp->mSelfTimeCounter;
+		TimerAccumulator& accumulator = timerp->getPrimaryAccumulator();
+		timerp->mTreeTimeCounter = accumulator.mSelfTimeCounter;
 		for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it)
 		{
 			timerp->mTreeTimeCounter += (*child_it)->mTreeTimeCounter;
 		}
 
-		S32 cur_frame = sCurFrameIndex;
+		S32 cur_frame = getCurFrameIndex();
 		if (cur_frame >= 0)
 		{
 			// update timer history
@@ -347,8 +357,8 @@ void BlockTimer::accumulateTimings()
 
 			timerp->mCountHistory[hidx] = timerp->mTreeTimeCounter;
 			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);
+			timerp->mCallHistory[hidx]  = accumulator.mCalls;
+			timerp->mCallAverage        = ((U64)timerp->mCallAverage * cur_frame + accumulator.mCalls) / (cur_frame+1);
 		}
 	}
 }
@@ -377,15 +387,19 @@ void BlockTimer::resetFrame()
 		LLSD sd;
 
 		{
-			for (instance_iter it = beginInstances(), end_it = endInstances(); it != end_it; ++it)
+			for (LLInstanceTracker<BlockTimer>::instance_iter it = LLInstanceTracker<BlockTimer>::beginInstances(), 
+					end_it = LLInstanceTracker<BlockTimer>::endInstances(); 
+				it != end_it; 
+				++it)
 			{
 				BlockTimer& timer = *it;
-				sd[timer.getName()]["Time"] = (LLSD::Real) (timer.mSelfTimeCounter*iclock_freq);	
-				sd[timer.getName()]["Calls"] = (LLSD::Integer) timer.mCalls;
+				TimerAccumulator& accumulator = timer.getPrimaryAccumulator();
+				sd[timer.getName()]["Time"] = (LLSD::Real) (accumulator.mSelfTimeCounter*iclock_freq);	
+				sd[timer.getName()]["Calls"] = (LLSD::Integer) accumulator.mCalls;
 				
 				// computing total time here because getting the root timer's getCountHistory
 				// doesn't work correctly on the first frame
-				total_time = total_time + timer.mSelfTimeCounter * iclock_freq;
+				total_time = total_time + accumulator.mSelfTimeCounter * iclock_freq;
 			}
 		}
 
@@ -399,13 +413,17 @@ void BlockTimer::resetFrame()
 	}
 
 	// reset for next frame
-	for (instance_iter it = beginInstances(), end_it = endInstances(); it != end_it; ++it)
+	for (LLInstanceTracker<BlockTimer>::instance_iter it = LLInstanceTracker<BlockTimer>::beginInstances(),
+			end_it = LLInstanceTracker<BlockTimer>::endInstances();
+		it != end_it;
+		++it)
 	{
 		BlockTimer& timer = *it;
-		timer.mSelfTimeCounter = 0;
-		timer.mCalls = 0;
-		timer.mLastCaller = NULL;
-		timer.mMoveUpTree = false;
+		TimerAccumulator& accumulator = timer.getPrimaryAccumulator();
+		accumulator.mSelfTimeCounter = 0;
+		accumulator.mCalls = 0;
+		accumulator.mLastCaller = NULL;
+		accumulator.mMoveUpTree = false;
 	}
 }
 
@@ -419,7 +437,7 @@ void BlockTimer::reset()
 	U32 cur_time = getCPUClockCount32();
 
 	// root defined by parent pointing to self
-	CurTimerData* cur_data = &sCurTimerData;
+	CurTimerData* cur_data = sCurTimerData.get();
 	Time* cur_timer = cur_data->mCurTimer;
 	while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
 	{
@@ -432,7 +450,10 @@ void BlockTimer::reset()
 
 	// reset all history
 	{
-		for (instance_iter it = beginInstances(), end_it = endInstances(); it != end_it; ++it)
+		for (LLInstanceTracker<BlockTimer>::instance_iter it = LLInstanceTracker<BlockTimer>::beginInstances(), 
+				end_it = LLInstanceTracker<BlockTimer>::endInstances(); 
+			it != end_it; 
+			++it)
 		{
 			BlockTimer& timer = *it;
 			if (&timer != &BlockTimer::getRootTimer()) 
@@ -453,13 +474,13 @@ void BlockTimer::reset()
 
 U32 BlockTimer::getHistoricalCount(S32 history_index) const
 {
-	S32 history_idx = (getLastFrameIndex() + history_index) % BlockTimer::HISTORY_NUM;
+	S32 history_idx = (getLastFrameIndex() + history_index) % HISTORY_NUM;
 	return mCountHistory[history_idx];
 }
 
 U32 BlockTimer::getHistoricalCalls(S32 history_index ) const
 {
-	S32 history_idx = (getLastFrameIndex() + history_index) % BlockTimer::HISTORY_NUM;
+	S32 history_idx = (getLastFrameIndex() + history_index) % HISTORY_NUM;
 	return mCallHistory[history_idx];
 }
 
@@ -479,10 +500,10 @@ std::vector<BlockTimer*>& BlockTimer::getChildren()
 }
 
 //static
-void Time::nextFrame()
+void BlockTimer::nextFrame()
 {
-	countsPerSecond(); // good place to calculate clock frequency
-	U64 frame_time = getCPUClockCount64();
+	BlockTimer::countsPerSecond(); // good place to calculate clock frequency
+	U64 frame_time = BlockTimer::getCPUClockCount64();
 	if ((frame_time - sLastFrameTime) >> 8 > 0xffffffff)
 	{
 		llinfos << "Slow frame, fast timers inaccurate" << llendl;
@@ -505,7 +526,7 @@ void Time::dumpCurTimes()
 	// accumulate timings, etc.
 	BlockTimer::processTimes();
 	
-	F64 clock_freq = (F64)countsPerSecond();
+	F64 clock_freq = (F64)BlockTimer::countsPerSecond();
 	F64 iclock_freq = 1000.0 / clock_freq; // clock_ticks -> milliseconds
 
 	// walk over timers in depth order and output timings
@@ -533,13 +554,6 @@ void Time::dumpCurTimes()
 	}
 }
 
-//static 
-void Time::reset()
-{
-	BlockTimer::reset();
-}
-
-
 //static
 void Time::writeLog(std::ostream& os)
 {
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index f5e6d874a2..69a6773b12 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -28,60 +28,77 @@
 #define LL_FASTTIMER_H
 
 #include "llinstancetracker.h"
+#include "lltrace.h"
 
 #define FAST_TIMER_ON 1
+#define LL_FASTTIMER_USE_RDTSC 1
 
 class LLMutex;
 
-#include "lltrace.h"
-
-#define LL_FASTTIMER_USE_RDTSC 1
-
 namespace LLTrace
 {
+struct CurTimerData
+{
+	class Time*			mCurTimer;
+	class BlockTimer*	mTimerData;
+	U64					mChildTime;
+};
 
 class Time
 {
 public:
+	friend class BlockTimer;
 	typedef Time self_t;
 	typedef class BlockTimer DeclareTimer;
 
-public:
 	Time(BlockTimer& timer);
 	~Time();
 
 public:
-	static bool				sLog;
-	static bool				sMetricLog;
-	static std::string		sLogName;
-	static bool 			sPauseHistory;
-	static bool 			sResetHistory;
-
-	// call this once a frame to reset timers
-	static void nextFrame();
-
 	// dumps current cumulative frame stats to log
 	// call nextFrame() to reset timers
 	static void dumpCurTimes();
 
-	// call this to reset timer hierarchy, averages, etc.
-	static void reset();
+	static void writeLog(std::ostream& os);
 
-	static U64 countsPerSecond();
-	static S32 getLastFrameIndex() { return sLastFrameIndex; }
-	static S32 getCurFrameIndex() { return sCurFrameIndex; }
+private:
 
-	static void writeLog(std::ostream& os);
+	U64				mStartTime;
+	CurTimerData	mLastTimerData;
+};
 
-	struct CurTimerData
-	{
-		Time*				mCurTimer;
-		BlockTimer*			mTimerData;
-		U64					mChildTime;
-	};
-	static LLThreadLocalPointer<CurTimerData>	sCurTimerData;
+// stores a "named" timer instance to be reused via multiple Time stack instances
+class BlockTimer 
+:	public TraceType<TimerAccumulator>,
+	public LLInstanceTracker<BlockTimer>
+{
+public:
+	BlockTimer(const char* name, bool open = false, BlockTimer* parent = &getRootTimer());
+	~BlockTimer();
 
-private:
+	enum { HISTORY_NUM = 300 };
+
+	BlockTimer* getParent() const { return mParent; }
+	void setParent(BlockTimer* parent);
+	S32 getDepth();
+
+	typedef std::vector<BlockTimer*>::const_iterator child_const_iter;
+	child_const_iter beginChildren();
+	child_const_iter endChildren();
+	std::vector<BlockTimer*>& getChildren();
+
+	void setCollapsed(bool collapsed)	{ mCollapsed = collapsed; }
+	bool getCollapsed() const			{ return mCollapsed; }
+
+	U32 getCountAverage() const { return mCountAverage; }
+	U32 getCallAverage() const	{ return mCallAverage; }
+
+	U32 getHistoricalCount(S32 history_index = 0) const;
+	U32 getHistoricalCalls(S32 history_index = 0) const;
+
+	static BlockTimer& getRootTimer();
+	static void pushLog(LLSD sd);
+	friend class Time;
 
 
 	//////////////////////////////////////////////////////////////////////////////
@@ -106,14 +123,14 @@ private:
 	//#undef _interlockedbittestandset
 	//#undef _interlockedbittestandreset
 
-	//inline U32 Time::getCPUClockCount32()
+	//inline U32 BlockTimer::getCPUClockCount32()
 	//{
 	//	U64 time_stamp = __rdtsc();
 	//	return (U32)(time_stamp >> 8);
 	//}
 	//
 	//// return full timer value, *not* shifted by 8 bits
-	//inline U64 Time::getCPUClockCount64()
+	//inline U64 BlockTimer::getCPUClockCount64()
 	//{
 	//	return __rdtsc();
 	//}
@@ -220,64 +237,7 @@ private:
 
 #endif
 
-	static U64	sClockResolution;
-	static S32	sCurFrameIndex;
-	static S32	sLastFrameIndex;
-	static U64	sLastFrameTime;
-
-	U64							mStartTime;
-	Time::CurTimerData	mLastTimerData;
-};
-
-struct TimerAccumulator
-{
-	void addSamples(const TimerAccumulator& other);
-	void reset(const TimerAccumulator* other);
-
-	//
-	// members
-	//
-	U64 						mSelfTimeCounter,
-								mTotalTimeCounter;
-	U32 						mCalls;
-	BlockTimer*					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 Time stack instances
-class BlockTimer 
-:	public TraceType<TimerAccumulator>,
-	public LLInstanceTracker<BlockTimer>
-{
-public:
-	BlockTimer(const char* name, bool open = false, BlockTimer* parent = &getRootTimer());
-	~BlockTimer();
-
-	enum { HISTORY_NUM = 300 };
-
-	BlockTimer* getParent() const { return mParent; }
-	void setParent(BlockTimer* parent);
-	S32 getDepth();
-
-	typedef std::vector<BlockTimer*>::const_iterator child_const_iter;
-	child_const_iter beginChildren();
-	child_const_iter endChildren();
-	std::vector<BlockTimer*>& getChildren();
-
-	void setCollapsed(bool collapsed)	{ mCollapsed = collapsed; }
-	bool getCollapsed() const			{ return mCollapsed; }
-
-	U32 getCountAverage() const { return mCountAverage; }
-	U32 getCallAverage() const	{ return mCallAverage; }
-
-	U32 getHistoricalCount(S32 history_index = 0) const;
-	U32 getHistoricalCalls(S32 history_index = 0) const;
-
-	static BlockTimer& getRootTimer();
-
-private:
-	friend class Time;
+	static U64 countsPerSecond();
 
 	// recursive call to gather total time from children
 	static void accumulateTimings();
@@ -289,6 +249,12 @@ private:
 	static void buildHierarchy();
 	static void resetFrame();
 	static void reset();
+	// call this once a frame to reset timers
+	static void nextFrame();
+	static S32 getLastFrameIndex() { return sLastFrameIndex; }
+	static S32 getCurFrameIndex() { return sCurFrameIndex; }
+
+
 
 	// 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; 
@@ -304,12 +270,25 @@ private:
 	std::vector<BlockTimer*>	mChildren;
 	bool						mCollapsed;				// don't show children
 	bool						mNeedsSorting;			// sort children whenever child added
+
+	// statics
+	static std::string							sLogName;
+	static bool									sMetricLog;
+	static bool									sLog;	
+	static LLThreadLocalPointer<CurTimerData>	sCurTimerData;
+	static U64									sClockResolution;
+	static S32									sCurFrameIndex;
+	static S32									sLastFrameIndex;
+	static U64									sLastFrameTime;
+	static bool 								sPauseHistory;
+	static bool 								sResetHistory;
+
 };
 
 LL_FORCE_INLINE Time::Time(BlockTimer& timer)
 {
 #if FAST_TIMER_ON
-	mStartTime = getCPUClockCount64();
+	mStartTime = BlockTimer::getCPUClockCount64();
 
 	TimerAccumulator& accumulator = timer.getPrimaryAccumulator();
 	accumulator.mActiveCount++;
@@ -317,7 +296,7 @@ LL_FORCE_INLINE Time::Time(BlockTimer& timer)
 	// keep current parent as long as it is active when we are
 	accumulator.mMoveUpTree |= (timer.mParent->getPrimaryAccumulator().mActiveCount == 0);
 
-	CurTimerData* cur_timer_data = Time::sCurTimerData.get();
+	CurTimerData* cur_timer_data = BlockTimer::sCurTimerData.get();
 	// store top of stack
 	mLastTimerData = *cur_timer_data;
 	// push new information
@@ -330,8 +309,8 @@ LL_FORCE_INLINE Time::Time(BlockTimer& timer)
 LL_FORCE_INLINE Time::~Time()
 {
 #if FAST_TIMER_ON
-	U64 total_time = getCPUClockCount64() - mStartTime;
-	CurTimerData* cur_timer_data = Time::sCurTimerData.get();
+	U64 total_time = BlockTimer::getCPUClockCount64() - mStartTime;
+	CurTimerData* cur_timer_data = BlockTimer::sCurTimerData.get();
 	TimerAccumulator& accumulator = cur_timer_data->mTimerData->getPrimaryAccumulator();
 	accumulator.mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
 	accumulator.mTotalTimeCounter += total_time;
@@ -344,7 +323,7 @@ LL_FORCE_INLINE Time::~Time()
 	// we are only tracking self time, so subtract our total time delta from parents
 	mLastTimerData.mChildTime += total_time;
 
-	*sCurTimerData = mLastTimerData;
+	*BlockTimer::sCurTimerData = mLastTimerData;
 #endif
 }
 
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index c51d042a3d..5917d7a420 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -28,7 +28,7 @@
  */
 
 #if LL_WINDOWS
-#include <windows.h>
+#include "llwin32headerslean.h"
 #include <stdlib.h>                 // Windows errno
 #else
 #include <errno.h>
diff --git a/indra/llcommon/llfindlocale.cpp b/indra/llcommon/llfindlocale.cpp
index cd7c0c7c09..f019bd0c64 100644
--- a/indra/llcommon/llfindlocale.cpp
+++ b/indra/llcommon/llfindlocale.cpp
@@ -33,7 +33,7 @@
 #include <ctype.h>
 
 #ifdef WIN32
-#include <windows.h>
+#include "llwin32headers.h"
 #include <winnt.h>
 #endif
 
diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index 32d4eec607..d72e10d2fa 100644
--- a/indra/llcommon/llinitparam.cpp
+++ b/indra/llcommon/llinitparam.cpp
@@ -28,6 +28,7 @@
 #include "linden_common.h"
 
 #include "llinitparam.h"
+#include "llformat.h"
 
 
 namespace LLInitParam
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index 3d4e4331c0..502f93cbb8 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -29,6 +29,7 @@
 #define LL_LLPARAM_H
 
 #include <vector>
+#include <list>
 #include <boost/function.hpp>
 #include <boost/type_traits/is_convertible.hpp>
 #include <boost/unordered_map.hpp>
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index afaf366668..7c4ab6cf98 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -32,7 +32,6 @@
 //#endif
 
 #if defined(LL_WINDOWS)
-//# include <windows.h>
 # include <psapi.h>
 #elif defined(LL_DARWIN)
 # include <sys/types.h>
diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp
index a1b0a684c5..43d98be47b 100644
--- a/indra/llcommon/llmetricperformancetester.cpp
+++ b/indra/llcommon/llmetricperformancetester.cpp
@@ -31,6 +31,7 @@
 #include "llsdserialize.h"
 #include "lltreeiterators.h"
 #include "llmetricperformancetester.h"
+#include "llfasttimer.h"
 
 //----------------------------------------------------------------------------------------------
 // LLMetricPerformanceTesterBasic : static methods and testers management
@@ -90,7 +91,7 @@ LLMetricPerformanceTesterBasic* LLMetricPerformanceTesterBasic::getTester(std::s
 // Return TRUE if this metric is requested or if the general default "catch all" metric is requested
 BOOL LLMetricPerformanceTesterBasic::isMetricLogRequested(std::string name)
 {
-	return (LLFastTimer::sMetricLog && ((LLFastTimer::sLogName == name) || (LLFastTimer::sLogName == DEFAULT_METRIC_NAME)));
+	return (LLTrace::BlockTimer::sMetricLog && ((LLTrace::BlockTimer::sLogName == name) || (LLTrace::BlockTimer::sLogName == DEFAULT_METRIC_NAME)));
 }
 
 /*static*/ 
@@ -193,8 +194,7 @@ void LLMetricPerformanceTesterBasic::preOutputTestResults(LLSD* sd)
 
 void LLMetricPerformanceTesterBasic::postOutputTestResults(LLSD* sd)
 {
-	LLMutexLock lock(LLFastTimer::sLogLock);
-	LLFastTimer::sLogQueue.push((*sd));
+	LLTrace::BlockTimer::pushLog(*sd);
 }
 
 void LLMetricPerformanceTesterBasic::outputTestResults() 
diff --git a/indra/llcommon/llmortician.h b/indra/llcommon/llmortician.h
index 319955ef93..9517e2db5e 100644
--- a/indra/llcommon/llmortician.h
+++ b/indra/llcommon/llmortician.h
@@ -28,6 +28,7 @@
 #define LLMORTICIAN_H
 
 #include "stdtypes.h"
+#include <list>
 
 class LL_COMMON_API LLMortician 
 {
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index d711ce2f74..2fe084afcd 100644
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -38,8 +38,7 @@
 #include <stdexcept>
 
 #if LL_WINDOWS
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>                // HANDLE (eye roll)
+#include "llwin32headerslean.h"	// for HANDLE
 #elif LL_LINUX
 #if defined(Status)
 #undef Status
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index 87a5930c14..6fe53396ca 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -32,9 +32,7 @@
 //#include <memory>
 
 #if LL_WINDOWS
-#	define WIN32_LEAN_AND_MEAN
-#	include <winsock2.h>
-#	include <windows.h>
+#	include "llwin32headerslean.h"
 #	define _interlockedbittestandset _renamed_interlockedbittestandset
 #	define _interlockedbittestandreset _renamed_interlockedbittestandreset
 #	include <intrin.h>
diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h
index 1181c2d433..7cfc265c62 100644
--- a/indra/llcommon/llsdparam.h
+++ b/indra/llcommon/llsdparam.h
@@ -30,6 +30,7 @@
 
 #include "llinitparam.h"
 #include "boost/function.hpp"
+#include "llfasttimer.h"
 
 struct LL_COMMON_API LLParamSDParserUtilities
 {
diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp
index ccd7ef91c2..e0e9056380 100644
--- a/indra/llcommon/llstacktrace.cpp
+++ b/indra/llcommon/llstacktrace.cpp
@@ -32,7 +32,7 @@
 #include <iostream>
 #include <sstream>
 
-#include "windows.h"
+#include "llwin32headerslean.h"
 #include "Dbghelp.h"
 
 typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index fa0eb9f72c..9600928ad5 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -28,11 +28,10 @@
 
 #include "llstring.h"
 #include "llerror.h"
+#include "llfasttimer.h"
 
 #if LL_WINDOWS
-#define WIN32_LEAN_AND_MEAN
-#include <winsock2.h>
-#include <windows.h>
+#include "llwin32headerslean.h"
 #include <winnls.h> // for WideCharToMultiByte
 #endif
 
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 119efc7957..9d81ac25dd 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -31,8 +31,9 @@
 #include <cstdio>
 #include <locale>
 #include <iomanip>
+#include <algorithm>
 #include "llsd.h"
-#include "llfasttimer.h"
+#include "llformat.h"
 
 #if LL_LINUX || LL_SOLARIS
 #include <wctype.h>
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 6073bcd0a6..00b72ce1d8 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -42,6 +42,7 @@
 #include "llprocessor.h"
 #include "llerrorcontrol.h"
 #include "llevents.h"
+#include "llformat.h"
 #include "lltimer.h"
 #include "llsdserialize.h"
 #include "llsdutil.h"
@@ -58,9 +59,7 @@
 using namespace llsd;
 
 #if LL_WINDOWS
-#	define WIN32_LEAN_AND_MEAN
-#	include <winsock2.h>
-#	include <windows.h>
+#	include "llwin32headerslean.h"
 #   include <psapi.h>               // GetPerformanceInfo() et al.
 #elif LL_DARWIN
 #	include <errno.h>
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 23cebf4336..26063beff0 100644
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -31,11 +31,9 @@
 #include "u64.h"
 
 #if LL_WINDOWS
-#	define WIN32_LEAN_AND_MEAN
-#	include <winsock2.h>
-#	include <windows.h>
+#	include "llwin32headerslean.h"
 #elif LL_LINUX || LL_SOLARIS || LL_DARWIN
-#       include <errno.h>
+#   include <errno.h>
 #	include <sys/time.h>
 #else 
 #	error "architecture not supported"
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index afb175c398..9346aa7a45 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -38,15 +38,15 @@ static MasterThreadRecorder* gMasterThreadRecorder = NULL;
 void init()
 {
 	gMasterThreadRecorder = new MasterThreadRecorder();
-	Time::sCurTimerData = new Time::CurTimerData();
+	BlockTimer::sCurTimerData = new CurTimerData();
 }
 
 void cleanup()
 {
 	delete gMasterThreadRecorder;
 	gMasterThreadRecorder = NULL;
-	delete Time::sCurTimerData.get();
-	Time::sCurTimerData = NULL;
+	delete BlockTimer::sCurTimerData.get();
+	BlockTimer::sCurTimerData = NULL;
 }
 
 MasterThreadRecorder& getMasterThreadRecorder()
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index fb9dca5e84..61fed6e7b8 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -235,8 +235,8 @@ namespace LLTrace
 
 		MeasurementAccumulator()
 		:	mSum(0),
-			mMin(std::numeric_limits<T>::max()),
-			mMax(std::numeric_limits<T>::min()),
+			mMin((std::numeric_limits<T>::max)()),
+			mMax((std::numeric_limits<T>::min)()),
 			mMean(0),
 			mVarianceSum(0),
 			mNumSamples(0),
@@ -380,6 +380,24 @@ namespace LLTrace
 		U32	mNumSamples;
 	};
 
+	class TimerAccumulator
+	{
+	public:
+		void addSamples(const TimerAccumulator& other);
+		void reset(const TimerAccumulator* other);
+
+		//
+		// members
+		//
+		U64 						mSelfTimeCounter,
+									mTotalTimeCounter;
+		U32 						mCalls;
+		class BlockTimer*			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
+	};
+
+
 	template <typename T = F64>
 	class Measurement
 	:	public TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 4dcadfdf29..efc54d240f 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -273,7 +273,7 @@ namespace LLTrace
 		template <typename T>
 		typename T getPeriodMin(const TraceType<CountAccumulator<T> >& stat) const
 		{
-			T min_val = std::numeric_limits<T>::max();
+			T min_val = (std::numeric_limits<T>::max)();
 			for (S32 i = 0; i < mNumPeriods; i++)
 			{
 				min_val = llmin(min_val, mRecordingPeriods[i].getSum(stat));
@@ -284,7 +284,7 @@ namespace LLTrace
 		template <typename T>
 		F64 getPeriodMinPerSec(const TraceType<CountAccumulator<T> >& stat) const
 		{
-			F64 min_val = std::numeric_limits<F64>::max();
+			F64 min_val = (std::numeric_limits<F64>::max)();
 			for (S32 i = 0; i < mNumPeriods; i++)
 			{
 				min_val = llmin(min_val, mRecordingPeriods[i].getPerSec(stat));
@@ -295,7 +295,7 @@ namespace LLTrace
 		template <typename T>
 		T getPeriodMax(const TraceType<CountAccumulator<T> >& stat) const
 		{
-			T max_val = std::numeric_limits<T>::min();
+			T max_val = (std::numeric_limits<T>::min)();
 			for (S32 i = 0; i < mNumPeriods; i++)
 			{
 				max_val = llmax(max_val, mRecordingPeriods[i].getSum(stat));
@@ -306,7 +306,7 @@ namespace LLTrace
 		template <typename T>
 		F64 getPeriodMaxPerSec(const TraceType<CountAccumulator<T> >& stat) const
 		{
-			F64 max_val = std::numeric_limits<F64>::min();
+			F64 max_val = (std::numeric_limits<F64>::min)();
 			for (S32 i = 0; i < mNumPeriods; i++)
 			{
 				max_val = llmax(max_val, mRecordingPeriods[i].getPerSec(stat));
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 5a6ff14f97..0f111aab59 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -26,6 +26,7 @@
 #include "linden_common.h"
 
 #include "lltracethreadrecorder.h"
+#include "llfasttimer.h"
 
 namespace LLTrace
 {
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 4ac2197c11..1fe492fdce 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -33,18 +33,12 @@
 namespace LLUnits
 {
 
-template<typename T, typename IS_UNIT = void>
+template<typename T>
 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; };
@@ -78,7 +72,6 @@ struct LLUnit
 {
 	typedef LLUnit<UNIT_TYPE, STORAGE_TYPE> self_t;
 	typedef typename STORAGE_TYPE storage_t;
-	typedef void is_unit_tag_t;
 
 	LLUnit(storage_t value = storage_t())
 	:	mValue(value)
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index db8c9c85ab..83ed987d30 100644
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -27,9 +27,7 @@
 
 // We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes.
 #if LL_WINDOWS
-#undef WIN32_LEAN_AND_MEAN
-#include <winsock2.h>
-#include <windows.h>
+#include "llwin32headers.h"
 // ugh, this is ugly.  We need to straighten out our linking for this library
 #pragma comment(lib, "IPHLPAPI.lib")
 #include <iphlpapi.h>
diff --git a/indra/llcommon/llwin32headers.h b/indra/llcommon/llwin32headers.h
new file mode 100644
index 0000000000..80fd2e1768
--- /dev/null
+++ b/indra/llcommon/llwin32headers.h
@@ -0,0 +1,38 @@
+/** 
+ * @file llwindows.h
+ * @brief sanitized include of windows header files
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLWINDOWS_H
+#define LL_LLWINDOWS_H
+
+#ifdef LL_WINDOWS
+#define NOMINMAX
+#undef WIN32_LEAN_AND_MEAN
+#include <winsock2.h>
+#include <windows.h>
+#undef NOMINMAX
+#endif
+
+#endif
diff --git a/indra/llcommon/llwin32headerslean.h b/indra/llcommon/llwin32headerslean.h
new file mode 100644
index 0000000000..ab6e9c09e2
--- /dev/null
+++ b/indra/llcommon/llwin32headerslean.h
@@ -0,0 +1,37 @@
+/** 
+ * @file llwindows.h
+ * @brief sanitized include of windows header files
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLWINDOWS_H
+#define LL_LLWINDOWS_H
+
+#ifdef LL_WINDOWS
+#define NOMINMAX
+#define WIN32_LEAN_AND_MEAN
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+#endif
-- 
cgit v1.2.3


From c136b432140f892a56d4996d5ed77e903ff0b32d Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 15 Nov 2012 19:46:09 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system eliminated min and
 max macros from windows.h got rest of viewer to compile against llfasttimer
 changes

---
 indra/llcommon/llapr.h              | 1 +
 indra/llcommon/llfasttimer.cpp      | 5 +++++
 indra/llcommon/llfasttimer.h        | 3 ++-
 indra/llcommon/llthread.h           | 2 ++
 indra/llcommon/lltrace.cpp          | 1 -
 indra/llcommon/llwin32headers.h     | 2 --
 indra/llcommon/llwin32headerslean.h | 1 -
 7 files changed, 10 insertions(+), 5 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index c77d96c1c9..d9fe257e86 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -40,6 +40,7 @@
 #include "apr_getopt.h"
 #include "apr_signal.h"
 #include "apr_atomic.h"
+
 #include "llstring.h"
 #include "llinstancetracker.h"
 
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index d007f76e5f..4ecca12832 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -121,6 +121,11 @@ void BlockTimer::pushLog(LLSD log)
 	sLogQueue.push(log);
 }
 
+void BlockTimer::setLogLock(LLMutex* lock)
+{
+	sLogLock = lock;
+}
+
 
 //static
 #if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 69a6773b12..af9b360e01 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -98,6 +98,7 @@ public:
 
 	static BlockTimer& getRootTimer();
 	static void pushLog(LLSD sd);
+	static void setLogLock(LLMutex* mutex);
 	friend class Time;
 
 
@@ -329,6 +330,6 @@ LL_FORCE_INLINE Time::~Time()
 
 }
 
-typedef LLTrace::Time LLFastTimer;
+typedef LLTrace::Time LLFastTimer; 
 
 #endif // LL_LLFASTTIMER_H
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 82ab5f47d2..93c752754d 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -32,6 +32,8 @@
 #include "apr_thread_cond.h"
 #include "llmutex.h"
 
+LL_COMMON_API void assert_main_thread();
+
 class LL_COMMON_API LLThread
 {
 private:
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 9346aa7a45..9bf9ae6c8e 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -59,7 +59,6 @@ LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
 {
 	static LLThreadLocalPointer<ThreadRecorder> s_thread_recorder;
 	return s_thread_recorder;
-
 }
 
 }
diff --git a/indra/llcommon/llwin32headers.h b/indra/llcommon/llwin32headers.h
index 80fd2e1768..9c89b6b280 100644
--- a/indra/llcommon/llwin32headers.h
+++ b/indra/llcommon/llwin32headers.h
@@ -28,11 +28,9 @@
 #define LL_LLWINDOWS_H
 
 #ifdef LL_WINDOWS
-#define NOMINMAX
 #undef WIN32_LEAN_AND_MEAN
 #include <winsock2.h>
 #include <windows.h>
-#undef NOMINMAX
 #endif
 
 #endif
diff --git a/indra/llcommon/llwin32headerslean.h b/indra/llcommon/llwin32headerslean.h
index ab6e9c09e2..d3fb90d4b1 100644
--- a/indra/llcommon/llwin32headerslean.h
+++ b/indra/llcommon/llwin32headerslean.h
@@ -28,7 +28,6 @@
 #define LL_LLWINDOWS_H
 
 #ifdef LL_WINDOWS
-#define NOMINMAX
 #define WIN32_LEAN_AND_MEAN
 #include <winsock2.h>
 #include <windows.h>
-- 
cgit v1.2.3


From 6db6cb39f41e921e75970d1570a74cf35d353a35 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 16 Nov 2012 23:02:53 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system got new fast timer
 code to compile and run

---
 indra/llcommon/llfasttimer.cpp           | 13 ++++++++++++-
 indra/llcommon/lltrace.cpp               | 12 +++++++++---
 indra/llcommon/lltrace.h                 |  6 ++++++
 indra/llcommon/lltracethreadrecorder.cpp |  4 ++++
 4 files changed, 31 insertions(+), 4 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 4ecca12832..e1549b4bff 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -336,7 +336,10 @@ void BlockTimer::accumulateTimings()
 
 		cur_data = &cur_timer->mLastTimerData;
 		cur_data->mChildTime += cumulative_time_delta;
-		accumulator = cur_data->mTimerData->getPrimaryAccumulator();
+		if (cur_data->mTimerData)
+		{
+			accumulator = cur_data->mTimerData->getPrimaryAccumulator();
+		}
 
 		cur_timer = cur_timer->mLastTimerData.mCurTimer;
 	}
@@ -572,6 +575,14 @@ void Time::writeLog(std::ostream& os)
 }
 
 
+LLTrace::TimerAccumulator::TimerAccumulator() :	mSelfTimeCounter(0),
+	mTotalTimeCounter(0),
+	mCalls(0),
+	mLastCaller(NULL),
+	mActiveCount(0),
+	mMoveUpTree(false)
+{}
+
 void LLTrace::TimerAccumulator::addSamples( const LLTrace::TimerAccumulator& other )
 {
 	mSelfTimeCounter += other.mSelfTimeCounter;
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 9bf9ae6c8e..e11e39a1a2 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -30,6 +30,8 @@
 #include "lltracethreadrecorder.h"
 #include "llfasttimer.h"
 
+static bool sInitialized;
+
 namespace LLTrace
 {
 
@@ -38,15 +40,18 @@ static MasterThreadRecorder* gMasterThreadRecorder = NULL;
 void init()
 {
 	gMasterThreadRecorder = new MasterThreadRecorder();
-	BlockTimer::sCurTimerData = new CurTimerData();
+	sInitialized = true;
+}
+
+bool isInitialized()
+{
+	return sInitialized; 
 }
 
 void cleanup()
 {
 	delete gMasterThreadRecorder;
 	gMasterThreadRecorder = NULL;
-	delete BlockTimer::sCurTimerData.get();
-	BlockTimer::sCurTimerData = NULL;
 }
 
 MasterThreadRecorder& getMasterThreadRecorder()
@@ -62,3 +67,4 @@ LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
 }
 
 }
+
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 61fed6e7b8..61d14569cd 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -67,6 +67,7 @@ namespace LLTrace
 
 	void init();
 	void cleanup();
+	bool isInitialized();
 
 	LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder();
 
@@ -162,6 +163,10 @@ namespace LLTrace
 		// NOTE: this is not thread-safe.  We assume that slots are reserved in the main thread before any child threads are spawned
 		size_t reserveSlot()
 		{
+			if (LLTrace::isInitialized())
+			{
+				llerrs << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << llendl;
+			}
 			size_t next_slot = mNextStorageSlot++;
 			if (next_slot >= mStorageSize)
 			{
@@ -383,6 +388,7 @@ namespace LLTrace
 	class TimerAccumulator
 	{
 	public:
+		TimerAccumulator();
 		void addSamples(const TimerAccumulator& other);
 		void reset(const TimerAccumulator* other);
 
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 0f111aab59..c2fefe2957 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -40,6 +40,8 @@ ThreadRecorder::ThreadRecorder()
 {
 	get_thread_recorder() = this;
 	mFullRecording.start();
+
+	BlockTimer::sCurTimerData = new CurTimerData();
 }
 
 ThreadRecorder::ThreadRecorder( const ThreadRecorder& other ) 
@@ -52,6 +54,8 @@ ThreadRecorder::ThreadRecorder( const ThreadRecorder& other )
 ThreadRecorder::~ThreadRecorder()
 {
 	get_thread_recorder() = NULL;
+	delete BlockTimer::sCurTimerData.get();
+	BlockTimer::sCurTimerData = NULL;
 }
 
 void ThreadRecorder::activate( Recording* recording )
-- 
cgit v1.2.3


From 5d51175cd79b15cf036cd7e6bd646a1a0777eb7f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 20 Nov 2012 15:55:04 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system fixes to merge

---
 indra/llcommon/llmemory.h   |   2 +-
 indra/llcommon/llmutex.cpp  |  49 +-------------
 indra/llcommon/llmutex.h    |  67 -------------------
 indra/llcommon/llthread.cpp | 153 +-------------------------------------------
 indra/llcommon/llthread.h   |   2 +-
 indra/llcommon/llunit.h     |  40 +++++++-----
 6 files changed, 29 insertions(+), 284 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 3744e68956..e725bdd9fa 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -26,7 +26,7 @@
 #ifndef LLMEMORY_H
 #define LLMEMORY_H
 
-#include "llmemtype.h"
+#include "linden_common.h"
 
 class LLMutex ;
 
diff --git a/indra/llcommon/llmutex.cpp b/indra/llcommon/llmutex.cpp
index 2ce14b3a2e..e6beb9e680 100644
--- a/indra/llcommon/llmutex.cpp
+++ b/indra/llcommon/llmutex.cpp
@@ -86,7 +86,7 @@ void LLMutex::lock()
 #if LL_DARWIN
 	mLockingThread = LLThread::currentID();
 #else
-	mLockingThread = LLThread::sThreadIndex;
+	mLockingThread = LLThread::sThreadID;
 #endif
 }
 
@@ -129,7 +129,7 @@ bool LLMutex::isSelfLocked()
 #if LL_DARWIN
 	return mLockingThread == LLThread::currentID();
 #else
-	return mLockingThread == LLThread::sThreadIndex;
+	return mLockingThread == LLThread::sThreadID;
 #endif
 }
 
@@ -181,49 +181,4 @@ void LLCondition::broadcast()
 }
 
 
-//============================================================================
-
-//----------------------------------------------------------------------------
-
-//static
-LLMutex* LLThreadSafeRefCount::sMutex = 0;
-
-//static
-void LLThreadSafeRefCount::initThreadSafeRefCount()
-{
-	if (!sMutex)
-	{
-		sMutex = new LLMutex(0);
-	}
-}
-
-//static
-void LLThreadSafeRefCount::cleanupThreadSafeRefCount()
-{
-	delete sMutex;
-	sMutex = NULL;
-}
-
-
-//----------------------------------------------------------------------------
-
-LLThreadSafeRefCount::LLThreadSafeRefCount() :
-mRef(0)
-{
-}
-
-LLThreadSafeRefCount::~LLThreadSafeRefCount()
-{ 
-	if (mRef != 0)
-	{
-		llerrs << "deleting non-zero reference" << llendl;
-	}
-}
-
-//============================================================================
-
-LLResponder::~LLResponder()
-{
-}
-
 //============================================================================
diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h
index bd0a59b577..cbde4c47a9 100644
--- a/indra/llcommon/llmutex.h
+++ b/indra/llcommon/llmutex.h
@@ -98,71 +98,4 @@ private:
 	LLMutex* mMutex;
 };
 
-
-//============================================================================
-
-// see llmemory.h for LLPointer<> definition
-
-class LL_COMMON_API LLThreadSafeRefCount
-{
-public:
-	static void initThreadSafeRefCount(); // creates sMutex
-	static void cleanupThreadSafeRefCount(); // destroys sMutex
-
-private:
-	static LLMutex* sMutex;
-
-private:
-	LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented
-	LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented
-
-protected:
-	virtual ~LLThreadSafeRefCount(); // use unref()
-
-public:
-	LLThreadSafeRefCount();
-
-	void ref()
-	{
-		if (sMutex) sMutex->lock();
-		mRef++; 
-		if (sMutex) sMutex->unlock();
-	} 
-
-	S32 unref()
-	{
-		llassert(mRef >= 1);
-		if (sMutex) sMutex->lock();
-		S32 res = --mRef;
-		if (sMutex) sMutex->unlock();
-		if (0 == res) 
-		{
-			delete this; 
-			return 0;
-		}
-		return res;
-	}	
-	S32 getNumRefs() const
-	{
-		return mRef;
-	}
-
-private: 
-	S32	mRef; 
-};
-
-
-//============================================================================
-
-// Simple responder for self destructing callbacks
-// Pure virtual class
-class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
-{
-protected:
-	virtual ~LLResponder();
-public:
-	virtual void completed(bool success) = 0;
-};
-
-
 #endif // LL_LLTHREAD_H
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 1c86eb4f06..8ce739bf23 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -62,7 +62,7 @@
 #if LL_DARWIN
 // statically allocated thread local storage not supported in Darwin executable formats
 #elif LL_WINDOWS
-U32 __declspec(thread) LLThread::sThreadIndex = 0;
+U32 __declspec(thread) LLThread::sThreadID = 0;
 #elif LL_LINUX
 U32 __thread LLThread::sThreadID = 0;
 #endif 
@@ -96,7 +96,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 	LLTrace::ThreadRecorder* thread_recorder = new LLTrace::SlaveThreadRecorder();
 
 #if !LL_DARWIN
-	sThreadIndex = threadp->mID;
+	sThreadID = threadp->mID;
 #endif
 
 	// Run the user supplied function
@@ -327,155 +327,6 @@ void LLThread::wakeLocked()
 
 //============================================================================
 
-LLMutex::LLMutex(apr_pool_t *poolp) :
-	mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD)
-{
-	//if (poolp)
-	//{
-	//	mIsLocalPool = FALSE;
-	//	mAPRPoolp = poolp;
-	//}
-	//else
-	{
-		mIsLocalPool = TRUE;
-		apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
-	}
-	apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
-}
-
-
-LLMutex::~LLMutex()
-{
-#if MUTEX_DEBUG
-	//bad assertion, the subclass LLSignal might be "locked", and that's OK
-	//llassert_always(!isLocked()); // better not be locked!
-#endif
-	apr_thread_mutex_destroy(mAPRMutexp);
-	mAPRMutexp = NULL;
-	if (mIsLocalPool)
-	{
-		apr_pool_destroy(mAPRPoolp);
-	}
-}
-
-
-void LLMutex::lock()
-{
-	if(isSelfLocked())
-	{ //redundant lock
-		mCount++;
-		return;
-	}
-	
-	apr_thread_mutex_lock(mAPRMutexp);
-	
-#if MUTEX_DEBUG
-	// Have to have the lock before we can access the debug info
-	U32 id = LLThread::currentID();
-	if (mIsLocked[id] != FALSE)
-		llerrs << "Already locked in Thread: " << id << llendl;
-	mIsLocked[id] = TRUE;
-#endif
-
-#if LL_DARWIN
-	mLockingThread = LLThread::currentID();
-#else
-	mLockingThread = sThreadID;
-#endif
-}
-
-void LLMutex::unlock()
-{
-	if (mCount > 0)
-	{ //not the root unlock
-		mCount--;
-		return;
-	}
-	
-#if MUTEX_DEBUG
-	// Access the debug info while we have the lock
-	U32 id = LLThread::currentID();
-	if (mIsLocked[id] != TRUE)
-		llerrs << "Not locked in Thread: " << id << llendl;	
-	mIsLocked[id] = FALSE;
-#endif
-
-	mLockingThread = NO_THREAD;
-	apr_thread_mutex_unlock(mAPRMutexp);
-}
-
-bool LLMutex::isLocked()
-{
-	apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
-	if (APR_STATUS_IS_EBUSY(status))
-	{
-		return true;
-	}
-	else
-	{
-		apr_thread_mutex_unlock(mAPRMutexp);
-		return false;
-	}
-}
-
-bool LLMutex::isSelfLocked()
-{
-#if LL_DARWIN
-	return mLockingThread == LLThread::currentID();
-#else
-	return mLockingThread == sThreadID;
-#endif
-}
-
-U32 LLMutex::lockingThread() const
-{
-	return mLockingThread;
-}
-
-//============================================================================
-
-LLCondition::LLCondition(apr_pool_t *poolp) :
-	LLMutex(poolp)
-{
-	// base class (LLMutex) has already ensured that mAPRPoolp is set up.
-
-	apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
-}
-
-
-LLCondition::~LLCondition()
-{
-	apr_thread_cond_destroy(mAPRCondp);
-	mAPRCondp = NULL;
-}
-
-
-void LLCondition::wait()
-{
-	if (!isLocked())
-	{ //mAPRMutexp MUST be locked before calling apr_thread_cond_wait
-		apr_thread_mutex_lock(mAPRMutexp);
-#if MUTEX_DEBUG
-		// avoid asserts on destruction in non-release builds
-		U32 id = LLThread::currentID();
-		mIsLocked[id] = TRUE;
-#endif
-	}
-	apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
-}
-
-void LLCondition::signal()
-{
-	apr_thread_cond_signal(mAPRCondp);
-}
-
-void LLCondition::broadcast()
-{
-	apr_thread_cond_broadcast(mAPRCondp);
-}
-
-//============================================================================
-
 //----------------------------------------------------------------------------
 
 //static
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 94b6b6d682..75222c83f9 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -42,7 +42,7 @@ private:
 #if LL_DARWIN
 	// statically allocated thread local storage not supported in Darwin executable formats
 #elif LL_WINDOWS
-	static U32 __declspec(thread) LLThread::sThreadIndex;
+	static U32 __declspec(thread) LLThread::sThreadID;
 #elif LL_LINUX
 	static U32 __thread LLThread::sThreadID ;
 #endif
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 1fe492fdce..53570779fc 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -109,9 +109,9 @@ struct LLUnit
 		return mValue;
 	}
 
-	template<typename NEW_UNIT_TYPE> LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE> as()
+	template<typename NEW_UNIT_TYPE, typename NEW_STORAGE_TYPE> LLUnit<NEW_UNIT_TYPE, NEW_STORAGE_TYPE> as()
 	{
-		return LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE>(*this);
+		return LLUnit<NEW_UNIT_TYPE, NEW_STORAGE_TYPE>(*this);
 	}
 
 	void operator += (storage_t value)
@@ -332,21 +332,27 @@ struct HighestPrecisionType<LLUnit<UNIT_TYPE, STORAGE_TYPE> >
 	typedef typename HighestPrecisionType<STORAGE_TYPE>::type_t type_t;
 };
 
-#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)); } \
+#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; };
-- 
cgit v1.2.3


From 1c894c05c10ef37be6507ee4bc4e9173506adfb6 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 27 Nov 2012 17:26:12 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system hunting down bad
 values and crashes

---
 indra/llcommon/llfasttimer.cpp           | 24 ++++++++++++++----------
 indra/llcommon/llfasttimer.h             |  8 ++++----
 indra/llcommon/lltrace.h                 |  1 +
 indra/llcommon/lltracerecording.cpp      |  5 ++++-
 indra/llcommon/lltracethreadrecorder.cpp |  4 ++++
 5 files changed, 27 insertions(+), 15 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index e1549b4bff..16dd21332c 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -177,8 +177,8 @@ BlockTimer::BlockTimer(const char* name, bool open, BlockTimer* parent)
 		mParent = this;
 	}
 
-	mCountHistory = new U32[HISTORY_NUM];
-	memset(mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
+	mCountHistory = new U64[HISTORY_NUM];
+	memset(mCountHistory, 0, sizeof(U64) * HISTORY_NUM);
 	mCallHistory = new U32[HISTORY_NUM];
 	memset(mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
 }
@@ -266,9 +266,12 @@ void BlockTimer::buildHierarchy()
 			
 			// bootstrap tree construction by attaching to last timer to be on stack
 			// when this timer was called
-			if (timer.getPrimaryAccumulator().mLastCaller && timer.mParent == &BlockTimer::getRootTimer())
+			if (timer.mParent == &BlockTimer::getRootTimer())
 			{
-				timer.setParent(timer.getPrimaryAccumulator().mLastCaller);
+				if (timer.getPrimaryAccumulator().mLastCaller)
+				{
+					timer.setParent(timer.getPrimaryAccumulator().mLastCaller);
+				}
 				// no need to push up tree on first use, flag can be set spuriously
 				timer.getPrimaryAccumulator().mMoveUpTree = false;
 			}
@@ -317,7 +320,7 @@ void BlockTimer::buildHierarchy()
 //static
 void BlockTimer::accumulateTimings()
 {
-	U32 cur_time = getCPUClockCount32();
+	U64 cur_time = getCPUClockCount64();
 
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
 	Time* cur_timer = sCurTimerData->mCurTimer;
@@ -326,8 +329,8 @@ void BlockTimer::accumulateTimings()
 	TimerAccumulator& accumulator = sCurTimerData->mTimerData->getPrimaryAccumulator();
 	while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
 	{
-		U32 cumulative_time_delta = cur_time - cur_timer->mStartTime;
-		U32 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
+		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
+		U64 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
 		cur_data->mChildTime = 0;
 		accumulator.mSelfTimeCounter += self_time_delta;
 		accumulator.mTotalTimeCounter += cumulative_time_delta;
@@ -429,6 +432,7 @@ void BlockTimer::resetFrame()
 		BlockTimer& timer = *it;
 		TimerAccumulator& accumulator = timer.getPrimaryAccumulator();
 		accumulator.mSelfTimeCounter = 0;
+		accumulator.mTotalTimeCounter = 0;
 		accumulator.mCalls = 0;
 		accumulator.mLastCaller = NULL;
 		accumulator.mMoveUpTree = false;
@@ -442,7 +446,7 @@ void BlockTimer::reset()
 
 	// walk up stack of active timers and reset start times to current time
 	// effectively zeroing out any accumulated time
-	U32 cur_time = getCPUClockCount32();
+	U64 cur_time = getCPUClockCount64();
 
 	// root defined by parent pointing to self
 	CurTimerData* cur_data = sCurTimerData.get();
@@ -471,7 +475,7 @@ void BlockTimer::reset()
 			
 			timer.mCountAverage = 0;
 			timer.mCallAverage = 0;
-			memset(timer.mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
+			memset(timer.mCountHistory, 0, sizeof(U64) * HISTORY_NUM);
 			memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
 		}
 	}
@@ -480,7 +484,7 @@ void BlockTimer::reset()
 	sCurFrameIndex = 0;
 }
 
-U32 BlockTimer::getHistoricalCount(S32 history_index) const
+U64 BlockTimer::getHistoricalCount(S32 history_index) const
 {
 	S32 history_idx = (getLastFrameIndex() + history_index) % HISTORY_NUM;
 	return mCountHistory[history_idx];
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index af9b360e01..cfe2cf5371 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -93,7 +93,7 @@ public:
 	U32 getCountAverage() const { return mCountAverage; }
 	U32 getCallAverage() const	{ return mCallAverage; }
 
-	U32 getHistoricalCount(S32 history_index = 0) const;
+	U64 getHistoricalCount(S32 history_index = 0) const;
 	U32 getHistoricalCalls(S32 history_index = 0) const;
 
 	static BlockTimer& getRootTimer();
@@ -258,12 +258,12 @@ public:
 
 
 	// 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; 
+	U64 						mTreeTimeCounter; 
 
-	U32 						mCountAverage;
+	U64 						mCountAverage;
 	U32							mCallAverage;
 
-	U32*						mCountHistory;
+	U64*						mCountHistory;
 	U32*						mCallHistory;
 
 	// tree structure
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 61d14569cd..11651ef953 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -107,6 +107,7 @@ namespace LLTrace
 				//TODO pick another primary?
 				sPrimaryStorage = NULL;
 			}
+			delete[] mStorage;
 		}
 
 		LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index) 
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 4252ed57dc..e7ed55e8ae 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -66,7 +66,10 @@ Recording::Recording( const Recording& other )
 
 
 Recording::~Recording()
-{}
+{
+	stop();
+	llassert(isStopped());
+}
 
 void Recording::update()
 {
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index c2fefe2957..faaab4c8e7 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -53,6 +53,10 @@ ThreadRecorder::ThreadRecorder( const ThreadRecorder& other )
 
 ThreadRecorder::~ThreadRecorder()
 {
+	while(mActiveRecordings.size())
+	{
+		mActiveRecordings.front().mTargetRecording->stop();
+	}
 	get_thread_recorder() = NULL;
 	delete BlockTimer::sCurTimerData.get();
 	BlockTimer::sCurTimerData = NULL;
-- 
cgit v1.2.3


From 93aca485ba08a82a6bd3a2fc31deca18af0d1478 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 27 Nov 2012 20:17:37 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system fixed precision of
 fast timer counts

---
 indra/llcommon/llfasttimer.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index e1549b4bff..9701a41dc5 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -317,7 +317,7 @@ void BlockTimer::buildHierarchy()
 //static
 void BlockTimer::accumulateTimings()
 {
-	U32 cur_time = getCPUClockCount32();
+	U64 cur_time = getCPUClockCount64();
 
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
 	Time* cur_timer = sCurTimerData->mCurTimer;
@@ -389,7 +389,7 @@ void BlockTimer::resetFrame()
 		}
 		call_count++;
 
-		F64 iclock_freq = 1000.0 / countsPerSecond(); // good place to calculate clock frequency
+		F64 iclock_freq = 1000.0 / get_clock_count(); // good place to calculate clock frequency
 
 		F64 total_time = 0;
 		LLSD sd;
@@ -442,7 +442,7 @@ void BlockTimer::reset()
 
 	// walk up stack of active timers and reset start times to current time
 	// effectively zeroing out any accumulated time
-	U32 cur_time = getCPUClockCount32();
+	U64 cur_time = getCPUClockCount64();
 
 	// root defined by parent pointing to self
 	CurTimerData* cur_data = sCurTimerData.get();
@@ -510,7 +510,7 @@ std::vector<BlockTimer*>& BlockTimer::getChildren()
 //static
 void BlockTimer::nextFrame()
 {
-	BlockTimer::countsPerSecond(); // good place to calculate clock frequency
+	get_clock_count(); // good place to calculate clock frequency
 	U64 frame_time = BlockTimer::getCPUClockCount64();
 	if ((frame_time - sLastFrameTime) >> 8 > 0xffffffff)
 	{
@@ -534,7 +534,7 @@ void Time::dumpCurTimes()
 	// accumulate timings, etc.
 	BlockTimer::processTimes();
 	
-	F64 clock_freq = (F64)BlockTimer::countsPerSecond();
+	F64 clock_freq = (F64)get_clock_count();
 	F64 iclock_freq = 1000.0 / clock_freq; // clock_ticks -> milliseconds
 
 	// walk over timers in depth order and output timings
-- 
cgit v1.2.3


From 02d503bf8f8890c6d4b57dd09a1fde2973715b75 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 29 Nov 2012 00:43:25 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system moved runtime timer
 tree topology information to separate array instead of recording stack

---
 indra/llcommon/llfasttimer.cpp           | 85 +++++++++++++++++---------------
 indra/llcommon/llfasttimer.h             | 34 +++++++------
 indra/llcommon/lltrace.h                 | 13 ++++-
 indra/llcommon/lltracethreadrecorder.cpp | 20 +++++---
 indra/llcommon/lltracethreadrecorder.h   |  4 +-
 5 files changed, 91 insertions(+), 65 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index e88a5a9ed1..1b3498cce3 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -58,24 +58,27 @@ namespace LLTrace
 //////////////////////////////////////////////////////////////////////////////
 // statics
 
-S32 BlockTimer::sCurFrameIndex = -1;
-S32 BlockTimer::sLastFrameIndex = -1;
-U64 BlockTimer::sLastFrameTime = BlockTimer::getCPUClockCount64();
-bool BlockTimer::sPauseHistory = 0;
-bool BlockTimer::sResetHistory = 0;
-LLThreadLocalPointer<CurTimerData> BlockTimer::sCurTimerData;
-bool BlockTimer::sLog = false;
-std::string BlockTimer::sLogName = "";
-bool BlockTimer::sMetricLog = false;
-static LLMutex*			sLogLock = NULL;
-static std::queue<LLSD> sLogQueue;
+S32         BlockTimer::sCurFrameIndex   = -1;
+S32         BlockTimer::sLastFrameIndex  = -1;
+U64         BlockTimer::sLastFrameTime   = BlockTimer::getCPUClockCount64();
+bool        BlockTimer::sPauseHistory    = 0;
+bool        BlockTimer::sResetHistory    = 0;
+bool        BlockTimer::sLog		     = false;
+std::string BlockTimer::sLogName         = "";
+bool        BlockTimer::sMetricLog       = false;
 
 #if LL_LINUX || LL_SOLARIS
-U64 BlockTimer::sClockResolution = 1000000000; // Nanosecond resolution
+U64         BlockTimer::sClockResolution = 1000000000; // Nanosecond resolution
 #else
-U64 BlockTimer::sClockResolution = 1000000; // Microsecond resolution
+U64         BlockTimer::sClockResolution = 1000000; // Microsecond resolution
 #endif
 
+LLThreadLocalPointer<CurTimerData> BlockTimer::sCurTimerData;
+
+static LLMutex*			sLogLock = NULL;
+static std::queue<LLSD> sLogQueue;
+
+
 // FIXME: move these declarations to the relevant modules
 
 // helper functions
@@ -108,6 +111,7 @@ static timer_tree_dfs_iterator_t end_timer_tree()
 	return timer_tree_dfs_iterator_t(); 
 }
 
+
 BlockTimer& BlockTimer::getRootTimer()
 {
 	static BlockTimer root_timer("root", true, NULL);
@@ -142,7 +146,7 @@ U64 BlockTimer::countsPerSecond() // counts per second for the *32-bit* timer
 
 	// we drop the low-order byte in our timers, so report a lower frequency
 #else
-	// If we're not using RDTSC, each fasttimer tick is just a performance counter tick.
+	// If we're not using RDTSC, each fast timer tick is just a performance counter tick.
 	// Not redefining the clock frequency itself (in llprocessor.cpp/calculate_cpu_frequency())
 	// since that would change displayed MHz stats for CPUs
 	static bool firstcall = true;
@@ -268,17 +272,19 @@ void BlockTimer::buildHierarchy()
 			// when this timer was called
 			if (timer.mParent == &BlockTimer::getRootTimer())
 			{
-				if (timer.getPrimaryAccumulator().mLastCaller)
-			{
-				timer.setParent(timer.getPrimaryAccumulator().mLastCaller);
+				TimerTreeNode& tree_node = sCurTimerData->mTimerTreeData[timer.getIndex()];
+
+				if (tree_node.mLastCaller)
+				{
+					timer.setParent(tree_node.mLastCaller);
 				}
 				// no need to push up tree on first use, flag can be set spuriously
-				timer.getPrimaryAccumulator().mMoveUpTree = false;
+				tree_node.mMoveUpTree = false;
 			}
 		}
 	}
 
-	// bump timers up tree if they've been flagged as being in the wrong place
+	// bump timers up tree if they have 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(BlockTimer::getRootTimer());
@@ -288,15 +294,16 @@ void BlockTimer::buildHierarchy()
 		BlockTimer* timerp = *it;
 		// skip root timer
 		if (timerp == &BlockTimer::getRootTimer()) continue;
+		TimerTreeNode& tree_node = sCurTimerData->mTimerTreeData[timerp->getIndex()];
 
-		if (timerp->getPrimaryAccumulator().mMoveUpTree)
+		if (tree_node.mMoveUpTree)
 		{
 			// since ancestors have already been visited, re-parenting 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->getPrimaryAccumulator().mMoveUpTree = false;
+			tree_node.mMoveUpTree = false;
 
 			// don't bubble up any ancestors until descendants are done bubbling up
 			it.skipAncestors();
@@ -322,11 +329,11 @@ void BlockTimer::accumulateTimings()
 {
 	U64 cur_time = getCPUClockCount64();
 
-	// walk up stack of active timers and accumulate current time while leaving timing structures active
-	Time* cur_timer = sCurTimerData->mCurTimer;
 	// root defined by parent pointing to self
 	CurTimerData* cur_data = sCurTimerData.get();
-	TimerAccumulator& accumulator = sCurTimerData->mTimerData->getPrimaryAccumulator();
+	// walk up stack of active timers and accumulate current time while leaving timing structures active
+	Time* cur_timer = cur_data->mCurTimer;
+	TimerAccumulator& accumulator = cur_data->mTimerData->getPrimaryAccumulator();
 	while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
 	{
 		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
@@ -431,11 +438,13 @@ void BlockTimer::resetFrame()
 	{
 		BlockTimer& timer = *it;
 		TimerAccumulator& accumulator = timer.getPrimaryAccumulator();
+		TimerTreeNode& tree_node = sCurTimerData->mTimerTreeData[timer.getIndex()];
+
 		accumulator.mSelfTimeCounter = 0;
 		accumulator.mTotalTimeCounter = 0;
 		accumulator.mCalls = 0;
-		accumulator.mLastCaller = NULL;
-		accumulator.mMoveUpTree = false;
+		tree_node.mLastCaller = NULL;
+		tree_node.mMoveUpTree = false;
 	}
 }
 
@@ -579,32 +588,28 @@ void Time::writeLog(std::ostream& os)
 }
 
 
-LLTrace::TimerAccumulator::TimerAccumulator() :	mSelfTimeCounter(0),
+TimerAccumulator::TimerAccumulator() :	mSelfTimeCounter(0),
 	mTotalTimeCounter(0),
-	mCalls(0),
-	mLastCaller(NULL),
-	mActiveCount(0),
-	mMoveUpTree(false)
+	mCalls(0)
 {}
 
-void LLTrace::TimerAccumulator::addSamples( const LLTrace::TimerAccumulator& other )
+void TimerAccumulator::addSamples( const TimerAccumulator& other )
 {
 	mSelfTimeCounter += other.mSelfTimeCounter;
 	mTotalTimeCounter += other.mTotalTimeCounter;
 	mCalls += other.mCalls;
-	if (!mLastCaller)
-	{
-		mLastCaller = other.mLastCaller;
-	}
-
-	//mActiveCount stays the same;
-	mMoveUpTree |= other.mMoveUpTree;
 }
 
-void LLTrace::TimerAccumulator::reset( const LLTrace::TimerAccumulator* other )
+void TimerAccumulator::reset( const TimerAccumulator* other )
 {
 	mTotalTimeCounter = 0;
 	mSelfTimeCounter = 0;
 	mCalls = 0;
 }
+
+TimerTreeNode::TimerTreeNode()
+:	mLastCaller(NULL),
+	mActiveCount(0),
+	mMoveUpTree(false)
+{}
 }
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index cfe2cf5371..9f981480f2 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -37,11 +37,13 @@ class LLMutex;
 
 namespace LLTrace
 {
+
 struct CurTimerData
 {
 	class Time*			mCurTimer;
 	class BlockTimer*	mTimerData;
 	U64					mChildTime;
+	TimerTreeNode*		mTimerTreeData;
 };
 
 class Time
@@ -269,20 +271,20 @@ public:
 	// tree structure
 	BlockTimer*					mParent;				// BlockTimer of caller(parent)
 	std::vector<BlockTimer*>	mChildren;
-	bool						mCollapsed;				// don't show children
-	bool						mNeedsSorting;			// sort children whenever child added
+	bool						mCollapsed,				// don't show children
+								mNeedsSorting;			// sort children whenever child added
 
 	// statics
 	static std::string							sLogName;
-	static bool									sMetricLog;
-	static bool									sLog;	
+	static bool									sMetricLog,
+												sLog;	
 	static LLThreadLocalPointer<CurTimerData>	sCurTimerData;
 	static U64									sClockResolution;
-	static S32									sCurFrameIndex;
-	static S32									sLastFrameIndex;
+	static S32									sCurFrameIndex,
+												sLastFrameIndex;
 	static U64									sLastFrameTime;
-	static bool 								sPauseHistory;
-	static bool 								sResetHistory;
+	static bool 								sPauseHistory,
+												sResetHistory;
 
 };
 
@@ -291,13 +293,12 @@ LL_FORCE_INLINE Time::Time(BlockTimer& timer)
 #if FAST_TIMER_ON
 	mStartTime = BlockTimer::getCPUClockCount64();
 
-	TimerAccumulator& accumulator = timer.getPrimaryAccumulator();
-	accumulator.mActiveCount++;
-	accumulator.mCalls++;
+	CurTimerData* cur_timer_data = BlockTimer::sCurTimerData.get();
+	TimerTreeNode& tree_node = cur_timer_data->mTimerTreeData[timer.getIndex()];
+	tree_node.mActiveCount++;
 	// keep current parent as long as it is active when we are
-	accumulator.mMoveUpTree |= (timer.mParent->getPrimaryAccumulator().mActiveCount == 0);
+	tree_node.mMoveUpTree |= (cur_timer_data->mTimerTreeData[timer.mParent->getIndex()].mActiveCount == 0);
 
-	CurTimerData* cur_timer_data = BlockTimer::sCurTimerData.get();
 	// store top of stack
 	mLastTimerData = *cur_timer_data;
 	// push new information
@@ -313,13 +314,16 @@ LL_FORCE_INLINE Time::~Time()
 	U64 total_time = BlockTimer::getCPUClockCount64() - mStartTime;
 	CurTimerData* cur_timer_data = BlockTimer::sCurTimerData.get();
 	TimerAccumulator& accumulator = cur_timer_data->mTimerData->getPrimaryAccumulator();
+	TimerTreeNode& tree_node = cur_timer_data->mTimerTreeData[cur_timer_data->mTimerData->getIndex()];
+
+	accumulator.mCalls++;
 	accumulator.mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
 	accumulator.mTotalTimeCounter += total_time;
-	accumulator.mActiveCount--;
+	tree_node.mActiveCount--;
 
 	// store last caller to bootstrap tree creation
 	// do this in the destructor in case of recursion to get topmost caller
-	accumulator.mLastCaller = mLastTimerData.mTimerData;
+	tree_node.mLastCaller = mLastTimerData.mTimerData;
 
 	// we are only tracking self time, so subtract our total time delta from parents
 	mLastTimerData.mChildTime += total_time;
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 11651ef953..ad9f170aae 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -189,6 +189,11 @@ namespace LLTrace
 			delete[] old_storage;
 		}
 
+		size_t size()
+		{
+			return mNextStorageSlot;
+		}
+
 		static AccumulatorBuffer<ACCUMULATOR>& getDefaultBuffer()
 		{
 			static AccumulatorBuffer sBuffer(STATIC_ALLOC);
@@ -216,7 +221,7 @@ namespace LLTrace
 			mAccumulatorIndex = AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer().reserveSlot();
 		}
 
-		LL_FORCE_INLINE ACCUMULATOR& getPrimaryAccumulator()
+		LL_FORCE_INLINE ACCUMULATOR& getPrimaryAccumulator() const
 		{
 			return AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage()[mAccumulatorIndex];
 		}
@@ -399,6 +404,12 @@ namespace LLTrace
 		U64 						mSelfTimeCounter,
 									mTotalTimeCounter;
 		U32 						mCalls;
+	};
+
+	class TimerTreeNode
+	{
+	public:
+		TimerTreeNode();
 		class BlockTimer*			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
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index faaab4c8e7..0a2d79cf3a 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -41,25 +41,29 @@ ThreadRecorder::ThreadRecorder()
 	get_thread_recorder() = this;
 	mFullRecording.start();
 
-	BlockTimer::sCurTimerData = new CurTimerData();
-}
+	mRootTimerData = new CurTimerData();
+	mRootTimerData->mTimerData = &BlockTimer::getRootTimer();
+	mRootTimerData->mTimerTreeData = new TimerTreeNode[AccumulatorBuffer<TimerAccumulator>::getDefaultBuffer().size()];
+	BlockTimer::sCurTimerData = mRootTimerData;
 
-ThreadRecorder::ThreadRecorder( const ThreadRecorder& other ) 
-:	mFullRecording(other.mFullRecording)
-{
-	get_thread_recorder() = this;
-	mFullRecording.start();
+	mRootTimer = new Time(BlockTimer::getRootTimer());
+	mRootTimerData->mCurTimer = mRootTimer;
+
+	mRootTimerData->mTimerTreeData[BlockTimer::getRootTimer().getIndex()].mActiveCount = 1;
 }
 
 ThreadRecorder::~ThreadRecorder()
 {
+	delete mRootTimer;
+
 	while(mActiveRecordings.size())
 	{
 		mActiveRecordings.front().mTargetRecording->stop();
 	}
 	get_thread_recorder() = NULL;
-	delete BlockTimer::sCurTimerData.get();
 	BlockTimer::sCurTimerData = NULL;
+	delete [] mRootTimerData->mTimerTreeData;
+	delete mRootTimerData;
 }
 
 void ThreadRecorder::activate( Recording* recording )
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 44fe67384b..277a468a40 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -41,7 +41,6 @@ namespace LLTrace
 		struct ActiveRecording;
 	public:
 		ThreadRecorder();
-		ThreadRecorder(const ThreadRecorder& other);
 
 		virtual ~ThreadRecorder();
 
@@ -63,6 +62,9 @@ namespace LLTrace
 		};
 		Recording					mFullRecording;
 		std::list<ActiveRecording>	mActiveRecordings;
+
+		struct CurTimerData*	mRootTimerData;
+		class Time*				mRootTimer;
 	};
 
 	class LL_COMMON_API MasterThreadRecorder : public ThreadRecorder
-- 
cgit v1.2.3


From ca37317a1473bb79ef8de4f683231700cb9e062c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 30 Nov 2012 15:48:22 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system fixed crash when
 sending viewer asset stats

---
 indra/llcommon/lltracerecording.cpp | 13 +++++++++----
 indra/llcommon/lltracerecording.h   |  2 ++
 2 files changed, 11 insertions(+), 4 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index e7ed55e8ae..e31e36cb27 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -58,10 +58,6 @@ Recording::Recording( const Recording& other )
 	mStackTimers       = other.mStackTimers;
 
 	LLStopWatchControlsMixin::initTo(other.getPlayState());
-	if (other.isStarted())
-	{
-		handleStart();
-	}
 }
 
 
@@ -127,6 +123,15 @@ bool Recording::isPrimary() const
 	return mCounts->isPrimary();
 }
 
+void Recording::makeUnique()
+{
+	mCountsFloat.makeUnique();
+	mMeasurementsFloat.makeUnique();
+	mCounts.makeUnique();
+	mMeasurements.makeUnique();
+	mStackTimers.makeUnique();
+}
+
 void Recording::appendRecording( const Recording& other )
 {
 	mCountsFloat.write()->addSamples(*other.mCountsFloat);
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index efc54d240f..e5a21a2d38 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -112,6 +112,8 @@ namespace LLTrace
 		void makePrimary();
 		bool isPrimary() const;
 
+		void makeUnique();
+
 		void appendRecording(const Recording& other);
 
 		void update();
-- 
cgit v1.2.3


From ca2207bd35c33b13b122f875a5a7d218f94ca3fc Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sat, 1 Dec 2012 00:17:04 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system fixed scale of
 reported times moved reset calls to happen at same time so we don't show
 partial results

---
 indra/llcommon/llfasttimer.cpp | 6 ++----
 indra/llcommon/lltrace.h       | 3 ++-
 indra/llcommon/llunit.h        | 2 +-
 3 files changed, 5 insertions(+), 6 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 1b3498cce3..19676cc0c6 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -144,7 +144,6 @@ U64 BlockTimer::countsPerSecond() // counts per second for the *32-bit* timer
 	//getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz
 	static LLUnit<LLUnits::Hertz, U64> sCPUClockFrequency = LLProcessorInfo().getCPUFrequency();
 
-	// we drop the low-order byte in our timers, so report a lower frequency
 #else
 	// If we're not using RDTSC, each fast timer tick is just a performance counter tick.
 	// Not redefining the clock frequency itself (in llprocessor.cpp/calculate_cpu_frequency())
@@ -157,7 +156,7 @@ U64 BlockTimer::countsPerSecond() // counts per second for the *32-bit* timer
 		firstcall = false;
 	}
 #endif
-	return sCPUClockFrequency >> 8;
+	return sCPUClockFrequency;
 }
 #endif
 
@@ -390,8 +389,7 @@ void BlockTimer::resetFrame()
 		static S32 call_count = 0;
 		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() << LL_ENDL;
+			LL_DEBUGS("FastTimers") << "countsPerSecond: " << countsPerSecond() << 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;
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index ad9f170aae..3e43a85e80 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -223,7 +223,8 @@ namespace LLTrace
 
 		LL_FORCE_INLINE ACCUMULATOR& getPrimaryAccumulator() const
 		{
-			return AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage()[mAccumulatorIndex];
+			ACCUMULATOR* accumulator_storage = AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage();
+			return accumulator_storage[mAccumulatorIndex];
 		}
 
 		size_t getIndex() const { return mAccumulatorIndex; }
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 53570779fc..fc1347b59f 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -71,7 +71,7 @@ template<typename UNIT_TYPE, typename STORAGE_TYPE>
 struct LLUnit
 {
 	typedef LLUnit<UNIT_TYPE, STORAGE_TYPE> self_t;
-	typedef typename STORAGE_TYPE storage_t;
+	typedef STORAGE_TYPE storage_t;
 
 	LLUnit(storage_t value = storage_t())
 	:	mValue(value)
-- 
cgit v1.2.3


From 4f9a5d0554c16a81625574a7a4ad6d5070e649e3 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sat, 1 Dec 2012 12:49:01 -0800
Subject: fix for gcc compile errors

---
 indra/llcommon/llapr.h  | 4 ++--
 indra/llcommon/llunit.h | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 7ca0f505ef..199b5291dd 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -249,7 +249,7 @@ public:
 //*******************************************************************************************************************************
 };
 
-class LLThreadLocalPointerBase : LLInstanceTracker<LLThreadLocalPointerBase>
+class LLThreadLocalPointerBase : public LLInstanceTracker<LLThreadLocalPointerBase>
 {
 public:
 	LLThreadLocalPointerBase()
@@ -331,7 +331,7 @@ public:
 
 
 	LLThreadLocalPointer(const LLThreadLocalPointer<T>& other)
-		:	LLThreadLocalPointerBase(other)
+	:	LLThreadLocalPointerBase(other)
 	{
 		set(other.get());		
 	}
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index fc1347b59f..54902b6322 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -177,6 +177,7 @@ template<typename UNIT_TYPE, typename STORAGE_TYPE>
 struct LLUnitStrict : public LLUnit<UNIT_TYPE, STORAGE_TYPE>
 {
 	typedef LLUnitStrict<UNIT_TYPE, STORAGE_TYPE> self_t;
+	typedef typename LLUnit<UNIT_TYPE, STORAGE_TYPE>::storage_t storage_t;
 
 	explicit LLUnitStrict(storage_t value = storage_t())
 	:	LLUnit(value)
-- 
cgit v1.2.3


From 13e4edf1cd664864afa585bc83bbe99d4f743326 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sun, 2 Dec 2012 23:00:36 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system started moving fast
 timer historical stats over to LLTrace periodic recording

---
 indra/llcommon/llfasttimer.cpp      |  6 +++---
 indra/llcommon/lltracerecording.cpp | 11 +++++++++++
 indra/llcommon/lltracerecording.h   | 22 +++++++++++++---------
 3 files changed, 27 insertions(+), 12 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 19676cc0c6..e33cb76eff 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -133,12 +133,12 @@ void BlockTimer::setLogLock(LLMutex* lock)
 
 //static
 #if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
-U64 BlockTimer::countsPerSecond() // counts per second for the *32-bit* timer
+U64 BlockTimer::countsPerSecond() // counts per second for the *64-bit* timer
 {
-	return sClockResolution >> 8;
+	return sClockResolution;
 }
 #else // windows or x86-mac or x86-linux or x86-solaris
-U64 BlockTimer::countsPerSecond() // counts per second for the *32-bit* timer
+U64 BlockTimer::countsPerSecond() // counts per second for the *64-bit* timer
 {
 #if LL_FASTTIMER_USE_RDTSC || !LL_WINDOWS
 	//getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index e31e36cb27..ff3ae1e553 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -26,6 +26,7 @@
 #include "linden_common.h"
 
 #include "lltrace.h"
+#include "llfasttimer.h"
 #include "lltracerecording.h"
 #include "lltracethreadrecorder.h"
 #include "llthread.h"
@@ -142,6 +143,16 @@ void Recording::appendRecording( const Recording& other )
 	mElapsedSeconds += other.mElapsedSeconds;
 }
 
+LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimerAccumulator>& stat) const
+{
+	return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / (F64)LLTrace::BlockTimer::countsPerSecond();
+}
+
+LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimerAccumulator>& stat) const
+{
+	return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / ((F64)LLTrace::BlockTimer::countsPerSecond() * mElapsedSeconds);
+}
+
 F64 Recording::getSum( const TraceType<CountAccumulator<F64> >& stat ) const
 {
 	return (*mCountsFloat)[stat.getIndex()].getSum();
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index e5a21a2d38..0adea2663b 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -118,6 +118,10 @@ namespace LLTrace
 
 		void update();
 
+		// Timer accessors
+		LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimerAccumulator>& stat) const;
+		LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimerAccumulator>& stat) const;
+
 		// Count accessors
 		F64 getSum(const TraceType<CountAccumulator<F64> >& stat) const;
 		S64 getSum(const TraceType<CountAccumulator<S64> >& stat) const;
@@ -273,18 +277,18 @@ namespace LLTrace
 		Recording& getTotalRecording();
 
 		template <typename T>
-		typename T getPeriodMin(const TraceType<CountAccumulator<T> >& stat) const
+		typename T::value_t getPeriodMin(const TraceType<T>& stat) const
 		{
-			T min_val = (std::numeric_limits<T>::max)();
+			typename T::value_t min_val = (std::numeric_limits<typename T::value_t>::max)();
 			for (S32 i = 0; i < mNumPeriods; i++)
 			{
 				min_val = llmin(min_val, mRecordingPeriods[i].getSum(stat));
 			}
-			return (T)min_val;
+			return min_val;
 		}
 
 		template <typename T>
-		F64 getPeriodMinPerSec(const TraceType<CountAccumulator<T> >& stat) const
+		F64 getPeriodMinPerSec(const TraceType<T>& stat) const
 		{
 			F64 min_val = (std::numeric_limits<F64>::max)();
 			for (S32 i = 0; i < mNumPeriods; i++)
@@ -295,9 +299,9 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		T getPeriodMax(const TraceType<CountAccumulator<T> >& stat) const
+		typename T::value_t getPeriodMax(const TraceType<T>& stat) const
 		{
-			T max_val = (std::numeric_limits<T>::min)();
+			typename T::value_t max_val = (std::numeric_limits<typename T::value_t>::min)();
 			for (S32 i = 0; i < mNumPeriods; i++)
 			{
 				max_val = llmax(max_val, mRecordingPeriods[i].getSum(stat));
@@ -306,7 +310,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		F64 getPeriodMaxPerSec(const TraceType<CountAccumulator<T> >& stat) const
+		F64 getPeriodMaxPerSec(const TraceType<T>& stat) const
 		{
 			F64 max_val = (std::numeric_limits<F64>::min)();
 			for (S32 i = 0; i < mNumPeriods; i++)
@@ -317,7 +321,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		F64 getPeriodMean(const TraceType<CountAccumulator<T> >& stat) const
+		F64 getPeriodMean(const TraceType<T>& stat) const
 		{
 			F64 mean = 0.0;
 			F64 count = 0;
@@ -334,7 +338,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		F64 getPeriodMeanPerSec(const TraceType<CountAccumulator<T> >& stat) const
+		F64 getPeriodMeanPerSec(const TraceType<T>& stat) const
 		{
 			F64 mean = 0.0;
 			F64 count = 0;
-- 
cgit v1.2.3


From 407e5013f3845208e0a60e26e8f0a7fad997df5d Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 3 Dec 2012 19:54:53 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system converted fast
 timer view over to new lltrace mechanisms

---
 indra/llcommon/llfasttimer.cpp               | 538 ++++++++++++---------------
 indra/llcommon/llfasttimer.h                 | 111 +++---
 indra/llcommon/llmetricperformancetester.cpp |   4 +-
 indra/llcommon/lltrace.h                     |  39 +-
 indra/llcommon/lltracerecording.cpp          |  21 +-
 indra/llcommon/lltracerecording.h            |   8 +-
 indra/llcommon/lltracethreadrecorder.cpp     |  12 +-
 indra/llcommon/lltracethreadrecorder.h       |   2 +-
 indra/llcommon/llunit.h                      |   8 +-
 9 files changed, 333 insertions(+), 410 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index e33cb76eff..cf7655acf7 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -34,6 +34,7 @@
 #include "llsdserialize.h"
 #include "llunit.h"
 #include "llsd.h"
+#include "lltracerecording.h"
 
 #include <boost/bind.hpp>
 #include <queue>
@@ -58,22 +59,22 @@ namespace LLTrace
 //////////////////////////////////////////////////////////////////////////////
 // statics
 
-S32         BlockTimer::sCurFrameIndex   = -1;
-S32         BlockTimer::sLastFrameIndex  = -1;
-U64         BlockTimer::sLastFrameTime   = BlockTimer::getCPUClockCount64();
-bool        BlockTimer::sPauseHistory    = 0;
-bool        BlockTimer::sResetHistory    = 0;
-bool        BlockTimer::sLog		     = false;
-std::string BlockTimer::sLogName         = "";
-bool        BlockTimer::sMetricLog       = false;
+S32         TimeBlock::sCurFrameIndex   = -1;
+S32         TimeBlock::sLastFrameIndex  = -1;
+U64         TimeBlock::sLastFrameTime   = TimeBlock::getCPUClockCount64();
+bool        TimeBlock::sPauseHistory    = 0;
+bool        TimeBlock::sResetHistory    = 0;
+bool        TimeBlock::sLog		     = false;
+std::string TimeBlock::sLogName         = "";
+bool        TimeBlock::sMetricLog       = false;
 
 #if LL_LINUX || LL_SOLARIS
-U64         BlockTimer::sClockResolution = 1000000000; // Nanosecond resolution
+U64         TimeBlock::sClockResolution = 1000000000; // Nanosecond resolution
 #else
-U64         BlockTimer::sClockResolution = 1000000; // Microsecond resolution
+U64         TimeBlock::sClockResolution = 1000000; // Microsecond resolution
 #endif
 
-LLThreadLocalPointer<CurTimerData> BlockTimer::sCurTimerData;
+LLThreadLocalPointer<CurTimerData> TimeBlock::sCurTimerData;
 
 static LLMutex*			sLogLock = NULL;
 static std::queue<LLSD> sLogQueue;
@@ -82,13 +83,13 @@ static std::queue<LLSD> sLogQueue;
 // FIXME: move these declarations to the relevant modules
 
 // helper functions
-typedef LLTreeDFSPostIter<BlockTimer, BlockTimer::child_const_iter> timer_tree_bottom_up_iterator_t;
+typedef LLTreeDFSPostIter<TimeBlock, TimeBlock::child_const_iter> timer_tree_bottom_up_iterator_t;
 
-static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(BlockTimer& id) 
+static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(TimeBlock& id) 
 { 
 	return timer_tree_bottom_up_iterator_t(&id, 
-							boost::bind(boost::mem_fn(&BlockTimer::beginChildren), _1), 
-							boost::bind(boost::mem_fn(&BlockTimer::endChildren), _1));
+							boost::bind(boost::mem_fn(&TimeBlock::beginChildren), _1), 
+							boost::bind(boost::mem_fn(&TimeBlock::endChildren), _1));
 }
 
 static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up() 
@@ -96,14 +97,14 @@ static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up()
 	return timer_tree_bottom_up_iterator_t(); 
 }
 
-typedef LLTreeDFSIter<BlockTimer, BlockTimer::child_const_iter> timer_tree_dfs_iterator_t;
+typedef LLTreeDFSIter<TimeBlock, TimeBlock::child_const_iter> timer_tree_dfs_iterator_t;
 
 
-static timer_tree_dfs_iterator_t begin_timer_tree(BlockTimer& id) 
+static timer_tree_dfs_iterator_t begin_timer_tree(TimeBlock& id) 
 { 
 	return timer_tree_dfs_iterator_t(&id, 
-		boost::bind(boost::mem_fn(&BlockTimer::beginChildren), _1), 
-							boost::bind(boost::mem_fn(&BlockTimer::endChildren), _1));
+		boost::bind(boost::mem_fn(&TimeBlock::beginChildren), _1), 
+							boost::bind(boost::mem_fn(&TimeBlock::endChildren), _1));
 }
 
 static timer_tree_dfs_iterator_t end_timer_tree() 
@@ -112,20 +113,29 @@ static timer_tree_dfs_iterator_t end_timer_tree()
 }
 
 
-BlockTimer& BlockTimer::getRootTimer()
+// sort child timers by name
+struct SortTimerByName
 {
-	static BlockTimer root_timer("root", true, NULL);
+	bool operator()(const TimeBlock* i1, const TimeBlock* i2)
+	{
+		return i1->getName() < i2->getName();
+	}
+};
+
+TimeBlock& TimeBlock::getRootTimer()
+{
+	static TimeBlock root_timer("root", true, NULL);
 	return root_timer;
 }
 
-void BlockTimer::pushLog(LLSD log)
+void TimeBlock::pushLog(LLSD log)
 {
 	LLMutexLock lock(sLogLock);
 
 	sLogQueue.push(log);
 }
 
-void BlockTimer::setLogLock(LLMutex* lock)
+void TimeBlock::setLogLock(LLMutex* lock)
 {
 	sLogLock = lock;
 }
@@ -133,12 +143,12 @@ void BlockTimer::setLogLock(LLMutex* lock)
 
 //static
 #if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
-U64 BlockTimer::countsPerSecond() // counts per second for the *64-bit* timer
+U64 TimeBlock::countsPerSecond() // counts per second for the *64-bit* timer
 {
 	return sClockResolution;
 }
 #else // windows or x86-mac or x86-linux or x86-solaris
-U64 BlockTimer::countsPerSecond() // counts per second for the *64-bit* timer
+U64 TimeBlock::countsPerSecond() // counts per second for the *64-bit* timer
 {
 #if LL_FASTTIMER_USE_RDTSC || !LL_WINDOWS
 	//getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz
@@ -160,13 +170,10 @@ U64 BlockTimer::countsPerSecond() // counts per second for the *64-bit* timer
 }
 #endif
 
-BlockTimer::BlockTimer(const char* name, bool open, BlockTimer* parent)
+TimeBlock::TimeBlock(const char* name, bool open, TimeBlock* parent)
 :	TraceType(name),
 	mCollapsed(true),
 	mParent(NULL),
-	mTreeTimeCounter(0),
-	mCountAverage(0),
-	mCallAverage(0),
 	mNeedsSorting(false)
 {
 	setCollapsed(!open);
@@ -179,37 +186,26 @@ BlockTimer::BlockTimer(const char* name, bool open, BlockTimer* parent)
 	{
 		mParent = this;
 	}
-
-	mCountHistory = new U64[HISTORY_NUM];
-	memset(mCountHistory, 0, sizeof(U64) * HISTORY_NUM);
-	mCallHistory = new U32[HISTORY_NUM];
-	memset(mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
 }
 
-BlockTimer::~BlockTimer()
-{
-	delete[] mCountHistory;
-	delete[] mCallHistory;
-}
-
-void BlockTimer::setParent(BlockTimer* parent)
+void TimeBlock::setParent(TimeBlock* parent)
 {
 	llassert_always(parent != this);
 	llassert_always(parent != NULL);
 
 	if (mParent)
 	{
-		// subtract our accumulated from previous parent
-		for (S32 i = 0; i < HISTORY_NUM; i++)
-		{
-			mParent->mCountHistory[i] -= mCountHistory[i];
-		}
+		//// subtract our accumulated from previous parent
+		//for (S32 i = 0; i < HISTORY_NUM; i++)
+		//{
+		//	mParent->mCountHistory[i] -= mCountHistory[i];
+		//}
 
-		// subtract average timing from previous parent
-		mParent->mCountAverage -= mCountAverage;
+		//// subtract average timing from previous parent
+		//mParent->mCountAverage -= mCountAverage;
 
-		std::vector<BlockTimer*>& children = mParent->getChildren();
-		std::vector<BlockTimer*>::iterator found_it = std::find(children.begin(), children.end(), this);
+		std::vector<TimeBlock*>& children = mParent->getChildren();
+		std::vector<TimeBlock*>::iterator found_it = std::find(children.begin(), children.end(), this);
 		if (found_it != children.end())
 		{
 			children.erase(found_it);
@@ -224,10 +220,10 @@ void BlockTimer::setParent(BlockTimer* parent)
 	}
 }
 
-S32 BlockTimer::getDepth()
+S32 TimeBlock::getDepth()
 {
 	S32 depth = 0;
-	BlockTimer* timerp = mParent;
+	TimeBlock* timerp = mParent;
 	while(timerp)
 	{
 		depth++;
@@ -238,291 +234,152 @@ S32 BlockTimer::getDepth()
 }
 
 // static
-void BlockTimer::processTimes()
+void TimeBlock::processTimes()
 {
-	if (getCurFrameIndex() < 0) return;
-
-	buildHierarchy();
-	accumulateTimings();
-}
-
-// sort child timers by name
-struct SortTimerByName
-{
-	bool operator()(const BlockTimer* i1, const BlockTimer* i2)
-	{
-		return i1->getName() < i2->getName();
-	}
-};
-
-//static
-void BlockTimer::buildHierarchy()
-{
-	if (getCurFrameIndex() < 0 ) return;
-
-	// set up initial tree
+	//void TimeBlock::buildHierarchy()
 	{
-		for (LLInstanceTracker<BlockTimer>::instance_iter it = LLInstanceTracker<BlockTimer>::beginInstances(), end_it = LLInstanceTracker<BlockTimer>::endInstances(); it != end_it; ++it)
+		// set up initial tree
 		{
-			BlockTimer& timer = *it;
-			if (&timer == &BlockTimer::getRootTimer()) continue;
-			
-			// bootstrap tree construction by attaching to last timer to be on stack
-			// when this timer was called
-			if (timer.mParent == &BlockTimer::getRootTimer())
+			for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(); it != end_it; ++it)
 			{
-				TimerTreeNode& tree_node = sCurTimerData->mTimerTreeData[timer.getIndex()];
+				TimeBlock& timer = *it;
+				if (&timer == &TimeBlock::getRootTimer()) continue;
 
-				if (tree_node.mLastCaller)
+				// bootstrap tree construction by attaching to last timer to be on stack
+				// when this timer was called
+				if (timer.mParent == &TimeBlock::getRootTimer())
 				{
-					timer.setParent(tree_node.mLastCaller);
+					TimeBlockTreeNode& tree_node = sCurTimerData->mTimerTreeData[timer.getIndex()];
+
+					if (tree_node.mLastCaller)
+					{
+						timer.setParent(tree_node.mLastCaller);
+					}
+					// no need to push up tree on first use, flag can be set spuriously
+					tree_node.mMoveUpTree = false;
 				}
-				// no need to push up tree on first use, flag can be set spuriously
-				tree_node.mMoveUpTree = false;
 			}
 		}
-	}
-
-	// bump timers up tree if they have 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(BlockTimer::getRootTimer());
-		it != end_timer_tree_bottom_up();
-		++it)
-	{
-		BlockTimer* timerp = *it;
-		// skip root timer
-		if (timerp == &BlockTimer::getRootTimer()) continue;
-		TimerTreeNode& tree_node = sCurTimerData->mTimerTreeData[timerp->getIndex()];
 
-		if (tree_node.mMoveUpTree)
+		// bump timers up tree if they have 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(TimeBlock::getRootTimer());
+			it != end_timer_tree_bottom_up();
+			++it)
 		{
-			// since ancestors have already been visited, re-parenting 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());
-			tree_node.mMoveUpTree = false;
+			TimeBlock* timerp = *it;
+			// skip root timer
+			if (timerp == &TimeBlock::getRootTimer()) continue;
+			TimeBlockTreeNode& tree_node = sCurTimerData->mTimerTreeData[timerp->getIndex()];
 
-			// don't bubble up any ancestors until descendants are done bubbling up
-			it.skipAncestors();
-		}
-	}
+			if (tree_node.mMoveUpTree)
+			{
+				// since ancestors have already been visited, re-parenting 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());
+				tree_node.mMoveUpTree = false;
 
-	// sort timers by time last called, so call graph makes sense
-	for(timer_tree_dfs_iterator_t it = begin_timer_tree(BlockTimer::getRootTimer());
-		it != end_timer_tree();
-		++it)
-	{
-		BlockTimer* timerp = (*it);
-		if (timerp->mNeedsSorting)
-		{
-			std::sort(timerp->getChildren().begin(), timerp->getChildren().end(), SortTimerByName());
+				// don't bubble up any ancestors until descendants are done bubbling up
+				it.skipAncestors();
+			}
 		}
-		timerp->mNeedsSorting = false;
-	}
-}
-
-//static
-void BlockTimer::accumulateTimings()
-{
-	U64 cur_time = getCPUClockCount64();
-
-	// root defined by parent pointing to self
-	CurTimerData* cur_data = sCurTimerData.get();
-	// walk up stack of active timers and accumulate current time while leaving timing structures active
-	Time* cur_timer = cur_data->mCurTimer;
-	TimerAccumulator& accumulator = cur_data->mTimerData->getPrimaryAccumulator();
-	while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
-	{
-		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
-		U64 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
-		cur_data->mChildTime = 0;
-		accumulator.mSelfTimeCounter += self_time_delta;
-		accumulator.mTotalTimeCounter += cumulative_time_delta;
-
-		cur_timer->mStartTime = cur_time;
 
-		cur_data = &cur_timer->mLastTimerData;
-		cur_data->mChildTime += cumulative_time_delta;
-		if (cur_data->mTimerData)
+		// sort timers by time last called, so call graph makes sense
+		for(timer_tree_dfs_iterator_t it = begin_timer_tree(TimeBlock::getRootTimer());
+			it != end_timer_tree();
+			++it)
 		{
-			accumulator = cur_data->mTimerData->getPrimaryAccumulator();
+			TimeBlock* timerp = (*it);
+			if (timerp->mNeedsSorting)
+			{
+				std::sort(timerp->getChildren().begin(), timerp->getChildren().end(), SortTimerByName());
+			}
+			timerp->mNeedsSorting = false;
 		}
-
-		cur_timer = cur_timer->mLastTimerData.mCurTimer;
 	}
-
-	// traverse tree in DFS post order, or bottom up
-	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(BlockTimer::getRootTimer());
-		it != end_timer_tree_bottom_up();
-		++it)
+	
+	//void TimeBlock::accumulateTimings()
 	{
-		BlockTimer* timerp = (*it);
-		TimerAccumulator& accumulator = timerp->getPrimaryAccumulator();
-		timerp->mTreeTimeCounter = accumulator.mSelfTimeCounter;
-		for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it)
-		{
-			timerp->mTreeTimeCounter += (*child_it)->mTreeTimeCounter;
-		}
-
-		S32 cur_frame = getCurFrameIndex();
-		if (cur_frame >= 0)
+		U64 cur_time = getCPUClockCount64();
+
+		// root defined by parent pointing to self
+		CurTimerData* cur_data = sCurTimerData.get();
+		// walk up stack of active timers and accumulate current time while leaving timing structures active
+		BlockTimer* cur_timer = cur_data->mCurTimer;
+		TimeBlockAccumulator& accumulator = cur_data->mTimerData->getPrimaryAccumulator();
+		while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
 		{
-			// update timer history
-			int hidx = cur_frame % HISTORY_NUM;
+			U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
+			U64 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
+			cur_data->mChildTime = 0;
+			accumulator.mSelfTimeCounter += self_time_delta;
+			accumulator.mTotalTimeCounter += cumulative_time_delta;
 
-			timerp->mCountHistory[hidx] = timerp->mTreeTimeCounter;
-			timerp->mCountAverage       = ((U64)timerp->mCountAverage * cur_frame + timerp->mTreeTimeCounter) / (cur_frame+1);
-			timerp->mCallHistory[hidx]  = accumulator.mCalls;
-			timerp->mCallAverage        = ((U64)timerp->mCallAverage * cur_frame + accumulator.mCalls) / (cur_frame+1);
-		}
-	}
-}
+			cur_timer->mStartTime = cur_time;
 
-// static
-void BlockTimer::resetFrame()
-{
-	if (sLog)
-	{ //output current frame counts to performance log
-
-		static S32 call_count = 0;
-		if (call_count % 100 == 0)
-		{
-			LL_DEBUGS("FastTimers") << "countsPerSecond: " << countsPerSecond() << 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()) / (LLUnit<LLUnits::Hertz, F64>(LLProcessorInfo().getCPUFrequency())) << LL_ENDL;
-		}
-		call_count++;
-
-		F64 iclock_freq = 1000.0 / get_clock_count(); // good place to calculate clock frequency
-
-		F64 total_time = 0;
-		LLSD sd;
-
-		{
-			for (LLInstanceTracker<BlockTimer>::instance_iter it = LLInstanceTracker<BlockTimer>::beginInstances(), 
-					end_it = LLInstanceTracker<BlockTimer>::endInstances(); 
-				it != end_it; 
-				++it)
+			cur_data = &cur_timer->mLastTimerData;
+			cur_data->mChildTime += cumulative_time_delta;
+			if (cur_data->mTimerData)
 			{
-				BlockTimer& timer = *it;
-				TimerAccumulator& accumulator = timer.getPrimaryAccumulator();
-				sd[timer.getName()]["Time"] = (LLSD::Real) (accumulator.mSelfTimeCounter*iclock_freq);	
-				sd[timer.getName()]["Calls"] = (LLSD::Integer) accumulator.mCalls;
-				
-				// computing total time here because getting the root timer's getCountHistory
-				// doesn't work correctly on the first frame
-				total_time = total_time + accumulator.mSelfTimeCounter * iclock_freq;
+				accumulator = cur_data->mTimerData->getPrimaryAccumulator();
 			}
-		}
 
-		sd["Total"]["Time"] = (LLSD::Real) total_time;
-		sd["Total"]["Calls"] = (LLSD::Integer) 1;
-
-		{		
-			LLMutexLock lock(sLogLock);
-			sLogQueue.push(sd);
+			cur_timer = cur_timer->mLastTimerData.mCurTimer;
 		}
-	}
-
-	// reset for next frame
-	for (LLInstanceTracker<BlockTimer>::instance_iter it = LLInstanceTracker<BlockTimer>::beginInstances(),
-			end_it = LLInstanceTracker<BlockTimer>::endInstances();
-		it != end_it;
-		++it)
-	{
-		BlockTimer& timer = *it;
-		TimerAccumulator& accumulator = timer.getPrimaryAccumulator();
-		TimerTreeNode& tree_node = sCurTimerData->mTimerTreeData[timer.getIndex()];
-
-		accumulator.mSelfTimeCounter = 0;
-		accumulator.mTotalTimeCounter = 0;
-		accumulator.mCalls = 0;
-		tree_node.mLastCaller = NULL;
-		tree_node.mMoveUpTree = false;
-	}
-}
-
-//static
-void BlockTimer::reset()
-{
-	resetFrame(); // reset frame data
-
-	// walk up stack of active timers and reset start times to current time
-	// effectively zeroing out any accumulated time
-	U64 cur_time = getCPUClockCount64();
-
-	// root defined by parent pointing to self
-	CurTimerData* cur_data = sCurTimerData.get();
-	Time* cur_timer = cur_data->mCurTimer;
-	while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
-	{
-		cur_timer->mStartTime = cur_time;
-		cur_data->mChildTime = 0;
-
-		cur_data = &cur_timer->mLastTimerData;
-		cur_timer = cur_data->mCurTimer;
-	}
 
-	// reset all history
-	{
-		for (LLInstanceTracker<BlockTimer>::instance_iter it = LLInstanceTracker<BlockTimer>::beginInstances(), 
-				end_it = LLInstanceTracker<BlockTimer>::endInstances(); 
-			it != end_it; 
-			++it)
-		{
-			BlockTimer& timer = *it;
-			if (&timer != &BlockTimer::getRootTimer()) 
-			{
-				timer.setParent(&BlockTimer::getRootTimer());
-			}
-			
-			timer.mCountAverage = 0;
-			timer.mCallAverage = 0;
-			memset(timer.mCountHistory, 0, sizeof(U64) * HISTORY_NUM);
-			memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
-		}
+		// traverse tree in DFS post order, or bottom up
+		//for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(TimeBlock::getRootTimer());
+		//	it != end_timer_tree_bottom_up();
+		//	++it)
+		//{
+		//	TimeBlock* timerp = (*it);
+		//	TimeBlockAccumulator& accumulator = timerp->getPrimaryAccumulator();
+		//	timerp->mTreeTimeCounter = accumulator.mSelfTimeCounter;
+		//	for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it)
+		//	{
+		//		timerp->mTreeTimeCounter += (*child_it)->mTreeTimeCounter;
+		//	}
+
+		//S32 cur_frame = getCurFrameIndex();
+		//if (cur_frame >= 0)
+		//{
+		//	// update timer history
+
+		//	int hidx = getCurFrameIndex() % HISTORY_NUM;
+
+		//	timerp->mCountHistory[hidx] = timerp->mTreeTimeCounter;
+		//	timerp->mCountAverage       = ((U64)timerp->mCountAverage * cur_frame + timerp->mTreeTimeCounter) / (cur_frame+1);
+		//	timerp->mCallHistory[hidx]  = accumulator.mCalls;
+		//	timerp->mCallAverage        = ((U64)timerp->mCallAverage * cur_frame + accumulator.mCalls) / (cur_frame+1);
+		//}
+		//}
 	}
-
-	sLastFrameIndex = 0;
-	sCurFrameIndex = 0;
 }
 
-U64 BlockTimer::getHistoricalCount(S32 history_index) const
-{
-	S32 history_idx = (getLastFrameIndex() + history_index) % HISTORY_NUM;
-	return mCountHistory[history_idx];
-}
-
-U32 BlockTimer::getHistoricalCalls(S32 history_index ) const
-{
-	S32 history_idx = (getLastFrameIndex() + history_index) % HISTORY_NUM;
-	return mCallHistory[history_idx];
-}
 
-std::vector<BlockTimer*>::const_iterator BlockTimer::beginChildren()
+std::vector<TimeBlock*>::const_iterator TimeBlock::beginChildren()
 { 
 	return mChildren.begin(); 
 }
 
-std::vector<BlockTimer*>::const_iterator BlockTimer::endChildren()
+std::vector<TimeBlock*>::const_iterator TimeBlock::endChildren()
 {
 	return mChildren.end();
 }
 
-std::vector<BlockTimer*>& BlockTimer::getChildren()
+std::vector<TimeBlock*>& TimeBlock::getChildren()
 {
 	return mChildren;
 }
 
 //static
-void BlockTimer::nextFrame()
+void TimeBlock::nextFrame()
 {
 	get_clock_count(); // good place to calculate clock frequency
-	U64 frame_time = BlockTimer::getCPUClockCount64();
+	U64 frame_time = TimeBlock::getCPUClockCount64();
 	if ((frame_time - sLastFrameTime) >> 8 > 0xffffffff)
 	{
 		llinfos << "Slow frame, fast timers inaccurate" << llendl;
@@ -530,31 +387,88 @@ void BlockTimer::nextFrame()
 
 	if (!sPauseHistory)
 	{
-		BlockTimer::processTimes();
+		TimeBlock::processTimes();
 		sLastFrameIndex = sCurFrameIndex++;
 	}
 	
 	// get ready for next frame
-	BlockTimer::resetFrame();
+	//void TimeBlock::resetFrame()
+	{
+		if (sLog)
+		{ //output current frame counts to performance log
+
+			static S32 call_count = 0;
+			if (call_count % 100 == 0)
+			{
+				LL_DEBUGS("FastTimers") << "countsPerSecond: " << countsPerSecond() << 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()) / (LLUnit<LLUnits::Hertz, F64>(LLProcessorInfo().getCPUFrequency())) << LL_ENDL;
+			}
+			call_count++;
+
+			LLUnit<LLUnits::Seconds, F64> total_time = 0;
+			LLSD sd;
+
+			{
+				for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), 
+					end_it = LLInstanceTracker<TimeBlock>::endInstances(); 
+					it != end_it; 
+				++it)
+				{
+					TimeBlock& timer = *it;
+					LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
+					sd[timer.getName()]["Time"] = (LLSD::Real) (frame_recording.getLastRecordingPeriod().getSum(timer).value());	
+					sd[timer.getName()]["Calls"] = (LLSD::Integer) (frame_recording.getLastRecordingPeriod().getSum(timer.callCount()));
+
+					// computing total time here because getting the root timer's getCountHistory
+					// doesn't work correctly on the first frame
+					total_time += frame_recording.getLastRecordingPeriod().getSum(timer);
+				}
+			}
+
+			sd["Total"]["Time"] = (LLSD::Real) total_time.value();
+			sd["Total"]["Calls"] = (LLSD::Integer) 1;
+
+			{		
+				LLMutexLock lock(sLogLock);
+				sLogQueue.push(sd);
+			}
+		}
+
+		// reset for next frame
+		for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(),
+			end_it = LLInstanceTracker<TimeBlock>::endInstances();
+			it != end_it;
+		++it)
+		{
+			TimeBlock& timer = *it;
+			TimeBlockTreeNode& tree_node = sCurTimerData->mTimerTreeData[timer.getIndex()];
+
+			tree_node.mLastCaller = NULL;
+			tree_node.mMoveUpTree = false;
+		}
+	}
 	sLastFrameTime = frame_time;
 }
 
 //static
-void Time::dumpCurTimes()
+void TimeBlock::dumpCurTimes()
 {
 	// accumulate timings, etc.
-	BlockTimer::processTimes();
+	processTimes();
 	
-	F64 clock_freq = (F64)get_clock_count();
-	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(BlockTimer::getRootTimer());
+	for(timer_tree_dfs_iterator_t it = begin_timer_tree(TimeBlock::getRootTimer());
 		it != end_timer_tree();
 		++it)
 	{
-		BlockTimer* timerp = (*it);
-		F64 total_time_ms = ((F64)timerp->getHistoricalCount(0) * iclock_freq);
+		LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
+		TimeBlock* timerp = (*it);
+		LLUnit<LLUnits::Seconds, F64> total_time_ms = frame_recording.getLastRecordingPeriod().getSum(*timerp);
+		U32 num_calls = frame_recording.getLastRecordingPeriod().getSum(timerp->callCount());
+
 		// Don't bother with really brief times, keep output concise
 		if (total_time_ms < 0.1) continue;
 
@@ -564,17 +478,16 @@ void Time::dumpCurTimes()
 			out_str << "\t";
 		}
 
-
 		out_str << timerp->getName() << " " 
-			<< std::setprecision(3) << total_time_ms << " ms, "
-			<< timerp->getHistoricalCalls(0) << " calls";
+			<< std::setprecision(3) << total_time_ms.as<LLUnits::Milliseconds, F32>() << " ms, "
+			<< num_calls << " calls";
 
 		llinfos << out_str.str() << llendl;
 	}
 }
 
 //static
-void Time::writeLog(std::ostream& os)
+void TimeBlock::writeLog(std::ostream& os)
 {
 	while (!sLogQueue.empty())
 	{
@@ -585,29 +498,34 @@ void Time::writeLog(std::ostream& os)
 	}
 }
 
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// TimeBlockAccumulator
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-TimerAccumulator::TimerAccumulator() :	mSelfTimeCounter(0),
+TimeBlockAccumulator::TimeBlockAccumulator() 
+:	mSelfTimeCounter(0),
 	mTotalTimeCounter(0),
 	mCalls(0)
 {}
 
-void TimerAccumulator::addSamples( const TimerAccumulator& other )
+void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
 {
 	mSelfTimeCounter += other.mSelfTimeCounter;
 	mTotalTimeCounter += other.mTotalTimeCounter;
 	mCalls += other.mCalls;
 }
 
-void TimerAccumulator::reset( const TimerAccumulator* other )
+void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
 {
 	mTotalTimeCounter = 0;
 	mSelfTimeCounter = 0;
 	mCalls = 0;
 }
 
-TimerTreeNode::TimerTreeNode()
+TimeBlockTreeNode::TimeBlockTreeNode()
 :	mLastCaller(NULL),
 	mActiveCount(0),
 	mMoveUpTree(false)
 {}
-}
+
+} // namespace LLTrace
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 9f981480f2..e3d99a9e4b 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -40,28 +40,21 @@ namespace LLTrace
 
 struct CurTimerData
 {
-	class Time*			mCurTimer;
-	class BlockTimer*	mTimerData;
+	class BlockTimer*	mCurTimer;
+	class TimeBlock*	mTimerData;
 	U64					mChildTime;
-	TimerTreeNode*		mTimerTreeData;
+	TimeBlockTreeNode*		mTimerTreeData;
 };
 
-class Time
+class BlockTimer
 {
 public:
-	friend class BlockTimer;
-	typedef Time self_t;
-	typedef class BlockTimer DeclareTimer;
+	friend class TimeBlock;
+	typedef BlockTimer self_t;
+	typedef class TimeBlock DeclareTimer;
 
-	Time(BlockTimer& timer);
-	~Time();
-
-public:
-	// dumps current cumulative frame stats to log
-	// call nextFrame() to reset timers
-	static void dumpCurTimes();
-
-	static void writeLog(std::ostream& os);
+	BlockTimer(TimeBlock& timer);
+	~BlockTimer();
 
 private:
 
@@ -69,40 +62,41 @@ private:
 	CurTimerData	mLastTimerData;
 };
 
-// stores a "named" timer instance to be reused via multiple Time stack instances
-class BlockTimer 
-:	public TraceType<TimerAccumulator>,
-	public LLInstanceTracker<BlockTimer>
+// stores a "named" timer instance to be reused via multiple BlockTimer stack instances
+class TimeBlock 
+:	public TraceType<TimeBlockAccumulator>,
+	public LLInstanceTracker<TimeBlock>
 {
 public:
-	BlockTimer(const char* name, bool open = false, BlockTimer* parent = &getRootTimer());
-	~BlockTimer();
+	TimeBlock(const char* name, bool open = false, TimeBlock* parent = &getRootTimer());
 
 	enum { HISTORY_NUM = 300 };
 
-	BlockTimer* getParent() const { return mParent; }
-	void setParent(BlockTimer* parent);
+	TimeBlock* getParent() const { return mParent; }
+	void setParent(TimeBlock* parent);
 	S32 getDepth();
 
-	typedef std::vector<BlockTimer*>::const_iterator child_const_iter;
+	typedef std::vector<TimeBlock*>::const_iterator child_const_iter;
 	child_const_iter beginChildren();
 	child_const_iter endChildren();
-	std::vector<BlockTimer*>& getChildren();
+	std::vector<TimeBlock*>& getChildren();
 
 	void setCollapsed(bool collapsed)	{ mCollapsed = collapsed; }
 	bool getCollapsed() const			{ return mCollapsed; }
 
-	U32 getCountAverage() const { return mCountAverage; }
-	U32 getCallAverage() const	{ return mCallAverage; }
-
-	U64 getHistoricalCount(S32 history_index = 0) const;
-	U32 getHistoricalCalls(S32 history_index = 0) const;
+	TraceType<TimeBlockAccumulator::CallCountAspect>& callCount() 
+	{ 
+		return static_cast<TraceType<TimeBlockAccumulator::CallCountAspect>&>(*(TraceType<TimeBlockAccumulator>*)this);
+	}
 
-	static BlockTimer& getRootTimer();
+	static TimeBlock& getRootTimer();
 	static void pushLog(LLSD sd);
 	static void setLogLock(LLMutex* mutex);
-	friend class Time;
+	static void writeLog(std::ostream& os);
 
+	// dumps current cumulative frame stats to log
+	// call nextFrame() to reset timers
+	static void dumpCurTimes();
 
 	//////////////////////////////////////////////////////////////////////////////
 	//
@@ -126,14 +120,14 @@ public:
 	//#undef _interlockedbittestandset
 	//#undef _interlockedbittestandreset
 
-	//inline U32 BlockTimer::getCPUClockCount32()
+	//inline U32 TimeBlock::getCPUClockCount32()
 	//{
 	//	U64 time_stamp = __rdtsc();
 	//	return (U32)(time_stamp >> 8);
 	//}
 	//
 	//// return full timer value, *not* shifted by 8 bits
-	//inline U64 BlockTimer::getCPUClockCount64()
+	//inline U64 TimeBlock::getCPUClockCount64()
 	//{
 	//	return __rdtsc();
 	//}
@@ -242,35 +236,16 @@ public:
 
 	static U64 countsPerSecond();
 
-	// recursive call to gather total time from children
-	static void accumulateTimings();
-
 	// updates cumulative times and hierarchy,
 	// can be called multiple times in a frame, at any point
 	static void processTimes();
 
-	static void buildHierarchy();
-	static void resetFrame();
-	static void reset();
 	// call this once a frame to reset timers
 	static void nextFrame();
-	static S32 getLastFrameIndex() { return sLastFrameIndex; }
-	static S32 getCurFrameIndex() { return sCurFrameIndex; }
-
-
-
-	// sum of recorded self time and tree time of all children timers (might not match actual recorded time of children if topology is incomplete
-	U64 						mTreeTimeCounter; 
-
-	U64 						mCountAverage;
-	U32							mCallAverage;
-
-	U64*						mCountHistory;
-	U32*						mCallHistory;
 
-	// tree structure
-	BlockTimer*					mParent;				// BlockTimer of caller(parent)
-	std::vector<BlockTimer*>	mChildren;
+	// tree structure, only updated from master trace thread
+	TimeBlock*					mParent;				// TimeBlock of caller(parent)
+	std::vector<TimeBlock*>	mChildren;
 	bool						mCollapsed,				// don't show children
 								mNeedsSorting;			// sort children whenever child added
 
@@ -288,13 +263,13 @@ public:
 
 };
 
-LL_FORCE_INLINE Time::Time(BlockTimer& timer)
+LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 {
 #if FAST_TIMER_ON
-	mStartTime = BlockTimer::getCPUClockCount64();
+	mStartTime = TimeBlock::getCPUClockCount64();
 
-	CurTimerData* cur_timer_data = BlockTimer::sCurTimerData.get();
-	TimerTreeNode& tree_node = cur_timer_data->mTimerTreeData[timer.getIndex()];
+	CurTimerData* cur_timer_data = TimeBlock::sCurTimerData.get();
+	TimeBlockTreeNode& tree_node = cur_timer_data->mTimerTreeData[timer.getIndex()];
 	tree_node.mActiveCount++;
 	// keep current parent as long as it is active when we are
 	tree_node.mMoveUpTree |= (cur_timer_data->mTimerTreeData[timer.mParent->getIndex()].mActiveCount == 0);
@@ -308,13 +283,13 @@ LL_FORCE_INLINE Time::Time(BlockTimer& timer)
 #endif
 }
 
-LL_FORCE_INLINE Time::~Time()
+LL_FORCE_INLINE BlockTimer::~BlockTimer()
 {
 #if FAST_TIMER_ON
-	U64 total_time = BlockTimer::getCPUClockCount64() - mStartTime;
-	CurTimerData* cur_timer_data = BlockTimer::sCurTimerData.get();
-	TimerAccumulator& accumulator = cur_timer_data->mTimerData->getPrimaryAccumulator();
-	TimerTreeNode& tree_node = cur_timer_data->mTimerTreeData[cur_timer_data->mTimerData->getIndex()];
+	U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
+	CurTimerData* cur_timer_data = TimeBlock::sCurTimerData.get();
+	TimeBlockAccumulator& accumulator = cur_timer_data->mTimerData->getPrimaryAccumulator();
+	TimeBlockTreeNode& tree_node = cur_timer_data->mTimerTreeData[cur_timer_data->mTimerData->getIndex()];
 
 	accumulator.mCalls++;
 	accumulator.mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
@@ -328,12 +303,12 @@ LL_FORCE_INLINE Time::~Time()
 	// we are only tracking self time, so subtract our total time delta from parents
 	mLastTimerData.mChildTime += total_time;
 
-	*BlockTimer::sCurTimerData = mLastTimerData;
+	*TimeBlock::sCurTimerData = mLastTimerData;
 #endif
 }
 
 }
 
-typedef LLTrace::Time LLFastTimer; 
+typedef LLTrace::BlockTimer LLFastTimer; 
 
 #endif // LL_LLFASTTIMER_H
diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp
index 43d98be47b..aaacbfb599 100644
--- a/indra/llcommon/llmetricperformancetester.cpp
+++ b/indra/llcommon/llmetricperformancetester.cpp
@@ -91,7 +91,7 @@ LLMetricPerformanceTesterBasic* LLMetricPerformanceTesterBasic::getTester(std::s
 // Return TRUE if this metric is requested or if the general default "catch all" metric is requested
 BOOL LLMetricPerformanceTesterBasic::isMetricLogRequested(std::string name)
 {
-	return (LLTrace::BlockTimer::sMetricLog && ((LLTrace::BlockTimer::sLogName == name) || (LLTrace::BlockTimer::sLogName == DEFAULT_METRIC_NAME)));
+	return (LLTrace::TimeBlock::sMetricLog && ((LLTrace::TimeBlock::sLogName == name) || (LLTrace::TimeBlock::sLogName == DEFAULT_METRIC_NAME)));
 }
 
 /*static*/ 
@@ -194,7 +194,7 @@ void LLMetricPerformanceTesterBasic::preOutputTestResults(LLSD* sd)
 
 void LLMetricPerformanceTesterBasic::postOutputTestResults(LLSD* sd)
 {
-	LLTrace::BlockTimer::pushLog(*sd);
+	LLTrace::TimeBlock::pushLog(*sd);
 }
 
 void LLMetricPerformanceTesterBasic::outputTestResults() 
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 3e43a85e80..9e275da647 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -37,7 +37,7 @@
 
 #include <list>
 
-#define LL_RECORD_BLOCK_TIME(block_timer) LLTrace::BlockTimer::Recorder LL_GLUE_TOKENS(block_time_recorder, __COUNTER__)(block_timer);
+#define LL_RECORD_BLOCK_TIME(block_timer) LLTrace::TimeBlock::Recorder LL_GLUE_TOKENS(block_time_recorder, __COUNTER__)(block_timer);
 
 namespace LLTrace
 {
@@ -213,10 +213,10 @@ namespace LLTrace
 	:	 public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
 	{
 	public:
-		TraceType(const char* name, const char* description = NULL)
+		TraceType(const char* name, const char* description = "")
 		:	LLInstanceTracker(name),
 			mName(name),
-			mDescription(description ? description : "")
+			mDescription(description)	
 		{
 			mAccumulatorIndex = AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer().reserveSlot();
 		}
@@ -392,26 +392,43 @@ namespace LLTrace
 		U32	mNumSamples;
 	};
 
-	class TimerAccumulator
+	class TimeBlockAccumulator
 	{
 	public:
-		TimerAccumulator();
-		void addSamples(const TimerAccumulator& other);
-		void reset(const TimerAccumulator* other);
+		typedef LLUnit<LLUnits::Seconds, F64> value_t;
+
+		// fake class that allows us to view call count aspect of timeblock accumulator
+		struct CallCountAspect 
+		{
+			typedef U32 value_t;
+		};
+
+		TimeBlockAccumulator();
+		void addSamples(const TimeBlockAccumulator& other);
+		void reset(const TimeBlockAccumulator* other);
 
 		//
 		// members
 		//
 		U64 						mSelfTimeCounter,
 									mTotalTimeCounter;
-		U32 						mCalls;
+		U32 mCalls;
+	};
+
+	template<>
+	class TraceType<TimeBlockAccumulator::CallCountAspect>
+	:	public TraceType<TimeBlockAccumulator>
+	{
+		TraceType(const char* name, const char* description = "")
+		:	TraceType<TimeBlockAccumulator>(name, description)
+		{}
 	};
 
-	class TimerTreeNode
+	class TimeBlockTreeNode
 	{
 	public:
-		TimerTreeNode();
-		class BlockTimer*			mLastCaller;	// used to bootstrap tree construction
+		TimeBlockTreeNode();
+		class TimeBlock*			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
 	};
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index ff3ae1e553..0d4d07faf6 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -44,7 +44,7 @@ Recording::Recording()
 	mMeasurementsFloat(new AccumulatorBuffer<MeasurementAccumulator<F64> >()),
 	mCounts(new AccumulatorBuffer<CountAccumulator<S64> >()),
 	mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<S64> >()),
-	mStackTimers(new AccumulatorBuffer<TimerAccumulator>())
+	mStackTimers(new AccumulatorBuffer<TimeBlockAccumulator>())
 {}
 
 Recording::Recording( const Recording& other )
@@ -143,16 +143,27 @@ void Recording::appendRecording( const Recording& other )
 	mElapsedSeconds += other.mElapsedSeconds;
 }
 
-LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimerAccumulator>& stat) const
+LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) const
 {
-	return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / (F64)LLTrace::BlockTimer::countsPerSecond();
+	return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
-LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimerAccumulator>& stat) const
+U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const
 {
-	return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / ((F64)LLTrace::BlockTimer::countsPerSecond() * mElapsedSeconds);
+	return (*mStackTimers)[stat.getIndex()].mCalls;
 }
 
+LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat) const
+{
+	return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
+}
+
+F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const
+{
+	return (F32)(*mStackTimers)[stat.getIndex()].mCalls / mElapsedSeconds;
+}
+
+
 F64 Recording::getSum( const TraceType<CountAccumulator<F64> >& stat ) const
 {
 	return (*mCountsFloat)[stat.getIndex()].getSum();
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 0adea2663b..efed3f662e 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -119,8 +119,10 @@ namespace LLTrace
 		void update();
 
 		// Timer accessors
-		LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimerAccumulator>& stat) const;
-		LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimerAccumulator>& stat) const;
+		LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator>& stat) const;
+		U32 getSum(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const;
+		LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimeBlockAccumulator>& stat) const;
+		F32 getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const;
 
 		// Count accessors
 		F64 getSum(const TraceType<CountAccumulator<F64> >& stat) const;
@@ -221,7 +223,7 @@ namespace LLTrace
 		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > >	mMeasurementsFloat;
 		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<S64> > >		mCounts;
 		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<S64> > >	mMeasurements;
-		LLCopyOnWritePointer<AccumulatorBuffer<TimerAccumulator> >				mStackTimers;
+		LLCopyOnWritePointer<AccumulatorBuffer<TimeBlockAccumulator> >				mStackTimers;
 
 		LLTimer			mSamplingTimer;
 		F64				mElapsedSeconds;
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 0a2d79cf3a..16235473ee 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -42,14 +42,14 @@ ThreadRecorder::ThreadRecorder()
 	mFullRecording.start();
 
 	mRootTimerData = new CurTimerData();
-	mRootTimerData->mTimerData = &BlockTimer::getRootTimer();
-	mRootTimerData->mTimerTreeData = new TimerTreeNode[AccumulatorBuffer<TimerAccumulator>::getDefaultBuffer().size()];
-	BlockTimer::sCurTimerData = mRootTimerData;
+	mRootTimerData->mTimerData = &TimeBlock::getRootTimer();
+	mRootTimerData->mTimerTreeData = new TimeBlockTreeNode[AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer().size()];
+	TimeBlock::sCurTimerData = mRootTimerData;
 
-	mRootTimer = new Time(BlockTimer::getRootTimer());
+	mRootTimer = new BlockTimer(TimeBlock::getRootTimer());
 	mRootTimerData->mCurTimer = mRootTimer;
 
-	mRootTimerData->mTimerTreeData[BlockTimer::getRootTimer().getIndex()].mActiveCount = 1;
+	mRootTimerData->mTimerTreeData[TimeBlock::getRootTimer().getIndex()].mActiveCount = 1;
 }
 
 ThreadRecorder::~ThreadRecorder()
@@ -61,7 +61,7 @@ ThreadRecorder::~ThreadRecorder()
 		mActiveRecordings.front().mTargetRecording->stop();
 	}
 	get_thread_recorder() = NULL;
-	BlockTimer::sCurTimerData = NULL;
+	TimeBlock::sCurTimerData = NULL;
 	delete [] mRootTimerData->mTimerTreeData;
 	delete mRootTimerData;
 }
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 277a468a40..102b980e44 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -64,7 +64,7 @@ namespace LLTrace
 		std::list<ActiveRecording>	mActiveRecordings;
 
 		struct CurTimerData*	mRootTimerData;
-		class Time*				mRootTimer;
+		class BlockTimer*				mRootTimer;
 	};
 
 	class LL_COMMON_API MasterThreadRecorder : public ThreadRecorder
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 54902b6322..01e9eb751d 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -180,23 +180,23 @@ struct LLUnitStrict : public LLUnit<UNIT_TYPE, STORAGE_TYPE>
 	typedef typename LLUnit<UNIT_TYPE, STORAGE_TYPE>::storage_t storage_t;
 
 	explicit LLUnitStrict(storage_t value = storage_t())
-	:	LLUnit(value)
+	:	LLUnit<UNIT_TYPE, STORAGE_TYPE>(value)
 	{}
 
 	template<typename OTHER_UNIT, typename OTHER_STORAGE>
 	LLUnitStrict(LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
-	:	LLUnit(convert(other))
+	:	LLUnit<UNIT_TYPE, STORAGE_TYPE>(convert(other))
 	{}
 
 	LLUnitStrict(self_t& other)
-	:	LLUnit(other)
+	:	LLUnit<UNIT_TYPE, STORAGE_TYPE>(other)
 	{}
 
 
 private:
 	operator storage_t() const
 	{
-		return value();
+		return LLUnit<UNIT_TYPE, STORAGE_TYPE>::value();
 	}
 };
 
-- 
cgit v1.2.3


From 6c7825107f6ebb3dd8697a52aeb5d29a93060dc4 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 4 Dec 2012 19:10:02 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system added copy
 constructor to periodic recording to allow snapshot generation in fast timer
 view fixed build errors

---
 indra/llcommon/lltrace.h            |  4 ++--
 indra/llcommon/lltracerecording.cpp | 14 ++++++++++++++
 indra/llcommon/lltracerecording.h   |  3 +++
 3 files changed, 19 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 9e275da647..a6b1b227c9 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -213,10 +213,10 @@ namespace LLTrace
 	:	 public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
 	{
 	public:
-		TraceType(const char* name, const char* description = "")
+		TraceType(const char* name, const char* description = NULL)
 		:	LLInstanceTracker(name),
 			mName(name),
-			mDescription(description)	
+			mDescription(description ? description : "")	
 		{
 			mAccumulatorIndex = AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer().reserveSlot();
 		}
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 0d4d07faf6..7ed7e57570 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -305,6 +305,20 @@ PeriodicRecording::PeriodicRecording( S32 num_periods, EStopWatchState state)
 	initTo(state);
 }
 
+PeriodicRecording::PeriodicRecording(PeriodicRecording& other)
+:	mNumPeriods(other.mNumPeriods),
+	mCurPeriod(other.mCurPeriod),
+	mTotalValid(other.mTotalValid),
+	mTotalRecording(other.mTotalRecording)
+{
+	mRecordingPeriods = new Recording[mNumPeriods];
+	for (S32 i = 0; i < mNumPeriods; i++)
+	{
+		mRecordingPeriods[i] = other.mRecordingPeriods[i];
+	}
+}
+
+
 PeriodicRecording::~PeriodicRecording()
 {
 	delete[] mRecordingPeriods;
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index efed3f662e..a3af215dd3 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -234,6 +234,7 @@ namespace LLTrace
 	{
 	public:
 		PeriodicRecording(S32 num_periods, EStopWatchState state = STOPPED);
+		PeriodicRecording(PeriodicRecording& recording);
 		~PeriodicRecording();
 
 		void nextPeriod();
@@ -261,11 +262,13 @@ namespace LLTrace
 
 		Recording& getPrevRecordingPeriod(S32 offset)
 		{
+			offset = llclamp(offset, 0, mNumPeriods - 1);
 			return mRecordingPeriods[(mCurPeriod + mNumPeriods - offset) % mNumPeriods];
 		}
 
 		const Recording& getPrevRecordingPeriod(S32 offset) const
 		{
+			offset = llclamp(offset, 0, mNumPeriods - 1);
 			return mRecordingPeriods[(mCurPeriod + mNumPeriods - offset) % mNumPeriods];
 		}
 
-- 
cgit v1.2.3


From 68967e7b2b9416ff66cb49ae755fb33d7b81d129 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 5 Dec 2012 14:22:18 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system changed thread id
 declaration to be local to llthread.cpp and use currentID() uniformly across
 platforms

---
 indra/llcommon/llmutex.cpp  |  8 --------
 indra/llcommon/llthread.cpp | 10 ++++++++--
 indra/llcommon/llthread.h   |  7 -------
 3 files changed, 8 insertions(+), 17 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llmutex.cpp b/indra/llcommon/llmutex.cpp
index e6beb9e680..b685bb4d60 100644
--- a/indra/llcommon/llmutex.cpp
+++ b/indra/llcommon/llmutex.cpp
@@ -83,11 +83,7 @@ void LLMutex::lock()
 	mIsLocked[id] = TRUE;
 #endif
 
-#if LL_DARWIN
 	mLockingThread = LLThread::currentID();
-#else
-	mLockingThread = LLThread::sThreadID;
-#endif
 }
 
 void LLMutex::unlock()
@@ -126,11 +122,7 @@ bool LLMutex::isLocked()
 
 bool LLMutex::isSelfLocked()
 {
-#if LL_DARWIN
 	return mLockingThread == LLThread::currentID();
-#else
-	return mLockingThread == LLThread::sThreadID;
-#endif
 }
 
 U32 LLMutex::lockingThread() const
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 8ce739bf23..6374b5398b 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -62,9 +62,9 @@
 #if LL_DARWIN
 // statically allocated thread local storage not supported in Darwin executable formats
 #elif LL_WINDOWS
-U32 __declspec(thread) LLThread::sThreadID = 0;
+U32 __declspec(thread) sThreadID = 0;
 #elif LL_LINUX
-U32 __thread LLThread::sThreadID = 0;
+U32 __thread sThreadID = 0;
 #endif 
 
 U32 LLThread::sIDIter = 0;
@@ -294,7 +294,13 @@ void LLThread::setQuitting()
 // static
 U32 LLThread::currentID()
 {
+#if LL_DARWIN
+	// statically allocated thread local storage not supported in Darwin executable formats
 	return (U32)apr_os_thread_current();
+#else
+	return sThreadID;
+#endif
+
 }
 
 // static
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 75222c83f9..92323f5fda 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -39,13 +39,6 @@ class LL_COMMON_API LLThread
 private:
 	friend class LLMutex;
 	static U32 sIDIter;
-#if LL_DARWIN
-	// statically allocated thread local storage not supported in Darwin executable formats
-#elif LL_WINDOWS
-	static U32 __declspec(thread) LLThread::sThreadID;
-#elif LL_LINUX
-	static U32 __thread LLThread::sThreadID ;
-#endif
 
 public:
 	typedef enum e_thread_status
-- 
cgit v1.2.3


From 60800dacdd7e9b66ed654af471f2b9e9680cd981 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 6 Dec 2012 00:37:15 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system fixed gcc compile
 error made LLCopyOnWritePointer contain an LLPointer, not derive from it
 added type trait to control periodicrecording mean value type

---
 indra/llcommon/llpointer.h          | 50 ++++++++++++++++++-------------------
 indra/llcommon/lltrace.h            | 22 +++++++++++++---
 indra/llcommon/lltracerecording.cpp |  2 +-
 indra/llcommon/lltracerecording.h   | 16 +++++-------
 4 files changed, 51 insertions(+), 39 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index 6a3bbeb768..f03551045e 100644
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -166,52 +166,52 @@ protected:
 };
 
 template<typename Type>
-class LLCopyOnWritePointer : public LLPointer<Type>
+class LLCopyOnWritePointer
 {
 public:
-	typedef LLPointer<Type> ref_pointer_t;
 	typedef LLCopyOnWritePointer<Type> self_t;
 
 	LLCopyOnWritePointer() 
-	{
-	}
+	{}
 
 	LLCopyOnWritePointer(Type* ptr) 
-	:	LLPointer(ptr)
-	{
-	}
+	:	mPointer(ptr)
+	{}
+
+	LLCopyOnWritePointer(LLPointer<Type>& ptr)
+	:	mPointer(ptr)
+	{}
 
 	Type* write()
 	{
 		makeUnique();
-		return mPointer;
+		return mPointer.get();
 	}
 
 	void makeUnique()
 	{
-		if (mPointer && mPointer->getNumRefs() > 1)
+		if (mPointer.notNull() && mPointer.get()->getNumRefs() > 1)
 		{
-			ref_pointer_t::assign(new Type(*mPointer));
+			mPointer = new Type(*mPointer.get());
 		}
 	}
 
-	using ref_pointer_t::operator BOOL;
-	using ref_pointer_t::operator bool;
-	using ref_pointer_t::operator!;
-
-	using ref_pointer_t::operator !=;
-	using ref_pointer_t::operator ==;
-	using LLPointer<Type>::operator =;
+	operator BOOL()  const						{ return (BOOL)mPointer; }
+	operator bool()  const						{ return (bool)mPointer; }
+	bool operator!() const						{ return !mPointer; }
+	bool isNull() const							{ return mPointer.isNull(); }
+	bool notNull() const						{ return mPointer.notNull(); }
 
-	using LLPointer<Type>::operator <;
-	using LLPointer<Type>::operator >;
-
-
-	operator Type*()							{ return mPointer; }
-	operator const Type*()   const				{ return mPointer; }
-	Type*	operator->()						{ return mPointer; }
-	const Type*	operator->() const				{ return mPointer; }
+	bool operator !=(Type* ptr) const           { return (mPointer.get() != ptr); 	}
+	bool operator ==(Type* ptr) const           { return (mPointer.get() == ptr); 	}
+	bool operator ==(const LLCopyOnWritePointer<Type>& ptr) const     { return (mPointer == ptr.mPointer); 	}
+	bool operator < (const LLCopyOnWritePointer<Type>& ptr) const     { return (mPointer < ptr.mPointer); 	}
+	bool operator > (const LLCopyOnWritePointer<Type>& ptr) const     { return (mPointer > ptr.mPointer); 	}
 
+	operator const Type*()   const				{ return mPointer.get(); }
+	const Type*	operator->() const				{ return mPointer.get(); }
+protected:
+	 LLPointer<Type> mPointer;
 };
 
 #endif
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index a6b1b227c9..6e6bb51e47 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -201,18 +201,27 @@ namespace LLTrace
 		}
 
 	private:
-		ACCUMULATOR*							mStorage;
-		size_t									mStorageSize;
-		size_t									mNextStorageSlot;
+		ACCUMULATOR*								mStorage;
+		size_t										mStorageSize;
+		size_t										mNextStorageSlot;
 		static LLThreadLocalPointer<ACCUMULATOR>	sPrimaryStorage;
 	};
 	template<typename ACCUMULATOR> LLThreadLocalPointer<ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>::sPrimaryStorage;
 
+	//TODO: replace with decltype when C++11 is enabled
+	template<typename T>
+	struct MeanValueType
+	{
+		typedef F64 type;
+	};
+
 	template<typename ACCUMULATOR>
 	class TraceType 
 	:	 public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
 	{
 	public:
+		typedef typename MeanValueType<TraceType<ACCUMULATOR> >::type  mean_t;
+
 		TraceType(const char* name, const char* description = NULL)
 		:	LLInstanceTracker(name),
 			mName(name),
@@ -415,6 +424,13 @@ namespace LLTrace
 		U32 mCalls;
 	};
 
+
+	template<>
+	struct MeanValueType<TraceType<TimeBlockAccumulator> >
+	{
+		typedef LLUnit<LLUnits::Seconds, F64> type;
+	};
+
 	template<>
 	class TraceType<TimeBlockAccumulator::CallCountAspect>
 	:	public TraceType<TimeBlockAccumulator>
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 7ed7e57570..e9b3376dae 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -49,7 +49,7 @@ Recording::Recording()
 
 Recording::Recording( const Recording& other )
 {
-	llassert(other.mCountsFloat.get() != NULL);
+	llassert(other.mCountsFloat.notNull());
 	mSamplingTimer     = other.mSamplingTimer;
 	mElapsedSeconds    = other.mElapsedSeconds;
 	mCountsFloat       = other.mCountsFloat;
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index a3af215dd3..6fd1a105d3 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -326,36 +326,32 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		F64 getPeriodMean(const TraceType<T>& stat) const
+		typename TraceType<T>::mean_t getPeriodMean(const TraceType<T>& stat) const
 		{
-			F64 mean = 0.0;
-			F64 count = 0;
+			typename TraceType<T>::mean_t mean = 0.0;
 			for (S32 i = 0; i < mNumPeriods; i++)
 			{
 				if (mRecordingPeriods[i].getDuration() > 0.f)
 				{
-					count++;
 					mean += mRecordingPeriods[i].getSum(stat);
 				}
 			}
-			mean /= (F64)mNumPeriods;
+			mean /= mNumPeriods;
 			return mean;
 		}
 
 		template <typename T>
-		F64 getPeriodMeanPerSec(const TraceType<T>& stat) const
+		typename TraceType<T>::mean_t getPeriodMeanPerSec(const TraceType<T>& stat) const
 		{
-			F64 mean = 0.0;
-			F64 count = 0;
+			typename TraceType<T>::mean_t mean = 0.0;
 			for (S32 i = 0; i < mNumPeriods; i++)
 			{
 				if (mRecordingPeriods[i].getDuration() > 0.f)
 				{
-					count++;
 					mean += mRecordingPeriods[i].getPerSec(stat);
 				}
 			}
-			mean /= count;
+			mean /= mNumPeriods;
 			return mean;
 		}
 
-- 
cgit v1.2.3


From 2facd6374517d88f03e3f06b1ccc02565da26b45 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 6 Dec 2012 14:30:56 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system improved LLUnit
 compile time errors removed cassert in favor of llstatic_assert

---
 indra/llcommon/llevents.cpp | 1 -
 indra/llcommon/llmd5.cpp    | 1 -
 indra/llcommon/llskipmap.h  | 6 ++----
 indra/llcommon/llunit.h     | 7 ++++---
 4 files changed, 6 insertions(+), 9 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
index 0855180dcd..1c928b3db8 100644
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -41,7 +41,6 @@
 #include <algorithm>
 // std headers
 #include <typeinfo>
-#include <cassert>
 #include <cmath>
 #include <cctype>
 // external library headers
diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp
index 1409c55d1c..ed80af36d8 100644
--- a/indra/llcommon/llmd5.cpp
+++ b/indra/llcommon/llmd5.cpp
@@ -76,7 +76,6 @@ documentation and/or software.
 
 #include "llmd5.h"
 
-#include <cassert>
 #include <iostream>		// cerr
 
 // how many bytes to grab at a time when checking files
diff --git a/indra/llcommon/llskipmap.h b/indra/llcommon/llskipmap.h
index 49ff2928d1..ed53973baa 100644
--- a/indra/llcommon/llskipmap.h
+++ b/indra/llcommon/llskipmap.h
@@ -210,8 +210,7 @@ inline LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::LLSkipMap()
 	:	mInsertFirst(NULL),
 		mEquals(defaultEquals)
 {
-	// Skipmaps must have binary depth of at least 2
-	cassert(BINARY_DEPTH >= 2);
+	llstatic_assert(BINARY_DEPTH >= 2, "Skipmaps must have binary depth of at least 2");
 
 	S32 i;
 	for (i = 0; i < BINARY_DEPTH; i++)
@@ -229,8 +228,7 @@ inline LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::LLSkipMap(BOOL	(*insert_f
 	:	mInsertFirst(insert_first),
 		mEquals(equals)
 {
-	// Skipmaps must have binary depth of at least 2
-	cassert(BINARY_DEPTH >= 2);
+	llstatic_assert(BINARY_DEPTH >= 2, "Skipmaps must have binary depth of at least 2");
 
 	mLevel = 1;
 	S32 i;
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 01e9eb751d..e57974c429 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -271,10 +271,11 @@ LLUnit<UNIT_TYPE, STORAGE_TYPE> operator * (LLUnit<UNIT_TYPE, STORAGE_TYPE> firs
 }
 
 template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2>
-void operator * (LLUnit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnit<UNIT_TYPE2, STORAGE_TYPE2>)
+LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator * (LLUnit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnit<UNIT_TYPE2, STORAGE_TYPE2>)
 {
 	// 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.");
+	return LLUnit<UNIT_TYPE1, STORAGE_TYPE1>();
 }
 
 //
@@ -293,10 +294,10 @@ LLUnit<UNIT_TYPE, STORAGE_TYPE> operator / (LLUnit<UNIT_TYPE, STORAGE_TYPE> firs
 }
 
 template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2>
-void operator / (LLUnit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnit<UNIT_TYPE2, STORAGE_TYPE2>)
+STORAGE_TYPE1 operator / (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second)
 {
 	// 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.");
+	return STORAGE_TYPE1(first.value() / second.value());
 }
 
 #define COMPARISON_OPERATORS(op)                                                                     \
-- 
cgit v1.2.3


From 3745d1254acc386acaadd20016123c9a47b8d10c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 6 Dec 2012 17:24:41 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system added unit tests
 for LLUnit

---
 indra/llcommon/CMakeLists.txt        |   1 +
 indra/llcommon/llunit.h              |  40 ++++-----
 indra/llcommon/tests/llunit_test.cpp | 156 +++++++++++++++++++++++++++++++++++
 3 files changed, 177 insertions(+), 20 deletions(-)
 create mode 100644 indra/llcommon/tests/llunit_test.cpp

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 0f5ded86ed..e1f2eb44fd 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -342,6 +342,7 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(llunit "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}")
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index e57974c429..1f3ed0237c 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -334,7 +334,7 @@ struct HighestPrecisionType<LLUnit<UNIT_TYPE, STORAGE_TYPE> >
 	typedef typename HighestPrecisionType<STORAGE_TYPE>::type_t type_t;
 };
 
-#define LL_DECLARE_DERIVED_UNIT(base_unit_name, unit_name, conversion_factor)                   \
+#define LL_DECLARE_DERIVED_UNIT(conversion_factor, base_unit_name, unit_name)                   \
 struct unit_name                                                                                \
 {                                                                                               \
 	typedef base_unit_name base_unit_t;                                                         \
@@ -358,30 +358,30 @@ struct ConversionFactor<base_unit_name, unit_name, STORAGE_TYPE>						        \
 }
 
 struct Bytes { typedef Bytes base_unit_t; };
-LL_DECLARE_DERIVED_UNIT(Bytes, Kilobytes, 1024);
-LL_DECLARE_DERIVED_UNIT(Bytes, Megabytes, 1024 * 1024);
-LL_DECLARE_DERIVED_UNIT(Bytes, Gigabytes, 1024 * 1024 * 1024);
-LL_DECLARE_DERIVED_UNIT(Bytes, Bits,	  (1.0 / 8.0));
-LL_DECLARE_DERIVED_UNIT(Bytes, Kilobits,  (1024 / 8));
-LL_DECLARE_DERIVED_UNIT(Bytes, Megabits,  (1024 / 8));
-LL_DECLARE_DERIVED_UNIT(Bytes, Gigabits,  (1024 * 1024 * 1024 / 8));
+LL_DECLARE_DERIVED_UNIT(1024, Bytes, Kilobytes);
+LL_DECLARE_DERIVED_UNIT(1024 * 1024, Bytes, Megabytes);
+LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024, Bytes, Gigabytes);
+LL_DECLARE_DERIVED_UNIT((1.0 / 8.0), Bytes, Bits);
+LL_DECLARE_DERIVED_UNIT((1024 / 8), Bytes, Kilobits);
+LL_DECLARE_DERIVED_UNIT((1024 / 8), Bytes, Megabits);
+LL_DECLARE_DERIVED_UNIT((1024 * 1024 * 1024 / 8), Bytes, Gigabits);
 
 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, 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)));
+LL_DECLARE_DERIVED_UNIT(60, Seconds, Minutes);
+LL_DECLARE_DERIVED_UNIT(60 * 60, Seconds, Hours);
+LL_DECLARE_DERIVED_UNIT((1.0 / 1000.0), Seconds, Milliseconds);
+LL_DECLARE_DERIVED_UNIT((1.0 / (1000000.0)), Seconds, Microseconds);
+LL_DECLARE_DERIVED_UNIT((1.0 / (1000000000.0)), Seconds, Nanoseconds);
 
 struct Meters { typedef Meters base_unit_t; };
-LL_DECLARE_DERIVED_UNIT(Meters, Kilometers, 1000);
-LL_DECLARE_DERIVED_UNIT(Meters, Centimeters, (1.0 / 100.0));
-LL_DECLARE_DERIVED_UNIT(Meters, Millimeters, (1.0 / 1000.0));
+LL_DECLARE_DERIVED_UNIT(1000, Meters, Kilometers);
+LL_DECLARE_DERIVED_UNIT((1.0 / 100.0), Meters, Centimeters);
+LL_DECLARE_DERIVED_UNIT((1.0 / 1000.0), Meters, Millimeters);
 
 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);
-}
+LL_DECLARE_DERIVED_UNIT(1000, Hertz, Kilohertz);
+LL_DECLARE_DERIVED_UNIT(1000 * 1000, Hertz, Megahertz);
+LL_DECLARE_DERIVED_UNIT(1000 * 1000 * 1000, Hertz, Gigahertz);
+} // namespace LLUnits
 
 #endif // LL_LLUNIT_H
diff --git a/indra/llcommon/tests/llunit_test.cpp b/indra/llcommon/tests/llunit_test.cpp
new file mode 100644
index 0000000000..a7e9c00740
--- /dev/null
+++ b/indra/llcommon/tests/llunit_test.cpp
@@ -0,0 +1,156 @@
+/** 
+ * @file llsingleton_test.cpp
+ * @date 2011-08-11
+ * @brief Unit test for the LLSingleton class
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llunit.h"
+#include "../test/lltut.h"
+
+namespace LLUnits
+{
+	// using powers of 2 to allow strict floating point equality
+	struct Quatloos { typedef Quatloos base_unit_t; };
+	LL_DECLARE_DERIVED_UNIT(4, Quatloos, Latinum);
+	LL_DECLARE_DERIVED_UNIT((1.0 / 4.0), Quatloos, Solari);
+}
+
+namespace tut
+{
+	using namespace LLUnits;
+	struct units
+	{
+	};
+
+	typedef test_group<units> units_t;
+	typedef units_t::object units_object_t;
+	tut::units_t tut_singleton("LLUnit");
+
+	// storage type conversions
+	template<> template<>
+	void units_object_t::test<1>()
+	{
+		LLUnit<Quatloos, F32> float_quatloos;
+		ensure(float_quatloos.value() == 0.f);
+
+		LLUnit<Quatloos, S32> int_quatloos;
+		ensure(int_quatloos.value() == 0);
+
+		int_quatloos = 42;
+		ensure(int_quatloos.value() == 42);
+		float_quatloos = int_quatloos;
+		ensure(float_quatloos.value() == 42.f);
+
+		int_quatloos = float_quatloos;
+		ensure(int_quatloos.value() == 42);
+
+		float_quatloos = 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);
+	}
+
+	// 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);
+
+		latinum_bars = 256;
+		quatloos = latinum_bars;
+		ensure(quatloos.value() == 1024);
+
+		LLUnit<Solari, F32> solari(quatloos);
+		ensure(solari.value() == 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);
+	}
+
+	// math operations
+	template<> template<>
+	void units_object_t::test<4>()
+	{
+		LLUnit<Quatloos, F32> quatloos = 1.f;
+		quatloos *= 4.f;
+		ensure(quatloos.value() == 4);
+		quatloos = quatloos * 2;
+		ensure(quatloos.value() == 8);
+		quatloos = 2.f * quatloos;
+		ensure(quatloos.value() == 16);
+
+		quatloos += 4.f;
+		ensure(quatloos.value() == 20);
+		quatloos += 4;
+		ensure(quatloos.value() == 24);
+		quatloos = quatloos + 4;
+		ensure(quatloos.value() == 28);
+		quatloos = 4 + quatloos;
+		ensure(quatloos.value() == 32);
+		quatloos += quatloos * 3;
+		ensure(quatloos.value() == 128);
+
+		quatloos -= quatloos / 4 * 3;
+		ensure(quatloos.value() == 32);
+		quatloos = quatloos - 8;
+		ensure(quatloos.value() == 24);
+		quatloos -= 4;
+		ensure(quatloos.value() == 20);
+		quatloos -= 4.f;
+		ensure(quatloos.value() == 16);
+
+		quatloos *= 2.f;
+		ensure(quatloos.value() == 32);
+		quatloos = quatloos * 2.f;
+		ensure(quatloos.value() == 64);
+		quatloos = 0.5f * quatloos;
+		ensure(quatloos.value() == 32);
+
+		quatloos /= 2.f;
+		ensure(quatloos.value() == 16);
+		quatloos = quatloos / 4;
+		ensure(quatloos.value() == 4);
+
+		F32 ratio = quatloos / LLUnit<Quatloos, F32>(4.f);
+		ensure(ratio == 1);
+
+		quatloos += LLUnit<Solari, F32>(4.f);
+		ensure(quatloos.value() == 5);
+		quatloos -= LLUnit<Latinum, F32>(1.f);
+		ensure(quatloos.value() == 1);
+	}
+}
-- 
cgit v1.2.3


From c99886d94389babc78e92bbfa5084fdd785915af Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 7 Dec 2012 15:20:12 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system improved unit tests
 for LLUnit renamed LLUnit to LLUnitImplicit with LLUnit being reserved for
 explicit units

---
 indra/llcommon/CMakeLists.txt         |   2 +-
 indra/llcommon/llfasttimer.cpp        |   6 +-
 indra/llcommon/llleap.cpp             |   2 +-
 indra/llcommon/llprocessor.cpp        |   2 +-
 indra/llcommon/llprocessor.h          |   2 +-
 indra/llcommon/lltimer.cpp            |  14 +--
 indra/llcommon/lltimer.h              |  16 +--
 indra/llcommon/lltrace.h              |   7 +-
 indra/llcommon/lltracerecording.h     |   2 +-
 indra/llcommon/llunit.h               | 193 ++++++++++++++++++++++---------
 indra/llcommon/tests/llunit_test.cpp  | 156 -------------------------
 indra/llcommon/tests/llunits_test.cpp | 208 ++++++++++++++++++++++++++++++++++
 12 files changed, 376 insertions(+), 234 deletions(-)
 delete mode 100644 indra/llcommon/tests/llunit_test.cpp
 create mode 100644 indra/llcommon/tests/llunits_test.cpp

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index e1f2eb44fd..5b76703af7 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -342,7 +342,7 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}")
-  LL_ADD_INTEGRATION_TEST(llunit "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(llunits "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}")
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index cf7655acf7..37e0fbac0a 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -166,7 +166,7 @@ U64 TimeBlock::countsPerSecond() // counts per second for the *64-bit* timer
 		firstcall = false;
 	}
 #endif
-	return sCPUClockFrequency;
+	return sCPUClockFrequency.value();
 }
 #endif
 
@@ -408,7 +408,7 @@ void TimeBlock::nextFrame()
 			}
 			call_count++;
 
-			LLUnit<LLUnits::Seconds, F64> total_time = 0;
+			LLUnit<LLUnits::Seconds, F64> total_time(0);
 			LLSD sd;
 
 			{
@@ -479,7 +479,7 @@ void TimeBlock::dumpCurTimes()
 		}
 
 		out_str << timerp->getName() << " " 
-			<< std::setprecision(3) << total_time_ms.as<LLUnits::Milliseconds, F32>() << " ms, "
+			<< std::setprecision(3) << total_time_ms.as<LLUnits::Milliseconds, F32>().value() << " ms, "
 			<< num_calls << " calls";
 
 		llinfos << out_str.str() << llendl;
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index 0a57ef1c48..84d2a12f65 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -394,7 +394,7 @@ public:
         LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN));
         LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
         LLSD nop;
-        F64 until(LLTimer::getElapsedSeconds() + 2);
+        F64 until = (LLTimer::getElapsedSeconds() + 2).value();
         while (childin.size() && LLTimer::getElapsedSeconds() < until)
         {
             mainloop.post(nop);
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index 6fe53396ca..5ddfa6fcef 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -875,7 +875,7 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL)
 
 
 LLProcessorInfo::~LLProcessorInfo() {}
-LLUnit<LLUnits::Megahertz, F64> LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); }
+LLUnitImplicit<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 2a21a5c115..fbd427f484 100644
--- a/indra/llcommon/llprocessor.h
+++ b/indra/llcommon/llprocessor.h
@@ -37,7 +37,7 @@ public:
 	LLProcessorInfo(); 
  	~LLProcessorInfo();
 
-	LLUnit<LLUnits::Megahertz, F64> getCPUFrequency() const;
+	LLUnitImplicit<LLUnits::Megahertz, F64> getCPUFrequency() const;
 	bool hasSSE() const;
 	bool hasSSE2() const;
 	bool hasAltivec() const;
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 26063beff0..838155d54d 100644
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -285,14 +285,14 @@ LLTimer::~LLTimer()
 }
 
 // static
-LLUnit<LLUnits::Microseconds, U64> LLTimer::getTotalTime()
+LLUnitImplicit<LLUnits::Microseconds, U64> LLTimer::getTotalTime()
 {
 	// simply call into the implementation function.
 	return totalTime();
 }	
 
 // static
-LLUnit<LLUnits::Seconds, F64> LLTimer::getTotalSeconds()
+LLUnitImplicit<LLUnits::Seconds, F64> LLTimer::getTotalSeconds()
 {
 	return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64;
 }
@@ -341,23 +341,23 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount)
 }
 
 
-LLUnit<LLUnits::Seconds, F64> LLTimer::getElapsedTimeF64() const
+LLUnitImplicit<LLUnits::Seconds, F64> LLTimer::getElapsedTimeF64() const
 {
 	U64 last = mLastClockCount;
 	return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv;
 }
 
-LLUnit<LLUnits::Seconds, F32> LLTimer::getElapsedTimeF32() const
+LLUnitImplicit<LLUnits::Seconds, F32> LLTimer::getElapsedTimeF32() const
 {
 	return (F32)getElapsedTimeF64();
 }
 
-LLUnit<LLUnits::Seconds, F64> LLTimer::getElapsedTimeAndResetF64()
+LLUnitImplicit<LLUnits::Seconds, F64> LLTimer::getElapsedTimeAndResetF64()
 {
 	return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv;
 }
 
-LLUnit<LLUnits::Seconds, F32> LLTimer::getElapsedTimeAndResetF32()
+LLUnitImplicit<LLUnits::Seconds, F32> LLTimer::getElapsedTimeAndResetF32()
 {
 	return (F32)getElapsedTimeAndResetF64();
 }
@@ -370,7 +370,7 @@ void  LLTimer::setTimerExpirySec(F32 expiration)
 		+ (U64)((F32)(expiration * gClockFrequency));
 }
 
-LLUnit<LLUnits::Seconds, F32> LLTimer::getRemainingTimeF32() const
+LLUnitImplicit<LLUnits::Seconds, F32> 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 5cb2b18111..0ba87d1e15 100644
--- 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 LLUnit<LLUnits::Seconds, F64> getElapsedSeconds()
+	static LLUnitImplicit<LLUnits::Seconds, F64> getElapsedSeconds()
 	{
 		return sTimer->getElapsedTimeF64();
 	}
 
 	// Return a high precision usec since epoch
-	static LLUnit<LLUnits::Microseconds, U64> getTotalTime();
+	static LLUnitImplicit<LLUnits::Microseconds, U64> getTotalTime();
 
 	// Return a high precision seconds since epoch
-	static LLUnit<LLUnits::Seconds, F64> getTotalSeconds();
+	static LLUnitImplicit<LLUnits::Seconds, F64> getTotalSeconds();
 
 
 	// MANIPULATORS
@@ -87,16 +87,16 @@ public:
 	void setTimerExpirySec(F32 expiration);
 	BOOL checkExpirationAndReset(F32 expiration);
 	BOOL hasExpired() const;
-	LLUnit<LLUnits::Seconds, F32> getElapsedTimeAndResetF32();	// Returns elapsed time in seconds with reset
-	LLUnit<LLUnits::Seconds, F64> getElapsedTimeAndResetF64();
+	LLUnitImplicit<LLUnits::Seconds, F32> getElapsedTimeAndResetF32();	// Returns elapsed time in seconds with reset
+	LLUnitImplicit<LLUnits::Seconds, F64> getElapsedTimeAndResetF64();
 
-	LLUnit<LLUnits::Seconds, F32> getRemainingTimeF32() const;
+	LLUnitImplicit<LLUnits::Seconds, F32> getRemainingTimeF32() const;
 
 	static BOOL knownBadTimer();
 
 	// ACCESSORS
-	LLUnit<LLUnits::Seconds, F32> getElapsedTimeF32() const;			// Returns elapsed time in seconds
-	LLUnit<LLUnits::Seconds, F64> getElapsedTimeF64() const;			// Returns elapsed time in seconds
+	LLUnitImplicit<LLUnits::Seconds, F32> getElapsedTimeF32() const;			// Returns elapsed time in seconds
+	LLUnitImplicit<LLUnits::Seconds, F64> 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 6e6bb51e47..25d95d9670 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -435,6 +435,9 @@ namespace LLTrace
 	class TraceType<TimeBlockAccumulator::CallCountAspect>
 	:	public TraceType<TimeBlockAccumulator>
 	{
+	public:
+		typedef F32 mean_t;
+
 		TraceType(const char* name, const char* description = "")
 		:	TraceType<TimeBlockAccumulator>(name, description)
 		{}
@@ -465,7 +468,7 @@ namespace LLTrace
 		void sample(UNIT_T value)
 		{
 			T converted_value(value);
-			getPrimaryAccumulator().sample((storage_t)converted_value);
+			getPrimaryAccumulator().sample(LLUnits::rawValue(converted_value));
 		}
 	};
 
@@ -484,7 +487,7 @@ namespace LLTrace
 		void add(UNIT_T value)
 		{
 			T converted_value(value);
-			getPrimaryAccumulator().add((storage_t)converted_value);
+			getPrimaryAccumulator().add(LLUnits::rawValue(converted_value));
 		}
 	};
 }
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 6fd1a105d3..f92281cea8 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -205,7 +205,7 @@ namespace LLTrace
 		U32 getSampleCount(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		U32 getSampleCount(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 
-		LLUnit<LLUnits::Seconds, F64> getDuration() const { return mElapsedSeconds; }
+		LLUnit<LLUnits::Seconds, F64> getDuration() const { return LLUnit<LLUnits::Seconds, F64>(mElapsedSeconds); }
 
 	private:
 		friend class ThreadRecorder;
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 1f3ed0237c..6b023f8287 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -65,6 +65,7 @@ struct ConversionFactor<BASE_UNITS_TAG, BASE_UNITS_TAG, VALUE_TYPE>
 		return 1; 
 	}
 };
+
 }
 
 template<typename UNIT_TYPE, typename STORAGE_TYPE>
@@ -73,25 +74,25 @@ struct LLUnit
 	typedef LLUnit<UNIT_TYPE, STORAGE_TYPE> self_t;
 	typedef STORAGE_TYPE storage_t;
 
+	// value initialization
 	LLUnit(storage_t value = storage_t())
 	:	mValue(value)
 	{}
 
+	// unit initialization and conversion
 	template<typename OTHER_UNIT, typename OTHER_STORAGE>
 	LLUnit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
 	:	mValue(convert(other))
 	{}
-
-	LLUnit(self_t& other)
-	:	mValue(other.mValue)
-	{}
-
+	
+	// value assignment
 	self_t& operator = (storage_t value)
 	{
 		mValue = value;
 		return *this;
 	}
 
+	// unit assignment
 	template<typename OTHER_UNIT, typename OTHER_STORAGE>
 	self_t& operator = (LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
 	{
@@ -99,11 +100,6 @@ struct LLUnit
 		return *this;
 	}
 
-	operator storage_t() const
-	{
-		return value();
-	}
-
 	storage_t value() const
 	{
 		return mValue;
@@ -157,7 +153,7 @@ struct LLUnit
 	void operator /= (LLUnit<OTHER_UNIT, OTHER_STORAGE> divisor)
 	{
 		// 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.");
+		llstatic_assert(sizeof(OTHER_UNIT) == 0, "Illegal in-place division of unit types.");
 	}
 
 	template<typename SOURCE_UNITS, typename SOURCE_STORAGE>
@@ -169,34 +165,30 @@ struct LLUnit
 	}
 
 protected:
-
 	storage_t mValue;
 };
 
 template<typename UNIT_TYPE, typename STORAGE_TYPE>
-struct LLUnitStrict : public LLUnit<UNIT_TYPE, STORAGE_TYPE>
+struct LLUnitImplicit : public LLUnit<UNIT_TYPE, STORAGE_TYPE>
 {
-	typedef LLUnitStrict<UNIT_TYPE, STORAGE_TYPE> self_t;
+	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;
 
-	explicit LLUnitStrict(storage_t value = storage_t())
-	:	LLUnit<UNIT_TYPE, STORAGE_TYPE>(value)
+	LLUnitImplicit(storage_t value = storage_t())
+	:	base_t(value)
 	{}
 
 	template<typename OTHER_UNIT, typename OTHER_STORAGE>
-	LLUnitStrict(LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
-	:	LLUnit<UNIT_TYPE, STORAGE_TYPE>(convert(other))
+	LLUnitImplicit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
+	:	base_t(convert(other))
 	{}
 
-	LLUnitStrict(self_t& other)
-	:	LLUnit<UNIT_TYPE, STORAGE_TYPE>(other)
-	{}
-
-
-private:
+	// unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD scalar (F32, S32, etc)
+	// this allows for interoperability with legacy code
 	operator storage_t() const
 	{
-		return LLUnit<UNIT_TYPE, STORAGE_TYPE>::value();
+		return value();
 	}
 };
 
@@ -204,7 +196,7 @@ private:
 // operator +
 //
 template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2>
-LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator + (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second)
+LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second)
 {
 	LLUnit<UNIT_TYPE1, STORAGE_TYPE1> result(first);
 	result += second;
@@ -227,6 +219,30 @@ LLUnit<UNIT_TYPE, STORAGE_TYPE> operator + (SCALAR_TYPE first, LLUnit<UNIT_TYPE,
 	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)
+{
+	LLUnitImplicit<UNIT_TYPE1, STORAGE_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)
+{
+	LLUnitImplicit<UNIT_TYPE, STORAGE_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)
+{
+	LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first);
+	result += second;
+	return result;
+}
+
 //
 // operator -
 //
@@ -238,7 +254,6 @@ LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator - (LLUnit<UNIT_TYPE1, STORAGE_TYPE1>
 	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)
 {
@@ -255,6 +270,30 @@ LLUnit<UNIT_TYPE, STORAGE_TYPE> operator - (SCALAR_TYPE first, LLUnit<UNIT_TYPE,
 	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)
+{
+	LLUnitImplicit<UNIT_TYPE1, STORAGE_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)
+{
+	LLUnitImplicit<UNIT_TYPE, STORAGE_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)
+{
+	LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first);
+	result -= second;
+	return result;
+}
+
 //
 // operator *
 //
@@ -278,6 +317,26 @@ LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator * (LLUnit<UNIT_TYPE1, STORAGE_TYPE1>,
 	return LLUnit<UNIT_TYPE1, STORAGE_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)
+{
+	return LLUnitImplicit<UNIT_TYPE, STORAGE_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)
+{
+	return LLUnitImplicit<UNIT_TYPE, STORAGE_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>)
+{
+	// 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.");
+	return LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1>();
+}
+
 //
 // operator /
 //
@@ -300,23 +359,42 @@ STORAGE_TYPE1 operator / (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_T
 	return STORAGE_TYPE1(first.value() / second.value());
 }
 
-#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)                         \
-{                                                                                                    \
-	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)                         \
-{                                                                                                    \
-	return first.value() op 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) \
-{                                                                                                    \
-	return first.value() op 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)
+{
+	return LLUnitImplicit<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)
+{
+	// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+	return STORAGE_TYPE1(first.value() / second.value());
+}
+
+#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)                                         \
+{                                                                                                                    \
+	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)                                         \
+{                                                                                                                    \
+	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) \
+{                                                                                                                    \
+	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)             \
+{                                                                                                                    \
+	return first.value() op first.convert(second);                                                                   \
 }
 
 COMPARISON_OPERATORS(<)
@@ -328,6 +406,15 @@ COMPARISON_OPERATORS(!=)
 
 namespace LLUnits
 {
+template<typename T>
+T rawValue(T val) { return val; }
+
+template<typename UNIT_TYPE, typename STORAGE_TYPE> 
+STORAGE_TYPE rawValue(LLUnit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value(); }
+
+template<typename UNIT_TYPE, typename STORAGE_TYPE> 
+STORAGE_TYPE rawValue(LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value(); }
+
 template<typename UNIT_TYPE, typename STORAGE_TYPE> 
 struct HighestPrecisionType<LLUnit<UNIT_TYPE, STORAGE_TYPE> >
 {
@@ -361,22 +448,22 @@ struct Bytes { typedef Bytes base_unit_t; };
 LL_DECLARE_DERIVED_UNIT(1024, Bytes, Kilobytes);
 LL_DECLARE_DERIVED_UNIT(1024 * 1024, Bytes, Megabytes);
 LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024, Bytes, Gigabytes);
-LL_DECLARE_DERIVED_UNIT((1.0 / 8.0), Bytes, Bits);
-LL_DECLARE_DERIVED_UNIT((1024 / 8), Bytes, Kilobits);
-LL_DECLARE_DERIVED_UNIT((1024 / 8), Bytes, Megabits);
-LL_DECLARE_DERIVED_UNIT((1024 * 1024 * 1024 / 8), Bytes, Gigabits);
+LL_DECLARE_DERIVED_UNIT(1.0 / 8.0, Bytes, Bits);
+LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Kilobits);
+LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Megabits);
+LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024 / 8, Bytes, Gigabits);
 
 struct Seconds { typedef Seconds base_unit_t; };
 LL_DECLARE_DERIVED_UNIT(60, Seconds, Minutes);
 LL_DECLARE_DERIVED_UNIT(60 * 60, Seconds, Hours);
-LL_DECLARE_DERIVED_UNIT((1.0 / 1000.0), Seconds, Milliseconds);
-LL_DECLARE_DERIVED_UNIT((1.0 / (1000000.0)), Seconds, Microseconds);
-LL_DECLARE_DERIVED_UNIT((1.0 / (1000000000.0)), Seconds, Nanoseconds);
+LL_DECLARE_DERIVED_UNIT(1.0 / 1000.0, Seconds, Milliseconds);
+LL_DECLARE_DERIVED_UNIT(1.0 / 1000000.0, Seconds, Microseconds);
+LL_DECLARE_DERIVED_UNIT(1.0 / 1000000000.0, Seconds, Nanoseconds);
 
 struct Meters { typedef Meters base_unit_t; };
 LL_DECLARE_DERIVED_UNIT(1000, Meters, Kilometers);
-LL_DECLARE_DERIVED_UNIT((1.0 / 100.0), Meters, Centimeters);
-LL_DECLARE_DERIVED_UNIT((1.0 / 1000.0), Meters, Millimeters);
+LL_DECLARE_DERIVED_UNIT(1.0 / 100.0, Meters, Centimeters);
+LL_DECLARE_DERIVED_UNIT(1.0 / 1000.0, Meters, Millimeters);
 
 struct Hertz { typedef Hertz base_unit_t; };
 LL_DECLARE_DERIVED_UNIT(1000, Hertz, Kilohertz);
diff --git a/indra/llcommon/tests/llunit_test.cpp b/indra/llcommon/tests/llunit_test.cpp
deleted file mode 100644
index a7e9c00740..0000000000
--- a/indra/llcommon/tests/llunit_test.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/** 
- * @file llsingleton_test.cpp
- * @date 2011-08-11
- * @brief Unit test for the LLSingleton class
- *
- * $LicenseInfo:firstyear=2011&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llunit.h"
-#include "../test/lltut.h"
-
-namespace LLUnits
-{
-	// using powers of 2 to allow strict floating point equality
-	struct Quatloos { typedef Quatloos base_unit_t; };
-	LL_DECLARE_DERIVED_UNIT(4, Quatloos, Latinum);
-	LL_DECLARE_DERIVED_UNIT((1.0 / 4.0), Quatloos, Solari);
-}
-
-namespace tut
-{
-	using namespace LLUnits;
-	struct units
-	{
-	};
-
-	typedef test_group<units> units_t;
-	typedef units_t::object units_object_t;
-	tut::units_t tut_singleton("LLUnit");
-
-	// storage type conversions
-	template<> template<>
-	void units_object_t::test<1>()
-	{
-		LLUnit<Quatloos, F32> float_quatloos;
-		ensure(float_quatloos.value() == 0.f);
-
-		LLUnit<Quatloos, S32> int_quatloos;
-		ensure(int_quatloos.value() == 0);
-
-		int_quatloos = 42;
-		ensure(int_quatloos.value() == 42);
-		float_quatloos = int_quatloos;
-		ensure(float_quatloos.value() == 42.f);
-
-		int_quatloos = float_quatloos;
-		ensure(int_quatloos.value() == 42);
-
-		float_quatloos = 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);
-	}
-
-	// 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);
-
-		latinum_bars = 256;
-		quatloos = latinum_bars;
-		ensure(quatloos.value() == 1024);
-
-		LLUnit<Solari, F32> solari(quatloos);
-		ensure(solari.value() == 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);
-	}
-
-	// math operations
-	template<> template<>
-	void units_object_t::test<4>()
-	{
-		LLUnit<Quatloos, F32> quatloos = 1.f;
-		quatloos *= 4.f;
-		ensure(quatloos.value() == 4);
-		quatloos = quatloos * 2;
-		ensure(quatloos.value() == 8);
-		quatloos = 2.f * quatloos;
-		ensure(quatloos.value() == 16);
-
-		quatloos += 4.f;
-		ensure(quatloos.value() == 20);
-		quatloos += 4;
-		ensure(quatloos.value() == 24);
-		quatloos = quatloos + 4;
-		ensure(quatloos.value() == 28);
-		quatloos = 4 + quatloos;
-		ensure(quatloos.value() == 32);
-		quatloos += quatloos * 3;
-		ensure(quatloos.value() == 128);
-
-		quatloos -= quatloos / 4 * 3;
-		ensure(quatloos.value() == 32);
-		quatloos = quatloos - 8;
-		ensure(quatloos.value() == 24);
-		quatloos -= 4;
-		ensure(quatloos.value() == 20);
-		quatloos -= 4.f;
-		ensure(quatloos.value() == 16);
-
-		quatloos *= 2.f;
-		ensure(quatloos.value() == 32);
-		quatloos = quatloos * 2.f;
-		ensure(quatloos.value() == 64);
-		quatloos = 0.5f * quatloos;
-		ensure(quatloos.value() == 32);
-
-		quatloos /= 2.f;
-		ensure(quatloos.value() == 16);
-		quatloos = quatloos / 4;
-		ensure(quatloos.value() == 4);
-
-		F32 ratio = quatloos / LLUnit<Quatloos, F32>(4.f);
-		ensure(ratio == 1);
-
-		quatloos += LLUnit<Solari, F32>(4.f);
-		ensure(quatloos.value() == 5);
-		quatloos -= LLUnit<Latinum, F32>(1.f);
-		ensure(quatloos.value() == 1);
-	}
-}
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
new file mode 100644
index 0000000000..2a941e8229
--- /dev/null
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -0,0 +1,208 @@
+/** 
+ * @file llsingleton_test.cpp
+ * @date 2011-08-11
+ * @brief Unit test for the LLSingleton class
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llunit.h"
+#include "../test/lltut.h"
+
+namespace LLUnits
+{
+	// using powers of 2 to allow strict floating point equality
+	struct Quatloos { typedef Quatloos base_unit_t; };
+	LL_DECLARE_DERIVED_UNIT(4, Quatloos, Latinum);
+	LL_DECLARE_DERIVED_UNIT((1.0 / 4.0), Quatloos, Solari);
+}
+
+namespace tut
+{
+	using namespace LLUnits;
+	struct units
+	{
+	};
+
+	typedef test_group<units> units_t;
+	typedef units_t::object units_object_t;
+	tut::units_t tut_singleton("LLUnit");
+
+	// storage type conversions
+	template<> template<>
+	void units_object_t::test<1>()
+	{
+		LLUnit<Quatloos, F32> float_quatloos;
+		ensure(float_quatloos.value() == 0.f);
+
+		LLUnit<Quatloos, S32> int_quatloos;
+		ensure(int_quatloos.value() == 0);
+
+		int_quatloos = 42;
+		ensure(int_quatloos.value() == 42);
+		float_quatloos = int_quatloos;
+		ensure(float_quatloos.value() == 42.f);
+
+		int_quatloos = float_quatloos;
+		ensure(int_quatloos.value() == 42);
+
+		float_quatloos = 42.1f;
+		ensure(float_quatloos.value() == 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);
+	}
+
+	// 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);
+
+		latinum_bars = 256;
+		quatloos = latinum_bars;
+		ensure(quatloos.value() == 1024);
+
+		LLUnit<Solari, F32> solari(quatloos);
+		ensure(solari.value() == 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);
+	}
+
+	// math operations
+	template<> template<>
+	void units_object_t::test<4>()
+	{
+		LLUnit<Quatloos, F32> quatloos = 1.f;
+		quatloos *= 4.f;
+		ensure(quatloos.value() == 4);
+		quatloos = quatloos * 2;
+		ensure(quatloos.value() == 8);
+		quatloos = 2.f * quatloos;
+		ensure(quatloos.value() == 16);
+
+		quatloos += 4.f;
+		ensure(quatloos.value() == 20);
+		quatloos += 4;
+		ensure(quatloos.value() == 24);
+		quatloos = quatloos + 4;
+		ensure(quatloos.value() == 28);
+		quatloos = 4 + quatloos;
+		ensure(quatloos.value() == 32);
+		quatloos += quatloos * 3;
+		ensure(quatloos.value() == 128);
+
+		quatloos -= quatloos / 4 * 3;
+		ensure(quatloos.value() == 32);
+		quatloos = quatloos - 8;
+		ensure(quatloos.value() == 24);
+		quatloos -= 4;
+		ensure(quatloos.value() == 20);
+		quatloos -= 4.f;
+		ensure(quatloos.value() == 16);
+
+		quatloos *= 2.f;
+		ensure(quatloos.value() == 32);
+		quatloos = quatloos * 2.f;
+		ensure(quatloos.value() == 64);
+		quatloos = 0.5f * quatloos;
+		ensure(quatloos.value() == 32);
+
+		quatloos /= 2.f;
+		ensure(quatloos.value() == 16);
+		quatloos = quatloos / 4;
+		ensure(quatloos.value() == 4);
+
+		F32 ratio = quatloos / LLUnit<Quatloos, F32>(4.f);
+		ensure(ratio == 1);
+
+		quatloos += LLUnit<Solari, F32>(4.f);
+		ensure(quatloos.value() == 5);
+		quatloos -= LLUnit<Latinum, F32>(1.f);
+		ensure(quatloos.value() == 1);
+	}
+
+	// implicit units
+	template<> template<>
+	void units_object_t::test<5>()
+	{
+		// 0-initialized
+		LLUnit<Quatloos, F32> quatloos(0);
+		// initialize implicit unit from explicit
+		LLUnitImplicit<Quatloos, F32> quatloos_implicit = quatloos + 1;
+		ensure(quatloos_implicit.value() == 1);
+
+		// assign implicit to explicit, or perform math operations
+		quatloos = quatloos_implicit;
+		ensure(quatloos.value() == 1);
+		quatloos += quatloos_implicit;
+		ensure(quatloos.value() == 2);
+
+		// math operations on implicits
+		quatloos_implicit = 1;
+		ensure(quatloos_implicit == 1);
+
+		quatloos_implicit += 2;
+		ensure(quatloos_implicit == 3);
+
+		quatloos_implicit *= 2;
+		ensure(quatloos_implicit == 6);
+
+		quatloos_implicit -= 1;
+		ensure(quatloos_implicit == 5);
+
+		quatloos_implicit /= 5;
+		ensure(quatloos_implicit == 1);
+
+		quatloos_implicit = quatloos_implicit + 3 + quatloos_implicit;
+		ensure(quatloos_implicit == 5);
+
+		quatloos_implicit = 10 - quatloos_implicit - 1;
+		ensure(quatloos_implicit == 4);
+
+		quatloos_implicit = 2 * quatloos_implicit * 2;
+		ensure(quatloos_implicit == 16);
+
+		F32 one_half = quatloos_implicit / (quatloos_implicit * 2);
+		ensure(one_half == 0.5f);
+
+		// implicit conversion to POD
+		F32 float_val = quatloos_implicit;
+		ensure(float_val == 16);
+
+		S32 int_val = quatloos_implicit;
+		ensure(int_val == 16);
+	}
+}
-- 
cgit v1.2.3


From c8c14ac72db3374cbd43893e5a97d98817cde0a3 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 7 Dec 2012 15:26:59 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system potential fixes for
 gcc builds

---
 indra/llcommon/lltrace.h | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 25d95d9670..0cb6a84aec 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -223,7 +223,7 @@ namespace LLTrace
 		typedef typename MeanValueType<TraceType<ACCUMULATOR> >::type  mean_t;
 
 		TraceType(const char* name, const char* description = NULL)
-		:	LLInstanceTracker(name),
+		:	LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>(name),
 			mName(name),
 			mDescription(description ? description : "")	
 		{
@@ -459,16 +459,17 @@ namespace LLTrace
 	{
 	public:
 		typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
+		typedef TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> > trace_t;
 
 		Measurement(const char* name, const char* description = NULL) 
-		:	TraceType(name, description)
+		:	trace_t(name, description)
 		{}
 
 		template<typename UNIT_T>
 		void sample(UNIT_T value)
 		{
 			T converted_value(value);
-			getPrimaryAccumulator().sample(LLUnits::rawValue(converted_value));
+			trace_t::getPrimaryAccumulator().sample(LLUnits::rawValue(converted_value));
 		}
 	};
 
@@ -478,16 +479,17 @@ namespace LLTrace
 	{
 	public:
 		typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
+		typedef TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> > trace_t;
 
 		Count(const char* name, const char* description = NULL) 
-		:	TraceType(name)
+		:	trace_t(name)
 		{}
 
 		template<typename UNIT_T>
 		void add(UNIT_T value)
 		{
 			T converted_value(value);
-			getPrimaryAccumulator().add(LLUnits::rawValue(converted_value));
+			trace_t::getPrimaryAccumulator().add(LLUnits::rawValue(converted_value));
 		}
 	};
 }
-- 
cgit v1.2.3


From b44c8593a34961f82fb523e42ad13b7e3da00ab6 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 7 Dec 2012 19:00:13 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system further fixes for
 gcc builds

---
 indra/llcommon/llunit.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 6b023f8287..72a6020ff8 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -188,7 +188,7 @@ struct LLUnitImplicit : public LLUnit<UNIT_TYPE, STORAGE_TYPE>
 	// this allows for interoperability with legacy code
 	operator storage_t() const
 	{
-		return value();
+		return base_t::value();
 	}
 };
 
-- 
cgit v1.2.3


From 8c2e3bea71ea15b805a9e2a288744f10d195d803 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sun, 9 Dec 2012 23:19:11 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system added ability to
 query self time of block timers indepedently

---
 indra/llcommon/llfasttimer.h        |  5 +++++
 indra/llcommon/lltrace.h            | 17 +++++++++++++++++
 indra/llcommon/lltracerecording.cpp | 11 +++++++++++
 indra/llcommon/lltracerecording.h   |  3 +++
 4 files changed, 36 insertions(+)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index e3d99a9e4b..b5b4a8d0b4 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -89,6 +89,11 @@ public:
 		return static_cast<TraceType<TimeBlockAccumulator::CallCountAspect>&>(*(TraceType<TimeBlockAccumulator>*)this);
 	}
 
+	TraceType<TimeBlockAccumulator::SelfTimeAspect>& selfTime() 
+	{ 
+		return static_cast<TraceType<TimeBlockAccumulator::SelfTimeAspect>&>(*(TraceType<TimeBlockAccumulator>*)this);
+	}
+
 	static TimeBlock& getRootTimer();
 	static void pushLog(LLSD sd);
 	static void setLogLock(LLMutex* mutex);
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 0cb6a84aec..d29d43a92c 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -412,6 +412,11 @@ namespace LLTrace
 			typedef U32 value_t;
 		};
 
+		struct SelfTimeAspect
+		{
+			typedef LLUnit<LLUnits::Seconds, F64> value_t;
+		};
+
 		TimeBlockAccumulator();
 		void addSamples(const TimeBlockAccumulator& other);
 		void reset(const TimeBlockAccumulator* other);
@@ -443,6 +448,18 @@ namespace LLTrace
 		{}
 	};
 
+	template<>
+	class TraceType<TimeBlockAccumulator::SelfTimeAspect>
+		:	public TraceType<TimeBlockAccumulator>
+	{
+	public:
+		typedef F32 mean_t;
+
+		TraceType(const char* name, const char* description = "")
+			:	TraceType<TimeBlockAccumulator>(name, description)
+		{}
+	};
+
 	class TimeBlockTreeNode
 	{
 	public:
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index e9b3376dae..3ea511ff3c 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -144,16 +144,27 @@ void Recording::appendRecording( const Recording& other )
 }
 
 LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) const
+{
+	return (F64)(*mStackTimers)[stat.getIndex()].mTotalTimeCounter / (F64)LLTrace::TimeBlock::countsPerSecond();
+}
+
+LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const
 {
 	return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
+
 U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const
 {
 	return (*mStackTimers)[stat.getIndex()].mCalls;
 }
 
 LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat) const
+{
+	return (F64)(*mStackTimers)[stat.getIndex()].mTotalTimeCounter / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
+}
+
+LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const
 {
 	return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
 }
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index f92281cea8..f4841214e8 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -120,8 +120,11 @@ namespace LLTrace
 
 		// Timer accessors
 		LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator>& stat) const;
+		LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const;
 		U32 getSum(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const;
+
 		LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimeBlockAccumulator>& stat) const;
+		LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const;
 		F32 getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const;
 
 		// Count accessors
-- 
cgit v1.2.3


From 1f56e57008f5a50c9e75fc0b4512c483ac359a52 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 18 Dec 2012 00:58:26 -0800
Subject: SH-3468 WIP add memory tracking base class created memory tracking
 trace type instrumented a few classes with memory tracking

---
 indra/llcommon/lltrace.h | 270 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 266 insertions(+), 4 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index d29d43a92c..d4fc93342d 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -424,9 +424,9 @@ namespace LLTrace
 		//
 		// members
 		//
-		U64 						mSelfTimeCounter,
-									mTotalTimeCounter;
-		U32 mCalls;
+		U64		mSelfTimeCounter,
+				mTotalTimeCounter;
+		U32		mCalls;
 	};
 
 
@@ -509,6 +509,268 @@ namespace LLTrace
 			trace_t::getPrimaryAccumulator().add(LLUnits::rawValue(converted_value));
 		}
 	};
-}
 
+struct MemStatAccumulator
+{
+	MemStatAccumulator()
+	:	mSize(0),
+		mChildSize(0),
+		mAllocatedCount(0),
+		mDeallocatedCount(0)
+	{}
+
+	void addSamples(const MemStatAccumulator& other)
+	{
+		mSize += other.mSize;
+		mChildSize += other.mChildSize;
+		mAllocatedCount += other.mAllocatedCount;
+		mDeallocatedCount += other.mDeallocatedCount;
+	}
+
+	void reset(const MemStatAccumulator* other)
+	{
+		mSize = 0;
+		mChildSize = 0;
+		mAllocatedCount = 0;
+		mDeallocatedCount = 0;
+	}
+
+	size_t		mSize,
+				mChildSize;
+	int			mAllocatedCount,
+				mDeallocatedCount;
+};
+
+class MemStat : public TraceType<MemStatAccumulator>
+{
+public:
+	typedef TraceType<MemStatAccumulator> trace_t;
+	MemStat(const char* name)
+	:	trace_t(name)
+	{}
+};
+
+// measures effective memory footprint of specified type
+// specialize to cover different types
+
+template<typename T>
+struct MemFootprint
+{
+	static size_t measure(const T& value)
+	{
+		return sizeof(T);
+	}
+
+	static size_t measure()
+	{
+		return sizeof(T);
+	}
+};
+
+template<typename T>
+struct MemFootprint<T*>
+{
+	static size_t measure(const T* value)
+	{
+		if (!value)
+		{
+			return 0;
+		}
+		return MemFootprint<T>::measure(*value);
+	}
+
+	static size_t measure()
+	{
+		return MemFootPrint<T>::measure();
+	}
+};
+
+template<typename T>
+struct MemFootprint<std::basic_string<T> >
+{
+	static size_t measure(const std::basic_string<T>& value)
+	{
+		return value.capacity() * sizeof(T);
+	}
+
+	static size_t measure()
+	{
+		return sizeof(std::basic_string<T>);
+	}
+};
+
+template<typename T>
+struct MemFootprint<std::vector<T> >
+{
+	static size_t measure(const std::vector<T>& value)
+	{
+		return value.capacity() * MemFootPrint<T>::measure();
+	}
+
+	static size_t measure()
+	{
+		return sizeof(std::vector<T>);
+	}
+};
+
+template<typename T>
+struct MemFootprint<std::list<T> >
+{
+	static size_t measure(const std::list<T>& value)
+	{
+		return value.size() * (MemFootPrint<T>::measure() + sizeof(void*) * 2);
+	}
+
+	static size_t measure()
+	{
+		return sizeof(std::list<T>);
+	}
+};
+
+template<typename T>
+class MemTrackable
+{
+	template<typename TRACKED, typename TRACKED_IS_TRACKER>
+	struct TrackMemImpl;
+
+	typedef MemTrackable<T> mem_trackable_t;
+
+public:
+	typedef void mem_trackable_tag_t;
+
+	~MemTrackable()
+	{
+		memDisclaim(mMemFootprint);
+	}
+
+	void* operator new(size_t allocation_size) 
+	{
+		// reserve 8 bytes for allocation size (and preserving 8 byte alignment of structs)
+		void* allocation = ::operator new(allocation_size + 8);
+		*(size_t*)allocation = allocation_size;
+		MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+		accumulator.mSize += allocation_size;
+		accumulator.mAllocatedCount++;
+		return (void*)((char*)allocation + 8);
+	}
+
+	void operator delete(void* ptr)
+	{
+		size_t* allocation_size = (size_t*)((char*)ptr - 8);
+		MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+		accumulator.mSize -= *allocation_size;
+		accumulator.mAllocatedCount--;
+		accumulator.mDeallocatedCount++;
+		::delete((char*)ptr - 8);
+	}
+
+	void *operator new [](size_t size)
+	{
+		size_t* result = (size_t*)malloc(size + 8);
+		*result = size;
+		MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+		accumulator.mSize += size;
+		accumulator.mAllocatedCount++;
+		return (void*)((char*)result + 8);
+	}
+
+	void operator delete[](void* ptr)
+	{
+		size_t* allocation_size = (size_t*)((char*)ptr - 8);
+		MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+		accumulator.mSize -= *allocation_size;
+		accumulator.mAllocatedCount--;
+		accumulator.mDeallocatedCount++;
+		::delete[]((char*)ptr - 8);
+	}
+
+	// claim memory associated with other objects/data as our own, adding to our calculated footprint
+	template<typename T>
+	T& memClaim(T& value)
+	{
+		TrackMemImpl<T>::claim(*this, value);
+		return value;
+	}
+
+	template<typename T>
+	const T& memClaim(const T& value)
+	{
+		TrackMemImpl<T>::claim(*this, value);
+		return value;
+	}
+
+
+	void memClaim(size_t size)
+	{
+		MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+		mMemFootprint += size;
+		accumulator.mSize += size;
+	}
+
+	// remove memory we had claimed from our calculated footprint
+	template<typename T>
+	T& memDisclaim(T& value)
+	{
+		TrackMemImpl<T>::disclaim(*this, value);
+		return value;
+	}
+
+	template<typename T>
+	const T& memDisclaim(const T& value)
+	{
+		TrackMemImpl<T>::disclaim(*this, value);
+		return value;
+	}
+
+	void memDisclaim(size_t size)
+	{
+		MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+		accumulator.mSize -= size;
+		mMemFootprint -= size;
+	}
+
+private:
+	size_t mMemFootprint;
+
+	template<typename TRACKED, typename TRACKED_IS_TRACKER = void>
+	struct TrackMemImpl
+	{
+		static void claim(mem_trackable_t& tracker, const TRACKED& tracked)
+		{
+			MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
+			accumulator.mSize += footprint;
+			tracker.mMemFootprint += footprint;
+		}
+
+		static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked)
+		{
+			MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
+			accumulator.mSize -= footprint;
+			tracker.mMemFootprint -= footprint;
+		}
+	};
+
+	template<typename TRACKED>
+	struct TrackMemImpl<TRACKED, typename TRACKED::mem_trackable_tag_t>
+	{
+		static void claim(mem_trackable_t& tracker, TRACKED& tracked)
+		{
+			MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+			accumulator.mChildSize += MemFootprint<TRACKED>::measure(tracked);
+		}
+
+		static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
+		{
+			MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+			accumulator.mChildSize -= MemFootprint<TRACKED>::measure(tracked);
+		}
+	};
+	static MemStat sStat;
+};
+
+template<typename T> MemStat MemTrackable<T>::sStat(typeid(T).name());
+
+}
 #endif // LL_LLTRACE_H
-- 
cgit v1.2.3


From c219282f5de753a044cecb53bd806145f68add9a Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 18 Dec 2012 20:07:25 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system removed some
 potential data races got memory stats recording in trace system

---
 indra/llcommon/llapr.h                   |  51 +++--
 indra/llcommon/llfasttimer.cpp           | 326 +++++++++++++------------------
 indra/llcommon/llfasttimer.h             |  27 +--
 indra/llcommon/lltrace.h                 |  56 +++---
 indra/llcommon/lltracerecording.cpp      |  21 +-
 indra/llcommon/lltracerecording.h        |  11 +-
 indra/llcommon/lltracethreadrecorder.cpp |  14 +-
 7 files changed, 238 insertions(+), 268 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 199b5291dd..f8f94263e4 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -48,6 +48,19 @@ extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
 extern apr_thread_mutex_t* gCallStacksLogMutexp;
 
 struct apr_dso_handle_t;
+/**
+ * @brief Function which appropriately logs error or remains quiet on
+ * APR_SUCCESS.
+ * @return Returns <code>true</code> if status is an error condition.
+ */
+bool LL_COMMON_API ll_apr_warn_status(apr_status_t status);
+/// There's a whole other APR error-message function if you pass a DSO handle.
+bool LL_COMMON_API ll_apr_warn_status(apr_status_t status, apr_dso_handle_t* handle);
+
+void LL_COMMON_API ll_apr_assert_status(apr_status_t status);
+void LL_COMMON_API ll_apr_assert_status(apr_status_t status, apr_dso_handle_t* handle);
+
+extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool
 
 /** 
  * @brief initialize the common apr constructs -- apr itself, the
@@ -285,26 +298,26 @@ protected:
 	{
 		llassert(sInitialized);
 		void* ptr;
-		//apr_status_t result =
+		apr_status_t result =
 		apr_threadkey_private_get(&ptr, mThreadKey);
-		//if (result != APR_SUCCESS)
-		//{
-		//	ll_apr_warn_status(s);
-		//	llerrs << "Failed to get thread local data" << llendl;
-		//}
+		if (result != APR_SUCCESS)
+		{
+			ll_apr_warn_status(result);
+			llerrs << "Failed to get thread local data" << llendl;
+		}
 		return ptr;
 	}
 
 	LL_FORCE_INLINE const void* get() const
 	{
 		void* ptr;
-		//apr_status_t result =
+		apr_status_t result =
 		apr_threadkey_private_get(&ptr, mThreadKey);
-		//if (result != APR_SUCCESS)
-		//{
-		//	ll_apr_warn_status(s);
-		//	llerrs << "Failed to get thread local data" << llendl;
-		//}
+		if (result != APR_SUCCESS)
+		{
+			ll_apr_warn_status(result);
+			llerrs << "Failed to get thread local data" << llendl;
+		}
 		return ptr;
 	}
 
@@ -379,18 +392,4 @@ public:
 	}
 };
 
-/**
- * @brief Function which appropriately logs error or remains quiet on
- * APR_SUCCESS.
- * @return Returns <code>true</code> if status is an error condition.
- */
-bool LL_COMMON_API ll_apr_warn_status(apr_status_t status);
-/// There's a whole other APR error-message function if you pass a DSO handle.
-bool LL_COMMON_API ll_apr_warn_status(apr_status_t status, apr_dso_handle_t* handle);
-
-void LL_COMMON_API ll_apr_assert_status(apr_status_t status);
-void LL_COMMON_API ll_apr_assert_status(apr_status_t status, apr_dso_handle_t* handle);
-
-extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool
-
 #endif // LL_LLAPR_H
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 37e0fbac0a..f4fa8f1e61 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -59,11 +59,6 @@ namespace LLTrace
 //////////////////////////////////////////////////////////////////////////////
 // statics
 
-S32         TimeBlock::sCurFrameIndex   = -1;
-S32         TimeBlock::sLastFrameIndex  = -1;
-U64         TimeBlock::sLastFrameTime   = TimeBlock::getCPUClockCount64();
-bool        TimeBlock::sPauseHistory    = 0;
-bool        TimeBlock::sResetHistory    = 0;
 bool        TimeBlock::sLog		     = false;
 std::string TimeBlock::sLogName         = "";
 bool        TimeBlock::sMetricLog       = false;
@@ -220,143 +215,126 @@ void TimeBlock::setParent(TimeBlock* parent)
 	}
 }
 
-S32 TimeBlock::getDepth()
-{
-	S32 depth = 0;
-	TimeBlock* timerp = mParent;
-	while(timerp)
-	{
-		depth++;
-		if (timerp->getParent() == timerp) break;
-		timerp = timerp->mParent;
-	}
-	return depth;
-}
-
 // static
 void TimeBlock::processTimes()
 {
-	//void TimeBlock::buildHierarchy()
+	get_clock_count(); // good place to calculate clock frequency
+	U64 cur_time = getCPUClockCount64();
+	CurTimerData* cur_data = sCurTimerData.get();
+
+	// set up initial tree
+	for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(); 
+		it != end_it; 
+		++it)
 	{
-		// set up initial tree
+		TimeBlock& timer = *it;
+		if (&timer == &TimeBlock::getRootTimer()) continue;
+
+		// bootstrap tree construction by attaching to last timer to be on stack
+		// when this timer was called
+		if (timer.mParent == &TimeBlock::getRootTimer())
 		{
-			for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(); it != end_it; ++it)
+			TimeBlockAccumulator& accumulator = timer.getPrimaryAccumulator();
+
+			if (accumulator.mLastCaller)
 			{
-				TimeBlock& timer = *it;
-				if (&timer == &TimeBlock::getRootTimer()) continue;
-
-				// bootstrap tree construction by attaching to last timer to be on stack
-				// when this timer was called
-				if (timer.mParent == &TimeBlock::getRootTimer())
-				{
-					TimeBlockTreeNode& tree_node = sCurTimerData->mTimerTreeData[timer.getIndex()];
-
-					if (tree_node.mLastCaller)
-					{
-						timer.setParent(tree_node.mLastCaller);
-					}
-					// no need to push up tree on first use, flag can be set spuriously
-					tree_node.mMoveUpTree = false;
-				}
+				timer.setParent(accumulator.mLastCaller);
+				accumulator.mParent = accumulator.mLastCaller;
 			}
+			// no need to push up tree on first use, flag can be set spuriously
+			accumulator.mMoveUpTree = false;
 		}
+	}
 
-		// bump timers up tree if they have 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(TimeBlock::getRootTimer());
-			it != end_timer_tree_bottom_up();
-			++it)
+	// bump timers up tree if they have 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(TimeBlock::getRootTimer());
+		it != end_timer_tree_bottom_up();
+		++it)
+	{
+		TimeBlock* timerp = *it;
+
+		// sort timers by time last called, so call graph makes sense
+		if (timerp->mNeedsSorting)
 		{
-			TimeBlock* timerp = *it;
-			// skip root timer
-			if (timerp == &TimeBlock::getRootTimer()) continue;
-			TimeBlockTreeNode& tree_node = sCurTimerData->mTimerTreeData[timerp->getIndex()];
+			std::sort(timerp->getChildren().begin(), timerp->getChildren().end(), SortTimerByName());
+		}
+
+		// skip root timer
+		if (timerp != &TimeBlock::getRootTimer())
+		{
+			TimeBlockAccumulator& accumulator = timerp->getPrimaryAccumulator();
 
-			if (tree_node.mMoveUpTree)
+			if (accumulator.mMoveUpTree)
 			{
 				// since ancestors have already been visited, re-parenting 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());
-				tree_node.mMoveUpTree = false;
+				accumulator.mParent = timerp->mParent;
+				accumulator.mMoveUpTree = false;
 
 				// don't bubble up any ancestors until descendants are done bubbling up
+				// as ancestors may call this timer only on certain paths, so we want to resolve
+				// child-most block locations before their parents
 				it.skipAncestors();
 			}
 		}
-
-		// sort timers by time last called, so call graph makes sense
-		for(timer_tree_dfs_iterator_t it = begin_timer_tree(TimeBlock::getRootTimer());
-			it != end_timer_tree();
-			++it)
-		{
-			TimeBlock* timerp = (*it);
-			if (timerp->mNeedsSorting)
-			{
-				std::sort(timerp->getChildren().begin(), timerp->getChildren().end(), SortTimerByName());
-			}
-			timerp->mNeedsSorting = false;
-		}
 	}
-	
-	//void TimeBlock::accumulateTimings()
-	{
-		U64 cur_time = getCPUClockCount64();
-
-		// root defined by parent pointing to self
-		CurTimerData* cur_data = sCurTimerData.get();
-		// walk up stack of active timers and accumulate current time while leaving timing structures active
-		BlockTimer* cur_timer = cur_data->mCurTimer;
-		TimeBlockAccumulator& accumulator = cur_data->mTimerData->getPrimaryAccumulator();
-		while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
-		{
-			U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
-			U64 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
-			cur_data->mChildTime = 0;
-			accumulator.mSelfTimeCounter += self_time_delta;
-			accumulator.mTotalTimeCounter += cumulative_time_delta;
 
-			cur_timer->mStartTime = cur_time;
+	// walk up stack of active timers and accumulate current time while leaving timing structures active
+	BlockTimer* cur_timer = cur_data->mCurTimer;
+	TimeBlockAccumulator& accumulator = cur_data->mTimerData->getPrimaryAccumulator();
+	// root defined by parent pointing to self
+	while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
+	{
+		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
+		U64 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
+		cur_data->mChildTime = 0;
+		accumulator.mSelfTimeCounter += self_time_delta;
+		accumulator.mTotalTimeCounter += cumulative_time_delta;
 
-			cur_data = &cur_timer->mLastTimerData;
-			cur_data->mChildTime += cumulative_time_delta;
-			if (cur_data->mTimerData)
-			{
-				accumulator = cur_data->mTimerData->getPrimaryAccumulator();
-			}
+		cur_timer->mStartTime = cur_time;
 
-			cur_timer = cur_timer->mLastTimerData.mCurTimer;
+		cur_data = &cur_timer->mLastTimerData;
+		cur_data->mChildTime += cumulative_time_delta;
+		if (cur_data->mTimerData)
+		{
+			accumulator = cur_data->mTimerData->getPrimaryAccumulator();
 		}
 
-		// traverse tree in DFS post order, or bottom up
-		//for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(TimeBlock::getRootTimer());
-		//	it != end_timer_tree_bottom_up();
-		//	++it)
-		//{
-		//	TimeBlock* timerp = (*it);
-		//	TimeBlockAccumulator& accumulator = timerp->getPrimaryAccumulator();
-		//	timerp->mTreeTimeCounter = accumulator.mSelfTimeCounter;
-		//	for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it)
-		//	{
-		//		timerp->mTreeTimeCounter += (*child_it)->mTreeTimeCounter;
-		//	}
-
-		//S32 cur_frame = getCurFrameIndex();
-		//if (cur_frame >= 0)
-		//{
-		//	// update timer history
+		cur_timer = cur_timer->mLastTimerData.mCurTimer;
+	}
 
-		//	int hidx = getCurFrameIndex() % HISTORY_NUM;
 
-		//	timerp->mCountHistory[hidx] = timerp->mTreeTimeCounter;
-		//	timerp->mCountAverage       = ((U64)timerp->mCountAverage * cur_frame + timerp->mTreeTimeCounter) / (cur_frame+1);
-		//	timerp->mCallHistory[hidx]  = accumulator.mCalls;
-		//	timerp->mCallAverage        = ((U64)timerp->mCallAverage * cur_frame + accumulator.mCalls) / (cur_frame+1);
-		//}
-		//}
+	// reset for next frame
+	for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(),
+			end_it = LLInstanceTracker<TimeBlock>::endInstances();
+		it != end_it;
+		++it)
+	{
+		TimeBlock& timer = *it;
+		TimeBlockAccumulator& accumulator = timer.getPrimaryAccumulator();
+
+		accumulator.mLastCaller = NULL;
+		accumulator.mMoveUpTree = false;
 	}
+
+	// traverse tree in DFS post order, or bottom up
+	//for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(TimeBlock::getRootTimer());
+	//	it != end_timer_tree_bottom_up();
+	//	++it)
+	//{
+	//	TimeBlock* timerp = (*it);
+	//	TimeBlockAccumulator& accumulator = timerp->getPrimaryAccumulator();
+	//	timerp->mTreeTimeCounter = accumulator.mSelfTimeCounter;
+	//	for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it)
+	//	{
+	//		timerp->mTreeTimeCounter += (*child_it)->mTreeTimeCounter;
+	//	}
+	//}
 }
 
 
@@ -376,106 +354,78 @@ std::vector<TimeBlock*>& TimeBlock::getChildren()
 }
 
 //static
-void TimeBlock::nextFrame()
+void TimeBlock::logStats()
 {
-	get_clock_count(); // good place to calculate clock frequency
-	U64 frame_time = TimeBlock::getCPUClockCount64();
-	if ((frame_time - sLastFrameTime) >> 8 > 0xffffffff)
-	{
-		llinfos << "Slow frame, fast timers inaccurate" << llendl;
-	}
-
-	if (!sPauseHistory)
-	{
-		TimeBlock::processTimes();
-		sLastFrameIndex = sCurFrameIndex++;
-	}
-	
 	// get ready for next frame
-	//void TimeBlock::resetFrame()
-	{
-		if (sLog)
-		{ //output current frame counts to performance log
+	if (sLog)
+	{ //output current frame counts to performance log
 
-			static S32 call_count = 0;
-			if (call_count % 100 == 0)
-			{
-				LL_DEBUGS("FastTimers") << "countsPerSecond: " << countsPerSecond() << 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()) / (LLUnit<LLUnits::Hertz, F64>(LLProcessorInfo().getCPUFrequency())) << LL_ENDL;
-			}
-			call_count++;
+		static S32 call_count = 0;
+		if (call_count % 100 == 0)
+		{
+			LL_DEBUGS("FastTimers") << "countsPerSecond: " << countsPerSecond() << 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()) / (LLUnit<LLUnits::Hertz, F64>(LLProcessorInfo().getCPUFrequency())) << LL_ENDL;
+		}
+		call_count++;
 
-			LLUnit<LLUnits::Seconds, F64> total_time(0);
-			LLSD sd;
+		LLUnit<LLUnits::Seconds, F64> total_time(0);
+		LLSD sd;
 
+		{
+			for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), 
+				end_it = LLInstanceTracker<TimeBlock>::endInstances(); 
+				it != end_it; 
+			++it)
 			{
-				for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), 
-					end_it = LLInstanceTracker<TimeBlock>::endInstances(); 
-					it != end_it; 
-				++it)
-				{
-					TimeBlock& timer = *it;
-					LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
-					sd[timer.getName()]["Time"] = (LLSD::Real) (frame_recording.getLastRecordingPeriod().getSum(timer).value());	
-					sd[timer.getName()]["Calls"] = (LLSD::Integer) (frame_recording.getLastRecordingPeriod().getSum(timer.callCount()));
-
-					// computing total time here because getting the root timer's getCountHistory
-					// doesn't work correctly on the first frame
-					total_time += frame_recording.getLastRecordingPeriod().getSum(timer);
-				}
-			}
-
-			sd["Total"]["Time"] = (LLSD::Real) total_time.value();
-			sd["Total"]["Calls"] = (LLSD::Integer) 1;
+				TimeBlock& timer = *it;
+				LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
+				sd[timer.getName()]["Time"] = (LLSD::Real) (frame_recording.getLastRecordingPeriod().getSum(timer).value());	
+				sd[timer.getName()]["Calls"] = (LLSD::Integer) (frame_recording.getLastRecordingPeriod().getSum(timer.callCount()));
 
-			{		
-				LLMutexLock lock(sLogLock);
-				sLogQueue.push(sd);
+				// computing total time here because getting the root timer's getCountHistory
+				// doesn't work correctly on the first frame
+				total_time += frame_recording.getLastRecordingPeriod().getSum(timer);
 			}
 		}
 
-		// reset for next frame
-		for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(),
-			end_it = LLInstanceTracker<TimeBlock>::endInstances();
-			it != end_it;
-		++it)
-		{
-			TimeBlock& timer = *it;
-			TimeBlockTreeNode& tree_node = sCurTimerData->mTimerTreeData[timer.getIndex()];
+		sd["Total"]["Time"] = (LLSD::Real) total_time.value();
+		sd["Total"]["Calls"] = (LLSD::Integer) 1;
 
-			tree_node.mLastCaller = NULL;
-			tree_node.mMoveUpTree = false;
+		{		
+			LLMutexLock lock(sLogLock);
+			sLogQueue.push(sd);
 		}
 	}
-	sLastFrameTime = frame_time;
+
 }
 
 //static
 void TimeBlock::dumpCurTimes()
 {
-	// accumulate timings, etc.
-	processTimes();
-	
+	LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
+	LLTrace::Recording& last_frame_recording = frame_recording.getLastRecordingPeriod();
+
 	// walk over timers in depth order and output timings
 	for(timer_tree_dfs_iterator_t it = begin_timer_tree(TimeBlock::getRootTimer());
 		it != end_timer_tree();
 		++it)
 	{
-		LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
 		TimeBlock* timerp = (*it);
-		LLUnit<LLUnits::Seconds, F64> total_time_ms = frame_recording.getLastRecordingPeriod().getSum(*timerp);
-		U32 num_calls = frame_recording.getLastRecordingPeriod().getSum(timerp->callCount());
+		LLUnit<LLUnits::Seconds, F64> total_time_ms = 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;
 
 		std::ostringstream out_str;
-		for (S32 i = 0; i < timerp->getDepth(); i++)
+		TimeBlock* parent_timerp = timerp;
+		while(parent_timerp && parent_timerp != parent_timerp->getParent())
 		{
 			out_str << "\t";
+			parent_timerp = parent_timerp->getParent();
 		}
 
 		out_str << timerp->getName() << " " 
@@ -505,7 +455,11 @@ void TimeBlock::writeLog(std::ostream& os)
 TimeBlockAccumulator::TimeBlockAccumulator() 
 :	mSelfTimeCounter(0),
 	mTotalTimeCounter(0),
-	mCalls(0)
+	mCalls(0),
+	mLastCaller(NULL),
+	mActiveCount(0),
+	mMoveUpTree(false),
+	mParent(NULL)
 {}
 
 void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
@@ -513,6 +467,10 @@ void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
 	mSelfTimeCounter += other.mSelfTimeCounter;
 	mTotalTimeCounter += other.mTotalTimeCounter;
 	mCalls += other.mCalls;
+	mLastCaller = other.mLastCaller;
+	mActiveCount = other.mActiveCount;
+	mMoveUpTree = other.mMoveUpTree;
+	mParent = other.mParent;
 }
 
 void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
@@ -522,10 +480,4 @@ void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
 	mCalls = 0;
 }
 
-TimeBlockTreeNode::TimeBlockTreeNode()
-:	mLastCaller(NULL),
-	mActiveCount(0),
-	mMoveUpTree(false)
-{}
-
 } // namespace LLTrace
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index b5b4a8d0b4..1e2e4b590f 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -43,7 +43,6 @@ struct CurTimerData
 	class BlockTimer*	mCurTimer;
 	class TimeBlock*	mTimerData;
 	U64					mChildTime;
-	TimeBlockTreeNode*		mTimerTreeData;
 };
 
 class BlockTimer
@@ -70,11 +69,8 @@ class TimeBlock
 public:
 	TimeBlock(const char* name, bool open = false, TimeBlock* parent = &getRootTimer());
 
-	enum { HISTORY_NUM = 300 };
-
 	TimeBlock* getParent() const { return mParent; }
 	void setParent(TimeBlock* parent);
-	S32 getDepth();
 
 	typedef std::vector<TimeBlock*>::const_iterator child_const_iter;
 	child_const_iter beginChildren();
@@ -245,12 +241,12 @@ public:
 	// can be called multiple times in a frame, at any point
 	static void processTimes();
 
-	// call this once a frame to reset timers
-	static void nextFrame();
+	// call this once a frame to periodically log timers
+	static void logStats();
 
 	// tree structure, only updated from master trace thread
 	TimeBlock*					mParent;				// TimeBlock of caller(parent)
-	std::vector<TimeBlock*>	mChildren;
+	std::vector<TimeBlock*>		mChildren;				// TimeBlock of callees
 	bool						mCollapsed,				// don't show children
 								mNeedsSorting;			// sort children whenever child added
 
@@ -260,12 +256,6 @@ public:
 												sLog;	
 	static LLThreadLocalPointer<CurTimerData>	sCurTimerData;
 	static U64									sClockResolution;
-	static S32									sCurFrameIndex,
-												sLastFrameIndex;
-	static U64									sLastFrameTime;
-	static bool 								sPauseHistory,
-												sResetHistory;
-
 };
 
 LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
@@ -274,10 +264,10 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 	mStartTime = TimeBlock::getCPUClockCount64();
 
 	CurTimerData* cur_timer_data = TimeBlock::sCurTimerData.get();
-	TimeBlockTreeNode& tree_node = cur_timer_data->mTimerTreeData[timer.getIndex()];
-	tree_node.mActiveCount++;
+	TimeBlockAccumulator& accumulator = cur_timer_data->mTimerData->getPrimaryAccumulator();
+	accumulator.mActiveCount++;
 	// keep current parent as long as it is active when we are
-	tree_node.mMoveUpTree |= (cur_timer_data->mTimerTreeData[timer.mParent->getIndex()].mActiveCount == 0);
+	accumulator.mMoveUpTree |= (accumulator.mParent->getPrimaryAccumulator().mActiveCount == 0);
 
 	// store top of stack
 	mLastTimerData = *cur_timer_data;
@@ -294,16 +284,15 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 	U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
 	CurTimerData* cur_timer_data = TimeBlock::sCurTimerData.get();
 	TimeBlockAccumulator& accumulator = cur_timer_data->mTimerData->getPrimaryAccumulator();
-	TimeBlockTreeNode& tree_node = cur_timer_data->mTimerTreeData[cur_timer_data->mTimerData->getIndex()];
 
 	accumulator.mCalls++;
 	accumulator.mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
 	accumulator.mTotalTimeCounter += total_time;
-	tree_node.mActiveCount--;
+	accumulator.mActiveCount--;
 
 	// store last caller to bootstrap tree creation
 	// do this in the destructor in case of recursion to get topmost caller
-	tree_node.mLastCaller = mLastTimerData.mTimerData;
+	accumulator.mLastCaller = mLastTimerData.mTimerData;
 
 	// we are only tracking self time, so subtract our total time delta from parents
 	mLastTimerData.mChildTime += total_time;
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index d4fc93342d..5b5e2b7879 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -82,18 +82,21 @@ namespace LLTrace
 		enum StaticAllocationMarker { STATIC_ALLOC };
 
 		AccumulatorBuffer(StaticAllocationMarker m)
-		:	mStorageSize(64),
-			mNextStorageSlot(0),
-			mStorage(new ACCUMULATOR[DEFAULT_ACCUMULATOR_BUFFER_SIZE])
-		{}
+		:	mStorageSize(0),
+			mStorage(NULL),
+			mNextStorageSlot(0)
+		{
+			resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
+		}
 
 	public:
 
 		AccumulatorBuffer(const AccumulatorBuffer& other = getDefaultBuffer())
-		:	mStorageSize(other.mStorageSize),
-			mStorage(new ACCUMULATOR[other.mStorageSize]),
+		:	mStorageSize(0),
+			mStorage(NULL),
 			mNextStorageSlot(other.mNextStorageSlot)
 		{
+			resize(other.mStorageSize);
 			for (S32 i = 0; i < mNextStorageSlot; i++)
 			{
 				mStorage[i] = other.mStorage[i];
@@ -181,9 +184,12 @@ namespace LLTrace
 		{
 			ACCUMULATOR* old_storage = mStorage;
 			mStorage = new ACCUMULATOR[new_size];
-			for (S32 i = 0; i < mStorageSize; i++)
+			if (old_storage)
 			{
-				mStorage[i] = old_storage[i];
+				for (S32 i = 0; i < mStorageSize; i++)
+				{
+					mStorage[i] = old_storage[i];
+				}
 			}
 			mStorageSize = new_size;
 			delete[] old_storage;
@@ -300,14 +306,14 @@ namespace LLTrace
 				mNumSamples += other.mNumSamples;
 				mMean = mMean * weight + other.mMean * (1.f - weight);
 
+				// combine variance (and hence standard deviation) of 2 different sized sample groups using
+				// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
 				F64 n_1 = (F64)mNumSamples,
 					n_2 = (F64)other.mNumSamples;
 				F64 m_1 = mMean,
 					m_2 = other.mMean;
 				F64 sd_1 = getStandardDeviation(),
 					sd_2 = other.getStandardDeviation();
-				// combine variance (and hence standard deviation) of 2 different sized sample groups using
-				// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
 				if (n_1 == 0)
 				{
 					mVarianceSum = other.mVarianceSum;
@@ -405,6 +411,7 @@ namespace LLTrace
 	{
 	public:
 		typedef LLUnit<LLUnits::Seconds, F64> value_t;
+		typedef TimeBlockAccumulator self_t;
 
 		// fake class that allows us to view call count aspect of timeblock accumulator
 		struct CallCountAspect 
@@ -418,15 +425,20 @@ namespace LLTrace
 		};
 
 		TimeBlockAccumulator();
-		void addSamples(const TimeBlockAccumulator& other);
-		void reset(const TimeBlockAccumulator* other);
+		void addSamples(const self_t& other);
+		void reset(const self_t* other);
 
 		//
 		// members
 		//
-		U64		mSelfTimeCounter,
-				mTotalTimeCounter;
-		U32		mCalls;
+		U64							mSelfTimeCounter,
+									mTotalTimeCounter;
+		U32							mCalls;
+		class TimeBlock*			mParent;		// last acknowledged parent of this time block
+		class TimeBlock*			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
+
 	};
 
 
@@ -460,16 +472,6 @@ namespace LLTrace
 		{}
 	};
 
-	class TimeBlockTreeNode
-	{
-	public:
-		TimeBlockTreeNode();
-		class TimeBlock*			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
-	};
-
-
 	template <typename T = F64>
 	class Measurement
 	:	public TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
@@ -604,7 +606,7 @@ struct MemFootprint<std::vector<T> >
 {
 	static size_t measure(const std::vector<T>& value)
 	{
-		return value.capacity() * MemFootPrint<T>::measure();
+		return value.capacity() * MemFootprint<T>::measure();
 	}
 
 	static size_t measure()
@@ -618,7 +620,7 @@ struct MemFootprint<std::list<T> >
 {
 	static size_t measure(const std::list<T>& value)
 	{
-		return value.size() * (MemFootPrint<T>::measure() + sizeof(void*) * 2);
+		return value.size() * (MemFootprint<T>::measure() + sizeof(void*) * 2);
 	}
 
 	static size_t measure()
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 3ea511ff3c..40079f40f1 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -44,7 +44,8 @@ Recording::Recording()
 	mMeasurementsFloat(new AccumulatorBuffer<MeasurementAccumulator<F64> >()),
 	mCounts(new AccumulatorBuffer<CountAccumulator<S64> >()),
 	mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<S64> >()),
-	mStackTimers(new AccumulatorBuffer<TimeBlockAccumulator>())
+	mStackTimers(new AccumulatorBuffer<TimeBlockAccumulator>()),
+	mMemStats(new AccumulatorBuffer<MemStatAccumulator>())
 {}
 
 Recording::Recording( const Recording& other )
@@ -57,6 +58,7 @@ Recording::Recording( const Recording& other )
 	mCounts            = other.mCounts;
 	mMeasurements      = other.mMeasurements;
 	mStackTimers       = other.mStackTimers;
+	mMemStats		   = other.mMemStats;
 
 	LLStopWatchControlsMixin::initTo(other.getPlayState());
 }
@@ -84,6 +86,7 @@ void Recording::handleReset()
 	mCounts.write()->reset();
 	mMeasurements.write()->reset();
 	mStackTimers.write()->reset();
+	mMemStats.write()->reset();
 
 	mElapsedSeconds = 0.0;
 	mSamplingTimer.reset();
@@ -98,6 +101,7 @@ void Recording::handleStart()
 void Recording::handleStop()
 {
 	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+	LLTrace::TimeBlock::processTimes();
 	LLTrace::get_thread_recorder()->deactivate(this);
 }
 
@@ -107,9 +111,9 @@ void Recording::handleSplitTo(Recording& other)
 	other.restart();
 	other.mMeasurementsFloat.write()->reset(mMeasurementsFloat);
 	other.mMeasurements.write()->reset(mMeasurements);
+	//TODO: figure out how to get seamless handoff of timing stats
 }
 
-
 void Recording::makePrimary()
 {
 	mCountsFloat.write()->makePrimary();
@@ -117,6 +121,7 @@ void Recording::makePrimary()
 	mCounts.write()->makePrimary();
 	mMeasurements.write()->makePrimary();
 	mStackTimers.write()->makePrimary();
+	mMemStats.write()->makePrimary();
 }
 
 bool Recording::isPrimary() const
@@ -131,6 +136,7 @@ void Recording::makeUnique()
 	mCounts.makeUnique();
 	mMeasurements.makeUnique();
 	mStackTimers.makeUnique();
+	mMemStats.makeUnique();
 }
 
 void Recording::appendRecording( const Recording& other )
@@ -140,6 +146,7 @@ void Recording::appendRecording( const Recording& other )
 	mCounts.write()->addSamples(*other.mCounts);
 	mMeasurements.write()->addSamples(*other.mMeasurements);
 	mStackTimers.write()->addSamples(*other.mStackTimers);
+	mMemStats.write()->addSamples(*other.mMemStats);
 	mElapsedSeconds += other.mElapsedSeconds;
 }
 
@@ -174,6 +181,16 @@ F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>&
 	return (F32)(*mStackTimers)[stat.getIndex()].mCalls / mElapsedSeconds;
 }
 
+LLUnit<LLUnits::Bytes, U32> Recording::getSum(const TraceType<MemStatAccumulator>& stat) const
+{
+	return (*mMemStats)[stat.getIndex()].mAllocatedCount;
+}
+
+LLUnit<LLUnits::Bytes, F32> Recording::getPerSec(const TraceType<MemStatAccumulator>& stat) const
+{
+	return (F32)(*mMemStats)[stat.getIndex()].mAllocatedCount / mElapsedSeconds;
+}
+
 
 F64 Recording::getSum( const TraceType<CountAccumulator<F64> >& stat ) const
 {
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index f4841214e8..8e5f1125ec 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -34,7 +34,7 @@
 #include "lltimer.h"
 #include "lltrace.h"
 
-class LL_COMMON_API LLStopWatchControlsMixinCommon
+class LLStopWatchControlsMixinCommon
 {
 public:
 	virtual ~LLStopWatchControlsMixinCommon() {}
@@ -101,7 +101,7 @@ private:
 
 namespace LLTrace
 {
-	class LL_COMMON_API Recording : public LLStopWatchControlsMixin<Recording>
+	class Recording : public LLStopWatchControlsMixin<Recording>
 	{
 	public:
 		Recording();
@@ -127,6 +127,10 @@ namespace LLTrace
 		LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const;
 		F32 getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const;
 
+		// Memory accessors
+		LLUnit<LLUnits::Bytes, U32> getSum(const TraceType<MemStatAccumulator>& stat) const;
+		LLUnit<LLUnits::Bytes, F32> getPerSec(const TraceType<MemStatAccumulator>& stat) const;
+
 		// Count accessors
 		F64 getSum(const TraceType<CountAccumulator<F64> >& stat) const;
 		S64 getSum(const TraceType<CountAccumulator<S64> >& stat) const;
@@ -226,7 +230,8 @@ namespace LLTrace
 		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > >	mMeasurementsFloat;
 		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<S64> > >		mCounts;
 		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<S64> > >	mMeasurements;
-		LLCopyOnWritePointer<AccumulatorBuffer<TimeBlockAccumulator> >				mStackTimers;
+		LLCopyOnWritePointer<AccumulatorBuffer<TimeBlockAccumulator> >			mStackTimers;
+		LLCopyOnWritePointer<AccumulatorBuffer<MemStatAccumulator> >			mMemStats;
 
 		LLTimer			mSamplingTimer;
 		F64				mElapsedSeconds;
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 16235473ee..c4144b4999 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -43,13 +43,20 @@ ThreadRecorder::ThreadRecorder()
 
 	mRootTimerData = new CurTimerData();
 	mRootTimerData->mTimerData = &TimeBlock::getRootTimer();
-	mRootTimerData->mTimerTreeData = new TimeBlockTreeNode[AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer().size()];
+
 	TimeBlock::sCurTimerData = mRootTimerData;
+	TimeBlock::getRootTimer().getPrimaryAccumulator().mActiveCount = 1;
+
+	// initialize parent pointers in time blocks
+	for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(); 
+		it != end_it; 
+		++it)
+	{
+		it->getPrimaryAccumulator().mParent = it->mParent;
+	}
 
 	mRootTimer = new BlockTimer(TimeBlock::getRootTimer());
 	mRootTimerData->mCurTimer = mRootTimer;
-
-	mRootTimerData->mTimerTreeData[TimeBlock::getRootTimer().getIndex()].mActiveCount = 1;
 }
 
 ThreadRecorder::~ThreadRecorder()
@@ -62,7 +69,6 @@ ThreadRecorder::~ThreadRecorder()
 	}
 	get_thread_recorder() = NULL;
 	TimeBlock::sCurTimerData = NULL;
-	delete [] mRootTimerData->mTimerTreeData;
 	delete mRootTimerData;
 }
 
-- 
cgit v1.2.3


From 013f04cabec8e110ee659d9b3f75a4d25f114b7b Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 21 Dec 2012 00:13:21 -0800
Subject: SH-3468 WIP add memory tracking base class improvements on lifetime
 of lltrace core data structures tweaks to thread local pointer handling so
 that static constructors/destructors can safely call functions that use
 lltrace

---
 indra/llcommon/llapr.cpp                 |  12 +--
 indra/llcommon/llapr.h                   |   2 +-
 indra/llcommon/llfasttimer.cpp           |  93 ++++++-------------
 indra/llcommon/llfasttimer.h             |  34 ++++---
 indra/llcommon/lltrace.cpp               |  29 ++++++
 indra/llcommon/lltrace.h                 | 150 ++++++++++++++++++++++---------
 indra/llcommon/lltracerecording.cpp      |  24 ++++-
 indra/llcommon/lltracerecording.h        |   4 +
 indra/llcommon/lltracethreadrecorder.cpp |  71 ++++++++++++---
 indra/llcommon/lltracethreadrecorder.h   |  13 ++-
 10 files changed, 286 insertions(+), 146 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 1db3aa9e89..6affdad61b 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -542,12 +542,12 @@ void LLThreadLocalPointerBase::destroyAllThreadLocalStorage()
 {
 	if (sInitialized)
 	{
-		for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances();
-			it != end_it;
-			++it)
-		{
-			(*it).destroyStorage();
-		}
+		//for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances();
+		//	it != end_it;
+		//	++it)
+		//{
+		//	(*it).destroyStorage();
+		//}
 		sInitialized = false;
 	}
 }
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index f8f94263e4..2faf4aad2d 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -296,7 +296,7 @@ protected:
 
 	LL_FORCE_INLINE void* get()
 	{
-		llassert(sInitialized);
+		// llassert(sInitialized);
 		void* ptr;
 		apr_status_t result =
 		apr_threadkey_private_get(&ptr, mThreadKey);
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index f4fa8f1e61..7c90b946af 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -35,6 +35,7 @@
 #include "llunit.h"
 #include "llsd.h"
 #include "lltracerecording.h"
+#include "lltracethreadrecorder.h"
 
 #include <boost/bind.hpp>
 #include <queue>
@@ -167,52 +168,16 @@ U64 TimeBlock::countsPerSecond() // counts per second for the *64-bit* timer
 
 TimeBlock::TimeBlock(const char* name, bool open, TimeBlock* parent)
 :	TraceType(name),
-	mCollapsed(true),
-	mParent(NULL),
-	mNeedsSorting(false)
+	mCollapsed(true)
 {
 	setCollapsed(!open);
-
-	if (parent)
-	{
-		setParent(parent);
-	}
-	else
-	{
-		mParent = this;
-	}
 }
 
-void TimeBlock::setParent(TimeBlock* parent)
+TimeBlockTreeNode& TimeBlock::getTreeNode() const
 {
-	llassert_always(parent != this);
-	llassert_always(parent != NULL);
-
-	if (mParent)
-	{
-		//// subtract our accumulated from previous parent
-		//for (S32 i = 0; i < HISTORY_NUM; i++)
-		//{
-		//	mParent->mCountHistory[i] -= mCountHistory[i];
-		//}
-
-		//// subtract average timing from previous parent
-		//mParent->mCountAverage -= mCountAverage;
-
-		std::vector<TimeBlock*>& children = mParent->getChildren();
-		std::vector<TimeBlock*>::iterator found_it = std::find(children.begin(), children.end(), this);
-		if (found_it != children.end())
-		{
-			children.erase(found_it);
-		}
-	}
-
-	mParent = parent;
-	if (parent)
-	{
-		parent->getChildren().push_back(this);
-		parent->mNeedsSorting = true;
-	}
+	TimeBlockTreeNode* nodep = LLTrace::get_thread_recorder()->getTimeBlockTreeNode(getIndex());
+	llassert(nodep);
+	return *nodep;
 }
 
 // static
@@ -232,17 +197,17 @@ void TimeBlock::processTimes()
 
 		// bootstrap tree construction by attaching to last timer to be on stack
 		// when this timer was called
-		if (timer.mParent == &TimeBlock::getRootTimer())
+		if (timer.getParent() == &TimeBlock::getRootTimer())
 		{
-			TimeBlockAccumulator& accumulator = timer.getPrimaryAccumulator();
+			TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 
-			if (accumulator.mLastCaller)
+			if (accumulator->mLastCaller)
 			{
-				timer.setParent(accumulator.mLastCaller);
-				accumulator.mParent = accumulator.mLastCaller;
+				timer.setParent(accumulator->mLastCaller);
+				accumulator->mParent = accumulator->mLastCaller;
 			}
 			// no need to push up tree on first use, flag can be set spuriously
-			accumulator.mMoveUpTree = false;
+			accumulator->mMoveUpTree = false;
 		}
 	}
 
@@ -256,25 +221,25 @@ void TimeBlock::processTimes()
 		TimeBlock* timerp = *it;
 
 		// sort timers by time last called, so call graph makes sense
-		if (timerp->mNeedsSorting)
+		if (timerp->getTreeNode().mNeedsSorting)
 		{
-			std::sort(timerp->getChildren().begin(), timerp->getChildren().end(), SortTimerByName());
+			std::sort(timerp->beginChildren(), timerp->endChildren(), SortTimerByName());
 		}
 
 		// skip root timer
 		if (timerp != &TimeBlock::getRootTimer())
 		{
-			TimeBlockAccumulator& accumulator = timerp->getPrimaryAccumulator();
+			TimeBlockAccumulator* accumulator = timerp->getPrimaryAccumulator();
 
-			if (accumulator.mMoveUpTree)
+			if (accumulator->mMoveUpTree)
 			{
 				// since ancestors have already been visited, re-parenting 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());
-				accumulator.mParent = timerp->mParent;
-				accumulator.mMoveUpTree = false;
+				accumulator->mParent = timerp->getParent();
+				accumulator->mMoveUpTree = false;
 
 				// don't bubble up any ancestors until descendants are done bubbling up
 				// as ancestors may call this timer only on certain paths, so we want to resolve
@@ -286,15 +251,15 @@ void TimeBlock::processTimes()
 
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
 	BlockTimer* cur_timer = cur_data->mCurTimer;
-	TimeBlockAccumulator& accumulator = cur_data->mTimerData->getPrimaryAccumulator();
+	TimeBlockAccumulator* accumulator = cur_data->mTimerData->getPrimaryAccumulator();
 	// root defined by parent pointing to self
 	while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
 	{
 		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
 		U64 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
 		cur_data->mChildTime = 0;
-		accumulator.mSelfTimeCounter += self_time_delta;
-		accumulator.mTotalTimeCounter += cumulative_time_delta;
+		accumulator->mSelfTimeCounter += self_time_delta;
+		accumulator->mTotalTimeCounter += cumulative_time_delta;
 
 		cur_timer->mStartTime = cur_time;
 
@@ -316,10 +281,10 @@ void TimeBlock::processTimes()
 		++it)
 	{
 		TimeBlock& timer = *it;
-		TimeBlockAccumulator& accumulator = timer.getPrimaryAccumulator();
+		TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 
-		accumulator.mLastCaller = NULL;
-		accumulator.mMoveUpTree = false;
+		accumulator->mLastCaller = NULL;
+		accumulator->mMoveUpTree = false;
 	}
 
 	// traverse tree in DFS post order, or bottom up
@@ -338,19 +303,19 @@ void TimeBlock::processTimes()
 }
 
 
-std::vector<TimeBlock*>::const_iterator TimeBlock::beginChildren()
+std::vector<TimeBlock*>::iterator TimeBlock::beginChildren()
 { 
-	return mChildren.begin(); 
+	return getTreeNode().mChildren.begin(); 
 }
 
-std::vector<TimeBlock*>::const_iterator TimeBlock::endChildren()
+std::vector<TimeBlock*>::iterator TimeBlock::endChildren()
 {
-	return mChildren.end();
+	return getTreeNode().mChildren.end();
 }
 
 std::vector<TimeBlock*>& TimeBlock::getChildren()
 {
-	return mChildren;
+	return getTreeNode().mChildren;
 }
 
 //static
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 1e2e4b590f..4d820d0664 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -69,12 +69,14 @@ class TimeBlock
 public:
 	TimeBlock(const char* name, bool open = false, TimeBlock* parent = &getRootTimer());
 
-	TimeBlock* getParent() const { return mParent; }
-	void setParent(TimeBlock* parent);
+	TimeBlockTreeNode& getTreeNode() const;
+	TimeBlock* getParent() const { return getTreeNode().getParent(); }
+	void setParent(TimeBlock* parent) { getTreeNode().setParent(parent); }
 
+	typedef std::vector<TimeBlock*>::iterator child_iter;
 	typedef std::vector<TimeBlock*>::const_iterator child_const_iter;
-	child_const_iter beginChildren();
-	child_const_iter endChildren();
+	child_iter beginChildren();
+	child_iter endChildren();
 	std::vector<TimeBlock*>& getChildren();
 
 	void setCollapsed(bool collapsed)	{ mCollapsed = collapsed; }
@@ -244,11 +246,7 @@ public:
 	// call this once a frame to periodically log timers
 	static void logStats();
 
-	// tree structure, only updated from master trace thread
-	TimeBlock*					mParent;				// TimeBlock of caller(parent)
-	std::vector<TimeBlock*>		mChildren;				// TimeBlock of callees
-	bool						mCollapsed,				// don't show children
-								mNeedsSorting;			// sort children whenever child added
+	bool						mCollapsed;				// don't show children
 
 	// statics
 	static std::string							sLogName;
@@ -264,10 +262,10 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 	mStartTime = TimeBlock::getCPUClockCount64();
 
 	CurTimerData* cur_timer_data = TimeBlock::sCurTimerData.get();
-	TimeBlockAccumulator& accumulator = cur_timer_data->mTimerData->getPrimaryAccumulator();
-	accumulator.mActiveCount++;
+	TimeBlockAccumulator* accumulator = cur_timer_data->mTimerData->getPrimaryAccumulator();
+	accumulator->mActiveCount++;
 	// keep current parent as long as it is active when we are
-	accumulator.mMoveUpTree |= (accumulator.mParent->getPrimaryAccumulator().mActiveCount == 0);
+	accumulator->mMoveUpTree |= (accumulator->mParent->getPrimaryAccumulator()->mActiveCount == 0);
 
 	// store top of stack
 	mLastTimerData = *cur_timer_data;
@@ -283,16 +281,16 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 #if FAST_TIMER_ON
 	U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
 	CurTimerData* cur_timer_data = TimeBlock::sCurTimerData.get();
-	TimeBlockAccumulator& accumulator = cur_timer_data->mTimerData->getPrimaryAccumulator();
+	TimeBlockAccumulator* accumulator = cur_timer_data->mTimerData->getPrimaryAccumulator();
 
-	accumulator.mCalls++;
-	accumulator.mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
-	accumulator.mTotalTimeCounter += total_time;
-	accumulator.mActiveCount--;
+	accumulator->mCalls++;
+	accumulator->mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
+	accumulator->mTotalTimeCounter += total_time;
+	accumulator->mActiveCount--;
 
 	// store last caller to bootstrap tree creation
 	// do this in the destructor in case of recursion to get topmost caller
-	accumulator.mLastCaller = mLastTimerData.mTimerData;
+	accumulator->mLastCaller = mLastTimerData.mTimerData;
 
 	// we are only tracking self time, so subtract our total time delta from parents
 	mLastTimerData.mChildTime += total_time;
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index e11e39a1a2..9d0c93b352 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -66,5 +66,34 @@ LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
 	return s_thread_recorder;
 }
 
+TimeBlockTreeNode::TimeBlockTreeNode() 
+:	mBlock(NULL),
+	mParent(NULL),
+	mNeedsSorting(false)
+{}
+
+void TimeBlockTreeNode::setParent( TimeBlock* parent )
+{
+	llassert_always(parent != mBlock);
+	llassert_always(parent != NULL);
+
+	TimeBlockTreeNode* parent_tree_node = get_thread_recorder()->getTimeBlockTreeNode(parent->getIndex());
+	if (!parent_tree_node) return;
+
+	if (mParent)
+	{
+		std::vector<TimeBlock*>& children = mParent->getChildren();
+		std::vector<TimeBlock*>::iterator found_it = std::find(children.begin(), children.end(), mBlock);
+		if (found_it != children.end())
+		{
+			children.erase(found_it);
+		}
+	}
+
+	mParent = parent;
+	mBlock->getPrimaryAccumulator()->mParent = parent;
+	parent_tree_node->mChildren.push_back(mBlock);
+	parent_tree_node->mNeedsSorting = true;
 }
 
+}
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 5b5e2b7879..4bb19f6070 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -77,21 +77,21 @@ namespace LLTrace
 	template<typename ACCUMULATOR>
 	class AccumulatorBuffer : public LLRefCount
 	{
+		typedef AccumulatorBuffer<ACCUMULATOR> self_t;
 		static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64;
 	private:
-		enum StaticAllocationMarker { STATIC_ALLOC };
+		struct StaticAllocationMarker { };
 
 		AccumulatorBuffer(StaticAllocationMarker m)
 		:	mStorageSize(0),
 			mStorage(NULL),
 			mNextStorageSlot(0)
 		{
-			resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
 		}
 
 	public:
 
-		AccumulatorBuffer(const AccumulatorBuffer& other = getDefaultBuffer())
+		AccumulatorBuffer(const AccumulatorBuffer& other = *getDefaultBuffer())
 		:	mStorageSize(0),
 			mStorage(NULL),
 			mNextStorageSlot(other.mNextStorageSlot)
@@ -107,8 +107,7 @@ namespace LLTrace
 		{
 			if (sPrimaryStorage == mStorage)
 			{
-				//TODO pick another primary?
-				sPrimaryStorage = NULL;
+				sPrimaryStorage = getDefaultBuffer()->mStorage;
 			}
 			delete[] mStorage;
 		}
@@ -182,6 +181,8 @@ namespace LLTrace
 
 		void resize(size_t new_size)
 		{
+			if (new_size <= mStorageSize) return;
+
 			ACCUMULATOR* old_storage = mStorage;
 			mStorage = new ACCUMULATOR[new_size];
 			if (old_storage)
@@ -193,16 +194,33 @@ namespace LLTrace
 			}
 			mStorageSize = new_size;
 			delete[] old_storage;
+
+			self_t* default_buffer = getDefaultBuffer();
+			if (this != default_buffer
+				&& new_size > default_buffer->size())
+			{
+				//NB: this is not thread safe, but we assume that all resizing occurs during static initialization
+				default_buffer->resize(new_size);
+			}
 		}
 
-		size_t size()
+		size_t size() const
 		{
 			return mNextStorageSlot;
 		}
 
-		static AccumulatorBuffer<ACCUMULATOR>& getDefaultBuffer()
+		static self_t* getDefaultBuffer()
 		{
-			static AccumulatorBuffer sBuffer(STATIC_ALLOC);
+			// this buffer is allowed to leak so that trace calls from global destructors have somewhere to put their data
+			// so as not to trigger an access violation
+			//TODO: make this thread local but need to either demand-init apr or remove apr dependency
+			static self_t* sBuffer = new AccumulatorBuffer(StaticAllocationMarker());
+			static bool sInitialized = false;
+			if (!sInitialized)
+			{
+				sBuffer->resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
+				sInitialized = true;
+			}
 			return sBuffer;
 		}
 
@@ -233,13 +251,13 @@ namespace LLTrace
 			mName(name),
 			mDescription(description ? description : "")	
 		{
-			mAccumulatorIndex = AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer().reserveSlot();
+			mAccumulatorIndex = AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot();
 		}
 
-		LL_FORCE_INLINE ACCUMULATOR& getPrimaryAccumulator() const
+		LL_FORCE_INLINE ACCUMULATOR* getPrimaryAccumulator() const
 		{
 			ACCUMULATOR* accumulator_storage = AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage();
-			return accumulator_storage[mAccumulatorIndex];
+			return &accumulator_storage[mAccumulatorIndex];
 		}
 
 		size_t getIndex() const { return mAccumulatorIndex; }
@@ -472,6 +490,22 @@ namespace LLTrace
 		{}
 	};
 
+	class TimeBlock;
+	class TimeBlockTreeNode
+	{
+	public:
+		TimeBlockTreeNode();
+
+		void setParent(TimeBlock* parent);
+		TimeBlock* getParent() { return mParent; }
+
+		TimeBlock*					mBlock;
+		TimeBlock*					mParent;	
+		std::vector<TimeBlock*>		mChildren;
+		bool						mNeedsSorting;
+	};
+
+
 	template <typename T = F64>
 	class Measurement
 	:	public TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
@@ -488,7 +522,7 @@ namespace LLTrace
 		void sample(UNIT_T value)
 		{
 			T converted_value(value);
-			trace_t::getPrimaryAccumulator().sample(LLUnits::rawValue(converted_value));
+			trace_t::getPrimaryAccumulator()->sample(LLUnits::rawValue(converted_value));
 		}
 	};
 
@@ -508,7 +542,7 @@ namespace LLTrace
 		void add(UNIT_T value)
 		{
 			T converted_value(value);
-			trace_t::getPrimaryAccumulator().add(LLUnits::rawValue(converted_value));
+			trace_t::getPrimaryAccumulator()->add(LLUnits::rawValue(converted_value));
 		}
 	};
 
@@ -650,19 +684,25 @@ public:
 		// reserve 8 bytes for allocation size (and preserving 8 byte alignment of structs)
 		void* allocation = ::operator new(allocation_size + 8);
 		*(size_t*)allocation = allocation_size;
-		MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
-		accumulator.mSize += allocation_size;
-		accumulator.mAllocatedCount++;
+		MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+		if (accumulator)
+		{
+			accumulator->mSize += allocation_size;
+			accumulator->mAllocatedCount++;
+		}
 		return (void*)((char*)allocation + 8);
 	}
 
 	void operator delete(void* ptr)
 	{
 		size_t* allocation_size = (size_t*)((char*)ptr - 8);
-		MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
-		accumulator.mSize -= *allocation_size;
-		accumulator.mAllocatedCount--;
-		accumulator.mDeallocatedCount++;
+		MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+		if (accumulator)
+		{
+			accumulator->mSize -= *allocation_size;
+			accumulator->mAllocatedCount--;
+			accumulator->mDeallocatedCount++;
+		}
 		::delete((char*)ptr - 8);
 	}
 
@@ -670,19 +710,25 @@ public:
 	{
 		size_t* result = (size_t*)malloc(size + 8);
 		*result = size;
-		MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
-		accumulator.mSize += size;
-		accumulator.mAllocatedCount++;
+		MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+		if (accumulator)
+		{
+			accumulator->mSize += size;
+			accumulator->mAllocatedCount++;
+		}
 		return (void*)((char*)result + 8);
 	}
 
 	void operator delete[](void* ptr)
 	{
 		size_t* allocation_size = (size_t*)((char*)ptr - 8);
-		MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
-		accumulator.mSize -= *allocation_size;
-		accumulator.mAllocatedCount--;
-		accumulator.mDeallocatedCount++;
+		MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+		if (accumulator)
+		{
+			accumulator->mSize -= *allocation_size;
+			accumulator->mAllocatedCount--;
+			accumulator->mDeallocatedCount++;
+		}
 		::delete[]((char*)ptr - 8);
 	}
 
@@ -704,9 +750,12 @@ public:
 
 	void memClaim(size_t size)
 	{
-		MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
 		mMemFootprint += size;
-		accumulator.mSize += size;
+		if (accumulator)
+		{
+			accumulator->mSize += size;
+		}
 	}
 
 	// remove memory we had claimed from our calculated footprint
@@ -726,8 +775,11 @@ public:
 
 	void memDisclaim(size_t size)
 	{
-		MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
-		accumulator.mSize -= size;
+		MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+		if (accumulator)
+		{
+			accumulator->mSize -= size;
+		}
 		mMemFootprint -= size;
 	}
 
@@ -739,18 +791,24 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
-			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
-			accumulator.mSize += footprint;
-			tracker.mMemFootprint += footprint;
+			MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+			if (accumulator)
+			{
+				size_t footprint = MemFootprint<TRACKED>::measure(tracked);
+				accumulator->mSize += footprint;
+				tracker.mMemFootprint += footprint;
+			}
 		}
 
 		static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
-			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
-			accumulator.mSize -= footprint;
-			tracker.mMemFootprint -= footprint;
+			MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+			if (accumulator)
+			{
+				size_t footprint = MemFootprint<TRACKED>::measure(tracked);
+				accumulator->mSize -= footprint;
+				tracker.mMemFootprint -= footprint;
+			}
 		}
 	};
 
@@ -759,14 +817,20 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
-			accumulator.mChildSize += MemFootprint<TRACKED>::measure(tracked);
+			MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+			if (accumulator)
+			{
+				accumulator->mChildSize += MemFootprint<TRACKED>::measure(tracked);
+			}
 		}
 
 		static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = sStat.getPrimaryAccumulator();
-			accumulator.mChildSize -= MemFootprint<TRACKED>::measure(tracked);
+			MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+			if (accumulator)
+			{
+				accumulator->mChildSize -= MemFootprint<TRACKED>::measure(tracked);
+			}
 		}
 	};
 	static MemStat sStat;
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 40079f40f1..9dbafc4e82 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -122,6 +122,18 @@ void Recording::makePrimary()
 	mMeasurements.write()->makePrimary();
 	mStackTimers.write()->makePrimary();
 	mMemStats.write()->makePrimary();
+
+	ThreadRecorder* thread_recorder = get_thread_recorder().get();
+	AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = *mStackTimers.write();
+	// update stacktimer parent pointers
+	for (S32 i = 0, end_i = mStackTimers->size(); i < end_i; i++)
+	{
+		TimeBlockTreeNode* tree_node = thread_recorder->getTimeBlockTreeNode(i);
+		if (tree_node)
+		{
+			timer_accumulator_buffer[i].mParent = tree_node->mParent;
+		}
+	}
 }
 
 bool Recording::isPrimary() const
@@ -145,11 +157,21 @@ void Recording::appendRecording( const Recording& other )
 	mMeasurementsFloat.write()->addSamples(*other.mMeasurementsFloat);
 	mCounts.write()->addSamples(*other.mCounts);
 	mMeasurements.write()->addSamples(*other.mMeasurements);
-	mStackTimers.write()->addSamples(*other.mStackTimers);
 	mMemStats.write()->addSamples(*other.mMemStats);
+
+	mStackTimers.write()->addSamples(*other.mStackTimers);
 	mElapsedSeconds += other.mElapsedSeconds;
 }
 
+void Recording::mergeRecording( const Recording& other)
+{
+	mCountsFloat.write()->addSamples(*other.mCountsFloat);
+	mMeasurementsFloat.write()->addSamples(*other.mMeasurementsFloat);
+	mCounts.write()->addSamples(*other.mCounts);
+	mMeasurements.write()->addSamples(*other.mMeasurements);
+	mMemStats.write()->addSamples(*other.mMemStats);
+}
+
 LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) const
 {
 	return (F64)(*mStackTimers)[stat.getIndex()].mTotalTimeCounter / (F64)LLTrace::TimeBlock::countsPerSecond();
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 8e5f1125ec..f2d7d42211 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -114,8 +114,12 @@ namespace LLTrace
 
 		void makeUnique();
 
+		// accumulate data from subsequent, non-overlapping recording
 		void appendRecording(const Recording& other);
 
+		// gather data from recording, ignoring time relationship (for example, pulling data from slave threads)
+		void mergeRecording(const Recording& other);
+
 		void update();
 
 		// Timer accessors
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index c4144b4999..156b0ef26b 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -38,25 +38,37 @@ namespace LLTrace
 
 ThreadRecorder::ThreadRecorder()
 {
+	//NB: the ordering of initialization in this function is very fragile due to a large number of implicit dependencies
 	get_thread_recorder() = this;
-	mFullRecording.start();
 
 	mRootTimerData = new CurTimerData();
 	mRootTimerData->mTimerData = &TimeBlock::getRootTimer();
-
 	TimeBlock::sCurTimerData = mRootTimerData;
-	TimeBlock::getRootTimer().getPrimaryAccumulator().mActiveCount = 1;
 
-	// initialize parent pointers in time blocks
+	mNumTimeBlockTreeNodes = AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer()->size();
+	mTimeBlockTreeNodes = new TimeBlockTreeNode[mNumTimeBlockTreeNodes];
+
+	mFullRecording.start();
+
+	TimeBlock& root_timer = TimeBlock::getRootTimer();
+
+	// initialize time block parent pointers
 	for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(); 
 		it != end_it; 
 		++it)
 	{
-		it->getPrimaryAccumulator().mParent = it->mParent;
+		TimeBlock& time_block = *it;
+		TimeBlockTreeNode& tree_node = mTimeBlockTreeNodes[it->getIndex()];
+		tree_node.mBlock = &time_block;
+		tree_node.mParent = &root_timer;
+
+		it->getPrimaryAccumulator()->mParent = &root_timer;
 	}
 
-	mRootTimer = new BlockTimer(TimeBlock::getRootTimer());
+	mRootTimer = new BlockTimer(root_timer);
 	mRootTimerData->mCurTimer = mRootTimer;
+
+	TimeBlock::getRootTimer().getPrimaryAccumulator()->mActiveCount = 1;
 }
 
 ThreadRecorder::~ThreadRecorder()
@@ -70,8 +82,19 @@ ThreadRecorder::~ThreadRecorder()
 	get_thread_recorder() = NULL;
 	TimeBlock::sCurTimerData = NULL;
 	delete mRootTimerData;
+	delete[] mTimeBlockTreeNodes;
 }
 
+TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode(S32 index)
+{
+	if (0 <= index && index < mNumTimeBlockTreeNodes)
+	{
+		return &mTimeBlockTreeNodes[index];
+	}
+	return NULL;
+}
+
+
 void ThreadRecorder::activate( Recording* recording )
 {
 	mActiveRecordings.push_front(ActiveRecording(recording));
@@ -113,6 +136,13 @@ std::list<ThreadRecorder::ActiveRecording>::iterator ThreadRecorder::update( Rec
 	return it;
 }
 
+AccumulatorBuffer<CountAccumulator<F64> > 		gCountsFloat;
+AccumulatorBuffer<MeasurementAccumulator<F64> >	gMeasurementsFloat;
+AccumulatorBuffer<CountAccumulator<S64> >		gCounts;
+AccumulatorBuffer<MeasurementAccumulator<S64> >	gMeasurements;
+AccumulatorBuffer<TimeBlockAccumulator>			gStackTimers;
+AccumulatorBuffer<MemStatAccumulator>			gMemStats;
+
 void ThreadRecorder::deactivate( Recording* recording )
 {
 	std::list<ActiveRecording>::iterator it = update(recording);
@@ -169,23 +199,42 @@ void SlaveThreadRecorder::pushToMaster()
 	mFullRecording.stop();
 	{
 		LLMutexLock(getMasterThreadRecorder().getSlaveListMutex());
-		mSharedData.copyFrom(mFullRecording);
+		mSharedData.appendFrom(mFullRecording);
 	}
 	mFullRecording.start();
 }
 
-void SlaveThreadRecorder::SharedData::copyFrom( const Recording& source )
+void SlaveThreadRecorder::SharedData::appendFrom( const Recording& source )
 {
 	LLMutexLock lock(&mRecordingMutex);
 	mRecording.appendRecording(source);
 }
 
-void SlaveThreadRecorder::SharedData::copyTo( Recording& sink )
+void SlaveThreadRecorder::SharedData::appendTo( Recording& sink )
 {
 	LLMutexLock lock(&mRecordingMutex);
 	sink.appendRecording(mRecording);
 }
 
+void SlaveThreadRecorder::SharedData::mergeFrom( const Recording& source )
+{
+	LLMutexLock lock(&mRecordingMutex);
+	mRecording.mergeRecording(source);
+}
+
+void SlaveThreadRecorder::SharedData::mergeTo( Recording& sink )
+{
+	LLMutexLock lock(&mRecordingMutex);
+	sink.mergeRecording(mRecording);
+}
+
+void SlaveThreadRecorder::SharedData::reset()
+{
+	LLMutexLock lock(&mRecordingMutex);
+	mRecording.reset();
+}
+
+
 ///////////////////////////////////////////////////////////////////////
 // MasterThreadRecorder
 ///////////////////////////////////////////////////////////////////////
@@ -203,7 +252,9 @@ void MasterThreadRecorder::pullFromSlaveThreads()
 		it != end_it;
 		++it)
 	{
-		(*it)->mSharedData.copyTo(target_recording);
+		// ignore block timing info for now
+		(*it)->mSharedData.mergeTo(target_recording);
+		(*it)->mSharedData.reset();
 	}
 }
 
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 102b980e44..d09527eced 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -50,6 +50,8 @@ namespace LLTrace
 
 		virtual void pushToMaster() = 0;
 
+		TimeBlockTreeNode* getTimeBlockTreeNode(S32 index);
+
 	protected:
 		struct ActiveRecording
 		{
@@ -64,7 +66,9 @@ namespace LLTrace
 		std::list<ActiveRecording>	mActiveRecordings;
 
 		struct CurTimerData*	mRootTimerData;
-		class BlockTimer*				mRootTimer;
+		class BlockTimer*		mRootTimer;
+		TimeBlockTreeNode*		mTimeBlockTreeNodes;
+		size_t					mNumTimeBlockTreeNodes;
 	};
 
 	class LL_COMMON_API MasterThreadRecorder : public ThreadRecorder
@@ -104,8 +108,11 @@ namespace LLTrace
 		class SharedData
 		{
 		public:
-			void copyFrom(const Recording& source);
-			void copyTo(Recording& sink);
+			void appendFrom(const Recording& source);
+			void appendTo(Recording& sink);
+			void mergeFrom(const Recording& source);
+			void mergeTo(Recording& sink);
+			void reset();
 		private:
 			LLMutex		mRecordingMutex;
 			Recording	mRecording;
-- 
cgit v1.2.3


From 3fd640a6e3dea7a3551c239323d782fb082e1dbd Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sun, 23 Dec 2012 12:27:25 -0800
Subject: SH-3468 WIP add memory tracking base class fixed crash on exit by
 making LLInstanceTracker iterators use atomic iterator nesting count for
 thread safety

---
 indra/llcommon/llapr.cpp              |   1 +
 indra/llcommon/llapr.h                | 137 ++--------------------------
 indra/llcommon/llinstancetracker.cpp  |  18 ++++
 indra/llcommon/llinstancetracker.h    |  27 +++---
 indra/llcommon/llstl.h                |   1 +
 indra/llcommon/llthreadlocalpointer.h | 164 ++++++++++++++++++++++++++++++++++
 indra/llcommon/lltrace.h              |   1 +
 indra/llcommon/llworkerthread.h       |   5 +-
 8 files changed, 209 insertions(+), 145 deletions(-)
 create mode 100644 indra/llcommon/llthreadlocalpointer.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 6affdad61b..092c276936 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -29,6 +29,7 @@
 #include "linden_common.h"
 #include "llapr.h"
 #include "apr_dso.h"
+#include "llthreadlocalpointer.h"
 
 apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
 LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool.
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 2faf4aad2d..b3c9bfd58c 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -42,7 +42,6 @@
 #include "apr_atomic.h"
 
 #include "llstring.h"
-#include "llinstancetracker.h"
 
 extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
 extern apr_thread_mutex_t* gCallStacksLogMutexp;
@@ -170,14 +169,17 @@ public:
 	LLAtomic32<Type>(Type x) {apr_atomic_set32(&mData, apr_uint32_t(x)); };
 	~LLAtomic32<Type>() {};
 
-	operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); }
+	operator const Type() { return get(); }
 	Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); }
 	void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); }
 	void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); }
 	Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++
-	Type operator --(int) { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise)
+	Type operator ++()	  { apr_atomic_inc32(&mData); return get();  } // ++Type
+	Type operator --(int) { const Type result(get()); apr_atomic_dec32(&mData); return result; } // Type-- 
+	Type operator --()	  { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise)
 	
 private:
+	const Type get() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); }
 	apr_uint32_t mData;
 };
 
@@ -262,134 +264,5 @@ public:
 //*******************************************************************************************************************************
 };
 
-class LLThreadLocalPointerBase : public LLInstanceTracker<LLThreadLocalPointerBase>
-{
-public:
-	LLThreadLocalPointerBase()
-	:	mThreadKey(NULL)
-	{
-		if (sInitialized)
-		{
-			initStorage();
-		}
-	}
-
-	LLThreadLocalPointerBase( const LLThreadLocalPointerBase& other)
-		:	mThreadKey(NULL)
-	{
-		if (sInitialized)
-		{
-			initStorage();
-		}
-	}
-
-	~LLThreadLocalPointerBase()
-	{
-		destroyStorage();
-	}
-
-	static void initAllThreadLocalStorage();
-	static void destroyAllThreadLocalStorage();
-
-protected:
-	void set(void* value);
-
-	LL_FORCE_INLINE void* get()
-	{
-		// llassert(sInitialized);
-		void* ptr;
-		apr_status_t result =
-		apr_threadkey_private_get(&ptr, mThreadKey);
-		if (result != APR_SUCCESS)
-		{
-			ll_apr_warn_status(result);
-			llerrs << "Failed to get thread local data" << llendl;
-		}
-		return ptr;
-	}
-
-	LL_FORCE_INLINE const void* get() const
-	{
-		void* ptr;
-		apr_status_t result =
-		apr_threadkey_private_get(&ptr, mThreadKey);
-		if (result != APR_SUCCESS)
-		{
-			ll_apr_warn_status(result);
-			llerrs << "Failed to get thread local data" << llendl;
-		}
-		return ptr;
-	}
-
-	void initStorage();
-	void destroyStorage();
-
-protected:
-	apr_threadkey_t* mThreadKey;
-	static bool		sInitialized;
-};
-
-template <typename T>
-class LLThreadLocalPointer : public LLThreadLocalPointerBase
-{
-public:
-
-	LLThreadLocalPointer()
-	{}
-
-	explicit LLThreadLocalPointer(T* value)
-	{
-		set(value);
-	}
-
-
-	LLThreadLocalPointer(const LLThreadLocalPointer<T>& other)
-	:	LLThreadLocalPointerBase(other)
-	{
-		set(other.get());		
-	}
-
-	LL_FORCE_INLINE T* get()
-	{
-		return (T*)LLThreadLocalPointerBase::get();
-	}
-
-	const T* get() const
-	{
-		return (const T*)LLThreadLocalPointerBase::get();
-	}
-
-	T* operator -> ()
-	{
-		return (T*)get();
-	}
-
-	const T* operator -> () const
-	{
-		return (T*)get();
-	}
-
-	T& operator*()
-	{
-		return *(T*)get();
-	}
-
-	const T& operator*() const
-	{
-		return *(T*)get();
-	}
-
-	LLThreadLocalPointer<T>& operator = (T* value)
-	{
-		set((void*)value);
-		return *this;
-	}
-
-	bool operator ==(T* other)
-	{
-		if (!sInitialized) return false;
-		return get() == other;
-	}
-};
 
 #endif // LL_LLAPR_H
diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp
index 5dc3ea5d7b..071a637cda 100644
--- a/indra/llcommon/llinstancetracker.cpp
+++ b/indra/llcommon/llinstancetracker.cpp
@@ -27,6 +27,8 @@
 #include "linden_common.h"
 // associated header
 #include "llinstancetracker.h"
+#include "llapr.h"
+
 // STL headers
 // std headers
 // external library headers
@@ -47,3 +49,19 @@ void * & LLInstanceTrackerBase::getInstances(std::type_info const & info)
 													 InstancesMap::mapped_type()))
 		.first->second;
 }
+
+void LLInstanceTrackerBase::StaticBase::incrementDepth()
+{
+	apr_atomic_inc32(&sIterationNestDepth);
+}
+
+void LLInstanceTrackerBase::StaticBase::decrementDepth()
+{
+	apr_atomic_dec32(&sIterationNestDepth);
+}
+
+U32 LLInstanceTrackerBase::StaticBase::getDepth()
+{
+	apr_uint32_t data = apr_atomic_read32(&sIterationNestDepth);
+	return data;
+}
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 3a1187a4c1..9dd6d4a7ed 100644
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -70,7 +70,12 @@ protected:
         StaticBase():
             sIterationNestDepth(0)
         {}
-        S32 sIterationNestDepth;
+
+		void incrementDepth();
+		void decrementDepth();
+		U32 getDepth();
+	private:
+		U32 sIterationNestDepth;
     };
 };
 
@@ -99,12 +104,12 @@ public:
 		instance_iter(const typename InstanceMap::iterator& it)
 		:	mIterator(it)
 		{
-			++getStatic().sIterationNestDepth;
+			getStatic().incrementDepth();
 		}
 
 		~instance_iter()
 		{
-			--getStatic().sIterationNestDepth;
+			getStatic().decrementDepth();
 		}
 
 
@@ -133,18 +138,18 @@ public:
 		key_iter(typename InstanceMap::iterator it)
 			:	mIterator(it)
 		{
-			++getStatic().sIterationNestDepth;
+			getStatic().incrementDepth();
 		}
 
 		key_iter(const key_iter& other)
 			:	mIterator(other.mIterator)
 		{
-			++getStatic().sIterationNestDepth;
+			getStatic().incrementDepth();
 		}
 
 		~key_iter()
 		{
-			--getStatic().sIterationNestDepth;
+			getStatic().decrementDepth();
 		}
 
 
@@ -203,7 +208,7 @@ protected:
 	virtual ~LLInstanceTracker() 
 	{ 
 		// it's unsafe to delete instances of this type while all instances are being iterated over.
-		llassert_always(getStatic().sIterationNestDepth == 0);
+		llassert_always(getStatic().getDepth() == 0);
 		remove_();		
 	}
 	virtual void setKey(KEY key) { remove_(); add_(key); }
@@ -262,18 +267,18 @@ public:
 		instance_iter(const typename InstanceSet::iterator& it)
 		:	mIterator(it)
 		{
-			++getStatic().sIterationNestDepth;
+			getStatic().incrementDepth();
 		}
 
 		instance_iter(const instance_iter& other)
 		:	mIterator(other.mIterator)
 		{
-			++getStatic().sIterationNestDepth;
+			getStatic().incrementDepth();
 		}
 
 		~instance_iter()
 		{
-			--getStatic().sIterationNestDepth;
+			getStatic().decrementDepth();
 		}
 
 	private:
@@ -306,7 +311,7 @@ protected:
 	virtual ~LLInstanceTracker()
 	{
 		// it's unsafe to delete instances of this type while all instances are being iterated over.
-		llassert_always(getStatic().sIterationNestDepth == 0);
+		llassert_always(getStatic().getDepth() == 0);
 		getSet_().erase(static_cast<T*>(this));
 	}
 
diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h
index d3941e1bc9..424138dad1 100644
--- a/indra/llcommon/llstl.h
+++ b/indra/llcommon/llstl.h
@@ -31,6 +31,7 @@
 #include <algorithm>
 #include <map>
 #include <vector>
+#include <list>
 #include <set>
 #include <deque>
 #include <typeinfo>
diff --git a/indra/llcommon/llthreadlocalpointer.h b/indra/llcommon/llthreadlocalpointer.h
new file mode 100644
index 0000000000..d40a8b5a27
--- /dev/null
+++ b/indra/llcommon/llthreadlocalpointer.h
@@ -0,0 +1,164 @@
+/** 
+ * @file llthreadlocalpointer.h
+ * @author Richard
+ * @brief Pointer class that manages a distinct value per thread
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTHREADLOCALPOINTER_H
+#define LL_LLTHREADLOCALPOINTER_H
+
+#include "llinstancetracker.h"
+#include "llapr.h"
+
+class LLThreadLocalPointerBase : public LLInstanceTracker<LLThreadLocalPointerBase>
+{
+public:
+	LLThreadLocalPointerBase()
+	:	mThreadKey(NULL)
+	{
+		if (sInitialized)
+		{
+			initStorage();
+		}
+	}
+
+	LLThreadLocalPointerBase( const LLThreadLocalPointerBase& other)
+		:	mThreadKey(NULL)
+	{
+		if (sInitialized)
+		{
+			initStorage();
+		}
+	}
+
+	~LLThreadLocalPointerBase()
+	{
+		destroyStorage();
+	}
+
+	static void initAllThreadLocalStorage();
+	static void destroyAllThreadLocalStorage();
+
+protected:
+	void set(void* value);
+
+	LL_FORCE_INLINE void* get()
+	{
+		// llassert(sInitialized);
+		void* ptr;
+		apr_status_t result =
+		apr_threadkey_private_get(&ptr, mThreadKey);
+		if (result != APR_SUCCESS)
+		{
+			ll_apr_warn_status(result);
+			llerrs << "Failed to get thread local data" << llendl;
+		}
+		return ptr;
+	}
+
+	LL_FORCE_INLINE const void* get() const
+	{
+		void* ptr;
+		apr_status_t result =
+		apr_threadkey_private_get(&ptr, mThreadKey);
+		if (result != APR_SUCCESS)
+		{
+			ll_apr_warn_status(result);
+			llerrs << "Failed to get thread local data" << llendl;
+		}
+		return ptr;
+	}
+
+	void initStorage();
+	void destroyStorage();
+
+protected:
+	apr_threadkey_t* mThreadKey;
+	static bool		sInitialized;
+};
+
+template <typename T>
+class LLThreadLocalPointer : public LLThreadLocalPointerBase
+{
+public:
+
+	LLThreadLocalPointer()
+	{}
+
+	explicit LLThreadLocalPointer(T* value)
+	{
+		set(value);
+	}
+
+
+	LLThreadLocalPointer(const LLThreadLocalPointer<T>& other)
+	:	LLThreadLocalPointerBase(other)
+	{
+		set(other.get());		
+	}
+
+	LL_FORCE_INLINE T* get()
+	{
+		return (T*)LLThreadLocalPointerBase::get();
+	}
+
+	const T* get() const
+	{
+		return (const T*)LLThreadLocalPointerBase::get();
+	}
+
+	T* operator -> ()
+	{
+		return (T*)get();
+	}
+
+	const T* operator -> () const
+	{
+		return (T*)get();
+	}
+
+	T& operator*()
+	{
+		return *(T*)get();
+	}
+
+	const T& operator*() const
+	{
+		return *(T*)get();
+	}
+
+	LLThreadLocalPointer<T>& operator = (T* value)
+	{
+		set((void*)value);
+		return *this;
+	}
+
+	bool operator ==(T* other)
+	{
+		if (!sInitialized) return false;
+		return get() == other;
+	}
+};
+
+#endif // LL_LLTHREADLOCALPOINTER_H
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 4bb19f6070..05191cafaa 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -34,6 +34,7 @@
 #include "llrefcount.h"
 #include "llunit.h"
 #include "llapr.h"
+#include "llthreadlocalpointer.h"
 
 #include <list>
 
diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h
index be46394d6e..09776816a8 100644
--- a/indra/llcommon/llworkerthread.h
+++ b/indra/llcommon/llworkerthread.h
@@ -26,10 +26,11 @@
 #ifndef LL_LLWORKERTHREAD_H
 #define LL_LLWORKERTHREAD_H
 
-#include <queue>
-#include <string>
+#include <list>
 #include <map>
+#include <queue>
 #include <set>
+#include <string>
 
 #include "llqueuedthread.h"
 #include "llapr.h"
-- 
cgit v1.2.3


From cda2cdda511eb2f7a58e284db2c852fd4a3808ae Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 3 Jan 2013 00:30:54 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system made fast timer
 stack thread local added LLThreadLocalSingleton made LLThreadLocalPointer
 obey pointer rules for const added LLThreadLocalSingletonPointer for fast
 thread local pointers

---
 indra/llcommon/CMakeLists.txt            |   1 +
 indra/llcommon/llapr.cpp                 |   2 +-
 indra/llcommon/llfasttimer.cpp           |  41 +++--
 indra/llcommon/llfasttimer.h             |  45 ++++--
 indra/llcommon/llsingleton.h             |  52 ++++---
 indra/llcommon/llthreadlocalpointer.h    | 164 --------------------
 indra/llcommon/llthreadlocalstorage.h    | 254 +++++++++++++++++++++++++++++++
 indra/llcommon/lltrace.cpp               |  13 +-
 indra/llcommon/lltrace.h                 |  32 ++--
 indra/llcommon/lltracethreadrecorder.cpp |  33 ++--
 indra/llcommon/lltracethreadrecorder.h   |   9 +-
 11 files changed, 380 insertions(+), 266 deletions(-)
 delete mode 100644 indra/llcommon/llthreadlocalpointer.h
 create mode 100644 indra/llcommon/llthreadlocalstorage.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 5b76703af7..6f5fe1832a 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -242,6 +242,7 @@ set(llcommon_HEADER_FILES
     llstringtable.h
     llsys.h
     llthread.h
+    llthreadlocalstorage.h
     llthreadsafequeue.h
     lltimer.h
     lltrace.h
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 092c276936..d911f258b6 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -29,7 +29,7 @@
 #include "linden_common.h"
 #include "llapr.h"
 #include "apr_dso.h"
-#include "llthreadlocalpointer.h"
+#include "llthreadlocalstorage.h"
 
 apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
 LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool.
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 7c90b946af..ad8cf7296e 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -70,8 +70,6 @@ U64         TimeBlock::sClockResolution = 1000000000; // Nanosecond resolution
 U64         TimeBlock::sClockResolution = 1000000; // Microsecond resolution
 #endif
 
-LLThreadLocalPointer<CurTimerData> TimeBlock::sCurTimerData;
-
 static LLMutex*			sLogLock = NULL;
 static std::queue<LLSD> sLogQueue;
 
@@ -118,7 +116,7 @@ struct SortTimerByName
 	}
 };
 
-TimeBlock& TimeBlock::getRootTimer()
+TimeBlock& TimeBlock::getRootTimeBlock()
 {
 	static TimeBlock root_timer("root", true, NULL);
 	return root_timer;
@@ -185,7 +183,7 @@ void TimeBlock::processTimes()
 {
 	get_clock_count(); // good place to calculate clock frequency
 	U64 cur_time = getCPUClockCount64();
-	CurTimerData* cur_data = sCurTimerData.get();
+	BlockTimerStackRecord* stack_record = ThreadTimerStack::getInstance();
 
 	// set up initial tree
 	for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(); 
@@ -193,11 +191,11 @@ void TimeBlock::processTimes()
 		++it)
 	{
 		TimeBlock& timer = *it;
-		if (&timer == &TimeBlock::getRootTimer()) continue;
+		if (&timer == &TimeBlock::getRootTimeBlock()) continue;
 
 		// bootstrap tree construction by attaching to last timer to be on stack
 		// when this timer was called
-		if (timer.getParent() == &TimeBlock::getRootTimer())
+		if (timer.getParent() == &TimeBlock::getRootTimeBlock())
 		{
 			TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 
@@ -214,20 +212,21 @@ void TimeBlock::processTimes()
 	// bump timers up tree if they have 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(TimeBlock::getRootTimer());
+	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(TimeBlock::getRootTimeBlock());
 		it != end_timer_tree_bottom_up();
 		++it)
 	{
 		TimeBlock* timerp = *it;
 
 		// sort timers by time last called, so call graph makes sense
-		if (timerp->getTreeNode().mNeedsSorting)
+		TimeBlockTreeNode& tree_node = timerp->getTreeNode();
+		if (tree_node.mNeedsSorting)
 		{
-			std::sort(timerp->beginChildren(), timerp->endChildren(), SortTimerByName());
+			std::sort(tree_node.mChildren.begin(), tree_node.mChildren.end(), SortTimerByName());
 		}
 
 		// skip root timer
-		if (timerp != &TimeBlock::getRootTimer())
+		if (timerp != &TimeBlock::getRootTimeBlock())
 		{
 			TimeBlockAccumulator* accumulator = timerp->getPrimaryAccumulator();
 
@@ -250,27 +249,27 @@ void TimeBlock::processTimes()
 	}
 
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
-	BlockTimer* cur_timer = cur_data->mCurTimer;
-	TimeBlockAccumulator* accumulator = cur_data->mTimerData->getPrimaryAccumulator();
+	BlockTimer* cur_timer = stack_record->mActiveTimer;
+	TimeBlockAccumulator* accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
 	// root defined by parent pointing to self
-	while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
+	while(cur_timer && cur_timer->mLastTimerData.mActiveTimer != cur_timer)
 	{
 		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
-		U64 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
-		cur_data->mChildTime = 0;
+		U64 self_time_delta = cumulative_time_delta - stack_record->mChildTime;
+		stack_record->mChildTime = 0;
 		accumulator->mSelfTimeCounter += self_time_delta;
 		accumulator->mTotalTimeCounter += cumulative_time_delta;
 
 		cur_timer->mStartTime = cur_time;
 
-		cur_data = &cur_timer->mLastTimerData;
-		cur_data->mChildTime += cumulative_time_delta;
-		if (cur_data->mTimerData)
+		stack_record = &cur_timer->mLastTimerData;
+		stack_record->mChildTime += cumulative_time_delta;
+		if (stack_record->mTimeBlock)
 		{
-			accumulator = cur_data->mTimerData->getPrimaryAccumulator();
+			accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
 		}
 
-		cur_timer = cur_timer->mLastTimerData.mCurTimer;
+		cur_timer = cur_timer->mLastTimerData.mActiveTimer;
 	}
 
 
@@ -374,7 +373,7 @@ void TimeBlock::dumpCurTimes()
 	LLTrace::Recording& last_frame_recording = frame_recording.getLastRecordingPeriod();
 
 	// walk over timers in depth order and output timings
-	for(timer_tree_dfs_iterator_t it = begin_timer_tree(TimeBlock::getRootTimer());
+	for(timer_tree_dfs_iterator_t it = begin_timer_tree(TimeBlock::getRootTimeBlock());
 		it != end_timer_tree();
 		++it)
 	{
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 4d820d0664..995eebd16a 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -38,13 +38,29 @@ class LLMutex;
 namespace LLTrace
 {
 
-struct CurTimerData
+struct BlockTimerStackRecord
 {
-	class BlockTimer*	mCurTimer;
-	class TimeBlock*	mTimerData;
+	class BlockTimer*	mActiveTimer;
+	class TimeBlock*	mTimeBlock;
 	U64					mChildTime;
 };
 
+class ThreadTimerStack 
+:	public BlockTimerStackRecord, 
+	public LLThreadLocalSingleton<ThreadTimerStack>
+{
+	friend LLThreadLocalSingleton<ThreadTimerStack>;
+	ThreadTimerStack() 
+	{}
+
+public:
+	ThreadTimerStack& operator=(const BlockTimerStackRecord& other)
+	{
+		BlockTimerStackRecord::operator=(other);
+		return *this;
+	}
+};
+
 class BlockTimer
 {
 public:
@@ -58,7 +74,7 @@ public:
 private:
 
 	U64				mStartTime;
-	CurTimerData	mLastTimerData;
+	BlockTimerStackRecord	mLastTimerData;
 };
 
 // stores a "named" timer instance to be reused via multiple BlockTimer stack instances
@@ -67,7 +83,7 @@ class TimeBlock
 	public LLInstanceTracker<TimeBlock>
 {
 public:
-	TimeBlock(const char* name, bool open = false, TimeBlock* parent = &getRootTimer());
+	TimeBlock(const char* name, bool open = false, TimeBlock* parent = &getRootTimeBlock());
 
 	TimeBlockTreeNode& getTreeNode() const;
 	TimeBlock* getParent() const { return getTreeNode().getParent(); }
@@ -92,7 +108,7 @@ public:
 		return static_cast<TraceType<TimeBlockAccumulator::SelfTimeAspect>&>(*(TraceType<TimeBlockAccumulator>*)this);
 	}
 
-	static TimeBlock& getRootTimer();
+	static TimeBlock& getRootTimeBlock();
 	static void pushLog(LLSD sd);
 	static void setLogLock(LLMutex* mutex);
 	static void writeLog(std::ostream& os);
@@ -252,7 +268,6 @@ public:
 	static std::string							sLogName;
 	static bool									sMetricLog,
 												sLog;	
-	static LLThreadLocalPointer<CurTimerData>	sCurTimerData;
 	static U64									sClockResolution;
 };
 
@@ -261,8 +276,8 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 #if FAST_TIMER_ON
 	mStartTime = TimeBlock::getCPUClockCount64();
 
-	CurTimerData* cur_timer_data = TimeBlock::sCurTimerData.get();
-	TimeBlockAccumulator* accumulator = cur_timer_data->mTimerData->getPrimaryAccumulator();
+	BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
+	TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
 	accumulator->mActiveCount++;
 	// keep current parent as long as it is active when we are
 	accumulator->mMoveUpTree |= (accumulator->mParent->getPrimaryAccumulator()->mActiveCount == 0);
@@ -270,8 +285,8 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 	// store top of stack
 	mLastTimerData = *cur_timer_data;
 	// push new information
-	cur_timer_data->mCurTimer = this;
-	cur_timer_data->mTimerData = &timer;
+	cur_timer_data->mActiveTimer = this;
+	cur_timer_data->mTimeBlock = &timer;
 	cur_timer_data->mChildTime = 0;
 #endif
 }
@@ -280,8 +295,8 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 {
 #if FAST_TIMER_ON
 	U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
-	CurTimerData* cur_timer_data = TimeBlock::sCurTimerData.get();
-	TimeBlockAccumulator* accumulator = cur_timer_data->mTimerData->getPrimaryAccumulator();
+	BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
+	TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
 
 	accumulator->mCalls++;
 	accumulator->mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
@@ -290,12 +305,12 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 
 	// store last caller to bootstrap tree creation
 	// do this in the destructor in case of recursion to get topmost caller
-	accumulator->mLastCaller = mLastTimerData.mTimerData;
+	accumulator->mLastCaller = mLastTimerData.mTimeBlock;
 
 	// we are only tracking self time, so subtract our total time delta from parents
 	mLastTimerData.mChildTime += total_time;
 
-	*TimeBlock::sCurTimerData = mLastTimerData;
+	*ThreadTimerStack::getIfExists() = mLastTimerData;
 #endif
 }
 
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 49d99f2cd0..f6b0a7194b 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -90,7 +90,7 @@ template <typename DERIVED_TYPE>
 class LLSingleton : private boost::noncopyable
 {
 	
-private:
+protected:
 	typedef enum e_init_state
 	{
 		UNINITIALIZED,
@@ -124,7 +124,7 @@ private:
 public:
 	virtual ~LLSingleton()
 	{
-		SingletonInstanceData& data = getData();
+		SingletonInstanceData& data = getSingletonData();
 		data.mSingletonInstance = NULL;
 		data.mInitState = DELETED;
 	}
@@ -151,29 +151,15 @@ public:
 	 */
 	static void deleteSingleton()
 	{
-		delete getData().mSingletonInstance;
-		getData().mSingletonInstance = NULL;
-		getData().mInitState = DELETED;
-	}
-
-	static SingletonInstanceData& getData()
-	{
-		// this is static to cache the lookup results
-		static void * & registry = LLSingletonRegistry::get<DERIVED_TYPE>();
-
-		// *TODO - look into making this threadsafe
-		if(NULL == registry)
-		{
-			static SingletonInstanceData data;
-			registry = &data;
-		}
-
-		return *static_cast<SingletonInstanceData *>(registry);
+		SingletonInstanceData& data = getSingletonData();
+		delete data.mSingletonInstance;
+		data.mSingletonInstance = NULL;
+		data.mInitState = DELETED;
 	}
 
 	static DERIVED_TYPE* getInstance()
 	{
-		SingletonInstanceData& data = getData();
+		SingletonInstanceData& data = getSingletonData();
 
 		if (data.mInitState == CONSTRUCTING)
 		{
@@ -197,6 +183,12 @@ public:
 		return data.mSingletonInstance;
 	}
 
+	static DERIVED_TYPE* getIfExists()
+	{
+		SingletonInstanceData& data = getSingletonData();
+		return data.mSingletonInstance;
+	}
+
 	// Reference version of getInstance()
 	// Preferred over getInstance() as it disallows checking for NULL
 	static DERIVED_TYPE& instance()
@@ -208,17 +200,31 @@ public:
 	// Use this to avoid accessing singletons before the can safely be constructed
 	static bool instanceExists()
 	{
-		return getData().mInitState == INITIALIZED;
+		return getSingletonData().mInitState == INITIALIZED;
 	}
 	
 	// Has this singleton already been deleted?
 	// Use this to avoid accessing singletons from a static object's destructor
 	static bool destroyed()
 	{
-		return getData().mInitState == DELETED;
+		return getSingletonData().mInitState == DELETED;
 	}
 
 private:
+	static SingletonInstanceData& getSingletonData()
+	{
+		// this is static to cache the lookup results
+		static void * & registry = LLSingletonRegistry::get<DERIVED_TYPE>();
+
+		// *TODO - look into making this threadsafe
+		if(NULL == registry)
+		{
+			static SingletonInstanceData data;
+			registry = &data;
+		}
+
+		return *static_cast<SingletonInstanceData *>(registry);
+	}
 	virtual void initSingleton() {}
 };
 
diff --git a/indra/llcommon/llthreadlocalpointer.h b/indra/llcommon/llthreadlocalpointer.h
deleted file mode 100644
index d40a8b5a27..0000000000
--- a/indra/llcommon/llthreadlocalpointer.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/** 
- * @file llthreadlocalpointer.h
- * @author Richard
- * @brief Pointer class that manages a distinct value per thread
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLTHREADLOCALPOINTER_H
-#define LL_LLTHREADLOCALPOINTER_H
-
-#include "llinstancetracker.h"
-#include "llapr.h"
-
-class LLThreadLocalPointerBase : public LLInstanceTracker<LLThreadLocalPointerBase>
-{
-public:
-	LLThreadLocalPointerBase()
-	:	mThreadKey(NULL)
-	{
-		if (sInitialized)
-		{
-			initStorage();
-		}
-	}
-
-	LLThreadLocalPointerBase( const LLThreadLocalPointerBase& other)
-		:	mThreadKey(NULL)
-	{
-		if (sInitialized)
-		{
-			initStorage();
-		}
-	}
-
-	~LLThreadLocalPointerBase()
-	{
-		destroyStorage();
-	}
-
-	static void initAllThreadLocalStorage();
-	static void destroyAllThreadLocalStorage();
-
-protected:
-	void set(void* value);
-
-	LL_FORCE_INLINE void* get()
-	{
-		// llassert(sInitialized);
-		void* ptr;
-		apr_status_t result =
-		apr_threadkey_private_get(&ptr, mThreadKey);
-		if (result != APR_SUCCESS)
-		{
-			ll_apr_warn_status(result);
-			llerrs << "Failed to get thread local data" << llendl;
-		}
-		return ptr;
-	}
-
-	LL_FORCE_INLINE const void* get() const
-	{
-		void* ptr;
-		apr_status_t result =
-		apr_threadkey_private_get(&ptr, mThreadKey);
-		if (result != APR_SUCCESS)
-		{
-			ll_apr_warn_status(result);
-			llerrs << "Failed to get thread local data" << llendl;
-		}
-		return ptr;
-	}
-
-	void initStorage();
-	void destroyStorage();
-
-protected:
-	apr_threadkey_t* mThreadKey;
-	static bool		sInitialized;
-};
-
-template <typename T>
-class LLThreadLocalPointer : public LLThreadLocalPointerBase
-{
-public:
-
-	LLThreadLocalPointer()
-	{}
-
-	explicit LLThreadLocalPointer(T* value)
-	{
-		set(value);
-	}
-
-
-	LLThreadLocalPointer(const LLThreadLocalPointer<T>& other)
-	:	LLThreadLocalPointerBase(other)
-	{
-		set(other.get());		
-	}
-
-	LL_FORCE_INLINE T* get()
-	{
-		return (T*)LLThreadLocalPointerBase::get();
-	}
-
-	const T* get() const
-	{
-		return (const T*)LLThreadLocalPointerBase::get();
-	}
-
-	T* operator -> ()
-	{
-		return (T*)get();
-	}
-
-	const T* operator -> () const
-	{
-		return (T*)get();
-	}
-
-	T& operator*()
-	{
-		return *(T*)get();
-	}
-
-	const T& operator*() const
-	{
-		return *(T*)get();
-	}
-
-	LLThreadLocalPointer<T>& operator = (T* value)
-	{
-		set((void*)value);
-		return *this;
-	}
-
-	bool operator ==(T* other)
-	{
-		if (!sInitialized) return false;
-		return get() == other;
-	}
-};
-
-#endif // LL_LLTHREADLOCALPOINTER_H
diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
new file mode 100644
index 0000000000..fdf0c18085
--- /dev/null
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -0,0 +1,254 @@
+/** 
+ * @file llthreadlocalstorage.h
+ * @author Richard
+ * @brief Class wrappers for thread local storage
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTHREADLOCALSTORAGE_H
+#define LL_LLTHREADLOCALSTORAGE_H
+
+#include "llinstancetracker.h"
+#include "llapr.h"
+
+class LLThreadLocalPointerBase : public LLInstanceTracker<LLThreadLocalPointerBase>
+{
+public:
+	LLThreadLocalPointerBase()
+	:	mThreadKey(NULL)
+	{
+		if (sInitialized)
+		{
+			initStorage();
+		}
+	}
+
+	LLThreadLocalPointerBase( const LLThreadLocalPointerBase& other)
+		:	mThreadKey(NULL)
+	{
+		if (sInitialized)
+		{
+			initStorage();
+		}
+	}
+
+	~LLThreadLocalPointerBase()
+	{
+		destroyStorage();
+	}
+
+	static void initAllThreadLocalStorage();
+	static void destroyAllThreadLocalStorage();
+
+protected:
+	void set(void* value);
+
+	LL_FORCE_INLINE void* get() const
+	{
+		// llassert(sInitialized);
+		void* ptr;
+		apr_status_t result =
+		apr_threadkey_private_get(&ptr, mThreadKey);
+		if (result != APR_SUCCESS)
+		{
+			ll_apr_warn_status(result);
+			llerrs << "Failed to get thread local data" << llendl;
+		}
+		return ptr;
+	}
+
+	void initStorage();
+	void destroyStorage();
+
+protected:
+	apr_threadkey_t* mThreadKey;
+	static bool		sInitialized;
+};
+
+template <typename T>
+class LLThreadLocalPointer : public LLThreadLocalPointerBase
+{
+public:
+
+	LLThreadLocalPointer()
+	{}
+
+	explicit LLThreadLocalPointer(T* value)
+	{
+		set(value);
+	}
+
+
+	LLThreadLocalPointer(const LLThreadLocalPointer<T>& other)
+	:	LLThreadLocalPointerBase(other)
+	{
+		set(other.get());		
+	}
+
+	LL_FORCE_INLINE T* get() const
+	{
+		return (T*)LLThreadLocalPointerBase::get();
+	}
+
+	T* operator -> () const
+	{
+		return (T*)get();
+	}
+
+	T& operator*() const
+	{
+		return *(T*)get();
+	}
+
+	LLThreadLocalPointer<T>& operator = (T* value)
+	{
+		set((void*)value);
+		return *this;
+	}
+
+	bool operator ==(const T* other) const
+	{
+		if (!sInitialized) return false;
+		return get() == other;
+	}
+};
+
+template<typename DERIVED_TYPE>
+class LLThreadLocalSingleton
+{
+	typedef enum e_init_state
+	{
+		UNINITIALIZED = 0,
+		CONSTRUCTING,
+		INITIALIZING,
+		INITIALIZED,
+		DELETED
+	} EInitState;
+
+public:
+	LLThreadLocalSingleton()
+	{}
+	
+	virtual ~LLThreadLocalSingleton()
+	{
+		sInstance = NULL;
+		sInitState = DELETED;
+	}
+
+	static void deleteSingleton()
+	{
+		delete sInstance;
+		sInstance = NULL;
+		sInitState = DELETED;
+	}
+
+	static DERIVED_TYPE* getInstance()
+	{
+		if (sInitState == CONSTRUCTING)
+		{
+			llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl;
+		}
+
+		if (sInitState == DELETED)
+		{
+			llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
+		}
+
+		if (!sInstance) 
+		{
+			sInitState = CONSTRUCTING;
+			sInstance = new DERIVED_TYPE(); 
+			sInitState = INITIALIZING;
+			sInstance->initSingleton(); 
+			sInitState = INITIALIZED;	
+		}
+
+		return sInstance;
+	}
+
+	static DERIVED_TYPE* getIfExists()
+	{
+		return sInstance;
+	}
+
+	// Reference version of getInstance()
+	// Preferred over getInstance() as it disallows checking for NULL
+	static DERIVED_TYPE& instance()
+	{
+		return *getInstance();
+	}
+
+	// Has this singleton been created uet?
+	// Use this to avoid accessing singletons before the can safely be constructed
+	static bool instanceExists()
+	{
+		return sInitState == INITIALIZED;
+	}
+
+	// Has this singleton already been deleted?
+	// Use this to avoid accessing singletons from a static object's destructor
+	static bool destroyed()
+	{
+		return sInitState == DELETED;
+	}
+private:
+	LLThreadLocalSingleton(const LLThreadLocalSingleton& other);
+	virtual void initSingleton() {}
+
+	static __declspec(thread) DERIVED_TYPE* sInstance;
+	static __declspec(thread) EInitState sInitState;
+};
+
+template<typename DERIVED_TYPE>
+__declspec(thread) DERIVED_TYPE* LLThreadLocalSingleton<DERIVED_TYPE>::sInstance = NULL;
+
+template<typename DERIVED_TYPE>
+__declspec(thread) typename LLThreadLocalSingleton<DERIVED_TYPE>::EInitState LLThreadLocalSingleton<DERIVED_TYPE>::sInitState = LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED;
+
+template<typename DERIVED_TYPE>
+class LLThreadLocalSingletonPointer
+{
+public:
+	void operator =(DERIVED_TYPE* value)
+	{
+		sInstance = value;
+	}
+
+	LL_FORCE_INLINE static DERIVED_TYPE* getInstance()
+	{
+		return sInstance;
+	}
+
+	LL_FORCE_INLINE static void setInstance(DERIVED_TYPE* instance)
+	{
+		sInstance = instance;
+	}
+
+private:
+	static __declspec(thread) DERIVED_TYPE* sInstance;
+};
+
+template<typename DERIVED_TYPE>
+__declspec(thread) DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL;
+
+#endif // LL_LLTHREADLOCALSTORAGE_H
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 9d0c93b352..9cadd70dd8 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -60,12 +60,23 @@ MasterThreadRecorder& getMasterThreadRecorder()
 	return *gMasterThreadRecorder;
 }
 
-LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
+LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder_ptr()
 {
 	static LLThreadLocalPointer<ThreadRecorder> s_thread_recorder;
 	return s_thread_recorder;
 }
 
+const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
+{
+	return get_thread_recorder_ptr();
+}
+
+void set_thread_recorder(ThreadRecorder* recorder)
+{
+	get_thread_recorder_ptr() = recorder;
+}
+
+
 TimeBlockTreeNode::TimeBlockTreeNode() 
 :	mBlock(NULL),
 	mParent(NULL),
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 05191cafaa..285d4389af 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -34,7 +34,7 @@
 #include "llrefcount.h"
 #include "llunit.h"
 #include "llapr.h"
-#include "llthreadlocalpointer.h"
+#include "llthreadlocalstorage.h"
 
 #include <list>
 
@@ -70,7 +70,8 @@ namespace LLTrace
 	void cleanup();
 	bool isInitialized();
 
-	LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder();
+	const LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder();
+	void set_thread_recorder(class ThreadRecorder*);
 
 	class MasterThreadRecorder& getMasterThreadRecorder();
 
@@ -106,9 +107,9 @@ namespace LLTrace
 
 		~AccumulatorBuffer()
 		{
-			if (sPrimaryStorage == mStorage)
+			if (LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage)
 			{
-				sPrimaryStorage = getDefaultBuffer()->mStorage;
+				LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(getDefaultBuffer()->mStorage);
 			}
 			delete[] mStorage;
 		}
@@ -151,17 +152,17 @@ namespace LLTrace
 
 		void makePrimary()
 		{
-			sPrimaryStorage = mStorage;
+			LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(mStorage);
 		}
 
 		bool isPrimary() const
 		{
-			return sPrimaryStorage == mStorage;
+			return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage;
 		}
 
 		LL_FORCE_INLINE static ACCUMULATOR* getPrimaryStorage() 
 		{ 
-			return sPrimaryStorage.get(); 
+			return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance(); 
 		}
 
 		// NOTE: this is not thread-safe.  We assume that slots are reserved in the main thread before any child threads are spawned
@@ -214,7 +215,6 @@ namespace LLTrace
 		{
 			// this buffer is allowed to leak so that trace calls from global destructors have somewhere to put their data
 			// so as not to trigger an access violation
-			//TODO: make this thread local but need to either demand-init apr or remove apr dependency
 			static self_t* sBuffer = new AccumulatorBuffer(StaticAllocationMarker());
 			static bool sInitialized = false;
 			if (!sInitialized)
@@ -229,9 +229,7 @@ namespace LLTrace
 		ACCUMULATOR*								mStorage;
 		size_t										mStorageSize;
 		size_t										mNextStorageSlot;
-		static LLThreadLocalPointer<ACCUMULATOR>	sPrimaryStorage;
 	};
-	template<typename ACCUMULATOR> LLThreadLocalPointer<ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>::sPrimaryStorage;
 
 	//TODO: replace with decltype when C++11 is enabled
 	template<typename T>
@@ -250,10 +248,9 @@ namespace LLTrace
 		TraceType(const char* name, const char* description = NULL)
 		:	LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>(name),
 			mName(name),
-			mDescription(description ? description : "")	
-		{
-			mAccumulatorIndex = AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot();
-		}
+			mDescription(description ? description : ""),
+			mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot())
+		{}
 
 		LL_FORCE_INLINE ACCUMULATOR* getPrimaryAccumulator() const
 		{
@@ -263,13 +260,12 @@ namespace LLTrace
 
 		size_t getIndex() const { return mAccumulatorIndex; }
 
-		std::string& getName() { return mName; }
 		const std::string& getName() const { return mName; }
 
 	protected:
-		std::string	mName;
-		std::string mDescription;
-		size_t		mAccumulatorIndex;
+		const std::string	mName;
+		const std::string	mDescription;
+		const size_t		mAccumulatorIndex;
 	};
 
 	template<typename T>
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 156b0ef26b..9fb789c62d 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -39,18 +39,17 @@ namespace LLTrace
 ThreadRecorder::ThreadRecorder()
 {
 	//NB: the ordering of initialization in this function is very fragile due to a large number of implicit dependencies
-	get_thread_recorder() = this;
+	set_thread_recorder(this);
+	TimeBlock& root_time_block = TimeBlock::getRootTimeBlock();
 
-	mRootTimerData = new CurTimerData();
-	mRootTimerData->mTimerData = &TimeBlock::getRootTimer();
-	TimeBlock::sCurTimerData = mRootTimerData;
+	ThreadTimerStack* timer_stack = ThreadTimerStack::getInstance();
+	timer_stack->mTimeBlock = &root_time_block;
+	timer_stack->mActiveTimer = NULL;
 
 	mNumTimeBlockTreeNodes = AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer()->size();
 	mTimeBlockTreeNodes = new TimeBlockTreeNode[mNumTimeBlockTreeNodes];
 
-	mFullRecording.start();
-
-	TimeBlock& root_timer = TimeBlock::getRootTimer();
+	mThreadRecording.start();
 
 	// initialize time block parent pointers
 	for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(); 
@@ -60,15 +59,15 @@ ThreadRecorder::ThreadRecorder()
 		TimeBlock& time_block = *it;
 		TimeBlockTreeNode& tree_node = mTimeBlockTreeNodes[it->getIndex()];
 		tree_node.mBlock = &time_block;
-		tree_node.mParent = &root_timer;
+		tree_node.mParent = &root_time_block;
 
-		it->getPrimaryAccumulator()->mParent = &root_timer;
+		it->getPrimaryAccumulator()->mParent = &root_time_block;
 	}
 
-	mRootTimer = new BlockTimer(root_timer);
-	mRootTimerData->mCurTimer = mRootTimer;
+	mRootTimer = new BlockTimer(root_time_block);
+	timer_stack->mActiveTimer = mRootTimer;
 
-	TimeBlock::getRootTimer().getPrimaryAccumulator()->mActiveCount = 1;
+	TimeBlock::getRootTimeBlock().getPrimaryAccumulator()->mActiveCount = 1;
 }
 
 ThreadRecorder::~ThreadRecorder()
@@ -79,9 +78,7 @@ ThreadRecorder::~ThreadRecorder()
 	{
 		mActiveRecordings.front().mTargetRecording->stop();
 	}
-	get_thread_recorder() = NULL;
-	TimeBlock::sCurTimerData = NULL;
-	delete mRootTimerData;
+	set_thread_recorder(NULL);
 	delete[] mTimeBlockTreeNodes;
 }
 
@@ -196,12 +193,12 @@ SlaveThreadRecorder::~SlaveThreadRecorder()
 
 void SlaveThreadRecorder::pushToMaster()
 {
-	mFullRecording.stop();
+	mThreadRecording.stop();
 	{
 		LLMutexLock(getMasterThreadRecorder().getSlaveListMutex());
-		mSharedData.appendFrom(mFullRecording);
+		mSharedData.appendFrom(mThreadRecording);
 	}
-	mFullRecording.start();
+	mThreadRecording.start();
 }
 
 void SlaveThreadRecorder::SharedData::appendFrom( const Recording& source )
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index d09527eced..337035974c 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -62,13 +62,12 @@ namespace LLTrace
 
 			void moveBaselineToTarget();
 		};
-		Recording					mFullRecording;
+		Recording					mThreadRecording;
 		std::list<ActiveRecording>	mActiveRecordings;
 
-		struct CurTimerData*	mRootTimerData;
-		class BlockTimer*		mRootTimer;
-		TimeBlockTreeNode*		mTimeBlockTreeNodes;
-		size_t					mNumTimeBlockTreeNodes;
+		class BlockTimer*				mRootTimer;
+		TimeBlockTreeNode*				mTimeBlockTreeNodes;
+		size_t							mNumTimeBlockTreeNodes;
 	};
 
 	class LL_COMMON_API MasterThreadRecorder : public ThreadRecorder
-- 
cgit v1.2.3


From 6e82bb7789c1e046dcfb97c6773150df110153f8 Mon Sep 17 00:00:00 2001
From: Andrew Meadows <andrew@lindenlab.com>
Date: Thu, 3 Jan 2013 22:34:34 +0000
Subject: fixing linux compile errors for llcommon after LLTrace work

---
 indra/llcommon/llfasttimer.h          |  2 +-
 indra/llcommon/llmemory.h             |  1 +
 indra/llcommon/llthreadlocalstorage.h | 21 +++++++++++++++++++++
 indra/llcommon/lltrace.h              | 26 +++++++++++++-------------
 indra/llcommon/lltracerecording.h     | 18 +++++++++---------
 5 files changed, 45 insertions(+), 23 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 995eebd16a..fb2868ff98 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -49,7 +49,7 @@ class ThreadTimerStack
 :	public BlockTimerStackRecord, 
 	public LLThreadLocalSingleton<ThreadTimerStack>
 {
-	friend LLThreadLocalSingleton<ThreadTimerStack>;
+	friend class LLThreadLocalSingleton<ThreadTimerStack>;
 	ThreadTimerStack() 
 	{}
 
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index e725bdd9fa..7e73afe06a 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -27,6 +27,7 @@
 #define LLMEMORY_H
 
 #include "linden_common.h"
+#include "stdint.h"
 
 class LLMutex ;
 
diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
index fdf0c18085..5a38d54eea 100644
--- a/indra/llcommon/llthreadlocalstorage.h
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -215,15 +215,28 @@ private:
 	LLThreadLocalSingleton(const LLThreadLocalSingleton& other);
 	virtual void initSingleton() {}
 
+#ifdef LL_WINDOWS
 	static __declspec(thread) DERIVED_TYPE* sInstance;
 	static __declspec(thread) EInitState sInitState;
+#elif LL_LINUX
+	static __thread DERIVED_TYPE* sInstance;
+	static __thread EInitState sInitState;
+#endif
 };
 
+#ifdef LL_WINDOWS
 template<typename DERIVED_TYPE>
 __declspec(thread) DERIVED_TYPE* LLThreadLocalSingleton<DERIVED_TYPE>::sInstance = NULL;
 
 template<typename DERIVED_TYPE>
 __declspec(thread) typename LLThreadLocalSingleton<DERIVED_TYPE>::EInitState LLThreadLocalSingleton<DERIVED_TYPE>::sInitState = LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED;
+#elif LL_LINUX
+template<typename DERIVED_TYPE>
+__thread DERIVED_TYPE* LLThreadLocalSingleton<DERIVED_TYPE>::sInstance = NULL;
+
+template<typename DERIVED_TYPE>
+__thread typename LLThreadLocalSingleton<DERIVED_TYPE>::EInitState LLThreadLocalSingleton<DERIVED_TYPE>::sInitState = LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED;
+#endif
 
 template<typename DERIVED_TYPE>
 class LLThreadLocalSingletonPointer
@@ -245,10 +258,18 @@ public:
 	}
 
 private:
+#ifdef LL_WINDOWS
 	static __declspec(thread) DERIVED_TYPE* sInstance;
+#elif LL_LINUX
+	static __thread DERIVED_TYPE* sInstance;
+#endif
 };
 
 template<typename DERIVED_TYPE>
+#ifdef LL_WINDOWS
 __declspec(thread) DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL;
+#elif LL_LINUX
+__thread DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL;
+#endif
 
 #endif // LL_LLTHREADLOCALSTORAGE_H
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 285d4389af..e15cffd7d2 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -614,7 +614,7 @@ struct MemFootprint<T*>
 
 	static size_t measure()
 	{
-		return MemFootPrint<T>::measure();
+		return MemFootprint<T>::measure();
 	}
 };
 
@@ -730,17 +730,17 @@ public:
 	}
 
 	// claim memory associated with other objects/data as our own, adding to our calculated footprint
-	template<typename T>
-	T& memClaim(T& value)
+	template<typename CLAIM_T>
+	CLAIM_T& memClaim(CLAIM_T& value)
 	{
-		TrackMemImpl<T>::claim(*this, value);
+		TrackMemImpl<CLAIM_T>::claim(*this, value);
 		return value;
 	}
 
-	template<typename T>
-	const T& memClaim(const T& value)
+	template<typename CLAIM_T>
+	const CLAIM_T& memClaim(const CLAIM_T& value)
 	{
-		TrackMemImpl<T>::claim(*this, value);
+		TrackMemImpl<CLAIM_T>::claim(*this, value);
 		return value;
 	}
 
@@ -756,17 +756,17 @@ public:
 	}
 
 	// remove memory we had claimed from our calculated footprint
-	template<typename T>
-	T& memDisclaim(T& value)
+	template<typename CLAIM_T>
+	CLAIM_T& memDisclaim(CLAIM_T& value)
 	{
-		TrackMemImpl<T>::disclaim(*this, value);
+		TrackMemImpl<CLAIM_T>::disclaim(*this, value);
 		return value;
 	}
 
-	template<typename T>
-	const T& memDisclaim(const T& value)
+	template<typename CLAIM_T>
+	const CLAIM_T& memDisclaim(const CLAIM_T& value)
 	{
-		TrackMemImpl<T>::disclaim(*this, value);
+		TrackMemImpl<CLAIM_T>::disclaim(*this, value);
 		return value;
 	}
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index f2d7d42211..aa3200e5ad 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -141,7 +141,7 @@ namespace LLTrace
 		template <typename T>
 		T getSum(const Count<T>& stat) const
 		{
-			return (T)getSum(static_cast<const TraceType<CountAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getSum(static_cast<const TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
 		F64 getPerSec(const TraceType<CountAccumulator<F64> >& stat) const;
@@ -149,7 +149,7 @@ namespace LLTrace
 		template <typename T>
 		T getPerSec(const Count<T>& stat) const
 		{
-			return (T)getPerSec(static_cast<const TraceType<CountAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getPerSec(static_cast<const TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
 		U32 getSampleCount(const TraceType<CountAccumulator<F64> >& stat) const;
@@ -162,7 +162,7 @@ namespace LLTrace
 		template <typename T>
 		T getSum(const Measurement<T>& stat) const
 		{
-			return (T)getSum(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getSum(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
 		F64 getPerSec(const TraceType<MeasurementAccumulator<F64> >& stat) const;
@@ -170,7 +170,7 @@ namespace LLTrace
 		template <typename T>
 		T getPerSec(const Measurement<T>& stat) const
 		{
-			return (T)getPerSec(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getPerSec(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
 		F64 getMin(const TraceType<MeasurementAccumulator<F64> >& stat) const;
@@ -178,7 +178,7 @@ namespace LLTrace
 		template <typename T>
 		T getMin(const Measurement<T>& stat) const
 		{
-			return (T)getMin(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getMin(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
 		F64 getMax(const TraceType<MeasurementAccumulator<F64> >& stat) const;
@@ -186,7 +186,7 @@ namespace LLTrace
 		template <typename T>
 		T getMax(const Measurement<T>& stat) const
 		{
-			return (T)getMax(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getMax(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
 		F64 getMean(const TraceType<MeasurementAccumulator<F64> >& stat) const;
@@ -194,7 +194,7 @@ namespace LLTrace
 		template <typename T>
 		T getMean(Measurement<T>& stat) const
 		{
-			return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
 		F64 getStandardDeviation(const TraceType<MeasurementAccumulator<F64> >& stat) const;
@@ -202,7 +202,7 @@ namespace LLTrace
 		template <typename T>
 		T getStandardDeviation(const Measurement<T>& stat) const
 		{
-			return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
 		F64 getLastValue(const TraceType<MeasurementAccumulator<F64> >& stat) const;
@@ -210,7 +210,7 @@ namespace LLTrace
 		template <typename T>
 		T getLastValue(const Measurement<T>& stat) const
 		{
-			return (T)getLastValue(static_cast<const TraceType<MeasurementAccumulator<LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getLastValue(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
 		U32 getSampleCount(const TraceType<MeasurementAccumulator<F64> >& stat) const;
-- 
cgit v1.2.3


From 019836a39667889d4347277cde82270113992bb6 Mon Sep 17 00:00:00 2001
From: Andrew Meadows <andrew@lindenlab.com>
Date: Fri, 4 Jan 2013 03:02:54 +0000
Subject: More fixes for linux build of lltrace changes

---
 indra/llcommon/llerrorlegacy.h |  2 ++
 indra/llcommon/llunit.h        | 11 ++++++-----
 2 files changed, 8 insertions(+), 5 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h
index 58cc2899af..097a533b1a 100644
--- a/indra/llcommon/llerrorlegacy.h
+++ b/indra/llcommon/llerrorlegacy.h
@@ -114,8 +114,10 @@ const int LL_ERR_PRICE_MISMATCH = -23018;
 
 #ifdef LL_WINDOWS
 #define llstatic_assert(func, msg) static_assert(func, msg)
+#define llstatic_assert_template(type, func, msg) static_assert(func, msg)
 #else
 #define llstatic_assert(func, msg) BOOST_STATIC_ASSERT(func)
+#define llstatic_assert_template(type, func, msg) BOOST_STATIC_ASSERT(sizeof(type) != 0 && func);
 #endif
 
 // handy compile-time assert - enforce those template parameters! 
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 72a6020ff8..c600883607 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -29,6 +29,7 @@
 
 #include "stdtypes.h"
 #include "llpreprocessor.h"
+#include "llerrorlegacy.h"
 
 namespace LLUnits
 {
@@ -53,7 +54,7 @@ struct ConversionFactor
 	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.");
+		llstatic_assert_template(DERIVED_UNITS_TAG, false,  "Cannot convert between types.");
 	}
 };
 
@@ -141,7 +142,7 @@ struct LLUnit
 	void operator *= (LLUnit<OTHER_UNIT, OTHER_STORAGE> multiplicand)
 	{
 		// 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.");
+		llstatic_assert_template(OTHER_UNIT, 0, "Multiplication of unit types not supported.");
 	}
 
 	void operator /= (storage_t divisor)
@@ -153,7 +154,7 @@ struct LLUnit
 	void operator /= (LLUnit<OTHER_UNIT, OTHER_STORAGE> divisor)
 	{
 		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
-		llstatic_assert(sizeof(OTHER_UNIT) == 0, "Illegal in-place division of unit types.");
+		llstatic_assert_template(OTHER_UNIT, 0, "Illegal in-place division of unit types.");
 	}
 
 	template<typename SOURCE_UNITS, typename SOURCE_STORAGE>
@@ -313,7 +314,7 @@ template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typen
 LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator * (LLUnit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnit<UNIT_TYPE2, STORAGE_TYPE2>)
 {
 	// 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.");
+	llstatic_assert_template(STORAGE_TYPE1, 0, "Multiplication of unit types results in new unit type - not supported.");
 	return LLUnit<UNIT_TYPE1, STORAGE_TYPE1>();
 }
 
@@ -333,7 +334,7 @@ template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typen
 LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator * (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2>)
 {
 	// 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.");
+	llstatic_assert_template(STORAGE_TYPE1, 0, "Multiplication of unit types results in new unit type - not supported.");
 	return LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1>();
 }
 
-- 
cgit v1.2.3


From b2197101c488de66ca9ecf71c229f5b80d1390fd Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 4 Jan 2013 13:04:09 -0800
Subject: SH-3468 WIP add memory tracking base class fix for compile error on
 windows ignore stdint.h even though VS2010 provides it

---
 indra/llcommon/llmemory.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 7e73afe06a..4ead45679f 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -27,7 +27,9 @@
 #define LLMEMORY_H
 
 #include "linden_common.h"
-#include "stdint.h"
+#if !LL_WINDOWS
+#include <stdint.h>
+#endif
 
 class LLMutex ;
 
-- 
cgit v1.2.3


From cbff0e7ab8afeebb6ddab854d35ea12ef9a9930a Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 4 Jan 2013 13:48:35 -0800
Subject: SH-3468 WIP add memory tracking base class attempted fix for gcc
 compile errors can't use typeid() on a class that doesn't have a method
 defined in a translation unit fix is to force classes deriving from
 LLMemTrackable to use their own static member named sMemStat

---
 indra/llcommon/lltrace.h | 27 ++++++++++++---------------
 1 file changed, 12 insertions(+), 15 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index e15cffd7d2..1a156e583e 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -660,13 +660,13 @@ struct MemFootprint<std::list<T> >
 	}
 };
 
-template<typename T>
+template<typename DERIVED>
 class MemTrackable
 {
 	template<typename TRACKED, typename TRACKED_IS_TRACKER>
 	struct TrackMemImpl;
 
-	typedef MemTrackable<T> mem_trackable_t;
+	typedef MemTrackable<DERIVED> mem_trackable_t;
 
 public:
 	typedef void mem_trackable_tag_t;
@@ -681,7 +681,7 @@ public:
 		// reserve 8 bytes for allocation size (and preserving 8 byte alignment of structs)
 		void* allocation = ::operator new(allocation_size + 8);
 		*(size_t*)allocation = allocation_size;
-		MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize += allocation_size;
@@ -693,7 +693,7 @@ public:
 	void operator delete(void* ptr)
 	{
 		size_t* allocation_size = (size_t*)((char*)ptr - 8);
-		MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize -= *allocation_size;
@@ -707,7 +707,7 @@ public:
 	{
 		size_t* result = (size_t*)malloc(size + 8);
 		*result = size;
-		MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize += size;
@@ -719,7 +719,7 @@ public:
 	void operator delete[](void* ptr)
 	{
 		size_t* allocation_size = (size_t*)((char*)ptr - 8);
-		MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize -= *allocation_size;
@@ -747,7 +747,7 @@ public:
 
 	void memClaim(size_t size)
 	{
-		MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		mMemFootprint += size;
 		if (accumulator)
 		{
@@ -772,7 +772,7 @@ public:
 
 	void memDisclaim(size_t size)
 	{
-		MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize -= size;
@@ -788,7 +788,7 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				size_t footprint = MemFootprint<TRACKED>::measure(tracked);
@@ -799,7 +799,7 @@ private:
 
 		static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				size_t footprint = MemFootprint<TRACKED>::measure(tracked);
@@ -814,7 +814,7 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				accumulator->mChildSize += MemFootprint<TRACKED>::measure(tracked);
@@ -823,17 +823,14 @@ private:
 
 		static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = sStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				accumulator->mChildSize -= MemFootprint<TRACKED>::measure(tracked);
 			}
 		}
 	};
-	static MemStat sStat;
 };
 
-template<typename T> MemStat MemTrackable<T>::sStat(typeid(T).name());
-
 }
 #endif // LL_LLTRACE_H
-- 
cgit v1.2.3


From cf8fa1a958f8676a0911bac7bdb950a865b58c83 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 4 Jan 2013 15:57:28 -0800
Subject: SH-3468 WIP add memory tracking base class further compile error
 fixes

---
 indra/llcommon/llfasttimer.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index ad8cf7296e..e6233a094e 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -137,12 +137,12 @@ void TimeBlock::setLogLock(LLMutex* lock)
 
 //static
 #if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
-U64 TimeBlock::countsPerSecond() // counts per second for the *64-bit* timer
+U64 TimeBlock::countsPerSecond()
 {
 	return sClockResolution;
 }
 #else // windows or x86-mac or x86-linux or x86-solaris
-U64 TimeBlock::countsPerSecond() // counts per second for the *64-bit* timer
+U64 TimeBlock::countsPerSecond()
 {
 #if LL_FASTTIMER_USE_RDTSC || !LL_WINDOWS
 	//getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz
@@ -165,7 +165,7 @@ U64 TimeBlock::countsPerSecond() // counts per second for the *64-bit* timer
 #endif
 
 TimeBlock::TimeBlock(const char* name, bool open, TimeBlock* parent)
-:	TraceType(name),
+:	TraceType<TimeBlockAccumulator>(name),
 	mCollapsed(true)
 {
 	setCollapsed(!open);
-- 
cgit v1.2.3


From 7dbb8860373769dfca7d6c6588284866a1bf86a3 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 4 Jan 2013 16:19:20 -0800
Subject: SH-3468 WIP add memory tracking base class further compile error
 fixes

---
 indra/llcommon/lltracerecording.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 9dbafc4e82..c110e64380 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -60,7 +60,7 @@ Recording::Recording( const Recording& other )
 	mStackTimers       = other.mStackTimers;
 	mMemStats		   = other.mMemStats;
 
-	LLStopWatchControlsMixin::initTo(other.getPlayState());
+	LLStopWatchControlsMixin<Recording>::initTo(other.getPlayState());
 }
 
 
-- 
cgit v1.2.3


From 68413515029f50713c70e4adec3ce6fd1022d59f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sun, 6 Jan 2013 21:37:31 -0800
Subject: SH-3468 WIP add memory tracking base class fix for unit test
 failures...cleanup apr without destroying pools, allowing LLProxy to clean
 itself up as a singleton (and avoiding spurious dependencies associated with
 manually destorying singletons that rely on apr pools)

---
 indra/llcommon/llapr.cpp                 | 4 ++--
 indra/llcommon/llapr.h                   | 2 +-
 indra/llcommon/lltracethreadrecorder.cpp | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index d911f258b6..8a87911315 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -60,7 +60,7 @@ void ll_init_apr()
 }
 
 
-void ll_cleanup_apr()
+void ll_cleanup_apr(bool destroy_pools)
 {
 	LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
 
@@ -83,7 +83,7 @@ void ll_cleanup_apr()
 
 	LLThreadLocalPointerBase::destroyAllThreadLocalStorage();
 
-	if (gAPRPoolp)
+	if (gAPRPoolp && destroy_pools)
 	{
 		apr_pool_destroy(gAPRPoolp);
 		gAPRPoolp = NULL;
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index b3c9bfd58c..424ddc6505 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -70,7 +70,7 @@ void LL_COMMON_API ll_init_apr();
 /** 
  * @brief Cleanup those common apr constructs.
  */
-void LL_COMMON_API ll_cleanup_apr();
+void LL_COMMON_API ll_cleanup_apr(bool destroy_pools = true);
 
 //
 //LL apr_pool
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 9fb789c62d..7b493a651e 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -127,7 +127,7 @@ std::list<ThreadRecorder::ActiveRecording>::iterator ThreadRecorder::update( Rec
 
 	if (it == end_it)
 	{
-		llerrs << "Recording not active on this thread" << llendl;
+		llwarns << "Recording not active on this thread" << llendl;
 	}
 
 	return it;
-- 
cgit v1.2.3


From 3c341a11ab7b8f3fd18afcf3f50af6dfafa632c2 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 8 Jan 2013 00:25:07 -0800
Subject: SH-3468 WIP add memory tracking base class more fixes for unit test
 crashes added llcommon initialization/teardown for unit tests that indirectly
 trigger lltrace changed access of atomic refcount to use
 preincrement/decrement operators to reflect desired semantics always call
 apr_initialize in LLCommon::initClass, even if already initialized...apr does
 internal reference counting to keep things straight

---
 indra/llcommon/llapr.cpp   | 19 +++++++++++++++----
 indra/llcommon/llapr.h     |  5 ++++-
 indra/llcommon/llmutex.cpp | 11 +++++++----
 3 files changed, 26 insertions(+), 9 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 8a87911315..0556fadb26 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -38,12 +38,15 @@ apr_thread_mutex_t *gCallStacksLogMutexp = NULL;
 
 const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool
 
+bool gAPRInitialized = false;
+
 void ll_init_apr()
 {
+	// Initialize APR and create the global pool
+	apr_initialize();
+	
 	if (!gAPRPoolp)
 	{
-		// Initialize APR and create the global pool
-		apr_initialize();
 		apr_pool_create(&gAPRPoolp, NULL);
 		
 		// Initialize the logging mutex
@@ -57,11 +60,19 @@ void ll_init_apr()
 	}
 
 	LLThreadLocalPointerBase::initAllThreadLocalStorage();
+	gAPRInitialized = true;
 }
 
 
-void ll_cleanup_apr(bool destroy_pools)
+bool ll_apr_is_initialized()
+{
+	return gAPRInitialized;
+}
+
+void ll_cleanup_apr()
 {
+	gAPRInitialized = false;
+
 	LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
 
 	if (gLogMutexp)
@@ -83,7 +94,7 @@ void ll_cleanup_apr(bool destroy_pools)
 
 	LLThreadLocalPointerBase::destroyAllThreadLocalStorage();
 
-	if (gAPRPoolp && destroy_pools)
+	if (gAPRPoolp)
 	{
 		apr_pool_destroy(gAPRPoolp);
 		gAPRPoolp = NULL;
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 424ddc6505..3b65c0dc34 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -70,7 +70,10 @@ void LL_COMMON_API ll_init_apr();
 /** 
  * @brief Cleanup those common apr constructs.
  */
-void LL_COMMON_API ll_cleanup_apr(bool destroy_pools = true);
+void LL_COMMON_API ll_cleanup_apr();
+
+bool LL_COMMON_API ll_apr_is_initialized();
+
 
 //
 //LL apr_pool
diff --git a/indra/llcommon/llmutex.cpp b/indra/llcommon/llmutex.cpp
index b685bb4d60..ad0287c6d5 100644
--- a/indra/llcommon/llmutex.cpp
+++ b/indra/llcommon/llmutex.cpp
@@ -56,12 +56,15 @@ LLMutex::~LLMutex()
 	//bad assertion, the subclass LLSignal might be "locked", and that's OK
 	//llassert_always(!isLocked()); // better not be locked!
 #endif
-	apr_thread_mutex_destroy(mAPRMutexp);
-	mAPRMutexp = NULL;
-	if (mIsLocalPool)
+	if (ll_apr_is_initialized())
 	{
-		apr_pool_destroy(mAPRPoolp);
+		apr_thread_mutex_destroy(mAPRMutexp);
+		if (mIsLocalPool)
+		{
+			apr_pool_destroy(mAPRPoolp);
+		}
 	}
+	mAPRMutexp = NULL;
 }
 
 
-- 
cgit v1.2.3


From 0ba9a00c3116b69745f2d5070ce772d5d4965dbf Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 8 Jan 2013 23:50:27 -0800
Subject: SH-3468 WIP add memory tracking base class cleaned up hacks used to
 get unit tests working LLTrace::init now supports recursive
 initialization/cleanup put NOMINMAX back in win32 header wrappers

---
 indra/llcommon/lltrace.cpp          | 17 +++++++++++------
 indra/llcommon/llwin32headers.h     |  4 ++++
 indra/llcommon/llwin32headerslean.h |  4 ++++
 3 files changed, 19 insertions(+), 6 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 9cadd70dd8..463048008f 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -30,7 +30,7 @@
 #include "lltracethreadrecorder.h"
 #include "llfasttimer.h"
 
-static bool sInitialized;
+static S32 sInitializationCount = 0;
 
 namespace LLTrace
 {
@@ -39,19 +39,24 @@ static MasterThreadRecorder* gMasterThreadRecorder = NULL;
 
 void init()
 {
-	gMasterThreadRecorder = new MasterThreadRecorder();
-	sInitialized = true;
+	if (sInitializationCount++ == 0)
+	{
+		gMasterThreadRecorder = new MasterThreadRecorder();
+	}
 }
 
 bool isInitialized()
 {
-	return sInitialized; 
+	return sInitializationCount > 0; 
 }
 
 void cleanup()
 {
-	delete gMasterThreadRecorder;
-	gMasterThreadRecorder = NULL;
+	if (--sInitializationCount == 0)
+	{
+		delete gMasterThreadRecorder;
+		gMasterThreadRecorder = NULL;
+	}
 }
 
 MasterThreadRecorder& getMasterThreadRecorder()
diff --git a/indra/llcommon/llwin32headers.h b/indra/llcommon/llwin32headers.h
index 9c89b6b280..8534ed6298 100644
--- a/indra/llcommon/llwin32headers.h
+++ b/indra/llcommon/llwin32headers.h
@@ -28,9 +28,13 @@
 #define LL_LLWINDOWS_H
 
 #ifdef LL_WINDOWS
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
 #undef WIN32_LEAN_AND_MEAN
 #include <winsock2.h>
 #include <windows.h>
+#undef NOMINMAX
 #endif
 
 #endif
diff --git a/indra/llcommon/llwin32headerslean.h b/indra/llcommon/llwin32headerslean.h
index d3fb90d4b1..f7e71301a8 100644
--- a/indra/llcommon/llwin32headerslean.h
+++ b/indra/llcommon/llwin32headerslean.h
@@ -28,9 +28,13 @@
 #define LL_LLWINDOWS_H
 
 #ifdef LL_WINDOWS
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
 #define WIN32_LEAN_AND_MEAN
 #include <winsock2.h>
 #include <windows.h>
+#undef NOMINMAX
 #endif
 
 #endif
-- 
cgit v1.2.3


From 386e918583fe25532f401c6b50c49632d7410d39 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 9 Jan 2013 11:21:45 -0800
Subject: SH-3468 WIP add memory tracking base class fix for linux build issues

---
 indra/llcommon/CMakeLists.txt | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 28677b036d..7ed1671ca8 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -257,6 +257,8 @@ set(llcommon_HEADER_FILES
     lluuidhashmap.h
     llversionserver.h
     llversionviewer.h
+    llwin32headers.h
+    llwin32headerslean.h
     llworkerthread.h
     ll_template_cast.h
     metaclass.h
-- 
cgit v1.2.3


From 1a888f786c274ee6eaed54272718eeef5e685dbf Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 9 Jan 2013 23:05:07 -0800
Subject: SH-3468 WIP add memory tracking base class made LLTrace::MemTrackable
 support custom alignment LLDrawable now uses MemTrackable new and delete
 operators

---
 indra/llcommon/llmemory.h | 14 ++++++++
 indra/llcommon/lltrace.h  | 85 +++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 85 insertions(+), 14 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 4ead45679f..95500753e4 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -39,6 +39,20 @@ class LLMutex ;
 #define LL_CHECK_MEMORY
 #endif
 
+#if LL_WINDOWS
+#define LL_ALIGN_OF __alignof
+#else
+#define LL_ALIGN_OF __align_of__
+#endif
+
+#if LL_WINDOWS
+#define LL_DEFAULT_HEAP_ALIGN 8
+#elif LL_DARWIN
+#define LL_DEFAULT_HEAP_ALIGN 16
+#elif LL_LINUX
+#define LL_DEFAULT_HEAP_ALIGN 8
+#endif
+
 inline void* ll_aligned_malloc( size_t size, int align )
 {
 	void* mem = malloc( size + (align - 1) + sizeof(void*) );
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 1a156e583e..8ec0cdc4dc 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -660,7 +660,57 @@ struct MemFootprint<std::list<T> >
 	}
 };
 
-template<typename DERIVED>
+template <size_t ALIGNMENT, size_t RESERVE>
+void* allocAligned(size_t size)
+{
+	llstatic_assert((ALIGNMENT > 0) && (ALIGNMENT & (ALIGNMENT - 1)) == 0, "Alignment must be a power of 2");
+
+	void* padded_allocation;
+	const size_t aligned_reserve = (RESERVE / ALIGNMENT) 
+		+ ((RESERVE % ALIGNMENT) ? ALIGNMENT : 0);
+	const size_t size_with_reserve = size + aligned_reserve;
+	if (ALIGNMENT <= LL_DEFAULT_HEAP_ALIGN)
+	{
+		padded_allocation = malloc(size_with_reserve);
+	}
+	else
+	{
+#if LL_WINDOWS
+		padded_allocation = _aligned_malloc(size_with_reserve, ALIGNMENT);
+#elif LL_DARWIN
+		padded_allocation = ll_aligned_malloc(size_with_reserve, ALIGNMENT);
+#else
+		posix_memalign(&padded_allocation, ALIGNMENT, size_with_reserve);
+#endif
+	}
+	return (char*)padded_allocation + aligned_reserve;
+}
+
+template<size_t ALIGNMENT, size_t RESERVE>
+void deallocAligned(void* ptr)
+{
+	const size_t aligned_reserve = (RESERVE / ALIGNMENT) 
+		+ ((RESERVE % ALIGNMENT) ? ALIGNMENT : 0);
+
+	void* original_allocation = (char*)ptr - aligned_reserve;
+
+	if (ALIGNMENT <= LL_DEFAULT_HEAP_ALIGN)
+	{
+		free(original_allocation);
+	}
+	else
+	{
+#if LL_WINDOWS
+		_aligned_free(original_allocation);
+#elif LL_DARWIN
+		ll_aligned_free(original_allocation);
+#else
+		free(original_allocation);		
+#endif
+	}	
+}
+
+template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN>
 class MemTrackable
 {
 	template<typename TRACKED, typename TRACKED_IS_TRACKER>
@@ -676,44 +726,49 @@ public:
 		memDisclaim(mMemFootprint);
 	}
 
-	void* operator new(size_t allocation_size) 
+	void* operator new(size_t size) 
 	{
-		// reserve 8 bytes for allocation size (and preserving 8 byte alignment of structs)
-		void* allocation = ::operator new(allocation_size + 8);
-		*(size_t*)allocation = allocation_size;
 		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
-			accumulator->mSize += allocation_size;
+			accumulator->mSize += size;
 			accumulator->mAllocatedCount++;
 		}
-		return (void*)((char*)allocation + 8);
+
+		// reserve 4 bytes for allocation size (and preserving requested alignment)
+		void* allocation = allocAligned<ALIGNMENT, sizeof(size_t)>(size);
+		((size_t*)allocation)[-1] = size;
+
+		return allocation;
 	}
 
 	void operator delete(void* ptr)
 	{
-		size_t* allocation_size = (size_t*)((char*)ptr - 8);
+		size_t allocation_size = ((size_t*)ptr)[-1];
 		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
-			accumulator->mSize -= *allocation_size;
+			accumulator->mSize -= allocation_size;
 			accumulator->mAllocatedCount--;
 			accumulator->mDeallocatedCount++;
 		}
-		::delete((char*)ptr - 8);
+		deallocAligned<ALIGNMENT, sizeof(size_t)>(ptr);
 	}
 
 	void *operator new [](size_t size)
 	{
-		size_t* result = (size_t*)malloc(size + 8);
-		*result = size;
 		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize += size;
 			accumulator->mAllocatedCount++;
 		}
-		return (void*)((char*)result + 8);
+
+		// reserve 4 bytes for allocation size (and preserving requested alignment)
+		void* allocation = allocAligned<ALIGNMENT, sizeof(size_t)>(size);
+		((size_t*)allocation)[-1] = size;
+
+		return allocation;
 	}
 
 	void operator delete[](void* ptr)
@@ -726,7 +781,7 @@ public:
 			accumulator->mAllocatedCount--;
 			accumulator->mDeallocatedCount++;
 		}
-		::delete[]((char*)ptr - 8);
+		deallocAligned<ALIGNMENT, sizeof(size_T)>(ptr);
 	}
 
 	// claim memory associated with other objects/data as our own, adding to our calculated footprint
@@ -783,6 +838,8 @@ public:
 private:
 	size_t mMemFootprint;
 
+
+
 	template<typename TRACKED, typename TRACKED_IS_TRACKER = void>
 	struct TrackMemImpl
 	{
-- 
cgit v1.2.3


From a891785f7a02098a53029311befd7083773d6ad8 Mon Sep 17 00:00:00 2001
From: Andrew Meadows <andrew@lindenlab.com>
Date: Thu, 10 Jan 2013 07:45:43 +0000
Subject: typo fix

---
 indra/llcommon/lltrace.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 8ec0cdc4dc..7694f65441 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -781,7 +781,7 @@ public:
 			accumulator->mAllocatedCount--;
 			accumulator->mDeallocatedCount++;
 		}
-		deallocAligned<ALIGNMENT, sizeof(size_T)>(ptr);
+		deallocAligned<ALIGNMENT, sizeof(size_t)>(ptr);
 	}
 
 	// claim memory associated with other objects/data as our own, adding to our calculated footprint
-- 
cgit v1.2.3


From 8c73ff245cee8da2ca75c5651be88a36358a5dae Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 10 Jan 2013 00:12:25 -0800
Subject: SH-3468 WIP add memory tracking base class actually use return value
 of posix_memalign!

---
 indra/llcommon/lltrace.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 7694f65441..a9d5cc58de 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -680,7 +680,7 @@ void* allocAligned(size_t size)
 #elif LL_DARWIN
 		padded_allocation = ll_aligned_malloc(size_with_reserve, ALIGNMENT);
 #else
-		posix_memalign(&padded_allocation, ALIGNMENT, size_with_reserve);
+		padded_allocation = posix_memalign(&padded_allocation, ALIGNMENT, size_with_reserve);
 #endif
 	}
 	return (char*)padded_allocation + aligned_reserve;
-- 
cgit v1.2.3


From f8a2bca6526ea1eef61a9b8cf0fb2e78c2663d60 Mon Sep 17 00:00:00 2001
From: Andrew Meadows <andrew@lindenlab.com>
Date: Thu, 10 Jan 2013 08:47:29 +0000
Subject: fix for invalid use of posix_memalign

---
 indra/llcommon/lltrace.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index a9d5cc58de..7694f65441 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -680,7 +680,7 @@ void* allocAligned(size_t size)
 #elif LL_DARWIN
 		padded_allocation = ll_aligned_malloc(size_with_reserve, ALIGNMENT);
 #else
-		padded_allocation = posix_memalign(&padded_allocation, ALIGNMENT, size_with_reserve);
+		posix_memalign(&padded_allocation, ALIGNMENT, size_with_reserve);
 #endif
 	}
 	return (char*)padded_allocation + aligned_reserve;
-- 
cgit v1.2.3


From d89d9cd10ff1fbe6f1f86f0b282075e775ed1b51 Mon Sep 17 00:00:00 2001
From: Andrew Meadows <andrew@lindenlab.com>
Date: Fri, 11 Jan 2013 01:52:09 +0000
Subject: gcc fixes

---
 indra/llcommon/lltrace.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 7694f65441..ab4ad59e3d 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -680,7 +680,8 @@ void* allocAligned(size_t size)
 #elif LL_DARWIN
 		padded_allocation = ll_aligned_malloc(size_with_reserve, ALIGNMENT);
 #else
-		posix_memalign(&padded_allocation, ALIGNMENT, size_with_reserve);
+		if (LL_UNLIKELY(0 != posix_memalign(&padded_allocation, 16, size)))
+			padded_allocation = NULL;
 #endif
 	}
 	return (char*)padded_allocation + aligned_reserve;
-- 
cgit v1.2.3


From 62a9f557d2e91beb685843775e8f9fe73dab4b94 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 11 Jan 2013 10:16:26 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system moved thread local
 storage to its own cpp file

---
 indra/llcommon/CMakeLists.txt           |   1 +
 indra/llcommon/llapr.cpp                |  71 ----------------------
 indra/llcommon/llthreadlocalstorage.cpp | 101 ++++++++++++++++++++++++++++++++
 3 files changed, 102 insertions(+), 71 deletions(-)
 create mode 100644 indra/llcommon/llthreadlocalstorage.cpp

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 7ed1671ca8..f8f1c010f7 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -98,6 +98,7 @@ set(llcommon_SOURCE_FILES
     llstringtable.cpp
     llsys.cpp
     llthread.cpp
+	llthreadlocalstorage.cpp
     llthreadsafequeue.cpp
     lltimer.cpp
     lltrace.cpp
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index 0556fadb26..47fa70614f 100644
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -493,77 +493,6 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
 	return LLAPRFile::seek(mFile, where, offset) ;
 }
 
-//
-//LLThreadLocalPointerBase
-//
-bool LLThreadLocalPointerBase::sInitialized = false;
-
-void LLThreadLocalPointerBase::set( void* value )
-{
-	llassert(sInitialized && mThreadKey);
-
-	apr_status_t result = apr_threadkey_private_set((void*)value, mThreadKey);
-	if (result != APR_SUCCESS)
-	{
-		ll_apr_warn_status(result);
-		llerrs << "Failed to set thread local data" << llendl;
-	}
-}
-
-void LLThreadLocalPointerBase::initStorage( )
-{
-	apr_status_t result = apr_threadkey_private_create(&mThreadKey, NULL, gAPRPoolp);
-	if (result != APR_SUCCESS)
-	{
-		ll_apr_warn_status(result);
-		llerrs << "Failed to allocate thread local data" << llendl;
-	}
-}
-
-void LLThreadLocalPointerBase::destroyStorage()
-{
-	if (sInitialized)
-	{
-		if (mThreadKey)
-		{
-			apr_status_t result = apr_threadkey_private_delete(mThreadKey);
-			if (result != APR_SUCCESS)
-			{
-				ll_apr_warn_status(result);
-				llerrs << "Failed to delete thread local data" << llendl;
-			}
-		}
-	}
-}
-
-void LLThreadLocalPointerBase::initAllThreadLocalStorage()
-{
-	if (!sInitialized)
-	{
-		for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances();
-			it != end_it;
-			++it)
-		{
-			(*it).initStorage();
-		}
-		sInitialized = true;
-	}
-}
-
-void LLThreadLocalPointerBase::destroyAllThreadLocalStorage()
-{
-	if (sInitialized)
-	{
-		//for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances();
-		//	it != end_it;
-		//	++it)
-		//{
-		//	(*it).destroyStorage();
-		//}
-		sInitialized = false;
-	}
-}
-
 //
 //*******************************************************************************************************************************
 //static components of LLAPRFile
diff --git a/indra/llcommon/llthreadlocalstorage.cpp b/indra/llcommon/llthreadlocalstorage.cpp
new file mode 100644
index 0000000000..7858ee5429
--- /dev/null
+++ b/indra/llcommon/llthreadlocalstorage.cpp
@@ -0,0 +1,101 @@
+/** 
+ * @file llthreadlocalstorage.cpp
+ * @author Richard
+ * @date 2013-1-11
+ * @brief implementation of thread local storage utility classes
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llthreadlocalstorage.h"
+
+//
+//LLThreadLocalPointerBase
+//
+bool LLThreadLocalPointerBase::sInitialized = false;
+
+void LLThreadLocalPointerBase::set( void* value )
+{
+	llassert(sInitialized && mThreadKey);
+
+	apr_status_t result = apr_threadkey_private_set((void*)value, mThreadKey);
+	if (result != APR_SUCCESS)
+	{
+		ll_apr_warn_status(result);
+		llerrs << "Failed to set thread local data" << llendl;
+	}
+}
+
+void LLThreadLocalPointerBase::initStorage( )
+{
+	apr_status_t result = apr_threadkey_private_create(&mThreadKey, NULL, gAPRPoolp);
+	if (result != APR_SUCCESS)
+	{
+		ll_apr_warn_status(result);
+		llerrs << "Failed to allocate thread local data" << llendl;
+	}
+}
+
+void LLThreadLocalPointerBase::destroyStorage()
+{
+	if (sInitialized)
+	{
+		if (mThreadKey)
+		{
+			apr_status_t result = apr_threadkey_private_delete(mThreadKey);
+			if (result != APR_SUCCESS)
+			{
+				ll_apr_warn_status(result);
+				llerrs << "Failed to delete thread local data" << llendl;
+			}
+		}
+	}
+}
+
+void LLThreadLocalPointerBase::initAllThreadLocalStorage()
+{
+	if (!sInitialized)
+	{
+		for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances();
+			it != end_it;
+			++it)
+		{
+			(*it).initStorage();
+		}
+		sInitialized = true;
+	}
+}
+
+void LLThreadLocalPointerBase::destroyAllThreadLocalStorage()
+{
+	if (sInitialized)
+	{
+		//for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances();
+		//	it != end_it;
+		//	++it)
+		//{
+		//	(*it).destroyStorage();
+		//}
+		sInitialized = false;
+	}
+}
-- 
cgit v1.2.3


From 44cc14fbee8c9cb033dcb94d9c54f532427a5768 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 11 Jan 2013 13:11:07 -0800
Subject: fix for mac builds

---
 indra/llcommon/llthreadlocalstorage.h | 69 ++++++++++++++++++++++++++++-------
 1 file changed, 55 insertions(+), 14 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
index 5a38d54eea..91f45d4f5f 100644
--- a/indra/llcommon/llthreadlocalstorage.h
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -152,43 +152,48 @@ public:
 	virtual ~LLThreadLocalSingleton()
 	{
 		sInstance = NULL;
-		sInitState = DELETED;
+		setInitState(DELETED);
 	}
 
 	static void deleteSingleton()
 	{
 		delete sInstance;
 		sInstance = NULL;
-		sInitState = DELETED;
+		setInitState(DELETED);
 	}
 
 	static DERIVED_TYPE* getInstance()
 	{
-		if (sInitState == CONSTRUCTING)
+        EInitState init_state = getInitState();
+		if (init_state == CONSTRUCTING)
 		{
 			llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl;
 		}
 
-		if (sInitState == DELETED)
+		if (init_state == DELETED)
 		{
 			llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
 		}
 
-		if (!sInstance) 
+		if (!getIfExists())
 		{
-			sInitState = CONSTRUCTING;
+			setInitState(CONSTRUCTING);
 			sInstance = new DERIVED_TYPE(); 
-			sInitState = INITIALIZING;
+			setInitState(INITIALIZING);
 			sInstance->initSingleton(); 
-			sInitState = INITIALIZED;	
+			setInitState(INITIALIZED);
 		}
 
-		return sInstance;
+        return getIfExists();
 	}
 
 	static DERIVED_TYPE* getIfExists()
 	{
+#if LL_DARWIN
+        return sInstance.get();
+#else
 		return sInstance;
+#endif
 	}
 
 	// Reference version of getInstance()
@@ -202,16 +207,33 @@ public:
 	// Use this to avoid accessing singletons before the can safely be constructed
 	static bool instanceExists()
 	{
-		return sInitState == INITIALIZED;
+		return getInitState() == INITIALIZED;
 	}
 
 	// Has this singleton already been deleted?
 	// Use this to avoid accessing singletons from a static object's destructor
 	static bool destroyed()
 	{
-		return sInitState == DELETED;
+		return getInitState() == DELETED;
 	}
 private:
+    static EInitState getInitState()
+    {
+#if LL_DARWIN
+        return (EInitState)(int)sInitState.get();
+#else
+        return sInitState;
+#endif
+    }
+    
+    static void setInitState(EInitState state)
+    {
+#if LL_DARWIN
+        sInitState = (int*)state;
+#else
+        sInitState = state;
+#endif
+    }
 	LLThreadLocalSingleton(const LLThreadLocalSingleton& other);
 	virtual void initSingleton() {}
 
@@ -221,10 +243,13 @@ private:
 #elif LL_LINUX
 	static __thread DERIVED_TYPE* sInstance;
 	static __thread EInitState sInitState;
+#elif LL_DARWIN
+    static LLThreadLocalPointer<DERIVED_TYPE> sInstance;
+    static LLThreadLocalPointer<int> sInitState;
 #endif
 };
 
-#ifdef LL_WINDOWS
+#if LL_WINDOWS
 template<typename DERIVED_TYPE>
 __declspec(thread) DERIVED_TYPE* LLThreadLocalSingleton<DERIVED_TYPE>::sInstance = NULL;
 
@@ -236,6 +261,12 @@ __thread DERIVED_TYPE* LLThreadLocalSingleton<DERIVED_TYPE>::sInstance = NULL;
 
 template<typename DERIVED_TYPE>
 __thread typename LLThreadLocalSingleton<DERIVED_TYPE>::EInitState LLThreadLocalSingleton<DERIVED_TYPE>::sInitState = LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED;
+#elif LL_DARWIN
+template<typename DERIVED_TYPE>
+LLThreadLocalPointer<DERIVED_TYPE> LLThreadLocalSingleton<DERIVED_TYPE>::sInstance;
+
+template<typename DERIVED_TYPE>
+LLThreadLocalPointer<int> LLThreadLocalSingleton<DERIVED_TYPE>::sInitState;
 #endif
 
 template<typename DERIVED_TYPE>
@@ -249,7 +280,11 @@ public:
 
 	LL_FORCE_INLINE static DERIVED_TYPE* getInstance()
 	{
+#if LL_DARWIN
+        return sInstance.get();
+#else
 		return sInstance;
+#endif
 	}
 
 	LL_FORCE_INLINE static void setInstance(DERIVED_TYPE* instance)
@@ -258,18 +293,24 @@ public:
 	}
 
 private:
-#ifdef LL_WINDOWS
+#if LL_WINDOWS
 	static __declspec(thread) DERIVED_TYPE* sInstance;
 #elif LL_LINUX
 	static __thread DERIVED_TYPE* sInstance;
+#elif LL_DARWIN
+    static LLThreadLocalPointer<DERIVED_TYPE> sInstance;
 #endif
 };
 
+#if LL_WINDOWS
 template<typename DERIVED_TYPE>
-#ifdef LL_WINDOWS
 __declspec(thread) DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL;
 #elif LL_LINUX
+template<typename DERIVED_TYPE>
 __thread DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL;
+#elif LL_DARWIN
+template<typename DERIVED_TYPE>
+LLThreadLocalPointer<DERIVED_TYPE> LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance;
 #endif
 
 #endif // LL_LLTHREADLOCALSTORAGE_H
-- 
cgit v1.2.3


From 85df1df3c34115efa0e18d116f7923b88ec1dadf Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 11 Jan 2013 14:24:52 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system gcc 4.1 fixes

---
 indra/llcommon/llunit.h | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index c600883607..c43ca2ba18 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -75,9 +75,9 @@ struct LLUnit
 	typedef LLUnit<UNIT_TYPE, STORAGE_TYPE> self_t;
 	typedef STORAGE_TYPE storage_t;
 
-	// value initialization
-	LLUnit(storage_t value = storage_t())
-	:	mValue(value)
+	// default initialization
+	LLUnit()
+	:	mValue(storage_t())
 	{}
 
 	// unit initialization and conversion
@@ -85,6 +85,12 @@ struct LLUnit
 	LLUnit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
 	:	mValue(convert(other))
 	{}
+
+	// value initialization
+	template<typename CONVERTABLE_TYPE>
+	LLUnit(CONVERTABLE_TYPE value)
+	: mValue(value)
+	{}
 	
 	// value assignment
 	self_t& operator = (storage_t value)
-- 
cgit v1.2.3


From 512d7381eca7bc53bb31e9528e5a7c5df189e82d Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 11 Jan 2013 15:45:20 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system gcc 4.1 fixes

---
 indra/llcommon/llunit.h | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index c43ca2ba18..f43df3753a 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -76,8 +76,8 @@ struct LLUnit
 	typedef STORAGE_TYPE storage_t;
 
 	// default initialization
-	LLUnit()
-	:	mValue(storage_t())
+	LLUnit(storage_t value = storage_t())
+	:	mValue(value)
 	{}
 
 	// unit initialization and conversion
@@ -85,12 +85,6 @@ struct LLUnit
 	LLUnit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
 	:	mValue(convert(other))
 	{}
-
-	// value initialization
-	template<typename CONVERTABLE_TYPE>
-	LLUnit(CONVERTABLE_TYPE value)
-	: mValue(value)
-	{}
 	
 	// value assignment
 	self_t& operator = (storage_t value)
-- 
cgit v1.2.3


From 91a8383b4a0bbd2d48d2d84678f5bcc3701c2b9f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 11 Jan 2013 16:30:05 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system gcc 4.1 fixes

---
 indra/llcommon/llunit.h | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index f43df3753a..c2a31b7604 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -75,7 +75,7 @@ struct LLUnit
 	typedef LLUnit<UNIT_TYPE, STORAGE_TYPE> self_t;
 	typedef STORAGE_TYPE storage_t;
 
-	// default initialization
+	// value initialization
 	LLUnit(storage_t value = storage_t())
 	:	mValue(value)
 	{}
@@ -301,13 +301,13 @@ LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator - (SCALAR_TYPE first, LLUnitImp
 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)
 {
-	return LLUnit<UNIT_TYPE, STORAGE_TYPE>(first * second.value());
+	return LLUnit<UNIT_TYPE, STORAGE_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)
 {
-	return LLUnit<UNIT_TYPE, STORAGE_TYPE>(first.value() * second);
+	return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() * second));
 }
 
 template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2>
@@ -350,7 +350,7 @@ SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> secon
 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)
 {
-	return LLUnit<UNIT_TYPE, STORAGE_TYPE>(first.value() / second);
+	return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() / second));
 }
 
 template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2>
@@ -363,7 +363,7 @@ STORAGE_TYPE1 operator / (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_T
 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)
 {
-	return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>(first.value() / second);
+	return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() / second));
 }
 
 template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2>
-- 
cgit v1.2.3


From 20b2fa4052ae6789ec8894f33f4764a1f7233b24 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 14 Jan 2013 23:08:01 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system improved
 performance of fast timer stat gathering

---
 indra/llcommon/llfasttimer.cpp           | 28 ++++++++++++++--------------
 indra/llcommon/llfasttimer.h             | 19 ++++++++++---------
 indra/llcommon/lltrace.h                 |  5 +++--
 indra/llcommon/lltracerecording.cpp      |  4 ++--
 indra/llcommon/lltracethreadrecorder.cpp |  6 ++++--
 5 files changed, 33 insertions(+), 29 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index e6233a094e..37332da31c 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -199,10 +199,11 @@ void TimeBlock::processTimes()
 		{
 			TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 
-			if (accumulator->mLastCaller)
+			if (accumulator->mLastAccumulator)
 			{
-				timer.setParent(accumulator->mLastCaller);
-				accumulator->mParent = accumulator->mLastCaller;
+				TimeBlock* parent = accumulator->mLastAccumulator->mBlock;
+				timer.setParent(parent);
+				accumulator->mParent = parent;
 			}
 			// no need to push up tree on first use, flag can be set spuriously
 			accumulator->mMoveUpTree = false;
@@ -250,23 +251,22 @@ void TimeBlock::processTimes()
 
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
 	BlockTimer* cur_timer = stack_record->mActiveTimer;
-	TimeBlockAccumulator* accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
+	TimeBlockAccumulator* accumulator = stack_record->mAccumulator;
 	// root defined by parent pointing to self
 	while(cur_timer && cur_timer->mLastTimerData.mActiveTimer != cur_timer)
 	{
 		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
-		U64 self_time_delta = cumulative_time_delta - stack_record->mChildTime;
+		accumulator->mChildTimeCounter += stack_record->mChildTime;
 		stack_record->mChildTime = 0;
-		accumulator->mSelfTimeCounter += self_time_delta;
 		accumulator->mTotalTimeCounter += cumulative_time_delta;
 
 		cur_timer->mStartTime = cur_time;
 
 		stack_record = &cur_timer->mLastTimerData;
 		stack_record->mChildTime += cumulative_time_delta;
-		if (stack_record->mTimeBlock)
+		if (stack_record->mAccumulator)
 		{
-			accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
+			accumulator = stack_record->mAccumulator;
 		}
 
 		cur_timer = cur_timer->mLastTimerData.mActiveTimer;
@@ -282,7 +282,7 @@ void TimeBlock::processTimes()
 		TimeBlock& timer = *it;
 		TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 
-		accumulator->mLastCaller = NULL;
+		accumulator->mLastAccumulator = NULL;
 		accumulator->mMoveUpTree = false;
 	}
 
@@ -417,10 +417,10 @@ void TimeBlock::writeLog(std::ostream& os)
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 TimeBlockAccumulator::TimeBlockAccumulator() 
-:	mSelfTimeCounter(0),
+:	mChildTimeCounter(0),
 	mTotalTimeCounter(0),
 	mCalls(0),
-	mLastCaller(NULL),
+	mLastAccumulator(NULL),
 	mActiveCount(0),
 	mMoveUpTree(false),
 	mParent(NULL)
@@ -428,10 +428,10 @@ TimeBlockAccumulator::TimeBlockAccumulator()
 
 void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
 {
-	mSelfTimeCounter += other.mSelfTimeCounter;
+	mChildTimeCounter += other.mChildTimeCounter;
 	mTotalTimeCounter += other.mTotalTimeCounter;
 	mCalls += other.mCalls;
-	mLastCaller = other.mLastCaller;
+	mLastAccumulator = other.mLastAccumulator;
 	mActiveCount = other.mActiveCount;
 	mMoveUpTree = other.mMoveUpTree;
 	mParent = other.mParent;
@@ -440,7 +440,7 @@ void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
 void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
 {
 	mTotalTimeCounter = 0;
-	mSelfTimeCounter = 0;
+	mChildTimeCounter = 0;
 	mCalls = 0;
 }
 
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index fb2868ff98..2d87629561 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -40,9 +40,9 @@ namespace LLTrace
 
 struct BlockTimerStackRecord
 {
-	class BlockTimer*	mActiveTimer;
-	class TimeBlock*	mTimeBlock;
-	U64					mChildTime;
+	class BlockTimer*			mActiveTimer;
+	class TimeBlockAccumulator*	mAccumulator;
+	U64							mChildTime;
 };
 
 class ThreadTimerStack 
@@ -277,7 +277,7 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 	mStartTime = TimeBlock::getCPUClockCount64();
 
 	BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
-	TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
+	TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 	accumulator->mActiveCount++;
 	// keep current parent as long as it is active when we are
 	accumulator->mMoveUpTree |= (accumulator->mParent->getPrimaryAccumulator()->mActiveCount == 0);
@@ -286,7 +286,7 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 	mLastTimerData = *cur_timer_data;
 	// push new information
 	cur_timer_data->mActiveTimer = this;
-	cur_timer_data->mTimeBlock = &timer;
+	cur_timer_data->mAccumulator = accumulator;
 	cur_timer_data->mChildTime = 0;
 #endif
 }
@@ -296,21 +296,22 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 #if FAST_TIMER_ON
 	U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
 	BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
-	TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
+	TimeBlockAccumulator* accumulator = cur_timer_data->mAccumulator;
 
 	accumulator->mCalls++;
-	accumulator->mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
+	accumulator->mChildTimeCounter += cur_timer_data->mChildTime;
 	accumulator->mTotalTimeCounter += total_time;
 	accumulator->mActiveCount--;
 
 	// store last caller to bootstrap tree creation
 	// do this in the destructor in case of recursion to get topmost caller
-	accumulator->mLastCaller = mLastTimerData.mTimeBlock;
+	accumulator->mLastAccumulator = mLastTimerData.mAccumulator;
 
 	// we are only tracking self time, so subtract our total time delta from parents
 	mLastTimerData.mChildTime += total_time;
 
-	*ThreadTimerStack::getIfExists() = mLastTimerData;
+	//pop stack
+	*cur_timer_data = mLastTimerData;
 #endif
 }
 
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index ab4ad59e3d..1d3c376a58 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -446,11 +446,12 @@ namespace LLTrace
 		//
 		// members
 		//
-		U64							mSelfTimeCounter,
+		U64							mChildTimeCounter,
 									mTotalTimeCounter;
 		U32							mCalls;
+		class TimeBlock*			mBlock;			// block associated with this accumulator
 		class TimeBlock*			mParent;		// last acknowledged parent of this time block
-		class TimeBlock*			mLastCaller;	// used to bootstrap tree construction
+		TimeBlockAccumulator*		mLastAccumulator;	// 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
 
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index c110e64380..ddd25bfe87 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -179,7 +179,7 @@ LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumul
 
 LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const
 {
-	return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / (F64)LLTrace::TimeBlock::countsPerSecond();
+	return ((F64)(*mStackTimers)[stat.getIndex()].mTotalTimeCounter - (F64)(*mStackTimers)[stat.getIndex()].mChildTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
 
@@ -195,7 +195,7 @@ LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccu
 
 LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const
 {
-	return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
+	return ((F64)(*mStackTimers)[stat.getIndex()].mTotalTimeCounter - (F64)(*mStackTimers)[stat.getIndex()].mChildTimeCounter) / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
 }
 
 F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 7b493a651e..9375c7bea3 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -43,7 +43,7 @@ ThreadRecorder::ThreadRecorder()
 	TimeBlock& root_time_block = TimeBlock::getRootTimeBlock();
 
 	ThreadTimerStack* timer_stack = ThreadTimerStack::getInstance();
-	timer_stack->mTimeBlock = &root_time_block;
+	timer_stack->mAccumulator = root_time_block.getPrimaryAccumulator();
 	timer_stack->mActiveTimer = NULL;
 
 	mNumTimeBlockTreeNodes = AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer()->size();
@@ -61,7 +61,9 @@ ThreadRecorder::ThreadRecorder()
 		tree_node.mBlock = &time_block;
 		tree_node.mParent = &root_time_block;
 
-		it->getPrimaryAccumulator()->mParent = &root_time_block;
+		TimeBlockAccumulator* accumulator = it->getPrimaryAccumulator();
+		accumulator->mParent = &root_time_block;
+		accumulator->mBlock = time_block;
 	}
 
 	mRootTimer = new BlockTimer(root_time_block);
-- 
cgit v1.2.3


From 486743e77efaa3926ddc2c0d666a0a7192700475 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 14 Jan 2013 23:10:02 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system improved
 performance of fast timer stat gathering (fixed typo)

---
 indra/llcommon/lltracethreadrecorder.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 9375c7bea3..bc1d19e72c 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -63,7 +63,7 @@ ThreadRecorder::ThreadRecorder()
 
 		TimeBlockAccumulator* accumulator = it->getPrimaryAccumulator();
 		accumulator->mParent = &root_time_block;
-		accumulator->mBlock = time_block;
+		accumulator->mBlock = &time_block;
 	}
 
 	mRootTimer = new BlockTimer(root_time_block);
-- 
cgit v1.2.3


From a74509355669d059d2645d3239c9499db6818b88 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 15 Jan 2013 10:12:23 -0800
Subject: Attempted fix for thread local storage on OS X

---
 indra/llcommon/llthreadlocalstorage.h | 58 ++++++++++++++++++++++++++---------
 1 file changed, 44 insertions(+), 14 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
index 91f45d4f5f..c8b7c5e229 100644
--- a/indra/llcommon/llthreadlocalstorage.h
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -151,15 +151,17 @@ public:
 	
 	virtual ~LLThreadLocalSingleton()
 	{
-		sInstance = NULL;
+#if LL_DARWIN
+        //pthread_setspecific(sInstanceKey, NULL);
+#else
+        sInstance = NULL;
+#endif
 		setInitState(DELETED);
 	}
 
 	static void deleteSingleton()
 	{
-		delete sInstance;
-		sInstance = NULL;
-		setInitState(DELETED);
+		delete getIfExists();
 	}
 
 	static DERIVED_TYPE* getInstance()
@@ -178,9 +180,24 @@ public:
 		if (!getIfExists())
 		{
 			setInitState(CONSTRUCTING);
-			sInstance = new DERIVED_TYPE(); 
+            DERIVED_TYPE* instancep = new DERIVED_TYPE();
+#if LL_DARWIN
+            /*static S32 sKeyCreated = pthread_key_create(&sInstanceKey, NULL);
+            if (sKeyCreated != 0)
+            {
+                llerrs << "Could not create thread local storage" << llendl;
+            }
+            
+            S32 result = pthread_setspecific(sInstanceKey, (void*)instancep);
+            if (result != 0)
+            {
+                llerrs << "Could not set thread local storage" << llendl;
+            }*/
+#else
+			sInstance = instancep;
+#endif
 			setInitState(INITIALIZING);
-			sInstance->initSingleton(); 
+			instancep->initSingleton();
 			setInitState(INITIALIZED);
 		}
 
@@ -190,7 +207,7 @@ public:
 	static DERIVED_TYPE* getIfExists()
 	{
 #if LL_DARWIN
-        return sInstance.get();
+        return NULL;//(DERIVED_TYPE*)pthread_getspecific(sInstanceKey);
 #else
 		return sInstance;
 #endif
@@ -217,10 +234,23 @@ public:
 		return getInitState() == DELETED;
 	}
 private:
+#if LL_DARWIN
+    static EInitState& threadLocalInitState()
+    {
+        /*static S32 sKeyCreated = pthread_key_create(&sInitStateKey, NULL);
+        if (sKeyCreated != 0)
+        {
+            llerrs << "Could not create thread local storage" << llendl;
+        }
+        return *(EInitState*)pthread_getspecific(sInitStateKey);*/
+        static EInitState state;
+        return state;
+    }
+#endif
     static EInitState getInitState()
     {
 #if LL_DARWIN
-        return (EInitState)(int)sInitState.get();
+        return threadLocalInitState();
 #else
         return sInitState;
 #endif
@@ -229,7 +259,7 @@ private:
     static void setInitState(EInitState state)
     {
 #if LL_DARWIN
-        sInitState = (int*)state;
+        threadLocalInitState() = state;
 #else
         sInitState = state;
 #endif
@@ -244,8 +274,8 @@ private:
 	static __thread DERIVED_TYPE* sInstance;
 	static __thread EInitState sInitState;
 #elif LL_DARWIN
-    static LLThreadLocalPointer<DERIVED_TYPE> sInstance;
-    static LLThreadLocalPointer<int> sInitState;
+    //static pthread_key_t sInstanceKey;
+    //static pthread_key_t sInitStateKey;
 #endif
 };
 
@@ -262,11 +292,11 @@ __thread DERIVED_TYPE* LLThreadLocalSingleton<DERIVED_TYPE>::sInstance = NULL;
 template<typename DERIVED_TYPE>
 __thread typename LLThreadLocalSingleton<DERIVED_TYPE>::EInitState LLThreadLocalSingleton<DERIVED_TYPE>::sInitState = LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED;
 #elif LL_DARWIN
-template<typename DERIVED_TYPE>
-LLThreadLocalPointer<DERIVED_TYPE> LLThreadLocalSingleton<DERIVED_TYPE>::sInstance;
+/*template<typename DERIVED_TYPE>
+pthread_key_t LLThreadLocalSingleton<DERIVED_TYPE>::sInstanceKey;
 
 template<typename DERIVED_TYPE>
-LLThreadLocalPointer<int> LLThreadLocalSingleton<DERIVED_TYPE>::sInitState;
+pthread_key_t LLThreadLocalSingleton<DERIVED_TYPE>::sInitStateKey;*/
 #endif
 
 template<typename DERIVED_TYPE>
-- 
cgit v1.2.3


From 670d03ceb83b92c9bb98d10bb37fba6f75971a2f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 15 Jan 2013 14:28:32 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system fixed
 LLExtendableRecording to actually accumulator recording time period renamed
 and updated LLStopWatchControlsMixin::initTo to setPlayState

---
 indra/llcommon/lltracerecording.cpp | 42 ++++++++++++++++++++++---------------
 indra/llcommon/lltracerecording.h   | 21 +++++++++----------
 2 files changed, 35 insertions(+), 28 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index ddd25bfe87..f45226eb9a 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -60,7 +60,7 @@ Recording::Recording( const Recording& other )
 	mStackTimers       = other.mStackTimers;
 	mMemStats		   = other.mMemStats;
 
-	LLStopWatchControlsMixin<Recording>::initTo(other.getPlayState());
+	LLStopWatchControlsMixin<Recording>::setPlayState(other.getPlayState());
 }
 
 
@@ -345,14 +345,14 @@ U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<S64> >& st
 // PeriodicRecording
 ///////////////////////////////////////////////////////////////////////
 
-PeriodicRecording::PeriodicRecording( S32 num_periods, EStopWatchState state) 
+PeriodicRecording::PeriodicRecording( S32 num_periods, EPlayState state) 
 :	mNumPeriods(num_periods),
 	mCurPeriod(0),
 	mTotalValid(false),
 	mRecordingPeriods( new Recording[num_periods])
 {
 	llassert(mNumPeriods > 0);
-	initTo(state);
+	setPlayState(state);
 }
 
 PeriodicRecording::PeriodicRecording(PeriodicRecording& other)
@@ -377,7 +377,7 @@ PeriodicRecording::~PeriodicRecording()
 
 void PeriodicRecording::nextPeriod()
 {
-	EStopWatchState play_state = getPlayState();
+	EPlayState play_state = getPlayState();
 	Recording& old_recording = getCurRecordingPeriod();
 	mCurPeriod = (mCurPeriod + 1) % mNumPeriods;
 	old_recording.splitTo(getCurRecordingPeriod());
@@ -458,8 +458,14 @@ void PeriodicRecording::splitFrom(PeriodicRecording& other)
 
 void ExtendableRecording::extend()
 {
+	// stop recording to get latest data
+	mPotentialRecording.stop();
+	// 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::start()
@@ -514,7 +520,7 @@ PeriodicRecording& get_frame_recording()
 
 void LLStopWatchControlsMixinCommon::start()
 {
-	switch (mState)
+	switch (mPlayState)
 	{
 	case STOPPED:
 		handleReset();
@@ -530,12 +536,12 @@ void LLStopWatchControlsMixinCommon::start()
 		llassert(false);
 		break;
 	}
-	mState = STARTED;
+	mPlayState = STARTED;
 }
 
 void LLStopWatchControlsMixinCommon::stop()
 {
-	switch (mState)
+	switch (mPlayState)
 	{
 	case STOPPED:
 		break;
@@ -549,12 +555,12 @@ void LLStopWatchControlsMixinCommon::stop()
 		llassert(false);
 		break;
 	}
-	mState = STOPPED;
+	mPlayState = STOPPED;
 }
 
 void LLStopWatchControlsMixinCommon::pause()
 {
-	switch (mState)
+	switch (mPlayState)
 	{
 	case STOPPED:
 		break;
@@ -567,12 +573,12 @@ void LLStopWatchControlsMixinCommon::pause()
 		llassert(false);
 		break;
 	}
-	mState = PAUSED;
+	mPlayState = PAUSED;
 }
 
 void LLStopWatchControlsMixinCommon::resume()
 {
-	switch (mState)
+	switch (mPlayState)
 	{
 	case STOPPED:
 		handleStart();
@@ -586,12 +592,12 @@ void LLStopWatchControlsMixinCommon::resume()
 		llassert(false);
 		break;
 	}
-	mState = STARTED;
+	mPlayState = STARTED;
 }
 
 void LLStopWatchControlsMixinCommon::restart()
 {
-	switch (mState)
+	switch (mPlayState)
 	{
 	case STOPPED:
 		handleReset();
@@ -608,7 +614,7 @@ void LLStopWatchControlsMixinCommon::restart()
 		llassert(false);
 		break;
 	}
-	mState = STARTED;
+	mPlayState = STARTED;
 }
 
 void LLStopWatchControlsMixinCommon::reset()
@@ -616,21 +622,23 @@ void LLStopWatchControlsMixinCommon::reset()
 	handleReset();
 }
 
-void LLStopWatchControlsMixinCommon::initTo( EStopWatchState state )
+void LLStopWatchControlsMixinCommon::setPlayState( EPlayState state )
 {
 	switch(state)
 	{
 	case STOPPED:
+		stop();
 		break;
 	case PAUSED:
+		pause();
 		break;
 	case STARTED:
-		handleStart();
+		start();
 		break;
 	default:
 		llassert(false);
 		break;
 	}
 
-	mState = state;
+	mPlayState = state;
 }
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index aa3200e5ad..e6b5e85f90 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -39,7 +39,7 @@ class LLStopWatchControlsMixinCommon
 public:
 	virtual ~LLStopWatchControlsMixinCommon() {}
 
-	enum EStopWatchState
+	enum EPlayState
 	{
 		STOPPED,
 		PAUSED,
@@ -53,19 +53,18 @@ public:
 	virtual void restart();
 	virtual void reset();
 
-	bool isStarted() const { return mState == STARTED; }
-	bool isPaused() const  { return mState == PAUSED; }
-	bool isStopped() const { return mState == STOPPED; }
-	EStopWatchState getPlayState() const { return mState; }
+	bool isStarted() const { return mPlayState == STARTED; }
+	bool isPaused() const  { return mPlayState == PAUSED; }
+	bool isStopped() const { return mPlayState == STOPPED; }
+	EPlayState getPlayState() const { return mPlayState; }
+	// force play state to specific value by calling appropriate handle* methods
+	void setPlayState(EPlayState state);
 
 protected:
 	LLStopWatchControlsMixinCommon()
-	:	mState(STOPPED)
+	:	mPlayState(STOPPED)
 	{}
 
-	// derived classes can call this from their copy constructor in order
-	// to duplicate play state of source
-	void initTo(EStopWatchState state);
 private:
 	// trigger active behavior (without reset)
 	virtual void handleStart(){};
@@ -74,7 +73,7 @@ private:
 	// clear accumulated state, can be called while started
 	virtual void handleReset(){};
 
-	EStopWatchState mState;
+	EPlayState mPlayState;
 };
 
 template<typename DERIVED>
@@ -245,7 +244,7 @@ namespace LLTrace
 	:	public LLStopWatchControlsMixin<PeriodicRecording>
 	{
 	public:
-		PeriodicRecording(S32 num_periods, EStopWatchState state = STOPPED);
+		PeriodicRecording(S32 num_periods, EPlayState state = STOPPED);
 		PeriodicRecording(PeriodicRecording& recording);
 		~PeriodicRecording();
 
-- 
cgit v1.2.3


From 970fbdbeb80f20811fb286f6731b854f9b20a76e Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Tue, 15 Jan 2013 20:28:05 -0700
Subject: a minor change to LLTrace::ExtendableRecording, make its functions
 public.

---
 indra/llcommon/lltracerecording.h | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index aa3200e5ad..5105874ba1 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -390,6 +390,7 @@ namespace LLTrace
 	class ExtendableRecording
 	:	public LLStopWatchControlsMixin<ExtendableRecording>
 	{
+	public:
 		void extend();
 
 		// implementation for LLStopWatchControlsMixin
@@ -401,6 +402,8 @@ namespace LLTrace
 		/*virtual*/ void reset();
 		/*virtual*/ void splitTo(ExtendableRecording& other);
 		/*virtual*/ void splitFrom(ExtendableRecording& other);
+
+		const Recording& getAcceptedRecording() const {return mAcceptedRecording;}
 	private:
 		Recording mAcceptedRecording;
 		Recording mPotentialRecording;
-- 
cgit v1.2.3


From a0413bdef71d804bbf008cf319f54a5a47efb29c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 17 Jan 2013 20:04:26 -0800
Subject: fix for mac thread local storage

---
 indra/llcommon/llthreadlocalstorage.h | 74 +++++++++++++++++++++++------------
 1 file changed, 48 insertions(+), 26 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
index c8b7c5e229..fd44589299 100644
--- a/indra/llcommon/llthreadlocalstorage.h
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -152,7 +152,7 @@ public:
 	virtual ~LLThreadLocalSingleton()
 	{
 #if LL_DARWIN
-        //pthread_setspecific(sInstanceKey, NULL);
+        pthread_setspecific(sInstanceKey, NULL);
 #else
         sInstance = NULL;
 #endif
@@ -182,17 +182,12 @@ public:
 			setInitState(CONSTRUCTING);
             DERIVED_TYPE* instancep = new DERIVED_TYPE();
 #if LL_DARWIN
-            /*static S32 sKeyCreated = pthread_key_create(&sInstanceKey, NULL);
-            if (sKeyCreated != 0)
-            {
-                llerrs << "Could not create thread local storage" << llendl;
-            }
-            
+            createTLSInstance();
             S32 result = pthread_setspecific(sInstanceKey, (void*)instancep);
             if (result != 0)
             {
                 llerrs << "Could not set thread local storage" << llendl;
-            }*/
+            }
 #else
 			sInstance = instancep;
 #endif
@@ -207,7 +202,7 @@ public:
 	static DERIVED_TYPE* getIfExists()
 	{
 #if LL_DARWIN
-        return NULL;//(DERIVED_TYPE*)pthread_getspecific(sInstanceKey);
+        return (DERIVED_TYPE*)pthread_getspecific(sInstanceKey);
 #else
 		return sInstance;
 #endif
@@ -235,22 +230,29 @@ public:
 	}
 private:
 #if LL_DARWIN
-    static EInitState& threadLocalInitState()
+    static void createTLSInitState()
+    {
+        static S32 key_created = pthread_key_create(&sInitStateKey, NULL);
+        if (key_created != 0)
+        {
+            llerrs << "Could not create thread local storage" << llendl;
+        }
+    }
+    
+    static void createTLSInstance()
     {
-        /*static S32 sKeyCreated = pthread_key_create(&sInitStateKey, NULL);
-        if (sKeyCreated != 0)
+        static S32 key_created = pthread_key_create(&sInstanceKey, NULL);
+        if (key_created != 0)
         {
             llerrs << "Could not create thread local storage" << llendl;
         }
-        return *(EInitState*)pthread_getspecific(sInitStateKey);*/
-        static EInitState state;
-        return state;
     }
 #endif
     static EInitState getInitState()
     {
 #if LL_DARWIN
-        return threadLocalInitState();
+        createTLSInitState();
+        return (EInitState)(int)pthread_getspecific(sInitStateKey);
 #else
         return sInitState;
 #endif
@@ -259,7 +261,8 @@ private:
     static void setInitState(EInitState state)
     {
 #if LL_DARWIN
-        threadLocalInitState() = state;
+        createTLSInitState();
+        pthread_setspecific(sInitStateKey, (void*)state);
 #else
         sInitState = state;
 #endif
@@ -274,8 +277,8 @@ private:
 	static __thread DERIVED_TYPE* sInstance;
 	static __thread EInitState sInitState;
 #elif LL_DARWIN
-    //static pthread_key_t sInstanceKey;
-    //static pthread_key_t sInitStateKey;
+    static pthread_key_t sInstanceKey;
+    static pthread_key_t sInitStateKey;
 #endif
 };
 
@@ -292,11 +295,12 @@ __thread DERIVED_TYPE* LLThreadLocalSingleton<DERIVED_TYPE>::sInstance = NULL;
 template<typename DERIVED_TYPE>
 __thread typename LLThreadLocalSingleton<DERIVED_TYPE>::EInitState LLThreadLocalSingleton<DERIVED_TYPE>::sInitState = LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED;
 #elif LL_DARWIN
-/*template<typename DERIVED_TYPE>
+template<typename DERIVED_TYPE>
 pthread_key_t LLThreadLocalSingleton<DERIVED_TYPE>::sInstanceKey;
 
 template<typename DERIVED_TYPE>
-pthread_key_t LLThreadLocalSingleton<DERIVED_TYPE>::sInitStateKey;*/
+pthread_key_t LLThreadLocalSingleton<DERIVED_TYPE>::sInitStateKey;
+
 #endif
 
 template<typename DERIVED_TYPE>
@@ -305,13 +309,14 @@ class LLThreadLocalSingletonPointer
 public:
 	void operator =(DERIVED_TYPE* value)
 	{
-		sInstance = value;
+		setInstance(value);
 	}
-
+    
 	LL_FORCE_INLINE static DERIVED_TYPE* getInstance()
 	{
 #if LL_DARWIN
-        return sInstance.get();
+        createTLSKey();
+        return (DERIVED_TYPE*)pthread_getspecific(sInstanceKey);
 #else
 		return sInstance;
 #endif
@@ -319,7 +324,12 @@ public:
 
 	LL_FORCE_INLINE static void setInstance(DERIVED_TYPE* instance)
 	{
+#if LL_DARWIN
+        createTLSKey();
+        pthread_setspecific(sInstanceKey, (void*)instance);
+#else
 		sInstance = instance;
+#endif
 	}
 
 private:
@@ -328,7 +338,19 @@ private:
 #elif LL_LINUX
 	static __thread DERIVED_TYPE* sInstance;
 #elif LL_DARWIN
-    static LLThreadLocalPointer<DERIVED_TYPE> sInstance;
+    static void TLSError()
+    {
+        llerrs << "Could not create thread local storage" << llendl;
+    }
+    static void createTLSKey()
+    {
+        static S32 key_created = pthread_key_create(&sInstanceKey, NULL);
+        if (key_created != 0)
+        {
+            llerrs << "Could not create thread local storage" << llendl;
+        }
+    }
+    static pthread_key_t sInstanceKey;
 #endif
 };
 
@@ -340,7 +362,7 @@ template<typename DERIVED_TYPE>
 __thread DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL;
 #elif LL_DARWIN
 template<typename DERIVED_TYPE>
-LLThreadLocalPointer<DERIVED_TYPE> LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance;
+pthread_key_t LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstanceKey;
 #endif
 
 #endif // LL_LLTHREADLOCALSTORAGE_H
-- 
cgit v1.2.3


From 43a92d01afdb4f1dd4003059b79f87e9687527a1 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 17 Jan 2013 20:11:43 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system fixed some
 uninitialized variables root timer accumulator was being initialized to NULL

---
 indra/llcommon/llfasttimer.cpp           | 30 +++++++++++++++++-------------
 indra/llcommon/llfasttimer.h             | 11 ++++++-----
 indra/llcommon/lltracethreadrecorder.cpp |  6 ++++--
 3 files changed, 27 insertions(+), 20 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 37332da31c..b4a422816e 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -183,7 +183,6 @@ void TimeBlock::processTimes()
 {
 	get_clock_count(); // good place to calculate clock frequency
 	U64 cur_time = getCPUClockCount64();
-	BlockTimerStackRecord* stack_record = ThreadTimerStack::getInstance();
 
 	// set up initial tree
 	for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(); 
@@ -202,6 +201,7 @@ void TimeBlock::processTimes()
 			if (accumulator->mLastAccumulator)
 			{
 				TimeBlock* parent = accumulator->mLastAccumulator->mBlock;
+				llassert(parent);
 				timer.setParent(parent);
 				accumulator->mParent = parent;
 			}
@@ -250,26 +250,28 @@ void TimeBlock::processTimes()
 	}
 
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
-	BlockTimer* cur_timer = stack_record->mActiveTimer;
-	TimeBlockAccumulator* accumulator = stack_record->mAccumulator;
+	BlockTimerStackRecord* stack_record			= ThreadTimerStack::getInstance();
+	BlockTimer* cur_timer						= stack_record->mActiveTimer;
+	TimeBlockAccumulator* accumulator			= stack_record->mAccumulator;
+
+	llassert(accumulator);
+
 	// root defined by parent pointing to self
-	while(cur_timer && cur_timer->mLastTimerData.mActiveTimer != cur_timer)
+	while(cur_timer && cur_timer->mParentTimerData.mActiveTimer != cur_timer)
 	{
 		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
+	
+		accumulator->mTotalTimeCounter += cumulative_time_delta;
 		accumulator->mChildTimeCounter += stack_record->mChildTime;
 		stack_record->mChildTime = 0;
-		accumulator->mTotalTimeCounter += cumulative_time_delta;
 
 		cur_timer->mStartTime = cur_time;
 
-		stack_record = &cur_timer->mLastTimerData;
-		stack_record->mChildTime += cumulative_time_delta;
-		if (stack_record->mAccumulator)
-		{
-			accumulator = stack_record->mAccumulator;
-		}
+		stack_record = &cur_timer->mParentTimerData;
+		accumulator = stack_record->mAccumulator;
+		cur_timer = stack_record->mActiveTimer;
 
-		cur_timer = cur_timer->mLastTimerData.mActiveTimer;
+		stack_record->mChildTime += cumulative_time_delta;
 	}
 
 
@@ -423,7 +425,8 @@ TimeBlockAccumulator::TimeBlockAccumulator()
 	mLastAccumulator(NULL),
 	mActiveCount(0),
 	mMoveUpTree(false),
-	mParent(NULL)
+	mParent(NULL),
+	mBlock(NULL)
 {}
 
 void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
@@ -435,6 +438,7 @@ void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
 	mActiveCount = other.mActiveCount;
 	mMoveUpTree = other.mMoveUpTree;
 	mParent = other.mParent;
+	mBlock = other.mBlock;
 }
 
 void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 2d87629561..06de8ea6ee 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -74,7 +74,7 @@ public:
 private:
 
 	U64				mStartTime;
-	BlockTimerStackRecord	mLastTimerData;
+	BlockTimerStackRecord	mParentTimerData;
 };
 
 // stores a "named" timer instance to be reused via multiple BlockTimer stack instances
@@ -280,10 +280,11 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 	TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 	accumulator->mActiveCount++;
 	// keep current parent as long as it is active when we are
+	llassert(accumulator->mParent);
 	accumulator->mMoveUpTree |= (accumulator->mParent->getPrimaryAccumulator()->mActiveCount == 0);
 
 	// store top of stack
-	mLastTimerData = *cur_timer_data;
+	mParentTimerData = *cur_timer_data;
 	// push new information
 	cur_timer_data->mActiveTimer = this;
 	cur_timer_data->mAccumulator = accumulator;
@@ -305,13 +306,13 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 
 	// store last caller to bootstrap tree creation
 	// do this in the destructor in case of recursion to get topmost caller
-	accumulator->mLastAccumulator = mLastTimerData.mAccumulator;
+	accumulator->mLastAccumulator = mParentTimerData.mAccumulator;
 
 	// we are only tracking self time, so subtract our total time delta from parents
-	mLastTimerData.mChildTime += total_time;
+	mParentTimerData.mChildTime += total_time;
 
 	//pop stack
-	*cur_timer_data = mLastTimerData;
+	*cur_timer_data = mParentTimerData;
 #endif
 }
 
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index bc1d19e72c..7c5995a104 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -43,14 +43,16 @@ ThreadRecorder::ThreadRecorder()
 	TimeBlock& root_time_block = TimeBlock::getRootTimeBlock();
 
 	ThreadTimerStack* timer_stack = ThreadTimerStack::getInstance();
-	timer_stack->mAccumulator = root_time_block.getPrimaryAccumulator();
-	timer_stack->mActiveTimer = NULL;
 
 	mNumTimeBlockTreeNodes = AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer()->size();
 	mTimeBlockTreeNodes = new TimeBlockTreeNode[mNumTimeBlockTreeNodes];
 
 	mThreadRecording.start();
 
+	timer_stack->mAccumulator = root_time_block.getPrimaryAccumulator();
+	timer_stack->mActiveTimer = NULL;
+
+
 	// initialize time block parent pointers
 	for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(); 
 		it != end_it; 
-- 
cgit v1.2.3


From e975ae35ab57f56adfaed64bc108240a5013f040 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 18 Jan 2013 15:59:16 -0800
Subject: SH-3406 WIP convert fast timers to lltrace system fixed crash on
 startup

---
 indra/llcommon/llfasttimer.cpp           | 26 ++++++++++----------------
 indra/llcommon/llfasttimer.h             | 15 +++++++--------
 indra/llcommon/lltrace.h                 |  3 +--
 indra/llcommon/lltracethreadrecorder.cpp | 10 +++-------
 4 files changed, 21 insertions(+), 33 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index b4a422816e..ea4e1a89a2 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -198,12 +198,10 @@ void TimeBlock::processTimes()
 		{
 			TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 
-			if (accumulator->mLastAccumulator)
+			if (accumulator->mLastCaller)
 			{
-				TimeBlock* parent = accumulator->mLastAccumulator->mBlock;
-				llassert(parent);
-				timer.setParent(parent);
-				accumulator->mParent = parent;
+				timer.setParent(accumulator->mLastCaller);
+				accumulator->mParent = accumulator->mLastCaller;
 			}
 			// no need to push up tree on first use, flag can be set spuriously
 			accumulator->mMoveUpTree = false;
@@ -252,10 +250,8 @@ void TimeBlock::processTimes()
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
 	BlockTimerStackRecord* stack_record			= ThreadTimerStack::getInstance();
 	BlockTimer* cur_timer						= stack_record->mActiveTimer;
-	TimeBlockAccumulator* accumulator			= stack_record->mAccumulator;
-
-	llassert(accumulator);
-
+	TimeBlockAccumulator* accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
+	
 	// root defined by parent pointing to self
 	while(cur_timer && cur_timer->mParentTimerData.mActiveTimer != cur_timer)
 	{
@@ -268,7 +264,7 @@ void TimeBlock::processTimes()
 		cur_timer->mStartTime = cur_time;
 
 		stack_record = &cur_timer->mParentTimerData;
-		accumulator = stack_record->mAccumulator;
+		accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
 		cur_timer = stack_record->mActiveTimer;
 
 		stack_record->mChildTime += cumulative_time_delta;
@@ -284,7 +280,7 @@ void TimeBlock::processTimes()
 		TimeBlock& timer = *it;
 		TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 
-		accumulator->mLastAccumulator = NULL;
+		accumulator->mLastCaller = NULL;
 		accumulator->mMoveUpTree = false;
 	}
 
@@ -422,11 +418,10 @@ TimeBlockAccumulator::TimeBlockAccumulator()
 :	mChildTimeCounter(0),
 	mTotalTimeCounter(0),
 	mCalls(0),
-	mLastAccumulator(NULL),
+	mLastCaller(NULL),
 	mActiveCount(0),
 	mMoveUpTree(false),
-	mParent(NULL),
-	mBlock(NULL)
+	mParent(NULL)
 {}
 
 void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
@@ -434,11 +429,10 @@ void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
 	mChildTimeCounter += other.mChildTimeCounter;
 	mTotalTimeCounter += other.mTotalTimeCounter;
 	mCalls += other.mCalls;
-	mLastAccumulator = other.mLastAccumulator;
+	mLastCaller = other.mLastCaller;
 	mActiveCount = other.mActiveCount;
 	mMoveUpTree = other.mMoveUpTree;
 	mParent = other.mParent;
-	mBlock = other.mBlock;
 }
 
 void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 06de8ea6ee..726db70fbe 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -40,9 +40,9 @@ namespace LLTrace
 
 struct BlockTimerStackRecord
 {
-	class BlockTimer*			mActiveTimer;
-	class TimeBlockAccumulator*	mAccumulator;
-	U64							mChildTime;
+	class BlockTimer*	mActiveTimer;
+	class TimeBlock*	mTimeBlock;
+	U64					mChildTime;
 };
 
 class ThreadTimerStack 
@@ -73,7 +73,7 @@ public:
 
 private:
 
-	U64				mStartTime;
+	U64						mStartTime;
 	BlockTimerStackRecord	mParentTimerData;
 };
 
@@ -280,14 +280,13 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 	TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 	accumulator->mActiveCount++;
 	// keep current parent as long as it is active when we are
-	llassert(accumulator->mParent);
 	accumulator->mMoveUpTree |= (accumulator->mParent->getPrimaryAccumulator()->mActiveCount == 0);
 
 	// store top of stack
 	mParentTimerData = *cur_timer_data;
 	// push new information
 	cur_timer_data->mActiveTimer = this;
-	cur_timer_data->mAccumulator = accumulator;
+	cur_timer_data->mTimeBlock = &timer;
 	cur_timer_data->mChildTime = 0;
 #endif
 }
@@ -297,7 +296,7 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 #if FAST_TIMER_ON
 	U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
 	BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
-	TimeBlockAccumulator* accumulator = cur_timer_data->mAccumulator;
+	TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
 
 	accumulator->mCalls++;
 	accumulator->mChildTimeCounter += cur_timer_data->mChildTime;
@@ -306,7 +305,7 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 
 	// store last caller to bootstrap tree creation
 	// do this in the destructor in case of recursion to get topmost caller
-	accumulator->mLastAccumulator = mParentTimerData.mAccumulator;
+	accumulator->mLastCaller = mParentTimerData.mTimeBlock;
 
 	// we are only tracking self time, so subtract our total time delta from parents
 	mParentTimerData.mChildTime += total_time;
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 1d3c376a58..0f927bad53 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -449,9 +449,8 @@ namespace LLTrace
 		U64							mChildTimeCounter,
 									mTotalTimeCounter;
 		U32							mCalls;
-		class TimeBlock*			mBlock;			// block associated with this accumulator
 		class TimeBlock*			mParent;		// last acknowledged parent of this time block
-		TimeBlockAccumulator*		mLastAccumulator;	// used to bootstrap tree construction
+		class TimeBlock*			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
 
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 7c5995a104..7b493a651e 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -43,16 +43,14 @@ ThreadRecorder::ThreadRecorder()
 	TimeBlock& root_time_block = TimeBlock::getRootTimeBlock();
 
 	ThreadTimerStack* timer_stack = ThreadTimerStack::getInstance();
+	timer_stack->mTimeBlock = &root_time_block;
+	timer_stack->mActiveTimer = NULL;
 
 	mNumTimeBlockTreeNodes = AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer()->size();
 	mTimeBlockTreeNodes = new TimeBlockTreeNode[mNumTimeBlockTreeNodes];
 
 	mThreadRecording.start();
 
-	timer_stack->mAccumulator = root_time_block.getPrimaryAccumulator();
-	timer_stack->mActiveTimer = NULL;
-
-
 	// initialize time block parent pointers
 	for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(); 
 		it != end_it; 
@@ -63,9 +61,7 @@ ThreadRecorder::ThreadRecorder()
 		tree_node.mBlock = &time_block;
 		tree_node.mParent = &root_time_block;
 
-		TimeBlockAccumulator* accumulator = it->getPrimaryAccumulator();
-		accumulator->mParent = &root_time_block;
-		accumulator->mBlock = &time_block;
+		it->getPrimaryAccumulator()->mParent = &root_time_block;
 	}
 
 	mRootTimer = new BlockTimer(root_time_block);
-- 
cgit v1.2.3


From 6fc355814f3dec7351fd629f4d263c46cfb0e160 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 22 Jan 2013 20:30:05 -0800
Subject: SH-3275 WIP Update viewer metrics system to be more flexible fix for
 mac unit tests failing

---
 indra/llcommon/llthreadlocalstorage.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
index fd44589299..4873b2740d 100644
--- a/indra/llcommon/llthreadlocalstorage.h
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -177,12 +177,14 @@ public:
 			llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
 		}
 
+#if LL_DARWIN
+        createTLSInstance();
+#endif
 		if (!getIfExists())
 		{
 			setInitState(CONSTRUCTING);
             DERIVED_TYPE* instancep = new DERIVED_TYPE();
 #if LL_DARWIN
-            createTLSInstance();
             S32 result = pthread_setspecific(sInstanceKey, (void*)instancep);
             if (result != 0)
             {
-- 
cgit v1.2.3


From 3a555a2ff84d9b340e33673d7a03f37c966f06e6 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 24 Jan 2013 19:53:17 -0800
Subject: SH-3275 WIP interesting Update viewer metrics system to be more
 flexible removed LLFastTimerView::getFrameTimer() dead code elimination fixed
 off by one array access crash

---
 indra/llcommon/llfasttimer.cpp | 15 ---------------
 1 file changed, 15 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index ea4e1a89a2..a144a8c94e 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -270,7 +270,6 @@ void TimeBlock::processTimes()
 		stack_record->mChildTime += cumulative_time_delta;
 	}
 
-
 	// reset for next frame
 	for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(),
 			end_it = LLInstanceTracker<TimeBlock>::endInstances();
@@ -283,20 +282,6 @@ void TimeBlock::processTimes()
 		accumulator->mLastCaller = NULL;
 		accumulator->mMoveUpTree = false;
 	}
-
-	// traverse tree in DFS post order, or bottom up
-	//for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(TimeBlock::getRootTimer());
-	//	it != end_timer_tree_bottom_up();
-	//	++it)
-	//{
-	//	TimeBlock* timerp = (*it);
-	//	TimeBlockAccumulator& accumulator = timerp->getPrimaryAccumulator();
-	//	timerp->mTreeTimeCounter = accumulator.mSelfTimeCounter;
-	//	for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it)
-	//	{
-	//		timerp->mTreeTimeCounter += (*child_it)->mTreeTimeCounter;
-	//	}
-	//}
 }
 
 
-- 
cgit v1.2.3


From 09ee16c61d372c1eb620bc3ef3dbfeb798c0a82e Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 25 Jan 2013 16:15:19 -0800
Subject: SH-3275 WIP interesting Update viewer metrics system to be more
 flexible fix for extendablerecording not having right state

---
 indra/llcommon/lltracerecording.cpp | 8 ++++++++
 indra/llcommon/lltracerecording.h   | 2 ++
 2 files changed, 10 insertions(+)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index f45226eb9a..913c4cbdad 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -470,43 +470,51 @@ void ExtendableRecording::extend()
 
 void ExtendableRecording::start()
 {
+	LLStopWatchControlsMixin<ExtendableRecording>::start();
 	mPotentialRecording.start();
 }
 
 void ExtendableRecording::stop()
 {
+	LLStopWatchControlsMixin<ExtendableRecording>::stop();
 	mPotentialRecording.stop();
 }
 
 void ExtendableRecording::pause()
 {
+	LLStopWatchControlsMixin<ExtendableRecording>::pause();
 	mPotentialRecording.pause();
 }
 
 void ExtendableRecording::resume()
 {
+	LLStopWatchControlsMixin<ExtendableRecording>::resume();
 	mPotentialRecording.resume();
 }
 
 void ExtendableRecording::restart()
 {
+	LLStopWatchControlsMixin<ExtendableRecording>::restart();
 	mAcceptedRecording.reset();
 	mPotentialRecording.restart();
 }
 
 void ExtendableRecording::reset()
 {
+	LLStopWatchControlsMixin<ExtendableRecording>::reset();
 	mAcceptedRecording.reset();
 	mPotentialRecording.reset();
 }
 
 void ExtendableRecording::splitTo(ExtendableRecording& other)
 {
+	LLStopWatchControlsMixin<ExtendableRecording>::splitTo(other);
 	mPotentialRecording.splitTo(other.mPotentialRecording);
 }
 
 void ExtendableRecording::splitFrom(ExtendableRecording& other)
 {
+	LLStopWatchControlsMixin<ExtendableRecording>::splitFrom(other);
 	mPotentialRecording.splitFrom(other.mPotentialRecording);
 }
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index e6b5e85f90..f575fbd8b2 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -389,7 +389,9 @@ namespace LLTrace
 	class ExtendableRecording
 	:	public LLStopWatchControlsMixin<ExtendableRecording>
 	{
+	public:
 		void extend();
+		Recording& getAcceptedRecording() { return mAcceptedRecording; }
 
 		// implementation for LLStopWatchControlsMixin
 		/*virtual*/ void start();
-- 
cgit v1.2.3


From 2c68d5367c5c44aceb4ff23d9672c35642e030f7 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sun, 27 Jan 2013 21:35:20 -0800
Subject: SH-3275 WIP interesting Update viewer metrics system to be more
 flexible fixed memory leak fixed glitching of fast timer display

---
 indra/llcommon/llfasttimer.cpp           |  7 +++++++
 indra/llcommon/lltrace.h                 | 18 +++++++++++++----
 indra/llcommon/lltracerecording.cpp      | 10 ++++++++++
 indra/llcommon/lltracerecording.h        | 11 +++++++----
 indra/llcommon/lltracethreadrecorder.cpp | 33 +++++++++++++++++++-------------
 indra/llcommon/lltracethreadrecorder.h   | 12 +++++++-----
 6 files changed, 65 insertions(+), 26 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index a144a8c94e..e58c5c0f98 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -425,6 +425,13 @@ void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
 	mTotalTimeCounter = 0;
 	mChildTimeCounter = 0;
 	mCalls = 0;
+	if (other)
+	{
+		mLastCaller = other->mLastCaller;
+		mActiveCount = other->mActiveCount;
+		mMoveUpTree = other->mMoveUpTree;
+		mParent = other->mParent;
+	}
 }
 
 } // namespace LLTrace
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 0f927bad53..c38e92962b 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -243,8 +243,6 @@ namespace LLTrace
 	:	 public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
 	{
 	public:
-		typedef typename MeanValueType<TraceType<ACCUMULATOR> >::type  mean_t;
-
 		TraceType(const char* name, const char* description = NULL)
 		:	LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>(name),
 			mName(name),
@@ -468,25 +466,37 @@ namespace LLTrace
 	:	public TraceType<TimeBlockAccumulator>
 	{
 	public:
-		typedef F32 mean_t;
 
 		TraceType(const char* name, const char* description = "")
 		:	TraceType<TimeBlockAccumulator>(name, description)
 		{}
 	};
 
+	template<>
+	struct MeanValueType<TraceType<TimeBlockAccumulator::CallCountAspect> >
+	{
+		typedef F64 type;
+	};
+
+
 	template<>
 	class TraceType<TimeBlockAccumulator::SelfTimeAspect>
 		:	public TraceType<TimeBlockAccumulator>
 	{
 	public:
-		typedef F32 mean_t;
 
 		TraceType(const char* name, const char* description = "")
 			:	TraceType<TimeBlockAccumulator>(name, description)
 		{}
 	};
 
+	template<>
+	struct MeanValueType<TraceType<TimeBlockAccumulator::SelfTimeAspect> >
+	{
+		typedef LLUnit<LLUnits::Seconds, F64> type;
+	};
+
+
 	class TimeBlock;
 	class TimeBlockTreeNode
 	{
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 913c4cbdad..737b95cdd5 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -109,8 +109,18 @@ void Recording::handleSplitTo(Recording& other)
 {
 	stop();
 	other.restart();
+	syncTo(other);
+}
+
+void Recording::syncTo(Recording& other)
+{
+	other.mCountsFloat.write()->reset(mCountsFloat);
 	other.mMeasurementsFloat.write()->reset(mMeasurementsFloat);
+	other.mCounts.write()->reset(mCounts);
 	other.mMeasurements.write()->reset(mMeasurements);
+	other.mStackTimers.write()->reset(mStackTimers);
+	other.mMemStats.write()->reset(mMemStats);
+
 	//TODO: figure out how to get seamless handoff of timing stats
 }
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index f575fbd8b2..af9ba02b29 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -119,6 +119,7 @@ namespace LLTrace
 		// gather data from recording, ignoring time relationship (for example, pulling data from slave threads)
 		void mergeRecording(const Recording& other);
 
+		// grab latest recorded data
 		void update();
 
 		// Timer accessors
@@ -217,6 +218,8 @@ namespace LLTrace
 
 		LLUnit<LLUnits::Seconds, F64> getDuration() const { return LLUnit<LLUnits::Seconds, F64>(mElapsedSeconds); }
 
+		void syncTo(Recording& other);
+
 	private:
 		friend class ThreadRecorder;
 
@@ -337,9 +340,9 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename TraceType<T>::mean_t getPeriodMean(const TraceType<T>& stat) const
+		typename MeanValueType<TraceType<T> >::type getPeriodMean(const TraceType<T>& stat) const
 		{
-			typename TraceType<T>::mean_t mean = 0.0;
+			typename MeanValueType<TraceType<T> >::type mean = 0.0;
 			for (S32 i = 0; i < mNumPeriods; i++)
 			{
 				if (mRecordingPeriods[i].getDuration() > 0.f)
@@ -352,9 +355,9 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename TraceType<T>::mean_t getPeriodMeanPerSec(const TraceType<T>& stat) const
+		typename MeanValueType<TraceType<T> >::type getPeriodMeanPerSec(const TraceType<T>& stat) const
 		{
-			typename TraceType<T>::mean_t mean = 0.0;
+			typename MeanValueType<TraceType<T> >::type mean = 0.0;
 			for (S32 i = 0; i < mNumPeriods; i++)
 			{
 				if (mRecordingPeriods[i].getDuration() > 0.f)
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 7b493a651e..113febcca8 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -76,7 +76,7 @@ ThreadRecorder::~ThreadRecorder()
 
 	while(mActiveRecordings.size())
 	{
-		mActiveRecordings.front().mTargetRecording->stop();
+		mActiveRecordings.front()->mTargetRecording->stop();
 	}
 	set_thread_recorder(NULL);
 	delete[] mTimeBlockTreeNodes;
@@ -94,31 +94,37 @@ TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode(S32 index)
 
 void ThreadRecorder::activate( Recording* recording )
 {
-	mActiveRecordings.push_front(ActiveRecording(recording));
-	mActiveRecordings.front().mBaseline.makePrimary();
+	ActiveRecording* active_recording = new ActiveRecording(recording);
+	if (!mActiveRecordings.empty())
+	{
+		mActiveRecordings.front()->mBaseline.syncTo(active_recording->mBaseline);
+	}
+	mActiveRecordings.push_front(active_recording);
+
+	mActiveRecordings.front()->mBaseline.makePrimary();
 }
 
-std::list<ThreadRecorder::ActiveRecording>::iterator ThreadRecorder::update( Recording* recording )
+ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::update( Recording* recording )
 {
-	std::list<ActiveRecording>::iterator it, end_it;
+	active_recording_list_t::iterator it, end_it;
 	for (it = mActiveRecordings.begin(), end_it = mActiveRecordings.end();
 		it != end_it;
 		++it)
 	{
-		std::list<ActiveRecording>::iterator next_it = it;
+		active_recording_list_t::iterator next_it = it;
 		++next_it;
 
 		// if we have another recording further down in the stack...
 		if (next_it != mActiveRecordings.end())
 		{
 			// ...push our gathered data down to it
-			next_it->mBaseline.appendRecording(it->mBaseline);
+			(*next_it)->mBaseline.appendRecording((*it)->mBaseline);
 		}
 
 		// copy accumulated measurements into result buffer and clear accumulator (mBaseline)
-		it->moveBaselineToTarget();
+		(*it)->moveBaselineToTarget();
 
-		if (it->mTargetRecording == recording)
+		if ((*it)->mTargetRecording == recording)
 		{
 			// found the recording, so return it
 			break;
@@ -142,17 +148,18 @@ AccumulatorBuffer<MemStatAccumulator>			gMemStats;
 
 void ThreadRecorder::deactivate( Recording* recording )
 {
-	std::list<ActiveRecording>::iterator it = update(recording);
+	active_recording_list_t::iterator it = update(recording);
 	if (it != mActiveRecordings.end())
 	{
 		// and if we've found the recording we wanted to update
-		std::list<ActiveRecording>::iterator next_it = it;
+		active_recording_list_t::iterator next_it = it;
 		++next_it;
 		if (next_it != mActiveRecordings.end())
 		{
-			next_it->mTargetRecording->makePrimary();
+			(*next_it)->mTargetRecording->makePrimary();
 		}
 
+		delete *it;
 		mActiveRecordings.erase(it);
 	}
 }
@@ -244,7 +251,7 @@ void MasterThreadRecorder::pullFromSlaveThreads()
 
 	LLMutexLock lock(&mSlaveListMutex);
 
-	Recording& target_recording = mActiveRecordings.front().mBaseline;
+	Recording& target_recording = mActiveRecordings.front()->mBaseline;
 	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
 		it != end_it;
 		++it)
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 337035974c..0e6c091900 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -39,13 +39,14 @@ namespace LLTrace
 	{
 	protected:
 		struct ActiveRecording;
+		typedef std::list<ActiveRecording*> active_recording_list_t;
 	public:
 		ThreadRecorder();
 
 		virtual ~ThreadRecorder();
 
 		void activate(Recording* recording);
-		std::list<struct ActiveRecording>::iterator update(Recording* recording);
+		active_recording_list_t::iterator update(Recording* recording);
 		void deactivate(Recording* recording);
 
 		virtual void pushToMaster() = 0;
@@ -63,11 +64,12 @@ namespace LLTrace
 			void moveBaselineToTarget();
 		};
 		Recording					mThreadRecording;
-		std::list<ActiveRecording>	mActiveRecordings;
 
-		class BlockTimer*				mRootTimer;
-		TimeBlockTreeNode*				mTimeBlockTreeNodes;
-		size_t							mNumTimeBlockTreeNodes;
+		active_recording_list_t		mActiveRecordings;
+
+		class BlockTimer*			mRootTimer;
+		TimeBlockTreeNode*			mTimeBlockTreeNodes;
+		size_t						mNumTimeBlockTreeNodes;
 	};
 
 	class LL_COMMON_API MasterThreadRecorder : public ThreadRecorder
-- 
cgit v1.2.3


From eb6c8959ca5b8b3c100114d4d659a48bb4d56b2c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sat, 2 Feb 2013 01:09:52 -0800
Subject: SH-3275 WIP interesting Update viewer metrics system to be more
 flexible fixed most fast timer display and interaction issues

---
 indra/llcommon/lltracerecording.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 737b95cdd5..29604f7155 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -530,7 +530,7 @@ void ExtendableRecording::splitFrom(ExtendableRecording& other)
 
 PeriodicRecording& get_frame_recording()
 {
-	static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(64, PeriodicRecording::STARTED));
+	static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(200, PeriodicRecording::STARTED));
 	return *sRecording;
 }
 
-- 
cgit v1.2.3


From 438cbfe489cc34261ac600bbb22983164e59b1d9 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 7 Feb 2013 20:07:31 -0800
Subject: SH-3275 WIP interesting Update viewer metrics system to be more
 flexible fix for timings for recursive fast timers not being correct

---
 indra/llcommon/llfasttimer.cpp      | 10 +++++-----
 indra/llcommon/llfasttimer.h        | 14 ++++++++++++--
 indra/llcommon/lltrace.h            |  2 +-
 indra/llcommon/lltracerecording.cpp |  8 ++++----
 4 files changed, 22 insertions(+), 12 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index e58c5c0f98..809a0ef4bf 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -257,8 +257,8 @@ void TimeBlock::processTimes()
 	{
 		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
 	
-		accumulator->mTotalTimeCounter += cumulative_time_delta;
-		accumulator->mChildTimeCounter += stack_record->mChildTime;
+		accumulator->mChildTimeCounter += stack_record->mChildTime - (accumulator->mSelfTimeCounter - cur_timer->mStartSelfTimeCount);
+		accumulator->mSelfTimeCounter += cumulative_time_delta - stack_record->mChildTime;
 		stack_record->mChildTime = 0;
 
 		cur_timer->mStartTime = cur_time;
@@ -401,7 +401,7 @@ void TimeBlock::writeLog(std::ostream& os)
 
 TimeBlockAccumulator::TimeBlockAccumulator() 
 :	mChildTimeCounter(0),
-	mTotalTimeCounter(0),
+	mSelfTimeCounter(0),
 	mCalls(0),
 	mLastCaller(NULL),
 	mActiveCount(0),
@@ -412,7 +412,7 @@ TimeBlockAccumulator::TimeBlockAccumulator()
 void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
 {
 	mChildTimeCounter += other.mChildTimeCounter;
-	mTotalTimeCounter += other.mTotalTimeCounter;
+	mSelfTimeCounter += other.mSelfTimeCounter;
 	mCalls += other.mCalls;
 	mLastCaller = other.mLastCaller;
 	mActiveCount = other.mActiveCount;
@@ -422,7 +422,7 @@ void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
 
 void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
 {
-	mTotalTimeCounter = 0;
+	mSelfTimeCounter = 0;
 	mChildTimeCounter = 0;
 	mCalls = 0;
 	if (other)
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 726db70fbe..9402bb7267 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -71,9 +71,12 @@ public:
 	BlockTimer(TimeBlock& timer);
 	~BlockTimer();
 
+	void logCurrentTime();
+
 private:
 
 	U64						mStartTime;
+	U64						mStartSelfTimeCount;
 	BlockTimerStackRecord	mParentTimerData;
 };
 
@@ -279,6 +282,7 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 	BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
 	TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 	accumulator->mActiveCount++;
+	mStartSelfTimeCount = accumulator->mSelfTimeCounter;
 	// keep current parent as long as it is active when we are
 	accumulator->mMoveUpTree |= (accumulator->mParent->getPrimaryAccumulator()->mActiveCount == 0);
 
@@ -298,9 +302,10 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 	BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
 	TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
 
+	U64 child_time = cur_timer_data->mChildTime - (accumulator->mSelfTimeCounter - mStartSelfTimeCount);
 	accumulator->mCalls++;
-	accumulator->mChildTimeCounter += cur_timer_data->mChildTime;
-	accumulator->mTotalTimeCounter += total_time;
+	accumulator->mChildTimeCounter += child_time;
+	accumulator->mSelfTimeCounter += total_time - child_time;
 	accumulator->mActiveCount--;
 
 	// store last caller to bootstrap tree creation
@@ -315,6 +320,11 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 #endif
 }
 
+inline void BlockTimer::logCurrentTime()
+{
+	U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
+	llinfos << "Time elapsed: " << (1000.0 * (F64)total_time / (F64)TimeBlock::countsPerSecond()) << llendl;
+}
 }
 
 typedef LLTrace::BlockTimer LLFastTimer; 
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index c38e92962b..9eadd8a2be 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -445,7 +445,7 @@ namespace LLTrace
 		// members
 		//
 		U64							mChildTimeCounter,
-									mTotalTimeCounter;
+									mSelfTimeCounter;
 		U32							mCalls;
 		class TimeBlock*			mParent;		// last acknowledged parent of this time block
 		class TimeBlock*			mLastCaller;	// used to bootstrap tree construction
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 29604f7155..69085ddcc2 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -184,12 +184,12 @@ void Recording::mergeRecording( const Recording& other)
 
 LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) const
 {
-	return (F64)(*mStackTimers)[stat.getIndex()].mTotalTimeCounter / (F64)LLTrace::TimeBlock::countsPerSecond();
+	return ((F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter + (F64)(*mStackTimers)[stat.getIndex()].mChildTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
 LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const
 {
-	return ((F64)(*mStackTimers)[stat.getIndex()].mTotalTimeCounter - (F64)(*mStackTimers)[stat.getIndex()].mChildTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond();
+	return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
 
@@ -200,12 +200,12 @@ U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountAspect>& st
 
 LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat) const
 {
-	return (F64)(*mStackTimers)[stat.getIndex()].mTotalTimeCounter / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
+	return ((F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter + (F64)(*mStackTimers)[stat.getIndex()].mChildTimeCounter) / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
 }
 
 LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const
 {
-	return ((F64)(*mStackTimers)[stat.getIndex()].mTotalTimeCounter - (F64)(*mStackTimers)[stat.getIndex()].mChildTimeCounter) / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
+	return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
 }
 
 F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const
-- 
cgit v1.2.3


From e3700112f313f3570887047d5b56a661af0afac5 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 8 Feb 2013 00:03:31 -0800
Subject: SH-3275 WIP interesting Update viewer metrics system to be more
 flexible added debug output to BlockTimer

---
 indra/llcommon/llfasttimer.cpp | 8 ++++++++
 indra/llcommon/llfasttimer.h   | 2 ++
 2 files changed, 10 insertions(+)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index e58c5c0f98..ba626bcc32 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -434,4 +434,12 @@ void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
 	}
 }
 
+LLUnit<LLUnits::Seconds, F64> BlockTimer::getElapsedTime()
+{
+	U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
+
+	return (F64)total_time / (F64)TimeBlock::countsPerSecond();
+}
+
+
 } // namespace LLTrace
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 726db70fbe..edbcb896b3 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -71,6 +71,8 @@ public:
 	BlockTimer(TimeBlock& timer);
 	~BlockTimer();
 
+	LLUnit<LLUnits::Seconds, F64> getElapsedTime();
+
 private:
 
 	U64						mStartTime;
-- 
cgit v1.2.3


From 2e15e8fd4ba62204c76f6e2a91d3e50f62e6c1fc Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sat, 9 Feb 2013 00:34:59 -0800
Subject: SH-3275 FIX interesting Update viewer metrics system to be more
 flexible fixed anamolous LLFastTimer timings

---
 indra/llcommon/llfasttimer.cpp      | 28 +++++++++++++++++++++-------
 indra/llcommon/llfasttimer.h        | 17 ++++++++---------
 indra/llcommon/lltrace.h            |  4 +++-
 indra/llcommon/lltracerecording.cpp | 19 +++++++++++++------
 4 files changed, 45 insertions(+), 23 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 4387218f5a..0ea91d7e51 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -256,12 +256,16 @@ void TimeBlock::processTimes()
 	while(cur_timer && cur_timer->mParentTimerData.mActiveTimer != cur_timer)
 	{
 		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
-	
-		accumulator->mChildTimeCounter += stack_record->mChildTime - (accumulator->mSelfTimeCounter - cur_timer->mStartSelfTimeCount);
-		accumulator->mSelfTimeCounter += cumulative_time_delta - stack_record->mChildTime;
+		U64 child_time = stack_record->mChildTime 
+			- (accumulator->mSelfTimeCounter - cur_timer->mStartSelfTimeCounter)
+			- (accumulator->mChildTimeCounter - cur_timer->mStartChildTimeCounter);
+		accumulator->mChildTimeCounter += child_time;
+		accumulator->mSelfTimeCounter += cumulative_time_delta - child_time;
 		stack_record->mChildTime = 0;
 
 		cur_timer->mStartTime = cur_time;
+		cur_timer->mStartSelfTimeCounter = accumulator->mSelfTimeCounter;
+		cur_timer->mStartChildTimeCounter = accumulator->mChildTimeCounter;
 
 		stack_record = &cur_timer->mParentTimerData;
 		accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
@@ -402,6 +406,8 @@ void TimeBlock::writeLog(std::ostream& os)
 TimeBlockAccumulator::TimeBlockAccumulator() 
 :	mChildTimeCounter(0),
 	mSelfTimeCounter(0),
+	mStartChildTimeCounter(0),
+	mStartSelfTimeCounter(0),
 	mCalls(0),
 	mLastCaller(NULL),
 	mActiveCount(0),
@@ -411,8 +417,8 @@ TimeBlockAccumulator::TimeBlockAccumulator()
 
 void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
 {
-	mChildTimeCounter += other.mChildTimeCounter;
-	mSelfTimeCounter += other.mSelfTimeCounter;
+	mChildTimeCounter += other.mChildTimeCounter - other.mStartChildTimeCounter;
+	mSelfTimeCounter += other.mSelfTimeCounter - other.mStartSelfTimeCounter;
 	mCalls += other.mCalls;
 	mLastCaller = other.mLastCaller;
 	mActiveCount = other.mActiveCount;
@@ -422,16 +428,24 @@ void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
 
 void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
 {
-	mSelfTimeCounter = 0;
-	mChildTimeCounter = 0;
 	mCalls = 0;
 	if (other)
 	{
+		mStartSelfTimeCounter = other->mSelfTimeCounter;
+		mSelfTimeCounter = mStartSelfTimeCounter;
+		mStartChildTimeCounter = other->mChildTimeCounter;
+		mChildTimeCounter = mStartChildTimeCounter;
+
 		mLastCaller = other->mLastCaller;
 		mActiveCount = other->mActiveCount;
 		mMoveUpTree = other->mMoveUpTree;
 		mParent = other->mParent;
 	}
+	else
+	{
+		mStartSelfTimeCounter = mSelfTimeCounter;
+		mStartChildTimeCounter = mChildTimeCounter;
+	}
 }
 
 LLUnit<LLUnits::Seconds, F64> BlockTimer::getElapsedTime()
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 2994b35e58..28e54a37de 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -76,7 +76,8 @@ public:
 private:
 
 	U64						mStartTime;
-	U64						mStartSelfTimeCount;
+	U64						mStartSelfTimeCounter;
+	U64						mStartChildTimeCounter;
 	BlockTimerStackRecord	mParentTimerData;
 };
 
@@ -282,7 +283,8 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 	BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
 	TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 	accumulator->mActiveCount++;
-	mStartSelfTimeCount = accumulator->mSelfTimeCounter;
+	mStartSelfTimeCounter = accumulator->mSelfTimeCounter;
+	mStartChildTimeCounter = accumulator->mChildTimeCounter;
 	// keep current parent as long as it is active when we are
 	accumulator->mMoveUpTree |= (accumulator->mParent->getPrimaryAccumulator()->mActiveCount == 0);
 
@@ -302,10 +304,12 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 	BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
 	TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
 
-	U64 child_time = cur_timer_data->mChildTime - (accumulator->mSelfTimeCounter - mStartSelfTimeCount);
+	U64 child_time = cur_timer_data->mChildTime 
+					- (accumulator->mSelfTimeCounter - mStartSelfTimeCounter)
+					- (accumulator->mChildTimeCounter - mStartChildTimeCounter);
 	accumulator->mCalls++;
 	accumulator->mChildTimeCounter += child_time;
-	accumulator->mSelfTimeCounter += total_time - child_time;
+	accumulator->mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
 	accumulator->mActiveCount--;
 
 	// store last caller to bootstrap tree creation
@@ -320,11 +324,6 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 #endif
 }
 
-inline void BlockTimer::logCurrentTime()
-{
-	U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
-	llinfos << "Time elapsed: " << (1000.0 * (F64)total_time / (F64)TimeBlock::countsPerSecond()) << llendl;
-}
 }
 
 typedef LLTrace::BlockTimer LLFastTimer; 
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 9eadd8a2be..8c3259eea9 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -444,7 +444,9 @@ namespace LLTrace
 		//
 		// members
 		//
-		U64							mChildTimeCounter,
+		U64							mStartChildTimeCounter,
+									mStartSelfTimeCounter,
+									mChildTimeCounter,
 									mSelfTimeCounter;
 		U32							mCalls;
 		class TimeBlock*			mParent;		// last acknowledged parent of this time block
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 69085ddcc2..2af9041863 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -120,8 +120,6 @@ void Recording::syncTo(Recording& other)
 	other.mMeasurements.write()->reset(mMeasurements);
 	other.mStackTimers.write()->reset(mStackTimers);
 	other.mMemStats.write()->reset(mMemStats);
-
-	//TODO: figure out how to get seamless handoff of timing stats
 }
 
 void Recording::makePrimary()
@@ -184,12 +182,15 @@ void Recording::mergeRecording( const Recording& other)
 
 LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) const
 {
-	return ((F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter + (F64)(*mStackTimers)[stat.getIndex()].mChildTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond();
+	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
+	return (F64)(accumulator.mSelfTimeCounter - accumulator.mStartSelfTimeCounter + accumulator.mChildTimeCounter - accumulator.mStartChildTimeCounter) 
+				/ (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
 LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const
 {
-	return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / (F64)LLTrace::TimeBlock::countsPerSecond();
+	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
+	return (F64)(accumulator.mSelfTimeCounter - accumulator.mStartSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
 
@@ -200,12 +201,18 @@ U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountAspect>& st
 
 LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat) const
 {
-	return ((F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter + (F64)(*mStackTimers)[stat.getIndex()].mChildTimeCounter) / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
+	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
+
+	return (F64)(accumulator.mSelfTimeCounter - accumulator.mStartSelfTimeCounter + accumulator.mChildTimeCounter - accumulator.mStartChildTimeCounter) 
+				/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
 }
 
 LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const
 {
-	return (F64)(*mStackTimers)[stat.getIndex()].mSelfTimeCounter / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
+	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
+
+	return (F64)(accumulator.mSelfTimeCounter - accumulator.mStartSelfTimeCounter) 
+			/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
 }
 
 F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const
-- 
cgit v1.2.3


From 67ac6e7a294bd7401c55ed1d7423166dda1c0ee6 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sun, 10 Feb 2013 23:53:45 -0800
Subject: SH-3275 FIX interesting Update viewer metrics system to be more
 flexible streamlined fast timer delta tracking

---
 indra/llcommon/llfasttimer.cpp      | 30 ++++++++++++------------------
 indra/llcommon/llfasttimer.h        | 11 +++--------
 indra/llcommon/lltrace.h            |  5 ++---
 indra/llcommon/lltracerecording.cpp |  8 ++++----
 4 files changed, 21 insertions(+), 33 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 0ea91d7e51..f8837a7085 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -256,16 +256,12 @@ void TimeBlock::processTimes()
 	while(cur_timer && cur_timer->mParentTimerData.mActiveTimer != cur_timer)
 	{
 		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
-		U64 child_time = stack_record->mChildTime 
-			- (accumulator->mSelfTimeCounter - cur_timer->mStartSelfTimeCounter)
-			- (accumulator->mChildTimeCounter - cur_timer->mStartChildTimeCounter);
-		accumulator->mChildTimeCounter += child_time;
-		accumulator->mSelfTimeCounter += cumulative_time_delta - child_time;
+		accumulator->mTotalTimeCounter += cumulative_time_delta - (accumulator->mTotalTimeCounter - accumulator->mStartTotalTimeCounter);
+		accumulator->mSelfTimeCounter += cumulative_time_delta - stack_record->mChildTime;
 		stack_record->mChildTime = 0;
 
 		cur_timer->mStartTime = cur_time;
-		cur_timer->mStartSelfTimeCounter = accumulator->mSelfTimeCounter;
-		cur_timer->mStartChildTimeCounter = accumulator->mChildTimeCounter;
+		cur_timer->mStartTotalTimeCounter = accumulator->mTotalTimeCounter;
 
 		stack_record = &cur_timer->mParentTimerData;
 		accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
@@ -404,10 +400,9 @@ void TimeBlock::writeLog(std::ostream& os)
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 TimeBlockAccumulator::TimeBlockAccumulator() 
-:	mChildTimeCounter(0),
+:	mTotalTimeCounter(0),
 	mSelfTimeCounter(0),
-	mStartChildTimeCounter(0),
-	mStartSelfTimeCounter(0),
+	mStartTotalTimeCounter(0),
 	mCalls(0),
 	mLastCaller(NULL),
 	mActiveCount(0),
@@ -417,8 +412,8 @@ TimeBlockAccumulator::TimeBlockAccumulator()
 
 void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
 {
-	mChildTimeCounter += other.mChildTimeCounter - other.mStartChildTimeCounter;
-	mSelfTimeCounter += other.mSelfTimeCounter - other.mStartSelfTimeCounter;
+	mTotalTimeCounter += other.mTotalTimeCounter - other.mStartTotalTimeCounter;
+	mSelfTimeCounter += other.mSelfTimeCounter;
 	mCalls += other.mCalls;
 	mLastCaller = other.mLastCaller;
 	mActiveCount = other.mActiveCount;
@@ -429,12 +424,12 @@ void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
 void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
 {
 	mCalls = 0;
+	mSelfTimeCounter = 0;
+
 	if (other)
 	{
-		mStartSelfTimeCounter = other->mSelfTimeCounter;
-		mSelfTimeCounter = mStartSelfTimeCounter;
-		mStartChildTimeCounter = other->mChildTimeCounter;
-		mChildTimeCounter = mStartChildTimeCounter;
+		mStartTotalTimeCounter = other->mTotalTimeCounter;
+		mTotalTimeCounter = mStartTotalTimeCounter;
 
 		mLastCaller = other->mLastCaller;
 		mActiveCount = other->mActiveCount;
@@ -443,8 +438,7 @@ void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
 	}
 	else
 	{
-		mStartSelfTimeCounter = mSelfTimeCounter;
-		mStartChildTimeCounter = mChildTimeCounter;
+		mStartTotalTimeCounter = mTotalTimeCounter;
 	}
 }
 
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 28e54a37de..ec1720d2df 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -76,8 +76,7 @@ public:
 private:
 
 	U64						mStartTime;
-	U64						mStartSelfTimeCounter;
-	U64						mStartChildTimeCounter;
+	U64						mStartTotalTimeCounter;
 	BlockTimerStackRecord	mParentTimerData;
 };
 
@@ -283,8 +282,7 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 	BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
 	TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 	accumulator->mActiveCount++;
-	mStartSelfTimeCounter = accumulator->mSelfTimeCounter;
-	mStartChildTimeCounter = accumulator->mChildTimeCounter;
+	mStartTotalTimeCounter = accumulator->mTotalTimeCounter;
 	// keep current parent as long as it is active when we are
 	accumulator->mMoveUpTree |= (accumulator->mParent->getPrimaryAccumulator()->mActiveCount == 0);
 
@@ -304,11 +302,8 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 	BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
 	TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
 
-	U64 child_time = cur_timer_data->mChildTime 
-					- (accumulator->mSelfTimeCounter - mStartSelfTimeCounter)
-					- (accumulator->mChildTimeCounter - mStartChildTimeCounter);
 	accumulator->mCalls++;
-	accumulator->mChildTimeCounter += child_time;
+	accumulator->mTotalTimeCounter += total_time - (accumulator->mTotalTimeCounter - mStartTotalTimeCounter);
 	accumulator->mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
 	accumulator->mActiveCount--;
 
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 8c3259eea9..5d57327a14 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -444,9 +444,8 @@ namespace LLTrace
 		//
 		// members
 		//
-		U64							mStartChildTimeCounter,
-									mStartSelfTimeCounter,
-									mChildTimeCounter,
+		U64							mStartTotalTimeCounter,
+									mTotalTimeCounter,
 									mSelfTimeCounter;
 		U32							mCalls;
 		class TimeBlock*			mParent;		// last acknowledged parent of this time block
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 2af9041863..ab8dbce2ce 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -183,14 +183,14 @@ void Recording::mergeRecording( const Recording& other)
 LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) const
 {
 	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
-	return (F64)(accumulator.mSelfTimeCounter - accumulator.mStartSelfTimeCounter + accumulator.mChildTimeCounter - accumulator.mStartChildTimeCounter) 
+	return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
 				/ (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
 LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const
 {
 	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
-	return (F64)(accumulator.mSelfTimeCounter - accumulator.mStartSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond();
+	return (F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
 
@@ -203,7 +203,7 @@ LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccu
 {
 	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
 
-	return (F64)(accumulator.mSelfTimeCounter - accumulator.mStartSelfTimeCounter + accumulator.mChildTimeCounter - accumulator.mStartChildTimeCounter) 
+	return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
 				/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
 }
 
@@ -211,7 +211,7 @@ LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccu
 {
 	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
 
-	return (F64)(accumulator.mSelfTimeCounter - accumulator.mStartSelfTimeCounter) 
+	return (F64)(accumulator.mSelfTimeCounter) 
 			/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
 }
 
-- 
cgit v1.2.3


From a6bb68b6e530df91d03abfc062c700ebc4e856aa Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 13 Feb 2013 15:21:20 -0800
Subject: SH-3275 FIX interesting Update viewer metrics system to be more
 flexible fix for inaccurate optimization of full block time calculations

---
 indra/llcommon/llfasttimer.cpp | 6 +++---
 indra/llcommon/llfasttimer.h   | 6 +++---
 indra/llcommon/llunit.h        | 5 +++--
 3 files changed, 9 insertions(+), 8 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index f8837a7085..5baf049c03 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -256,12 +256,12 @@ void TimeBlock::processTimes()
 	while(cur_timer && cur_timer->mParentTimerData.mActiveTimer != cur_timer)
 	{
 		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
-		accumulator->mTotalTimeCounter += cumulative_time_delta - (accumulator->mTotalTimeCounter - accumulator->mStartTotalTimeCounter);
+		accumulator->mTotalTimeCounter += cumulative_time_delta - (accumulator->mTotalTimeCounter - cur_timer->mBlockStartTotalTimeCounter);
 		accumulator->mSelfTimeCounter += cumulative_time_delta - stack_record->mChildTime;
 		stack_record->mChildTime = 0;
 
 		cur_timer->mStartTime = cur_time;
-		cur_timer->mStartTotalTimeCounter = accumulator->mTotalTimeCounter;
+		cur_timer->mBlockStartTotalTimeCounter = accumulator->mTotalTimeCounter;
 
 		stack_record = &cur_timer->mParentTimerData;
 		accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
@@ -376,7 +376,7 @@ void TimeBlock::dumpCurTimes()
 		}
 
 		out_str << timerp->getName() << " " 
-			<< std::setprecision(3) << total_time_ms.as<LLUnits::Milliseconds, F32>().value() << " ms, "
+			<< std::setprecision(3) << total_time_ms.as<LLUnits::Milliseconds>().value() << " ms, "
 			<< num_calls << " calls";
 
 		llinfos << out_str.str() << llendl;
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index ec1720d2df..32a0629a87 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -76,7 +76,7 @@ public:
 private:
 
 	U64						mStartTime;
-	U64						mStartTotalTimeCounter;
+	U64						mBlockStartTotalTimeCounter;
 	BlockTimerStackRecord	mParentTimerData;
 };
 
@@ -282,7 +282,7 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 	BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
 	TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 	accumulator->mActiveCount++;
-	mStartTotalTimeCounter = accumulator->mTotalTimeCounter;
+	mBlockStartTotalTimeCounter = accumulator->mTotalTimeCounter;
 	// keep current parent as long as it is active when we are
 	accumulator->mMoveUpTree |= (accumulator->mParent->getPrimaryAccumulator()->mActiveCount == 0);
 
@@ -303,7 +303,7 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 	TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
 
 	accumulator->mCalls++;
-	accumulator->mTotalTimeCounter += total_time - (accumulator->mTotalTimeCounter - mStartTotalTimeCounter);
+	accumulator->mTotalTimeCounter += total_time - (accumulator->mTotalTimeCounter - mBlockStartTotalTimeCounter);
 	accumulator->mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
 	accumulator->mActiveCount--;
 
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index c2a31b7604..823550db5d 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -106,11 +106,12 @@ struct LLUnit
 		return mValue;
 	}
 
-	template<typename NEW_UNIT_TYPE, typename NEW_STORAGE_TYPE> LLUnit<NEW_UNIT_TYPE, NEW_STORAGE_TYPE> as()
+	template<typename NEW_UNIT_TYPE> LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE> as()
 	{
-		return LLUnit<NEW_UNIT_TYPE, NEW_STORAGE_TYPE>(*this);
+		return LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE>(*this);
 	}
 
+
 	void operator += (storage_t value)
 	{
 		mValue += value;
-- 
cgit v1.2.3


From f07b9c2c69f1f6882dcf249aacf33cdfacf878ab Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 6 Mar 2013 11:08:25 -0800
Subject: renamed LLTrace stat gathering classes/methods to make the structure
 of LLTrace clearer Count becomes CountStatHandle Count.sum becomes sum(Count,
 value), etc.

---
 indra/llcommon/lltrace.h          | 832 +++++++++++++++++++-------------------
 indra/llcommon/lltracerecording.h |  23 +-
 2 files changed, 429 insertions(+), 426 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 5d57327a14..44da1939c6 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -42,517 +42,519 @@
 
 namespace LLTrace
 {
-	class Recording;
-
-	typedef LLUnit<LLUnits::Bytes, F64>			Bytes;
-	typedef LLUnit<LLUnits::Kilobytes, F64>		Kilobytes;
-	typedef LLUnit<LLUnits::Megabytes, F64>		Megabytes;
-	typedef LLUnit<LLUnits::Gigabytes, F64>		Gigabytes;
-	typedef LLUnit<LLUnits::Bits, F64>			Bits;
-	typedef LLUnit<LLUnits::Kilobits, F64>		Kilobits;
-	typedef LLUnit<LLUnits::Megabits, F64>		Megabits;
-	typedef LLUnit<LLUnits::Gigabits, F64>		Gigabits;
-
-	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;
-
-	void init();
-	void cleanup();
-	bool isInitialized();
-
-	const LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder();
-	void set_thread_recorder(class ThreadRecorder*);
-
-	class MasterThreadRecorder& getMasterThreadRecorder();
-
-	// one per thread per type
-	template<typename ACCUMULATOR>
-	class AccumulatorBuffer : public LLRefCount
-	{
-		typedef AccumulatorBuffer<ACCUMULATOR> self_t;
-		static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64;
-	private:
-		struct StaticAllocationMarker { };
-
-		AccumulatorBuffer(StaticAllocationMarker m)
-		:	mStorageSize(0),
-			mStorage(NULL),
-			mNextStorageSlot(0)
-		{
-		}
+class Recording;
+
+typedef LLUnit<LLUnits::Bytes, F64>			Bytes;
+typedef LLUnit<LLUnits::Kilobytes, F64>		Kilobytes;
+typedef LLUnit<LLUnits::Megabytes, F64>		Megabytes;
+typedef LLUnit<LLUnits::Gigabytes, F64>		Gigabytes;
+typedef LLUnit<LLUnits::Bits, F64>			Bits;
+typedef LLUnit<LLUnits::Kilobits, F64>		Kilobits;
+typedef LLUnit<LLUnits::Megabits, F64>		Megabits;
+typedef LLUnit<LLUnits::Gigabits, F64>		Gigabits;
+
+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;
+
+void init();
+void cleanup();
+bool isInitialized();
+
+const LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder();
+void set_thread_recorder(class ThreadRecorder*);
+
+class MasterThreadRecorder& getMasterThreadRecorder();
+
+// one per thread per type
+template<typename ACCUMULATOR>
+class AccumulatorBuffer : public LLRefCount
+{
+	typedef AccumulatorBuffer<ACCUMULATOR> self_t;
+	static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64;
+private:
+	struct StaticAllocationMarker { };
 
-	public:
+	AccumulatorBuffer(StaticAllocationMarker m)
+	:	mStorageSize(0),
+		mStorage(NULL),
+		mNextStorageSlot(0)
+	{
+	}
 
-		AccumulatorBuffer(const AccumulatorBuffer& other = *getDefaultBuffer())
-		:	mStorageSize(0),
-			mStorage(NULL),
-			mNextStorageSlot(other.mNextStorageSlot)
-		{
-			resize(other.mStorageSize);
-			for (S32 i = 0; i < mNextStorageSlot; i++)
-			{
-				mStorage[i] = other.mStorage[i];
-			}
-		}
+public:
 
-		~AccumulatorBuffer()
+	AccumulatorBuffer(const AccumulatorBuffer& other = *getDefaultBuffer())
+	:	mStorageSize(0),
+		mStorage(NULL),
+		mNextStorageSlot(other.mNextStorageSlot)
+	{
+		resize(other.mStorageSize);
+		for (S32 i = 0; i < mNextStorageSlot; i++)
 		{
-			if (LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage)
-			{
-				LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(getDefaultBuffer()->mStorage);
-			}
-			delete[] mStorage;
+			mStorage[i] = other.mStorage[i];
 		}
+	}
 
-		LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index) 
-		{ 
-			return mStorage[index]; 
+	~AccumulatorBuffer()
+	{
+		if (LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage)
+		{
+			LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(getDefaultBuffer()->mStorage);
 		}
+		delete[] mStorage;
+	}
 
-		LL_FORCE_INLINE const ACCUMULATOR& operator[](size_t index) const
-		{ 
-			return mStorage[index]; 
-		}
+	LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index) 
+	{ 
+		return mStorage[index]; 
+	}
 
-		void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other)
-		{
-			llassert(mNextStorageSlot == other.mNextStorageSlot);
+	LL_FORCE_INLINE const ACCUMULATOR& operator[](size_t index) const
+	{ 
+		return mStorage[index]; 
+	}
 
-			for (size_t i = 0; i < mNextStorageSlot; i++)
-			{
-				mStorage[i].addSamples(other.mStorage[i]);
-			}
-		}
+	void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other)
+	{
+		llassert(mNextStorageSlot == other.mNextStorageSlot);
 
-		void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
+		for (size_t i = 0; i < mNextStorageSlot; i++)
 		{
-			for (size_t i = 0; i < mNextStorageSlot; i++)
-			{
-				mStorage[i] = other.mStorage[i];
-			}
+			mStorage[i].addSamples(other.mStorage[i]);
 		}
+	}
 
-		void reset(const AccumulatorBuffer<ACCUMULATOR>* other = NULL)
+	void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
+	{
+		for (size_t i = 0; i < mNextStorageSlot; i++)
 		{
-			for (size_t i = 0; i < mNextStorageSlot; i++)
-			{
-				mStorage[i].reset(other ? &other->mStorage[i] : NULL);
-			}
+			mStorage[i] = other.mStorage[i];
 		}
+	}
 
-		void makePrimary()
+	void reset(const AccumulatorBuffer<ACCUMULATOR>* other = NULL)
+	{
+		for (size_t i = 0; i < mNextStorageSlot; i++)
 		{
-			LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(mStorage);
+			mStorage[i].reset(other ? &other->mStorage[i] : NULL);
 		}
+	}
 
-		bool isPrimary() const
-		{
-			return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage;
-		}
+	void makePrimary()
+	{
+		LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(mStorage);
+	}
 
-		LL_FORCE_INLINE static ACCUMULATOR* getPrimaryStorage() 
-		{ 
-			return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance(); 
-		}
+	bool isPrimary() const
+	{
+		return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage;
+	}
 
-		// NOTE: this is not thread-safe.  We assume that slots are reserved in the main thread before any child threads are spawned
-		size_t reserveSlot()
+	LL_FORCE_INLINE static ACCUMULATOR* getPrimaryStorage() 
+	{ 
+		return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance(); 
+	}
+
+	// NOTE: this is not thread-safe.  We assume that slots are reserved in the main thread before any child threads are spawned
+	size_t reserveSlot()
+	{
+		if (LLTrace::isInitialized())
 		{
-			if (LLTrace::isInitialized())
-			{
-				llerrs << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << llendl;
-			}
-			size_t next_slot = mNextStorageSlot++;
-			if (next_slot >= mStorageSize)
-			{
-				resize(mStorageSize + (mStorageSize >> 2));
-			}
-			llassert(mStorage && next_slot < mStorageSize);
-			return next_slot;
+			llerrs << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << llendl;
 		}
-
-		void resize(size_t new_size)
+		size_t next_slot = mNextStorageSlot++;
+		if (next_slot >= mStorageSize)
 		{
-			if (new_size <= mStorageSize) return;
+			resize(mStorageSize + (mStorageSize >> 2));
+		}
+		llassert(mStorage && next_slot < mStorageSize);
+		return next_slot;
+	}
 
-			ACCUMULATOR* old_storage = mStorage;
-			mStorage = new ACCUMULATOR[new_size];
-			if (old_storage)
-			{
-				for (S32 i = 0; i < mStorageSize; i++)
-				{
-					mStorage[i] = old_storage[i];
-				}
-			}
-			mStorageSize = new_size;
-			delete[] old_storage;
+	void resize(size_t new_size)
+	{
+		if (new_size <= mStorageSize) return;
 
-			self_t* default_buffer = getDefaultBuffer();
-			if (this != default_buffer
-				&& new_size > default_buffer->size())
+		ACCUMULATOR* old_storage = mStorage;
+		mStorage = new ACCUMULATOR[new_size];
+		if (old_storage)
+		{
+			for (S32 i = 0; i < mStorageSize; i++)
 			{
-				//NB: this is not thread safe, but we assume that all resizing occurs during static initialization
-				default_buffer->resize(new_size);
+				mStorage[i] = old_storage[i];
 			}
 		}
+		mStorageSize = new_size;
+		delete[] old_storage;
 
-		size_t size() const
+		self_t* default_buffer = getDefaultBuffer();
+		if (this != default_buffer
+			&& new_size > default_buffer->size())
 		{
-			return mNextStorageSlot;
+			//NB: this is not thread safe, but we assume that all resizing occurs during static initialization
+			default_buffer->resize(new_size);
 		}
+	}
+
+	size_t size() const
+	{
+		return mNextStorageSlot;
+	}
 
-		static self_t* getDefaultBuffer()
+	static self_t* getDefaultBuffer()
+	{
+		// this buffer is allowed to leak so that trace calls from global destructors have somewhere to put their data
+		// so as not to trigger an access violation
+		static self_t* sBuffer = new AccumulatorBuffer(StaticAllocationMarker());
+		static bool sInitialized = false;
+		if (!sInitialized)
 		{
-			// this buffer is allowed to leak so that trace calls from global destructors have somewhere to put their data
-			// so as not to trigger an access violation
-			static self_t* sBuffer = new AccumulatorBuffer(StaticAllocationMarker());
-			static bool sInitialized = false;
-			if (!sInitialized)
-			{
-				sBuffer->resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
-				sInitialized = true;
-			}
-			return sBuffer;
+			sBuffer->resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
+			sInitialized = true;
 		}
+		return sBuffer;
+	}
 
-	private:
-		ACCUMULATOR*								mStorage;
-		size_t										mStorageSize;
-		size_t										mNextStorageSlot;
-	};
+private:
+	ACCUMULATOR*								mStorage;
+	size_t										mStorageSize;
+	size_t										mNextStorageSlot;
+};
 
-	//TODO: replace with decltype when C++11 is enabled
-	template<typename T>
-	struct MeanValueType
-	{
-		typedef F64 type;
-	};
+//TODO: replace with decltype when C++11 is enabled
+template<typename T>
+struct MeanValueType
+{
+	typedef F64 type;
+};
 
-	template<typename ACCUMULATOR>
-	class TraceType 
-	:	 public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
+template<typename ACCUMULATOR>
+class TraceType 
+:	 public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
+{
+public:
+	TraceType(const char* name, const char* description = NULL)
+	:	LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>(name),
+		mName(name),
+		mDescription(description ? description : ""),
+		mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot())
+	{}
+
+	LL_FORCE_INLINE ACCUMULATOR* getPrimaryAccumulator() const
 	{
-	public:
-		TraceType(const char* name, const char* description = NULL)
-		:	LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>(name),
-			mName(name),
-			mDescription(description ? description : ""),
-			mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot())
-		{}
+		ACCUMULATOR* accumulator_storage = AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage();
+		return &accumulator_storage[mAccumulatorIndex];
+	}
 
-		LL_FORCE_INLINE ACCUMULATOR* getPrimaryAccumulator() const
-		{
-			ACCUMULATOR* accumulator_storage = AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage();
-			return &accumulator_storage[mAccumulatorIndex];
-		}
+	size_t getIndex() const { return mAccumulatorIndex; }
 
-		size_t getIndex() const { return mAccumulatorIndex; }
+	const std::string& getName() const { return mName; }
 
-		const std::string& getName() const { return mName; }
+protected:
+	const std::string	mName;
+	const std::string	mDescription;
+	const size_t		mAccumulatorIndex;
+};
 
-	protected:
-		const std::string	mName;
-		const std::string	mDescription;
-		const size_t		mAccumulatorIndex;
-	};
+template<typename T>
+class MeasurementAccumulator
+{
+public:
+	typedef T value_t;
+	typedef MeasurementAccumulator<T> self_t;
+
+	MeasurementAccumulator()
+	:	mSum(0),
+		mMin((std::numeric_limits<T>::max)()),
+		mMax((std::numeric_limits<T>::min)()),
+		mMean(0),
+		mVarianceSum(0),
+		mNumSamples(0),
+		mLastValue(0)
+	{}
 
-	template<typename T>
-	class MeasurementAccumulator
+	void sample(T value)
 	{
-	public:
-		typedef T value_t;
-		typedef MeasurementAccumulator<T> self_t;
-
-		MeasurementAccumulator()
-		:	mSum(0),
-			mMin((std::numeric_limits<T>::max)()),
-			mMax((std::numeric_limits<T>::min)()),
-			mMean(0),
-			mVarianceSum(0),
-			mNumSamples(0),
-			mLastValue(0)
-		{}
+		mNumSamples++;
+		mSum += value;
+		if (value < mMin)
+		{
+			mMin = value;
+		}
+		if (value > mMax)
+		{
+			mMax = value;
+		}
+		F64 old_mean = mMean;
+		mMean += ((F64)value - old_mean) / (F64)mNumSamples;
+		mVarianceSum += ((F64)value - old_mean) * ((F64)value - mMean);
+		mLastValue = value;
+	}
 
-		LL_FORCE_INLINE void sample(T value)
+	void addSamples(const self_t& other)
+	{
+		if (other.mNumSamples)
 		{
-			T storage_value(value);
-			mNumSamples++;
-			mSum += storage_value;
-			if (storage_value < mMin)
+			mSum += other.mSum;
+			if (other.mMin < mMin)
 			{
-				mMin = storage_value;
+				mMin = other.mMin;
 			}
-			if (storage_value > mMax)
+			if (other.mMax > mMax)
 			{
-				mMax = storage_value;
+				mMax = other.mMax;
 			}
-			F64 old_mean = mMean;
-			mMean += ((F64)storage_value - old_mean) / (F64)mNumSamples;
-			mVarianceSum += ((F64)storage_value - old_mean) * ((F64)storage_value - mMean);
-			mLastValue = storage_value;
-		}
-
-		void addSamples(const self_t& other)
-		{
-			if (other.mNumSamples)
+			F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
+			mNumSamples += other.mNumSamples;
+			mMean = mMean * weight + other.mMean * (1.f - weight);
+
+			// combine variance (and hence standard deviation) of 2 different sized sample groups using
+			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+			F64 n_1 = (F64)mNumSamples,
+				n_2 = (F64)other.mNumSamples;
+			F64 m_1 = mMean,
+				m_2 = other.mMean;
+			F64 v_1 = mVarianceSum / mNumSamples,
+				v_2 = other.mVarianceSum / other.mNumSamples;
+			if (n_1 == 0)
+			{
+				mVarianceSum = other.mVarianceSum;
+			}
+			else if (n_2 == 0)
 			{
-				mSum += other.mSum;
-				if (other.mMin < mMin)
-				{
-					mMin = other.mMin;
-				}
-				if (other.mMax > mMax)
-				{
-					mMax = other.mMax;
-				}
-				F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
-				mNumSamples += other.mNumSamples;
-				mMean = mMean * weight + other.mMean * (1.f - weight);
-
-				// combine variance (and hence standard deviation) of 2 different sized sample groups using
-				// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
-				F64 n_1 = (F64)mNumSamples,
-					n_2 = (F64)other.mNumSamples;
-				F64 m_1 = mMean,
-					m_2 = other.mMean;
-				F64 sd_1 = getStandardDeviation(),
-					sd_2 = other.getStandardDeviation();
-				if (n_1 == 0)
-				{
-					mVarianceSum = other.mVarianceSum;
-				}
-				else if (n_2 == 0)
-				{
-					// don't touch variance
-					// mVarianceSum = mVarianceSum;
-				}
-				else
-				{
-					mVarianceSum =  (F64)mNumSamples
-								* ((((n_1 - 1.f) * sd_1 * sd_1)
-									+ ((n_2 - 1.f) * sd_2 * sd_2)
-									+ (((n_1 * n_2) / (n_1 + n_2))
-										* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
-								/ (n_1 + n_2 - 1.f));
-				}
-				mLastValue = other.mLastValue;
+				// don't touch variance
+				// mVarianceSum = mVarianceSum;
 			}
+			else
+			{
+				mVarianceSum = (F64)mNumSamples
+					* ((((n_1 - 1.f) * v_1)
+					+ ((n_2 - 1.f) * v_2)
+					+ (((n_1 * n_2) / (n_1 + n_2))
+					* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+					/ (n_1 + n_2 - 1.f));
+			}
+			mLastValue = other.mLastValue;
 		}
+	}
 
-		void reset(const self_t* other)
-		{
-			mNumSamples = 0;
-			mSum = 0;
-			mMin = 0;
-			mMax = 0;
-			mMean = 0;
-			mVarianceSum = 0;
-			mLastValue = other ? other->mLastValue : 0;
-		}
+	void reset(const self_t* other)
+	{
+		mNumSamples = 0;
+		mSum = 0;
+		mMin = 0;
+		mMax = 0;
+		mMean = 0;
+		mVarianceSum = 0;
+		mLastValue = other ? other->mLastValue : 0;
+	}
 
-		T	getSum() const { return (T)mSum; }
-		T	getMin() const { return (T)mMin; }
-		T	getMax() const { return (T)mMax; }
-		T	getLastValue() const { return (T)mLastValue; }
-		F64	getMean() const { return mMean; }
-		F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mNumSamples); }
-		U32 getSampleCount() const { return mNumSamples; }
+	T	getSum() const { return (T)mSum; }
+	T	getMin() const { return (T)mMin; }
+	T	getMax() const { return (T)mMax; }
+	T	getLastValue() const { return (T)mLastValue; }
+	F64	getMean() const { return mMean; }
+	F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mNumSamples); }
+	U32 getSampleCount() const { return mNumSamples; }
 
-	private:
-		T	mSum,
-			mMin,
-			mMax,
-			mLastValue;
+private:
+	T	mSum,
+		mMin,
+		mMax,
+		mLastValue;
 
-		F64	mMean,
-			mVarianceSum;
+	F64	mMean,
+		mVarianceSum;
 
-		U32	mNumSamples;
-	};
+	U32	mNumSamples;
+};
+
+template<typename T>
+class CountAccumulator
+{
+public:
+	typedef CountAccumulator<T> self_t;
+	typedef T value_t;
+
+	CountAccumulator()
+	:	mSum(0),
+		mNumSamples(0)
+	{}
 
-	template<typename T>
-	class CountAccumulator
+	void add(T value)
 	{
-	public:
-		typedef CountAccumulator<T> self_t;
-		typedef T value_t;
+		mNumSamples++;
+		mSum += value;
+	}
 
-		CountAccumulator()
-		:	mSum(0),
-			mNumSamples(0)
-		{}
+	void addSamples(const CountAccumulator<T>& other)
+	{
+		mSum += other.mSum;
+		mNumSamples += other.mNumSamples;
+	}
 
-		LL_FORCE_INLINE void add(T value)
-		{
-			mNumSamples++;
-			mSum += value;
-		}
+	void reset(const self_t* other)
+	{
+		mNumSamples = 0;
+		mSum = 0;
+	}
 
-		void addSamples(const CountAccumulator<T>& other)
-		{
-			mSum += other.mSum;
-			mNumSamples += other.mNumSamples;
-		}
+	T	getSum() const { return (T)mSum; }
 
-		void reset(const self_t* other)
-		{
-			mNumSamples = 0;
-			mSum = 0;
-		}
+	U32 getSampleCount() const { return mNumSamples; }
 
-		T	getSum() const { return (T)mSum; }
+private:
+	T	mSum;
 
-		U32 getSampleCount() const { return mNumSamples; }
+	U32	mNumSamples;
+};
 
-	private:
-		T	mSum;
+class TimeBlockAccumulator
+{
+public:
+	typedef LLUnit<LLUnits::Seconds, F64> value_t;
+	typedef TimeBlockAccumulator self_t;
 
-		U32	mNumSamples;
+	// fake class that allows us to view call count aspect of timeblock accumulator
+	struct CallCountAspect 
+	{
+		typedef U32 value_t;
 	};
 
-	class TimeBlockAccumulator
+	struct SelfTimeAspect
 	{
-	public:
 		typedef LLUnit<LLUnits::Seconds, F64> value_t;
-		typedef TimeBlockAccumulator self_t;
+	};
 
-		// fake class that allows us to view call count aspect of timeblock accumulator
-		struct CallCountAspect 
-		{
-			typedef U32 value_t;
-		};
+	TimeBlockAccumulator();
+	void addSamples(const self_t& other);
+	void reset(const self_t* other);
+
+	//
+	// members
+	//
+	U64							mStartTotalTimeCounter,
+								mTotalTimeCounter,
+								mSelfTimeCounter;
+	U32							mCalls;
+	class TimeBlock*			mParent;		// last acknowledged parent of this time block
+	class TimeBlock*			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
 
-		struct SelfTimeAspect
-		{
-			typedef LLUnit<LLUnits::Seconds, F64> value_t;
-		};
-
-		TimeBlockAccumulator();
-		void addSamples(const self_t& other);
-		void reset(const self_t* other);
-
-		//
-		// members
-		//
-		U64							mStartTotalTimeCounter,
-									mTotalTimeCounter,
-									mSelfTimeCounter;
-		U32							mCalls;
-		class TimeBlock*			mParent;		// last acknowledged parent of this time block
-		class TimeBlock*			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
+};
 
-	};
 
+template<>
+struct MeanValueType<TraceType<TimeBlockAccumulator> >
+{
+	typedef LLUnit<LLUnits::Seconds, F64> type;
+};
 
-	template<>
-	struct MeanValueType<TraceType<TimeBlockAccumulator> >
-	{
-		typedef LLUnit<LLUnits::Seconds, F64> type;
-	};
+template<>
+class TraceType<TimeBlockAccumulator::CallCountAspect>
+:	public TraceType<TimeBlockAccumulator>
+{
+public:
 
-	template<>
-	class TraceType<TimeBlockAccumulator::CallCountAspect>
+	TraceType(const char* name, const char* description = "")
+	:	TraceType<TimeBlockAccumulator>(name, description)
+	{}
+};
+
+template<>
+struct MeanValueType<TraceType<TimeBlockAccumulator::CallCountAspect> >
+{
+	typedef F64 type;
+};
+
+
+template<>
+class TraceType<TimeBlockAccumulator::SelfTimeAspect>
 	:	public TraceType<TimeBlockAccumulator>
-	{
-	public:
+{
+public:
 
-		TraceType(const char* name, const char* description = "")
+	TraceType(const char* name, const char* description = "")
 		:	TraceType<TimeBlockAccumulator>(name, description)
-		{}
-	};
-
-	template<>
-	struct MeanValueType<TraceType<TimeBlockAccumulator::CallCountAspect> >
-	{
-		typedef F64 type;
-	};
+	{}
+};
 
+template<>
+struct MeanValueType<TraceType<TimeBlockAccumulator::SelfTimeAspect> >
+{
+	typedef LLUnit<LLUnits::Seconds, F64> type;
+};
 
-	template<>
-	class TraceType<TimeBlockAccumulator::SelfTimeAspect>
-		:	public TraceType<TimeBlockAccumulator>
-	{
-	public:
 
-		TraceType(const char* name, const char* description = "")
-			:	TraceType<TimeBlockAccumulator>(name, description)
-		{}
-	};
+class TimeBlock;
+class TimeBlockTreeNode
+{
+public:
+	TimeBlockTreeNode();
 
-	template<>
-	struct MeanValueType<TraceType<TimeBlockAccumulator::SelfTimeAspect> >
-	{
-		typedef LLUnit<LLUnits::Seconds, F64> type;
-	};
+	void setParent(TimeBlock* parent);
+	TimeBlock* getParent() { return mParent; }
 
+	TimeBlock*					mBlock;
+	TimeBlock*					mParent;	
+	std::vector<TimeBlock*>		mChildren;
+	bool						mNeedsSorting;
+};
 
-	class TimeBlock;
-	class TimeBlockTreeNode
-	{
-	public:
-		TimeBlockTreeNode();
 
-		void setParent(TimeBlock* parent);
-		TimeBlock* getParent() { return mParent; }
+template <typename T = F64>
+class MeasurementStatHandle
+:	public TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
+{
+public:
+	typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
+	typedef TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> > trace_t;
 
-		TimeBlock*					mBlock;
-		TimeBlock*					mParent;	
-		std::vector<TimeBlock*>		mChildren;
-		bool						mNeedsSorting;
-	};
+	MeasurementStatHandle(const char* name, const char* description = NULL) 
+	:	trace_t(name, description)
+	{}
+};
 
+template<typename T, typename VALUE_T>
+void sample(MeasurementStatHandle<T>& measurement, VALUE_T value)
+{
+	T converted_value(value);
+	measurement.getPrimaryAccumulator()->sample(LLUnits::rawValue(converted_value));
+}
 
-	template <typename T = F64>
-	class Measurement
-	:	public TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
-	{
-	public:
-		typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
-		typedef TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> > trace_t;
 
-		Measurement(const char* name, const char* description = NULL) 
-		:	trace_t(name, description)
-		{}
+template <typename T = F64>
+class CountStatHandle
+:	public TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
+{
+public:
+	typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
+	typedef TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> > trace_t;
 
-		template<typename UNIT_T>
-		void sample(UNIT_T value)
-		{
-			T converted_value(value);
-			trace_t::getPrimaryAccumulator()->sample(LLUnits::rawValue(converted_value));
-		}
-	};
+	CountStatHandle(const char* name, const char* description = NULL) 
+	:	trace_t(name)
+	{}
 
-	template <typename T = F64>
-	class Count 
-	:	public TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
-	{
-	public:
-		typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
-		typedef TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> > trace_t;
+};
 
-		Count(const char* name, const char* description = NULL) 
-		:	trace_t(name)
-		{}
+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));
+}
 
-		template<typename UNIT_T>
-		void add(UNIT_T value)
-		{
-			T converted_value(value);
-			trace_t::getPrimaryAccumulator()->add(LLUnits::rawValue(converted_value));
-		}
-	};
 
 struct MemStatAccumulator
 {
@@ -585,11 +587,11 @@ struct MemStatAccumulator
 				mDeallocatedCount;
 };
 
-class MemStat : public TraceType<MemStatAccumulator>
+class MemStatHandle : public TraceType<MemStatAccumulator>
 {
 public:
 	typedef TraceType<MemStatAccumulator> trace_t;
-	MemStat(const char* name)
+	MemStatHandle(const char* name)
 	:	trace_t(name)
 	{}
 };
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index af9ba02b29..6b4d4357db 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -135,11 +135,11 @@ namespace LLTrace
 		LLUnit<LLUnits::Bytes, U32> getSum(const TraceType<MemStatAccumulator>& stat) const;
 		LLUnit<LLUnits::Bytes, F32> getPerSec(const TraceType<MemStatAccumulator>& stat) const;
 
-		// Count accessors
+		// CountStatHandle accessors
 		F64 getSum(const TraceType<CountAccumulator<F64> >& stat) const;
 		S64 getSum(const TraceType<CountAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getSum(const Count<T>& stat) const
+		T getSum(const CountStatHandle<T>& stat) const
 		{
 			return (T)getSum(static_cast<const TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -147,7 +147,7 @@ namespace LLTrace
 		F64 getPerSec(const TraceType<CountAccumulator<F64> >& stat) const;
 		F64 getPerSec(const TraceType<CountAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getPerSec(const Count<T>& stat) const
+		T getPerSec(const CountStatHandle<T>& stat) const
 		{
 			return (T)getPerSec(static_cast<const TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -156,11 +156,11 @@ namespace LLTrace
 		U32 getSampleCount(const TraceType<CountAccumulator<S64> >& stat) const;
 
 
-		// Measurement accessors
+		// MeasurementStatHandle accessors
 		F64 getSum(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		S64 getSum(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getSum(const Measurement<T>& stat) const
+		T getSum(const MeasurementStatHandle<T>& stat) const
 		{
 			return (T)getSum(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -168,7 +168,7 @@ namespace LLTrace
 		F64 getPerSec(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		F64 getPerSec(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getPerSec(const Measurement<T>& stat) const
+		T getPerSec(const MeasurementStatHandle<T>& stat) const
 		{
 			return (T)getPerSec(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -176,7 +176,7 @@ namespace LLTrace
 		F64 getMin(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		S64 getMin(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getMin(const Measurement<T>& stat) const
+		T getMin(const MeasurementStatHandle<T>& stat) const
 		{
 			return (T)getMin(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -184,7 +184,7 @@ namespace LLTrace
 		F64 getMax(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		S64 getMax(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getMax(const Measurement<T>& stat) const
+		T getMax(const MeasurementStatHandle<T>& stat) const
 		{
 			return (T)getMax(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -192,7 +192,7 @@ namespace LLTrace
 		F64 getMean(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		F64 getMean(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getMean(Measurement<T>& stat) const
+		T getMean(MeasurementStatHandle<T>& stat) const
 		{
 			return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -200,7 +200,7 @@ namespace LLTrace
 		F64 getStandardDeviation(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		F64 getStandardDeviation(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getStandardDeviation(const Measurement<T>& stat) const
+		T getStandardDeviation(const MeasurementStatHandle<T>& stat) const
 		{
 			return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -208,7 +208,7 @@ namespace LLTrace
 		F64 getLastValue(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		S64 getLastValue(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getLastValue(const Measurement<T>& stat) const
+		T getLastValue(const MeasurementStatHandle<T>& stat) const
 		{
 			return (T)getLastValue(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
@@ -394,6 +394,7 @@ namespace LLTrace
 	{
 	public:
 		void extend();
+
 		Recording& getAcceptedRecording() { return mAcceptedRecording; }
 
 		// implementation for LLStopWatchControlsMixin
-- 
cgit v1.2.3


From 1a256eca280e41a672fc87e083db851ab180612c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 11 Mar 2013 00:37:50 -0700
Subject: renamed some variables/methods in LLTrace to make things clearer

---
 indra/llcommon/lltrace.h                 |  1 +
 indra/llcommon/lltracerecording.cpp      |  4 ++--
 indra/llcommon/lltracerecording.h        |  2 +-
 indra/llcommon/lltracethreadrecorder.cpp | 30 +++++++++++++++---------------
 indra/llcommon/lltracethreadrecorder.h   |  2 +-
 5 files changed, 20 insertions(+), 19 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 44da1939c6..9bca3625b6 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -287,6 +287,7 @@ public:
 	{
 		mNumSamples++;
 		mSum += value;
+		// NOTE: both conditions will hold on first pass through
 		if (value < mMin)
 		{
 			mMin = value;
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index ab8dbce2ce..3df06c5172 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -109,10 +109,10 @@ void Recording::handleSplitTo(Recording& other)
 {
 	stop();
 	other.restart();
-	syncTo(other);
+	handOffTo(other);
 }
 
-void Recording::syncTo(Recording& other)
+void Recording::handOffTo(Recording& other)
 {
 	other.mCountsFloat.write()->reset(mCountsFloat);
 	other.mMeasurementsFloat.write()->reset(mMeasurementsFloat);
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 6b4d4357db..7dd3b98187 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -218,7 +218,7 @@ namespace LLTrace
 
 		LLUnit<LLUnits::Seconds, F64> getDuration() const { return LLUnit<LLUnits::Seconds, F64>(mElapsedSeconds); }
 
-		void syncTo(Recording& other);
+		void handOffTo(Recording& other);
 
 	private:
 		friend class ThreadRecorder;
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 113febcca8..d540a60308 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -97,11 +97,11 @@ void ThreadRecorder::activate( Recording* recording )
 	ActiveRecording* active_recording = new ActiveRecording(recording);
 	if (!mActiveRecordings.empty())
 	{
-		mActiveRecordings.front()->mBaseline.syncTo(active_recording->mBaseline);
+		mActiveRecordings.front()->mPartialRecording.handOffTo(active_recording->mPartialRecording);
 	}
 	mActiveRecordings.push_front(active_recording);
 
-	mActiveRecordings.front()->mBaseline.makePrimary();
+	mActiveRecordings.front()->mPartialRecording.makePrimary();
 }
 
 ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::update( Recording* recording )
@@ -118,10 +118,10 @@ ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::update( Record
 		if (next_it != mActiveRecordings.end())
 		{
 			// ...push our gathered data down to it
-			(*next_it)->mBaseline.appendRecording((*it)->mBaseline);
+			(*next_it)->mPartialRecording.appendRecording((*it)->mPartialRecording);
 		}
 
-		// copy accumulated measurements into result buffer and clear accumulator (mBaseline)
+		// copy accumulated measurements into result buffer and clear accumulator (mPartialRecording)
 		(*it)->moveBaselineToTarget();
 
 		if ((*it)->mTargetRecording == recording)
@@ -171,16 +171,16 @@ ThreadRecorder::ActiveRecording::ActiveRecording( Recording* target )
 
 void ThreadRecorder::ActiveRecording::moveBaselineToTarget()
 {
-	mTargetRecording->mMeasurementsFloat.write()->addSamples(*mBaseline.mMeasurementsFloat);
-	mTargetRecording->mCountsFloat.write()->addSamples(*mBaseline.mCountsFloat);
-	mTargetRecording->mMeasurements.write()->addSamples(*mBaseline.mMeasurements);
-	mTargetRecording->mCounts.write()->addSamples(*mBaseline.mCounts);
-	mTargetRecording->mStackTimers.write()->addSamples(*mBaseline.mStackTimers);
-	mBaseline.mMeasurementsFloat.write()->reset();
-	mBaseline.mCountsFloat.write()->reset();
-	mBaseline.mMeasurements.write()->reset();
-	mBaseline.mCounts.write()->reset();
-	mBaseline.mStackTimers.write()->reset();
+	mTargetRecording->mMeasurementsFloat.write()->addSamples(*mPartialRecording.mMeasurementsFloat);
+	mTargetRecording->mCountsFloat.write()->addSamples(*mPartialRecording.mCountsFloat);
+	mTargetRecording->mMeasurements.write()->addSamples(*mPartialRecording.mMeasurements);
+	mTargetRecording->mCounts.write()->addSamples(*mPartialRecording.mCounts);
+	mTargetRecording->mStackTimers.write()->addSamples(*mPartialRecording.mStackTimers);
+	mPartialRecording.mMeasurementsFloat.write()->reset();
+	mPartialRecording.mCountsFloat.write()->reset();
+	mPartialRecording.mMeasurements.write()->reset();
+	mPartialRecording.mCounts.write()->reset();
+	mPartialRecording.mStackTimers.write()->reset();
 }
 
 
@@ -251,7 +251,7 @@ void MasterThreadRecorder::pullFromSlaveThreads()
 
 	LLMutexLock lock(&mSlaveListMutex);
 
-	Recording& target_recording = mActiveRecordings.front()->mBaseline;
+	Recording& target_recording = mActiveRecordings.front()->mPartialRecording;
 	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
 		it != end_it;
 		++it)
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 0e6c091900..ee2e04236a 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -59,7 +59,7 @@ namespace LLTrace
 			ActiveRecording(Recording* target);
 
 			Recording*	mTargetRecording;
-			Recording	mBaseline;
+			Recording	mPartialRecording;
 
 			void moveBaselineToTarget();
 		};
-- 
cgit v1.2.3


From 24a1ceb25de2b9573eb369a6e0d1811fe594aabb Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 11 Mar 2013 01:08:51 -0700
Subject: separated RecordingBuffers from Recording to make active recording
 stack more safe

---
 indra/llcommon/lltracerecording.cpp | 166 +++++++++++++++++++-----------------
 indra/llcommon/lltracerecording.h   |  38 +++++----
 2 files changed, 111 insertions(+), 93 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 3df06c5172..ef0a633c9c 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -34,13 +34,13 @@
 namespace LLTrace
 {
 
+
 ///////////////////////////////////////////////////////////////////////
-// Recording
+// RecordingBuffers
 ///////////////////////////////////////////////////////////////////////
 
-Recording::Recording() 
-:	mElapsedSeconds(0),
-	mCountsFloat(new AccumulatorBuffer<CountAccumulator<F64> >()),
+RecordingBuffers::RecordingBuffers() 
+:	mCountsFloat(new AccumulatorBuffer<CountAccumulator<F64> >()),
 	mMeasurementsFloat(new AccumulatorBuffer<MeasurementAccumulator<F64> >()),
 	mCounts(new AccumulatorBuffer<CountAccumulator<S64> >()),
 	mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<S64> >()),
@@ -48,71 +48,7 @@ Recording::Recording()
 	mMemStats(new AccumulatorBuffer<MemStatAccumulator>())
 {}
 
-Recording::Recording( const Recording& other )
-{
-	llassert(other.mCountsFloat.notNull());
-	mSamplingTimer     = other.mSamplingTimer;
-	mElapsedSeconds    = other.mElapsedSeconds;
-	mCountsFloat       = other.mCountsFloat;
-	mMeasurementsFloat = other.mMeasurementsFloat;
-	mCounts            = other.mCounts;
-	mMeasurements      = other.mMeasurements;
-	mStackTimers       = other.mStackTimers;
-	mMemStats		   = other.mMemStats;
-
-	LLStopWatchControlsMixin<Recording>::setPlayState(other.getPlayState());
-}
-
-
-Recording::~Recording()
-{
-	stop();
-	llassert(isStopped());
-}
-
-void Recording::update()
-{
-	if (isStarted())
-	{
-		LLTrace::get_thread_recorder()->update(this);
-		mSamplingTimer.reset();
-	}
-}
-
-void Recording::handleReset()
-{
-	mCountsFloat.write()->reset();
-	mMeasurementsFloat.write()->reset();
-	mCounts.write()->reset();
-	mMeasurements.write()->reset();
-	mStackTimers.write()->reset();
-	mMemStats.write()->reset();
-
-	mElapsedSeconds = 0.0;
-	mSamplingTimer.reset();
-}
-
-void Recording::handleStart()
-{
-	mSamplingTimer.reset();
-	LLTrace::get_thread_recorder()->activate(this);
-}
-
-void Recording::handleStop()
-{
-	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
-	LLTrace::TimeBlock::processTimes();
-	LLTrace::get_thread_recorder()->deactivate(this);
-}
-
-void Recording::handleSplitTo(Recording& other)
-{
-	stop();
-	other.restart();
-	handOffTo(other);
-}
-
-void Recording::handOffTo(Recording& other)
+void RecordingBuffers::handOffTo(RecordingBuffers& other)
 {
 	other.mCountsFloat.write()->reset(mCountsFloat);
 	other.mMeasurementsFloat.write()->reset(mMeasurementsFloat);
@@ -122,7 +58,7 @@ void Recording::handOffTo(Recording& other)
 	other.mMemStats.write()->reset(mMemStats);
 }
 
-void Recording::makePrimary()
+void RecordingBuffers::makePrimary()
 {
 	mCountsFloat.write()->makePrimary();
 	mMeasurementsFloat.write()->makePrimary();
@@ -144,12 +80,12 @@ void Recording::makePrimary()
 	}
 }
 
-bool Recording::isPrimary() const
+bool RecordingBuffers::isPrimary() const
 {
 	return mCounts->isPrimary();
 }
 
-void Recording::makeUnique()
+void RecordingBuffers::makeUnique()
 {
 	mCountsFloat.makeUnique();
 	mMeasurementsFloat.makeUnique();
@@ -159,19 +95,17 @@ void Recording::makeUnique()
 	mMemStats.makeUnique();
 }
 
-void Recording::appendRecording( const Recording& other )
+void RecordingBuffers::appendBuffers( const RecordingBuffers& other )
 {
 	mCountsFloat.write()->addSamples(*other.mCountsFloat);
 	mMeasurementsFloat.write()->addSamples(*other.mMeasurementsFloat);
 	mCounts.write()->addSamples(*other.mCounts);
 	mMeasurements.write()->addSamples(*other.mMeasurements);
 	mMemStats.write()->addSamples(*other.mMemStats);
-
 	mStackTimers.write()->addSamples(*other.mStackTimers);
-	mElapsedSeconds += other.mElapsedSeconds;
 }
 
-void Recording::mergeRecording( const Recording& other)
+void RecordingBuffers::mergeBuffers( const RecordingBuffers& other)
 {
 	mCountsFloat.write()->addSamples(*other.mCountsFloat);
 	mMeasurementsFloat.write()->addSamples(*other.mMeasurementsFloat);
@@ -180,6 +114,84 @@ void Recording::mergeRecording( const Recording& other)
 	mMemStats.write()->addSamples(*other.mMemStats);
 }
 
+void RecordingBuffers::resetBuffers(RecordingBuffers* other)
+{
+	mCountsFloat.write()->reset(other ? other->mCountsFloat : NULL);
+	mMeasurementsFloat.write()->reset(other ? other->mMeasurementsFloat : NULL);
+	mCounts.write()->reset(other ? other->mCounts : NULL);
+	mMeasurements.write()->reset(other ? other->mMeasurements : NULL);
+	mStackTimers.write()->reset(other ? other->mStackTimers : NULL);
+	mMemStats.write()->reset(other ? other->mMemStats : NULL);
+}
+
+///////////////////////////////////////////////////////////////////////
+// Recording
+///////////////////////////////////////////////////////////////////////
+
+Recording::Recording() 
+:	mElapsedSeconds(0)
+{}
+
+Recording::Recording( const Recording& other )
+{
+	LLStopWatchControlsMixin<Recording>::setPlayState(other.getPlayState());
+}
+
+
+Recording::~Recording()
+{
+	stop();
+	llassert(isStopped());
+}
+
+void Recording::update()
+{
+	if (isStarted())
+	{
+		LLTrace::get_thread_recorder()->update(this);
+		mSamplingTimer.reset();
+	}
+}
+
+void Recording::handleReset()
+{
+	resetBuffers();
+
+	mElapsedSeconds = 0.0;
+	mSamplingTimer.reset();
+}
+
+void Recording::handleStart()
+{
+	mSamplingTimer.reset();
+	LLTrace::get_thread_recorder()->activate(this);
+}
+
+void Recording::handleStop()
+{
+	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+	LLTrace::TimeBlock::processTimes();
+	LLTrace::get_thread_recorder()->deactivate(this);
+}
+
+void Recording::handleSplitTo(Recording& other)
+{
+	stop();
+	other.restart();
+	handOffTo(other);
+}
+
+void Recording::appendRecording( const Recording& other )
+{
+	appendBuffers(other);
+	mElapsedSeconds += other.mElapsedSeconds;
+}
+
+void Recording::mergeRecording( const Recording& other)
+{
+	mergeBuffers(other);
+}
+
 LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) const
 {
 	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
@@ -356,8 +368,6 @@ U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<S64> >& st
 	return (*mMeasurements)[stat.getIndex()].getSampleCount();
 }
 
-
-
 ///////////////////////////////////////////////////////////////////////
 // PeriodicRecording
 ///////////////////////////////////////////////////////////////////////
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 7dd3b98187..a5edcb857a 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -100,19 +100,36 @@ private:
 
 namespace LLTrace
 {
-	class Recording : public LLStopWatchControlsMixin<Recording>
+	struct RecordingBuffers
 	{
-	public:
-		Recording();
-
-		Recording(const Recording& other);
-		~Recording();
+		RecordingBuffers();
+		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<F64> > >		mCountsFloat;
+		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > >	mMeasurementsFloat;
+		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<S64> > >		mCounts;
+		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<S64> > >	mMeasurements;
+		LLCopyOnWritePointer<AccumulatorBuffer<TimeBlockAccumulator> >			mStackTimers;
+		LLCopyOnWritePointer<AccumulatorBuffer<MemStatAccumulator> >			mMemStats;
 
+		void handOffTo(RecordingBuffers& other);
 		void makePrimary();
 		bool isPrimary() const;
 
 		void makeUnique();
 
+		void appendBuffers(const RecordingBuffers& other);
+		void mergeBuffers(const RecordingBuffers& other);
+		void resetBuffers(RecordingBuffers* other = NULL);
+
+	};
+
+	class Recording : public LLStopWatchControlsMixin<Recording>, public RecordingBuffers
+	{
+	public:
+		Recording();
+
+		Recording(const Recording& other);
+		~Recording();
+
 		// accumulate data from subsequent, non-overlapping recording
 		void appendRecording(const Recording& other);
 
@@ -218,8 +235,6 @@ namespace LLTrace
 
 		LLUnit<LLUnits::Seconds, F64> getDuration() const { return LLUnit<LLUnits::Seconds, F64>(mElapsedSeconds); }
 
-		void handOffTo(Recording& other);
-
 	private:
 		friend class ThreadRecorder;
 
@@ -232,13 +247,6 @@ namespace LLTrace
 		// returns data for current thread
 		class ThreadRecorder* getThreadRecorder(); 
 
-		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<F64> > >		mCountsFloat;
-		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > >	mMeasurementsFloat;
-		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<S64> > >		mCounts;
-		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<S64> > >	mMeasurements;
-		LLCopyOnWritePointer<AccumulatorBuffer<TimeBlockAccumulator> >			mStackTimers;
-		LLCopyOnWritePointer<AccumulatorBuffer<MemStatAccumulator> >			mMemStats;
-
 		LLTimer			mSamplingTimer;
 		F64				mElapsedSeconds;
 	};
-- 
cgit v1.2.3


From b9c78533ae701fe6af5263e902f8df93c558e493 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 11 Mar 2013 01:09:48 -0700
Subject: separated RecordingBuffers from Recording to make active recording
 stack more safe (part 2)

---
 indra/llcommon/lltracethreadrecorder.cpp | 26 +++++++++-----------------
 indra/llcommon/lltracethreadrecorder.h   |  6 +++---
 2 files changed, 12 insertions(+), 20 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index d540a60308..9bef040cf7 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -118,7 +118,7 @@ ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::update( Record
 		if (next_it != mActiveRecordings.end())
 		{
 			// ...push our gathered data down to it
-			(*next_it)->mPartialRecording.appendRecording((*it)->mPartialRecording);
+			(*next_it)->mPartialRecording.appendBuffers((*it)->mPartialRecording);
 		}
 
 		// copy accumulated measurements into result buffer and clear accumulator (mPartialRecording)
@@ -171,16 +171,8 @@ ThreadRecorder::ActiveRecording::ActiveRecording( Recording* target )
 
 void ThreadRecorder::ActiveRecording::moveBaselineToTarget()
 {
-	mTargetRecording->mMeasurementsFloat.write()->addSamples(*mPartialRecording.mMeasurementsFloat);
-	mTargetRecording->mCountsFloat.write()->addSamples(*mPartialRecording.mCountsFloat);
-	mTargetRecording->mMeasurements.write()->addSamples(*mPartialRecording.mMeasurements);
-	mTargetRecording->mCounts.write()->addSamples(*mPartialRecording.mCounts);
-	mTargetRecording->mStackTimers.write()->addSamples(*mPartialRecording.mStackTimers);
-	mPartialRecording.mMeasurementsFloat.write()->reset();
-	mPartialRecording.mCountsFloat.write()->reset();
-	mPartialRecording.mMeasurements.write()->reset();
-	mPartialRecording.mCounts.write()->reset();
-	mPartialRecording.mStackTimers.write()->reset();
+	mTargetRecording->appendBuffers(mPartialRecording);
+	mPartialRecording.resetBuffers();
 }
 
 
@@ -220,16 +212,16 @@ void SlaveThreadRecorder::SharedData::appendTo( Recording& sink )
 	sink.appendRecording(mRecording);
 }
 
-void SlaveThreadRecorder::SharedData::mergeFrom( const Recording& source )
+void SlaveThreadRecorder::SharedData::mergeFrom( const RecordingBuffers& source )
 {
 	LLMutexLock lock(&mRecordingMutex);
-	mRecording.mergeRecording(source);
+	mRecording.mergeBuffers(source);
 }
 
-void SlaveThreadRecorder::SharedData::mergeTo( Recording& sink )
+void SlaveThreadRecorder::SharedData::mergeTo( RecordingBuffers& sink )
 {
 	LLMutexLock lock(&mRecordingMutex);
-	sink.mergeRecording(mRecording);
+	sink.mergeBuffers(mRecording);
 }
 
 void SlaveThreadRecorder::SharedData::reset()
@@ -251,13 +243,13 @@ void MasterThreadRecorder::pullFromSlaveThreads()
 
 	LLMutexLock lock(&mSlaveListMutex);
 
-	Recording& target_recording = mActiveRecordings.front()->mPartialRecording;
+	RecordingBuffers& target_recording_buffers = mActiveRecordings.front()->mPartialRecording;
 	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
 		it != end_it;
 		++it)
 	{
 		// ignore block timing info for now
-		(*it)->mSharedData.mergeTo(target_recording);
+		(*it)->mSharedData.mergeTo(target_recording_buffers);
 		(*it)->mSharedData.reset();
 	}
 }
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index ee2e04236a..3e24303d92 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -59,7 +59,7 @@ namespace LLTrace
 			ActiveRecording(Recording* target);
 
 			Recording*	mTargetRecording;
-			Recording	mPartialRecording;
+			RecordingBuffers	mPartialRecording;
 
 			void moveBaselineToTarget();
 		};
@@ -111,8 +111,8 @@ namespace LLTrace
 		public:
 			void appendFrom(const Recording& source);
 			void appendTo(Recording& sink);
-			void mergeFrom(const Recording& source);
-			void mergeTo(Recording& sink);
+			void mergeFrom(const RecordingBuffers& source);
+			void mergeTo(RecordingBuffers& sink);
 			void reset();
 		private:
 			LLMutex		mRecordingMutex;
-- 
cgit v1.2.3


From 7b4d27ecbcb5ac702459be97cbf6b81354850658 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 14 Mar 2013 19:36:50 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 collapsed Orientation enums to all use LLView::EOrientation added ability to
 display stat bar horizontally

---
 indra/llcommon/lltracerecording.cpp |  2 +-
 indra/llcommon/lltracerecording.h   | 16 +++++++++-------
 2 files changed, 10 insertions(+), 8 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index ef0a633c9c..6695ebeaca 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -547,7 +547,7 @@ void ExtendableRecording::splitFrom(ExtendableRecording& other)
 
 PeriodicRecording& get_frame_recording()
 {
-	static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(200, PeriodicRecording::STARTED));
+	static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(1000, PeriodicRecording::STARTED));
 	return *sRecording;
 }
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index a5edcb857a..70afe51d6e 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -100,15 +100,10 @@ private:
 
 namespace LLTrace
 {
-	struct RecordingBuffers
+	class RecordingBuffers
 	{
+	public:
 		RecordingBuffers();
-		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<F64> > >		mCountsFloat;
-		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > >	mMeasurementsFloat;
-		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<S64> > >		mCounts;
-		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<S64> > >	mMeasurements;
-		LLCopyOnWritePointer<AccumulatorBuffer<TimeBlockAccumulator> >			mStackTimers;
-		LLCopyOnWritePointer<AccumulatorBuffer<MemStatAccumulator> >			mMemStats;
 
 		void handOffTo(RecordingBuffers& other);
 		void makePrimary();
@@ -120,6 +115,13 @@ namespace LLTrace
 		void mergeBuffers(const RecordingBuffers& other);
 		void resetBuffers(RecordingBuffers* other = NULL);
 
+	protected:
+		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<F64> > >		mCountsFloat;
+		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > >	mMeasurementsFloat;
+		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<S64> > >		mCounts;
+		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<S64> > >	mMeasurements;
+		LLCopyOnWritePointer<AccumulatorBuffer<TimeBlockAccumulator> >			mStackTimers;
+		LLCopyOnWritePointer<AccumulatorBuffer<MemStatAccumulator> >			mMemStats;
 	};
 
 	class Recording : public LLStopWatchControlsMixin<Recording>, public RecordingBuffers
-- 
cgit v1.2.3


From 8de397b19ec9e2f6206fd5ae57dba96c70e78b74 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 18 Mar 2013 08:43:03 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 changed LLCriticalDamp to LLSmoothInterpolation and sped up interpolator
 lookup improvements to stats display of llstatbar added scene load stats
 floater accessed with ctrl|shift|2

---
 indra/llcommon/llcriticaldamp.cpp   | 77 ++++++++++++++++++++++++++-----------
 indra/llcommon/llcriticaldamp.h     | 32 ++++++++++++---
 indra/llcommon/lltracerecording.cpp | 17 --------
 indra/llcommon/lltracerecording.h   |  8 ----
 4 files changed, 80 insertions(+), 54 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llcriticaldamp.cpp b/indra/llcommon/llcriticaldamp.cpp
index 87d79b1ee0..59a31bf9df 100644
--- a/indra/llcommon/llcriticaldamp.cpp
+++ b/indra/llcommon/llcriticaldamp.cpp
@@ -27,18 +27,38 @@
 #include "linden_common.h"
 
 #include "llcriticaldamp.h"
+#include <algorithm>
 
 //-----------------------------------------------------------------------------
 // static members
 //-----------------------------------------------------------------------------
-LLFrameTimer LLCriticalDamp::sInternalTimer;
-std::map<F32, F32> LLCriticalDamp::sInterpolants;
-F32 LLCriticalDamp::sTimeDelta;
+LLFrameTimer LLSmoothInterpolation::sInternalTimer;
+std::vector<LLSmoothInterpolation::Interpolant> LLSmoothInterpolation::sInterpolants;
+F32 LLSmoothInterpolation::sTimeDelta;
+
+// helper functors
+struct LLSmoothInterpolation::CompareTimeConstants
+{
+	bool operator()(const F32& a, const LLSmoothInterpolation::Interpolant& b) const
+	{
+		return a < b.mTimeScale;
+	}
+
+	bool operator()(const LLSmoothInterpolation::Interpolant& a, const F32& b) const
+	{
+		return a.mTimeScale < b; // bottom of a is higher than bottom of b
+	}
+
+	bool operator()(const LLSmoothInterpolation::Interpolant& a, const LLSmoothInterpolation::Interpolant& b) const
+	{
+		return a.mTimeScale < b.mTimeScale; // bottom of a is higher than bottom of b
+	}
+};
 
 //-----------------------------------------------------------------------------
-// LLCriticalDamp()
+// LLSmoothInterpolation()
 //-----------------------------------------------------------------------------
-LLCriticalDamp::LLCriticalDamp()
+LLSmoothInterpolation::LLSmoothInterpolation()
 {
 	sTimeDelta = 0.f;
 }
@@ -47,43 +67,54 @@ LLCriticalDamp::LLCriticalDamp()
 //-----------------------------------------------------------------------------
 // updateInterpolants()
 //-----------------------------------------------------------------------------
-void LLCriticalDamp::updateInterpolants()
+void LLSmoothInterpolation::updateInterpolants()
 {
 	sTimeDelta = sInternalTimer.getElapsedTimeAndResetF32();
 
-	F32 time_constant;
-
-	for (std::map<F32, F32>::iterator iter = sInterpolants.begin();
-		 iter != sInterpolants.end(); iter++)
+	for (S32 i = 0; i < sInterpolants.size(); i++)
 	{
-		time_constant = iter->first;
-		F32 new_interpolant = 1.f - pow(2.f, -sTimeDelta / time_constant);
-		new_interpolant = llclamp(new_interpolant, 0.f, 1.f);
-		sInterpolants[time_constant] = new_interpolant;
+		Interpolant& interp = sInterpolants[i];
+		interp.mInterpolant = calcInterpolant(interp.mTimeScale);
 	}
 } 
 
 //-----------------------------------------------------------------------------
 // getInterpolant()
 //-----------------------------------------------------------------------------
-F32 LLCriticalDamp::getInterpolant(const F32 time_constant, BOOL use_cache)
+F32 LLSmoothInterpolation::getInterpolant(LLUnit<LLUnits::Seconds, F32> time_constant, bool use_cache)
 {
 	if (time_constant == 0.f)
 	{
 		return 1.f;
 	}
 
-	if (use_cache && sInterpolants.count(time_constant))
+	if (use_cache)
 	{
-		return sInterpolants[time_constant];
+		interpolant_vec_t::iterator find_it = std::lower_bound(sInterpolants.begin(), sInterpolants.end(), time_constant.value(), CompareTimeConstants());
+		if (find_it != sInterpolants.end() && find_it->mTimeScale == time_constant) 
+		{
+			return find_it->mInterpolant;
+		}
+		else
+		{
+			Interpolant interp;
+			interp.mTimeScale = time_constant.value();
+			interp.mInterpolant = calcInterpolant(time_constant.value());
+			sInterpolants.insert(find_it, interp);
+			return interp.mInterpolant;
+		}
 	}
-	
-	F32 interpolant = 1.f - pow(2.f, -sTimeDelta / time_constant);
-	interpolant = llclamp(interpolant, 0.f, 1.f);
-	if (use_cache)
+	else
 	{
-		sInterpolants[time_constant] = interpolant;
+		return calcInterpolant(time_constant.value());
+
 	}
+}
 
-	return interpolant;
+//-----------------------------------------------------------------------------
+// getInterpolant()
+//-----------------------------------------------------------------------------
+F32 LLSmoothInterpolation::calcInterpolant(F32 time_constant)
+{
+	return llclamp(1.f - pow(2.f, -sTimeDelta / time_constant), 0.f, 1.f);
 }
diff --git a/indra/llcommon/llcriticaldamp.h b/indra/llcommon/llcriticaldamp.h
index 52f052ae25..ab5d4ba6e2 100644
--- a/indra/llcommon/llcriticaldamp.h
+++ b/indra/llcommon/llcriticaldamp.h
@@ -28,26 +28,46 @@
 #ifndef LL_LLCRITICALDAMP_H
 #define LL_LLCRITICALDAMP_H
 
-#include <map>
+#include <vector>
 
 #include "llframetimer.h"
+#include "llunit.h"
 
-class LL_COMMON_API LLCriticalDamp 
+class LL_COMMON_API LLSmoothInterpolation 
 {
 public:
-	LLCriticalDamp();
+	LLSmoothInterpolation();
 
 	// MANIPULATORS
 	static void updateInterpolants();
 
 	// ACCESSORS
-	static F32 getInterpolant(const F32 time_constant, BOOL use_cache = TRUE);
+	static F32 getInterpolant(LLUnit<LLUnits::Seconds, F32> time_constant, bool use_cache = true);
 
-protected:	
+	template<typename T> 
+	static T lerp(T a, T b, LLUnit<LLUnits::Seconds, F32> time_constant, bool use_cache = true)
+	{
+		F32 interpolant = getInterpolant(time_constant, use_cache);
+		return ((a * (1.f - interpolant)) 
+				+ (b * interpolant));
+	}
+
+protected:
+	static F32 calcInterpolant(F32 time_constant);
+
+	struct CompareTimeConstants;
 	static LLFrameTimer sInternalTimer;	// frame timer for calculating deltas
 
-	static std::map<F32, F32> 	sInterpolants;
+	struct Interpolant
+	{
+		F32 mTimeScale;
+		F32 mInterpolant;
+	};
+	typedef std::vector<Interpolant> interpolant_vec_t;
+	static interpolant_vec_t 	sInterpolants;
 	static F32					sTimeDelta;
 };
 
+typedef LLSmoothInterpolation LLCriticalDamp;
+
 #endif  // LL_LLCRITICALDAMP_H
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 6695ebeaca..259f5a7a27 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -291,23 +291,6 @@ U32 Recording::getSampleCount( const TraceType<CountAccumulator<S64> >& stat ) c
 	return (*mMeasurementsFloat)[stat.getIndex()].getSampleCount();
 }
 
-
-F64 Recording::getPerSec( const TraceType<MeasurementAccumulator<F64> >& stat ) const
-{
-	F64 sum = (*mMeasurementsFloat)[stat.getIndex()].getSum();
-	return  (sum != 0.0) 
-		? (sum / mElapsedSeconds)
-		: 0.0;
-}
-
-F64 Recording::getPerSec( const TraceType<MeasurementAccumulator<S64> >& stat ) const
-{
-	S64 sum = (*mMeasurements)[stat.getIndex()].getSum();
-	return (sum != 0) 
-		? ((F64)sum / mElapsedSeconds)
-		: 0.0;
-}
-
 F64 Recording::getMin( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
 	return (*mMeasurementsFloat)[stat.getIndex()].getMin();
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 70afe51d6e..751ff298ce 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -184,14 +184,6 @@ namespace LLTrace
 			return (T)getSum(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getPerSec(const TraceType<MeasurementAccumulator<F64> >& stat) const;
-		F64 getPerSec(const TraceType<MeasurementAccumulator<S64> >& stat) const;
-		template <typename T>
-		T getPerSec(const MeasurementStatHandle<T>& stat) const
-		{
-			return (T)getPerSec(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
-		}
-
 		F64 getMin(const TraceType<MeasurementAccumulator<F64> >& stat) const;
 		S64 getMin(const TraceType<MeasurementAccumulator<S64> >& stat) const;
 		template <typename T>
-- 
cgit v1.2.3


From 78f60fad0e4608cb996ee9cba8e4d10d3893f54d Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 18 Mar 2013 23:37:57 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 cleaned up MemTrackable stats to not use special padded allocation

---
 indra/llcommon/lltrace.h | 81 ++++++------------------------------------------
 1 file changed, 9 insertions(+), 72 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 9bca3625b6..71bf1e53e4 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -674,57 +674,6 @@ struct MemFootprint<std::list<T> >
 	}
 };
 
-template <size_t ALIGNMENT, size_t RESERVE>
-void* allocAligned(size_t size)
-{
-	llstatic_assert((ALIGNMENT > 0) && (ALIGNMENT & (ALIGNMENT - 1)) == 0, "Alignment must be a power of 2");
-
-	void* padded_allocation;
-	const size_t aligned_reserve = (RESERVE / ALIGNMENT) 
-		+ ((RESERVE % ALIGNMENT) ? ALIGNMENT : 0);
-	const size_t size_with_reserve = size + aligned_reserve;
-	if (ALIGNMENT <= LL_DEFAULT_HEAP_ALIGN)
-	{
-		padded_allocation = malloc(size_with_reserve);
-	}
-	else
-	{
-#if LL_WINDOWS
-		padded_allocation = _aligned_malloc(size_with_reserve, ALIGNMENT);
-#elif LL_DARWIN
-		padded_allocation = ll_aligned_malloc(size_with_reserve, ALIGNMENT);
-#else
-		if (LL_UNLIKELY(0 != posix_memalign(&padded_allocation, 16, size)))
-			padded_allocation = NULL;
-#endif
-	}
-	return (char*)padded_allocation + aligned_reserve;
-}
-
-template<size_t ALIGNMENT, size_t RESERVE>
-void deallocAligned(void* ptr)
-{
-	const size_t aligned_reserve = (RESERVE / ALIGNMENT) 
-		+ ((RESERVE % ALIGNMENT) ? ALIGNMENT : 0);
-
-	void* original_allocation = (char*)ptr - aligned_reserve;
-
-	if (ALIGNMENT <= LL_DEFAULT_HEAP_ALIGN)
-	{
-		free(original_allocation);
-	}
-	else
-	{
-#if LL_WINDOWS
-		_aligned_free(original_allocation);
-#elif LL_DARWIN
-		ll_aligned_free(original_allocation);
-#else
-		free(original_allocation);		
-#endif
-	}	
-}
-
 template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN>
 class MemTrackable
 {
@@ -736,7 +685,7 @@ class MemTrackable
 public:
 	typedef void mem_trackable_tag_t;
 
-	~MemTrackable()
+	virtual ~MemTrackable()
 	{
 		memDisclaim(mMemFootprint);
 	}
@@ -750,24 +699,19 @@ public:
 			accumulator->mAllocatedCount++;
 		}
 
-		// reserve 4 bytes for allocation size (and preserving requested alignment)
-		void* allocation = allocAligned<ALIGNMENT, sizeof(size_t)>(size);
-		((size_t*)allocation)[-1] = size;
-
-		return allocation;
+		return ::operator new(size);
 	}
 
-	void operator delete(void* ptr)
+	void operator delete(void* ptr, size_t size)
 	{
-		size_t allocation_size = ((size_t*)ptr)[-1];
 		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
-			accumulator->mSize -= allocation_size;
+			accumulator->mSize -= size;
 			accumulator->mAllocatedCount--;
 			accumulator->mDeallocatedCount++;
 		}
-		deallocAligned<ALIGNMENT, sizeof(size_t)>(ptr);
+		::operator delete(ptr);
 	}
 
 	void *operator new [](size_t size)
@@ -779,24 +723,19 @@ public:
 			accumulator->mAllocatedCount++;
 		}
 
-		// reserve 4 bytes for allocation size (and preserving requested alignment)
-		void* allocation = allocAligned<ALIGNMENT, sizeof(size_t)>(size);
-		((size_t*)allocation)[-1] = size;
-
-		return allocation;
+		return ::operator new[](size);
 	}
 
-	void operator delete[](void* ptr)
+	void operator delete[](void* ptr, size_t size)
 	{
-		size_t* allocation_size = (size_t*)((char*)ptr - 8);
 		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
-			accumulator->mSize -= *allocation_size;
+			accumulator->mSize -= size;
 			accumulator->mAllocatedCount--;
 			accumulator->mDeallocatedCount++;
 		}
-		deallocAligned<ALIGNMENT, sizeof(size_t)>(ptr);
+		::operator delete[](ptr);
 	}
 
 	// claim memory associated with other objects/data as our own, adding to our calculated footprint
@@ -853,8 +792,6 @@ public:
 private:
 	size_t mMemFootprint;
 
-
-
 	template<typename TRACKED, typename TRACKED_IS_TRACKER = void>
 	struct TrackMemImpl
 	{
-- 
cgit v1.2.3


From 1f507c3cfca0c7722ebeaf71883fbaa83988e1a9 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 21 Mar 2013 00:37:20 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 copied over scene load frame differencing changes from viewer-interesting
 made periodicrecording flexible enough to allow for indefinite number of
 periods added scene loading stats floater fixed collapsing behavior of
 container views

---
 indra/llcommon/lltracerecording.cpp | 55 +++++++++++++++++++------------------
 indra/llcommon/lltracerecording.h   | 51 +++++++++++++++++++---------------
 indra/llcommon/llunit.h             |  8 +++---
 3 files changed, 61 insertions(+), 53 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 259f5a7a27..5d74ea32df 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -355,41 +355,30 @@ U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<S64> >& st
 // PeriodicRecording
 ///////////////////////////////////////////////////////////////////////
 
-PeriodicRecording::PeriodicRecording( S32 num_periods, EPlayState state) 
-:	mNumPeriods(num_periods),
+PeriodicRecording::PeriodicRecording( U32 num_periods, EPlayState state) 
+:	mAutoResize(num_periods == 0),
 	mCurPeriod(0),
-	mTotalValid(false),
-	mRecordingPeriods( new Recording[num_periods])
+	mTotalValid(false)
 {
-	llassert(mNumPeriods > 0);
-	setPlayState(state);
-}
-
-PeriodicRecording::PeriodicRecording(PeriodicRecording& other)
-:	mNumPeriods(other.mNumPeriods),
-	mCurPeriod(other.mCurPeriod),
-	mTotalValid(other.mTotalValid),
-	mTotalRecording(other.mTotalRecording)
-{
-	mRecordingPeriods = new Recording[mNumPeriods];
-	for (S32 i = 0; i < mNumPeriods; i++)
+	if (num_periods)
 	{
-		mRecordingPeriods[i] = other.mRecordingPeriods[i];
+		mRecordingPeriods.resize(num_periods);
 	}
+	setPlayState(state);
 }
 
-
-PeriodicRecording::~PeriodicRecording()
-{
-	delete[] mRecordingPeriods;
-}
-
-
 void PeriodicRecording::nextPeriod()
 {
 	EPlayState play_state = getPlayState();
 	Recording& old_recording = getCurRecordingPeriod();
-	mCurPeriod = (mCurPeriod + 1) % mNumPeriods;
+	if (mAutoResize)
+	{
+		mRecordingPeriods.push_back(Recording());
+	}
+	U32 num_periods = mRecordingPeriods.size();
+	mCurPeriod = (num_periods > 0) 
+				? (mCurPeriod + 1) % num_periods 
+				: mCurPeriod + 1;
 	old_recording.splitTo(getCurRecordingPeriod());
 
 	switch(play_state)
@@ -412,9 +401,21 @@ Recording& PeriodicRecording::getTotalRecording()
 	if (!mTotalValid)
 	{
 		mTotalRecording.reset();
-		for (S32 i = mCurPeriod + 1; i < mCurPeriod + mNumPeriods; i++)
+		U32 num_periods = mRecordingPeriods.size();
+
+		if (num_periods)
+		{
+			for (S32 i = mCurPeriod + 1; i < mCurPeriod + num_periods; i++)
+			{
+				mTotalRecording.appendRecording(mRecordingPeriods[i % num_periods]);
+			}
+		}
+		else
 		{
-			mTotalRecording.appendRecording(mRecordingPeriods[i % mNumPeriods]);
+			for (S32 i = 0; i < mCurPeriod; i++)
+			{
+				mTotalRecording.appendRecording(mRecordingPeriods[i]);
+			}
 		}
 	}
 	mTotalValid = true;
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 751ff298ce..3e7ed2b592 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -249,16 +249,15 @@ namespace LLTrace
 	:	public LLStopWatchControlsMixin<PeriodicRecording>
 	{
 	public:
-		PeriodicRecording(S32 num_periods, EPlayState state = STOPPED);
-		PeriodicRecording(PeriodicRecording& recording);
-		~PeriodicRecording();
+		PeriodicRecording(U32 num_periods, EPlayState state = STOPPED);
 
 		void nextPeriod();
-		S32 getNumPeriods() { return mNumPeriods; }
+		U32 getNumPeriods() { return mRecordingPeriods.size(); }
 
 		Recording& getLastRecordingPeriod()
 		{
-			return mRecordingPeriods[(mCurPeriod + mNumPeriods - 1) % mNumPeriods];
+			U32 num_periods = mRecordingPeriods.size();
+			return mRecordingPeriods[(mCurPeriod + num_periods - 1) % num_periods];
 		}
 
 		const Recording& getLastRecordingPeriod() const
@@ -276,16 +275,18 @@ namespace LLTrace
 			return mRecordingPeriods[mCurPeriod];
 		}
 
-		Recording& getPrevRecordingPeriod(S32 offset)
+		Recording& getPrevRecordingPeriod(U32 offset)
 		{
-			offset = llclamp(offset, 0, mNumPeriods - 1);
-			return mRecordingPeriods[(mCurPeriod + mNumPeriods - offset) % mNumPeriods];
+			U32 num_periods = mRecordingPeriods.size();
+			offset = llclamp(offset, 0u, num_periods - 1);
+			return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
 		}
 
-		const Recording& getPrevRecordingPeriod(S32 offset) const
+		const Recording& getPrevRecordingPeriod(U32 offset) const
 		{
-			offset = llclamp(offset, 0, mNumPeriods - 1);
-			return mRecordingPeriods[(mCurPeriod + mNumPeriods - offset) % mNumPeriods];
+			U32 num_periods = mRecordingPeriods.size();
+			offset = llclamp(offset, 0u, num_periods - 1);
+			return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
 		}
 
 		Recording snapshotCurRecordingPeriod() const
@@ -301,7 +302,8 @@ namespace LLTrace
 		typename T::value_t getPeriodMin(const TraceType<T>& stat) const
 		{
 			typename T::value_t min_val = (std::numeric_limits<typename T::value_t>::max)();
-			for (S32 i = 0; i < mNumPeriods; i++)
+			U32 num_periods = mRecordingPeriods.size();
+			for (S32 i = 0; i < num_periods; i++)
 			{
 				min_val = llmin(min_val, mRecordingPeriods[i].getSum(stat));
 			}
@@ -312,7 +314,8 @@ namespace LLTrace
 		F64 getPeriodMinPerSec(const TraceType<T>& stat) const
 		{
 			F64 min_val = (std::numeric_limits<F64>::max)();
-			for (S32 i = 0; i < mNumPeriods; i++)
+			U32 num_periods = mRecordingPeriods.size();
+			for (S32 i = 0; i < num_periods; i++)
 			{
 				min_val = llmin(min_val, mRecordingPeriods[i].getPerSec(stat));
 			}
@@ -323,7 +326,8 @@ namespace LLTrace
 		typename T::value_t getPeriodMax(const TraceType<T>& stat) const
 		{
 			typename T::value_t max_val = (std::numeric_limits<typename T::value_t>::min)();
-			for (S32 i = 0; i < mNumPeriods; i++)
+			U32 num_periods = mRecordingPeriods.size();
+			for (S32 i = 0; i < num_periods; i++)
 			{
 				max_val = llmax(max_val, mRecordingPeriods[i].getSum(stat));
 			}
@@ -334,7 +338,8 @@ namespace LLTrace
 		F64 getPeriodMaxPerSec(const TraceType<T>& stat) const
 		{
 			F64 max_val = (std::numeric_limits<F64>::min)();
-			for (S32 i = 0; i < mNumPeriods; i++)
+			U32 num_periods = mRecordingPeriods.size();
+			for (S32 i = 0; i < num_periods; i++)
 			{
 				max_val = llmax(max_val, mRecordingPeriods[i].getPerSec(stat));
 			}
@@ -345,14 +350,15 @@ namespace LLTrace
 		typename MeanValueType<TraceType<T> >::type getPeriodMean(const TraceType<T>& stat) const
 		{
 			typename MeanValueType<TraceType<T> >::type mean = 0.0;
-			for (S32 i = 0; i < mNumPeriods; i++)
+			U32 num_periods = mRecordingPeriods.size();
+			for (S32 i = 0; i < num_periods; i++)
 			{
 				if (mRecordingPeriods[i].getDuration() > 0.f)
 				{
 					mean += mRecordingPeriods[i].getSum(stat);
 				}
 			}
-			mean /= mNumPeriods;
+			mean /= num_periods;
 			return mean;
 		}
 
@@ -360,14 +366,15 @@ namespace LLTrace
 		typename MeanValueType<TraceType<T> >::type getPeriodMeanPerSec(const TraceType<T>& stat) const
 		{
 			typename MeanValueType<TraceType<T> >::type mean = 0.0;
-			for (S32 i = 0; i < mNumPeriods; i++)
+			U32 num_periods = mRecordingPeriods.size();
+			for (S32 i = 0; i < num_periods; i++)
 			{
 				if (mRecordingPeriods[i].getDuration() > 0.f)
 				{
 					mean += mRecordingPeriods[i].getPerSec(stat);
 				}
 			}
-			mean /= mNumPeriods;
+			mean /= num_periods;
 			return mean;
 		}
 
@@ -382,11 +389,11 @@ namespace LLTrace
 		/*virtual*/ void splitFrom(PeriodicRecording& other);
 
 	private:
-		Recording*	mRecordingPeriods;
+		std::vector<Recording>	mRecordingPeriods;
 		Recording	mTotalRecording;
 		bool		mTotalValid;
-		S32			mNumPeriods,
-					mCurPeriod;
+		const bool	mAutoResize;
+		S32			mCurPeriod;
 	};
 
 	PeriodicRecording& get_frame_recording();
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 823550db5d..f86f111b90 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -143,7 +143,7 @@ struct LLUnit
 	void operator *= (LLUnit<OTHER_UNIT, OTHER_STORAGE> multiplicand)
 	{
 		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
-		llstatic_assert_template(OTHER_UNIT, 0, "Multiplication of unit types not supported.");
+		llstatic_assert_template(OTHER_UNIT, false, "Multiplication of unit types not supported.");
 	}
 
 	void operator /= (storage_t divisor)
@@ -155,7 +155,7 @@ struct LLUnit
 	void operator /= (LLUnit<OTHER_UNIT, OTHER_STORAGE> divisor)
 	{
 		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
-		llstatic_assert_template(OTHER_UNIT, 0, "Illegal in-place division of unit types.");
+		llstatic_assert_template(OTHER_UNIT, false, "Illegal in-place division of unit types.");
 	}
 
 	template<typename SOURCE_UNITS, typename SOURCE_STORAGE>
@@ -315,7 +315,7 @@ template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typen
 LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator * (LLUnit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnit<UNIT_TYPE2, STORAGE_TYPE2>)
 {
 	// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
-	llstatic_assert_template(STORAGE_TYPE1, 0, "Multiplication of unit types results in new unit type - not supported.");
+	llstatic_assert_template(STORAGE_TYPE1, false, "Multiplication of unit types results in new unit type - not supported.");
 	return LLUnit<UNIT_TYPE1, STORAGE_TYPE1>();
 }
 
@@ -335,7 +335,7 @@ template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typen
 LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator * (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2>)
 {
 	// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
-	llstatic_assert_template(STORAGE_TYPE1, 0, "Multiplication of unit types results in new unit type - not supported.");
+	llstatic_assert_template(STORAGE_TYPE1, false, "Multiplication of unit types results in new unit type - not supported.");
 	return LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1>();
 }
 
-- 
cgit v1.2.3


From 0c63f95b9e1368607126b8d2edbcd91172e61db5 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 21 Mar 2013 17:26:43 -0700
Subject: BUILDFIX fix for gcc build

---
 indra/llcommon/llcriticaldamp.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llcriticaldamp.cpp b/indra/llcommon/llcriticaldamp.cpp
index 59a31bf9df..e47ab35641 100644
--- a/indra/llcommon/llcriticaldamp.cpp
+++ b/indra/llcommon/llcriticaldamp.cpp
@@ -116,5 +116,5 @@ F32 LLSmoothInterpolation::getInterpolant(LLUnit<LLUnits::Seconds, F32> time_con
 //-----------------------------------------------------------------------------
 F32 LLSmoothInterpolation::calcInterpolant(F32 time_constant)
 {
-	return llclamp(1.f - pow(2.f, -sTimeDelta / time_constant), 0.f, 1.f);
+	return llclamp(1.f - powf(2.f, -sTimeDelta / time_constant), 0.f, 1.f);
 }
-- 
cgit v1.2.3


From 368dd542bec7c31e14673b83d3342c35717d2920 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 21 Mar 2013 19:07:48 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 fix for broken pause button on fast timer view

---
 indra/llcommon/llcriticaldamp.cpp   | 2 +-
 indra/llcommon/lltracerecording.cpp | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llcriticaldamp.cpp b/indra/llcommon/llcriticaldamp.cpp
index e47ab35641..2f013fe255 100644
--- a/indra/llcommon/llcriticaldamp.cpp
+++ b/indra/llcommon/llcriticaldamp.cpp
@@ -112,7 +112,7 @@ F32 LLSmoothInterpolation::getInterpolant(LLUnit<LLUnits::Seconds, F32> time_con
 }
 
 //-----------------------------------------------------------------------------
-// getInterpolant()
+// calcInterpolant()
 //-----------------------------------------------------------------------------
 F32 LLSmoothInterpolation::calcInterpolant(F32 time_constant)
 {
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 5d74ea32df..b70d42b082 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -133,6 +133,9 @@ Recording::Recording()
 {}
 
 Recording::Recording( const Recording& other )
+:	RecordingBuffers(other),
+	mElapsedSeconds(other.mElapsedSeconds),
+	mSamplingTimer(other.mSamplingTimer)
 {
 	LLStopWatchControlsMixin<Recording>::setPlayState(other.getPlayState());
 }
-- 
cgit v1.2.3


From cf4798b8f90eebaa62dcb8817538f1e3965b6bc9 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 22 Mar 2013 14:00:09 -0700
Subject: BUILDFIX gcc and vc fixes

---
 indra/llcommon/lltracerecording.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index b70d42b082..f78b7942a7 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -116,12 +116,12 @@ void RecordingBuffers::mergeBuffers( const RecordingBuffers& other)
 
 void RecordingBuffers::resetBuffers(RecordingBuffers* other)
 {
-	mCountsFloat.write()->reset(other ? other->mCountsFloat : NULL);
-	mMeasurementsFloat.write()->reset(other ? other->mMeasurementsFloat : NULL);
-	mCounts.write()->reset(other ? other->mCounts : NULL);
-	mMeasurements.write()->reset(other ? other->mMeasurements : NULL);
-	mStackTimers.write()->reset(other ? other->mStackTimers : NULL);
-	mMemStats.write()->reset(other ? other->mMemStats : NULL);
+	mCountsFloat.write()->reset(other ? other->mCountsFloat : LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<F64> > >());
+	mMeasurementsFloat.write()->reset(other ? other->mMeasurementsFloat : LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > >());
+	mCounts.write()->reset(other ? other->mCounts : LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<S64> > >());
+	mMeasurements.write()->reset(other ? other->mMeasurements : LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<S64> > >());
+	mStackTimers.write()->reset(other ? other->mStackTimers : LLCopyOnWritePointer<AccumulatorBuffer<TimeBlockAccumulator> >());
+	mMemStats.write()->reset(other ? other->mMemStats : LLCopyOnWritePointer<AccumulatorBuffer<MemStatAccumulator> >());
 }
 
 ///////////////////////////////////////////////////////////////////////
-- 
cgit v1.2.3


From 935dce7d6b0a343cef5b13f53d6da5d0c2dc6a73 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 25 Mar 2013 00:18:06 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 fixed some compile errors made label spacing automatic on stat bars fixed
 infinite values coming from stats

---
 indra/llcommon/lltrace.h            | 36 +++++++++++++++++++-----------------
 indra/llcommon/lltracerecording.cpp | 12 ++++++------
 indra/llcommon/lltracerecording.h   | 16 ++++++++--------
 3 files changed, 33 insertions(+), 31 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 71bf1e53e4..a574be02da 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -86,20 +86,17 @@ private:
 
 	AccumulatorBuffer(StaticAllocationMarker m)
 	:	mStorageSize(0),
-		mStorage(NULL),
-		mNextStorageSlot(0)
-	{
-	}
+		mStorage(NULL)
+	{}
 
 public:
 
 	AccumulatorBuffer(const AccumulatorBuffer& other = *getDefaultBuffer())
 	:	mStorageSize(0),
-		mStorage(NULL),
-		mNextStorageSlot(other.mNextStorageSlot)
+		mStorage(NULL)
 	{
 		resize(other.mStorageSize);
-		for (S32 i = 0; i < mNextStorageSlot; i++)
+		for (S32 i = 0; i < sNextStorageSlot; i++)
 		{
 			mStorage[i] = other.mStorage[i];
 		}
@@ -126,9 +123,8 @@ public:
 
 	void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other)
 	{
-		llassert(mNextStorageSlot == other.mNextStorageSlot);
-
-		for (size_t i = 0; i < mNextStorageSlot; i++)
+		llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot);
+		for (size_t i = 0; i < sNextStorageSlot; i++)
 		{
 			mStorage[i].addSamples(other.mStorage[i]);
 		}
@@ -136,7 +132,8 @@ public:
 
 	void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
 	{
-		for (size_t i = 0; i < mNextStorageSlot; i++)
+		llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot);
+		for (size_t i = 0; i < sNextStorageSlot; i++)
 		{
 			mStorage[i] = other.mStorage[i];
 		}
@@ -144,7 +141,8 @@ public:
 
 	void reset(const AccumulatorBuffer<ACCUMULATOR>* other = NULL)
 	{
-		for (size_t i = 0; i < mNextStorageSlot; i++)
+		llassert(mStorageSize >= sNextStorageSlot);
+		for (size_t i = 0; i < sNextStorageSlot; i++)
 		{
 			mStorage[i].reset(other ? &other->mStorage[i] : NULL);
 		}
@@ -172,7 +170,7 @@ public:
 		{
 			llerrs << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << llendl;
 		}
-		size_t next_slot = mNextStorageSlot++;
+		size_t next_slot = sNextStorageSlot++;
 		if (next_slot >= mStorageSize)
 		{
 			resize(mStorageSize + (mStorageSize >> 2));
@@ -208,7 +206,7 @@ public:
 
 	size_t size() const
 	{
-		return mNextStorageSlot;
+		return sNextStorageSlot;
 	}
 
 	static self_t* getDefaultBuffer()
@@ -226,11 +224,15 @@ public:
 	}
 
 private:
-	ACCUMULATOR*								mStorage;
-	size_t										mStorageSize;
-	size_t										mNextStorageSlot;
+	ACCUMULATOR*	mStorage;
+	size_t			mStorageSize;
+	static size_t	sNextStorageSlot;
 };
 
+template<typename ACCUMULATOR> size_t AccumulatorBuffer<ACCUMULATOR>::sNextStorageSlot = 0;
+
+
+
 //TODO: replace with decltype when C++11 is enabled
 template<typename T>
 struct MeanValueType
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index b70d42b082..f78b7942a7 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -116,12 +116,12 @@ void RecordingBuffers::mergeBuffers( const RecordingBuffers& other)
 
 void RecordingBuffers::resetBuffers(RecordingBuffers* other)
 {
-	mCountsFloat.write()->reset(other ? other->mCountsFloat : NULL);
-	mMeasurementsFloat.write()->reset(other ? other->mMeasurementsFloat : NULL);
-	mCounts.write()->reset(other ? other->mCounts : NULL);
-	mMeasurements.write()->reset(other ? other->mMeasurements : NULL);
-	mStackTimers.write()->reset(other ? other->mStackTimers : NULL);
-	mMemStats.write()->reset(other ? other->mMemStats : NULL);
+	mCountsFloat.write()->reset(other ? other->mCountsFloat : LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<F64> > >());
+	mMeasurementsFloat.write()->reset(other ? other->mMeasurementsFloat : LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > >());
+	mCounts.write()->reset(other ? other->mCounts : LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<S64> > >());
+	mMeasurements.write()->reset(other ? other->mMeasurements : LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<S64> > >());
+	mStackTimers.write()->reset(other ? other->mStackTimers : LLCopyOnWritePointer<AccumulatorBuffer<TimeBlockAccumulator> >());
+	mMemStats.write()->reset(other ? other->mMemStats : LLCopyOnWritePointer<AccumulatorBuffer<MemStatAccumulator> >());
 }
 
 ///////////////////////////////////////////////////////////////////////
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 3e7ed2b592..b96d0666e5 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -305,7 +305,7 @@ namespace LLTrace
 			U32 num_periods = mRecordingPeriods.size();
 			for (S32 i = 0; i < num_periods; i++)
 			{
-				min_val = llmin(min_val, mRecordingPeriods[i].getSum(stat));
+				min_val = llmin(min_val, mRecordingPeriods[(mCurPeriod + i) % num_periods].getSum(stat));
 			}
 			return min_val;
 		}
@@ -317,7 +317,7 @@ namespace LLTrace
 			U32 num_periods = mRecordingPeriods.size();
 			for (S32 i = 0; i < num_periods; i++)
 			{
-				min_val = llmin(min_val, mRecordingPeriods[i].getPerSec(stat));
+				min_val = llmin(min_val, mRecordingPeriods[(mCurPeriod + i) % num_periods].getPerSec(stat));
 			}
 			return min_val;
 		}
@@ -329,7 +329,7 @@ namespace LLTrace
 			U32 num_periods = mRecordingPeriods.size();
 			for (S32 i = 0; i < num_periods; i++)
 			{
-				max_val = llmax(max_val, mRecordingPeriods[i].getSum(stat));
+				max_val = llmax(max_val, mRecordingPeriods[(mCurPeriod + i) % num_periods].getSum(stat));
 			}
 			return max_val;
 		}
@@ -339,9 +339,9 @@ namespace LLTrace
 		{
 			F64 max_val = (std::numeric_limits<F64>::min)();
 			U32 num_periods = mRecordingPeriods.size();
-			for (S32 i = 0; i < num_periods; i++)
+			for (S32 i = 1; i < num_periods; i++)
 			{
-				max_val = llmax(max_val, mRecordingPeriods[i].getPerSec(stat));
+				max_val = llmax(max_val, mRecordingPeriods[(mCurPeriod + i) % num_periods].getPerSec(stat));
 			}
 			return max_val;
 		}
@@ -353,9 +353,9 @@ namespace LLTrace
 			U32 num_periods = mRecordingPeriods.size();
 			for (S32 i = 0; i < num_periods; i++)
 			{
-				if (mRecordingPeriods[i].getDuration() > 0.f)
+				if (mRecordingPeriods[(mCurPeriod + i) % num_periods].getDuration() > 0.f)
 				{
-					mean += mRecordingPeriods[i].getSum(stat);
+					mean += mRecordingPeriods[(mCurPeriod + i) % num_periods].getSum(stat);
 				}
 			}
 			mean /= num_periods;
@@ -371,7 +371,7 @@ namespace LLTrace
 			{
 				if (mRecordingPeriods[i].getDuration() > 0.f)
 				{
-					mean += mRecordingPeriods[i].getPerSec(stat);
+					mean += mRecordingPeriods[(mCurPeriod + i) % num_periods].getPerSec(stat);
 				}
 			}
 			mean /= num_periods;
-- 
cgit v1.2.3


From cd46f3d08cef6f43c29447e36c920d10ec184a18 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 25 Mar 2013 20:21:04 -0700
Subject: BUILDFIX gcc fix

---
 indra/llcommon/llfasttimer.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index fbffe133f1..b40aec4886 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -185,7 +185,7 @@ void TimeBlock::processTimes()
 	U64 cur_time = getCPUClockCount64();
 
 	// set up initial tree
-	for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(); 
+	for (LLInstanceTracker<TimeBlock>::instance_iter begin_it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(), it = begin_it; 
 		it != end_it; 
 		++it)
 	{
-- 
cgit v1.2.3


From 07ca6fce7c9cffe1b8f215f25bb826fedf57a5b7 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 10 Apr 2013 21:51:56 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 removed PeriodicRecording::getTotalRecording as it was showing up at the top
 on the profiler renamed getPrevRecordingPeriod, etc. to getPrevRecording

---
 indra/llcommon/llfasttimer.cpp      | 13 +++++----
 indra/llcommon/lltracerecording.cpp | 55 +++++++++----------------------------
 indra/llcommon/lltracerecording.h   | 21 ++++++--------
 3 files changed, 30 insertions(+), 59 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index fbffe133f1..a7adcc6729 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -176,11 +176,14 @@ TimeBlockTreeNode& TimeBlock::getTreeNode() const
 	TimeBlockTreeNode* nodep = LLTrace::get_thread_recorder()->getTimeBlockTreeNode(getIndex());
 	llassert(nodep);
 	return *nodep;
-	}
+}
+
+static LLFastTimer::DeclareTimer FTM_PROCESS_TIMES("Process FastTimer Times");
 
 //static
 void TimeBlock::processTimes()
 {
+	LLFastTimer _(FTM_PROCESS_TIMES);
 	get_clock_count(); // good place to calculate clock frequency
 	U64 cur_time = getCPUClockCount64();
 
@@ -329,12 +332,12 @@ void TimeBlock::logStats()
 			{
 				TimeBlock& timer = *it;
 				LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
-				sd[timer.getName()]["Time"] = (LLSD::Real) (frame_recording.getLastRecordingPeriod().getSum(timer).value());	
-				sd[timer.getName()]["Calls"] = (LLSD::Integer) (frame_recording.getLastRecordingPeriod().getSum(timer.callCount()));
+				sd[timer.getName()]["Time"] = (LLSD::Real) (frame_recording.getLastRecording().getSum(timer).value());	
+				sd[timer.getName()]["Calls"] = (LLSD::Integer) (frame_recording.getLastRecording().getSum(timer.callCount()));
 				
 				// computing total time here because getting the root timer's getCountHistory
 				// doesn't work correctly on the first frame
-				total_time += frame_recording.getLastRecordingPeriod().getSum(timer);
+				total_time += frame_recording.getLastRecording().getSum(timer);
 			}
 		}
 
@@ -353,7 +356,7 @@ void TimeBlock::logStats()
 void TimeBlock::dumpCurTimes()
 {
 	LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
-	LLTrace::Recording& last_frame_recording = frame_recording.getLastRecordingPeriod();
+	LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording();
 
 	// walk over timers in depth order and output timings
 	for(timer_tree_dfs_iterator_t it = begin_timer_tree(TimeBlock::getRootTimeBlock());
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index f78b7942a7..21156b4d61 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -360,8 +360,7 @@ U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<S64> >& st
 
 PeriodicRecording::PeriodicRecording( U32 num_periods, EPlayState state) 
 :	mAutoResize(num_periods == 0),
-	mCurPeriod(0),
-	mTotalValid(false)
+	mCurPeriod(0)
 {
 	if (num_periods)
 	{
@@ -373,7 +372,7 @@ PeriodicRecording::PeriodicRecording( U32 num_periods, EPlayState state)
 void PeriodicRecording::nextPeriod()
 {
 	EPlayState play_state = getPlayState();
-	Recording& old_recording = getCurRecordingPeriod();
+	Recording& old_recording = getCurRecording();
 	if (mAutoResize)
 	{
 		mRecordingPeriods.push_back(Recording());
@@ -382,87 +381,59 @@ void PeriodicRecording::nextPeriod()
 	mCurPeriod = (num_periods > 0) 
 				? (mCurPeriod + 1) % num_periods 
 				: mCurPeriod + 1;
-	old_recording.splitTo(getCurRecordingPeriod());
+	old_recording.splitTo(getCurRecording());
 
 	switch(play_state)
 	{
 	case STOPPED:
-		getCurRecordingPeriod().stop();
+		getCurRecording().stop();
 		break;
 	case PAUSED:
-		getCurRecordingPeriod().pause();
+		getCurRecording().pause();
 		break;
 	case STARTED:
 		break;
 	}
-	// new period, need to recalculate total
-	mTotalValid = false;
-}
-
-Recording& PeriodicRecording::getTotalRecording()
-{
-	if (!mTotalValid)
-	{
-		mTotalRecording.reset();
-		U32 num_periods = mRecordingPeriods.size();
-
-		if (num_periods)
-		{
-			for (S32 i = mCurPeriod + 1; i < mCurPeriod + num_periods; i++)
-			{
-				mTotalRecording.appendRecording(mRecordingPeriods[i % num_periods]);
-			}
-		}
-		else
-		{
-			for (S32 i = 0; i < mCurPeriod; i++)
-			{
-				mTotalRecording.appendRecording(mRecordingPeriods[i]);
-			}
-		}
-	}
-	mTotalValid = true;
-	return mTotalRecording;
 }
 
 void PeriodicRecording::start()
 {
-	getCurRecordingPeriod().start();
+	getCurRecording().start();
 }
 
 void PeriodicRecording::stop()
 {
-	getCurRecordingPeriod().stop();
+	getCurRecording().stop();
 }
 
 void PeriodicRecording::pause()
 {
-	getCurRecordingPeriod().pause();
+	getCurRecording().pause();
 }
 
 void PeriodicRecording::resume()
 {
-	getCurRecordingPeriod().resume();
+	getCurRecording().resume();
 }
 
 void PeriodicRecording::restart()
 {
-	getCurRecordingPeriod().restart();
+	getCurRecording().restart();
 }
 
 void PeriodicRecording::reset()
 {
-	getCurRecordingPeriod().reset();
+	getCurRecording().reset();
 }
 
 void PeriodicRecording::splitTo(PeriodicRecording& other)
 {
-	getCurRecordingPeriod().splitTo(other.getCurRecordingPeriod());
+	getCurRecording().splitTo(other.getCurRecording());
 }
 
 void PeriodicRecording::splitFrom(PeriodicRecording& other)
 {
-	getCurRecordingPeriod().splitFrom(other.getCurRecordingPeriod());
+	getCurRecording().splitFrom(other.getCurRecording());
 }
 
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index b96d0666e5..0a3e9e5a0b 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -254,50 +254,48 @@ namespace LLTrace
 		void nextPeriod();
 		U32 getNumPeriods() { return mRecordingPeriods.size(); }
 
-		Recording& getLastRecordingPeriod()
+		Recording& getLastRecording()
 		{
 			U32 num_periods = mRecordingPeriods.size();
 			return mRecordingPeriods[(mCurPeriod + num_periods - 1) % num_periods];
 		}
 
-		const Recording& getLastRecordingPeriod() const
+		const Recording& getLastRecording() const
 		{
-			return getPrevRecordingPeriod(1);
+			return getPrevRecording(1);
 		}
 
-		Recording& getCurRecordingPeriod()
+		Recording& getCurRecording()
 		{
 			return mRecordingPeriods[mCurPeriod];
 		}
 
-		const Recording& getCurRecordingPeriod() const
+		const Recording& getCurRecording() const
 		{
 			return mRecordingPeriods[mCurPeriod];
 		}
 
-		Recording& getPrevRecordingPeriod(U32 offset)
+		Recording& getPrevRecording(U32 offset)
 		{
 			U32 num_periods = mRecordingPeriods.size();
 			offset = llclamp(offset, 0u, num_periods - 1);
 			return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
 		}
 
-		const Recording& getPrevRecordingPeriod(U32 offset) const
+		const Recording& getPrevRecording(U32 offset) const
 		{
 			U32 num_periods = mRecordingPeriods.size();
 			offset = llclamp(offset, 0u, num_periods - 1);
 			return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
 		}
 
-		Recording snapshotCurRecordingPeriod() const
+		Recording snapshotCurRecording() const
 		{
-			Recording recording_copy(getCurRecordingPeriod());
+			Recording recording_copy(getCurRecording());
 			recording_copy.stop();
 			return recording_copy;
 		}
 
-		Recording& getTotalRecording();
-
 		template <typename T>
 		typename T::value_t getPeriodMin(const TraceType<T>& stat) const
 		{
@@ -391,7 +389,6 @@ namespace LLTrace
 	private:
 		std::vector<Recording>	mRecordingPeriods;
 		Recording	mTotalRecording;
-		bool		mTotalValid;
 		const bool	mAutoResize;
 		S32			mCurPeriod;
 	};
-- 
cgit v1.2.3


From 49933aadb1b7044e947575bc377b34826e94fe99 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 11 Apr 2013 06:38:03 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 removed MeanValueType<T>

---
 indra/llcommon/lltrace.h          | 31 +------------------------------
 indra/llcommon/lltracerecording.h |  8 ++++----
 2 files changed, 5 insertions(+), 34 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index a574be02da..376248c87a 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -231,15 +231,6 @@ private:
 
 template<typename ACCUMULATOR> size_t AccumulatorBuffer<ACCUMULATOR>::sNextStorageSlot = 0;
 
-
-
-//TODO: replace with decltype when C++11 is enabled
-template<typename T>
-struct MeanValueType
-{
-	typedef F64 type;
-};
-
 template<typename ACCUMULATOR>
 class TraceType 
 :	 public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
@@ -382,6 +373,7 @@ private:
 	U32	mNumSamples;
 };
 
+
 template<typename T>
 class CountAccumulator
 {
@@ -457,13 +449,6 @@ public:
 
 };
 
-
-template<>
-struct MeanValueType<TraceType<TimeBlockAccumulator> >
-{
-	typedef LLUnit<LLUnits::Seconds, F64> type;
-};
-
 template<>
 class TraceType<TimeBlockAccumulator::CallCountAspect>
 :	public TraceType<TimeBlockAccumulator>
@@ -475,13 +460,6 @@ public:
 	{}
 };
 
-template<>
-struct MeanValueType<TraceType<TimeBlockAccumulator::CallCountAspect> >
-{
-	typedef F64 type;
-};
-
-
 template<>
 class TraceType<TimeBlockAccumulator::SelfTimeAspect>
 	:	public TraceType<TimeBlockAccumulator>
@@ -493,13 +471,6 @@ public:
 	{}
 };
 
-template<>
-struct MeanValueType<TraceType<TimeBlockAccumulator::SelfTimeAspect> >
-{
-	typedef LLUnit<LLUnits::Seconds, F64> type;
-};
-
-
 class TimeBlock;
 class TimeBlockTreeNode
 {
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 0a3e9e5a0b..9ebcbdd8ce 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -345,9 +345,9 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename MeanValueType<TraceType<T> >::type getPeriodMean(const TraceType<T>& stat) const
+		typename T::value_t getPeriodMean(const TraceType<T>& stat) const
 		{
-			typename MeanValueType<TraceType<T> >::type mean = 0.0;
+			typename T::value_t mean = 0.0;
 			U32 num_periods = mRecordingPeriods.size();
 			for (S32 i = 0; i < num_periods; i++)
 			{
@@ -361,9 +361,9 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename MeanValueType<TraceType<T> >::type getPeriodMeanPerSec(const TraceType<T>& stat) const
+		typename T::value_t getPeriodMeanPerSec(const TraceType<T>& stat) const
 		{
-			typename MeanValueType<TraceType<T> >::type mean = 0.0;
+			typename T::value_t mean = 0.0;
 			U32 num_periods = mRecordingPeriods.size();
 			for (S32 i = 0; i < num_periods; i++)
 			{
-- 
cgit v1.2.3


From ae028e79872f166db8e514ca3b442c7807d6ebdb Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 11 Apr 2013 19:08:57 -0700
Subject: removed unused data structures

---
 indra/llcommon/CMakeLists.txt  |    5 -
 indra/llcommon/llptrskiplist.h |  724 -----------------------
 indra/llcommon/llptrskipmap.h  | 1239 ----------------------------------------
 indra/llcommon/llskiplist.h    |  517 -----------------
 indra/llcommon/llskipmap.h     | 1020 ---------------------------------
 indra/llcommon/lluuidhashmap.h |  583 -------------------
 6 files changed, 4088 deletions(-)
 delete mode 100644 indra/llcommon/llptrskiplist.h
 delete mode 100644 indra/llcommon/llptrskipmap.h
 delete mode 100644 indra/llcommon/llskiplist.h
 delete mode 100644 indra/llcommon/llskipmap.h
 delete mode 100644 indra/llcommon/lluuidhashmap.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index f8f1c010f7..5117224ddb 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -212,8 +212,6 @@ set(llcommon_HEADER_FILES
     llpriqueuemap.h
     llprocess.h
     llprocessor.h
-    llptrskiplist.h
-    llptrskipmap.h
     llptrto.h
     llqueuedthread.h
     llrand.h
@@ -230,8 +228,6 @@ set(llcommon_HEADER_FILES
     llsecondlifeurls.h
     llsimplehash.h
     llsingleton.h
-    llskiplist.h
-    llskipmap.h
     llsortedvector.h
     llstack.h
     llstacktrace.h
@@ -255,7 +251,6 @@ set(llcommon_HEADER_FILES
     llunit.h
     lluri.h
     lluuid.h
-    lluuidhashmap.h
     llversionserver.h
     llversionviewer.h
     llwin32headers.h
diff --git a/indra/llcommon/llptrskiplist.h b/indra/llcommon/llptrskiplist.h
deleted file mode 100644
index 67c7cde352..0000000000
--- a/indra/llcommon/llptrskiplist.h
+++ /dev/null
@@ -1,724 +0,0 @@
-/** 
- * @file llptrskiplist.h
- * @brief Skip list implementation.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLPTRSKIPLIST_H
-#define LL_LLPTRSKIPLIST_H
-
-#include "llerror.h"
-#include "llrand.h"
-//#include "vmath.h"
-#include "llrand.h"
-
-/////////////////////////////////////////////
-//
-//	LLPtrSkipList implementation - skip list for pointers to objects
-//
-
-template <class DATA_TYPE, S32 BINARY_DEPTH = 8>
-class LLPtrSkipList
-{
-public:
-	friend class LLPtrSkipNode;
-
-	// basic constructor
-	LLPtrSkipList();
-	// basic constructor including sorter
-	LLPtrSkipList(BOOL	(*insert_first)(DATA_TYPE *first, DATA_TYPE *second), 
-				  BOOL	(*equals)(DATA_TYPE *first, DATA_TYPE *second));
-	~LLPtrSkipList();
-
-	inline void setInsertFirst(BOOL (*insert_first)(const DATA_TYPE *first, const DATA_TYPE *second));
-	inline void setEquals(BOOL (*equals)(const DATA_TYPE *first, const DATA_TYPE *second));
-
-	inline BOOL addData(DATA_TYPE *data);
-
-	inline BOOL checkData(const DATA_TYPE *data);
-
-	inline S32 getLength();	// returns number of items in the list - NOT constant time!
-
-	inline BOOL removeData(const DATA_TYPE *data);
-
-	// note that b_sort is ignored
-	inline BOOL moveData(const DATA_TYPE *data, LLPtrSkipList *newlist, BOOL b_sort);
-
-	inline BOOL moveCurrentData(LLPtrSkipList *newlist, BOOL b_sort);
-
-	// resort -- use when the value we're sorting by changes
-	/* IW 12/6/02 - This doesn't work!
-	   Instead, remove the data BEFORE you change it
-	   Then re-insert it after you change it
-	BOOL resortData(DATA_TYPE *data)
-	*/
-
-	// remove all nodes from the list but do not delete data
-	inline void removeAllNodes();
-
-	inline BOOL deleteData(const DATA_TYPE *data);
-
-	// remove all nodes from the list and delete data
-	inline void deleteAllData();
-
-	// place mCurrentp on first node
-	inline void resetList();
-
-	// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-	inline DATA_TYPE	*getCurrentData();
-
-	// same as getCurrentData() but a more intuitive name for the operation
-	inline DATA_TYPE	*getNextData();
-
-	// remove the Node at mCurentOperatingp
-	// leave mCurrentp and mCurentOperatingp on the next entry
-	inline void removeCurrentData();
-
-	// delete the Node at mCurentOperatingp
-	// leave mCurrentp and mCurentOperatingp on the next entry
-	inline void deleteCurrentData();
-
-	// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-	inline DATA_TYPE	*getFirstData();
-
-	// TRUE if nodes are not in sorted order
-	inline BOOL corrupt();
-
-protected:
-	class LLPtrSkipNode
-	{
-	public:
-		LLPtrSkipNode()
-		:	mData(NULL)
-		{
-			S32 i;
-			for (i = 0; i < BINARY_DEPTH; i++)
-			{
-				mForward[i] = NULL;
-			}
-		}
-
-		LLPtrSkipNode(DATA_TYPE *data)
-			: mData(data)
-		{
-			S32 i;
-			for (i = 0; i < BINARY_DEPTH; i++)
-			{
-				mForward[i] = NULL;
-			}
-		}
-
-		~LLPtrSkipNode()
-		{
-			if (mData)
-			{
-				llerror("Attempting to call LLPtrSkipNode destructor with a non-null mDatap!", 1);
-			}
-		}
-
-		// delete associated data and NULLs out pointer
-		void deleteData()
-		{
-			delete mData;
-			mData = NULL;
-		}
-
-		// NULLs out pointer
-		void removeData()
-		{
-			mData = NULL;
-		}
-
-		DATA_TYPE					*mData;
-		LLPtrSkipNode				*mForward[BINARY_DEPTH];
-	};
-
-	static BOOL					defaultEquals(const DATA_TYPE *first, const DATA_TYPE *second)
-	{
-		return first == second;
-	}
-
-
-	LLPtrSkipNode				mHead;
-	LLPtrSkipNode				*mUpdate[BINARY_DEPTH];
-	LLPtrSkipNode				*mCurrentp;
-	LLPtrSkipNode				*mCurrentOperatingp;
-	S32							mLevel;
-	BOOL						(*mInsertFirst)(const DATA_TYPE *first, const DATA_TYPE *second);
-	BOOL						(*mEquals)(const DATA_TYPE *first, const DATA_TYPE *second);
-};
-
-
-// basic constructor
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::LLPtrSkipList()
-	: mInsertFirst(NULL), mEquals(defaultEquals)
-{
-	if (BINARY_DEPTH < 2)
-	{
-		llerrs << "Trying to create skip list with too little depth, "
-			"must be 2 or greater" << llendl;
-	}
-	S32 i;
-	for (i = 0; i < BINARY_DEPTH; i++)
-	{
-		mUpdate[i] = NULL;
-	}
-	mLevel = 1;
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-// basic constructor including sorter
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::LLPtrSkipList(BOOL	(*insert_first)(DATA_TYPE *first, DATA_TYPE *second), 
-													  BOOL	(*equals)(DATA_TYPE *first, DATA_TYPE *second)) 
-	:mInsertFirst(insert_first), mEquals(equals)
-{
-	if (BINARY_DEPTH < 2)
-	{
-		llerrs << "Trying to create skip list with too little depth, "
-			"must be 2 or greater" << llendl;
-	}
-	mLevel = 1;
-	S32 i;
-	for (i = 0; i < BINARY_DEPTH; i++)
-	{
-		mHead.mForward[i] = NULL;
-		mUpdate[i] = NULL;
-	}
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::~LLPtrSkipList()
-{
-	removeAllNodes();
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::setInsertFirst(BOOL (*insert_first)(const DATA_TYPE *first, const DATA_TYPE *second))
-{
-	mInsertFirst = insert_first;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::setEquals(BOOL (*equals)(const DATA_TYPE *first, const DATA_TYPE *second))
-{
-	mEquals = equals;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::addData(DATA_TYPE *data)
-{
-	S32				level;
-	LLPtrSkipNode	*current = &mHead;
-	LLPtrSkipNode	*temp;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mData, data)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mData < data))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-	// now add the new node
-	S32 newlevel;
-	for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
-	{
-		if (ll_frand() < 0.5f)
-			break;
-	}
-
-	LLPtrSkipNode *snode = new LLPtrSkipNode(data);
-
-	if (newlevel > mLevel)
-	{
-		mHead.mForward[mLevel] = NULL;
-		mUpdate[mLevel] = &mHead;
-		mLevel = newlevel;
-	}
-
-	for (level = 0; level < newlevel; level++)
-	{
-		snode->mForward[level] = mUpdate[level]->mForward[level];
-		mUpdate[level]->mForward[level] = snode;
-	}
-	return TRUE;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::checkData(const DATA_TYPE *data)
-{
-	S32			level;
-	LLPtrSkipNode	*current = &mHead;
-	LLPtrSkipNode	*temp;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mData, data)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mData < data))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-	
-	if (current)
-	{
-		return mEquals(current->mData, data);
-	}
-	else
-	{
-		return FALSE;
-	}
-}
-
-// returns number of items in the list
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline S32 LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getLength()
-{
-	U32	length = 0;
-	for (LLPtrSkipNode* temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0])
-	{
-		length++;
-	}
-	return length;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::removeData(const DATA_TYPE *data)
-{
-	S32			level;
-	LLPtrSkipNode	*current = &mHead;
-	LLPtrSkipNode	*temp;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mData, data)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mData < data))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-	if (!current)
-	{
-		// empty list or beyond the end!
-		return FALSE;
-	}
-
-	// is this the one we want?
-	if (!mEquals(current->mData, data))
-	{
-		// nope!
-			return FALSE;
-	}
-	else
-	{
-		// yes it is!  change pointers as required
-		for (level = 0; level < mLevel; level++)
-		{
-			if (mUpdate[level]->mForward[level] != current)
-			{
-				// cool, we've fixed all the pointers!
-				break;
-			}
-			mUpdate[level]->mForward[level] = current->mForward[level];
-		}
-
-		// clean up cuurent
-		current->removeData();
-		delete current;
-
-		// clean up mHead
-		while (  (mLevel > 1)
-			   &&(!mHead.mForward[mLevel - 1]))
-		{
-			mLevel--;
-		}
-	}
-	return TRUE;
-}
-
-// note that b_sort is ignored
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::moveData(const DATA_TYPE *data, LLPtrSkipList *newlist, BOOL b_sort)
-{
-	BOOL removed = removeData(data);
-	BOOL added = newlist->addData(data);
-	return removed && added;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::moveCurrentData(LLPtrSkipList *newlist, BOOL b_sort)
-{
-	if (mCurrentOperatingp)
-	{
-		mCurrentp = mCurrentOperatingp->mForward[0];	
-		BOOL removed = removeData(mCurrentOperatingp);
-		BOOL added = newlist->addData(mCurrentOperatingp);
-		mCurrentOperatingp = mCurrentp;
-		return removed && added;
-	}
-	return FALSE;
-}
-
-// resort -- use when the value we're sorting by changes
-/* IW 12/6/02 - This doesn't work!
-   Instead, remove the data BEFORE you change it
-   Then re-insert it after you change it
-BOOL resortData(DATA_TYPE *data)
-{
-	removeData(data);
-	addData(data);
-}
-*/
-
-// remove all nodes from the list but do not delete data
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::removeAllNodes()
-{
-	LLPtrSkipNode *temp;
-	// reset mCurrentp
-	mCurrentp = *(mHead.mForward);
-
-	while (mCurrentp)
-	{
-		temp = mCurrentp->mForward[0];
-		mCurrentp->removeData();
-		delete mCurrentp;
-		mCurrentp = temp;
-	}
-
-	S32 i;
-	for (i = 0; i < BINARY_DEPTH; i++)
-	{
-		mHead.mForward[i] = NULL;
-		mUpdate[i] = NULL;
-	}
-
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::deleteData(const DATA_TYPE *data)
-{
-	S32			level;
-	LLPtrSkipNode	*current = &mHead;
-	LLPtrSkipNode	*temp;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mData, data)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mData < data))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-	if (!current)
-	{
-		// empty list or beyond the end!
-		return FALSE;
-	}
-
-	// is this the one we want?
-	if (!mEquals(current->mData, data))
-	{
-		// nope!
-		return FALSE;
-	}
-	else
-	{
-		// do we need to fix current or currentop?
-		if (current == mCurrentp)
-		{
-			mCurrentp = current->mForward[0];
-		}
-
-		if (current == mCurrentOperatingp)
-		{
-			mCurrentOperatingp = current->mForward[0];
-		}
-
-		// yes it is!  change pointers as required
-		for (level = 0; level < mLevel; level++)
-		{
-			if (mUpdate[level]->mForward[level] != current)
-			{
-				// cool, we've fixed all the pointers!
-				break;
-			}
-			mUpdate[level]->mForward[level] = current->mForward[level];
-		}
-
-		// clean up cuurent
-		current->deleteData();
-		delete current;
-
-		// clean up mHead
-		while (  (mLevel > 1)
-			   &&(!mHead.mForward[mLevel - 1]))
-		{
-			mLevel--;
-		}
-	}
-	return TRUE;
-}
-
-// remove all nodes from the list and delete data
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::deleteAllData()
-{
-	LLPtrSkipNode *temp;
-	// reset mCurrentp
-	mCurrentp = *(mHead.mForward);
-
-	while (mCurrentp)
-	{
-		temp = mCurrentp->mForward[0];
-		mCurrentp->deleteData();
-		delete mCurrentp;
-		mCurrentp = temp;
-	}
-
-	S32 i;
-	for (i = 0; i < BINARY_DEPTH; i++)
-	{
-		mHead.mForward[i] = NULL;
-		mUpdate[i] = NULL;
-	}
-
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-// place mCurrentp on first node
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::resetList()
-{
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline DATA_TYPE *LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getCurrentData()
-{
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = *mCurrentp->mForward;
-		return mCurrentOperatingp->mData;
-	}
-	else
-	{
-		//return NULL;		// causes compile warning
-		return 0; 			// equivalent, but no warning
-	}
-}
-
-// same as getCurrentData() but a more intuitive name for the operation
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline DATA_TYPE *LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getNextData()
-{
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = *mCurrentp->mForward;
-		return mCurrentOperatingp->mData;
-	}
-	else
-	{
-		//return NULL;		// causes compile warning
-		return 0; 			// equivalent, but no warning
-	}
-}
-
-// remove the Node at mCurentOperatingp
-// leave mCurrentp and mCurentOperatingp on the next entry
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::removeCurrentData()
-{
-	if (mCurrentOperatingp)
-	{
-		removeData(mCurrentOperatingp->mData);
-	}
-}
-
-// delete the Node at mCurentOperatingp
-// leave mCurrentp and mCurentOperatingp on the next entry
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::deleteCurrentData()
-{
-	if (mCurrentOperatingp)
-	{
-		deleteData(mCurrentOperatingp->mData);
-	}
-}
-
-// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline DATA_TYPE *LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getFirstData()
-{
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mForward[0];
-		return mCurrentOperatingp->mData;
-	}
-	else
-	{
-		//return NULL;		// causes compile warning
-		return 0; 			// equivalent, but no warning
-	}
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH> 
-inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::corrupt()
-{
-	LLPtrSkipNode *previous = mHead.mForward[0];
-
-	// Empty lists are not corrupt.
-	if (!previous) return FALSE;
-
-	LLPtrSkipNode *current = previous->mForward[0];
-	while(current)
-	{
-		if (!mInsertFirst(previous->mData, current->mData))
-		{
-			// prev shouldn't be in front of cur!
-			return TRUE;
-		}
-		current = current->mForward[0];
-	}
-	return FALSE;
-}
-
-#endif
diff --git a/indra/llcommon/llptrskipmap.h b/indra/llcommon/llptrskipmap.h
deleted file mode 100644
index 94bc71ec55..0000000000
--- a/indra/llcommon/llptrskipmap.h
+++ /dev/null
@@ -1,1239 +0,0 @@
-/** 
- * @file llptrskipmap.h
- * @brief Just like a LLSkipMap, but since it's pointers, you can call
- * deleteAllData
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-#ifndef LL_LLPTRSKIPMAP_H
-#define LL_LLPTRSKIPMAP_H
-
-#include "llerror.h"
-#include "llrand.h"
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH = 8> 
-class LLPtrSkipMapNode
-{
-public:
-	LLPtrSkipMapNode()
-	{
-		S32 i;
-		for (i = 0; i < BINARY_DEPTH; i++)
-		{
-			mForward[i] = NULL;
-		}
-
-		U8  *zero = (U8 *)&mIndex;
-
-		for (i = 0; i < (S32)sizeof(INDEX_T); i++)
-		{
-			*(zero + i) = 0;
-		}
-
-		zero = (U8 *)&mData;
-
-		for (i = 0; i < (S32)sizeof(DATA_T); i++)
-		{
-			*(zero + i) = 0;
-		}
-	}
-
-	LLPtrSkipMapNode(const INDEX_T &index)
-	:	mIndex(index)
-	{
-
-		S32 i;
-		for (i = 0; i < BINARY_DEPTH; i++)
-		{
-			mForward[i] = NULL;
-		}
-
-		U8 *zero = (U8 *)&mData;
-
-		for (i = 0; i < (S32)sizeof(DATA_T); i++)
-		{
-			*(zero + i) = 0;
-		}
-	}
-
-	LLPtrSkipMapNode(const INDEX_T &index, DATA_T datap)
-	:	mIndex(index)
-	{
-
-		S32 i;
-		for (i = 0; i < BINARY_DEPTH; i++)
-		{
-			mForward[i] = NULL;
-		}
-
-		mData = datap;
-	}
-
-	~LLPtrSkipMapNode()
-	{
-	}
-
-	// delete associated data and NULLs out pointer
-	void deleteData()
-	{
-		delete mData;
-		mData = 0;
-	}
-
-	// NULLs out pointer
-	void removeData()
-	{
-		mData = 0;
-	}
-
-	INDEX_T					mIndex;
-	DATA_T					mData;
-	LLPtrSkipMapNode				*mForward[BINARY_DEPTH];
-
-private:
-	// Disallow copying of LLPtrSkipMapNodes by not implementing these methods.
-	LLPtrSkipMapNode(const LLPtrSkipMapNode &);
-	LLPtrSkipMapNode &operator=(const LLPtrSkipMapNode &rhs);
-};
-
-//---------------------------------------------------------------------------
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH = 8> 
-class LLPtrSkipMap
-{
-public:
-	typedef BOOL (*compare)(const DATA_T& first, const DATA_T& second);
-	typedef compare insert_func;
-	typedef compare equals_func;
-
-	void init();
-
-	// basic constructor
-	LLPtrSkipMap();
-
-	// basic constructor including sorter
-	LLPtrSkipMap(insert_func insert_first, equals_func equals);
-
-	~LLPtrSkipMap();
-
-	void setInsertFirst(insert_func insert_first);
-	void setEquals(equals_func equals);
-
-	DATA_T &addData(const INDEX_T &index, DATA_T datap);
-	DATA_T &addData(const INDEX_T &index);
-	DATA_T &getData(const INDEX_T &index);
-	DATA_T &operator[](const INDEX_T &index);
-
-	// If index present, returns data.
-	// If index not present, adds <index,NULL> and returns NULL.
-	DATA_T &getData(const INDEX_T &index, BOOL &b_new_entry);
-
-	// returns data entry before and after index
-	BOOL getInterval(const INDEX_T &index, INDEX_T &index_before, INDEX_T &index_after,
-		DATA_T &data_before, DATA_T &data_after	);
-
-	// Returns TRUE if data present in map.
-	BOOL checkData(const INDEX_T &index);
-
-	// Returns TRUE if key is present in map. This is useful if you
-	// are potentially storing NULL pointers in the map
-	BOOL checkKey(const INDEX_T &index);
-
-	// If there, returns the data.
-	// If not, returns NULL.
-	// Never adds entries to the map.
-	DATA_T getIfThere(const INDEX_T &index);
-
-	INDEX_T reverseLookup(const DATA_T datap);
-
-	// returns number of items in the list
-	S32 getLength(); // WARNING!  getLength is O(n), not O(1)!
-
-	BOOL removeData(const INDEX_T &index);
-	BOOL deleteData(const INDEX_T &index);
-
-	// remove all nodes from the list but do not delete data
-	void removeAllData();
-	void deleteAllData();
-
-	// place mCurrentp on first node
-	void resetList();
-
-	// return the data currently pointed to
-	DATA_T	getCurrentDataWithoutIncrement();
-
-	// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-	DATA_T	getCurrentData();
-
-	// same as getCurrentData() but a more intuitive name for the operation
-	DATA_T	getNextData();
-
-	INDEX_T	getNextKey();
-
-	// return the key currently pointed to
-	INDEX_T	getCurrentKeyWithoutIncrement();
-
-	// remove the Node at mCurentOperatingp
-	// leave mCurrentp and mCurentOperatingp on the next entry
-	void removeCurrentData();
-
-	void deleteCurrentData();
-
-	// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-	DATA_T	getFirstData();
-
-	INDEX_T	getFirstKey();
-
-	static BOOL	defaultEquals(const INDEX_T &first, const INDEX_T &second)
-	{
-		return first == second;
-	}
-
-private:
-	// don't generate implicit copy constructor or copy assignment
-	LLPtrSkipMap(const LLPtrSkipMap &);
-	LLPtrSkipMap &operator=(const LLPtrSkipMap &);
-
-private:
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	mHead;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*mUpdate[BINARY_DEPTH];
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*mCurrentp;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*mCurrentOperatingp;
-	S32							mLevel;
-	BOOL						(*mInsertFirst)(const INDEX_T &first, const INDEX_T &second);
-	BOOL						(*mEquals)(const INDEX_T &first, const INDEX_T &second);
-	S32							mNumberOfSteps;
-};
-
-//////////////////////////////////////////////////
-//
-// LLPtrSkipMap implementation
-//
-//
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::LLPtrSkipMap()
-	:	mInsertFirst(NULL),
-		mEquals(defaultEquals),
-		mNumberOfSteps(0)
-{
-	if (BINARY_DEPTH < 2)
-	{
-		llerrs << "Trying to create skip list with too little depth, "
-			"must be 2 or greater" << llendl;
-	}
-	S32 i;
-	for (i = 0; i < BINARY_DEPTH; i++)
-	{
-		mUpdate[i] = NULL;
-	}
-	mLevel = 1;
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::LLPtrSkipMap(insert_func insert_first, 
-																 equals_func equals) 
-:	mInsertFirst(insert_first),
-	mEquals(equals),
-	mNumberOfSteps(0)
-{
-	if (BINARY_DEPTH < 2)
-	{
-		llerrs << "Trying to create skip list with too little depth, "
-			"must be 2 or greater" << llendl;
-	}
-	mLevel = 1;
-	S32 i;
-	for (i = 0; i < BINARY_DEPTH; i++)
-	{
-		mHead.mForward[i] = NULL;
-		mUpdate[i] = NULL;
-	}
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::~LLPtrSkipMap()
-{
-	removeAllData();
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::setInsertFirst(insert_func insert_first)
-{
-	mInsertFirst = insert_first;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::setEquals(equals_func equals)
-{
-	mEquals = equals;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::addData(const INDEX_T &index, DATA_T datap)
-{
-	S32			level;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*current = &mHead;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*temp;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-	// replace the existing data if a node is already there
-	if (  (current)
-		&&(mEquals(current->mIndex, index)))
-	{
-		current->mData = datap;
-		return current->mData;
-	}
-
-	// now add the new node
-	S32 newlevel;
-	for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
-	{
-		if (ll_frand() < 0.5f)
-		{
-			break;
-		}
-	}
-
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *snode 
-		= new LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>(index, datap);
-
-	if (newlevel > mLevel)
-	{
-		mHead.mForward[mLevel] = NULL;
-		mUpdate[mLevel] = &mHead;
-		mLevel = newlevel;
-	}
-
-	for (level = 0; level < newlevel; level++)
-	{
-		snode->mForward[level] = mUpdate[level]->mForward[level];
-		mUpdate[level]->mForward[level] = snode;
-	}
-	return snode->mData;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::addData(const INDEX_T &index)
-{
-	S32			level;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*current = &mHead;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*temp;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-	// now add the new node
-	S32 newlevel;
-	for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
-	{
-		if (ll_frand() < 0.5f)
-			break;
-	}
-
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *snode 
-		= new LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>(index);
-
-	if (newlevel > mLevel)
-	{
-		mHead.mForward[mLevel] = NULL;
-		mUpdate[mLevel] = &mHead;
-		mLevel = newlevel;
-	}
-
-	for (level = 0; level < newlevel; level++)
-	{
-		snode->mForward[level] = mUpdate[level]->mForward[level];
-		mUpdate[level]->mForward[level] = snode;
-	}
-	return snode->mData;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getData(const INDEX_T &index)
-{
-	S32			level;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*current = &mHead;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*temp;
-
-	mNumberOfSteps = 0;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-				mNumberOfSteps++;
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-				mNumberOfSteps++;
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-	mNumberOfSteps++;
-
-	if (  (current)
-		&&(mEquals(current->mIndex, index)))
-	{
-		
-		return current->mData;
-	}
-	
-	// now add the new node
-	S32 newlevel;
-	for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
-	{
-		if (ll_frand() < 0.5f)
-			break;
-	}
-
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *snode 
-		= new LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>(index);
-
-	if (newlevel > mLevel)
-	{
-		mHead.mForward[mLevel] = NULL;
-		mUpdate[mLevel] = &mHead;
-		mLevel = newlevel;
-	}
-
-	for (level = 0; level < newlevel; level++)
-	{
-		snode->mForward[level] = mUpdate[level]->mForward[level];
-		mUpdate[level]->mForward[level] = snode;
-	}
-	
-	return snode->mData;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getInterval(const INDEX_T &index, 
-																	 INDEX_T &index_before, 
-																	 INDEX_T &index_after, 
-																	 DATA_T &data_before, 
-																	 DATA_T &data_after)
-{
-	S32			level;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*current = &mHead;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*temp;
-
-	mNumberOfSteps = 0;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-				mNumberOfSteps++;
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-				mNumberOfSteps++;
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	BOOL both_found = TRUE;
-
-	if (current != &mHead)
-	{
-		index_before = current->mIndex;
-		data_before = current->mData;
-	}
-	else
-	{
-		data_before = 0;
-		index_before = 0;
-		both_found = FALSE;
-	}
-
-	// we're now just in front of where we want to be . . . take one step forward
-	mNumberOfSteps++;
-	current = *current->mForward;
-
-	if (current)
-	{
-		data_after = current->mData;
-		index_after = current->mIndex;
-	}
-	else
-	{
-		data_after = 0;
-		index_after = 0;
-		both_found = FALSE;
-	}
-
-	return both_found;
-}
-
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::operator[](const INDEX_T &index)
-{
-	
-	return getData(index);
-}
-
-// If index present, returns data.
-// If index not present, adds <index,NULL> and returns NULL.
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getData(const INDEX_T &index, BOOL &b_new_entry)
-{
-	S32			level;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*current = &mHead;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*temp;
-
-	mNumberOfSteps = 0;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-				mNumberOfSteps++;
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-				mNumberOfSteps++;
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	mNumberOfSteps++;
-	current = *current->mForward;
-
-	if (  (current)
-		&&(mEquals(current->mIndex, index)))
-	{
-		
-		return current->mData;
-	}
-	b_new_entry = TRUE;
-	addData(index);
-	
-	return current->mData;
-}
-
-// Returns TRUE if data present in map.
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::checkData(const INDEX_T &index)
-{
-	S32			level;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*current = &mHead;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*temp;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-	if (current)
-	{
-		// Gets rid of some compiler ambiguity for the LLPointer<> templated class.
-		if (current->mData)
-		{
-			return mEquals(current->mIndex, index);
-		}
-	}
-
-	return FALSE;
-}
-
-// Returns TRUE if key is present in map. This is useful if you
-// are potentially storing NULL pointers in the map
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::checkKey(const INDEX_T &index)
-{
-	S32			level;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*current = &mHead;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*temp;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-	if (current)
-	{
-		return mEquals(current->mIndex, index);
-	}
-
-	return FALSE;
-}
-
-// If there, returns the data.
-// If not, returns NULL.
-// Never adds entries to the map.
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getIfThere(const INDEX_T &index)
-{
-	S32			level;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*current = &mHead;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*temp;
-
-	mNumberOfSteps = 0;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-				mNumberOfSteps++;
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-				mNumberOfSteps++;
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	mNumberOfSteps++;
-	current = *current->mForward;
-
-	if (current)
-	{
-		if (mEquals(current->mIndex, index))
-		{
-			return current->mData;
-		}
-	}
-
-	// Avoid Linux compiler warning on returning NULL.
-	return (DATA_T)0;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::reverseLookup(const DATA_T datap)
-{
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*current = &mHead;
-
-	while (current)
-	{
-		if (datap == current->mData)
-		{
-			
-			return current->mIndex;
-		}
-		current = *current->mForward;
-	}
-
-	// not found! return NULL
-	return INDEX_T();
-}
-
-// returns number of items in the list
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline S32 LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getLength()
-{
-	U32	length = 0;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>* temp;
-	for (temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0])
-	{
-		length++;
-	}
-	
-	return length;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::removeData(const INDEX_T &index)
-{
-	S32			level;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*current = &mHead;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*temp;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-	if (!current)
-	{
-		// empty list or beyond the end!
-		
-		return FALSE;
-	}
-
-	// is this the one we want?
-	if (!mEquals(current->mIndex, index))
-	{
-		// nope!
-		
-		return FALSE;
-	}
-	else
-	{
-		// do we need to fix current or currentop?
-		if (current == mCurrentp)
-		{
-			mCurrentp = *current->mForward;
-		}
-
-		if (current == mCurrentOperatingp)
-		{
-			mCurrentOperatingp = *current->mForward;
-		}
-		// yes it is!  change pointers as required
-		for (level = 0; level < mLevel; level++)
-		{
-			if (*((*(mUpdate + level))->mForward + level) != current)
-			{
-				// cool, we've fixed all the pointers!
-				break;
-			}
-			*((*(mUpdate + level))->mForward + level) = *(current->mForward + level);
-		}
-
-		// clean up cuurent
-		current->removeData();
-		delete current;
-
-		// clean up mHead
-		while (  (mLevel > 1)
-			   &&(!*(mHead.mForward + mLevel - 1)))
-		{
-			mLevel--;
-		}
-	}
-	
-	return TRUE;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::deleteData(const INDEX_T &index)
-{
-	S32			level;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*current = &mHead;
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>	*temp;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-	if (!current)
-	{
-		// empty list or beyond the end!
-		
-		return FALSE;
-	}
-
-	// is this the one we want?
-	if (!mEquals(current->mIndex, index))
-	{
-		// nope!
-		
-		return FALSE;
-	}
-	else
-	{
-		// do we need to fix current or currentop?
-		if (current == mCurrentp)
-		{
-			mCurrentp = *current->mForward;
-		}
-
-		if (current == mCurrentOperatingp)
-		{
-			mCurrentOperatingp = *current->mForward;
-		}
-		// yes it is!  change pointers as required
-		for (level = 0; level < mLevel; level++)
-		{
-			if (*((*(mUpdate + level))->mForward + level) != current)
-			{
-				// cool, we've fixed all the pointers!
-				break;
-			}
-			*((*(mUpdate + level))->mForward + level) = *(current->mForward + level);
-		}
-
-		// clean up cuurent
-		current->deleteData();
-		delete current;
-
-		// clean up mHead
-		while (  (mLevel > 1)
-			   &&(!*(mHead.mForward + mLevel - 1)))
-		{
-			mLevel--;
-		}
-	}
-	
-	return TRUE;
-}
-
-// remove all nodes from the list but do not delete data
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::removeAllData()
-{
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
-	// reset mCurrentp
-	mCurrentp = *(mHead.mForward);
-
-	while (mCurrentp)
-	{
-		temp = mCurrentp->mForward[0];
-		mCurrentp->removeData();
-		delete mCurrentp;
-		mCurrentp = temp;
-	}
-
-	S32 i;
-	for (i = 0; i < BINARY_DEPTH; i++)
-	{
-		mHead.mForward[i] = NULL;
-		mUpdate[i] = NULL;
-	}
-
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::deleteAllData()
-{
-	LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
-	// reset mCurrentp
-	mCurrentp = *(mHead.mForward);
-
-	while (mCurrentp)
-	{
-		temp = mCurrentp->mForward[0];
-		mCurrentp->deleteData();
-		delete mCurrentp;
-		mCurrentp = temp;
-	}
-
-	S32 i;
-	for (i = 0; i < BINARY_DEPTH; i++)
-	{
-		mHead.mForward[i] = NULL;
-		mUpdate[i] = NULL;
-	}
-
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-// place mCurrentp on first node
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::resetList()
-{
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-
-// return the data currently pointed to
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getCurrentDataWithoutIncrement()
-{
-	if (mCurrentOperatingp)
-	{
-		return mCurrentOperatingp->mData;
-	}
-	else
-	{
-		//return NULL; 		// causes warning
-		return (DATA_T)0;			// equivalent, but no warning
-	}
-}
-
-// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getCurrentData()
-{
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mForward[0];
-		return mCurrentOperatingp->mData;
-	}
-	else
-	{
-		//return NULL; 		// causes warning
-		return (DATA_T)0;			// equivalent, but no warning
-	}
-}
-
-// same as getCurrentData() but a more intuitive name for the operation
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getNextData()
-{
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mForward[0];
-		return mCurrentOperatingp->mData;
-	}
-	else
-	{
-		//return NULL;	// causes compile warning
-		return (DATA_T)0;		// equivalent, but removes warning
-	}
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getNextKey()
-{
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mForward[0];
-		return mCurrentOperatingp->mIndex;
-	}
-	else
-	{
-		return mHead.mIndex;
-	}
-}
-
-// return the key currently pointed to
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getCurrentKeyWithoutIncrement()
-{
-	if (mCurrentOperatingp)
-	{
-		return mCurrentOperatingp->mIndex;
-	}
-	else
-	{
-		//return NULL;	// causes compile warning
-		return (INDEX_T)0;		// equivalent, but removes warning
-	}
-}
-
-
-// remove the Node at mCurentOperatingp
-// leave mCurrentp and mCurentOperatingp on the next entry
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::removeCurrentData()
-{
-	if (mCurrentOperatingp)
-	{
-		removeData(mCurrentOperatingp->mIndex);
-	}
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::deleteCurrentData()
-{
-	if (mCurrentOperatingp)
-	{
-		deleteData(mCurrentOperatingp->mIndex);
-	}
-}
-
-// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getFirstData()
-{
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mForward[0];
-		return mCurrentOperatingp->mData;
-	}
-	else
-	{
-		//return NULL;	// causes compile warning
-		return (DATA_T)0;		// equivalent, but removes warning
-	}
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getFirstKey()
-{
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mForward[0];
-		return mCurrentOperatingp->mIndex;
-	}
-	else
-	{
-		return mHead.mIndex;
-	}
-}
-
-#endif
diff --git a/indra/llcommon/llskiplist.h b/indra/llcommon/llskiplist.h
deleted file mode 100644
index ed132381f9..0000000000
--- a/indra/llcommon/llskiplist.h
+++ /dev/null
@@ -1,517 +0,0 @@
-/** 
- * @file llskiplist.h
- * @brief skip list implementation
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-#ifndef LL_LLSKIPLIST_H
-#define LL_LLSKIPLIST_H
-
-#include "llrand.h"
-#include "llrand.h"
-
-// NOTA BENE: Insert first needs to be < NOT <=
-// Binary depth must be >= 2
-template <class DATA_TYPE, S32 BINARY_DEPTH = 10>
-class LLSkipList
-{
-public:
-	typedef BOOL (*compare)(const DATA_TYPE& first, const DATA_TYPE& second);
-	typedef compare insert_func;
-	typedef compare equals_func;
-
-	void init();
-
-	// basic constructor
-	LLSkipList();
-
-	// basic constructor including sorter
-	LLSkipList(insert_func insert_first, equals_func equals);
-	~LLSkipList();
-
-	inline void setInsertFirst(insert_func insert_first);
-	inline void setEquals(equals_func equals);
-
-	inline BOOL addData(const DATA_TYPE& data);
-	inline BOOL checkData(const DATA_TYPE& data);
-
-	// returns number of items in the list
-	inline S32 getLength() const; // NOT a constant time operation, traverses entire list!
-
-	inline BOOL moveData(const DATA_TYPE& data, LLSkipList *newlist);
-
-	inline BOOL removeData(const DATA_TYPE& data);
-
-	// remove all nodes from the list but do not delete data
-	inline void removeAllNodes();
-
-	// place mCurrentp on first node
-	inline void resetList();
-
-	// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-	inline DATA_TYPE getCurrentData();
-
-	// same as getCurrentData() but a more intuitive name for the operation
-	inline DATA_TYPE getNextData();
-
-	// remove the Node at mCurentOperatingp
-	// leave mCurrentp and mCurentOperatingp on the next entry
-	inline void removeCurrentData();
-
-	// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-	inline DATA_TYPE getFirstData();
-
-	class LLSkipNode
-	{
-	public:
-		LLSkipNode()
-		:	mData(0)
-		{
-			S32 i;
-			for (i = 0; i < BINARY_DEPTH; i++)
-			{
-				mForward[i] = NULL;
-			}
-		}
-
-		LLSkipNode(DATA_TYPE data)
-			: mData(data)
-		{
-			S32 i;
-			for (i = 0; i < BINARY_DEPTH; i++)
-			{
-				mForward[i] = NULL;
-			}
-		}
-
-		~LLSkipNode()
-		{
-		}
-
-		DATA_TYPE					mData;
-		LLSkipNode					*mForward[BINARY_DEPTH];
-
-	private:
-		// Disallow copying of LLSkipNodes by not implementing these methods.
-		LLSkipNode(const LLSkipNode &);
-		LLSkipNode &operator=(const LLSkipNode &);
-	};
-
-	static BOOL defaultEquals(const DATA_TYPE& first, const DATA_TYPE& second)
-	{
-		return first == second;
-	}
-
-private:
-	LLSkipNode					mHead;
-	LLSkipNode					*mUpdate[BINARY_DEPTH];
-	LLSkipNode					*mCurrentp;
-	LLSkipNode					*mCurrentOperatingp;
-	S32							mLevel;
-	insert_func mInsertFirst;
-	equals_func mEquals;
-
-private:
-	// Disallow copying of LLSkipNodes by not implementing these methods.
-	LLSkipList(const LLSkipList &);
-	LLSkipList &operator=(const LLSkipList &);
-};
-
-
-///////////////////////
-//
-// Implementation
-//
-
-
-// Binary depth must be >= 2
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::init()
-{
-	S32 i;
-	for (i = 0; i < BINARY_DEPTH; i++)
-	{
-		mHead.mForward[i] = NULL;
-		mUpdate[i] = NULL;
-	}
-	mLevel = 1;
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-
-// basic constructor
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline LLSkipList<DATA_TYPE, BINARY_DEPTH>::LLSkipList()
-:	mInsertFirst(NULL), 
-	mEquals(defaultEquals)
-{
-	init();
-}
-
-// basic constructor including sorter
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline LLSkipList<DATA_TYPE, BINARY_DEPTH>::LLSkipList(insert_func insert,
-													   equals_func equals)
-:	mInsertFirst(insert), 
-	mEquals(equals)
-{
-	init();
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline LLSkipList<DATA_TYPE, BINARY_DEPTH>::~LLSkipList()
-{
-	removeAllNodes();
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::setInsertFirst(insert_func insert_first)
-{
-	mInsertFirst = insert_first;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::setEquals(equals_func equals)
-{
-	mEquals = equals;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::addData(const DATA_TYPE& data)
-{
-	S32			level;
-	LLSkipNode	*current = &mHead;
-	LLSkipNode	*temp;
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mData, data)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mData < data))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-	// now add the new node
-	S32 newlevel;
-	for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
-	{
-		if (ll_frand() < 0.5f)
-			break;
-	}
-
-	LLSkipNode *snode = new LLSkipNode(data);
-
-	if (newlevel > mLevel)
-	{
-		mHead.mForward[mLevel] = NULL;
-		mUpdate[mLevel] = &mHead;
-		mLevel = newlevel;
-	}
-
-	for (level = 0; level < newlevel; level++)
-	{
-		snode->mForward[level] = mUpdate[level]->mForward[level];
-		mUpdate[level]->mForward[level] = snode;
-	}
-	return TRUE;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::checkData(const DATA_TYPE& data)
-{
-	S32			level;
-	LLSkipNode	*current = &mHead;
-	LLSkipNode	*temp;
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mData, data)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mData < data))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-
-	if (current)
-	{
-		return mEquals(current->mData, data);
-	}
-
-	return FALSE;
-}
-
-// returns number of items in the list
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline S32 LLSkipList<DATA_TYPE, BINARY_DEPTH>::getLength() const
-{
-	U32	length = 0;
-	for (LLSkipNode* temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0])
-	{
-		length++;
-	}
-	return length;
-}
-
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::moveData(const DATA_TYPE& data, LLSkipList *newlist)
-{
-	BOOL removed = removeData(data);
-	BOOL added = newlist->addData(data);
-	return removed && added;
-}
-
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::removeData(const DATA_TYPE& data)
-{
-	S32			level;
-	LLSkipNode	*current = &mHead;
-	LLSkipNode	*temp;
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mData, data)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mData < data))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-
-	if (!current)
-	{
-		// empty list or beyond the end!
-		return FALSE;
-	}
-
-	// is this the one we want?
-	if (!mEquals(current->mData, data))
-	{
-		// nope!
-		return FALSE;
-	}
-	else
-	{
-		// do we need to fix current or currentop?
-		if (current == mCurrentp)
-		{
-			mCurrentp = current->mForward[0];
-		}
-
-		if (current == mCurrentOperatingp)
-		{
-			mCurrentOperatingp = current->mForward[0];
-		}
-		// yes it is!  change pointers as required
-		for (level = 0; level < mLevel; level++)
-		{
-			if (mUpdate[level]->mForward[level] != current)
-			{
-				// cool, we've fixed all the pointers!
-				break;
-			}
-			mUpdate[level]->mForward[level] = current->mForward[level];
-		}
-
-		// clean up cuurent
-		delete current;
-
-		// clean up mHead
-		while (  (mLevel > 1)
-			   &&(!mHead.mForward[mLevel - 1]))
-		{
-			mLevel--;
-		}
-	}
-	return TRUE;
-}
-
-// remove all nodes from the list but do not delete data
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::removeAllNodes()
-{
-	LLSkipNode *temp;
-	// reset mCurrentp
-	mCurrentp = *(mHead.mForward);
-
-	while (mCurrentp)
-	{
-		temp = mCurrentp->mForward[0];
-		delete mCurrentp;
-		mCurrentp = temp;
-	}
-
-	S32 i;
-	for (i = 0; i < BINARY_DEPTH; i++)
-	{
-		mHead.mForward[i] = NULL;
-		mUpdate[i] = NULL;
-	}
-
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-// place mCurrentp on first node
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::resetList()
-{
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipList<DATA_TYPE, BINARY_DEPTH>::getCurrentData()
-{
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mForward[0];
-		return mCurrentOperatingp->mData;
-	}
-	else
-	{
-		//return NULL;		// causes compile warning
-		return (DATA_TYPE)0; 			// equivalent, but no warning
-	}
-}
-
-// same as getCurrentData() but a more intuitive name for the operation
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipList<DATA_TYPE, BINARY_DEPTH>::getNextData()
-{
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mForward[0];
-		return mCurrentOperatingp->mData;
-	}
-	else
-	{
-		//return NULL;		// causes compile warning
-		return (DATA_TYPE)0; 			// equivalent, but no warning
-	}
-}
-
-// remove the Node at mCurentOperatingp
-// leave mCurrentp and mCurentOperatingp on the next entry
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::removeCurrentData()
-{
-	if (mCurrentOperatingp)
-	{
-		removeData(mCurrentOperatingp->mData);
-	}
-}
-
-// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipList<DATA_TYPE, BINARY_DEPTH>::getFirstData()
-{
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mForward[0];
-		return mCurrentOperatingp->mData;
-	}
-	else
-	{
-		//return NULL;		// causes compile warning
-		return (DATA_TYPE)0; 			// equivalent, but no warning
-	}
-}
-
-
-#endif
diff --git a/indra/llcommon/llskipmap.h b/indra/llcommon/llskipmap.h
deleted file mode 100644
index ed53973baa..0000000000
--- a/indra/llcommon/llskipmap.h
+++ /dev/null
@@ -1,1020 +0,0 @@
-/** 
- * @file llskipmap.h
- * @brief Associative container based on the skiplist algorithm.
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLSKIPMAP_H
-#define LL_LLSKIPMAP_H
-
-#include "llerror.h"
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH = 8> 
-class LLSkipMap
-{
-public:
-	// basic constructor
-	LLSkipMap();
-
-	// basic constructor including sorter
-	LLSkipMap(BOOL	(*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second), 
-			   BOOL	(*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second));
-
-	~LLSkipMap();
-
-	void setInsertFirst(BOOL (*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second));
-	void setEquals(BOOL (*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second));
-
-	DATA_TYPE &addData(const INDEX_TYPE &index, DATA_TYPE datap);
-	DATA_TYPE &addData(const INDEX_TYPE &index);
-	DATA_TYPE &getData(const INDEX_TYPE &index);
-	DATA_TYPE &operator[](const INDEX_TYPE &index);
-
-	// If index present, returns data.
-	// If index not present, adds <index,NULL> and returns NULL.
-	DATA_TYPE &getData(const INDEX_TYPE &index, BOOL &b_new_entry);
-
-	// Returns TRUE if data present in map.
-	BOOL checkData(const INDEX_TYPE &index);
-
-	// Returns TRUE if key is present in map. This is useful if you
-	// are potentially storing NULL pointers in the map
-	BOOL checkKey(const INDEX_TYPE &index);
-
-	// If there, returns the data.
-	// If not, returns NULL.
-	// Never adds entries to the map.
-	DATA_TYPE getIfThere(const INDEX_TYPE &index);
-
-	INDEX_TYPE reverseLookup(const DATA_TYPE datap);
-
-	// returns number of items in the list
-	S32 getLength(); // WARNING!  getLength is O(n), not O(1)!
-
-	BOOL removeData(const INDEX_TYPE &index);
-
-	// remove all nodes from the list but do not delete data
-	void removeAllData();
-
-	// place mCurrentp on first node
-	void resetList();
-
-	// return the data currently pointed to
-	DATA_TYPE	getCurrentDataWithoutIncrement();
-
-	// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-	DATA_TYPE	getCurrentData();
-
-	// same as getCurrentData() but a more intuitive name for the operation
-	DATA_TYPE	getNextData();
-
-	INDEX_TYPE	getNextKey();
-
-	// return the key currently pointed to
-	INDEX_TYPE	getCurrentKeyWithoutIncrement();
-
-	// The internal iterator is at the end of the list.
-	BOOL		notDone() const;
-
-	// remove the Node at mCurentOperatingp
-	// leave mCurrentp and mCurentOperatingp on the next entry
-	void removeCurrentData();
-
-	void deleteCurrentData();
-
-	// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-	DATA_TYPE	getFirstData();
-
-	INDEX_TYPE	getFirstKey();
-
-	class LLSkipMapNode
-	{
-	public:
-		LLSkipMapNode()
-		{
-			S32 i;
-			for (i = 0; i < BINARY_DEPTH; i++)
-			{
-				mForward[i] = NULL;
-			}
-
-			U8  *zero = (U8 *)&mIndex;
-
-			for (i = 0; i < (S32)sizeof(INDEX_TYPE); i++)
-			{
-				*(zero + i) = 0;
-			}
-
-			zero = (U8 *)&mData;
-
-			for (i = 0; i < (S32)sizeof(DATA_TYPE); i++)
-			{
-				*(zero + i) = 0;
-			}
-		}
-
-		LLSkipMapNode(const INDEX_TYPE &index)
-		:	mIndex(index)
-		{
-
-			S32 i;
-			for (i = 0; i < BINARY_DEPTH; i++)
-			{
-				mForward[i] = NULL;
-			}
-
-			U8 *zero = (U8 *)&mData;
-
-			for (i = 0; i < (S32)sizeof(DATA_TYPE); i++)
-			{
-				*(zero + i) = 0;
-			}
-		}
-
-		LLSkipMapNode(const INDEX_TYPE &index, DATA_TYPE datap)
-		:	mIndex(index)
-		{
-
-			S32 i;
-			for (i = 0; i < BINARY_DEPTH; i++)
-			{
-				mForward[i] = NULL;
-			}
-
-			mData = datap;
-		}
-
-		~LLSkipMapNode()
-		{
-		}
-
-
-		INDEX_TYPE					mIndex;
-		DATA_TYPE					mData;
-		LLSkipMapNode				*mForward[BINARY_DEPTH];
-
-	private:
-		// Disallow copying of LLSkipMapNodes by not implementing these methods.
-		LLSkipMapNode(const LLSkipMapNode &);
-		LLSkipMapNode &operator=(const LLSkipMapNode &rhs);
-	};
-
-	static BOOL	defaultEquals(const INDEX_TYPE &first, const INDEX_TYPE &second)
-	{
-		return first == second;
-	}
-
-private:
-	// don't generate implicit copy constructor or copy assignment
-	LLSkipMap(const LLSkipMap &);
-	LLSkipMap &operator=(const LLSkipMap &);
-
-private:
-	LLSkipMapNode				mHead;
-	LLSkipMapNode				*mUpdate[BINARY_DEPTH];
-	LLSkipMapNode				*mCurrentp;
-	LLSkipMapNode				*mCurrentOperatingp;
-	S32							mLevel;
-	BOOL						(*mInsertFirst)(const INDEX_TYPE &first, const INDEX_TYPE &second);
-	BOOL						(*mEquals)(const INDEX_TYPE &first, const INDEX_TYPE &second);
-	S32							mNumberOfSteps;
-};
-
-//////////////////////////////////////////////////
-//
-// LLSkipMap implementation
-//
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::LLSkipMap()
-	:	mInsertFirst(NULL),
-		mEquals(defaultEquals)
-{
-	llstatic_assert(BINARY_DEPTH >= 2, "Skipmaps must have binary depth of at least 2");
-
-	S32 i;
-	for (i = 0; i < BINARY_DEPTH; i++)
-	{
-		mUpdate[i] = NULL;
-	}
-	mLevel = 1;
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::LLSkipMap(BOOL	(*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second), 
-			   BOOL	(*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second)) 
-	:	mInsertFirst(insert_first),
-		mEquals(equals)
-{
-	llstatic_assert(BINARY_DEPTH >= 2, "Skipmaps must have binary depth of at least 2");
-
-	mLevel = 1;
-	S32 i;
-	for (i = 0; i < BINARY_DEPTH; i++)
-	{
-		mHead.mForward[i] = NULL;
-		mUpdate[i] = NULL;
-	}
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::~LLSkipMap()
-{
-	removeAllData();
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::setInsertFirst(BOOL (*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second))
-{
-	mInsertFirst = insert_first;
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::setEquals(BOOL (*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second))
-{
-	mEquals = equals;
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::addData(const INDEX_TYPE &index, DATA_TYPE datap)
-{
-	S32			level;
-	LLSkipMapNode	*current = &mHead;
-	LLSkipMapNode	*temp;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-	// replace the existing data if a node is already there
-	if (  (current)
-		&&(mEquals(current->mIndex, index)))
-	{
-		current->mData = datap;
-		return current->mData;
-	}
-
-	// now add the new node
-	S32 newlevel;
-	for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
-	{
-		if (rand() & 1)
-		{
-			break;
-		}
-	}
-
-	LLSkipMapNode *snode = new LLSkipMapNode(index, datap);
-
-	if (newlevel > mLevel)
-	{
-		mHead.mForward[mLevel] = NULL;
-		mUpdate[mLevel] = &mHead;
-		mLevel = newlevel;
-	}
-
-	for (level = 0; level < newlevel; level++)
-	{
-		snode->mForward[level] = mUpdate[level]->mForward[level];
-		mUpdate[level]->mForward[level] = snode;
-	}
-	return snode->mData;
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::addData(const INDEX_TYPE &index)
-{
-	S32			level;
-	LLSkipMapNode	*current = &mHead;
-	LLSkipMapNode	*temp;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-	// now add the new node
-	S32 newlevel;
-	for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
-	{
-		if (rand() & 1)
-			break;
-	}
-
-	LLSkipMapNode *snode = new LLSkipMapNode(index);
-
-	if (newlevel > mLevel)
-	{
-		mHead.mForward[mLevel] = NULL;
-		mUpdate[mLevel] = &mHead;
-		mLevel = newlevel;
-	}
-
-	for (level = 0; level < newlevel; level++)
-	{
-		snode->mForward[level] = mUpdate[level]->mForward[level];
-		mUpdate[level]->mForward[level] = snode;
-	}
-	return snode->mData;
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getData(const INDEX_TYPE &index)
-{
-	S32			level;
-	LLSkipMapNode	*current = &mHead;
-	LLSkipMapNode	*temp;
-
-	mNumberOfSteps = 0;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-				mNumberOfSteps++;
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-				mNumberOfSteps++;
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-	mNumberOfSteps++;
-
-	if (  (current)
-		&&(mEquals(current->mIndex, index)))
-	{
-		
-		return current->mData;
-	}
-	
-	// now add the new node
-	S32 newlevel;
-	for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
-	{
-		if (rand() & 1)
-			break;
-	}
-
-	LLSkipMapNode *snode = new LLSkipMapNode(index);
-
-	if (newlevel > mLevel)
-	{
-		mHead.mForward[mLevel] = NULL;
-		mUpdate[mLevel] = &mHead;
-		mLevel = newlevel;
-	}
-
-	for (level = 0; level < newlevel; level++)
-	{
-		snode->mForward[level] = mUpdate[level]->mForward[level];
-		mUpdate[level]->mForward[level] = snode;
-	}
-	
-	return snode->mData;
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::operator[](const INDEX_TYPE &index)
-{
-	
-	return getData(index);
-}
-
-// If index present, returns data.
-// If index not present, adds <index,NULL> and returns NULL.
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getData(const INDEX_TYPE &index, BOOL &b_new_entry)
-{
-	S32			level;
-	LLSkipMapNode	*current = &mHead;
-	LLSkipMapNode	*temp;
-
-	mNumberOfSteps = 0;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-				mNumberOfSteps++;
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-				mNumberOfSteps++;
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	mNumberOfSteps++;
-	current = *current->mForward;
-
-	if (  (current)
-		&&(mEquals(current->mIndex, index)))
-	{
-		
-		return current->mData;
-	}
-	b_new_entry = TRUE;
-	addData(index);
-	
-	return current->mData;
-}
-
-// Returns TRUE if data present in map.
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::checkData(const INDEX_TYPE &index)
-{
-	S32			level;
-	LLSkipMapNode	*current = &mHead;
-	LLSkipMapNode	*temp;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-	if (current)
-	{
-		// Gets rid of some compiler ambiguity for the LLPointer<> templated class.
-		if (current->mData)
-		{
-			return mEquals(current->mIndex, index);
-		}
-	}
-
-	return FALSE;
-}
-
-// Returns TRUE if key is present in map. This is useful if you
-// are potentially storing NULL pointers in the map
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::checkKey(const INDEX_TYPE &index)
-{
-	S32			level;
-	LLSkipMapNode	*current = &mHead;
-	LLSkipMapNode	*temp;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-	if (current)
-	{
-		return mEquals(current->mIndex, index);
-	}
-
-	return FALSE;
-}
-
-// If there, returns the data.
-// If not, returns NULL.
-// Never adds entries to the map.
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getIfThere(const INDEX_TYPE &index)
-{
-	S32			level;
-	LLSkipMapNode	*current = &mHead;
-	LLSkipMapNode	*temp;
-
-	mNumberOfSteps = 0;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-				mNumberOfSteps++;
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-				mNumberOfSteps++;
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	mNumberOfSteps++;
-	current = *current->mForward;
-
-	if (current)
-	{
-		if (mEquals(current->mIndex, index))
-		{
-			return current->mData;
-		}
-	}
-
-	// Avoid Linux compiler warning on returning NULL.
-	return DATA_TYPE();
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::reverseLookup(const DATA_TYPE datap)
-{
-	LLSkipMapNode	*current = &mHead;
-
-	while (current)
-	{
-		if (datap == current->mData)
-		{
-			
-			return current->mIndex;
-		}
-		current = *current->mForward;
-	}
-
-	// not found! return NULL
-	return INDEX_TYPE();
-}
-
-// returns number of items in the list
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline S32 LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getLength()
-{
-	U32	length = 0;
-	for (LLSkipMapNode* temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0])
-	{
-		length++;
-	}
-	
-	return length;
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::removeData(const INDEX_TYPE &index)
-{
-	S32			level;
-	LLSkipMapNode	*current = &mHead;
-	LLSkipMapNode	*temp;
-
-	// find the pointer one in front of the one we want
-	if (mInsertFirst)
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(mInsertFirst(temp->mIndex, index)))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	else
-	{
-		for (level = mLevel - 1; level >= 0; level--)
-		{
-			temp = *(current->mForward + level);
-			while (  (temp)
-				   &&(temp->mIndex < index))
-			{
-				current = temp;
-				temp = *(current->mForward + level);
-			}
-			*(mUpdate + level) = current;
-		}
-	}
-	
-	// we're now just in front of where we want to be . . . take one step forward
-	current = *current->mForward;
-
-	if (!current)
-	{
-		// empty list or beyond the end!
-		
-		return FALSE;
-	}
-
-	// is this the one we want?
-	if (!mEquals(current->mIndex, index))
-	{
-		// nope!
-		
-		return FALSE;
-	}
-	else
-	{
-		// do we need to fix current or currentop?
-		if (current == mCurrentp)
-		{
-			mCurrentp = *current->mForward;
-		}
-
-		if (current == mCurrentOperatingp)
-		{
-			mCurrentOperatingp = *current->mForward;
-		}
-		// yes it is!  change pointers as required
-		for (level = 0; level < mLevel; level++)
-		{
-			if (*((*(mUpdate + level))->mForward + level) != current)
-			{
-				// cool, we've fixed all the pointers!
-				break;
-			}
-			*((*(mUpdate + level))->mForward + level) = *(current->mForward + level);
-		}
-
-		delete current;
-
-		// clean up mHead
-		while (  (mLevel > 1)
-			   &&(!*(mHead.mForward + mLevel - 1)))
-		{
-			mLevel--;
-		}
-	}
-	
-	return TRUE;
-}
-
-
-// remove all nodes from the list but do not delete data
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::removeAllData()
-{
-	LLSkipMapNode *temp;
-	// reset mCurrentp
-	mCurrentp = *(mHead.mForward);
-
-	while (mCurrentp)
-	{
-		temp = mCurrentp->mForward[0];
-		delete mCurrentp;
-		mCurrentp = temp;
-	}
-
-	S32 i;
-	for (i = 0; i < BINARY_DEPTH; i++)
-	{
-		mHead.mForward[i] = NULL;
-		mUpdate[i] = NULL;
-	}
-
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-
-// place mCurrentp on first node
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::resetList()
-{
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-}
-
-
-// return the data currently pointed to
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getCurrentDataWithoutIncrement()
-{
-	if (mCurrentOperatingp)
-	{
-		return mCurrentOperatingp->mData;
-	}
-	else
-	{
-		return DATA_TYPE();
-	}
-}
-
-// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getCurrentData()
-{
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mForward[0];
-		return mCurrentOperatingp->mData;
-	}
-	else
-	{
-		// Basic types, like int, have default constructors that initialize
-		// them to zero.  g++ 2.95 supports this.  "int()" is zero.
-		// This also is nice for LLUUID()
-		return DATA_TYPE();
-	}
-}
-
-// same as getCurrentData() but a more intuitive name for the operation
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getNextData()
-{
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mForward[0];
-		return mCurrentOperatingp->mData;
-	}
-	else
-	{
-		// Basic types, like int, have default constructors that initialize
-		// them to zero.  g++ 2.95 supports this.  "int()" is zero.
-		// This also is nice for LLUUID()
-		return DATA_TYPE();
-	}
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getNextKey()
-{
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mForward[0];
-		return mCurrentOperatingp->mIndex;
-	}
-	else
-	{
-		return mHead.mIndex;
-	}
-}
-
-// return the key currently pointed to
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getCurrentKeyWithoutIncrement()
-{
-	if (mCurrentOperatingp)
-	{
-		return mCurrentOperatingp->mIndex;
-	}
-	else
-	{
-		// See comment for getNextData()
-		return INDEX_TYPE();
-	}
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::notDone() const
-{
-	if (mCurrentOperatingp)
-	{
-		return TRUE;
-	}
-	else
-	{
-		return FALSE;
-	}
-}
-
-
-// remove the Node at mCurentOperatingp
-// leave mCurrentp and mCurentOperatingp on the next entry
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::removeCurrentData()
-{
-	if (mCurrentOperatingp)
-	{
-		removeData(mCurrentOperatingp->mIndex);
-	}
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::deleteCurrentData()
-{
-	if (mCurrentOperatingp)
-	{
-		deleteData(mCurrentOperatingp->mIndex);
-	}
-}
-
-// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getFirstData()
-{
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mForward[0];
-		return mCurrentOperatingp->mData;
-	}
-	else
-	{
-		// See comment for getNextData()
-		return DATA_TYPE();
-	}
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getFirstKey()
-{
-	mCurrentp = *(mHead.mForward);
-	mCurrentOperatingp = *(mHead.mForward);
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mForward[0];
-		return mCurrentOperatingp->mIndex;
-	}
-	else
-	{
-		return mHead.mIndex;
-	}
-}
-
-#endif
diff --git a/indra/llcommon/lluuidhashmap.h b/indra/llcommon/lluuidhashmap.h
deleted file mode 100644
index e294670030..0000000000
--- a/indra/llcommon/lluuidhashmap.h
+++ /dev/null
@@ -1,583 +0,0 @@
-/** 
- * @file lluuidhashmap.h
- * @brief A uuid based hash map.
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLUUIDHASHMAP_H
-#define LL_LLUUIDHASHMAP_H
-
-#include "stdtypes.h"
-#include "llerror.h"
-#include "lluuid.h"
-
-// UUID hash map
-
-	/*
-	LLUUIDHashMap<uuid_pair, 32> foo(test_equals);
-	LLUUIDHashMapIter<uuid_pair, 32> bar(&foo);
-
-	LLDynamicArray<LLUUID> source_ids;
-	const S32 COUNT = 100000;
-	S32 q;
-	for (q = 0; q < COUNT; q++)
-	{
-		llinfos << "Creating" << llendl;
-		LLUUID id;
-		id.generate();
-		//llinfos << q << ":" << id << llendl;
-		uuid_pair pair;
-		pair.mUUID = id;
-		pair.mValue = q;
-		foo.set(id, pair);
-		source_ids.put(id);
-		//ms_sleep(1);
-	}
-
-	uuid_pair cur;
-	llinfos << "Iterating" << llendl;
-	for (cur = bar.first(); !bar.done(); cur = bar.next())
-	{
-		if (source_ids[cur.mValue] != cur.mUUID)
-		{
-			llerrs << "Incorrect value iterated!" << llendl;
-		}
-		//llinfos << cur.mValue << ":" << cur.mUUID << llendl;
-		//ms_sleep(1);
-	}
-
-	llinfos << "Finding" << llendl;
-	for (q = 0; q < COUNT; q++)
-	{
-		cur = foo.get(source_ids[q]);
-		if (source_ids[cur.mValue] != cur.mUUID)
-		{
-			llerrs << "Incorrect value found!" << llendl;
-		}
-		//llinfos << res.mValue << ":" << res.mUUID << llendl;
-		//ms_sleep(1);
-	}
-	
-	llinfos << "Removing" << llendl;
-	for (q = 0; q < COUNT/2; q++)
-	{
-		if (!foo.remove(source_ids[q]))
-		{
-			llerrs << "Remove failed!" << llendl;
-		}
-		//ms_sleep(1);
-	}
-
-	llinfos << "Iterating" << llendl;
-	for (cur = bar.first(); !bar.done(); cur = bar.next())
-	{
-		if (source_ids[cur.mValue] != cur.mUUID)
-		{
-			llerrs << "Incorrect value found!" << llendl;
-		}
-		//llinfos << cur.mValue << ":" << cur.mUUID << llendl;
-		//ms_sleep(1);
-	}
-	llinfos << "Done with UUID map test" << llendl;
-
-	return 0;
-	*/
-
-
-//
-// LLUUIDHashNode
-//
-
-template <class DATA, int SIZE>
-class LLUUIDHashNode
-{
-public:
-	LLUUIDHashNode();
-
-public:
-	S32 mCount;
-	U8	mKey[SIZE];
-	DATA mData[SIZE];
-	LLUUIDHashNode<DATA, SIZE> *mNextNodep;
-};
-
-
-//
-// LLUUIDHashNode implementation
-//
-template <class DATA, int SIZE>
-LLUUIDHashNode<DATA, SIZE>::LLUUIDHashNode()
-{
-	mCount = 0;
-	mNextNodep = NULL;
-}
-
-
-template <class DATA_TYPE, int SIZE>
-class LLUUIDHashMap
-{
-public:
-	// basic constructor including sorter
-	LLUUIDHashMap(BOOL (*equals)(const LLUUID &uuid, const DATA_TYPE &data),
-				  const DATA_TYPE &null_data);
-	~LLUUIDHashMap();
-
-	inline DATA_TYPE &get(const LLUUID &uuid);
-	inline BOOL check(const LLUUID &uuid) const;
-	inline DATA_TYPE &set(const LLUUID &uuid, const DATA_TYPE &type);
-	inline BOOL remove(const LLUUID &uuid);
-	void removeAll();
-
-	inline S32 getLength() const; // Warning, NOT O(1!)
-public:
-	BOOL (*mEquals)(const LLUUID &uuid, const DATA_TYPE &data);
-	LLUUIDHashNode<DATA_TYPE, SIZE> mNodes[256];
-
-	S32 mIterCount;
-protected:
-	DATA_TYPE mNull;
-};
-
-
-//
-// LLUUIDHashMap implementation
-//
-
-template <class DATA_TYPE, int SIZE>
-LLUUIDHashMap<DATA_TYPE, SIZE>::LLUUIDHashMap(BOOL (*equals)(const LLUUID &uuid, const DATA_TYPE &data),
-											  const DATA_TYPE &null_data)
-:	mEquals(equals),
-	mIterCount(0),
-	mNull(null_data)
-{ }
-
-template <class DATA_TYPE, int SIZE>
-LLUUIDHashMap<DATA_TYPE, SIZE>::~LLUUIDHashMap()
-{
-	removeAll();
-}
-
-template <class DATA_TYPE, int SIZE>
-void LLUUIDHashMap<DATA_TYPE, SIZE>::removeAll()
-{
-	S32 bin;
-	for (bin = 0; bin < 256; bin++)
-	{
-		LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
-
-		BOOL first = TRUE;
-		while (nodep)
-		{
-			S32 i;
-			const S32 count = nodep->mCount;
-
-			// Iterate through all members of this node
-			for (i = 0; i < count; i++)
-			{
-				nodep->mData[i] = mNull;
-			}
-
-			nodep->mCount = 0;
-			// Done with all objects in this node, go to the next.
-
-			LLUUIDHashNode<DATA_TYPE, SIZE>* curp = nodep;
-			nodep = nodep->mNextNodep;
-
-			// Delete the node if it's not the first node
-			if (first)
-			{
-				first = FALSE;
-				curp->mNextNodep = NULL;
-			}
-			else
-			{
-				delete curp;
-			}
-		}
-	}
-}
-
-template <class DATA_TYPE, int SIZE>
-inline S32 LLUUIDHashMap<DATA_TYPE, SIZE>::getLength() const
-{
-	S32 count = 0;
-	S32 bin;
-	for (bin = 0; bin < 256; bin++)
-	{
-		LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = (LLUUIDHashNode<DATA_TYPE, SIZE>*) &mNodes[bin];
-		while (nodep)
-		{
-			count += nodep->mCount;
-			nodep = nodep->mNextNodep;
-		}
-	}
-	return count;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline DATA_TYPE &LLUUIDHashMap<DATA_TYPE, SIZE>::get(const LLUUID &uuid)
-{
-	LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[uuid.mData[0]];
-
-	// Grab the second byte of the UUID, which is the key for the node data
-	const S32 second_byte = uuid.mData[1];
-	while (nodep)
-	{
-		S32 i;
-		const S32 count = nodep->mCount;
-
-		// Iterate through all members of this node
-		for (i = 0; i < count; i++)
-		{
-			if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
-			{
-				// The second byte matched, and our equality test passed.
-				// We found it.
-				return nodep->mData[i];
-			}
-		}
-
-		// Done with all objects in this node, go to the next.
-		nodep = nodep->mNextNodep;
-	}
-	return mNull;
-}
-
-
-template <class DATA_TYPE, int SIZE>
-inline BOOL LLUUIDHashMap<DATA_TYPE, SIZE>::check(const LLUUID &uuid) const
-{
-	const LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[uuid.mData[0]];
-
-	// Grab the second byte of the UUID, which is the key for the node data
-	const S32 second_byte = uuid.mData[1];
-	while (nodep)
-	{
-		S32 i;
-		const S32 count = nodep->mCount;
-
-		// Iterate through all members of this node
-		for (i = 0; i < count; i++)
-		{
-			if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
-			{
-				// The second byte matched, and our equality test passed.
-				// We found it.
-				return TRUE;
-			}
-		}
-
-		// Done with all objects in this node, go to the next.
-		nodep = nodep->mNextNodep;
-	}
-
-	// Didn't find anything
-	return FALSE;
-}
-
-
-template <class DATA_TYPE, int SIZE>
-inline DATA_TYPE &LLUUIDHashMap<DATA_TYPE, SIZE>::set(const LLUUID &uuid, const DATA_TYPE &data)
-{
-	// Set is just like a normal find, except that if we find a match
-	// we replace it with the input value.
-	// If we don't find a match, we append to the end of the list.
-
-	LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[uuid.mData[0]];
-
-	const S32 second_byte = uuid.mData[1];
-	while (1)
-	{
-		const S32 count = nodep->mCount;
-
-		S32 i;
-		for (i = 0; i < count; i++)
-		{
-			if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
-			{
-				// We found a match for this key, replace the data with
-				// the incoming data.
-				nodep->mData[i] = data;
-				return nodep->mData[i];
-			}
-		}
-		if (!nodep->mNextNodep)
-		{
-			// We've iterated through all of the keys without finding a match
-			if (i < SIZE)
-			{
-				// There's still some space on this node, append
-				// the key and data to it.
-				nodep->mKey[i] = second_byte;
-				nodep->mData[i] = data;
-				nodep->mCount++;
-
-				return nodep->mData[i];
-			}
-			else
-			{
-				// This node is full, append a new node to the end.
-				nodep->mNextNodep = new LLUUIDHashNode<DATA_TYPE, SIZE>;
-				nodep->mNextNodep->mKey[0] = second_byte;
-				nodep->mNextNodep->mData[0] = data;
-				nodep->mNextNodep->mCount = 1;
-
-				return nodep->mNextNodep->mData[0];
-			}
-		}
-
-		// No match on this node, go to the next
-		nodep = nodep->mNextNodep;
-	}
-}
-
-
-template <class DATA_TYPE, int SIZE>
-inline BOOL LLUUIDHashMap<DATA_TYPE, SIZE>::remove(const LLUUID &uuid)
-{
-	if (mIterCount)
-	{
-		// We don't allow remove when we're iterating, it's bad karma!
-		llerrs << "Attempted remove while an outstanding iterator in LLUUIDHashMap!" << llendl;
-	}
-	// Remove is the trickiest operation.
-	// What we want to do is swap the last element of the last
-	// node if we find the one that we want to remove, but we have
-	// to deal with deleting the node from the tail if it's empty, but
-	// NOT if it's the only node left.
-
-	LLUUIDHashNode<DATA_TYPE, SIZE> *nodep = &mNodes[uuid.mData[0]];
-
-	// Not empty, we need to search through the nodes
-	const S32 second_byte = uuid.mData[1];
-
-	// A modification of the standard search algorithm.
-	while (nodep)
-	{
-		const S32 count = nodep->mCount;
-
-		S32 i;
-		for (i = 0; i < count; i++)
-		{
-			if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
-			{
-				// We found the node that we want to remove.
-				// Find the last (and next-to-last) node, and the index of the last
-				// element.  We could conceviably start from the node we're on,
-				// but that makes it more complicated, this is easier.
-
-				LLUUIDHashNode<DATA_TYPE, SIZE> *prevp = &mNodes[uuid.mData[0]];
-				LLUUIDHashNode<DATA_TYPE, SIZE> *lastp = prevp;
-
-				// Find the last and next-to-last
-				while (lastp->mNextNodep)
-				{
-					prevp = lastp;
-					lastp = lastp->mNextNodep;
-				}
-
-				// First, swap in the last to the current location.
-				nodep->mKey[i] = lastp->mKey[lastp->mCount - 1];
-				nodep->mData[i] = lastp->mData[lastp->mCount - 1];
-
-				// Now, we delete the entry
-				lastp->mCount--;
-				lastp->mData[lastp->mCount] = mNull;
-
-				if (!lastp->mCount)
-				{
-					// We deleted the last element!
-					if (lastp != &mNodes[uuid.mData[0]])
-					{
-						// Only blitz the node if it's not the head
-						// Set the previous node to point to NULL, then
-						// blitz the empty last node
-						prevp->mNextNodep = NULL;
-						delete lastp;
-					}
-				}
-				return TRUE;
-			}
-		}
-
-		// Iterate to the next node, we've scanned all the entries in this one.
-		nodep = nodep->mNextNodep;
-	}
-	return FALSE;
-}
-
-
-//
-// LLUUIDHashMapIter
-//
-
-template <class DATA_TYPE, int SIZE>
-class LLUUIDHashMapIter
-{
-public:
-	LLUUIDHashMapIter(LLUUIDHashMap<DATA_TYPE, SIZE> *hash_mapp);
-	~LLUUIDHashMapIter();
-
-
-	inline void reset();
-	inline void first();
-	inline void next();
-	inline BOOL done() const;
-
-	DATA_TYPE& operator*() const
-	{
-		return mCurHashNodep->mData[mCurHashNodeKey];
-	}
-	DATA_TYPE* operator->() const
-	{
-		return &(operator*());
-	}
-
-protected:
-	LLUUIDHashMap<DATA_TYPE, SIZE> *mHashMapp;
-	LLUUIDHashNode<DATA_TYPE, SIZE> *mCurHashNodep;
-
-	S32 mCurHashMapNodeNum;
-	S32 mCurHashNodeKey;
-
-	DATA_TYPE mNull;
-};
-
-
-//
-// LLUUIDHashMapIter Implementation
-//
-template <class DATA_TYPE, int SIZE>
-LLUUIDHashMapIter<DATA_TYPE, SIZE>::LLUUIDHashMapIter(LLUUIDHashMap<DATA_TYPE, SIZE> *hash_mapp)
-{
-	mHashMapp = hash_mapp;
-	mCurHashNodep = NULL;
-	mCurHashMapNodeNum = 0;
-	mCurHashNodeKey = 0;
-}
-
-template <class DATA_TYPE, int SIZE>
-LLUUIDHashMapIter<DATA_TYPE, SIZE>::~LLUUIDHashMapIter()
-{
-	reset();
-}
-
-template <class DATA_TYPE, int SIZE>
-inline void LLUUIDHashMapIter<DATA_TYPE, SIZE>::reset()
-{
-	if (mCurHashNodep)
-	{
-		// We're partway through an iteration, we can clean up now
-		mHashMapp->mIterCount--;
-		mCurHashNodep = NULL;
-	}
-}
-
-template <class DATA_TYPE, int SIZE>
-inline void LLUUIDHashMapIter<DATA_TYPE, SIZE>::first()
-{
-	// Iterate through until we find the first non-empty node;
-	S32 i;
-	for (i = 0; i < 256; i++)
-	{
-		if (mHashMapp->mNodes[i].mCount)
-		{
-			if (!mCurHashNodep)
-			{
-				// Increment, since it's no longer safe for us to do a remove
-				mHashMapp->mIterCount++;
-			}
-
-			mCurHashNodep = &mHashMapp->mNodes[i];
-			mCurHashMapNodeNum = i;
-			mCurHashNodeKey = 0;
-			//return mCurHashNodep->mData[0];
-			return;
-		}
-	}
-
-	// Completely empty!
-	mCurHashNodep = NULL;
-	//return mNull;
-	return;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline BOOL LLUUIDHashMapIter<DATA_TYPE, SIZE>::done() const
-{
-	return mCurHashNodep ? FALSE : TRUE;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline void LLUUIDHashMapIter<DATA_TYPE, SIZE>::next()
-{
-	// No current entry, this iterator is done
-	if (!mCurHashNodep)
-	{
-		//return mNull;
-		return;
-	}
-
-	// Go to the next element
-	mCurHashNodeKey++;
-	if (mCurHashNodeKey < mCurHashNodep->mCount)
-	{
-		// We're not done with this node, return the current element
-		//return mCurHashNodep->mData[mCurHashNodeKey];
-		return;
-	}
-
-	// Done with this node, move to the next
-	mCurHashNodep = mCurHashNodep->mNextNodep;
-	if (mCurHashNodep)
-	{
-		// Return the first element
-		mCurHashNodeKey = 0;
-		//return mCurHashNodep->mData[0];
-		return;
-	}
-
-	// Find the next non-empty node (keyed on the first byte)
-	mCurHashMapNodeNum++;
-
-	S32 i;
-	for (i = mCurHashMapNodeNum; i < 256; i++)
-	{
-		if (mHashMapp->mNodes[i].mCount)
-		{
-			// We found one that wasn't empty
-			mCurHashNodep = &mHashMapp->mNodes[i];
-			mCurHashMapNodeNum = i;
-			mCurHashNodeKey = 0;
-			//return mCurHashNodep->mData[0];
-			return;
-		}
-	}
-
-	// OK, we're done, nothing else to iterate
-	mCurHashNodep = NULL;
-	mHashMapp->mIterCount--; // Decrement since we're safe to do removes now
-	//return mNull;
-}
-
-#endif // LL_LLUUIDHASHMAP_H
-- 
cgit v1.2.3


From bdc6d58b7e84bc81977148995b0028f7420eee65 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 11 Apr 2013 19:12:27 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 added ability to query periodic timer for specific number of periods used
 that to do smaller time averaged window for camera speed

---
 indra/llcommon/lltracerecording.h | 74 +++++++++++++++++++++++++--------------
 1 file changed, 48 insertions(+), 26 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 9ebcbdd8ce..6cf6f4f84f 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -297,63 +297,80 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename T::value_t getPeriodMin(const TraceType<T>& stat) const
+		typename T::value_t getPeriodMin(const TraceType<T>& stat, U32 num_periods = S32_MAX) const
 		{
+			size_t total_periods = mRecordingPeriods.size();
+			num_periods = llmin(num_periods, total_periods);
+
 			typename T::value_t min_val = (std::numeric_limits<typename T::value_t>::max)();
-			U32 num_periods = mRecordingPeriods.size();
-			for (S32 i = 0; i < num_periods; i++)
+			for (S32 i = 1; i <= num_periods; i++)
 			{
-				min_val = llmin(min_val, mRecordingPeriods[(mCurPeriod + i) % num_periods].getSum(stat));
+				S32 index = (mCurPeriod + total_periods - i) % total_periods;
+				min_val = llmin(min_val, mRecordingPeriods[index].getSum(stat));
 			}
 			return min_val;
 		}
 
 		template <typename T>
-		F64 getPeriodMinPerSec(const TraceType<T>& stat) const
+		F64 getPeriodMinPerSec(const TraceType<T>& stat, U32 num_periods = S32_MAX) const
 		{
+			size_t total_periods = mRecordingPeriods.size();
+			num_periods = llmin(num_periods, total_periods);
+
 			F64 min_val = (std::numeric_limits<F64>::max)();
-			U32 num_periods = mRecordingPeriods.size();
-			for (S32 i = 0; i < num_periods; i++)
+			for (S32 i = 1; i <= num_periods; i++)
 			{
-				min_val = llmin(min_val, mRecordingPeriods[(mCurPeriod + i) % num_periods].getPerSec(stat));
+				S32 index = (mCurPeriod + total_periods - i) % total_periods;
+				min_val = llmin(min_val, mRecordingPeriods[index].getPerSec(stat));
 			}
 			return min_val;
 		}
 
 		template <typename T>
-		typename T::value_t getPeriodMax(const TraceType<T>& stat) const
+		typename T::value_t getPeriodMax(const TraceType<T>& stat, U32 num_periods = S32_MAX) const
 		{
+			size_t total_periods = mRecordingPeriods.size();
+			num_periods = llmin(num_periods, total_periods);
+
 			typename T::value_t max_val = (std::numeric_limits<typename T::value_t>::min)();
-			U32 num_periods = mRecordingPeriods.size();
-			for (S32 i = 0; i < num_periods; i++)
+			for (S32 i = 1; i <= num_periods; i++)
 			{
-				max_val = llmax(max_val, mRecordingPeriods[(mCurPeriod + i) % num_periods].getSum(stat));
+				S32 index = (mCurPeriod + total_periods - i) % total_periods;
+				max_val = llmax(max_val, mRecordingPeriods[index].getSum(stat));
 			}
 			return max_val;
 		}
 
 		template <typename T>
-		F64 getPeriodMaxPerSec(const TraceType<T>& stat) const
+		F64 getPeriodMaxPerSec(const TraceType<T>& stat, U32 num_periods = S32_MAX) const
 		{
+			size_t total_periods = mRecordingPeriods.size();
+			num_periods = llmin(num_periods, total_periods);
+
 			F64 max_val = (std::numeric_limits<F64>::min)();
-			U32 num_periods = mRecordingPeriods.size();
-			for (S32 i = 1; i < num_periods; i++)
+			for (S32 i = 1; i <= num_periods; i++)
 			{
-				max_val = llmax(max_val, mRecordingPeriods[(mCurPeriod + i) % num_periods].getPerSec(stat));
+				S32 index = (mCurPeriod + total_periods - i) % total_periods;
+				max_val = llmax(max_val, mRecordingPeriods[index].getPerSec(stat));
 			}
 			return max_val;
 		}
 
 		template <typename T>
-		typename T::value_t getPeriodMean(const TraceType<T>& stat) const
+		typename T::value_t getPeriodMean(const TraceType<T>& stat, U32 num_periods = S32_MAX) const
 		{
+			size_t total_periods = mRecordingPeriods.size();
+			num_periods = llmin(num_periods, total_periods);
+
 			typename T::value_t mean = 0.0;
-			U32 num_periods = mRecordingPeriods.size();
-			for (S32 i = 0; i < num_periods; i++)
+			if (num_periods <= 0) { return mean; }
+
+			for (S32 i = 1; i <= num_periods; i++)
 			{
-				if (mRecordingPeriods[(mCurPeriod + i) % num_periods].getDuration() > 0.f)
+				S32 index = (mCurPeriod + total_periods - i) % total_periods;
+				if (mRecordingPeriods[index].getDuration() > 0.f)
 				{
-					mean += mRecordingPeriods[(mCurPeriod + i) % num_periods].getSum(stat);
+					mean += mRecordingPeriods[index].getSum(stat);
 				}
 			}
 			mean /= num_periods;
@@ -361,15 +378,20 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename T::value_t getPeriodMeanPerSec(const TraceType<T>& stat) const
+		typename T::value_t getPeriodMeanPerSec(const TraceType<T>& stat, U32 num_periods = S32_MAX) const
 		{
+			size_t total_periods = mRecordingPeriods.size();
+			num_periods = llmin(num_periods, total_periods);
+
 			typename T::value_t mean = 0.0;
-			U32 num_periods = mRecordingPeriods.size();
-			for (S32 i = 0; i < num_periods; i++)
+			if (num_periods <= 0) { return mean; }
+
+			for (S32 i = 1; i <= num_periods; i++)
 			{
-				if (mRecordingPeriods[i].getDuration() > 0.f)
+				S32 index = (mCurPeriod + total_periods - i) % total_periods;
+				if (mRecordingPeriods[index].getDuration() > 0.f)
 				{
-					mean += mRecordingPeriods[(mCurPeriod + i) % num_periods].getPerSec(stat);
+					mean += mRecordingPeriods[index].getPerSec(stat);
 				}
 			}
 			mean /= num_periods;
-- 
cgit v1.2.3


From f964c8faa84cfa95bbf73552e99a2d0b80f7bee2 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 12 Apr 2013 11:47:15 -0700
Subject: BUILDFIX: attempted gcc fix

---
 indra/llcommon/lltracerecording.h | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 6cf6f4f84f..1412d78a56 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -297,7 +297,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename T::value_t getPeriodMin(const TraceType<T>& stat, U32 num_periods = S32_MAX) const
+		typename T::value_t getPeriodMin(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
@@ -312,7 +312,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		F64 getPeriodMinPerSec(const TraceType<T>& stat, U32 num_periods = S32_MAX) const
+		F64 getPeriodMinPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
@@ -327,7 +327,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename T::value_t getPeriodMax(const TraceType<T>& stat, U32 num_periods = S32_MAX) const
+		typename T::value_t getPeriodMax(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
@@ -342,7 +342,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		F64 getPeriodMaxPerSec(const TraceType<T>& stat, U32 num_periods = S32_MAX) const
+		F64 getPeriodMaxPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
@@ -357,7 +357,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename T::value_t getPeriodMean(const TraceType<T>& stat, U32 num_periods = S32_MAX) const
+		typename T::value_t getPeriodMean(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
@@ -378,7 +378,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename T::value_t getPeriodMeanPerSec(const TraceType<T>& stat, U32 num_periods = S32_MAX) const
+		typename T::value_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
-- 
cgit v1.2.3


From 54d7fc95893d1bf8cc3b6ebe94f3bf37f40125d0 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 12 Apr 2013 14:25:40 -0700
Subject: BUILDFIX: attempted gcc fix

---
 indra/llcommon/lltrace.h          | 5 +++++
 indra/llcommon/lltracerecording.h | 4 ++--
 2 files changed, 7 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 376248c87a..d1edaf969b 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -264,6 +264,7 @@ class MeasurementAccumulator
 {
 public:
 	typedef T value_t;
+	typedef F64 mean_t;
 	typedef MeasurementAccumulator<T> self_t;
 
 	MeasurementAccumulator()
@@ -380,6 +381,7 @@ class CountAccumulator
 public:
 	typedef CountAccumulator<T> self_t;
 	typedef T value_t;
+	typedef F64 mean_t;
 
 	CountAccumulator()
 	:	mSum(0),
@@ -418,17 +420,20 @@ class TimeBlockAccumulator
 {
 public:
 	typedef LLUnit<LLUnits::Seconds, F64> value_t;
+	typedef LLUnit<LLUnits::Seconds, F64> mean_t;
 	typedef TimeBlockAccumulator self_t;
 
 	// fake class that allows us to view call count aspect of timeblock accumulator
 	struct CallCountAspect 
 	{
 		typedef U32 value_t;
+		typedef F32 mean_t;
 	};
 
 	struct SelfTimeAspect
 	{
 		typedef LLUnit<LLUnits::Seconds, F64> value_t;
+		typedef LLUnit<LLUnits::Seconds, F64> mean_t;
 	};
 
 	TimeBlockAccumulator();
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 1412d78a56..14018bc48f 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -362,7 +362,7 @@ namespace LLTrace
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
 
-			typename T::value_t mean = 0.0;
+			typename T::value_t mean = T::value_t();
 			if (num_periods <= 0) { return mean; }
 
 			for (S32 i = 1; i <= num_periods; i++)
@@ -383,7 +383,7 @@ namespace LLTrace
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
 
-			typename T::value_t mean = 0.0;
+			typename T::value_t mean = T::value_t();
 			if (num_periods <= 0) { return mean; }
 
 			for (S32 i = 1; i <= num_periods; i++)
-- 
cgit v1.2.3


From c9470856473097247c5f0290929e11007e572111 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 12 Apr 2013 15:25:10 -0700
Subject: BUILDFIX: attempted gcc fix

---
 indra/llcommon/lltracerecording.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 14018bc48f..765a510dbb 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -362,7 +362,7 @@ namespace LLTrace
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
 
-			typename T::value_t mean = T::value_t();
+			typename T::value_t mean = typename T::value_t();
 			if (num_periods <= 0) { return mean; }
 
 			for (S32 i = 1; i <= num_periods; i++)
@@ -383,7 +383,7 @@ namespace LLTrace
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
 
-			typename T::value_t mean = T::value_t();
+			typename T::value_t mean = typename T::value_t();
 			if (num_periods <= 0) { return mean; }
 
 			for (S32 i = 1; i <= num_periods; i++)
-- 
cgit v1.2.3


From 39d8ea6327ad96b4977dfec991a20d66e2442b50 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 12 Apr 2013 15:55:34 -0700
Subject: BUILDFIX: attempted gcc fix

---
 indra/llcommon/lltracerecording.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 765a510dbb..511db0e115 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -362,7 +362,7 @@ namespace LLTrace
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
 
-			typename T::value_t mean = typename T::value_t();
+			typename T::mean_t mean = typename T::mean_t();
 			if (num_periods <= 0) { return mean; }
 
 			for (S32 i = 1; i <= num_periods; i++)
@@ -383,7 +383,7 @@ namespace LLTrace
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
 
-			typename T::value_t mean = typename T::value_t();
+			typename T::mean_t mean = typename T::mean_t();
 			if (num_periods <= 0) { return mean; }
 
 			for (S32 i = 1; i <= num_periods; i++)
-- 
cgit v1.2.3


From 08b061dc1d9bfef8fc36ac25f260b291adda6d8c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 12 Apr 2013 16:34:38 -0700
Subject: BUILDFIX: attempted gcc fix

---
 indra/llcommon/lltracerecording.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 511db0e115..8a278d80b0 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -357,7 +357,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename T::value_t getPeriodMean(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
+		typename T::mean_t getPeriodMean(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
@@ -378,7 +378,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename T::value_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
+		typename T::mean_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
-- 
cgit v1.2.3


From cc7d92147c4a4502ec2ac04f150e94a4ac18f79e Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 19 Apr 2013 20:09:00 -0700
Subject: SH-4080 WIP interesting: random crash on Mac removed unused dll
 support from llinstancetracker as it didn't appear to be thread safe

---
 indra/llcommon/llinstancetracker.cpp | 16 ----------------
 indra/llcommon/llinstancetracker.h   | 20 ++------------------
 2 files changed, 2 insertions(+), 34 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp
index 071a637cda..7ff8324fe3 100644
--- a/indra/llcommon/llinstancetracker.cpp
+++ b/indra/llcommon/llinstancetracker.cpp
@@ -34,22 +34,6 @@
 // external library headers
 // other Linden headers
 
-//static 
-void * & LLInstanceTrackerBase::getInstances(std::type_info const & info)
-{
-	typedef std::map<std::string, void *> InstancesMap;
-	static InstancesMap instances;
-
-	// std::map::insert() is just what we want here. You attempt to insert a
-	// (key, value) pair. If the specified key doesn't yet exist, it inserts
-	// the pair and returns a std::pair of (iterator, true). If the specified
-	// key DOES exist, insert() simply returns (iterator, false). One lookup
-	// handles both cases.
-	return instances.insert(InstancesMap::value_type(info.name(),
-													 InstancesMap::mapped_type()))
-		.first->second;
-}
-
 void LLInstanceTrackerBase::StaticBase::incrementDepth()
 {
 	apr_atomic_inc32(&sIterationNestDepth);
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 9dd6d4a7ed..596bea548d 100644
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -46,22 +46,6 @@
 class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable
 {
 protected:
-	/// Get a process-unique void* pointer slot for the specified type_info
-	static void * & getInstances(std::type_info const & info);
-
-	/// Find or create a STATICDATA instance for the specified TRACKED class.
-	/// STATICDATA must be default-constructible.
-	template<typename STATICDATA, class TRACKED>
-	static STATICDATA& getStatic()
-	{
-		void *& instances = getInstances(typeid(TRACKED));
-		if (! instances)
-		{
-			instances = new STATICDATA;
-		}
-		return *static_cast<STATICDATA*>(instances);
-	}
-
     /// It's not essential to derive your STATICDATA (for use with
     /// getStatic()) from StaticBase; it's just that both known
     /// implementations do.
@@ -92,7 +76,7 @@ class LLInstanceTracker : public LLInstanceTrackerBase
 	{
 		InstanceMap sMap;
 	};
-	static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); }
+	static StaticData& getStatic() { static StaticData sData; return sData;}
 	static InstanceMap& getMap_() { return getStatic().sMap; }
 
 public:
@@ -240,7 +224,7 @@ class LLInstanceTracker<T, void> : public LLInstanceTrackerBase
 	{
 		InstanceSet sSet;
 	};
-	static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); }
+	static StaticData& getStatic() { static StaticData sData; return sData; }
 	static InstanceSet& getSet_() { return getStatic().sSet; }
 
 public:
-- 
cgit v1.2.3


From 62c8844414b84ee9e8cc488f4e02cbaed5f67a14 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sun, 21 Apr 2013 23:10:03 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 added ExtendablePeriodicRecording and ability to append periodic recordings
 to each other

---
 indra/llcommon/llinstancetracker.h  |  10 ++-
 indra/llcommon/lltracerecording.cpp | 136 ++++++++++++++++++++++++++++++++++++
 indra/llcommon/lltracerecording.h   |  28 +++++++-
 3 files changed, 170 insertions(+), 4 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 596bea548d..a79ddd088d 100644
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -67,6 +67,7 @@ protected:
 /// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
 /// If KEY is not provided, then instances are stored in a simple set
 /// @NOTE: see explicit specialization below for default KEY==void case
+/// @NOTE: this class is not thread-safe unless used as read-only
 template<typename T, typename KEY = void>
 class LLInstanceTracker : public LLInstanceTrackerBase
 {
@@ -120,13 +121,13 @@ public:
 		typedef boost::iterator_facade<key_iter, KEY, boost::forward_traversal_tag> super_t;
 
 		key_iter(typename InstanceMap::iterator it)
-			:	mIterator(it)
+		:	mIterator(it)
 		{
 			getStatic().incrementDepth();
 		}
 
 		key_iter(const key_iter& other)
-			:	mIterator(other.mIterator)
+		:	mIterator(other.mIterator)
 		{
 			getStatic().incrementDepth();
 		}
@@ -171,7 +172,10 @@ public:
 		return instance_iter(getMap_().end());
 	}
 
-	static S32 instanceCount() { return getMap_().size(); }
+	static S32 instanceCount() 
+	{ 
+		return getMap_().size(); 
+	}
 
 	static key_iter beginKeys()
 	{
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 21156b4d61..2917c217d7 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -396,6 +396,76 @@ void PeriodicRecording::nextPeriod()
 	}
 }
 
+
+void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
+{
+	if (other.mRecordingPeriods.size() < 2) return;
+
+	EPlayState play_state = getPlayState();
+	pause();
+
+	EPlayState other_play_state = other.getPlayState();
+	other.pause();
+
+	if (mAutoResize)
+	{
+		// copy everything after current period of other recording to end of buffer
+		// this will only apply if other recording is using a fixed circular buffer
+		if (other.mCurPeriod < other.mRecordingPeriods.size() - 1)
+		{
+			std::copy(	other.mRecordingPeriods.begin() + other.mCurPeriod + 1,
+						other.mRecordingPeriods.end(),
+						std::back_inserter(mRecordingPeriods));
+		}
+
+		// copy everything from beginning of other recording's buffer up to, but not including
+		// current period
+		std::copy(	other.mRecordingPeriods.begin(),
+					other.mRecordingPeriods.begin() + other.mCurPeriod,
+					std::back_inserter(mRecordingPeriods));
+
+		mCurPeriod = mRecordingPeriods.size() - 1;
+	}
+	else
+	{
+		size_t num_to_copy = llmin(	mRecordingPeriods.size(), other.mRecordingPeriods.size() );
+		std::vector<Recording>::iterator src_it = other.mRecordingPeriods.begin() 
+													+ (	(other.mCurPeriod + 1)									// cur 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;
+
+			if (++src_it == other.mRecordingPeriods.end())
+			{
+				src_it = other.mRecordingPeriods.begin();
+			}
+
+			if (++dest_it == mRecordingPeriods.end())
+			{
+				dest_it = mRecordingPeriods.begin();
+			}
+		}
+		
+		mCurPeriod = (mCurPeriod + num_to_copy) % mRecordingPeriods.size();
+	}
+
+	// if copying from periodic recording that wasn't active advance our period to the next available one
+	// otherwise continue recording on top of the last period of data received from the other recording
+	if (other_play_state != STARTED)
+	{
+		nextPeriod();
+	}
+
+	setPlayState(play_state);
+	other.setPlayState(other_play_state);
+}
+
+
+
 void PeriodicRecording::start()
 {
 	getCurRecording().start();
@@ -503,6 +573,72 @@ void ExtendableRecording::splitFrom(ExtendableRecording& other)
 	mPotentialRecording.splitFrom(other.mPotentialRecording);
 }
 
+///////////////////////////////////////////////////////////////////////
+// ExtendablePeriodicRecording
+///////////////////////////////////////////////////////////////////////
+
+void ExtendablePeriodicRecording::extend()
+{
+	// stop recording to get latest data
+	mPotentialRecording.stop();
+	// 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());
+}
+
+void ExtendablePeriodicRecording::start()
+{
+	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::start();
+	mPotentialRecording.start();
+}
+
+void ExtendablePeriodicRecording::stop()
+{
+	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::stop();
+	mPotentialRecording.stop();
+}
+
+void ExtendablePeriodicRecording::pause()
+{
+	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::pause();
+	mPotentialRecording.pause();
+}
+
+void ExtendablePeriodicRecording::resume()
+{
+	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::resume();
+	mPotentialRecording.resume();
+}
+
+void ExtendablePeriodicRecording::restart()
+{
+	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::restart();
+	mAcceptedRecording.reset();
+	mPotentialRecording.restart();
+}
+
+void ExtendablePeriodicRecording::reset()
+{
+	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::reset();
+	mAcceptedRecording.reset();
+	mPotentialRecording.reset();
+}
+
+void ExtendablePeriodicRecording::splitTo(ExtendablePeriodicRecording& other)
+{
+	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::splitTo(other);
+	mPotentialRecording.splitTo(other.mPotentialRecording);
+}
+
+void ExtendablePeriodicRecording::splitFrom(ExtendablePeriodicRecording& other)
+{
+	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::splitFrom(other);
+	mPotentialRecording.splitFrom(other.mPotentialRecording);
+}
+
 PeriodicRecording& get_frame_recording()
 {
 	static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(1000, PeriodicRecording::STARTED));
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 7c4113dbf0..23b031b49b 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -254,6 +254,8 @@ namespace LLTrace
 		void nextPeriod();
 		U32 getNumPeriods() { return mRecordingPeriods.size(); }
 
+		void appendPeriodicRecording(PeriodicRecording& other);
+
 		Recording& getLastRecording()
 		{
 			U32 num_periods = mRecordingPeriods.size();
@@ -424,6 +426,7 @@ namespace LLTrace
 		void extend();
 
 		Recording& getAcceptedRecording() { return mAcceptedRecording; }
+		const Recording& getAcceptedRecording() const {return mAcceptedRecording;}
 
 		// implementation for LLStopWatchControlsMixin
 		/*virtual*/ void start();
@@ -435,11 +438,34 @@ namespace LLTrace
 		/*virtual*/ void splitTo(ExtendableRecording& other);
 		/*virtual*/ void splitFrom(ExtendableRecording& other);
 
-		const Recording& getAcceptedRecording() const {return mAcceptedRecording;}
 	private:
 		Recording mAcceptedRecording;
 		Recording mPotentialRecording;
 	};
+
+	class ExtendablePeriodicRecording
+	:	public LLStopWatchControlsMixin<ExtendablePeriodicRecording>
+	{
+	public:
+		void extend();
+
+		PeriodicRecording& getAcceptedRecording() { return mAcceptedRecording; }
+		const PeriodicRecording& getAcceptedRecording() const {return mAcceptedRecording;}
+
+		// implementation for LLStopWatchControlsMixin
+		/*virtual*/ void start();
+		/*virtual*/ void stop();
+		/*virtual*/ void pause();
+		/*virtual*/ void resume();
+		/*virtual*/ void restart();
+		/*virtual*/ void reset();
+		/*virtual*/ void splitTo(ExtendablePeriodicRecording& other);
+		/*virtual*/ void splitFrom(ExtendablePeriodicRecording& other);
+
+	private:
+		PeriodicRecording mAcceptedRecording;
+		PeriodicRecording mPotentialRecording;
+	};
 }
 
 #endif // LL_LLTRACERECORDING_H
-- 
cgit v1.2.3


From c6737163854981d94fde8bdd440eaf4bbc816b4f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 23 Apr 2013 18:52:34 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 convert scene monitor to use extendable periodic recording

---
 indra/llcommon/lltracerecording.cpp | 61 +++++++++++++++++++++++++++++++++++++
 indra/llcommon/lltracerecording.h   | 56 ++++++++--------------------------
 2 files changed, 73 insertions(+), 44 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 2917c217d7..af7b61dd4e 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -464,8 +464,62 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 	other.setPlayState(other_play_state);
 }
 
+LLUnit<LLUnits::Seconds, F64> PeriodicRecording::getDuration()
+{
+	LLUnit<LLUnits::Seconds, F64> duration;
+	size_t num_periods = mRecordingPeriods.size();
+	for (size_t i = 1; i <= num_periods; i++)
+	{
+		size_t index = (mCurPeriod + num_periods - i) % num_periods;
+		duration += mRecordingPeriods[index].getDuration();
+	}
+	return duration;
+}
 
 
+LLTrace::Recording PeriodicRecording::snapshotCurRecording() const
+{
+	Recording recording_copy(getCurRecording());
+	recording_copy.stop();
+	return recording_copy;
+}
+
+
+Recording& PeriodicRecording::getLastRecording()
+{
+	U32 num_periods = mRecordingPeriods.size();
+	return mRecordingPeriods[(mCurPeriod + num_periods - 1) % num_periods];
+}
+
+const Recording& PeriodicRecording::getLastRecording() const
+{
+	return getPrevRecording(1);
+}
+
+Recording& PeriodicRecording::getCurRecording()
+{
+	return mRecordingPeriods[mCurPeriod];
+}
+
+const Recording& PeriodicRecording::getCurRecording() const
+{
+	return mRecordingPeriods[mCurPeriod];
+}
+
+Recording& PeriodicRecording::getPrevRecording( U32 offset )
+{
+	U32 num_periods = mRecordingPeriods.size();
+	offset = llclamp(offset, 0u, num_periods - 1);
+	return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
+}
+
+const Recording& PeriodicRecording::getPrevRecording( U32 offset ) const
+{
+	U32 num_periods = mRecordingPeriods.size();
+	offset = llclamp(offset, 0u, num_periods - 1);
+	return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
+}
+
 void PeriodicRecording::start()
 {
 	getCurRecording().start();
@@ -577,6 +631,13 @@ void ExtendableRecording::splitFrom(ExtendableRecording& other)
 // ExtendablePeriodicRecording
 ///////////////////////////////////////////////////////////////////////
 
+
+ExtendablePeriodicRecording::ExtendablePeriodicRecording() 
+:	mAcceptedRecording(0), 
+	mPotentialRecording(0)
+{
+}
+
 void ExtendablePeriodicRecording::extend()
 {
 	// stop recording to get latest data
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 23b031b49b..84006a10b8 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -254,49 +254,16 @@ namespace LLTrace
 		void nextPeriod();
 		U32 getNumPeriods() { return mRecordingPeriods.size(); }
 
-		void appendPeriodicRecording(PeriodicRecording& other);
-
-		Recording& getLastRecording()
-		{
-			U32 num_periods = mRecordingPeriods.size();
-			return mRecordingPeriods[(mCurPeriod + num_periods - 1) % num_periods];
-		}
-
-		const Recording& getLastRecording() const
-		{
-			return getPrevRecording(1);
-		}
-
-		Recording& getCurRecording()
-		{
-			return mRecordingPeriods[mCurPeriod];
-		}
-
-		const Recording& getCurRecording() const
-		{
-			return mRecordingPeriods[mCurPeriod];
-		}
-
-		Recording& getPrevRecording(U32 offset)
-		{
-			U32 num_periods = mRecordingPeriods.size();
-			offset = llclamp(offset, 0u, num_periods - 1);
-			return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
-		}
+		LLUnit<LLUnits::Seconds, F64> getDuration();
 
-		const Recording& getPrevRecording(U32 offset) const
-		{
-			U32 num_periods = mRecordingPeriods.size();
-			offset = llclamp(offset, 0u, num_periods - 1);
-			return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
-		}
-
-		Recording snapshotCurRecording() const
-		{
-			Recording recording_copy(getCurRecording());
-			recording_copy.stop();
-			return recording_copy;
-		}
+		void appendPeriodicRecording(PeriodicRecording& other);
+		Recording& getLastRecording();
+		const Recording& getLastRecording() const;
+		Recording& getCurRecording();
+		const Recording& getCurRecording() const;
+		Recording& getPrevRecording(U32 offset);
+		const Recording& getPrevRecording(U32 offset) const;
+		Recording snapshotCurRecording() const;
 
 		template <typename T>
 		typename T::value_t getPeriodMin(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
@@ -447,10 +414,11 @@ namespace LLTrace
 	:	public LLStopWatchControlsMixin<ExtendablePeriodicRecording>
 	{
 	public:
+		ExtendablePeriodicRecording();
 		void extend();
 
-		PeriodicRecording& getAcceptedRecording() { return mAcceptedRecording; }
-		const PeriodicRecording& getAcceptedRecording() const {return mAcceptedRecording;}
+		PeriodicRecording& getAcceptedRecording()				{ return mAcceptedRecording; }
+		const PeriodicRecording& getAcceptedRecording() const	{return mAcceptedRecording;}
 
 		// implementation for LLStopWatchControlsMixin
 		/*virtual*/ void start();
-- 
cgit v1.2.3


From 84af0e9852486231b5ef0cde7ad1704d41689a3a Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 24 Apr 2013 14:13:45 -0700
Subject: SH-4080 WIP interesting: random crash on Mac potential fix for
 crasher cleaned up llsingleton

---
 indra/llcommon/llsingleton.cpp      |  1 -
 indra/llcommon/llsingleton.h        | 74 +++++++++----------------------------
 indra/llcommon/lltracerecording.cpp |  4 ++
 3 files changed, 22 insertions(+), 57 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp
index eb8e2c9456..9b49e52377 100644
--- a/indra/llcommon/llsingleton.cpp
+++ b/indra/llcommon/llsingleton.cpp
@@ -28,5 +28,4 @@
 
 #include "llsingleton.h"
 
-std::map<std::string, void *> * LLSingletonRegistry::sSingletonMap = NULL;
 
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index f6b0a7194b..697d1b042a 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -30,38 +30,6 @@
 #include <typeinfo>
 #include <boost/noncopyable.hpp>
 
-/// @brief A global registry of all singletons to prevent duplicate allocations
-/// across shared library boundaries
-class LL_COMMON_API LLSingletonRegistry {
-	private:
-		typedef std::map<std::string, void *> TypeMap;
-		static TypeMap * sSingletonMap;
-
-		static void checkInit()
-		{
-			if(sSingletonMap == NULL)
-			{
-				sSingletonMap = new TypeMap();
-			}
-		}
-
-	public:
-		template<typename T> static void * & get()
-		{
-			std::string name(typeid(T).name());
-
-			checkInit();
-
-			// the first entry of the pair returned by insert will be either the existing
-			// iterator matching our key, or the newly inserted NULL initialized entry
-			// see "Insert element" in http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
-			TypeMap::iterator result =
-				sSingletonMap->insert(std::make_pair(name, (void*)NULL)).first;
-
-			return result->second;
-		}
-};
-
 // LLSingleton implements the getInstance() method part of the Singleton
 // pattern. It can't make the derived class constructors protected, though, so
 // you have to do that yourself.
@@ -90,10 +58,9 @@ template <typename DERIVED_TYPE>
 class LLSingleton : private boost::noncopyable
 {
 	
-protected:
+private:
 	typedef enum e_init_state
 	{
-		UNINITIALIZED,
 		CONSTRUCTING,
 		INITIALIZING,
 		INITIALIZED,
@@ -109,8 +76,11 @@ protected:
 		
 		SingletonInstanceData()
 		:	mSingletonInstance(NULL),
-			mInitState(UNINITIALIZED)
-		{}
+			mInitState(CONSTRUCTING)
+		{
+			mSingletonInstance = new DERIVED_TYPE(); 
+			mInitState = INITIALIZING;
+		}
 
 		~SingletonInstanceData()
 		{
@@ -151,12 +121,12 @@ public:
 	 */
 	static void deleteSingleton()
 	{
-		SingletonInstanceData& data = getSingletonData();
-		delete data.mSingletonInstance;
-		data.mSingletonInstance = NULL;
-		data.mInitState = DELETED;
+		delete getSingletonData().mSingletonInstance;
+		getSingletonData().mSingletonInstance = NULL;
+		getSingletonData().mInitState = DELETED;
 	}
 
+
 	static DERIVED_TYPE* getInstance()
 	{
 		SingletonInstanceData& data = getSingletonData();
@@ -171,13 +141,11 @@ public:
 			llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
 		}
 		
-		if (!data.mSingletonInstance) 
+		if (data.mInitState == INITIALIZING) 
 		{
-			data.mInitState = CONSTRUCTING;
-			data.mSingletonInstance = new DERIVED_TYPE(); 
-			data.mInitState = INITIALIZING;
-			data.mSingletonInstance->initSingleton(); 
+			// go ahead and flag ourselves as initialized so we can be reentrant during initialization
 			data.mInitState = INITIALIZED;	
+			data.mSingletonInstance->initSingleton(); 
 		}
 		
 		return data.mSingletonInstance;
@@ -185,7 +153,7 @@ public:
 
 	static DERIVED_TYPE* getIfExists()
 	{
-		SingletonInstanceData& data = getSingletonData();
+		SingletonInstanceData& data = getData();
 		return data.mSingletonInstance;
 	}
 
@@ -211,20 +179,14 @@ public:
 	}
 
 private:
+
 	static SingletonInstanceData& getSingletonData()
 	{
 		// this is static to cache the lookup results
-		static void * & registry = LLSingletonRegistry::get<DERIVED_TYPE>();
-
-		// *TODO - look into making this threadsafe
-		if(NULL == registry)
-		{
-			static SingletonInstanceData data;
-			registry = &data;
-		}
-
-		return *static_cast<SingletonInstanceData *>(registry);
+		static SingletonInstanceData sData;
+		return sData;
 	}
+
 	virtual void initSingleton() {}
 };
 
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index af7b61dd4e..e562f2bce2 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -362,6 +362,10 @@ PeriodicRecording::PeriodicRecording( U32 num_periods, EPlayState state)
 :	mAutoResize(num_periods == 0),
 	mCurPeriod(0)
 {
+	if (mAutoResize) 
+	{
+		num_periods = 1;
+	}
 	if (num_periods)
 	{
 		mRecordingPeriods.resize(num_periods);
-- 
cgit v1.2.3


From 5622a47403443fb7b4b459fac1b0206deb2eadb3 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 24 Apr 2013 17:44:34 -0700
Subject: BUILDFIX: method name was wrong

---
 indra/llcommon/llsingleton.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 697d1b042a..e3b614cf86 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -153,7 +153,7 @@ public:
 
 	static DERIVED_TYPE* getIfExists()
 	{
-		SingletonInstanceData& data = getData();
+		SingletonInstanceData& data = getSingletonData();
 		return data.mSingletonInstance;
 	}
 
-- 
cgit v1.2.3


From 1a01542e22a7c602b4e2733a42d933600c5e6609 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 24 Apr 2013 21:04:51 -0700
Subject: BUILDFIX: singleton unit test could not resurrect singleton

---
 indra/llcommon/llsingleton.h | 6 ++++++
 1 file changed, 6 insertions(+)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index e3b614cf86..1cbefb1cd0 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -77,6 +77,11 @@ private:
 		SingletonInstanceData()
 		:	mSingletonInstance(NULL),
 			mInitState(CONSTRUCTING)
+		{
+			construct();
+		}
+
+		void construct()
 		{
 			mSingletonInstance = new DERIVED_TYPE(); 
 			mInitState = INITIALIZING;
@@ -139,6 +144,7 @@ public:
 		if (data.mInitState == DELETED)
 		{
 			llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
+			data.construct();
 		}
 		
 		if (data.mInitState == INITIALIZING) 
-- 
cgit v1.2.3


From 81291381f876e7a2c01889ddc3d849d88520af41 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 26 Apr 2013 11:21:16 -0700
Subject: SH-4080 WIP interesting: random crash on Mac fixed Mac crash related
 to non-reentrant singleton constructor

---
 indra/llcommon/llsingleton.h | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 1cbefb1cd0..165344ed19 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -83,8 +83,10 @@ private:
 
 		void construct()
 		{
+			sReentrantConstructorGuard = true;
 			mSingletonInstance = new DERIVED_TYPE(); 
 			mInitState = INITIALIZING;
+			sReentrantConstructorGuard = false;
 		}
 
 		~SingletonInstanceData()
@@ -174,7 +176,7 @@ public:
 	// Use this to avoid accessing singletons before the can safely be constructed
 	static bool instanceExists()
 	{
-		return getSingletonData().mInitState == INITIALIZED;
+		return sReentrantConstructorGuard || getSingletonData().mInitState == INITIALIZED;
 	}
 	
 	// Has this singleton already been deleted?
@@ -194,6 +196,11 @@ private:
 	}
 
 	virtual void initSingleton() {}
+
+	static bool sReentrantConstructorGuard;
 };
 
+template<typename T>
+bool LLSingleton<T>::sReentrantConstructorGuard = false;
+
 #endif
-- 
cgit v1.2.3


From a4e53da0b0d8f227865303a785d3d65848cd4ade Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 26 Apr 2013 16:14:44 -0700
Subject: SH-4080 WIP interesting: random crash on Mac fixed Mac crash related
 to non-reentrant singleton constructor

---
 indra/llcommon/llsingleton.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 165344ed19..829c7e4192 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -176,7 +176,7 @@ public:
 	// Use this to avoid accessing singletons before the can safely be constructed
 	static bool instanceExists()
 	{
-		return sReentrantConstructorGuard || getSingletonData().mInitState == INITIALIZED;
+		return !sReentrantConstructorGuard && getSingletonData().mInitState == INITIALIZED;
 	}
 	
 	// Has this singleton already been deleted?
-- 
cgit v1.2.3


From 215612bde86969e49ff9577d1d64390696280b3e Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sat, 27 Apr 2013 07:42:32 -0700
Subject: SH-4080 WIP interesting: random crash on Mac more singleton cleanup
 to eliminate crashes on startup/exit

---
 indra/llcommon/llsingleton.h | 95 +++++++++++++++++++++-----------------------
 1 file changed, 45 insertions(+), 50 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 829c7e4192..7558bf4fae 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -61,6 +61,7 @@ class LLSingleton : private boost::noncopyable
 private:
 	typedef enum e_init_state
 	{
+		UNINITIALIZED,
 		CONSTRUCTING,
 		INITIALIZING,
 		INITIALIZED,
@@ -68,30 +69,23 @@ private:
 	} EInitState;
 	
 	// stores pointer to singleton instance
-	// and tracks initialization state of singleton
-	struct SingletonInstanceData
+	struct SingletonLifetimeManager
 	{
-		EInitState		mInitState;
-		DERIVED_TYPE*	mSingletonInstance;
-		
-		SingletonInstanceData()
-		:	mSingletonInstance(NULL),
-			mInitState(CONSTRUCTING)
+		SingletonLifetimeManager()
 		{
 			construct();
 		}
 
-		void construct()
+		static void construct()
 		{
-			sReentrantConstructorGuard = true;
-			mSingletonInstance = new DERIVED_TYPE(); 
-			mInitState = INITIALIZING;
-			sReentrantConstructorGuard = false;
+			sData.mInitState = CONSTRUCTING;
+			sData.mInstance = new DERIVED_TYPE(); 
+			sData.mInitState = INITIALIZING;
 		}
 
-		~SingletonInstanceData()
+		~SingletonLifetimeManager()
 		{
-			if (mInitState != DELETED)
+			if (sData.mInitState != DELETED)
 			{
 				deleteSingleton();
 			}
@@ -101,9 +95,8 @@ private:
 public:
 	virtual ~LLSingleton()
 	{
-		SingletonInstanceData& data = getSingletonData();
-		data.mSingletonInstance = NULL;
-		data.mInitState = DELETED;
+		sData.mInstance = NULL;
+		sData.mInitState = DELETED;
 	}
 
 	/**
@@ -128,41 +121,45 @@ public:
 	 */
 	static void deleteSingleton()
 	{
-		delete getSingletonData().mSingletonInstance;
-		getSingletonData().mSingletonInstance = NULL;
-		getSingletonData().mInitState = DELETED;
+		delete sData.mInstance;
+		sData.mInstance = NULL;
+		sData.mInitState = DELETED;
 	}
 
 
 	static DERIVED_TYPE* getInstance()
 	{
-		SingletonInstanceData& data = getSingletonData();
+		static SingletonLifetimeManager sLifeTimeMgr;
 
-		if (data.mInitState == CONSTRUCTING)
+		switch (sData.mInitState)
 		{
+		case UNINITIALIZED:
+			// should never be uninitialized at this point
+			llassert(false);
+			break;
+		case CONSTRUCTING:
 			llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl;
-		}
-
-		if (data.mInitState == DELETED)
-		{
-			llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
-			data.construct();
-		}
-		
-		if (data.mInitState == INITIALIZING) 
-		{
+			break;
+		case INITIALIZING:
 			// go ahead and flag ourselves as initialized so we can be reentrant during initialization
-			data.mInitState = INITIALIZED;	
-			data.mSingletonInstance->initSingleton(); 
+			sData.mInitState = INITIALIZED;	
+			sData.mInstance->initSingleton(); 
+			return sData.mInstance;
+			break;
+		case INITIALIZED:
+			return sData.mInstance;
+		case DELETED:
+			llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
+			SingletonLifetimeManager::construct();
+			return sData.mInstance;
 		}
-		
-		return data.mSingletonInstance;
+
+		return NULL;
 	}
 
 	static DERIVED_TYPE* getIfExists()
 	{
-		SingletonInstanceData& data = getSingletonData();
-		return data.mSingletonInstance;
+		return sData.mInstance;
 	}
 
 	// Reference version of getInstance()
@@ -176,31 +173,29 @@ public:
 	// Use this to avoid accessing singletons before the can safely be constructed
 	static bool instanceExists()
 	{
-		return !sReentrantConstructorGuard && getSingletonData().mInitState == INITIALIZED;
+		return sData.mInitState == INITIALIZED;
 	}
 	
 	// Has this singleton already been deleted?
 	// Use this to avoid accessing singletons from a static object's destructor
 	static bool destroyed()
 	{
-		return getSingletonData().mInitState == DELETED;
+		return sData.mInitState == DELETED;
 	}
 
 private:
 
-	static SingletonInstanceData& getSingletonData()
-	{
-		// this is static to cache the lookup results
-		static SingletonInstanceData sData;
-		return sData;
-	}
-
 	virtual void initSingleton() {}
 
-	static bool sReentrantConstructorGuard;
+	struct SingletonData
+	{
+		EInitState		mInitState;
+		DERIVED_TYPE*	mInstance;
+	};
+	static SingletonData sData;
 };
 
 template<typename T>
-bool LLSingleton<T>::sReentrantConstructorGuard = false;
+typename LLSingleton<T>::SingletonData LLSingleton<T>::sData;
 
 #endif
-- 
cgit v1.2.3


From 41e5bf346eaa0a43646058691cc8090ddfe498e9 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 29 Apr 2013 10:58:37 -0700
Subject: SH-4080 WIP interesting: random crash on Mac fixed singleton unit
 test resurrecting a singleton now properly calls initSingleton()

---
 indra/llcommon/llsingleton.h | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 7558bf4fae..40002313f1 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -136,21 +136,22 @@ public:
 		case UNINITIALIZED:
 			// should never be uninitialized at this point
 			llassert(false);
-			break;
+			return NULL;
 		case CONSTRUCTING:
 			llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl;
-			break;
+			return NULL;
 		case INITIALIZING:
 			// go ahead and flag ourselves as initialized so we can be reentrant during initialization
 			sData.mInitState = INITIALIZED;	
 			sData.mInstance->initSingleton(); 
 			return sData.mInstance;
-			break;
 		case INITIALIZED:
 			return sData.mInstance;
 		case DELETED:
 			llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
 			SingletonLifetimeManager::construct();
+			sData.mInitState = INITIALIZED;	
+			sData.mInstance->initSingleton(); 
 			return sData.mInstance;
 		}
 
-- 
cgit v1.2.3


From dd07e240538ae8eaed07526396069dae82448576 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 2 May 2013 19:38:35 -0700
Subject: SH-4080 WIP interesting: random crash on Mac added comments to
 llsingleton.h

---
 indra/llcommon/llsingleton.h | 5 +++++
 1 file changed, 5 insertions(+)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 40002313f1..1e87d9bd7b 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -143,6 +143,8 @@ public:
 		case INITIALIZING:
 			// go ahead and flag ourselves as initialized so we can be reentrant during initialization
 			sData.mInitState = INITIALIZED;	
+			// initialize singleton after constructing it so that it can reference other singletons which in turn depend on it,
+			// thus breaking cyclic dependencies
 			sData.mInstance->initSingleton(); 
 			return sData.mInstance;
 		case INITIALIZED:
@@ -150,6 +152,7 @@ public:
 		case DELETED:
 			llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
 			SingletonLifetimeManager::construct();
+			// same as first time construction
 			sData.mInitState = INITIALIZED;	
 			sData.mInstance->initSingleton(); 
 			return sData.mInstance;
@@ -190,6 +193,8 @@ private:
 
 	struct SingletonData
 	{
+		// explicitly has a default constructor so that member variables are zero initialized in BSS
+		// and only changed by singleton logic, not constructor running during startup
 		EInitState		mInitState;
 		DERIVED_TYPE*	mInstance;
 	};
-- 
cgit v1.2.3


From 6b81b8629e67d82a7620e48781ded73b6e6126ea Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sun, 5 May 2013 17:45:35 -0700
Subject: Spring cleaning: removed unused .cpp and.h files, and cleaned up
 header dependencies

---
 indra/llcommon/CMakeLists.txt            |   26 +-
 indra/llcommon/doublelinkedlist.h        | 1397 ------------------------------
 indra/llcommon/llassoclist.h             |  296 -------
 indra/llcommon/lldarrayptr.h             |   36 -
 indra/llcommon/lldeleteutils.h           |   47 -
 indra/llcommon/lldepthstack.h            |   34 +-
 indra/llcommon/lldlinked.h               |   93 --
 indra/llcommon/lldqueueptr.h             |  352 --------
 indra/llcommon/llenum.h                  |   78 --
 indra/llcommon/llindexedqueue.h          |  155 ----
 indra/llcommon/lllazy.cpp                |   40 -
 indra/llcommon/lllazy.h                  |  399 ---------
 indra/llcommon/lllocalidhashmap.h        |  895 -------------------
 indra/llcommon/llregistry.h              |   12 +-
 indra/llcommon/llsortedvector.h          |  152 ----
 indra/llcommon/llstack.h                 |   48 -
 indra/llcommon/llthread.h                |    8 +-
 indra/llcommon/lltypeinfolookup.h        |  117 ---
 indra/llcommon/metaclass.cpp             |   81 --
 indra/llcommon/metaclass.h               |   82 --
 indra/llcommon/metaclasst.h              |   60 --
 indra/llcommon/metaproperty.cpp          |   56 --
 indra/llcommon/metaproperty.h            |   73 --
 indra/llcommon/metapropertyt.h           |  183 ----
 indra/llcommon/reflective.cpp            |   40 -
 indra/llcommon/reflective.h              |   42 -
 indra/llcommon/reflectivet.h             |   48 -
 indra/llcommon/tests/reflection_test.cpp |  220 -----
 28 files changed, 30 insertions(+), 5040 deletions(-)
 delete mode 100644 indra/llcommon/doublelinkedlist.h
 delete mode 100644 indra/llcommon/llassoclist.h
 delete mode 100644 indra/llcommon/lldarrayptr.h
 delete mode 100644 indra/llcommon/lldeleteutils.h
 delete mode 100644 indra/llcommon/lldlinked.h
 delete mode 100644 indra/llcommon/lldqueueptr.h
 delete mode 100644 indra/llcommon/llenum.h
 delete mode 100644 indra/llcommon/llindexedqueue.h
 delete mode 100644 indra/llcommon/lllazy.cpp
 delete mode 100644 indra/llcommon/lllazy.h
 delete mode 100644 indra/llcommon/lllocalidhashmap.h
 delete mode 100644 indra/llcommon/llsortedvector.h
 delete mode 100644 indra/llcommon/llstack.h
 delete mode 100644 indra/llcommon/lltypeinfolookup.h
 delete mode 100644 indra/llcommon/metaclass.cpp
 delete mode 100644 indra/llcommon/metaclass.h
 delete mode 100644 indra/llcommon/metaclasst.h
 delete mode 100644 indra/llcommon/metaproperty.cpp
 delete mode 100644 indra/llcommon/metaproperty.h
 delete mode 100644 indra/llcommon/metapropertyt.h
 delete mode 100644 indra/llcommon/reflective.cpp
 delete mode 100644 indra/llcommon/reflective.h
 delete mode 100644 indra/llcommon/reflectivet.h
 delete mode 100644 indra/llcommon/tests/reflection_test.cpp

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 5117224ddb..23a5dc24c0 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -98,7 +98,7 @@ set(llcommon_SOURCE_FILES
     llstringtable.cpp
     llsys.cpp
     llthread.cpp
-	llthreadlocalstorage.cpp
+    llthreadlocalstorage.cpp
     llthreadsafequeue.cpp
     lltimer.cpp
     lltrace.cpp
@@ -107,9 +107,6 @@ set(llcommon_SOURCE_FILES
     lluri.cpp
     lluuid.cpp
     llworkerthread.cpp
-    metaclass.cpp
-    metaproperty.cpp
-    reflective.cpp
     timing.cpp
     u64.cpp
     )
@@ -119,7 +116,6 @@ set(llcommon_HEADER_FILES
 
     bitpack.h
     ctype_workaround.h
-    doublelinkedlist.h
     fix_macros.h
     imageids.h
     indra_constants.h
@@ -133,7 +129,6 @@ set(llcommon_HEADER_FILES
     llapp.h
     llapr.h
     llassettype.h
-    llassoclist.h
     llavatarconstants.h
     llbase32.h
     llbase64.h
@@ -147,18 +142,13 @@ set(llcommon_HEADER_FILES
     llcriticaldamp.h
     llcursortypes.h
     lldarray.h
-    lldarrayptr.h
     lldate.h
     lldefs.h
     lldependencies.h
-    lldeleteutils.h
     lldepthstack.h
     lldictionary.h
-    lldlinked.h
     lldoubledispatch.h
-    lldqueueptr.h
     llendianswizzle.h
-    llenum.h
     llerror.h
     llerrorcontrol.h
     llerrorlegacy.h
@@ -182,18 +172,15 @@ set(llcommon_HEADER_FILES
     llhash.h
     llheartbeat.h
     llhttpstatuscodes.h
-    llindexedqueue.h
     llinitparam.h
     llinstancetracker.h
     llkeythrottle.h
-    lllazy.h
     llleap.h
     llleaplistener.h
     lllistenerwrapper.h
     lllinkedqueue.h
     llliveappconfig.h
     lllivefile.h
-    lllocalidhashmap.h
     lllog.h
     lllslconstants.h
     llmap.h
@@ -228,8 +215,6 @@ set(llcommon_HEADER_FILES
     llsecondlifeurls.h
     llsimplehash.h
     llsingleton.h
-    llsortedvector.h
-    llstack.h
     llstacktrace.h
     llstatenums.h
     llstl.h
@@ -247,7 +232,6 @@ set(llcommon_HEADER_FILES
     lltracerecording.h
     lltracethreadrecorder.h
     lltreeiterators.h
-    lltypeinfolookup.h
     llunit.h
     lluri.h
     lluuid.h
@@ -257,12 +241,6 @@ set(llcommon_HEADER_FILES
     llwin32headerslean.h
     llworkerthread.h
     ll_template_cast.h
-    metaclass.h
-    metaclasst.h
-    metaproperty.h
-    metapropertyt.h
-    reflective.h
-    reflectivet.h
     roles_constants.h
     stdenums.h
     stdtypes.h
@@ -334,7 +312,6 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(llerror "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llinstancetracker "" "${test_libs}")
-  LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llprocessor "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
@@ -343,7 +320,6 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llunits "" "${test_libs}")
-  LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llprocess "" "${test_libs}")
diff --git a/indra/llcommon/doublelinkedlist.h b/indra/llcommon/doublelinkedlist.h
deleted file mode 100644
index 0aeaa69df3..0000000000
--- a/indra/llcommon/doublelinkedlist.h
+++ /dev/null
@@ -1,1397 +0,0 @@
-/** 
- * @file doublelinkedlist.h
- * @brief Provides a standard doubly linked list for fun and profit.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_DOUBLELINKEDLIST_H
-#define LL_DOUBLELINKEDLIST_H
-
-#include "llerror.h"
-#include "llrand.h"
-
-// node that actually contains the data
-template <class DATA_TYPE> class LLDoubleLinkedNode
-{
-public:
-	DATA_TYPE			*mDatap;
-	LLDoubleLinkedNode	*mNextp;
-	LLDoubleLinkedNode	*mPrevp;
-
-
-public:
-	// assign the mDatap pointer
-	LLDoubleLinkedNode(DATA_TYPE *data);
-
-	// destructor does not, by default, destroy associated data
-	// however, the mDatap must be NULL to ensure that we aren't causing memory leaks
-	~LLDoubleLinkedNode();
-
-	// delete associated data and NULL out pointer
-	void deleteData();
-
-	// remove associated data and NULL out pointer
-	void removeData();
-};
-
-
-const U32 LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH = 4;
-
-template <class DATA_TYPE> class LLDoubleLinkedList
-{
-private:
-	LLDoubleLinkedNode<DATA_TYPE> mHead;		// head node
-	LLDoubleLinkedNode<DATA_TYPE> mTail;		// tail node
-	LLDoubleLinkedNode<DATA_TYPE> *mQueuep;		// The node in the batter's box
-	LLDoubleLinkedNode<DATA_TYPE> *mCurrentp;	// The node we're talking about
-
-	// The state stack allows nested exploration of the LLDoubleLinkedList
-	// but should be used with great care
-	LLDoubleLinkedNode<DATA_TYPE> *mQueuepStack[LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH];
-	LLDoubleLinkedNode<DATA_TYPE> *mCurrentpStack[LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH];
-	U32 mStateStackDepth;
-	U32	mCount;
-
-	// mInsertBefore is a pointer to a user-set function that returns 
-	// TRUE if "first" should be located before "second"
-	// NOTE: mInsertBefore() should never return TRUE when ("first" == "second")
-	// or never-ending loops can occur
-	BOOL				(*mInsertBefore)(DATA_TYPE *first, DATA_TYPE *second);	
-																				
-public:
-	LLDoubleLinkedList();
-
-	// destructor destroys list and nodes, but not data in nodes
-	~LLDoubleLinkedList();
-
-	// put data into a node and stick it at the front of the list
-	// set mCurrentp to mQueuep
-	void addData(DATA_TYPE *data);
-
-	// put data into a node and stick it at the end of the list
-	// set mCurrentp to mQueuep
-	void addDataAtEnd(DATA_TYPE *data);
-
-	S32 getLength() const;
-	// search the list starting at mHead.mNextp and remove the link with mDatap == data
-	// set mCurrentp to mQueuep
-	// return TRUE if found, FALSE if not found
-	BOOL removeData(const DATA_TYPE *data);
-
-	// search the list starting at mHead.mNextp and delete the link with mDatap == data
-	// set mCurrentp to mQueuep
-	// return TRUE if found, FALSE if not found
-	BOOL deleteData(DATA_TYPE *data);
-
-	// remove all nodes from the list and delete the associated data
-	void deleteAllData();
-
-	// remove all nodes from the list but do not delete data
-	void removeAllNodes();
-
-	BOOL isEmpty();
-
-	// check to see if data is in list
-	// set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
-	// return TRUE if found, FALSE if not found
-	BOOL	checkData(const DATA_TYPE *data);
-
-	// NOTE: This next two funtions are only included here 
-	// for those too familiar with the LLLinkedList template class.
-	// They are depreciated.  resetList() is unecessary while 
-	// getCurrentData() is identical to getNextData() and has
-	// a misleading name.
-	//
-	// The recommended way to loop through a list is as follows:
-	//
-	// datap = list.getFirstData();
-	// while (datap)
-	// {
-	//     /* do stuff */
-	//     datap = list.getNextData();
-	// }
-
-		// place mQueuep on mHead node
-		void resetList();
-	
-		// return the data currently pointed to, 
-		// set mCurrentp to that node and bump mQueuep down the list
-		// NOTE: this function is identical to getNextData()
-		DATA_TYPE *getCurrentData();
-
-
-	// reset the list and return the data currently pointed to, 
-	// set mCurrentp to that node and bump mQueuep down the list
-	DATA_TYPE *getFirstData();
-
-
-	// reset the list and return the data at position n, set mCurentp 
-	// to that node and bump mQueuep down the list
-	// Note: n=0 will behave like getFirstData()
-	DATA_TYPE *getNthData(U32 n);
-
-	// reset the list and return the last data in it, 
-	// set mCurrentp to that node and bump mQueuep up the list
-	DATA_TYPE *getLastData();
-
-	// return data in mQueuep,
-	// set mCurrentp mQueuep and bump mQueuep down the list
-	DATA_TYPE *getNextData();
-
-	// return the data in mQueuep, 
-	// set mCurrentp to mQueuep and bump mQueuep up the list
-	DATA_TYPE *getPreviousData();
-
-	// remove the Node at mCurrentp
-	// set mCurrentp to mQueuep
-	void removeCurrentData();
-
-	// delete the Node at mCurrentp
-	// set mCurrentp to mQueuep
-	void deleteCurrentData();
-
-	// remove the Node at mCurrentp and insert it into newlist
-	// set mCurrentp to mQueuep
-	void moveCurrentData(LLDoubleLinkedList<DATA_TYPE> *newlist);
-
-	// insert the node in front of mCurrentp
-	// set mCurrentp to mQueuep
-	void insertNode(LLDoubleLinkedNode<DATA_TYPE> *node);
-
-	// insert the data in front of mCurrentp
-	// set mCurrentp to mQueuep
-	void insertData(DATA_TYPE *data);
-
-	// if mCurrentp has a previous node then :
-	//   * swaps mCurrentp with its previous
-	//   * set mCurrentp to mQueuep
-	//     (convenient for forward bubble-sort)
-	// otherwise does nothing
-	void swapCurrentWithPrevious();
-
-	// if mCurrentp has a next node then :
-	//   * swaps mCurrentp with its next
-	//   * set mCurrentp to mQueuep
-	//     (convenient for backwards bubble-sort)
-	// otherwise does nothing
-	void swapCurrentWithNext();
-
-	// move mCurrentp to the front of the list
-	// set mCurrentp to mQueuep
-	void moveCurrentToFront();
-	
-	// move mCurrentp to the end of the list
-	// set mCurrentp to mQueuep
-	void moveCurrentToEnd();
-
-	// set mInsertBefore
-	void setInsertBefore(BOOL (*insert_before)(DATA_TYPE *first, DATA_TYPE *second));
-
-	// add data in front of first node for which mInsertBefore(datap, node->mDatap) returns TRUE
-	// set mCurrentp to mQueuep
-	BOOL addDataSorted(DATA_TYPE *datap);
-
-	// sort the list using bubble-sort
-	// Yes, this is a different name than the same function in LLLinkedList.
-	// When it comes time for a name consolidation hopefully this one will win.
-	BOOL bubbleSort();
-
-	// does a single bubble sort pass on the list
-	BOOL lazyBubbleSort();
-
-	// returns TRUE if state successfully pushed (state stack not full)
-	BOOL pushState();
-
-	// returns TRUE if state successfully popped (state stack not empty)
-	BOOL popState();
-
-	// empties the state stack
-	void clearStateStack();
-
-	// randomly move the the links in the list for debug or (Discordian) purposes
-	// sets mCurrentp and mQueuep to top of list
-	void scramble();
-
-private:
-	// add node to beginning of list
-	// set mCurrentp to mQueuep
-	void addNode(LLDoubleLinkedNode<DATA_TYPE> *node);
-
-	// add node to end of list
-	// set mCurrentp to mQueuep
-	void addNodeAtEnd(LLDoubleLinkedNode<DATA_TYPE> *node);
-};
-
-//#endif
-
-////////////////////////////////////////////////////////////////////////////////////////////
-
-// doublelinkedlist.cpp
-// LLDoubleLinkedList template class implementation file.
-// Provides a standard doubly linked list for fun and profit.
-// 
-// Copyright 2001, Linden Research, Inc.
-
-//#include "llerror.h"
-//#include "doublelinkedlist.h"
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// LLDoubleLinkedNode
-//////////////////////////////////////////////////////////////////////////////////////////
-
-
-// assign the mDatap pointer
-template <class DATA_TYPE>
-LLDoubleLinkedNode<DATA_TYPE>::LLDoubleLinkedNode(DATA_TYPE *data) : 
-	mDatap(data), mNextp(NULL), mPrevp(NULL)
-{
-}
-
-
-// destructor does not, by default, destroy associated data
-// however, the mDatap must be NULL to ensure that we aren't causing memory leaks
-template <class DATA_TYPE>
-LLDoubleLinkedNode<DATA_TYPE>::~LLDoubleLinkedNode()
-{
-	if (mDatap)
-	{
-		llerror("Attempting to call LLDoubleLinkedNode destructor with a non-null mDatap!", 1);
-	}
-}
-
-
-// delete associated data and NULL out pointer
-template <class DATA_TYPE>
-void LLDoubleLinkedNode<DATA_TYPE>::deleteData()
-{
-	delete mDatap;
-	mDatap = NULL;
-}
-
-
-template <class DATA_TYPE>
-void LLDoubleLinkedNode<DATA_TYPE>::removeData()
-{
-	mDatap = NULL;
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////////
-// LLDoubleLinkedList
-//////////////////////////////////////////////////////////////////////////////////////
-
-//                                   <------- up -------
-//
-//                                               mCurrentp
-//                                   mQueuep         |
-//                                      |            |
-//                                      |            | 
-//                      .------.     .------.     .------.      .------.
-//                      |      |---->|      |---->|      |----->|      |-----> NULL
-//           NULL <-----|      |<----|      |<----|      |<-----|      |
-//                     _'------'     '------'     '------'      '------:_
-//             .------. /|               |             |               |\ .------.
-//  NULL <-----|mHead |/                 |         mQueuep               \|mTail |-----> NULL
-//             |      |               mCurrentp                           |      |
-//             '------'                                                   '------'
-//                               -------- down --------->
-
-template <class DATA_TYPE>
-LLDoubleLinkedList<DATA_TYPE>::LLDoubleLinkedList()
-: mHead(NULL), mTail(NULL), mQueuep(NULL)
-{
-	mCurrentp = mHead.mNextp;
-	mQueuep = mHead.mNextp;
-	mStateStackDepth = 0;
-	mCount = 0;
-	mInsertBefore = NULL;
-}
-
-
-// destructor destroys list and nodes, but not data in nodes
-template <class DATA_TYPE>
-LLDoubleLinkedList<DATA_TYPE>::~LLDoubleLinkedList()
-{
-	removeAllNodes();
-}
-
-
-// put data into a node and stick it at the front of the list
-// doesn't change mCurrentp nor mQueuep
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::addData(DATA_TYPE *data)
-{
-	// don't allow NULL to be passed to addData
-	if (!data)
-	{
-		llerror("NULL pointer passed to LLDoubleLinkedList::addData()", 0);
-	}
-
-	// make the new node
-	LLDoubleLinkedNode<DATA_TYPE> *temp = new LLDoubleLinkedNode<DATA_TYPE> (data);
-
-	// add the node to the front of the list
-	temp->mPrevp = NULL; 
-	temp->mNextp = mHead.mNextp;
-	mHead.mNextp = temp;
-
-	// if there's something in the list, fix its back pointer
-	if (temp->mNextp)
-	{
-		temp->mNextp->mPrevp = temp;
-	}
-	// otherwise, fix the tail of the list
-	else 
-	{
-		mTail.mPrevp = temp;
-	}
-
-	mCount++;
-}
-
-
-// put data into a node and stick it at the end of the list
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::addDataAtEnd(DATA_TYPE *data)
-{
-	// don't allow NULL to be passed to addData
-	if (!data)
-	{
-		llerror("NULL pointer passed to LLDoubleLinkedList::addData()", 0);
-	}
-
-	// make the new node
-	LLDoubleLinkedNode<DATA_TYPE> *nodep = new LLDoubleLinkedNode<DATA_TYPE>(data);
-
-	addNodeAtEnd(nodep);
-	mCount++;
-}
-
-
-// search the list starting at mHead.mNextp and remove the link with mDatap == data
-// set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::removeData(const DATA_TYPE *data)
-{
-	BOOL b_found = FALSE;
-	// don't allow NULL to be passed to addData
-	if (!data)
-	{
-		llerror("NULL pointer passed to LLDoubleLinkedList::removeData()", 0);
-	}
-
-	mCurrentp = mHead.mNextp;
-
-	while (mCurrentp)
-	{
-		if (mCurrentp->mDatap == data)
-		{
-			b_found = TRUE;
-
-			// if there is a next one, fix it
-			if (mCurrentp->mNextp)
-			{
-				mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
-			}
-			else // we are at end of list
-			{
-				mTail.mPrevp = mCurrentp->mPrevp;
-			}
-
-			// if there is a previous one, fix it
-			if (mCurrentp->mPrevp)
-			{
-				mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
-			}
-			else // we are at beginning of list
-			{
-				mHead.mNextp = mCurrentp->mNextp;
-			}
-
-			// remove the node
-			mCurrentp->removeData();
-			delete mCurrentp;
-			mCount--;
-			break;
-		}
-		mCurrentp = mCurrentp->mNextp; 
-	}
-
-	// reset the list back to where it was
-	if (mCurrentp == mQueuep)
-	{
-		mCurrentp = mQueuep = NULL;
-	}
-	else
-	{
-		mCurrentp = mQueuep;
-	}
-
-	return b_found;
-}
-
-
-// search the list starting at mHead.mNextp and delete the link with mDatap == data
-// set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::deleteData(DATA_TYPE *data)
-{
-	BOOL b_found = FALSE;
-	// don't allow NULL to be passed to addData
-	if (!data)
-	{
-		llerror("NULL pointer passed to LLDoubleLinkedList::deleteData()", 0);
-	}
-
-	mCurrentp = mHead.mNextp;
-
-	while (mCurrentp)
-	{
-		if (mCurrentp->mDatap == data)
-		{
-			b_found = TRUE;
-
-			// if there is a next one, fix it
-			if (mCurrentp->mNextp)
-			{
-				mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
-			}
-			else // we are at end of list
-			{
-				mTail.mPrevp = mCurrentp->mPrevp;
-			}
-
-			// if there is a previous one, fix it
-			if (mCurrentp->mPrevp)
-			{
-				mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
-			}
-			else // we are at beginning of list
-			{
-				mHead.mNextp = mCurrentp->mNextp;
-			}
-
-			// remove the node
-			mCurrentp->deleteData();
-			delete mCurrentp;
-			mCount--;
-			break;
-		}
-		mCurrentp = mCurrentp->mNextp;
-	}
-
-	// reset the list back to where it was
-	if (mCurrentp == mQueuep)
-	{
-		mCurrentp = mQueuep = NULL;
-	}
-	else
-	{
-		mCurrentp = mQueuep;
-	}
-
-	return b_found;
-}
-
-
-// remove all nodes from the list and delete the associated data
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::deleteAllData()
-{
-	mCurrentp = mHead.mNextp;
-
-	while (mCurrentp)
-	{
-		mQueuep = mCurrentp->mNextp;
-		mCurrentp->deleteData();
-		delete mCurrentp;
-		mCurrentp = mQueuep;
-	}
-
-	// reset mHead and mQueuep
-	mHead.mNextp = NULL;
-	mTail.mPrevp = NULL;
-	mCurrentp = mHead.mNextp;
-	mQueuep = mHead.mNextp;
-	mStateStackDepth = 0;
-	mCount = 0;
-}
-
-
-// remove all nodes from the list but do not delete associated data
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::removeAllNodes()
-{
-	mCurrentp = mHead.mNextp;
-
-	while (mCurrentp)
-	{
-		mQueuep = mCurrentp->mNextp;
-		mCurrentp->removeData();
-		delete mCurrentp;
-		mCurrentp = mQueuep;
-	}
-
-	// reset mHead and mCurrentp
-	mHead.mNextp = NULL;
-	mTail.mPrevp = NULL;
-	mCurrentp = mHead.mNextp;
-	mQueuep = mHead.mNextp;
-	mStateStackDepth = 0;
-	mCount = 0;
-}
-
-template <class DATA_TYPE>
-S32 LLDoubleLinkedList<DATA_TYPE>::getLength() const
-{
-//	U32	length = 0;
-//	for (LLDoubleLinkedNode<DATA_TYPE>* temp = mHead.mNextp; temp != NULL; temp = temp->mNextp)
-//	{
-//		length++;
-//	}
-	return mCount;
-}
-
-// check to see if data is in list
-// set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::checkData(const DATA_TYPE *data)
-{
-	mCurrentp = mHead.mNextp;
-
-	while (mCurrentp)
-	{
-		if (mCurrentp->mDatap == data)
-		{
-			mQueuep = mCurrentp;
-			return TRUE;
-		}
-		mCurrentp = mCurrentp->mNextp;
-	}
-
-	mCurrentp = mQueuep;
-	return FALSE;
-}
-
-// NOTE: This next two funtions are only included here 
-// for those too familiar with the LLLinkedList template class.
-// They are depreciated.  resetList() is unecessary while 
-// getCurrentData() is identical to getNextData() and has
-// a misleading name.
-//
-// The recommended way to loop through a list is as follows:
-//
-// datap = list.getFirstData();
-// while (datap)
-// {
-//     /* do stuff */
-//     datap = list.getNextData();
-// }
-
-	// place mCurrentp and mQueuep on first node
-	template <class DATA_TYPE>
-	void LLDoubleLinkedList<DATA_TYPE>::resetList()
-	{
-		mCurrentp = mHead.mNextp;
-		mQueuep = mHead.mNextp;
-		mStateStackDepth = 0;
-	}
-	
-	
-	// return the data currently pointed to, 
-	// set mCurrentp to that node and bump mQueuep down the list
-	template <class DATA_TYPE>
-	DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getCurrentData()
-	{
-		if (mQueuep)
-		{
-			mCurrentp = mQueuep;
-			mQueuep = mQueuep->mNextp;
-			return mCurrentp->mDatap;
-		}
-		else
-		{
-			return NULL;
-		}
-	}
-
-
-// reset the list and return the data currently pointed to, 
-// set mCurrentp to that node and bump mQueuep down the list
-template <class DATA_TYPE>
-DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getFirstData()
-{
-	mQueuep = mHead.mNextp;
-	mCurrentp = mQueuep;
-	if (mQueuep)
-	{
-		mQueuep = mQueuep->mNextp;
-		return mCurrentp->mDatap;
-	}
-	else
-	{
-		return NULL;
-	}
-}
-
-
-// reset the list and return the data at position n, set mCurentp 
-// to that node and bump mQueuep down the list
-// Note: n=0 will behave like getFirstData()
-template <class DATA_TYPE>
-DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getNthData(U32 n)
-{
-	mCurrentp = mHead.mNextp;
-
-	if (mCurrentp)
-	{
-		for (U32 i=0; i<n; i++)
-		{
-			mCurrentp = mCurrentp->mNextp;
-			if (!mCurrentp)
-			{
-				break;
-			}		
-		}
-	}
-
-	if (mCurrentp)
-	{
-		// bump mQueuep down the list
-		mQueuep = mCurrentp->mNextp;
-		return mCurrentp->mDatap;
-	}
-	else
-	{
-		mQueuep = NULL;
-		return NULL;
-	}
-}
-
-
-// reset the list and return the last data in it, 
-// set mCurrentp to that node and bump mQueuep up the list
-template <class DATA_TYPE>
-DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getLastData()
-{
-	mQueuep = mTail.mPrevp;
-	mCurrentp = mQueuep;
-	if (mQueuep)
-	{
-		mQueuep = mQueuep->mPrevp;
-		return mCurrentp->mDatap;
-	}
-	else
-	{
-		return NULL;
-	}
-}
-
-
-// return the data in mQueuep, 
-// set mCurrentp to mQueuep and bump mQueuep down the list
-template <class DATA_TYPE>
-DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getNextData()
-{
-	if (mQueuep)
-	{
-		mCurrentp = mQueuep;
-		mQueuep = mQueuep->mNextp;
-		return mCurrentp->mDatap;
-	}
-	else
-	{
-		return NULL;
-	}
-}
-
-
-// return the data in mQueuep, 
-// set mCurrentp to mQueuep and bump mQueuep up the list
-template <class DATA_TYPE>
-DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getPreviousData()
-{
-	if (mQueuep)
-	{
-		mCurrentp = mQueuep;
-		mQueuep = mQueuep->mPrevp;
-		return mCurrentp->mDatap;
-	}
-	else
-	{
-		return NULL;
-	}
-}
-
-
-// remove the Node at mCurrentp
-// set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep)
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::removeCurrentData()
-{
-	if (mCurrentp)
-	{
-		// if there is a next one, fix it
-		if (mCurrentp->mNextp)
-		{
-			mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
-		}
-		else	// otherwise we are at end of list
-		{
-			mTail.mPrevp = mCurrentp->mPrevp;
-		}
-
-		// if there is a previous one, fix it
-		if (mCurrentp->mPrevp)
-		{
-			mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
-		}
-		else	// otherwise we are at beginning of list
-		{
-			mHead.mNextp = mCurrentp->mNextp;
-		}
-
-		// remove the node
-		mCurrentp->removeData();
-		delete mCurrentp;
-		mCount--;
-
-		// check for redundant pointing
-		if (mCurrentp == mQueuep)
-		{
-			mCurrentp = mQueuep = NULL;
-		}
-		else
-		{
-			mCurrentp = mQueuep;
-		}
-	}
-}
-
-
-// delete the Node at mCurrentp
-// set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep) 
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::deleteCurrentData()
-{
-	if (mCurrentp)
-	{
-		// remove the node
-		// if there is a next one, fix it
-		if (mCurrentp->mNextp)
-		{
-			mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
-		}
-		else	// otherwise we are at end of list
-		{
-			mTail.mPrevp = mCurrentp->mPrevp;
-		}
-
-		// if there is a previous one, fix it
-		if (mCurrentp->mPrevp)
-		{
-			mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
-		}
-		else	// otherwise we are at beginning of list
-		{
-			mHead.mNextp = mCurrentp->mNextp;
-		}
-
-		// remove the LLDoubleLinkedNode
-		mCurrentp->deleteData();
-		delete mCurrentp;
-		mCount--;
-
-		// check for redundant pointing
-		if (mCurrentp == mQueuep)
-		{
-			mCurrentp = mQueuep = NULL;
-		}
-		else
-		{
-			mCurrentp = mQueuep;
-		}
-	}
-}
-
-
-// remove the Node at mCurrentp and insert it into newlist
-// set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep)
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::moveCurrentData(LLDoubleLinkedList<DATA_TYPE> *newlist)
-{
-	if (mCurrentp)
-	{
-		// remove the node
-		// if there is a next one, fix it
-		if (mCurrentp->mNextp)
-		{
-			mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
-		}
-		else	// otherwise we are at end of list
-		{
-			mTail.mPrevp = mCurrentp->mPrevp;
-		}
-
-		// if there is a previous one, fix it
-		if (mCurrentp->mPrevp)
-		{
-			mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
-		}
-		else	// otherwise we are at beginning of list
-		{
-			mHead.mNextp = mCurrentp->mNextp;
-		}
-
-		// move the node to the new list
-		newlist->addNode(mCurrentp);
-
-		// check for redundant pointing
-		if (mCurrentp == mQueuep)
-		{
-			mCurrentp = mQueuep = NULL;
-		}
-		else
-		{
-			mCurrentp = mQueuep;
-		}
-	}
-}
-
-
-// Inserts the node previous to mCurrentp
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::insertNode(LLDoubleLinkedNode<DATA_TYPE> *nodep)
-{
-	// don't allow pointer to NULL to be passed
-	if (!nodep)
-	{
-		llerror("NULL pointer passed to LLDoubleLinkedList::insertNode()", 0);
-	}
-	if (!nodep->mDatap)
-	{
-		llerror("NULL data pointer passed to LLDoubleLinkedList::insertNode()", 0);
-	}
-
-	if (mCurrentp)
-	{
-		if (mCurrentp->mPrevp)
-		{
-			nodep->mPrevp = mCurrentp->mPrevp;
-			nodep->mNextp = mCurrentp;
-			mCurrentp->mPrevp->mNextp = nodep;
-			mCurrentp->mPrevp = nodep;
-		}
-		else	// at beginning of list
-		{
-			nodep->mPrevp = NULL;
-			nodep->mNextp = mCurrentp;
-			mHead.mNextp = nodep;
-			mCurrentp->mPrevp = nodep;
-		}
-		mCurrentp = mQueuep;
-	}
-	else	// add to front of list
-	{
-		addNode(nodep);
-	}
-}
-
-
-// insert the data in front of mCurrentp
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::insertData(DATA_TYPE *data)
-{
-	if (!data)
-	{
-		llerror("NULL data pointer passed to LLDoubleLinkedList::insertNode()", 0);
-	}
-	LLDoubleLinkedNode<DATA_TYPE> *node = new LLDoubleLinkedNode<DATA_TYPE>(data);
-	insertNode(node);
-	mCount++;
-}
-
-
-// if mCurrentp has a previous node then :
-//   * swaps mCurrentp with its previous
-//   * set mCurrentp to mQueuep
-// otherwise does nothing
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::swapCurrentWithPrevious()
-{
-	if (mCurrentp)
-	{
-		if (mCurrentp->mPrevp)
-		{
-			// Pull mCurrentp out of list
-			mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
-			if (mCurrentp->mNextp)
-			{
-				mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
-			}
-			else 	// mCurrentp was at end of list
-			{
-				mTail.mPrevp = mCurrentp->mPrevp;
-			}
-
-			// Fix mCurrentp's pointers
-			mCurrentp->mNextp = mCurrentp->mPrevp;
-			mCurrentp->mPrevp = mCurrentp->mNextp->mPrevp;
-			mCurrentp->mNextp->mPrevp = mCurrentp;
-
-			if (mCurrentp->mPrevp)
-			{
-				// Fix the backward pointer of mCurrentp's new previous
-				mCurrentp->mPrevp->mNextp = mCurrentp;
-			}
-			else	// mCurrentp is now at beginning of list
-			{
-				mHead.mNextp = mCurrentp;
-			}
-
-			// Set the list back to the way it was
-			mCurrentp = mQueuep;
-		}
-	}
-}
-
-
-// if mCurrentp has a next node then :
-//   * swaps mCurrentp with its next
-//   * set mCurrentp to mQueuep
-// otherwise does nothing
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::swapCurrentWithNext()
-{
-	if (mCurrentp)
-	{
-		if (mCurrentp->mNextp)
-		{
-			// Pull mCurrentp out of list
-			mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
-			if (mCurrentp->mPrevp)
-			{
-				mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
-			}
-			else 	// mCurrentp was at beginning of list
-			{
-				mHead.mNextp = mCurrentp->mNextp;
-			}
-
-			// Fix mCurrentp's pointers
-			mCurrentp->mPrevp = mCurrentp->mNextp;
-			mCurrentp->mNextp = mCurrentp->mPrevp->mNextp;
-			mCurrentp->mPrevp->mNextp = mCurrentp;
-
-			if (mCurrentp->mNextp)
-			{
-				// Fix the back pointer of mCurrentp's new next
-				mCurrentp->mNextp->mPrevp = mCurrentp;
-			}
-			else 	// mCurrentp is now at end of list
-			{
-				mTail.mPrevp = mCurrentp;
-			}
-			
-			// Set the list back to the way it was
-			mCurrentp = mQueuep;
-		}
-	}
-}
-
-// move mCurrentp to the front of the list
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::moveCurrentToFront()
-{
-	if (mCurrentp)
-	{
-		// if there is a previous one, fix it
-		if (mCurrentp->mPrevp)
-		{
-			mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
-		}
-		else	// otherwise we are at beginning of list
-		{
-			// check for redundant pointing
-			if (mCurrentp == mQueuep)
-			{
-				mCurrentp = mQueuep = NULL;
-			}
-			else
-			{
-				mCurrentp = mQueuep;
-			}
-			return;
-		}
-
-		// if there is a next one, fix it
-		if (mCurrentp->mNextp)
-		{
-			mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
-		}
-		else	// otherwise we are at end of list
-		{
-			mTail.mPrevp = mCurrentp->mPrevp;
-		}
-
-		// add mCurrentp to beginning of list
-		mCurrentp->mNextp = mHead.mNextp;
-		mHead.mNextp->mPrevp = mCurrentp;	// mHead.mNextp MUST be valid, 
-											// or the list had only one node
-											// and we would have returned already
-		mCurrentp->mPrevp = NULL;
-		mHead.mNextp = mCurrentp;
-
-		// check for redundant pointing
-		if (mCurrentp == mQueuep)
-		{
-			mCurrentp = mQueuep = NULL;
-		}
-		else
-		{
-			mCurrentp = mQueuep;
-		}
-	}
-
-}
-
-// move mCurrentp to the end of the list
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::moveCurrentToEnd()
-{
-	if (mCurrentp)
-	{
-		// if there is a next one, fix it
-		if (mCurrentp->mNextp)
-		{
-			mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
-		}
-		else	// otherwise we are at end of list and we're done
-		{
-			// check for redundant pointing
-			if (mCurrentp == mQueuep)
-			{
-				mCurrentp = mQueuep = NULL;
-			}
-			else
-			{
-				mCurrentp = mQueuep;
-			}
-			return;
-		}
-
-		// if there is a previous one, fix it
-		if (mCurrentp->mPrevp)
-		{
-			mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
-		}
-		else	// otherwise we are at beginning of list
-		{
-			mHead.mNextp = mCurrentp->mNextp;
-		}
-
-		// add mCurrentp to end of list
-		mCurrentp->mPrevp = mTail.mPrevp;
-		mTail.mPrevp->mNextp = mCurrentp;	// mTail.mPrevp MUST be valid, 
-											// or the list had only one node
-											// and we would have returned already
-		mCurrentp->mNextp = NULL;
-		mTail.mPrevp = mCurrentp;
-
-		// check for redundant pointing
-		if (mCurrentp == mQueuep)
-		{
-			mCurrentp = mQueuep = NULL;
-		}
-		else
-		{
-			mCurrentp = mQueuep;
-		}
-	}
-}
-
-
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::setInsertBefore(BOOL (*insert_before)(DATA_TYPE *first, DATA_TYPE *second) )
-{
-	mInsertBefore = insert_before;
-}
-
-
-// add data in front of the first node for which mInsertBefore(datap, node->mDatap) returns TRUE
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::addDataSorted(DATA_TYPE *datap)
-{
-	// don't allow NULL to be passed to addData()
-	if (!datap)
-	{
-		llerror("NULL pointer passed to LLDoubleLinkedList::addDataSorted()", 0);
-	}
-
-	// has mInsertBefore not been set?
-	if (!mInsertBefore)
-	{
-		addData(datap);
-		return FALSE;
-	}
-
-	// is the list empty?
-	if (!mHead.mNextp)
-	{
-		addData(datap);
-		return TRUE;
-	}
-
-	// Note: this step has been added so that the behavior of LLDoubleLinkedList
-	// is as rigorous as the LLLinkedList class about adding duplicate nodes.
-	// Duplicate nodes can cause a problem when sorting if mInsertBefore(foo, foo) 
-	// returns TRUE.  However, if mInsertBefore(foo, foo) returns FALSE, then there 
-	// shouldn't be any reason to exclude duplicate nodes (as we do here).
-	if (checkData(datap))
-	{
-		return FALSE;
-	}
-	
-	mCurrentp = mHead.mNextp;
-	while (mCurrentp)
-	{
-		// check to see if datap is already in the list
-		if (datap == mCurrentp->mDatap)
-		{
-			return FALSE;
-		}
-		else if (mInsertBefore(datap, mCurrentp->mDatap))
-		{
-			insertData(datap);
-			return TRUE;
-		}
-		mCurrentp = mCurrentp->mNextp;
-	}
-	
-	addDataAtEnd(datap);
-	return TRUE;
-}
-
-
-// bubble-sort until sorted and return TRUE if anything was sorted
-// leaves mQueuep pointing at last node that was swapped with its mNextp
-//
-// NOTE: if you find this function looping for really long times, then you
-// probably need to check your implementation of mInsertBefore(a,b) and make 
-// sure it does not return TRUE when (a == b)!
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::bubbleSort()
-{
-	BOOL b_swapped = FALSE;
-	U32 count = 0;
-	while (lazyBubbleSort()) 
-	{
-		b_swapped = TRUE;
-		if (count++ > 0x7FFFFFFF)
-		{
-			llwarning("LLDoubleLinkedList::bubbleSort() : too many passes...", 1);
-			llwarning("    make sure the mInsertBefore(a, b) does not return TRUE for a == b", 1);
-			break;
-		}
-	}
-	return b_swapped;
-}
-
-
-// do a single bubble-sort pass and return TRUE if anything was sorted
-// leaves mQueuep pointing at last node that was swapped with its mNextp
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::lazyBubbleSort()
-{
-	// has mInsertBefore been set?
-	if (!mInsertBefore)
-	{
-		return FALSE;
-	}
-
-	// is list empty?
-	mCurrentp = mHead.mNextp;
-	if (!mCurrentp)
-	{
-		return FALSE;
-	}
-
-	BOOL b_swapped = FALSE;
-
-	// the sort will exit after 0x7FFFFFFF nodes or the end of the list, whichever is first
-	S32  length = 0x7FFFFFFF;
-	S32  count = 0;
-
-	while (mCurrentp  &&  mCurrentp->mNextp  &&  count<length)
-	{
-		if (mInsertBefore(mCurrentp->mNextp->mDatap, mCurrentp->mDatap))
-		{
-			b_swapped = TRUE;
-			mQueuep = mCurrentp;
-			swapCurrentWithNext();	// sets mCurrentp to mQueuep
-		}
-		count++;
-		mCurrentp = mCurrentp->mNextp;
-	}
-	
-	return b_swapped;
-}
-
-
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::pushState()
-{
-	if (mStateStackDepth < LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH)
-	{
-		*(mQueuepStack + mStateStackDepth) = mQueuep;
-		*(mCurrentpStack + mStateStackDepth) = mCurrentp;
-		mStateStackDepth++;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::popState()
-{
-	if (mStateStackDepth > 0)
-	{
-		mStateStackDepth--;
-		mQueuep = *(mQueuepStack + mStateStackDepth);
-		mCurrentp = *(mCurrentpStack + mStateStackDepth);
-		return TRUE;
-	}
-	return FALSE;
-}
-
-
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::clearStateStack()
-{
-	mStateStackDepth = 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// private members
-//////////////////////////////////////////////////////////////////////////////////////////
-
-// add node to beginning of list
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::addNode(LLDoubleLinkedNode<DATA_TYPE> *nodep)
-{
-	// add the node to the front of the list
-	nodep->mPrevp = NULL;
-	nodep->mNextp = mHead.mNextp;
-	mHead.mNextp = nodep;
-
-	// if there's something in the list, fix its back pointer
-	if (nodep->mNextp)
-	{
-		nodep->mNextp->mPrevp = nodep;
-	}
-	else	// otherwise fix the tail node
-	{
-		mTail.mPrevp = nodep;
-	}
-
-	mCurrentp = mQueuep;
-}
-
-
-// add node to end of list
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::addNodeAtEnd(LLDoubleLinkedNode<DATA_TYPE> *node)
-{
-	// add the node to the end of the list
-	node->mNextp = NULL;
-	node->mPrevp = mTail.mPrevp;
-	mTail.mPrevp = node;
-
-	// if there's something in the list, fix its back pointer
-	if (node->mPrevp)
-	{
-		node->mPrevp->mNextp = node;
-	}
-	else	// otherwise fix the head node
-	{
-		mHead.mNextp = node;
-	}
-
-	mCurrentp = mQueuep;
-}
-
-
-// randomly move nodes in the list for DEBUG (or Discordian) purposes
-// sets mCurrentp and mQueuep to top of list
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::scramble()
-{
-	S32 random_number;
-	DATA_TYPE *datap = getFirstData();
-	while(datap)
-	{
-		random_number = ll_rand(5);
-
-		if (0 == random_number)
-		{
-			removeCurrentData();
-			addData(datap);
-		}
-		else if (1 == random_number)
-		{
-			removeCurrentData();
-			addDataAtEnd(datap);
-		}
-		else if (2 == random_number)
-		{
-			swapCurrentWithPrevious();
-		}
-		else if (3 == random_number)
-		{
-			swapCurrentWithNext();
-		}
-		datap = getNextData();
-	}
-	mQueuep = mHead.mNextp;
-	mCurrentp = mQueuep;
-}
-
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::isEmpty()
-{
-	return (mCount == 0);
-}
-
-
-#endif
diff --git a/indra/llcommon/llassoclist.h b/indra/llcommon/llassoclist.h
deleted file mode 100644
index 2950504155..0000000000
--- a/indra/llcommon/llassoclist.h
+++ /dev/null
@@ -1,296 +0,0 @@
-/** 
- * @file llassoclist.h
- * @brief LLAssocList class header file
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLASSOCLIST_H
-#define LL_LLASSOCLIST_H
-
-//------------------------------------------------------------------------
-// LLAssocList is an associative list container class.
-//
-// The implementation is a single linked list.
-// Both index and value objects are stored by value (not reference).
-// If pointer values are specified for index and/or value, this
-// container does NOT assume ownership of the referenced objects,
-// and does NOT delete() them on removal or destruction of the container.
-//
-// Note that operations are generally not optimized, and may of them
-// are O(n) complexity.
-//------------------------------------------------------------------------
-
-#include <iostream>
-
-template<class INDEX_TYPE, class VALUE_TYPE>
-class LLAssocList
-{
-private:
-	// internal list node type
-	class Node
-	{
-	public:
-		Node(const INDEX_TYPE &index, const VALUE_TYPE &value, Node *next)
-		{
-			mIndex = index;
-			mValue = value;
-			mNext = next;
-		}
-		~Node() { }
-		INDEX_TYPE	mIndex;
-		VALUE_TYPE	mValue;
-		Node		*mNext;
-	};
-
-	// head of the linked list
-	Node *mHead;
-
-public:
-	// Constructor
-	LLAssocList()
-	{
-		mHead = NULL;
-	}
-
-	// Destructor
-	~LLAssocList()
-	{
-		removeAll();
-	}
-
-	// Returns TRUE if list is empty.
-	BOOL isEmpty()
-	{
-		return (mHead == NULL);
-	}
-
-	// Returns the number of items in the list.
-	U32 length()
-	{
-		U32 count = 0;
-		for (	Node *node = mHead;
-				node;
-				node = node->mNext )
-		{
-			count++;
-		}
-		return count;
-	}
-
-	// Removes item with the specified index.
-	BOOL remove( const INDEX_TYPE &index )
-	{
-		if (!mHead)
-			return FALSE;
-
-		if (mHead->mIndex == index)
-		{
-			Node *node = mHead;
-			mHead = mHead->mNext;
-			delete node;
-			return TRUE;
-		}
-
-		for (	Node *prev = mHead;
-				prev->mNext;
-				prev = prev->mNext )
-		{
-			if (prev->mNext->mIndex == index)
-			{
-				Node *node = prev->mNext;
-				prev->mNext = prev->mNext->mNext;
-				delete node;
-				return TRUE;
-			}
-		}
-		return FALSE;
-	}
-
-	// Removes all items from the list.
-	void removeAll()
-	{
-		while ( mHead )
-		{
-			Node *node = mHead;
-			mHead = mHead->mNext;
-			delete node;
-		}
-	}
-
-	// Adds a new item to the head of the list,
-	// removing any existing item with same index.
-	void addToHead( const INDEX_TYPE &index, const VALUE_TYPE &value )
-	{
-		remove(index);
-		Node *node = new Node(index, value, mHead);
-		mHead = node;
-	}
-
-	// Adds a new item to the end of the list,
-	// removing any existing item with the same index.
-	void addToTail( const INDEX_TYPE &index, const VALUE_TYPE &value )
-	{
-		remove(index);
-		Node *node = new Node(index, value, NULL);
-		if (!mHead)
-		{
-			mHead = node;
-			return;
-		}
-		for (	Node *prev=mHead;
-				prev;
-				prev=prev->mNext )
-		{
-			if (!prev->mNext)
-			{
-				prev->mNext=node;
-				return;
-			}
-		}
-	}
-
-	// Sets the value of a specified index.
-	// If index does not exist, a new value will be added only if
-	// 'addIfNotFound' is set to TRUE.
-	// Returns TRUE if successful.
-	BOOL setValue( const INDEX_TYPE &index, const VALUE_TYPE &value, BOOL addIfNotFound=FALSE )
-	{
-		VALUE_TYPE *valueP = getValue(index);
-		if (valueP)
-		{
-			*valueP = value;
-			return TRUE;
-		}
-		if (!addIfNotFound)
-			return FALSE;
-		addToTail(index, value);
-		return TRUE;
-	}
-
-	// Sets the ith value in the list.
-	// A new value will NOT be addded, if the ith value does not exist.
-	// Returns TRUE if successful.
-	BOOL setValueAt( U32 i, const VALUE_TYPE &value )
-	{
-		VALUE_TYPE *valueP = getValueAt(i);
-		if (valueP)
-		{
-			*valueP = value;
-			return TRUE;
-		}
-		return FALSE;
-	}
-
-	// Returns a pointer to the value for the specified index,
-	// or NULL if no item found.
-	VALUE_TYPE *getValue( const INDEX_TYPE &index )
-	{
-		for (	Node *node = mHead;
-				node;
-				node = node->mNext )
-		{
-			if (node->mIndex == index)
-				return &node->mValue;
-		}
-		return NULL;
-	}
-
-	// Returns a pointer to the ith value in the list, or
-	// NULL if i is not valid.
-	VALUE_TYPE *getValueAt( U32 i )
-	{
-		U32 count = 0;
-		for (	Node *node = mHead;
-				node;
-				node = node->mNext )
-		{
-			if (count == i)
-				return &node->mValue;
-			count++;
-		}
-		return NULL;
-	}
-
-	// Returns a pointer to the index for the specified index,
-	// or NULL if no item found.
-	INDEX_TYPE *getIndex( const INDEX_TYPE &index )
-	{
-		for (	Node *node = mHead;
-				node;
-				node = node->mNext )
-		{
-			if (node->mIndex == index)
-				return &node->mIndex;
-		}
-		return NULL;
-	}
-
-	// Returns a pointer to the ith index in the list, or
-	// NULL if i is not valid.
-	INDEX_TYPE *getIndexAt( U32 i )
-	{
-		U32 count = 0;
-		for (	Node *node = mHead;
-				node;
-				node = node->mNext )
-		{
-			if (count == i)
-				return &node->mIndex;
-			count++;
-		}
-		return NULL;
-	}
-
-	// Returns a pointer to the value for the specified index,
-	// or NULL if no item found.
-	VALUE_TYPE *operator[](const INDEX_TYPE &index)
-	{
-		return getValue(index);
-	}
-
-	// Returns a pointer to the ith value in the list, or
-	// NULL if i is not valid.
-	VALUE_TYPE *operator[](U32 i)
-	{
-		return getValueAt(i);
-	}
-
-	// Prints the list contents to the specified stream.
-	friend std::ostream &operator<<( std::ostream &os, LLAssocList &map )
-	{
-		os << "{";
-		for (	Node *node = map.mHead;
-				node;
-				node = node->mNext )
-		{
-			os << "<" << node->mIndex << ", " << node->mValue << ">";
-			if (node->mNext)
-				os << ", ";
-		}
-		os << "}";
-
-		return os;
-	}
-};
-
-#endif // LL_LLASSOCLIST_H
diff --git a/indra/llcommon/lldarrayptr.h b/indra/llcommon/lldarrayptr.h
deleted file mode 100644
index c9a0b204d1..0000000000
--- a/indra/llcommon/lldarrayptr.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/** 
- * @file lldarrayptr.h
- * @brief Wrapped std::vector for backward compatibility.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-#ifndef LL_LLDARRAYPTR_H
-#define LL_LLDARRAYPTR_H
-
-#include "lldarray.h"
-
-template <class Type, int BlockSize = 32> 
-class LLDynamicArrayPtr : public LLDynamicArray<Type, BlockSize>
-{
-};
-
-#endif // LL_LLDARRAYPTR_H
diff --git a/indra/llcommon/lldeleteutils.h b/indra/llcommon/lldeleteutils.h
deleted file mode 100644
index f250dc3028..0000000000
--- a/indra/llcommon/lldeleteutils.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/** 
- * @file lldeleteutils.h
- * @brief Utility functions to simplify some common pointer-munging idioms.
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-#ifndef LL_DELETE_UTILS_H
-#define LL_DELETE_UTILS_H
-
-// Simple utility functions to eventually replace the common 2-line
-// idiom scattered throughout the viewer codebase.  Note that where
-// possible we would rather be using smart pointers of some sort.
-
-template <class T>
-inline void deleteAndClear(T*& ptr)
-{
-	delete ptr;
-	ptr = NULL;
-}
-
-template <class T>
-inline void deleteAndClearArray(T*& array_ptr)
-{
-	delete[] array_ptr;
-	array_ptr = NULL;
-}
-
-#endif
diff --git a/indra/llcommon/lldepthstack.h b/indra/llcommon/lldepthstack.h
index d9db54efc7..ac435a30fa 100644
--- a/indra/llcommon/lldepthstack.h
+++ b/indra/llcommon/lldepthstack.h
@@ -27,17 +27,20 @@
 #ifndef LL_LLDEPTHSTACK_H
 #define LL_LLDEPTHSTACK_H
 
-#include "linked_lists.h"
+#include "llstl.h"
 
 template <class DATA_TYPE> class LLDepthStack
 {
 private:
-	LLLinkedList<DATA_TYPE> mStack;
+	std::deque<DATA_TYPE*>	mStack;
 	U32						mCurrentDepth;
 	U32						mMaxDepth;
 
 public:
-	LLDepthStack() : mCurrentDepth(0), mMaxDepth(0) {}
+	LLDepthStack() 
+	:	mCurrentDepth(0), mMaxDepth(0) 
+	{}
+
 	~LLDepthStack()	{}
 
 	void setDepth(U32 depth)
@@ -54,24 +57,27 @@ public:
 	{ 
 		if (mCurrentDepth < mMaxDepth)
 		{
-			mStack.addData(data); 
+			mStack.push_back(data); 
 			mCurrentDepth++;
 		}
 		else
 		{
 			// the last item falls off stack and is deleted
-			mStack.getLastData();
-			mStack.deleteCurrentData();	
-			mStack.addData(data);
+			if (!mStack.empty())
+			{
+				mStack.pop_front();
+			}
+			mStack.push_back(data);
 		}
 	}
 	
 	DATA_TYPE *pop()
 	{ 
-		DATA_TYPE *tempp = mStack.getFirstData(); 
-		if (tempp)
+		DATA_TYPE *tempp = NULL;
+		if (!mStack.empty())
 		{
-			mStack.removeCurrentData(); 
+			tempp = mStack.back();
+			mStack.pop_back(); 
 			mCurrentDepth--;
 		}
 		return tempp; 
@@ -79,20 +85,20 @@ public:
 	
 	DATA_TYPE *check()
 	{ 
-		DATA_TYPE *tempp = mStack.getFirstData(); 
-		return tempp; 
+		return mStack.empty() ? NULL : mStack.back();
 	}
 	
 	void deleteAllData()
 	{ 
 		mCurrentDepth = 0;
-		mStack.deleteAllData(); 
+		std::for_each(mStack.begin(), mStack.end(), DeletePointer());
+		mStack.clear(); 
 	}
 	
 	void removeAllNodes()
 	{ 
 		mCurrentDepth = 0;
-		mStack.removeAllNodes(); 
+		mStack.clear(); 
 	}
 };
 
diff --git a/indra/llcommon/lldlinked.h b/indra/llcommon/lldlinked.h
deleted file mode 100644
index 3f7c197be7..0000000000
--- a/indra/llcommon/lldlinked.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/** 
- * @file lldlinked.h
- * @brief Declaration of the LLDLinked class.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-#ifndef LL_LLDLINKED_H
-#define LL_LLDLINKED_H
-
-template <class Type> class LLDLinked
-{
-	LLDLinked* mNextp;
-	LLDLinked* mPrevp;
-public:
-
-	Type*   getNext()  { return (Type*)mNextp; }
-	Type*   getPrev()  { return (Type*)mPrevp; }
-	Type*   getFirst() { return (Type*)mNextp; }
-
-	void    init()
-	{
-		mNextp = mPrevp = NULL;
-	}
-
-	void    unlink()
-	{
-		if (mPrevp) mPrevp->mNextp = mNextp;
-		if (mNextp) mNextp->mPrevp = mPrevp;
-	}
-
-	 LLDLinked() { mNextp = mPrevp = NULL; }
-	virtual ~LLDLinked() { unlink(); }
-
-	virtual void    deleteAll()
-	{
-		Type *curp = getFirst();
-		while(curp)
-		{
-			Type *nextp = curp->getNext();
-			curp->unlink();
-			delete curp;
-			curp = nextp;
-		}
-	}
-
-	void relink(Type &after)
-	{
-		LLDLinked *afterp = (LLDLinked*)&after;
-		afterp->mPrevp = this;
-		mNextp = afterp;
-	}
-
-	virtual void    append(Type& after)
-	{
-		LLDLinked *afterp = (LLDLinked*)&after;
-		afterp->mPrevp    = this;
-		afterp->mNextp    = mNextp;
-		if (mNextp) mNextp->mPrevp = afterp;
-		mNextp            = afterp;
-	}
-
-	virtual void    insert(Type& before)
-	{
-		LLDLinked *beforep = (LLDLinked*)&before;
-		beforep->mNextp    = this;
-		beforep->mPrevp    = mPrevp;
-		if (mPrevp) mPrevp->mNextp = beforep;
-		mPrevp             = beforep;
-	}
-
-	virtual void    put(Type& obj) { append(obj); }
-};
-
-#endif
diff --git a/indra/llcommon/lldqueueptr.h b/indra/llcommon/lldqueueptr.h
deleted file mode 100644
index 9fe08191e1..0000000000
--- a/indra/llcommon/lldqueueptr.h
+++ /dev/null
@@ -1,352 +0,0 @@
-/** 
- * @file lldqueueptr.h
- * @brief LLDynamicQueuePtr declaration
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-#ifndef LL_LLDQUEUEPTR_H
-#define LL_LLDQUEUEPTR_H
-
-template <class Type> 
-class LLDynamicQueuePtr
-{
-public:
-	enum
-	{
-		OKAY = 0,
-		FAIL = -1
-	};
-	
-	LLDynamicQueuePtr(const S32 size=8);
-	~LLDynamicQueuePtr();
-
-	void init();
-	void destroy();
-	void reset();
-	void reallocate(U32 newsize);
-
-	// ACCESSORS
-	const Type& get(const S32 index) const;					// no bounds checking
-	Type&       get(const S32 index);						// no bounds checking
-	const Type& operator []	(const S32 index) const			{ return get(index); }
-	Type&       operator []	(const S32 index)				{ return get(index); }
-	S32			find(const Type &obj) const;
-
-	S32			count() const								{ return (mLastObj >= mFirstObj ? mLastObj - mFirstObj : mLastObj + mMaxObj - mFirstObj); }
-	S32			getMax() const								{ return mMaxObj; }
-	S32			getFirst() const       { return mFirstObj; }
-	S32			getLast () const       { return mLastObj; }
-
-	// MANIPULATE
-	S32         push(const Type &obj);					// add to end of Queue, returns index from start
-	S32			pull(      Type &obj);			        // pull from Queue, returns index from start
-
-	S32			remove   (S32 index);				    // remove by index
-	S32			removeObj(const Type &obj);				// remove by object
-
-protected:
-	S32           mFirstObj, mLastObj, mMaxObj;
-	Type*		  mMemory;
-
-public:
-
-	void print()
-	{
-		/*
-		Convert this to llinfos if it's intended to be used - djs 08/30/02
-
-		printf("Printing from %d to %d (of %d): ",mFirstObj, mLastObj, mMaxObj);
-
-		if (mFirstObj <= mLastObj)
-		{
-			for (S32 i=mFirstObj;i<mLastObj;i++)
-			{
-				printf("%d ",mMemory[i]);
-			}
-		}
-		else
-		{
-			for (S32 i=mFirstObj;i<mMaxObj;i++)
-			{
-				printf("%d ",mMemory[i]);
-			}
-			for (i=0;i<mLastObj;i++)
-			{
-				printf("%d ",mMemory[i]);
-			}
-		}
-		printf("\n");
-		*/
-	}
-
-};
-
-
-//--------------------------------------------------------
-// LLDynamicQueuePtrPtr implementation
-//--------------------------------------------------------
-
-
-template <class Type>
-inline LLDynamicQueuePtr<Type>::LLDynamicQueuePtr(const S32 size)
-{
-	init();
-	reallocate(size);
-}
-
-template <class Type>
-inline LLDynamicQueuePtr<Type>::~LLDynamicQueuePtr()
-{
-	destroy();
-}
-
-template <class Type>
-inline void LLDynamicQueuePtr<Type>::init()
-{ 
-	mFirstObj    = 0;
-	mLastObj     = 0;
-	mMaxObj      = 0;
-	mMemory      = NULL;
-}
-
-template <class Type>
-inline void LLDynamicQueuePtr<Type>::reallocate(U32 newsize)
-{ 
-	if (newsize)
-	{
-		if (mFirstObj > mLastObj && newsize > mMaxObj)
-		{
-			Type* new_memory = new Type[newsize];
-
-			llassert(new_memory);
-
-			S32 _count = count();
-			S32 i, m = 0;
-			for (i=mFirstObj; i < mMaxObj; i++)
-			{
-				new_memory[m++] = mMemory[i];
-			}
-			for (i=0; i <=mLastObj; i++)
-			{
-				new_memory[m++] = mMemory[i];
-			}
-
-			delete[] mMemory;
-			mMemory = new_memory;
-
-			mFirstObj = 0;
-			mLastObj  = _count;
-		}
-		else
-		{
-			Type* new_memory = new Type[newsize];
-
-			llassert(new_memory);
-
-			S32 i, m = 0;
-			for (i=0; i < mLastObj; i++)
-			{
-				new_memory[m++] = mMemory[i];
-			}
-			delete[] mMemory;
-			mMemory = new_memory;
-		}
-	}
-	else if (mMemory)
-	{
-		delete[] mMemory;
-		mMemory = NULL;
-	}
-
-	mMaxObj = newsize;
-}
-
-template <class Type>
-inline void LLDynamicQueuePtr<Type>::destroy()
-{
-	reset();
-	delete[] mMemory;
-	mMemory = NULL;
-}
-
-
-template <class Type>
-void LLDynamicQueuePtr<Type>::reset()	   
-{ 
-	for (S32 i=0; i < mMaxObj; i++)
-	{
-		get(i) = NULL; // unrefs for pointers
-	}
-
-	mFirstObj    = 0;
-	mLastObj     = 0;
-}
-
-
-template <class Type>
-inline S32 LLDynamicQueuePtr<Type>::find(const Type &obj) const
-{
-	S32 i;
-	if (mFirstObj <= mLastObj)
-	{
-		for ( i = mFirstObj; i < mLastObj; i++ )
-		{
-			if (mMemory[i] == obj)
-			{
-				return i;
-			}
-		}
-	}
-	else
-	{
-		for ( i = mFirstObj; i < mMaxObj; i++ )
-		{
-			if (mMemory[i] == obj)
-			{
-				return i;
-			}
-		}
-		for ( i = 0; i < mLastObj; i++ )
-		{
-			if (mMemory[i] == obj)
-			{
-				return i;
-			}
-		}
-	}
-
-	return FAIL;
-}
-
-template <class Type>
-inline S32 LLDynamicQueuePtr<Type>::remove(S32 i)
-{
-	if (mFirstObj > mLastObj)
-	{
-		if (i >= mFirstObj && i < mMaxObj)
-		{
-			while( i > mFirstObj)
-			{
-				mMemory[i] = mMemory[i-1];
-				i--;
-			}
-			mMemory[mFirstObj] = NULL;
-			mFirstObj++;
-			if (mFirstObj >= mMaxObj) mFirstObj = 0;
-
-			return count();
-		}
-		else if (i < mLastObj && i >= 0)
-		{
-			while(i < mLastObj)
-			{
-				mMemory[i] = mMemory[i+1];
-				i++;
-			}
-			mMemory[mLastObj] = NULL;
-			mLastObj--;
-			if (mLastObj < 0) mLastObj = mMaxObj-1;
-
-			return count();
-		}
-	}
-	else if (i <= mLastObj && i >= mFirstObj)
-	{
-		while(i < mLastObj)
-		{
-			mMemory[i] = mMemory[i+1];
-			i++;
-		}
-		mMemory[mLastObj] = NULL;
-		mLastObj--;
-		if (mLastObj < 0) mLastObj = mMaxObj-1;
-
-		return count();
-	}
-
-	
-	return FAIL;
-}
-
-template <class Type>
-inline S32 LLDynamicQueuePtr<Type>::removeObj(const Type& obj)
-{
-	S32 ind = find(obj);
-	if (ind >= 0)
-	{
-		return remove(ind);
-	}
-	return FAIL;
-}
-
-template <class Type>
-inline S32	LLDynamicQueuePtr<Type>::push(const Type &obj) 
-{
-	if (mMaxObj - count() <= 1)
-	{
-		reallocate(mMaxObj * 2);
-	}
-
-	mMemory[mLastObj++] = obj;
-
-	if (mLastObj >= mMaxObj) 
-	{
-		mLastObj = 0;
-	}
-
-	return count();
-}
-
-template <class Type>
-inline S32	LLDynamicQueuePtr<Type>::pull(Type &obj) 
-{
-	obj = NULL;
-
-	if (count() < 1) return -1;
-
-	obj = mMemory[mFirstObj];
-	mMemory[mFirstObj] = NULL;
-
-	mFirstObj++;
-
-	if (mFirstObj >= mMaxObj) 
-	{
-		mFirstObj = 0;
-	}
-
-	return count();
-}
-
-template <class Type>
-inline const Type& LLDynamicQueuePtr<Type>::get(const S32 i) const
-{
-	return mMemory[i];
-}
-
-template <class Type>
-inline Type& LLDynamicQueuePtr<Type>::get(const S32 i)
-{
-	return mMemory[i];
-}
-
-
-#endif // LL_LLDQUEUEPTR_H
diff --git a/indra/llcommon/llenum.h b/indra/llcommon/llenum.h
deleted file mode 100644
index f57b2bc0b5..0000000000
--- a/indra/llcommon/llenum.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/** 
- * @file llenum.h
- * @author Tom Yedwab
- * @brief Utility class for storing enum value <-> string lookup.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLENUM_H
-#define LL_LLENUM_H
-
-class LLEnum
-{
-public:
-	typedef std::pair<const std::string, const U32> enum_t;
-	enum
-	{
-		UNDEFINED = 0xffffffff,
-	};
-
-	LLEnum(const enum_t values_array[], const U32 length)
-	{
-		for (U32 i=0; i<length; ++i)
-		{
-			mEnumMap.insert(values_array[i]);
-			if (values_array[i].second >= mEnumArray.size())
-			{
-				mEnumArray.resize(values_array[i].second+1);
-			}
-			mEnumArray[values_array[i].second] = values_array[i].first;
-		}
-	}
-
-	U32 operator[](std::string str)
-	{
-		std::map<const std::string, const U32>::iterator itor;
-		itor = mEnumMap.find(str);
-		if (itor != mEnumMap.end())
-		{
-			return itor->second;
-		}
-		return UNDEFINED;
-	}
-
-	const std::string operator[](U32 index)
-	{
-		if (index < mEnumArray.size())
-		{
-			return mEnumArray[index];
-		}
-		return "";
-	}
-
-private:
-	std::map<const std::string, const U32> mEnumMap;
-	std::vector<std::string> mEnumArray;
-};
-
-#endif // LL_LLENUM_H
diff --git a/indra/llcommon/llindexedqueue.h b/indra/llcommon/llindexedqueue.h
deleted file mode 100644
index aa2675d87d..0000000000
--- a/indra/llcommon/llindexedqueue.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/** 
- * @file llindexedqueue.h
- * @brief An indexed FIFO queue, where only one element with each key
- * can be in the queue.
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLINDEXEDQUEUE_H
-#define LL_LLINDEXEDQUEUE_H
-
-// An indexed FIFO queue, where only one element with each key can be in the queue.
-// This is ONLY used in the interest list, you'll probably want to review this code
-// carefully if you want to use it elsewhere - Doug
-
-template <typename Type> 
-class LLIndexedQueue
-{
-protected:
-	typedef std::deque<Type> type_deque;
-	type_deque mQueue;
-	std::set<Type> mKeySet;
-
-public:
-	LLIndexedQueue() {}
-
-	// move_if_there is an O(n) operation
-	bool push_back(const Type &value, bool move_if_there = false)
-	{
-		if (mKeySet.find(value) != mKeySet.end())
-		{
-			// Already on the queue
-			if (move_if_there)
-			{
-				// Remove the existing entry.
-				typename type_deque::iterator it;
-				for (it = mQueue.begin(); it != mQueue.end(); ++it)
-				{
-					if (*it == value)
-					{
-						break;
-					}
-				}
-
-				// This HAS to succeed, otherwise there's a serious bug in the keyset implementation
-				// (although this isn't thread safe, at all)
-
-				mQueue.erase(it);
-			}
-			else
-			{
-				// We're not moving it, leave it alone
-				return false;
-			}
-		}
-		else
-		{
-			// Doesn't exist, add it to the key set
-			mKeySet.insert(value);
-		}
-
-		mQueue.push_back(value);
-
-		// We succeeded in adding the new element.
-		return true;
-	}
-
-	bool push_front(const Type &value, bool move_if_there = false)
-	{
-		if (mKeySet.find(value) != mKeySet.end())
-		{
-			// Already on the queue
-			if (move_if_there)
-			{
-				// Remove the existing entry.
-				typename type_deque::iterator it;
-				for (it = mQueue.begin(); it != mQueue.end(); ++it)
-				{
-					if (*it == value)
-					{
-						break;
-					}
-				}
-
-				// This HAS to succeed, otherwise there's a serious bug in the keyset implementation
-				// (although this isn't thread safe, at all)
-
-				mQueue.erase(it);
-			}
-			else
-			{
-				// We're not moving it, leave it alone
-				return false;
-			}
-		}
-		else
-		{
-			// Doesn't exist, add it to the key set
-			mKeySet.insert(value);
-		}
-
-		mQueue.push_front(value);
-		return true;
-	}
-
-	void pop()
-	{
-		Type value = mQueue.front();
-		mKeySet.erase(value);
-		mQueue.pop_front();
-	}
-
-	Type &front()
-	{
-		return mQueue.front();
-	}
-
-	S32 size() const
-	{
-		return mQueue.size();
-	}
-
-	bool empty() const
-	{
-		return mQueue.empty();
-	}
-
-	void clear()
-	{
-		// Clear out all elements on the queue
-		mQueue.clear();
-		mKeySet.clear();
-	}
-};
-
-#endif // LL_LLINDEXEDQUEUE_H
diff --git a/indra/llcommon/lllazy.cpp b/indra/llcommon/lllazy.cpp
deleted file mode 100644
index 29fa040387..0000000000
--- a/indra/llcommon/lllazy.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * @file   lllazy.cpp
- * @author Nat Goodspeed
- * @date   2009-01-28
- * @brief  Implementation for lllazy.
- * 
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-// Precompiled header
-#include "linden_common.h"
-// associated header
-#include "lllazy.h"
-// STL headers
-// std headers
-// external library headers
-// other Linden headers
-
-// lllazy.h is presently header-only. This file exists only because our CMake
-// test macro ADD_BUILD_TEST requires it.
-int dummy = 0;
diff --git a/indra/llcommon/lllazy.h b/indra/llcommon/lllazy.h
deleted file mode 100644
index 5f3bbce79e..0000000000
--- a/indra/llcommon/lllazy.h
+++ /dev/null
@@ -1,399 +0,0 @@
-/**
- * @file   lllazy.h
- * @author Nat Goodspeed
- * @date   2009-01-22
- * @brief  Lazy instantiation of specified type. Useful in conjunction with
- *         Michael Feathers's "Extract and Override Getter" ("Working
- *         Effectively with Legacy Code", p. 352).
- *
- * Quoting his synopsis of steps on p.355:
- *
- * 1. Identify the object you need a getter for.
- * 2. Extract all of the logic needed to create the object into a getter.
- * 3. Replace all uses of the object with calls to the getter, and initialize
- *    the reference that holds the object to null in all constructors.
- * 4. Add the first-time logic to the getter so that the object is constructed
- *    and assigned to the reference whenever the reference is null.
- * 5. Subclass the class and override the getter to provide an alternative
- *    object for testing.
- *
- * It's the second half of bullet 3 (3b, as it were) that bothers me. I find
- * it all too easy to imagine adding pointer initializers to all but one
- * constructor... the one not exercised by my tests. That suggested using
- * (e.g.) boost::scoped_ptr<MyObject> so you don't have to worry about
- * destroying it either.
- *
- * However, introducing additional machinery allows us to encapsulate bullet 4
- * as well.
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LLLAZY_H)
-#define LL_LLLAZY_H
-
-#include <boost/function.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/lambda/construct.hpp>
-#include <stdexcept>
-
-/// LLLazyCommon simply factors out of LLLazy<T> things that don't depend on
-/// its template parameter.
-class LLLazyCommon
-{
-public:
-    /**
-     * This exception is thrown if you try to replace an LLLazy<T>'s factory
-     * (or T* instance) after it already has an instance in hand. Since T
-     * might well be stateful, we can't know the effect of silently discarding
-     * and replacing an existing instance, so we disallow it. This facility is
-     * intended for testing, and in a test scenario we can definitely control
-     * that.
-     */
-    struct InstanceChange: public std::runtime_error
-    {
-        InstanceChange(const std::string& what): std::runtime_error(what) {}
-    };
-
-protected:
-    /**
-     * InstanceChange might be appropriate in a couple of different LLLazy<T>
-     * methods. Factor out the common logic.
-     */
-    template <typename PTR>
-    static void ensureNoInstance(const PTR& ptr)
-    {
-        if (ptr)
-        {
-            // Too late: we've already instantiated the lazy object. We don't
-            // know whether it's stateful or not, so it's not safe to discard
-            // the existing instance in favor of a replacement.
-            throw InstanceChange("Too late to replace LLLazy instance");
-        }
-    }
-};
-
-/**
- * LLLazy<T> is useful when you have an outer class Outer that you're trying
- * to bring under unit test, that contains a data member difficult to
- * instantiate in a test harness. Typically the data member's class Inner has
- * many thorny dependencies. Feathers generally advocates "Extract and
- * Override Factory Method" (p. 350). But in C++, you can't call a derived
- * class override of a virtual method from the derived class constructor,
- * which limits applicability of "Extract and Override Factory Method." For
- * such cases Feathers presents "Extract and Override Getter" (p. 352).
- *
- * So we'll assume that your class Outer contains a member like this:
- * @code
- * Inner mInner;
- * @endcode
- *
- * LLLazy<Inner> can be used to replace this member. You can directly declare:
- * @code
- * LLLazy<Inner> mInner;
- * @endcode
- * and change references to mInner accordingly.
- *
- * (Alternatively, you can add a base class of the form
- * <tt>LLLazyBase<Inner></tt>. This is discussed further in the LLLazyBase<T>
- * documentation.)
- *
- * LLLazy<T> binds a <tt>boost::scoped_ptr<T></tt> and a factory functor
- * returning T*. You can either bind that functor explicitly or let it default
- * to the expression <tt>new T()</tt>.
- *
- * As long as LLLazy<T> remains unreferenced, its T remains uninstantiated.
- * The first time you use get(), <tt>operator*()</tt> or <tt>operator->()</tt>
- * it will instantiate its T and thereafter behave like a pointer to it.
- *
- * Thus, any existing reference to <tt>mInner.member</tt> should be replaced
- * with <tt>mInner->member</tt>. Any simple reference to @c mInner should be
- * replaced by <tt>*mInner</tt>.
- *
- * (If the original declaration was a pointer initialized in Outer's
- * constructor, e.g. <tt>Inner* mInner</tt>, so much the better. In that case
- * you should be able to drop in <tt>LLLazy<Inner></tt> without much change.)
- *
- * The support for "Extract and Override Getter" lies in the fact that you can
- * replace the factory functor -- or provide an explicit T*. Presumably this
- * is most useful from a test subclass -- which suggests that your @c mInner
- * member should be @c protected.
- *
- * Note that <tt>boost::lambda::new_ptr<T>()</tt> makes a dandy factory
- * functor, for either the set() method or LLLazy<T>'s constructor. If your T
- * requires constructor arguments, use an expression more like
- * <tt>boost::lambda::bind(boost::lambda::new_ptr<T>(), arg1, arg2, ...)</tt>.
- *
- * Of course the point of replacing the functor is to substitute a class that,
- * though referenced as Inner*, is not an Inner; presumably this is a testing
- * subclass of Inner (e.g. TestInner). Thus your test subclass TestOuter for
- * the containing class Outer will contain something like this:
- * @code
- * class TestOuter: public Outer
- * {
- * public:
- *     TestOuter()
- *     {
- *         // mInner must be 'protected' rather than 'private'
- *         mInner.set(boost::lambda::new_ptr<TestInner>());
- *     }
- *     ...
- * };
- * @endcode
- */
-template <typename T>
-class LLLazy: public LLLazyCommon
-{
-public:
-    /// Any nullary functor returning T* will work as a Factory
-    typedef boost::function<T* ()> Factory;
-
-    /// The default LLLazy constructor uses <tt>new T()</tt> as its Factory
-    LLLazy():
-        mFactory(boost::lambda::new_ptr<T>())
-    {}
-
-    /// Bind an explicit Factory functor
-    LLLazy(const Factory& factory):
-        mFactory(factory)
-    {}
-
-    /// Reference T, instantiating it if this is the first access
-    const T& get() const
-    {
-        if (! mInstance)
-        {
-            // use the bound Factory functor
-            mInstance.reset(mFactory());
-        }
-        return *mInstance;
-    }
-
-    /// non-const get()
-    T& get()
-    {
-        return const_cast<T&>(const_cast<const LLLazy<T>*>(this)->get());
-    }
-
-    /// operator*() is equivalent to get()
-    const T& operator*() const { return get(); }
-    /// operator*() is equivalent to get()
-    T& operator*() { return get(); }
-
-    /**
-     * operator->() must return (something resembling) T*. It's tempting to
-     * return the underlying boost::scoped_ptr<T>, but that would require
-     * breaking out the lazy-instantiation logic from get() into a common
-     * private method. Assume the pointer used for operator->() access is very
-     * short-lived.
-     */
-    const T* operator->() const { return &get(); }
-    /// non-const operator->()
-    T* operator->() { return &get(); }
-
-    /// set(Factory). This will throw InstanceChange if mInstance has already
-    /// been set.
-    void set(const Factory& factory)
-    {
-        ensureNoInstance(mInstance);
-        mFactory = factory;
-    }
-
-    /// set(T*). This will throw InstanceChange if mInstance has already been
-    /// set.
-    void set(T* instance)
-    {
-        ensureNoInstance(mInstance);
-        mInstance.reset(instance);
-    }
-
-private:
-    Factory mFactory;
-    // Consider an LLLazy<T> member of a class we're accessing by const
-    // reference. We want to allow even const methods to touch the LLLazy<T>
-    // member. Hence the actual pointer must be mutable because such access
-    // might assign it.
-    mutable boost::scoped_ptr<T> mInstance;
-};
-
-#if (! defined(__GNUC__)) || (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)
-// Not gcc at all, or a gcc more recent than gcc 3.3
-#define GCC33 0
-#else
-#define GCC33 1
-#endif
-
-/**
- * LLLazyBase<T> wraps LLLazy<T>, giving you an alternative way to replace
- * <tt>Inner mInner;</tt>. Instead of coding <tt>LLLazy<Inner> mInner</tt>,
- * you can add LLLazyBase<Inner> to your Outer class's bases, e.g.:
- * @code
- * class Outer: public LLLazyBase<Inner>
- * {
- *     ...
- * };
- * @endcode
- *
- * This gives you @c public get() and @c protected set() methods without
- * having to make your LLLazy<Inner> member @c protected. The tradeoff is that
- * you must access the wrapped LLLazy<Inner> using get() and set() rather than
- * with <tt>operator*()</tt> or <tt>operator->()</tt>.
- *
- * This mechanism can be used for more than one member, but only if they're of
- * different types. That is, you can replace:
- * @code
- * DifficultClass mDifficult;
- * AwkwardType    mAwkward;
- * @endcode
- * with:
- * @code
- * class Outer: public LLLazyBase<DifficultClass>, public LLLazyBase<AwkwardType>
- * {
- *     ...
- * };
- * @endcode
- * but for a situation like this:
- * @code
- * DifficultClass mMainDifficult, mAuxDifficult;
- * @endcode
- * you should directly embed LLLazy<DifficultClass> (q.v.).
- *
- * For multiple LLLazyBase bases, e.g. the <tt>LLLazyBase<DifficultClass>,
- * LLLazyBase<AwkwardType></tt> example above, access the relevant get()/set()
- * as (e.g.) <tt>LLLazyBase<DifficultClass>::get()</tt>. (This is why you
- * can't have multiple LLLazyBase<T> of the same T.) For a bit of syntactic
- * sugar, please see getLazy()/setLazy().
- */
-template <typename T>
-class LLLazyBase
-{
-public:
-    /// invoke default LLLazy constructor
-    LLLazyBase() {}
-    /// make wrapped LLLazy bind an explicit Factory
-    LLLazyBase(const typename LLLazy<T>::Factory& factory):
-        mInstance(factory)
-    {}
-
-    /// access to LLLazy::get()
-    T& get() { return *mInstance; }
-    /// access to LLLazy::get()
-    const T& get() const { return *mInstance; }
-
-protected:
-    // see getLazy()/setLazy()
-    #if (! GCC33)
-    template <typename T2, class MYCLASS> friend T2& getLazy(MYCLASS* this_);
-    template <typename T2, class MYCLASS> friend const T2& getLazy(const MYCLASS* this_);
-    #else // gcc 3.3
-    template <typename T2, class MYCLASS> friend T2& getLazy(const MYCLASS* this_);
-    #endif // gcc 3.3
-    template <typename T2, class MYCLASS> friend void setLazy(MYCLASS* this_, T2* instance);
-    template <typename T2, class MYCLASS>
-    friend void setLazy(MYCLASS* this_, const typename LLLazy<T2>::Factory& factory);
-
-    /// access to LLLazy::set(Factory)
-    void set(const typename LLLazy<T>::Factory& factory)
-    {
-        mInstance.set(factory);
-    }
-
-    /// access to LLLazy::set(T*)
-    void set(T* instance)
-    {
-        mInstance.set(instance);
-    }
-
-private:
-    LLLazy<T> mInstance;
-};
-
-/**
- * @name getLazy()/setLazy()
- * Suppose you have something like the following:
- * @code
- * class Outer: public LLLazyBase<DifficultClass>, public LLLazyBase<AwkwardType>
- * {
- *     ...
- * };
- * @endcode
- *
- * Your methods can reference the @c DifficultClass instance using
- * <tt>LLLazyBase<DifficultClass>::get()</tt>, which is admittedly a bit ugly.
- * Alternatively, you can write <tt>getLazy<DifficultClass>(this)</tt>, which
- * is somewhat more straightforward to read.
- *
- * Similarly,
- * @code
- * LLLazyBase<DifficultClass>::set(new TestDifficultClass());
- * @endcode
- * could instead be written:
- * @code
- * setLazy<DifficultClass>(this, new TestDifficultClass());
- * @endcode
- *
- * @note
- * I wanted to provide getLazy() and setLazy() without explicitly passing @c
- * this. That would imply making them methods on a base class rather than free
- * functions. But if <tt>LLLazyBase<T></tt> derives normally from (say) @c
- * LLLazyGrandBase providing those methods, then unqualified getLazy() would
- * be ambiguous: you'd have to write <tt>LLLazyBase<T>::getLazy<T>()</tt>,
- * which is even uglier than <tt>LLLazyBase<T>::get()</tt>, and therefore
- * pointless. You can make the compiler not care which @c LLLazyGrandBase
- * instance you're talking about by making @c LLLazyGrandBase a @c virtual
- * base class of @c LLLazyBase. But in that case,
- * <tt>LLLazyGrandBase::getLazy<T>()</tt> can't access
- * <tt>LLLazyBase<T>::get()</tt>!
- *
- * We want <tt>getLazy<T>()</tt> to access <tt>LLLazyBase<T>::get()</tt> as if
- * in the lexical context of some subclass method. Ironically, free functions
- * let us do that better than methods on a @c virtual base class -- but that
- * implies passing @c this explicitly. So be it.
- */
-//@{
-#if (! GCC33)
-template <typename T, class MYCLASS>
-T& getLazy(MYCLASS* this_) { return this_->LLLazyBase<T>::get(); }
-template <typename T, class MYCLASS>
-const T& getLazy(const MYCLASS* this_) { return this_->LLLazyBase<T>::get(); }
-#else // gcc 3.3
-// For const-correctness, we really should have two getLazy() variants: one
-// accepting const MYCLASS* and returning const T&, the other accepting
-// non-const MYCLASS* and returning non-const T&. This works fine on the Mac
-// (gcc 4.0.1) and Windows (MSVC 8.0), but fails on our Linux 32-bit Debian
-// Sarge stations (gcc 3.3.5). Since I really don't know how to beat that aging
-// compiler over the head to make it do the right thing, I'm going to have to
-// move forward with the wrong thing: a single getLazy() function that accepts
-// const MYCLASS* and returns non-const T&.
-template <typename T, class MYCLASS>
-T& getLazy(const MYCLASS* this_) { return const_cast<MYCLASS*>(this_)->LLLazyBase<T>::get(); }
-#endif // gcc 3.3
-template <typename T, class MYCLASS>
-void setLazy(MYCLASS* this_, T* instance) { this_->LLLazyBase<T>::set(instance); }
-template <typename T, class MYCLASS>
-void setLazy(MYCLASS* this_, const typename LLLazy<T>::Factory& factory)
-{
-    this_->LLLazyBase<T>::set(factory);
-}
-//@}
-
-#endif /* ! defined(LL_LLLAZY_H) */
diff --git a/indra/llcommon/lllocalidhashmap.h b/indra/llcommon/lllocalidhashmap.h
deleted file mode 100644
index 8f4f91a560..0000000000
--- a/indra/llcommon/lllocalidhashmap.h
+++ /dev/null
@@ -1,895 +0,0 @@
-/** 
- * @file lllocalidhashmap.h
- * @brief Map specialized for dealing with local ids
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLLOCALIDHASHMAP_H
-#define LL_LLLOCALIDHASHMAP_H
-
-#include "stdtypes.h"
-#include "llerror.h"
-
-const S32 MAX_ITERS = 4;
-// LocalID hash map
-
-//
-// LLLocalIDHashNode
-//
-
-template <class DATA, int SIZE>
-class LLLocalIDHashNode
-{
-public:
-	LLLocalIDHashNode();
-
-public:
-	S32 mCount;
-	U32	mKey[SIZE];
-	DATA mData[SIZE];
-	LLLocalIDHashNode<DATA, SIZE> *mNextNodep;
-};
-
-
-//
-// LLLocalIDHashNode implementation
-//
-template <class DATA, int SIZE>
-LLLocalIDHashNode<DATA, SIZE>::LLLocalIDHashNode()
-{
-	mCount = 0;
-	mNextNodep = NULL;
-}
-
-//
-// LLLocalIDHashMapIter
-//
-template <class DATA_TYPE, int SIZE>
-class LLLocalIDHashMap;
-
-template <class DATA_TYPE, int SIZE>
-class LLLocalIDHashMapIter
-{
-public:
-	LLLocalIDHashMapIter(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp);
-	~LLLocalIDHashMapIter();
-
-	void setMap(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp);
-	inline void first();
-	inline void next();
-	inline DATA_TYPE& current(); // *NOTE: Deprecate? Phoenix 2005-04-15
-	inline BOOL done() const;
-	inline S32  currentBin() const;
-	inline void setBin(S32 bin);
-
-	DATA_TYPE& operator*() const
-	{
-		return mCurHashNodep->mData[mCurHashNodeKey];
-	}
-	DATA_TYPE* operator->() const
-	{
-		return &(operator*());
-	}
-
-	LLLocalIDHashMap<DATA_TYPE, SIZE> *mHashMapp;
-	LLLocalIDHashNode<DATA_TYPE, SIZE> *mCurHashNodep;
-
-	S32 mCurHashMapNodeNum;
-	S32 mCurHashNodeKey;
-
-	DATA_TYPE mNull;
-
-	S32 mIterID;
-};
-
-
-
-template <class DATA_TYPE, int SIZE>
-class LLLocalIDHashMap
-{
-public:
-	friend class LLLocalIDHashMapIter<DATA_TYPE, SIZE>;
-
-	LLLocalIDHashMap(); // DO NOT use this unless you explicitly setNull, or the data type constructs a "null"
-						// object by default
-	// basic constructor including sorter
-	LLLocalIDHashMap(const DATA_TYPE &null_data);
-	// Hack, this should really be a const ref, but I'm not doing it that way because the sim
-	// usually uses pointers.
-	~LLLocalIDHashMap();
-
-	inline DATA_TYPE &get(const U32 local_id);
-	inline BOOL check(const U32 local_id) const;
-	inline DATA_TYPE &set(const U32 local_id, const DATA_TYPE data);
-	inline BOOL remove(const U32 local_id);
-	void removeAll();
-
-	void setNull(const DATA_TYPE data) { mNull = data; }
-
-	inline S32 getLength() const; // Warning, NOT O(1!)
-
-	void dumpIter();
-	void dumpBin(U32 bin);
-
-protected:
-	// Only used by the iterator.
-	void addIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter);
-	void removeIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter);
-
-	// Remove the item and shift all items afterward down the list,
-	// fixing up iterators as we go.
-	BOOL removeWithShift(const U32 local_id);
-
-protected:
-	LLLocalIDHashNode<DATA_TYPE, SIZE> mNodes[256];
-
-	S32 mIterCount;
-	LLLocalIDHashMapIter<DATA_TYPE, SIZE> *mIters[MAX_ITERS];
-
-	DATA_TYPE mNull;
-};
-
-
-//
-// LLLocalIDHashMap implementation
-//
-
-template <class DATA_TYPE, int SIZE>
-LLLocalIDHashMap<DATA_TYPE, SIZE>::LLLocalIDHashMap()
-:	mIterCount(0),
-	mNull()
-{
-	S32 i;
-	for (i = 0; i < MAX_ITERS; i++)
-	{
-		mIters[i] = NULL;
-	}
-}
-
-template <class DATA_TYPE, int SIZE>
-LLLocalIDHashMap<DATA_TYPE, SIZE>::LLLocalIDHashMap(const DATA_TYPE &null_data)
-:	mIterCount(0),
-	mNull(null_data)
-{
-	S32 i;
-	for (i = 0; i < MAX_ITERS; i++)
-	{
-		mIters[i] = NULL;
-	}
-}
-
-template <class DATA_TYPE, int SIZE>
-LLLocalIDHashMap<DATA_TYPE, SIZE>::~LLLocalIDHashMap()
-{
-	S32 i;
-	for (i = 0; i < MAX_ITERS; i++)
-	{
-		if (mIters[i])
-		{
-			mIters[i]->mHashMapp = NULL;
-			mIterCount--;
-		}
-	}
-	removeAll();
-}
-
-template <class DATA_TYPE, int SIZE>
-void LLLocalIDHashMap<DATA_TYPE, SIZE>::removeAll()
-{
-	S32 bin;
-	for (bin = 0; bin < 256; bin++)
-	{
-		LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
-
-		BOOL first = TRUE;
-		do // First node guaranteed to be there
-		{
-			S32 i;
-			const S32 count = nodep->mCount;
-
-			// Iterate through all members of this node
-			for (i = 0; i < count; i++)
-			{
-				nodep->mData[i] = mNull;
-			}
-
-			nodep->mCount = 0;
-			// Done with all objects in this node, go to the next.
-
-			LLLocalIDHashNode<DATA_TYPE, SIZE>* curp = nodep;
-			nodep = nodep->mNextNodep;
-
-			// Delete the node if it's not the first node
-			if (first)
-			{
-				first = FALSE;
-				curp->mNextNodep = NULL;
-			}
-			else
-			{
-				delete curp;
-			}
-		} while (nodep);
-	}
-}
-
-template <class DATA_TYPE, int SIZE>
-void LLLocalIDHashMap<DATA_TYPE, SIZE>::dumpIter()
-{
-	std::cout << "Hash map with " << mIterCount << " iterators" << std::endl;
-
-	std::cout << "Hash Map Iterators:" << std::endl;
-	S32 i;
-	for (i = 0; i < MAX_ITERS; i++)
-	{
-		if (mIters[i])
-		{
-			llinfos << i << " " << mIters[i]->mCurHashNodep << " " << mIters[i]->mCurHashNodeKey << llendl;
-		}
-		else
-		{
-			llinfos << i << "null" << llendl;
-		}
-	}
-}
-
-template <class DATA_TYPE, int SIZE>
-void LLLocalIDHashMap<DATA_TYPE, SIZE>::dumpBin(U32 bin)
-{
-	std::cout << "Dump bin " << bin << std::endl;
-
-	LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
-	S32 node = 0;
-	do // First node guaranteed to be there.
-	{
-		std::cout << "Bin " << bin 
-			<< " node " << node
-			<< " count " << nodep->mCount
-			<< " contains " << std::flush;
-
-		S32 i;
-		for (i = 0; i < nodep->mCount; i++)
-		{
-			std::cout << nodep->mData[i] << " " << std::flush;
-		}
-
-		std::cout << std::endl;
-
-		nodep = nodep->mNextNodep;
-		node++;
-	} while (nodep);
-}
-
-template <class DATA_TYPE, int SIZE>
-inline S32 LLLocalIDHashMap<DATA_TYPE, SIZE>::getLength() const
-{
-	S32 count = 0;
-	S32 bin;
-	for (bin = 0; bin < 256; bin++)
-	{
-		const LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
-		while (nodep)
-		{
-			count += nodep->mCount;
-			nodep = nodep->mNextNodep;
-		}
-	}
-	return count;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline DATA_TYPE &LLLocalIDHashMap<DATA_TYPE, SIZE>::get(const U32 local_id)
-{
-	LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff];
-
-	do // First node guaranteed to be there
-	{
-		S32 i;
-		const S32 count = nodep->mCount;
-
-		// Iterate through all members of this node
-		for (i = 0; i < count; i++)
-		{
-			if (nodep->mKey[i] == local_id)
-			{
-				// We found it.
-				return nodep->mData[i];
-			}
-		}
-
-		// Done with all objects in this node, go to the next.
-		nodep = nodep->mNextNodep;
-	} while (nodep);
-
-	return mNull;
-}
-
-
-template <class DATA_TYPE, int SIZE>
-inline BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::check(const U32 local_id) const
-{
-	const LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff];
-
-	do // First node guaranteed to be there
-	{
-		S32 i;
-		const S32 count = nodep->mCount;
-
-		// Iterate through all members of this node
-		for (i = 0; i < count; i++)
-		{
-			if (nodep->mKey[i] == local_id)
-			{
-				// We found it.
-				return TRUE;
-			}
-		}
-
-		// Done with all objects in this node, go to the next.
-		nodep = nodep->mNextNodep;
-	} while (nodep);
-
-	// Didn't find anything
-	return FALSE;
-}
-
-
-template <class DATA_TYPE, int SIZE>
-inline DATA_TYPE &LLLocalIDHashMap<DATA_TYPE, SIZE>::set(const U32 local_id, const DATA_TYPE data)
-{
-	// Set is just like a normal find, except that if we find a match
-	// we replace it with the input value.
-	// If we don't find a match, we append to the end of the list.
-
-	LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff];
-
-	while (1)
-	{
-		const S32 count = nodep->mCount;
-
-		S32 i;
-		for (i = 0; i < count; i++)
-		{
-			if (nodep->mKey[i] == local_id)
-			{
-				// We found a match for this key, replace the data with
-				// the incoming data.
-				nodep->mData[i] = data;
-				return nodep->mData[i];
-			}
-		}
-		if (!nodep->mNextNodep)
-		{
-			// We've iterated through all of the keys without finding a match
-			if (i < SIZE)
-			{
-				// There's still some space on this node, append
-				// the key and data to it.
-				nodep->mKey[i] = local_id;
-				nodep->mData[i] = data;
-				nodep->mCount++;
-
-				return nodep->mData[i];
-			}
-			else
-			{
-				// This node is full, append a new node to the end.
-				nodep->mNextNodep = new LLLocalIDHashNode<DATA_TYPE, SIZE>;
-				nodep->mNextNodep->mKey[0] = local_id;
-				nodep->mNextNodep->mData[0] = data;
-				nodep->mNextNodep->mCount = 1;
-
-				return nodep->mNextNodep->mData[0];
-			}
-		}
-
-		// No match on this node, go to the next
-		nodep = nodep->mNextNodep;
-	}
-}
-
-
-template <class DATA_TYPE, int SIZE>
-inline BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::remove(const U32 local_id)
-{
-	// Remove is the trickiest operation.
-	// What we want to do is swap the last element of the last
-	// node if we find the one that we want to remove, but we have
-	// to deal with deleting the node from the tail if it's empty, but
-	// NOT if it's the only node left.
-
-	const S32 node_index = local_id & 0xff;
-
-	LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[node_index];
-
-	// A modification of the standard search algorithm.
-	do // First node guaranteed to be there
-	{
-		const S32 count = nodep->mCount;
-
-		S32 i;
-		for (i = 0; i < count; i++)
-		{
-			if (nodep->mKey[i] == local_id)
-			{
-				// If we're removing the item currently pointed to by one
-				// or more iterators, we can just swap in the last item
-				// and back the iterator(s) up by one.
-				// Otherwise, we need to do a slow and safe shift of all
-				// items back to one position to fill the hole and fix up 
-				// all iterators we find.
-				BOOL need_shift = FALSE;
-				S32 cur_iter;
-				if (mIterCount)
-				{
-					for (cur_iter = 0; cur_iter < MAX_ITERS; cur_iter++)
-					{
-						if (mIters[cur_iter])
-						{
-							// We only care if the hash map node is on the one
-							// that we're working on.  If it's before, we've already
-							// traversed it, if it's after, changing the order doesn't
-							// matter.
-							if (mIters[cur_iter]->mCurHashMapNodeNum == node_index)
-							{
-								if ((mIters[cur_iter]->mCurHashNodep == nodep)
-									&& (mIters[cur_iter]->mCurHashNodeKey == i))
-								{
-									// it's on the one we're deleting, we'll
-									// fix the iterator quickly below.
-								}
-								else
-								{
-									// We're trying to remove an item on this
-									// iterator's chain that this
-									// iterator doesn't point to!  We need to do
-									// the slow remove-and-shift-down case.
-									need_shift = TRUE;
-								}
-							}
-						}
-					}
-				}
-
-				// Removing an item that isn't pointed to by all iterators
-				if (need_shift)
-				{
-					return removeWithShift(local_id);
-				}
-
-				// Fix the iterators that point to this node/i pair, the
-				// one we're deleting
-				for (cur_iter = 0; cur_iter < MAX_ITERS; cur_iter++)
-				{
-					if (mIters[cur_iter])
-					{
-						// We only care if the hash map node is on the one
-						// that we're working on.  If it's before, we've already
-						// traversed it, if it's after, changing the order doesn't
-						// matter.
-						if (mIters[cur_iter]->mCurHashMapNodeNum == node_index)
-						{
-							if ((mIters[cur_iter]->mCurHashNodep == nodep)
-								&& (mIters[cur_iter]->mCurHashNodeKey == i))
-							{
-								// We can handle the case where we're deleting 
-								// the element we're on trivially (sort of).
-								if (nodep->mCount > 1)
-								{
-									// If we're not going to delete this node,
-									// it's OK.
-									mIters[cur_iter]->mCurHashNodeKey--;
-								}
-								else
-								{
-									// We're going to delete this node, because this
-									// is the last element on it.
-									
-									// Find the next node, and then back up one.
-									mIters[cur_iter]->next();
-									mIters[cur_iter]->mCurHashNodeKey--;
-								}
-							}
-						}
-					}
-				}
-
-				// We found the node that we want to remove.
-				// Find the last (and next-to-last) node, and the index of the last
-				// element.  We could conceviably start from the node we're on,
-				// but that makes it more complicated, this is easier.
-
-				LLLocalIDHashNode<DATA_TYPE, SIZE> *prevp = &mNodes[node_index];
-				LLLocalIDHashNode<DATA_TYPE, SIZE> *lastp = prevp;
-
-				// Find the last and next-to-last
-				while (lastp->mNextNodep)
-				{
-					prevp = lastp;
-					lastp = lastp->mNextNodep;
-				}
-
-				// First, swap in the last to the current location.
-				nodep->mKey[i] = lastp->mKey[lastp->mCount - 1];
-				nodep->mData[i] = lastp->mData[lastp->mCount - 1];
-
-				// Now, we delete the entry
-				lastp->mCount--;
-				lastp->mData[lastp->mCount] = mNull;
-
-				if (!lastp->mCount)
-				{
-					// We deleted the last element!
-					if (lastp != &mNodes[local_id & 0xff])
-					{
-						// Only blitz the node if it's not the head
-						// Set the previous node to point to NULL, then
-						// blitz the empty last node
-						prevp->mNextNodep = NULL;
-						delete lastp;
-					}
-				}
-
-				return TRUE;
-			}
-		}
-
-		// Iterate to the next node, we've scanned all the entries in this one.
-		nodep = nodep->mNextNodep;
-	} while (nodep);
-
-	return FALSE;
-}
-
-template <class DATA_TYPE, int SIZE>
-BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::removeWithShift(const U32 local_id)
-{
-	const S32 node_index = local_id & 0xFF;
-	LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[node_index];
-	LLLocalIDHashNode<DATA_TYPE, SIZE>* prevp = NULL;
-	BOOL found = FALSE;
-
-	do // First node guaranteed to be there
-	{
-		const S32 count = nodep->mCount;
-		S32 i;
-		for (i = 0; i < count; i++)
-		{
-			if (nodep->mKey[i] == local_id)
-			{
-				// Found the item.  Start shifting items from later
-				// in the list over this item.
-				found = TRUE;
-			}
-
-			if (found)
-			{
-				// If there is an iterator on this node, we need to 
-				// back it up.
-				S32 cur_iter;
-				for (cur_iter = 0; cur_iter <MAX_ITERS; cur_iter++)
-				{
-					LLLocalIDHashMapIter<DATA_TYPE, SIZE>* iter;
-					iter = mIters[cur_iter];
-					// If an iterator is on this node,i pair, then back it up.
-					if (iter
-						&& iter->mCurHashMapNodeNum == node_index
-						&& iter->mCurHashNodep == nodep
-						&& iter->mCurHashNodeKey == i)
-					{
-						if (i > 0)
-						{
-							// Don't need to move iterator nodep, since 
-							// we're in the same node.
-							iter->mCurHashNodeKey--;
-						}
-						else if (prevp)
-						{
-							// need to go the previous node, last item
-							iter->mCurHashNodep = prevp;
-							iter->mCurHashNodeKey = prevp->mCount - 1;
-						}
-						else
-						{
-							// we're on the first item in the list, but
-							// need to go back anyhow.
-
-							// BUG: If this deletion empties the list, 
-							// iter->done() will be wrong until
-							// iter->next() is called.
-							iter->mCurHashNodeKey = -1;
-						}
-					}
-				}
-
-				// Copy data from the next position into this position.
-				if (i < count-1)
-				{
-					// we're not on the last item in the node,
-					// so we can copy within the node
-					nodep->mKey[i] = nodep->mKey[i+1];
-					nodep->mData[i] = nodep->mData[i+1];
-				}
-				else if (nodep->mNextNodep)
-				{
-					// we're on the last item in the node,
-					// but there's a next node we can copy from
-					nodep->mKey[i] = nodep->mNextNodep->mKey[0];
-					nodep->mData[i] = nodep->mNextNodep->mData[0];
-				}
-				else
-				{
-					// We're on the last position in the list.
-					// No one to copy from.  Replace with nothing.
-					nodep->mKey[i] = 0;
-					nodep->mData[i] = mNull;
-				}
-			}
-		}
-
-		// Last node in chain, so delete the last node
-		if (found
-			&& !nodep->mNextNodep)
-		{
-			// delete the last item off the last node
-			nodep->mCount--;
-
-			if (nodep->mCount == 0)
-			{
-				// We deleted the last element!
-				if (nodep != &mNodes[node_index])
-				{
-					// Always have a prevp if we're not the head.
-					llassert(prevp);
-
-					// Only blitz the node if it's not the head
-					// Set the previous node to point to NULL, then
-					// blitz the empty last node
-					prevp->mNextNodep = NULL;
-					delete nodep;
-					nodep = NULL;
-				}
-			}
-
-			// Deleted last item in chain, so we're done.
-			return found;
-		}
-
-		prevp = nodep;
-		nodep = nodep->mNextNodep;
-	} while (nodep);
-
-	return found;
-}
-
-template <class DATA_TYPE, int SIZE>
-void LLLocalIDHashMap<DATA_TYPE, SIZE>::removeIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter)
-{
-	S32 i;
-	for (i = 0; i < MAX_ITERS; i++)
-	{
-		if (mIters[i] == iter)
-		{
-			mIters[i] = NULL;
-			mIterCount--;
-			return;
-		}
-	}
-	llerrs << "Iterator " << iter << " not found for removal in hash map!" << llendl;
-}
-
-template <class DATA_TYPE, int SIZE>
-void LLLocalIDHashMap<DATA_TYPE, SIZE>::addIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter)
-{
-	S32 i;
-	for (i = 0; i < MAX_ITERS; i++)
-	{
-		if (mIters[i] == NULL)
-		{
-			mIters[i] = iter;
-			mIterCount++;
-			return;
-		}
-	}
-	llerrs << "More than " << MAX_ITERS << " iterating over a map simultaneously!" << llendl;
-}
-
-
-
-//
-// LLLocalIDHashMapIter Implementation
-//
-template <class DATA_TYPE, int SIZE>
-LLLocalIDHashMapIter<DATA_TYPE, SIZE>::LLLocalIDHashMapIter(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp)
-{
-	mHashMapp = NULL;
-	setMap(hash_mapp);
-}
-
-template <class DATA_TYPE, int SIZE>
-LLLocalIDHashMapIter<DATA_TYPE, SIZE>::~LLLocalIDHashMapIter()
-{
-	if (mHashMapp)
-	{
-		mHashMapp->removeIter(this);
-	}
-}
-
-template <class DATA_TYPE, int SIZE>
-void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::setMap(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp)
-{
-	if (mHashMapp)
-	{
-		mHashMapp->removeIter(this);
-	}
-	mHashMapp = hash_mapp;
-	if (mHashMapp)
-	{
-		mHashMapp->addIter(this);
-	}
-
-	mCurHashNodep = NULL;
-	mCurHashMapNodeNum = -1;
-	mCurHashNodeKey = 0;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::first()
-{
-	// Iterate through until we find the first non-empty node;
-	S32 i;
-	for (i = 0; i < 256; i++)
-	{
-		if (mHashMapp->mNodes[i].mCount)
-		{
-
-			mCurHashNodep = &mHashMapp->mNodes[i];
-			mCurHashMapNodeNum = i;
-			mCurHashNodeKey = 0;
-			//return mCurHashNodep->mData[0];
-			return;
-		}
-	}
-
-	// Completely empty!
-	mCurHashNodep = NULL;
-	//return mNull;
-	return;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline BOOL LLLocalIDHashMapIter<DATA_TYPE, SIZE>::done() const
-{
-	return mCurHashNodep ? FALSE : TRUE;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline S32 LLLocalIDHashMapIter<DATA_TYPE, SIZE>::currentBin() const
-{
-	if (  (mCurHashMapNodeNum > 255)
-		||(mCurHashMapNodeNum < 0))
-	{
-		return 0;
-	}
-	else
-	{
-		return mCurHashMapNodeNum;
-	}
-}
-
-template <class DATA_TYPE, int SIZE>
-inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::setBin(S32 bin)
-{
-	// Iterate through until we find the first non-empty node;
-	S32 i;
-	bin = llclamp(bin, 0, 255);
-	for (i = bin; i < 256; i++)
-	{
-		if (mHashMapp->mNodes[i].mCount)
-		{
-
-			mCurHashNodep = &mHashMapp->mNodes[i];
-			mCurHashMapNodeNum = i;
-			mCurHashNodeKey = 0;
-			return;
-		}
-	}
-	for (i = 0; i < bin; i++)
-	{
-		if (mHashMapp->mNodes[i].mCount)
-		{
-
-			mCurHashNodep = &mHashMapp->mNodes[i];
-			mCurHashMapNodeNum = i;
-			mCurHashNodeKey = 0;
-			return;
-		}
-	}
-	// Completely empty!
-	mCurHashNodep = NULL;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline DATA_TYPE &LLLocalIDHashMapIter<DATA_TYPE, SIZE>::current()
-{
-	if (!mCurHashNodep)
-	{
-		return mNull;
-	}
-	return mCurHashNodep->mData[mCurHashNodeKey];
-}
-
-template <class DATA_TYPE, int SIZE>
-inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::next()
-{
-	// No current entry, this iterator is done
-	if (!mCurHashNodep)
-	{
-		//return mNull;
-		return;
-	}
-
-	// Go to the next element
-	mCurHashNodeKey++;
-	if (mCurHashNodeKey < mCurHashNodep->mCount)
-	{
-		// We're not done with this node, return the current element
-		//return mCurHashNodep->mData[mCurHashNodeKey];
-		return;
-	}
-
-	// Done with this node, move to the next
-	mCurHashNodep = mCurHashNodep->mNextNodep;
-	if (mCurHashNodep)
-	{
-		// Return the first element
-		mCurHashNodeKey = 0;
-		//return mCurHashNodep->mData[0];
-		return;
-	}
-
-	// Find the next non-empty node (keyed on the first byte)
-	mCurHashMapNodeNum++;
-
-	S32 i;
-	for (i = mCurHashMapNodeNum; i < 256; i++)
-	{
-		if (mHashMapp->mNodes[i].mCount)
-		{
-			// We found one that wasn't empty
-			mCurHashNodep = &mHashMapp->mNodes[i];
-			mCurHashMapNodeNum = i;
-			mCurHashNodeKey = 0;
-			//return mCurHashNodep->mData[0];
-			return;
-		}
-	}
-
-	// OK, we're done, nothing else to iterate
-	mCurHashNodep = NULL;
-	mHashMapp->mIterCount--; // Decrement since we're safe to do removes now
-	//return mNull;
-	return;
-}
-
-#endif // LL_LLLOCALIDHASHMAP_H
diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h
index 853c427a13..9bb66d13dd 100644
--- a/indra/llcommon/llregistry.h
+++ b/indra/llcommon/llregistry.h
@@ -29,7 +29,6 @@
 
 #include <list>
 
-#include <boost/type_traits.hpp>
 #include "llsingleton.h"
 #include "llstl.h"
 
@@ -47,12 +46,11 @@ template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultC
 class LLRegistry
 {
 public:
-	typedef LLRegistry<KEY, VALUE, COMPARATOR>											registry_t;
-	typedef typename boost::add_reference<typename boost::add_const<KEY>::type>::type	ref_const_key_t;
-	typedef typename boost::add_reference<typename boost::add_const<VALUE>::type>::type	ref_const_value_t;
-	typedef typename boost::add_reference<VALUE>::type									ref_value_t;
-	typedef typename boost::add_pointer<typename boost::add_const<VALUE>::type>::type	ptr_const_value_t;
-	typedef typename boost::add_pointer<VALUE>::type									ptr_value_t;
+	typedef LLRegistry<KEY, VALUE, COMPARATOR>		registry_t;
+	typedef const KEY& 								ref_const_key_t;
+	typedef const VALUE&							ref_const_value_t;
+	typedef const VALUE*							ptr_const_value_t;
+	typedef VALUE*									ptr_value_t;
 
 	class Registrar
 	{
diff --git a/indra/llcommon/llsortedvector.h b/indra/llcommon/llsortedvector.h
deleted file mode 100644
index 391b82ee44..0000000000
--- a/indra/llcommon/llsortedvector.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- * @file   llsortedvector.h
- * @author Nat Goodspeed
- * @date   2012-04-08
- * @brief  LLSortedVector class wraps a vector that we maintain in sorted
- *         order so we can perform binary-search lookups.
- * 
- * $LicenseInfo:firstyear=2012&license=viewerlgpl$
- * Copyright (c) 2012, Linden Research, Inc.
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LLSORTEDVECTOR_H)
-#define LL_LLSORTEDVECTOR_H
-
-#include <vector>
-#include <algorithm>
-
-/**
- * LLSortedVector contains a std::vector<std::pair> that we keep sorted on the
- * first of the pair. This makes insertion somewhat more expensive than simple
- * std::vector::push_back(), but allows us to use binary search for lookups.
- * It's intended for small aggregates where lookup is far more performance-
- * critical than insertion; in such cases a binary search on a small, sorted
- * std::vector can be more performant than a std::map lookup.
- */
-template <typename KEY, typename VALUE>
-class LLSortedVector
-{
-public:
-    typedef LLSortedVector<KEY, VALUE> self;
-    typedef KEY key_type;
-    typedef VALUE mapped_type;
-    typedef std::pair<key_type, mapped_type> value_type;
-    typedef std::vector<value_type> PairVector;
-    typedef typename PairVector::iterator iterator;
-    typedef typename PairVector::const_iterator const_iterator;
-
-    /// Empty
-    LLSortedVector() {}
-
-    /// Fixed initial size
-    LLSortedVector(std::size_t size):
-        mVector(size)
-    {}
-
-    /// Bulk load
-    template <typename ITER>
-    LLSortedVector(ITER begin, ITER end):
-        mVector(begin, end)
-    {
-        // Allow caller to dump in a bunch of (pairs convertible to)
-        // value_type if desired, but make sure we sort afterwards.
-        std::sort(mVector.begin(), mVector.end());
-    }
-
-    /// insert(key, value)
-    std::pair<iterator, bool> insert(const key_type& key, const mapped_type& value)
-    {
-        return insert(value_type(key, value));
-    }
-
-    /// insert(value_type)
-    std::pair<iterator, bool> insert(const value_type& pair)
-    {
-        typedef std::pair<iterator, bool> iterbool;
-        iterator found = std::lower_bound(mVector.begin(), mVector.end(), pair,
-                                          less<value_type>());
-        // have to check for end() before it's even valid to dereference
-        if (found == mVector.end())
-        {
-            std::size_t index(mVector.size());
-            mVector.push_back(pair);
-            // don't forget that push_back() invalidates 'found'
-            return iterbool(mVector.begin() + index, true);
-        }
-        if (found->first == pair.first)
-        {
-            return iterbool(found, false);
-        }
-        // remember that insert() invalidates 'found' -- save index
-        std::size_t index(found - mVector.begin());
-        mVector.insert(found, pair);
-        // okay, convert from index back to iterator
-        return iterbool(mVector.begin() + index, true);
-    }
-
-    iterator begin() { return mVector.begin(); }
-    iterator end()   { return mVector.end(); }
-    const_iterator begin() const { return mVector.begin(); }
-    const_iterator end()   const { return mVector.end(); }
-
-    bool empty() const { return mVector.empty(); }
-    std::size_t size() const { return mVector.size(); }
-
-    /// find
-    iterator find(const key_type& key)
-    {
-        iterator found = std::lower_bound(mVector.begin(), mVector.end(),
-                                          value_type(key, mapped_type()),
-                                          less<value_type>());
-        if (found == mVector.end() || found->first != key)
-            return mVector.end();
-        return found;
-    }
-
-    const_iterator find(const key_type& key) const
-    {
-        return const_cast<self*>(this)->find(key);
-    }
-
-private:
-    // Define our own 'less' comparator so we can specialize without messing
-    // with std::less.
-    template <typename T>
-    struct less: public std::less<T> {};
-
-    // Specialize 'less' for an LLSortedVector::value_type involving
-    // std::type_info*. This is one of LLSortedVector's foremost use cases. We
-    // specialize 'less' rather than just defining a specific comparator
-    // because LLSortedVector should be usable for other key_types as well.
-    template <typename T>
-    struct less< std::pair<std::type_info*, T> >:
-        public std::binary_function<std::pair<std::type_info*, T>,
-                                    std::pair<std::type_info*, T>,
-                                    bool>
-    {
-        bool operator()(const std::pair<std::type_info*, T>& lhs,
-                        const std::pair<std::type_info*, T>& rhs) const
-        {
-            return lhs.first->before(*rhs.first);
-        }
-    };
-
-    // Same as above, but with const std::type_info*.
-    template <typename T>
-    struct less< std::pair<const std::type_info*, T> >:
-        public std::binary_function<std::pair<const std::type_info*, T>,
-                                    std::pair<const std::type_info*, T>,
-                                    bool>
-    {
-        bool operator()(const std::pair<const std::type_info*, T>& lhs,
-                        const std::pair<const std::type_info*, T>& rhs) const
-        {
-            return lhs.first->before(*rhs.first);
-        }
-    };
-
-    PairVector mVector;
-};
-
-#endif /* ! defined(LL_LLSORTEDVECTOR_H) */
diff --git a/indra/llcommon/llstack.h b/indra/llcommon/llstack.h
deleted file mode 100644
index 315de6ba2d..0000000000
--- a/indra/llcommon/llstack.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/** 
- * @file llstack.h
- * @brief LLStack template class
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLSTACK_H
-#define LL_LLSTACK_H
-
-#include "linked_lists.h"
-
-template <class DATA_TYPE> class LLStack
-{
-private:
-	LLLinkedList<DATA_TYPE> mStack;
-
-public:
-	LLStack()	{}
-	~LLStack()	{}
-
-	void push(DATA_TYPE *data)	{ mStack.addData(data); }
-	DATA_TYPE *pop()			{ DATA_TYPE *tempp = mStack.getFirstData(); mStack.removeCurrentData(); return tempp; }
-	void deleteAllData()		{ mStack.deleteAllData(); }
-	void removeAllNodes()		{ mStack.removeAllNodes(); }
-};
-
-#endif
-
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 92323f5fda..f499beca80 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -91,15 +91,15 @@ private:
 	BOOL				mPaused;
 	
 	// static function passed to APR thread creation routine
-	static void *APR_THREAD_FUNC staticRun(apr_thread_t *apr_threadp, void *datap);
+	static void *APR_THREAD_FUNC staticRun(struct apr_thread_t *apr_threadp, void *datap);
 
 protected:
 	std::string			mName;
 	class LLCondition*	mRunCondition;
 	LLMutex*			mDataLock;
 
-	apr_thread_t		*mAPRThreadp;
-	apr_pool_t			*mAPRPoolp;
+	apr_thread_t*		mAPRThreadp;
+	apr_pool_t*			mAPRPoolp;
 	BOOL				mIsLocalPool;
 	EThreadStatus		mStatus;
 	U32					mID;
@@ -107,7 +107,7 @@ protected:
 	//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
 	//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
 	//      otherwise it will cause severe memory leaking!!! --bao
-	LLVolatileAPRPool  *mLocalAPRFilePoolp ; 
+	LLVolatileAPRPool*	mLocalAPRFilePoolp ; 
 
 	void setQuitting();
 	
diff --git a/indra/llcommon/lltypeinfolookup.h b/indra/llcommon/lltypeinfolookup.h
deleted file mode 100644
index 0b6862444e..0000000000
--- a/indra/llcommon/lltypeinfolookup.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- * @file   lltypeinfolookup.h
- * @author Nat Goodspeed
- * @date   2012-04-08
- * @brief  Template data structure like std::map<std::type_info*, T>
- * 
- * $LicenseInfo:firstyear=2012&license=viewerlgpl$
- * Copyright (c) 2012, Linden Research, Inc.
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LLTYPEINFOLOOKUP_H)
-#define LL_LLTYPEINFOLOOKUP_H
-
-#include <boost/unordered_map.hpp>
-#include <boost/functional/hash.hpp>
-#include <boost/optional.hpp>
-#include <functional>               // std::binary_function
-#include <typeinfo>
-
-/**
- * The following helper classes are based on the Boost.Unordered documentation:
- * http://www.boost.org/doc/libs/1_45_0/doc/html/unordered/hash_equality.html
- */
-
-/**
- * Compute hash for a string passed as const char*
- */
-struct const_char_star_hash: public std::unary_function<const char*, std::size_t>
-{
-    std::size_t operator()(const char* str) const
-    {
-        std::size_t seed = 0;
-        for ( ; *str; ++str)
-        {
-            boost::hash_combine(seed, *str);
-        }
-        return seed;
-    }
-};
-
-/**
- * Compute equality for strings passed as const char*
- *
- * I (nat) suspect that this is where the default behavior breaks for the
- * const char* values returned from std::type_info::name(). If you compare the
- * two const char* pointer values, as a naive, unspecialized implementation
- * will surely do, they'll compare unequal.
- */
-struct const_char_star_equal: public std::binary_function<const char*, const char*, bool>
-{
-    bool operator()(const char* lhs, const char* rhs) const
-    {
-        return strcmp(lhs, rhs) == 0;
-    }
-};
-
-/**
- * LLTypeInfoLookup is specifically designed for use cases for which you might
- * consider std::map<std::type_info*, VALUE>. We have several such data
- * structures in the viewer. The trouble with them is that at least on Linux,
- * you can't rely on always getting the same std::type_info* for a given type:
- * different load modules will produce different std::type_info*.
- * LLTypeInfoLookup contains a workaround to address this issue.
- *
- * The API deliberately diverges from std::map in several respects:
- * * It avoids iterators, not only begin()/end() but also as return values
- *   from insert() and find(). This bypasses transform_iterator overhead.
- * * Since we literally use compile-time types as keys, the essential insert()
- *   and find() methods accept the key type as a @em template parameter,
- *   accepting and returning value_type as a normal runtime value. This is to
- *   permit future optimization (e.g. compile-time type hashing) without
- *   changing the API.
- */
-template <typename VALUE>
-class LLTypeInfoLookup
-{
-    // Use this for our underlying implementation: lookup by
-    // std::type_info::name() string. This is one of the rare cases in which I
-    // dare use const char* directly, rather than std::string, because I'm
-    // sure that every value returned by std::type_info::name() is static.
-    // HOWEVER, specify our own hash + equality functors: naively comparing
-    // distinct const char* values won't work.
-    typedef boost::unordered_map<const char*, VALUE,
-                                 const_char_star_hash, const_char_star_equal> impl_map_type;
-
-public:
-    typedef VALUE value_type;
-
-    LLTypeInfoLookup() {}
-
-    bool empty() const { return mMap.empty(); }
-    std::size_t size() const { return mMap.size(); }
-
-    template <typename KEY>
-    bool insert(const value_type& value)
-    {
-        // Obtain and store the std::type_info::name() string as the key.
-        // Return just the bool from std::map::insert()'s return pair.
-        return mMap.insert(typename impl_map_type::value_type(typeid(KEY).name(), value)).second;
-    }
-
-    template <typename KEY>
-    boost::optional<value_type> find() const
-    {
-        // Use the std::type_info::name() string as the key.
-        typename impl_map_type::const_iterator found = mMap.find(typeid(KEY).name());
-        if (found == mMap.end())
-            return boost::optional<value_type>();
-        return found->second;
-    }
-
-private:
-    impl_map_type mMap;
-};
-
-#endif /* ! defined(LL_LLTYPEINFOLOOKUP_H) */
diff --git a/indra/llcommon/metaclass.cpp b/indra/llcommon/metaclass.cpp
deleted file mode 100644
index 5e403511cf..0000000000
--- a/indra/llcommon/metaclass.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/** 
- * @file metaclass.cpp
- * @author Babbage
- * @date 2006-05-15
- * @brief Implementation of LLMetaClass
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h" 
-
-#include "metaclass.h"
-
-#include "metaproperty.h"
-#include "reflective.h"
-
-LLMetaClass::LLMetaClass()
-{
-}
-
-//virtual 
-LLMetaClass::~LLMetaClass()
-{
-}
-
-const LLMetaProperty* LLMetaClass::findProperty(const std::string& name) const
-{
-	PropertyIterator iter = mProperties.find(name);
-	if(iter == mProperties.end())
-	{
-		return NULL;
-	}
-	return (*iter).second;
-}
-
-void LLMetaClass::addProperty(const LLMetaProperty* property)
-{
-	mProperties.insert(std::make_pair(property->getName(), property));
-}
-
-U32 LLMetaClass::getPropertyCount() const
-{
-	return mProperties.size();
-}
-
-LLMetaClass::PropertyIterator LLMetaClass::beginProperties() const
-{
-	return mProperties.begin();
-}
-
-LLMetaClass::PropertyIterator LLMetaClass::endProperties() const
-{
-	return mProperties.end();
-}
-
-bool LLMetaClass::isInstance(const LLReflective* object) const
-{
-	// TODO: Babbage: Search through super classes of objects MetaClass.
-	const LLMetaClass* object_meta_class = &(object->getMetaClass());
-	return (object_meta_class == this);
-}
-
diff --git a/indra/llcommon/metaclass.h b/indra/llcommon/metaclass.h
deleted file mode 100644
index 626757d58d..0000000000
--- a/indra/llcommon/metaclass.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/** 
- * @file metaclass.h
- * @author Babbage
- * @date 2006-05-15
- * @brief Reflective meta information describing a class.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_METACLASS_H
-#define LL_METACLASS_H
-
-#include <string>
-#include <map>
-
-#include "stdtypes.h"
-
-class LLReflective;
-class LLMetaProperty;
-class LLMetaMethod;
-class LL_COMMON_API LLMetaClass
-{
-public:
-
-	LLMetaClass();
-	virtual ~LLMetaClass();
-  
-	// Create instance of this MetaClass. NULL if class is abstract. 
-	// Gives ownership of returned object.
-	// virtual LLReflective* create() const = 0;
-  
-	// Returns named property or NULL.
-	const LLMetaProperty* findProperty(const std::string& name) const;
-  
-	// Add property to metaclass. Takes ownership of given property.
-	void addProperty(const LLMetaProperty* property);
-	
-	typedef std::map<std::string, const LLMetaProperty*>::const_iterator PropertyIterator;
-	
-	U32 getPropertyCount() const;
-	
-	PropertyIterator beginProperties() const;
-	PropertyIterator endProperties() const;
-  
-	// Returns named property or NULL.
-	// const LLMetaMethod* findMethod(const std::string& name) const;
-  
-	// Add method to metaclass. Takes ownership of given method.
-	// void addMethod(const LLMetaMethod* method);
-  
-	// Find MetaClass by name. NULL if name is unknown.
-	// static LLMetaClass* findClass(const std::string& name);
-	
-	// True if object is instance of this meta class.
-	bool isInstance(const LLReflective* object) const;
-  
-private:
-
-	typedef std::map<std::string, const LLMetaProperty*> PropertyMap;
-	PropertyMap mProperties;
-};
-
-#endif // LL_METACLASS_H
diff --git a/indra/llcommon/metaclasst.h b/indra/llcommon/metaclasst.h
deleted file mode 100644
index b9a7ae219d..0000000000
--- a/indra/llcommon/metaclasst.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/** 
- * @file metaclasst.h
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_METACLASST_H
-#define LL_METACLASST_H
-
-#include "metaclass.h"
-
-template<class TObject>
-class LLMetaClassT : public LLMetaClass
-{
-	public:
-		
-		virtual ~LLMetaClassT() {;}
-		
-		static const LLMetaClassT& instance()
-		{
-			static const LLMetaClassT& instance = buildMetaClass();
-			return instance;
-		}
-	
-	private:
-	
-		static const LLMetaClassT& buildMetaClass()
-		{
-			LLMetaClassT& meta_class = *(new LLMetaClassT());
-			reflectProperties(meta_class);
-			return meta_class;
-		}
-	
-		LLMetaClassT() {;}
-	
-		static void reflectProperties(LLMetaClass&)
-		{
-		}
-};
-
-#endif // LL_METACLASST_H
diff --git a/indra/llcommon/metaproperty.cpp b/indra/llcommon/metaproperty.cpp
deleted file mode 100644
index 98d850bf1e..0000000000
--- a/indra/llcommon/metaproperty.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/** 
- * @file metaproperty.cpp
- * @author Babbage
- * @date 2006-05-15
- * @brief Implementation of LLMetaProperty.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h" 
-
-#include "metaproperty.h"
-
-#include "metaclass.h"
-
-LLMetaProperty::LLMetaProperty(const std::string& name, const LLMetaClass& object_class) : 
-	mName(name), mObjectClass(object_class) 
-{
-}
-
-//virtual 
-LLMetaProperty::~LLMetaProperty()
-{
-}
-
-const LLMetaClass& LLMetaProperty::getObjectMetaClass() const
-{
-	return mObjectClass;
-}
-
-void LLMetaProperty::checkObjectClass(const LLReflective* object) const
-{
-	if(! mObjectClass.isInstance(object))
-	{
-		throw "class cast exception";
-	}
-}
diff --git a/indra/llcommon/metaproperty.h b/indra/llcommon/metaproperty.h
deleted file mode 100644
index bd5bb1a30f..0000000000
--- a/indra/llcommon/metaproperty.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/** 
- * @file metaproperty.h
- * @author Babbage
- * @date 2006-05-15
- * @brief Reflective meta information describing a property of a class.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_METAPROPERTY_H
-#define LL_METAPROPERTY_H
-
-#include "stdtypes.h"
-#include "llsd.h"
-#include "reflective.h"
-
-class LLMetaClass;
-class LLReflective;
-class LL_COMMON_API LLMetaProperty
-{
-public:
-	LLMetaProperty(const std::string& name, const LLMetaClass& object_class);
-  virtual ~LLMetaProperty();
-  
-  // Get property name.
-  const std::string& getName() const {return mName;}
-
-  // Get value of this property.
-  virtual const LLReflective* get(const LLReflective* object) const = 0;
-  
-  // Set value of this property.
-  // virtual void set(LLReflective* object, const LLReflective* value) = 0;
-  
-  // Get value of this property as LLSD. Default returns undefined LLSD.
-  virtual LLSD getLLSD(const LLReflective* object) const = 0;
-  
-  // Get the MetaClass of legal values of this property.
-  // const LLMetaClass& getValueMetaClass();
-  
-  // Get the meta class that this property is a member of.
-  const LLMetaClass& getObjectMetaClass() const;
-
-protected:
-
-  // Check object is instance of object class, throw exception if not.
-  void checkObjectClass(const LLReflective* object) const;
-
-private:
-
-	std::string mName;
-	const LLMetaClass& mObjectClass;
-};
-
-#endif // LL_METAPROPERTY_H
diff --git a/indra/llcommon/metapropertyt.h b/indra/llcommon/metapropertyt.h
deleted file mode 100644
index 7a36c161da..0000000000
--- a/indra/llcommon/metapropertyt.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/** 
- * @file metapropertyt.h
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_METAPROPERTYT_H
-#define LL_METAPROPERTYT_H
-
-#include "llsd.h"
-#include "llstring.h"
-#include "metaclasst.h"
-#include "metaproperty.h"
-#include "reflectivet.h"
-
-template<class TProperty>
-class LLMetaPropertyT : public LLMetaProperty
-{
-public:
-	
-	virtual ~LLMetaPropertyT() {;}
-	
-	// Get value of this property. Gives ownership of returned value.
-	virtual const LLReflective* get(const LLReflective* object) const
-	{
-		checkObjectClass(object);
-		return getProperty(object);
-	}
-  
-	// Set value of this property.
-	/*virtual void set(LLReflective* object, const LLReflective* value)
-	{
-		// TODO: Babbage: Check types.
-		ref(object) = static_cast<const LLReflectiveT<TProperty>* >(value)->getValue();
-	}*/
-	
-	// Get value of this property as LLSD.
-	virtual LLSD getLLSD(const LLReflective* object) const
-	{
-		return LLSD();
-	}
-
-protected:
-
-	LLMetaPropertyT(const std::string& name, const LLMetaClass& object_class) : LLMetaProperty(name, object_class) {;}
-
-	virtual const TProperty* getProperty(const LLReflective* object) const = 0;
-};
-
-template <>
-inline const LLReflective* LLMetaPropertyT<S32>::get(const LLReflective* object) const
-{
-	checkObjectClass(object);
-	return NULL;
-}
-
-template <>
-inline const LLReflective* LLMetaPropertyT<std::string>::get(const LLReflective* object) const
-{
-	checkObjectClass(object);
-	return NULL;
-}
-
-template <>
-inline const LLReflective* LLMetaPropertyT<LLUUID>::get(const LLReflective* object) const
-{
-	checkObjectClass(object);
-	return NULL;
-}
-
-template <>
-inline const LLReflective* LLMetaPropertyT<bool>::get(const LLReflective* object) const
-{
-	checkObjectClass(object);
-	return NULL;
-}
-
-template <>
-inline LLSD LLMetaPropertyT<S32>::getLLSD(const LLReflective* object) const
-{
-	return *(getProperty(object));
-}
-
-template <>
-inline LLSD LLMetaPropertyT<std::string>::getLLSD(const LLReflective* object) const
-{
-	return *(getProperty(object));
-}
-
-template <>
-inline LLSD LLMetaPropertyT<LLUUID>::getLLSD(const LLReflective* object) const
-{
-	return *(getProperty(object));
-}
-
-template <>
-inline LLSD LLMetaPropertyT<bool>::getLLSD(const LLReflective* object) const
-{
-	return *(getProperty(object));
-}
-
-template<class TObject, class TProperty>
-class LLMetaPropertyTT : public LLMetaPropertyT<TProperty>
-{
-public:
-
-	LLMetaPropertyTT(const std::string& name, const LLMetaClass& object_class, TProperty (TObject::*property)) : 
-	  LLMetaPropertyT<TProperty>(name, object_class), mProperty(property) {;}
-
-protected:
-
-	// Get void* to property.
-	virtual const TProperty* getProperty(const LLReflective* object) const
-	{
-		const TObject* typed_object = static_cast<const TObject*>(object);
-		return &(typed_object->*mProperty);
-	};
-
-private:
-
-	TProperty (TObject::*mProperty);
-};
-
-template<class TObject, class TProperty>
-class LLMetaPropertyPtrTT : public LLMetaPropertyT<TProperty>
-{
-public:
-
-	LLMetaPropertyPtrTT(const std::string& name, const LLMetaClass& object_class, TProperty* (TObject::*property)) : 
-	  LLMetaPropertyT<TProperty>(name, object_class), mProperty(property) {;}
-
-protected:
-
-	// Get void* to property.
-	virtual const TProperty* getProperty(const LLReflective* object) const
-	{
-		const TObject* typed_object = static_cast<const TObject*>(object);
-		return typed_object->*mProperty;
-	};
-
-private:
-
-	TProperty* (TObject::*mProperty);
-};
-
-// Utility function to simplify the registration of members.
-template<class TObject, class TProperty>
-void reflectProperty(LLMetaClass& meta_class, const std::string& name, TProperty (TObject::*property))
-{
-	typedef LLMetaPropertyTT<TObject, TProperty> PropertyType;
-	const LLMetaProperty* meta_property = new PropertyType(name, meta_class, property);
-	meta_class.addProperty(meta_property);
-}
-
-// Utility function to simplify the registration of ptr properties.
-template<class TObject, class TProperty>
-void reflectPtrProperty(LLMetaClass& meta_class, const std::string& name, TProperty* (TObject::*property))
-{
-	typedef LLMetaPropertyPtrTT<TObject, TProperty> PropertyType;
-	const LLMetaProperty* meta_property = new PropertyType(name, meta_class, property);
-	meta_class.addProperty(meta_property);
-}
-
-#endif // LL_METAPROPERTYT_H
diff --git a/indra/llcommon/reflective.cpp b/indra/llcommon/reflective.cpp
deleted file mode 100644
index 2cc0e7e1f2..0000000000
--- a/indra/llcommon/reflective.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/** 
- * @file reflective.cpp
- * @author Babbage
- * @date 2006-05-15
- * @brief Implementation of LLReflective.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h" 
- 
-#include "reflective.h"
-
-LLReflective::LLReflective()
-{
-}
-
-//virtual 
-LLReflective::~LLReflective()
-{
-}
diff --git a/indra/llcommon/reflective.h b/indra/llcommon/reflective.h
deleted file mode 100644
index da5c5a2630..0000000000
--- a/indra/llcommon/reflective.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/** 
- * @file reflective.h
- * @author Babbage
- * @date 2006-05-15
- * @brief Interface that must be implemented by all reflective classes.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_REFLECTIVE_H
-#define LL_REFLECTIVE_H
-
-class LLMetaClass;
-class LL_COMMON_API LLReflective
-{
-public:
-	LLReflective();
-	virtual ~LLReflective();
-	
-	virtual const LLMetaClass& getMetaClass() const = 0;
-};
-
-#endif // LL_REFLECTIVE_H
diff --git a/indra/llcommon/reflectivet.h b/indra/llcommon/reflectivet.h
deleted file mode 100644
index 958921f23e..0000000000
--- a/indra/llcommon/reflectivet.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/** 
- * @file reflectivet.h
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_REFLECTIVET_H
-#define LL_REFLECTIVET_H
-
-#include "reflective.h"
-
-template <class T>
-class LLReflectiveT : public LLReflective
-{
-public:
-
-	LLReflectiveT(const T& value) : mValue(value) {;}
-	virtual ~LLReflectiveT() {;}
-	
-	virtual const LLMetaClass& getMetaClass() const {return LLMetaClassT<LLReflectiveT<T> >::instance();}
-	
-	const T& getValue() const {return mValue;}
-	
-private:
-
-	T mValue;
-};
-
-#endif
diff --git a/indra/llcommon/tests/reflection_test.cpp b/indra/llcommon/tests/reflection_test.cpp
deleted file mode 100644
index 8980ebb1f1..0000000000
--- a/indra/llcommon/tests/reflection_test.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-/** 
- * @file reflection_test.cpp
- * @date   May 2006
- * @brief Reflection unit tests.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "../linden_common.h"
-#include "../reflective.h"
-#include "../metaclasst.h"
-#include "../metapropertyt.h"
-#include "../stdtypes.h"
-
-#include "../test/lltut.h"
-
-namespace tut
-{
-  class TestAggregatedData : public LLReflective
-  {
-  public:
-	TestAggregatedData() {;}
-	virtual const LLMetaClass& getMetaClass() const;
-  
-  private:
-  };
-  
-  class TestReflectionData : public LLReflective
-  {
-  public:
-	TestReflectionData() : mInt(42), mString("foo"), mNullPtr(NULL), mPtr(new TestAggregatedData()), mRef(*(new TestAggregatedData)) {;}
-	virtual ~TestReflectionData() {delete mPtr;}
-	virtual const LLMetaClass& getMetaClass() const;
-	
-	static U32 getPropertyCount() {return 5;}
-	
-  private:
-  
-	friend class LLMetaClassT<TestReflectionData>;
-    S32 mInt;
-	std::string mString;
-	TestAggregatedData* mNullPtr;
-	TestAggregatedData* mPtr;
-	TestAggregatedData mObj;
-	TestAggregatedData& mRef;
-  };
-}
-
-template <>
-void LLMetaClassT<tut::TestReflectionData>::reflectProperties(LLMetaClass& meta_class)
-{
-	reflectProperty(meta_class, "mInt", &tut::TestReflectionData::mInt);
-	reflectProperty(meta_class, "mString", &tut::TestReflectionData::mString);
-	reflectPtrProperty(meta_class, "mNullPtr", &tut::TestReflectionData::mNullPtr);
-	reflectPtrProperty(meta_class, "mPtr", &tut::TestReflectionData::mPtr);
-	reflectProperty(meta_class, "mObj", &tut::TestReflectionData::mObj);
-	//reflectProperty(meta_class, "mRef", &tut::TestReflectionData::mRef); // AARGH!
-}
-
-namespace tut
-{
-	// virtual
-	const LLMetaClass& TestReflectionData::getMetaClass() const
-	{
-	   return LLMetaClassT<TestReflectionData>::instance();
-    }
-	
-	const LLMetaClass& TestAggregatedData::getMetaClass() const
-	{
-	   return LLMetaClassT<TestAggregatedData>::instance();
-    }
-}
-
-namespace tut
-{
-  typedef tut::test_group<TestReflectionData> TestReflectionGroup;
-  typedef TestReflectionGroup::object TestReflectionObject;
-  TestReflectionGroup gTestReflectionGroup("reflection");
-
-  template<> template<>
-  void TestReflectionObject::test<1>()
-  {
-	// Check properties can be found.
-    const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
-	const LLMetaProperty* null = NULL;
-	ensure_not_equals(meta_class.findProperty("mInt"), null);
-	ensure_not_equals(meta_class.findProperty("mString"), null);
-  }
-  
-  template<> template<>
-  void TestReflectionObject::test<2>()
-  {
-	// Check non-existent property cannot be found.
-    const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
-	const LLMetaProperty* null = NULL;
-	ensure_equals(meta_class.findProperty("foo"), null);
-  }
-  
-  template<> template<>
-  void TestReflectionObject::test<3>()
-  {
-	// Check integer property has correct value.	
-    const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
-	ensure_equals(meta_class.findProperty("mInt")->getLLSD(this).asInteger(), 42);
-  }
-  
-  template<> template<>
-  void TestReflectionObject::test<4>()
-  {
-	// Check string property has correct value.	
-    const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
-	ensure_equals(meta_class.findProperty("mString")->getLLSD(this).asString(), std::string("foo"));
-  }
-  
-  template<> template<>
-  void TestReflectionObject::test<5>()
-  {
-	// Check NULL reference property has correct value.
-	const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
-	const LLReflective* null = NULL;
-	ensure_equals(meta_class.findProperty("mNullPtr")->get(this), null);
-  }
-  
-  template<> template<>
-  void TestReflectionObject::test<6>()
-  {
-	// Check reference property has correct value.
-	const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
-	const LLReflective* null = NULL;
-	const LLReflective* ref = meta_class.findProperty("mPtr")->get(this);
-	ensure_not_equals(ref, null);
-  }
-  
-  template<> template<>
-  void TestReflectionObject::test<7>()
-  {
-	// Check reflective property has correct value.
-	const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
-	const LLReflective* null = NULL;
-	const LLReflective* ref = meta_class.findProperty("mObj")->get(this);
-	ensure_not_equals(ref, null);
-  }
-
-  template<> template<>
-  void TestReflectionObject::test<8>()
-  {
-	// Check property count.
-    const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
-	ensure_equals(meta_class.getPropertyCount(), TestReflectionData::getPropertyCount());
-  }
-  
-  template<> template<>
-  void TestReflectionObject::test<9>()
-  {
-	// Check property iteration.
-    const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
-	U32 count = 0;
-	LLMetaClass::PropertyIterator iter;
-	for(iter = meta_class.beginProperties(); iter != meta_class.endProperties(); ++iter)
-	{
-		++count;
-	}
-	ensure_equals(count, TestReflectionData::getPropertyCount());
-  }
-  
-  template<> template<>
-  void TestReflectionObject::test<10>()
-  {
-	// Check meta classes of different types do not compare equal.
-	const LLMetaClass* reflection_data_meta_class = &(LLMetaClassT<TestReflectionData>::instance());
-	const LLMetaClass* aggregated_data_meta_class = &(LLMetaClassT<TestAggregatedData>::instance());
-	ensure_not_equals(reflection_data_meta_class, aggregated_data_meta_class);
-  }
-  
-  template<> template<>
-  void TestReflectionObject::test<11>()
-  {
-	// Check class cast checks.
-	const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
-	TestAggregatedData* aggregated_data = new TestAggregatedData();
-	LLMetaClass::PropertyIterator iter;
-	U32 exception_count = 0;
-	for(iter = meta_class.beginProperties(); iter != meta_class.endProperties(); ++iter)
-	{
-		try
-		{
-			const LLMetaProperty* property = (*iter).second;
-			const LLReflective* reflective = property->get(aggregated_data); // Wrong reflective type, should throw exception.
-
-			// useless op to get rid of compiler warning.
-			reflective = reflective;
-		}
-		catch(...)
-		{
-			++exception_count;
-		}
-	}
-	ensure_equals(exception_count, getPropertyCount());
-	
-  }
-}
-- 
cgit v1.2.3


From 12c34dc30f0cb6270c11e100fcaceb3fa6b27e81 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 16 May 2013 00:53:01 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 renamed LLView::handleVisibilityChange to onVisibilityChange to reflect
 cleaned up scene monitor stats recording, now all trace stats dumped to csv
 also fixed extendablerecording, periodicrecording, etc. to properly implement
 start/stop/etc

---
 indra/llcommon/lltracerecording.cpp | 228 ++++++++++++------------------------
 indra/llcommon/lltracerecording.h   |  73 ++++++------
 2 files changed, 111 insertions(+), 190 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index e562f2bce2..6b5c6c7d3e 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -179,8 +179,6 @@ void Recording::handleStop()
 
 void Recording::handleSplitTo(Recording& other)
 {
-	stop();
-	other.restart();
 	handOffTo(other);
 }
 
@@ -375,94 +373,86 @@ PeriodicRecording::PeriodicRecording( U32 num_periods, EPlayState state)
 
 void PeriodicRecording::nextPeriod()
 {
-	EPlayState play_state = getPlayState();
-	Recording& old_recording = getCurRecording();
 	if (mAutoResize)
 	{
 		mRecordingPeriods.push_back(Recording());
 	}
-	U32 num_periods = mRecordingPeriods.size();
-	mCurPeriod = (num_periods > 0) 
-				? (mCurPeriod + 1) % num_periods 
-				: mCurPeriod + 1;
-	old_recording.splitTo(getCurRecording());
 
-	switch(play_state)
-	{
-	case STOPPED:
-		getCurRecording().stop();
-		break;
-	case PAUSED:
-		getCurRecording().pause();
-		break;
-	case STARTED:
-		break;
-	}
+	Recording& old_recording = getCurRecording();
+
+	mCurPeriod = mRecordingPeriods.empty()
+				? mCurPeriod + 1
+				: (mCurPeriod + 1) % mRecordingPeriods.size();
+	old_recording.splitTo(getCurRecording());
 }
 
 
 void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 {
-	if (other.mRecordingPeriods.size() < 2) return;
+	if (other.mRecordingPeriods.empty()) return;
 
 	EPlayState play_state = getPlayState();
-	pause();
+	stop();
 
 	EPlayState other_play_state = other.getPlayState();
 	other.pause();
 
-	if (mAutoResize)
-	{
-		// copy everything after current period of other recording to end of buffer
-		// this will only apply if other recording is using a fixed circular buffer
-		if (other.mCurPeriod < other.mRecordingPeriods.size() - 1)
-		{
-			std::copy(	other.mRecordingPeriods.begin() + other.mCurPeriod + 1,
-						other.mRecordingPeriods.end(),
-						std::back_inserter(mRecordingPeriods));
-		}
+	U32 other_recording_count = other.mRecordingPeriods.size();
 
-		// copy everything from beginning of other recording's buffer up to, but not including
-		// current period
-		std::copy(	other.mRecordingPeriods.begin(),
-					other.mRecordingPeriods.begin() + other.mCurPeriod,
-					std::back_inserter(mRecordingPeriods));
+	Recording& other_oldest_recording = other.mRecordingPeriods[(other.mCurPeriod + 1) % other.mRecordingPeriods.size()];
 
-		mCurPeriod = mRecordingPeriods.size() - 1;
+	// if I have a recording of any length, then close it off and start a fresh one
+	if (getCurRecording().getDuration().value())
+	{
+		nextPeriod();
 	}
-	else
+	getCurRecording().appendRecording(other_oldest_recording);
+
+	if (other_recording_count > 1)
 	{
-		size_t num_to_copy = llmin(	mRecordingPeriods.size(), other.mRecordingPeriods.size() );
-		std::vector<Recording>::iterator src_it = other.mRecordingPeriods.begin() 
-													+ (	(other.mCurPeriod + 1)									// cur 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++)
+		if (mAutoResize)
 		{
-			*dest_it = *src_it;
-
-			if (++src_it == other.mRecordingPeriods.end())
+			for (S32 other_index = (other.mCurPeriod + 2) % other_recording_count; 
+				other_index != other.mCurPeriod; 
+				other_index = (other_index + 1) % other_recording_count)
 			{
-				src_it = other.mRecordingPeriods.begin();
+				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]);
 			}
 
-			if (++dest_it == mRecordingPeriods.end())
+			mCurPeriod = mRecordingPeriods.size() - 1;
+		}
+		else
+		{
+			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 = mRecordingPeriods.begin();
+				*dest_it = *src_it;
+
+				if (++src_it == other.mRecordingPeriods.end())
+				{
+					src_it = other.mRecordingPeriods.begin();
+				}
+
+				if (++dest_it == mRecordingPeriods.end())
+				{
+					dest_it = mRecordingPeriods.begin();
+				}
 			}
-		}
 		
-		mCurPeriod = (mCurPeriod + num_to_copy) % mRecordingPeriods.size();
+			mCurPeriod = (mCurPeriod + num_to_copy) % mRecordingPeriods.size();
+		}
 	}
 
-	// if copying from periodic recording that wasn't active advance our period to the next available one
-	// otherwise continue recording on top of the last period of data received from the other recording
-	if (other_play_state != STARTED)
-	{
-		nextPeriod();
-	}
+	nextPeriod();
 
 	setPlayState(play_state);
 	other.setPlayState(other_play_state);
@@ -524,47 +514,28 @@ const Recording& PeriodicRecording::getPrevRecording( U32 offset ) const
 	return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
 }
 
-void PeriodicRecording::start()
+void PeriodicRecording::handleStart()
 {
 	getCurRecording().start();
 }
 
-void PeriodicRecording::stop()
-{
-	getCurRecording().stop();
-}
-
-void PeriodicRecording::pause()
+void PeriodicRecording::handleStop()
 {
 	getCurRecording().pause();
 }
 
-void PeriodicRecording::resume()
-{
-	getCurRecording().resume();
-}
-
-void PeriodicRecording::restart()
+void PeriodicRecording::handleReset()
 {
-	getCurRecording().restart();
+	mRecordingPeriods.clear();
+	mRecordingPeriods.push_back(Recording());
+	mCurPeriod = 0;
 }
 
-void PeriodicRecording::reset()
+void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
 {
-	getCurRecording().reset();
+	getCurRecording().handOffTo(other.getCurRecording());
 }
 
-void PeriodicRecording::splitTo(PeriodicRecording& other)
-{
-	getCurRecording().splitTo(other.getCurRecording());
-}
-
-void PeriodicRecording::splitFrom(PeriodicRecording& other)
-{
-	getCurRecording().splitFrom(other.getCurRecording());
-}
-
-
 ///////////////////////////////////////////////////////////////////////
 // ExtendableRecording
 ///////////////////////////////////////////////////////////////////////
@@ -581,55 +552,27 @@ void ExtendableRecording::extend()
 	mPotentialRecording.setPlayState(getPlayState());
 }
 
-void ExtendableRecording::start()
+void ExtendableRecording::handleStart()
 {
-	LLStopWatchControlsMixin<ExtendableRecording>::start();
 	mPotentialRecording.start();
 }
 
-void ExtendableRecording::stop()
-{
-	LLStopWatchControlsMixin<ExtendableRecording>::stop();
-	mPotentialRecording.stop();
-}
-
-void ExtendableRecording::pause()
+void ExtendableRecording::handleStop()
 {
-	LLStopWatchControlsMixin<ExtendableRecording>::pause();
 	mPotentialRecording.pause();
 }
 
-void ExtendableRecording::resume()
-{
-	LLStopWatchControlsMixin<ExtendableRecording>::resume();
-	mPotentialRecording.resume();
-}
-
-void ExtendableRecording::restart()
-{
-	LLStopWatchControlsMixin<ExtendableRecording>::restart();
-	mAcceptedRecording.reset();
-	mPotentialRecording.restart();
-}
-
-void ExtendableRecording::reset()
+void ExtendableRecording::handleReset()
 {
-	LLStopWatchControlsMixin<ExtendableRecording>::reset();
 	mAcceptedRecording.reset();
 	mPotentialRecording.reset();
 }
 
-void ExtendableRecording::splitTo(ExtendableRecording& other)
+void ExtendableRecording::handleSplitTo(ExtendableRecording& other)
 {
-	LLStopWatchControlsMixin<ExtendableRecording>::splitTo(other);
-	mPotentialRecording.splitTo(other.mPotentialRecording);
+	mPotentialRecording.handOffTo(other.mPotentialRecording);
 }
 
-void ExtendableRecording::splitFrom(ExtendableRecording& other)
-{
-	LLStopWatchControlsMixin<ExtendableRecording>::splitFrom(other);
-	mPotentialRecording.splitFrom(other.mPotentialRecording);
-}
 
 ///////////////////////////////////////////////////////////////////////
 // ExtendablePeriodicRecording
@@ -639,13 +582,13 @@ void ExtendableRecording::splitFrom(ExtendableRecording& other)
 ExtendablePeriodicRecording::ExtendablePeriodicRecording() 
 :	mAcceptedRecording(0), 
 	mPotentialRecording(0)
-{
-}
+{}
 
 void ExtendablePeriodicRecording::extend()
 {
+	llassert(mPotentialRecording.getPlayState() == getPlayState());
 	// stop recording to get latest data
-	mPotentialRecording.stop();
+	mPotentialRecording.pause();
 	// push the data back to accepted recording
 	mAcceptedRecording.appendPeriodicRecording(mPotentialRecording);
 	// flush data, so we can start from scratch
@@ -654,55 +597,28 @@ void ExtendablePeriodicRecording::extend()
 	mPotentialRecording.setPlayState(getPlayState());
 }
 
-void ExtendablePeriodicRecording::start()
-{
-	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::start();
-	mPotentialRecording.start();
-}
 
-void ExtendablePeriodicRecording::stop()
+void ExtendablePeriodicRecording::handleStart()
 {
-	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::stop();
-	mPotentialRecording.stop();
+	mPotentialRecording.start();
 }
 
-void ExtendablePeriodicRecording::pause()
+void ExtendablePeriodicRecording::handleStop()
 {
-	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::pause();
 	mPotentialRecording.pause();
 }
 
-void ExtendablePeriodicRecording::resume()
-{
-	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::resume();
-	mPotentialRecording.resume();
-}
-
-void ExtendablePeriodicRecording::restart()
-{
-	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::restart();
-	mAcceptedRecording.reset();
-	mPotentialRecording.restart();
-}
-
-void ExtendablePeriodicRecording::reset()
+void ExtendablePeriodicRecording::handleReset()
 {
-	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::reset();
 	mAcceptedRecording.reset();
 	mPotentialRecording.reset();
 }
 
-void ExtendablePeriodicRecording::splitTo(ExtendablePeriodicRecording& other)
+void ExtendablePeriodicRecording::handleSplitTo(ExtendablePeriodicRecording& other)
 {
-	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::splitTo(other);
 	mPotentialRecording.splitTo(other.mPotentialRecording);
 }
 
-void ExtendablePeriodicRecording::splitFrom(ExtendablePeriodicRecording& other)
-{
-	LLStopWatchControlsMixin<ExtendablePeriodicRecording>::splitFrom(other);
-	mPotentialRecording.splitFrom(other.mPotentialRecording);
-}
 
 PeriodicRecording& get_frame_recording()
 {
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 84006a10b8..be8618a299 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -46,12 +46,12 @@ public:
 		STARTED
 	};
 
-	virtual void start();
-	virtual void stop();
-	virtual void pause();
-	virtual void resume();
-	virtual void restart();
-	virtual void reset();
+	void start();
+	void stop();
+	void pause();
+	void resume();
+	void restart();
+	void reset();
 
 	bool isStarted() const { return mPlayState == STARTED; }
 	bool isPaused() const  { return mPlayState == PAUSED; }
@@ -67,11 +67,11 @@ protected:
 
 private:
 	// trigger active behavior (without reset)
-	virtual void handleStart(){};
+	virtual void handleStart() = 0;
 	// stop active behavior
-	virtual void handleStop(){};
+	virtual void handleStop() = 0;
 	// clear accumulated state, can be called while started
-	virtual void handleReset(){};
+	virtual void handleReset() = 0;
 
 	EPlayState mPlayState;
 };
@@ -84,7 +84,13 @@ public:
 	typedef LLStopWatchControlsMixin<DERIVED> self_t;
 	virtual void splitTo(DERIVED& other)
 	{
+		EPlayState play_state = getPlayState();
+		stop();
+		other.reset();
+
 		handleSplitTo(other);
+
+		other.setPlayState(play_state);
 	}
 
 	virtual void splitFrom(DERIVED& other)
@@ -124,7 +130,9 @@ namespace LLTrace
 		LLCopyOnWritePointer<AccumulatorBuffer<MemStatAccumulator> >			mMemStats;
 	};
 
-	class Recording : public LLStopWatchControlsMixin<Recording>, public RecordingBuffers
+	class Recording 
+	:	public LLStopWatchControlsMixin<Recording>, 
+		public RecordingBuffers
 	{
 	public:
 		Recording();
@@ -367,15 +375,12 @@ namespace LLTrace
 			return mean;
 		}
 
+	private:
 		// implementation for LLStopWatchControlsMixin
-		/*virtual*/ void start();
-		/*virtual*/ void stop();
-		/*virtual*/ void pause();
-		/*virtual*/ void resume();
-		/*virtual*/ void restart();
-		/*virtual*/ void reset();
-		/*virtual*/ void splitTo(PeriodicRecording& other);
-		/*virtual*/ void splitFrom(PeriodicRecording& other);
+		/*virtual*/ void handleStart();
+		/*virtual*/ void handleStop();
+		/*virtual*/ void handleReset();
+		/*virtual*/ void handleSplitTo(PeriodicRecording& other);
 
 	private:
 		std::vector<Recording>	mRecordingPeriods;
@@ -395,15 +400,15 @@ namespace LLTrace
 		Recording& getAcceptedRecording() { return mAcceptedRecording; }
 		const Recording& getAcceptedRecording() const {return mAcceptedRecording;}
 
+		Recording& getPotentialRecording()				{ return mPotentialRecording; }
+		const Recording& getPotentialRecording() const	{ return mPotentialRecording;}
+
+	private:
 		// implementation for LLStopWatchControlsMixin
-		/*virtual*/ void start();
-		/*virtual*/ void stop();
-		/*virtual*/ void pause();
-		/*virtual*/ void resume();
-		/*virtual*/ void restart();
-		/*virtual*/ void reset();
-		/*virtual*/ void splitTo(ExtendableRecording& other);
-		/*virtual*/ void splitFrom(ExtendableRecording& other);
+		/*virtual*/ void handleStart();
+		/*virtual*/ void handleStop();
+		/*virtual*/ void handleReset();
+		/*virtual*/ void handleSplitTo(ExtendableRecording& other);
 
 	private:
 		Recording mAcceptedRecording;
@@ -419,16 +424,16 @@ namespace LLTrace
 
 		PeriodicRecording& getAcceptedRecording()				{ return mAcceptedRecording; }
 		const PeriodicRecording& getAcceptedRecording() const	{return mAcceptedRecording;}
+		
+		PeriodicRecording& getPotentialRecording()				{ return mPotentialRecording; }
+		const PeriodicRecording& getPotentialRecording() const	{return mPotentialRecording;}
 
+	private:
 		// implementation for LLStopWatchControlsMixin
-		/*virtual*/ void start();
-		/*virtual*/ void stop();
-		/*virtual*/ void pause();
-		/*virtual*/ void resume();
-		/*virtual*/ void restart();
-		/*virtual*/ void reset();
-		/*virtual*/ void splitTo(ExtendablePeriodicRecording& other);
-		/*virtual*/ void splitFrom(ExtendablePeriodicRecording& other);
+		/*virtual*/ void handleStart();
+		/*virtual*/ void handleStop();
+		/*virtual*/ void handleReset();
+		/*virtual*/ void handleSplitTo(ExtendablePeriodicRecording& other);
 
 	private:
 		PeriodicRecording mAcceptedRecording;
-- 
cgit v1.2.3


From f850ae03b399a5cc7aa32f82b8ed996518a86a2a Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 20 May 2013 00:01:57 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 fixed copy construction of Recorders, eliminated most zero-length frames
 fixed reset behavior of periodic recordings and extendable recordings to
 clear entire history removed busy-loop recording of stats from worker
 threads...stats reported only when work is done

---
 indra/llcommon/llqueuedthread.cpp   | 11 ++++++-----
 indra/llcommon/lltracerecording.cpp | 38 +++++++++++++++++++++++++++----------
 2 files changed, 34 insertions(+), 15 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 956642e97a..4339f203db 100644
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -404,6 +404,7 @@ S32 LLQueuedThread::processNextRequest()
 	QueuedRequest *req;
 	// Get next request from pool
 	lockData();
+	
 	while(1)
 	{
 		req = NULL;
@@ -468,10 +469,11 @@ S32 LLQueuedThread::processNextRequest()
 				ms_sleep(1); // sleep the thread a little
 			}
 		}
+		
+		LLTrace::get_thread_recorder()->pushToMaster();
 	}
 
 	S32 pending = getPending();
-
 	return pending;
 }
 
@@ -500,6 +502,7 @@ void LLQueuedThread::run()
 		
 		if (isQuitting())
 		{
+			LLTrace::get_thread_recorder()->pushToMaster();
 			endThread();
 			break;
 		}
@@ -508,11 +511,9 @@ void LLQueuedThread::run()
 
 		threadedUpdate();
 		
-		int res = processNextRequest();
-
-		LLTrace::get_thread_recorder()->pushToMaster();
+		int pending_work = processNextRequest();
 
-		if (res == 0)
+		if (pending_work == 0)
 		{
 			mIdleThread = TRUE;
 			ms_sleep(1);
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 6b5c6c7d3e..4aa3a5a0f7 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -133,11 +133,19 @@ Recording::Recording()
 {}
 
 Recording::Recording( const Recording& other )
-:	RecordingBuffers(other),
-	mElapsedSeconds(other.mElapsedSeconds),
-	mSamplingTimer(other.mSamplingTimer)
+:	mSamplingTimer(other.mSamplingTimer)
 {
-	LLStopWatchControlsMixin<Recording>::setPlayState(other.getPlayState());
+	Recording& mutable_other = const_cast<Recording&>(other);
+	EPlayState other_play_state = other.getPlayState();
+	mutable_other.pause();
+
+	appendBuffers(other);
+
+	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;
 }
 
 
@@ -380,9 +388,7 @@ void PeriodicRecording::nextPeriod()
 
 	Recording& old_recording = getCurRecording();
 
-	mCurPeriod = mRecordingPeriods.empty()
-				? mCurPeriod + 1
-				: (mCurPeriod + 1) % mRecordingPeriods.size();
+	mCurPeriod = (mCurPeriod + 1) % mRecordingPeriods.size();
 	old_recording.splitTo(getCurRecording());
 }
 
@@ -526,9 +532,22 @@ void PeriodicRecording::handleStop()
 
 void PeriodicRecording::handleReset()
 {
-	mRecordingPeriods.clear();
-	mRecordingPeriods.push_back(Recording());
+	if (mAutoResize)
+	{
+		mRecordingPeriods.clear();
+		mRecordingPeriods.push_back(Recording());
+	}
+	else
+	{
+		for (std::vector<Recording>::iterator it = mRecordingPeriods.begin(), end_it = mRecordingPeriods.end();
+			it != end_it;
+			++it)
+		{
+			it->reset();
+		}
+	}
 	mCurPeriod = 0;
+	getCurRecording().setPlayState(getPlayState());
 }
 
 void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
@@ -656,7 +675,6 @@ void LLStopWatchControlsMixinCommon::stop()
 	case STOPPED:
 		break;
 	case PAUSED:
-		handleStop();
 		break;
 	case STARTED:
 		handleStop();
-- 
cgit v1.2.3


From 13f43fdc5bd046f7857f06254c84b8993bdcc50a Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 20 May 2013 18:56:40 -0700
Subject: BUILDFIX: mac gcc fix

---
 indra/llcommon/llsingleton.h | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 1e87d9bd7b..b9cb8e3d41 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -67,6 +67,11 @@ private:
 		INITIALIZED,
 		DELETED
 	} EInitState;
+    
+    static DERIVED_TYPE* constructSingleton()
+    {
+        return new DERIVED_TYPE();
+    }
 	
 	// stores pointer to singleton instance
 	struct SingletonLifetimeManager
@@ -79,7 +84,7 @@ private:
 		static void construct()
 		{
 			sData.mInitState = CONSTRUCTING;
-			sData.mInstance = new DERIVED_TYPE(); 
+			sData.mInstance = constructSingleton();
 			sData.mInitState = INITIALIZING;
 		}
 
-- 
cgit v1.2.3


From ab5106535758393e02b075d1e404e4e1fcf81abf Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 20 May 2013 19:27:50 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 removed extra dereference for copy on write pointer moved copyonwrite
 mechanism to RecordingBuffers from individual buffer fixed logic that was
 leaving scene unfrozen when camera moved during metrics gathering

---
 indra/llcommon/llpointer.h               |  33 +++---
 indra/llcommon/lltracerecording.cpp      | 173 ++++++++++++++-----------------
 indra/llcommon/lltracerecording.h        |  37 ++++---
 indra/llcommon/lltracethreadrecorder.cpp |  18 ++--
 indra/llcommon/lltracethreadrecorder.h   |   3 +-
 5 files changed, 119 insertions(+), 145 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index f03551045e..b9a9bf1ef0 100644
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -166,7 +166,7 @@ protected:
 };
 
 template<typename Type>
-class LLCopyOnWritePointer
+class LLCopyOnWritePointer : public LLPointer<Type>
 {
 public:
 	typedef LLCopyOnWritePointer<Type> self_t;
@@ -175,43 +175,40 @@ public:
 	{}
 
 	LLCopyOnWritePointer(Type* ptr) 
-	:	mPointer(ptr)
+	:	LLPointer(ptr)
 	{}
 
 	LLCopyOnWritePointer(LLPointer<Type>& ptr)
-	:	mPointer(ptr)
+	:	LLPointer(ptr)
 	{}
 
 	Type* write()
 	{
 		makeUnique();
-		return mPointer.get();
+		return mPointer;
 	}
 
 	void makeUnique()
 	{
-		if (mPointer.notNull() && mPointer.get()->getNumRefs() > 1)
+		if (notNull() && mPointer->getNumRefs() > 1)
 		{
-			mPointer = new Type(*mPointer.get());
+			*(LLPointer*)(this) = new Type(*mPointer);
 		}
 	}
+	/*operator BOOL()  const						{ return (mPointer != NULL); }
+	operator bool()  const						{ return (mPointer != NULL); }
+	bool operator!() const						{ return (mPointer == NULL); }
+	bool isNull() const							{ return (mPointer == NULL); }
+	bool notNull() const						{ return (mPointer != NULL); }
 
-	operator BOOL()  const						{ return (BOOL)mPointer; }
-	operator bool()  const						{ return (bool)mPointer; }
-	bool operator!() const						{ return !mPointer; }
-	bool isNull() const							{ return mPointer.isNull(); }
-	bool notNull() const						{ return mPointer.notNull(); }
-
-	bool operator !=(Type* ptr) const           { return (mPointer.get() != ptr); 	}
-	bool operator ==(Type* ptr) const           { return (mPointer.get() == ptr); 	}
+	bool operator !=(Type* ptr) const           { return (mPointer != ptr); 	}
+	bool operator ==(Type* ptr) const           { return (mPointer == ptr); 	}
 	bool operator ==(const LLCopyOnWritePointer<Type>& ptr) const     { return (mPointer == ptr.mPointer); 	}
 	bool operator < (const LLCopyOnWritePointer<Type>& ptr) const     { return (mPointer < ptr.mPointer); 	}
 	bool operator > (const LLCopyOnWritePointer<Type>& ptr) const     { return (mPointer > ptr.mPointer); 	}
 
-	operator const Type*()   const				{ return mPointer.get(); }
-	const Type*	operator->() const				{ return mPointer.get(); }
-protected:
-	 LLPointer<Type> mPointer;
+	operator const Type*()   const				{ return mPointer; }
+	const Type*	operator->() const				{ return mPointer; }*/
 };
 
 #endif
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 4aa3a5a0f7..cced6546ba 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -40,37 +40,31 @@ namespace LLTrace
 ///////////////////////////////////////////////////////////////////////
 
 RecordingBuffers::RecordingBuffers() 
-:	mCountsFloat(new AccumulatorBuffer<CountAccumulator<F64> >()),
-	mMeasurementsFloat(new AccumulatorBuffer<MeasurementAccumulator<F64> >()),
-	mCounts(new AccumulatorBuffer<CountAccumulator<S64> >()),
-	mMeasurements(new AccumulatorBuffer<MeasurementAccumulator<S64> >()),
-	mStackTimers(new AccumulatorBuffer<TimeBlockAccumulator>()),
-	mMemStats(new AccumulatorBuffer<MemStatAccumulator>())
 {}
 
 void RecordingBuffers::handOffTo(RecordingBuffers& other)
 {
-	other.mCountsFloat.write()->reset(mCountsFloat);
-	other.mMeasurementsFloat.write()->reset(mMeasurementsFloat);
-	other.mCounts.write()->reset(mCounts);
-	other.mMeasurements.write()->reset(mMeasurements);
-	other.mStackTimers.write()->reset(mStackTimers);
-	other.mMemStats.write()->reset(mMemStats);
+	other.mCountsFloat.reset(&mCountsFloat);
+	other.mMeasurementsFloat.reset(&mMeasurementsFloat);
+	other.mCounts.reset(&mCounts);
+	other.mMeasurements.reset(&mMeasurements);
+	other.mStackTimers.reset(&mStackTimers);
+	other.mMemStats.reset(&mMemStats);
 }
 
 void RecordingBuffers::makePrimary()
 {
-	mCountsFloat.write()->makePrimary();
-	mMeasurementsFloat.write()->makePrimary();
-	mCounts.write()->makePrimary();
-	mMeasurements.write()->makePrimary();
-	mStackTimers.write()->makePrimary();
-	mMemStats.write()->makePrimary();
+	mCountsFloat.makePrimary();
+	mMeasurementsFloat.makePrimary();
+	mCounts.makePrimary();
+	mMeasurements.makePrimary();
+	mStackTimers.makePrimary();
+	mMemStats.makePrimary();
 
 	ThreadRecorder* thread_recorder = get_thread_recorder().get();
-	AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = *mStackTimers.write();
+	AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers;
 	// update stacktimer parent pointers
-	for (S32 i = 0, end_i = mStackTimers->size(); i < end_i; i++)
+	for (S32 i = 0, end_i = mStackTimers.size(); i < end_i; i++)
 	{
 		TimeBlockTreeNode* tree_node = thread_recorder->getTimeBlockTreeNode(i);
 		if (tree_node)
@@ -82,46 +76,36 @@ void RecordingBuffers::makePrimary()
 
 bool RecordingBuffers::isPrimary() const
 {
-	return mCounts->isPrimary();
+	return mCounts.isPrimary();
 }
 
-void RecordingBuffers::makeUnique()
+void RecordingBuffers::append( const RecordingBuffers& other )
 {
-	mCountsFloat.makeUnique();
-	mMeasurementsFloat.makeUnique();
-	mCounts.makeUnique();
-	mMeasurements.makeUnique();
-	mStackTimers.makeUnique();
-	mMemStats.makeUnique();
+	mCountsFloat.addSamples(other.mCountsFloat);
+	mMeasurementsFloat.addSamples(other.mMeasurementsFloat);
+	mCounts.addSamples(other.mCounts);
+	mMeasurements.addSamples(other.mMeasurements);
+	mMemStats.addSamples(other.mMemStats);
+	mStackTimers.addSamples(other.mStackTimers);
 }
 
-void RecordingBuffers::appendBuffers( const RecordingBuffers& other )
+void RecordingBuffers::merge( const RecordingBuffers& other)
 {
-	mCountsFloat.write()->addSamples(*other.mCountsFloat);
-	mMeasurementsFloat.write()->addSamples(*other.mMeasurementsFloat);
-	mCounts.write()->addSamples(*other.mCounts);
-	mMeasurements.write()->addSamples(*other.mMeasurements);
-	mMemStats.write()->addSamples(*other.mMemStats);
-	mStackTimers.write()->addSamples(*other.mStackTimers);
+	mCountsFloat.addSamples(other.mCountsFloat);
+	mMeasurementsFloat.addSamples(other.mMeasurementsFloat);
+	mCounts.addSamples(other.mCounts);
+	mMeasurements.addSamples(other.mMeasurements);
+	mMemStats.addSamples(other.mMemStats);
 }
 
-void RecordingBuffers::mergeBuffers( const RecordingBuffers& other)
+void RecordingBuffers::reset(RecordingBuffers* other)
 {
-	mCountsFloat.write()->addSamples(*other.mCountsFloat);
-	mMeasurementsFloat.write()->addSamples(*other.mMeasurementsFloat);
-	mCounts.write()->addSamples(*other.mCounts);
-	mMeasurements.write()->addSamples(*other.mMeasurements);
-	mMemStats.write()->addSamples(*other.mMemStats);
-}
-
-void RecordingBuffers::resetBuffers(RecordingBuffers* other)
-{
-	mCountsFloat.write()->reset(other ? other->mCountsFloat : LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<F64> > >());
-	mMeasurementsFloat.write()->reset(other ? other->mMeasurementsFloat : LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > >());
-	mCounts.write()->reset(other ? other->mCounts : LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<S64> > >());
-	mMeasurements.write()->reset(other ? other->mMeasurements : LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<S64> > >());
-	mStackTimers.write()->reset(other ? other->mStackTimers : LLCopyOnWritePointer<AccumulatorBuffer<TimeBlockAccumulator> >());
-	mMemStats.write()->reset(other ? other->mMemStats : LLCopyOnWritePointer<AccumulatorBuffer<MemStatAccumulator> >());
+	mCountsFloat.reset(other ? &other->mCountsFloat : NULL);
+	mMeasurementsFloat.reset(other ? &other->mMeasurementsFloat : NULL);
+	mCounts.reset(other ? &other->mCounts : NULL);
+	mMeasurements.reset(other ? &other->mMeasurements : NULL);
+	mStackTimers.reset(other ? &other->mStackTimers : NULL);
+	mMemStats.reset(other ? &other->mMemStats : NULL);
 }
 
 ///////////////////////////////////////////////////////////////////////
@@ -130,22 +114,24 @@ void RecordingBuffers::resetBuffers(RecordingBuffers* other)
 
 Recording::Recording() 
 :	mElapsedSeconds(0)
-{}
+{
+	mBuffers = new RecordingBuffers();
+}
 
 Recording::Recording( const Recording& other )
-:	mSamplingTimer(other.mSamplingTimer)
 {
 	Recording& mutable_other = const_cast<Recording&>(other);
 	EPlayState other_play_state = other.getPlayState();
 	mutable_other.pause();
 
-	appendBuffers(other);
+	mBuffers = 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;
 }
 
 
@@ -166,7 +152,7 @@ void Recording::update()
 
 void Recording::handleReset()
 {
-	resetBuffers();
+	mBuffers.write()->reset();
 
 	mElapsedSeconds = 0.0;
 	mSamplingTimer.reset();
@@ -187,42 +173,42 @@ void Recording::handleStop()
 
 void Recording::handleSplitTo(Recording& other)
 {
-	handOffTo(other);
+	mBuffers.write()->handOffTo(*other.mBuffers.write());
 }
 
 void Recording::appendRecording( const Recording& other )
 {
-	appendBuffers(other);
+	mBuffers.write()->append(*other.mBuffers);
 	mElapsedSeconds += other.mElapsedSeconds;
 }
 
 void Recording::mergeRecording( const Recording& other)
 {
-	mergeBuffers(other);
+	mBuffers.write()->merge(*other.mBuffers);
 }
 
 LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) const
 {
-	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
+	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 	return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
 				/ (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
 LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const
 {
-	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
+	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 	return (F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
 
 U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const
 {
-	return (*mStackTimers)[stat.getIndex()].mCalls;
+	return mBuffers->mStackTimers[stat.getIndex()].mCalls;
 }
 
 LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat) const
 {
-	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
+	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
 	return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
 				/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
@@ -230,7 +216,7 @@ LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccu
 
 LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const
 {
-	const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()];
+	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
 	return (F64)(accumulator.mSelfTimeCounter) 
 			/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
@@ -238,45 +224,45 @@ LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccu
 
 F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const
 {
-	return (F32)(*mStackTimers)[stat.getIndex()].mCalls / mElapsedSeconds;
+	return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds;
 }
 
 LLUnit<LLUnits::Bytes, U32> Recording::getSum(const TraceType<MemStatAccumulator>& stat) const
 {
-	return (*mMemStats)[stat.getIndex()].mAllocatedCount;
+	return mBuffers->mMemStats[stat.getIndex()].mAllocatedCount;
 }
 
 LLUnit<LLUnits::Bytes, F32> Recording::getPerSec(const TraceType<MemStatAccumulator>& stat) const
 {
-	return (F32)(*mMemStats)[stat.getIndex()].mAllocatedCount / mElapsedSeconds;
+	return (F32)mBuffers->mMemStats[stat.getIndex()].mAllocatedCount / mElapsedSeconds;
 }
 
 
 F64 Recording::getSum( const TraceType<CountAccumulator<F64> >& stat ) const
 {
-	return (*mCountsFloat)[stat.getIndex()].getSum();
+	return mBuffers->mCountsFloat[stat.getIndex()].getSum();
 }
 
 S64 Recording::getSum( const TraceType<CountAccumulator<S64> >& stat ) const
 {
-	return (*mCounts)[stat.getIndex()].getSum();
+	return mBuffers->mCounts[stat.getIndex()].getSum();
 }
 
 F64 Recording::getSum( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return (F64)(*mMeasurementsFloat)[stat.getIndex()].getSum();
+	return (F64)mBuffers->mMeasurementsFloat[stat.getIndex()].getSum();
 }
 
 S64 Recording::getSum( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (S64)(*mMeasurements)[stat.getIndex()].getSum();
+	return (S64)mBuffers->mMeasurements[stat.getIndex()].getSum();
 }
 
 
 
 F64 Recording::getPerSec( const TraceType<CountAccumulator<F64> >& stat ) const
 {
-	F64 sum = (*mCountsFloat)[stat.getIndex()].getSum();
+	F64 sum = mBuffers->mCountsFloat[stat.getIndex()].getSum();
 	return  (sum != 0.0) 
 		? (sum / mElapsedSeconds)
 		: 0.0;
@@ -284,7 +270,7 @@ F64 Recording::getPerSec( const TraceType<CountAccumulator<F64> >& stat ) const
 
 F64 Recording::getPerSec( const TraceType<CountAccumulator<S64> >& stat ) const
 {
-	S64 sum = (*mCounts)[stat.getIndex()].getSum();
+	S64 sum = mBuffers->mCounts[stat.getIndex()].getSum();
 	return (sum != 0) 
 		? ((F64)sum / mElapsedSeconds)
 		: 0.0;
@@ -292,72 +278,72 @@ F64 Recording::getPerSec( const TraceType<CountAccumulator<S64> >& stat ) const
 
 U32 Recording::getSampleCount( const TraceType<CountAccumulator<F64> >& stat ) const
 {
-	return (*mCountsFloat)[stat.getIndex()].getSampleCount();
+	return mBuffers->mCountsFloat[stat.getIndex()].getSampleCount();
 }
 
 U32 Recording::getSampleCount( const TraceType<CountAccumulator<S64> >& stat ) const
 {
-	return (*mMeasurementsFloat)[stat.getIndex()].getSampleCount();
+	return mBuffers->mMeasurementsFloat[stat.getIndex()].getSampleCount();
 }
 
 F64 Recording::getMin( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return (*mMeasurementsFloat)[stat.getIndex()].getMin();
+	return mBuffers->mMeasurementsFloat[stat.getIndex()].getMin();
 }
 
 S64 Recording::getMin( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (*mMeasurements)[stat.getIndex()].getMin();
+	return mBuffers->mMeasurements[stat.getIndex()].getMin();
 }
 
 F64 Recording::getMax( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return (*mMeasurementsFloat)[stat.getIndex()].getMax();
+	return mBuffers->mMeasurementsFloat[stat.getIndex()].getMax();
 }
 
 S64 Recording::getMax( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (*mMeasurements)[stat.getIndex()].getMax();
+	return mBuffers->mMeasurements[stat.getIndex()].getMax();
 }
 
 F64 Recording::getMean( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return (*mMeasurementsFloat)[stat.getIndex()].getMean();
+	return mBuffers->mMeasurementsFloat[stat.getIndex()].getMean();
 }
 
 F64 Recording::getMean( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (*mMeasurements)[stat.getIndex()].getMean();
+	return mBuffers->mMeasurements[stat.getIndex()].getMean();
 }
 
 F64 Recording::getStandardDeviation( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return (*mMeasurementsFloat)[stat.getIndex()].getStandardDeviation();
+	return mBuffers->mMeasurementsFloat[stat.getIndex()].getStandardDeviation();
 }
 
 F64 Recording::getStandardDeviation( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (*mMeasurements)[stat.getIndex()].getStandardDeviation();
+	return mBuffers->mMeasurements[stat.getIndex()].getStandardDeviation();
 }
 
 F64 Recording::getLastValue( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return (*mMeasurementsFloat)[stat.getIndex()].getLastValue();
+	return mBuffers->mMeasurementsFloat[stat.getIndex()].getLastValue();
 }
 
 S64 Recording::getLastValue( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (*mMeasurements)[stat.getIndex()].getLastValue();
+	return mBuffers->mMeasurements[stat.getIndex()].getLastValue();
 }
 
 U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<F64> >& stat ) const
 {
-	return (*mMeasurementsFloat)[stat.getIndex()].getSampleCount();
+	return mBuffers->mMeasurementsFloat[stat.getIndex()].getSampleCount();
 }
 
 U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<S64> >& stat ) const
 {
-	return (*mMeasurements)[stat.getIndex()].getSampleCount();
+	return mBuffers->mMeasurements[stat.getIndex()].getSampleCount();
 }
 
 ///////////////////////////////////////////////////////////////////////
@@ -366,16 +352,9 @@ U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<S64> >& st
 
 PeriodicRecording::PeriodicRecording( U32 num_periods, EPlayState state) 
 :	mAutoResize(num_periods == 0),
-	mCurPeriod(0)
+	mCurPeriod(0),
+	mRecordingPeriods(num_periods ? num_periods : 1)
 {
-	if (mAutoResize) 
-	{
-		num_periods = 1;
-	}
-	if (num_periods)
-	{
-		mRecordingPeriods.resize(num_periods);
-	}
 	setPlayState(state);
 }
 
@@ -552,7 +531,7 @@ void PeriodicRecording::handleReset()
 
 void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
 {
-	getCurRecording().handOffTo(other.getCurRecording());
+	getCurRecording().splitTo(other.getCurRecording());
 }
 
 ///////////////////////////////////////////////////////////////////////
@@ -589,7 +568,7 @@ void ExtendableRecording::handleReset()
 
 void ExtendableRecording::handleSplitTo(ExtendableRecording& other)
 {
-	mPotentialRecording.handOffTo(other.mPotentialRecording);
+	mPotentialRecording.splitTo(other.mPotentialRecording);
 }
 
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index be8618a299..b339e72e5c 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -106,33 +106,28 @@ private:
 
 namespace LLTrace
 {
-	class RecordingBuffers
+	struct RecordingBuffers : public LLRefCount
 	{
-	public:
 		RecordingBuffers();
 
 		void handOffTo(RecordingBuffers& other);
 		void makePrimary();
 		bool isPrimary() const;
 
-		void makeUnique();
-
-		void appendBuffers(const RecordingBuffers& other);
-		void mergeBuffers(const RecordingBuffers& other);
-		void resetBuffers(RecordingBuffers* other = NULL);
+		void append(const RecordingBuffers& other);
+		void merge(const RecordingBuffers& other);
+		void reset(RecordingBuffers* other = NULL);
 
-	protected:
-		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<F64> > >		mCountsFloat;
-		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<F64> > >	mMeasurementsFloat;
-		LLCopyOnWritePointer<AccumulatorBuffer<CountAccumulator<S64> > >		mCounts;
-		LLCopyOnWritePointer<AccumulatorBuffer<MeasurementAccumulator<S64> > >	mMeasurements;
-		LLCopyOnWritePointer<AccumulatorBuffer<TimeBlockAccumulator> >			mStackTimers;
-		LLCopyOnWritePointer<AccumulatorBuffer<MemStatAccumulator> >			mMemStats;
+		AccumulatorBuffer<CountAccumulator<F64> > 		mCountsFloat;
+		AccumulatorBuffer<MeasurementAccumulator<F64> > mMeasurementsFloat;
+		AccumulatorBuffer<CountAccumulator<S64> > 		mCounts;
+		AccumulatorBuffer<MeasurementAccumulator<S64> > mMeasurements;
+		AccumulatorBuffer<TimeBlockAccumulator> 		mStackTimers;
+		AccumulatorBuffer<MemStatAccumulator> 			mMemStats;
 	};
 
 	class Recording 
-	:	public LLStopWatchControlsMixin<Recording>, 
-		public RecordingBuffers
+	:	public LLStopWatchControlsMixin<Recording>
 	{
 	public:
 		Recording();
@@ -149,6 +144,9 @@ namespace LLTrace
 		// grab latest recorded data
 		void update();
 
+		// ensure that buffers are exclusively owned by this recording
+		void makeUnique() { mBuffers.makeUnique(); }
+
 		// Timer accessors
 		LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator>& stat) const;
 		LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const;
@@ -237,7 +235,7 @@ namespace LLTrace
 
 		LLUnit<LLUnits::Seconds, F64> getDuration() const { return LLUnit<LLUnits::Seconds, F64>(mElapsedSeconds); }
 
-	private:
+	protected:
 		friend class ThreadRecorder;
 
 		// implementation for LLStopWatchControlsMixin
@@ -249,8 +247,9 @@ namespace LLTrace
 		// returns data for current thread
 		class ThreadRecorder* getThreadRecorder(); 
 
-		LLTimer			mSamplingTimer;
-		F64				mElapsedSeconds;
+		LLTimer				mSamplingTimer;
+		F64					mElapsedSeconds;
+		LLCopyOnWritePointer<RecordingBuffers>	mBuffers;
 	};
 
 	class LL_COMMON_API PeriodicRecording
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 9bef040cf7..2001b9cd7f 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -118,7 +118,7 @@ ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::update( Record
 		if (next_it != mActiveRecordings.end())
 		{
 			// ...push our gathered data down to it
-			(*next_it)->mPartialRecording.appendBuffers((*it)->mPartialRecording);
+			(*next_it)->mPartialRecording.append((*it)->mPartialRecording);
 		}
 
 		// copy accumulated measurements into result buffer and clear accumulator (mPartialRecording)
@@ -156,7 +156,7 @@ void ThreadRecorder::deactivate( Recording* recording )
 		++next_it;
 		if (next_it != mActiveRecordings.end())
 		{
-			(*next_it)->mTargetRecording->makePrimary();
+			(*next_it)->mTargetRecording->mBuffers.write()->makePrimary();
 		}
 
 		delete *it;
@@ -171,8 +171,8 @@ ThreadRecorder::ActiveRecording::ActiveRecording( Recording* target )
 
 void ThreadRecorder::ActiveRecording::moveBaselineToTarget()
 {
-	mTargetRecording->appendBuffers(mPartialRecording);
-	mPartialRecording.resetBuffers();
+	mTargetRecording->mBuffers.write()->append(mPartialRecording);
+	mPartialRecording.reset();
 }
 
 
@@ -203,31 +203,31 @@ void SlaveThreadRecorder::pushToMaster()
 void SlaveThreadRecorder::SharedData::appendFrom( const Recording& source )
 {
 	LLMutexLock lock(&mRecordingMutex);
-	mRecording.appendRecording(source);
+	appendRecording(source);
 }
 
 void SlaveThreadRecorder::SharedData::appendTo( Recording& sink )
 {
 	LLMutexLock lock(&mRecordingMutex);
-	sink.appendRecording(mRecording);
+	sink.appendRecording(*this);
 }
 
 void SlaveThreadRecorder::SharedData::mergeFrom( const RecordingBuffers& source )
 {
 	LLMutexLock lock(&mRecordingMutex);
-	mRecording.mergeBuffers(source);
+	mBuffers.write()->merge(source);
 }
 
 void SlaveThreadRecorder::SharedData::mergeTo( RecordingBuffers& sink )
 {
 	LLMutexLock lock(&mRecordingMutex);
-	sink.mergeBuffers(mRecording);
+	sink.merge(*mBuffers);
 }
 
 void SlaveThreadRecorder::SharedData::reset()
 {
 	LLMutexLock lock(&mRecordingMutex);
-	mRecording.reset();
+	Recording::reset();
 }
 
 
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 3e24303d92..c44bcbd12d 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -106,7 +106,7 @@ namespace LLTrace
 
 		MasterThreadRecorder* 	mMaster;
 
-		class SharedData
+		class SharedData : public Recording
 		{
 		public:
 			void appendFrom(const Recording& source);
@@ -116,7 +116,6 @@ namespace LLTrace
 			void reset();
 		private:
 			LLMutex		mRecordingMutex;
-			Recording	mRecording;
 		};
 		SharedData		mSharedData;
 	};
-- 
cgit v1.2.3


From 7aeac00e444ebf3fdc73bdc4be3c47bb9ae65e43 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 21 May 2013 10:20:30 -0700
Subject: BUIDLFIX: trying to make gcc happy

---
 indra/llcommon/llpointer.h | 22 ++++------------------
 1 file changed, 4 insertions(+), 18 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index b9a9bf1ef0..3273a85af1 100644
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -175,11 +175,11 @@ public:
 	{}
 
 	LLCopyOnWritePointer(Type* ptr) 
-	:	LLPointer(ptr)
+	:	LLPointer<Type>(ptr)
 	{}
 
 	LLCopyOnWritePointer(LLPointer<Type>& ptr)
-	:	LLPointer(ptr)
+	:	LLPointer<Type>(ptr)
 	{}
 
 	Type* write()
@@ -190,25 +190,11 @@ public:
 
 	void makeUnique()
 	{
-		if (notNull() && mPointer->getNumRefs() > 1)
+		if (LLPointer<Type>::notNull() && mPointer->getNumRefs() > 1)
 		{
-			*(LLPointer*)(this) = new Type(*mPointer);
+			*(LLPointer<Type>*)(this) = new Type(*mPointer);
 		}
 	}
-	/*operator BOOL()  const						{ return (mPointer != NULL); }
-	operator bool()  const						{ return (mPointer != NULL); }
-	bool operator!() const						{ return (mPointer == NULL); }
-	bool isNull() const							{ return (mPointer == NULL); }
-	bool notNull() const						{ return (mPointer != NULL); }
-
-	bool operator !=(Type* ptr) const           { return (mPointer != ptr); 	}
-	bool operator ==(Type* ptr) const           { return (mPointer == ptr); 	}
-	bool operator ==(const LLCopyOnWritePointer<Type>& ptr) const     { return (mPointer == ptr.mPointer); 	}
-	bool operator < (const LLCopyOnWritePointer<Type>& ptr) const     { return (mPointer < ptr.mPointer); 	}
-	bool operator > (const LLCopyOnWritePointer<Type>& ptr) const     { return (mPointer > ptr.mPointer); 	}
-
-	operator const Type*()   const				{ return mPointer; }
-	const Type*	operator->() const				{ return mPointer; }*/
 };
 
 #endif
-- 
cgit v1.2.3


From 269fb97eba380baf5674178294bf86fb01cd712c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 21 May 2013 10:28:21 -0700
Subject: BUILDFIX: gcc fixes

---
 indra/llcommon/llpointer.h | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index 3273a85af1..c83e55577d 100644
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -170,7 +170,8 @@ class LLCopyOnWritePointer : public LLPointer<Type>
 {
 public:
 	typedef LLCopyOnWritePointer<Type> self_t;
-
+    typedef LLPointer<Type> pointer_t;
+    
 	LLCopyOnWritePointer() 
 	{}
 
@@ -185,14 +186,14 @@ public:
 	Type* write()
 	{
 		makeUnique();
-		return mPointer;
+		return pointer_t::mPointer;
 	}
 
 	void makeUnique()
 	{
-		if (LLPointer<Type>::notNull() && mPointer->getNumRefs() > 1)
+		if (pointer_t::notNull() && pointer_t::mPointer->getNumRefs() > 1)
 		{
-			*(LLPointer<Type>*)(this) = new Type(*mPointer);
+			*(pointer_t*)(this) = new Type(*pointer_t::mPointer);
 		}
 	}
 };
-- 
cgit v1.2.3


From 9ae76d12157641033431381959ef4f798a119b8d Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 29 May 2013 17:00:50 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 fixed copy construction behavior of Recordings to not zero out data split
 measurement into event and sample, with sample representing a continuous
 function

---
 indra/llcommon/llthread.cpp              |   2 +-
 indra/llcommon/llthreadlocalstorage.h    |   4 +
 indra/llcommon/lltrace.cpp               |  14 +-
 indra/llcommon/lltrace.h                 | 234 +++++++++++++++++++++++++----
 indra/llcommon/lltracerecording.cpp      | 188 ++++++++++++++++++------
 indra/llcommon/lltracerecording.h        | 244 ++++++++++++++++++++++++++-----
 indra/llcommon/lltracethreadrecorder.cpp |  78 +++++-----
 indra/llcommon/lltracethreadrecorder.h   |  13 +-
 8 files changed, 615 insertions(+), 162 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 6374b5398b..118568d5ef 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -93,7 +93,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 {
 	LLThread *threadp = (LLThread *)datap;
 
-	LLTrace::ThreadRecorder* thread_recorder = new LLTrace::SlaveThreadRecorder();
+	LLTrace::ThreadRecorder* thread_recorder = new LLTrace::SlaveThreadRecorder(LLTrace::getUIThreadRecorder());
 
 #if !LL_DARWIN
 	sThreadID = threadp->mID;
diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
index 4873b2740d..471784749b 100644
--- a/indra/llcommon/llthreadlocalstorage.h
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -131,6 +131,10 @@ public:
 		if (!sInitialized) return false;
 		return get() == other;
 	}
+
+	bool isNull() const { return !sInitialized || get() == NULL; }
+
+	bool notNull() const { return sInitialized && get() != NULL; }
 };
 
 template<typename DERIVED_TYPE>
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 463048008f..c831a1548d 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -35,13 +35,13 @@ static S32 sInitializationCount = 0;
 namespace LLTrace
 {
 
-static MasterThreadRecorder* gMasterThreadRecorder = NULL;
+static MasterThreadRecorder* gUIThreadRecorder = NULL;
 
 void init()
 {
 	if (sInitializationCount++ == 0)
 	{
-		gMasterThreadRecorder = new MasterThreadRecorder();
+		gUIThreadRecorder = new MasterThreadRecorder();
 	}
 }
 
@@ -54,15 +54,15 @@ void cleanup()
 {
 	if (--sInitializationCount == 0)
 	{
-		delete gMasterThreadRecorder;
-		gMasterThreadRecorder = NULL;
+		delete gUIThreadRecorder;
+		gUIThreadRecorder = NULL;
 	}
 }
 
-MasterThreadRecorder& getMasterThreadRecorder()
+MasterThreadRecorder& getUIThreadRecorder()
 {
-	llassert(gMasterThreadRecorder != NULL);
-	return *gMasterThreadRecorder;
+	llassert(gUIThreadRecorder != NULL);
+	return *gUIThreadRecorder;
 }
 
 LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder_ptr()
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index d1edaf969b..f94576de45 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -73,7 +73,7 @@ bool isInitialized();
 const LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder();
 void set_thread_recorder(class ThreadRecorder*);
 
-class MasterThreadRecorder& getMasterThreadRecorder();
+class MasterThreadRecorder& getUIThreadRecorder();
 
 // one per thread per type
 template<typename ACCUMULATOR>
@@ -148,6 +148,15 @@ public:
 		}
 	}
 
+	void flush()
+	{
+		llassert(mStorageSize >= sNextStorageSlot);
+		for (size_t i = 0; i < sNextStorageSlot; i++)
+		{
+			mStorage[i].flush();
+		}
+	}
+
 	void makePrimary()
 	{
 		LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(mStorage);
@@ -260,14 +269,14 @@ protected:
 };
 
 template<typename T>
-class MeasurementAccumulator
+class EventAccumulator
 {
 public:
 	typedef T value_t;
 	typedef F64 mean_t;
-	typedef MeasurementAccumulator<T> self_t;
+	typedef EventAccumulator<T> self_t;
 
-	MeasurementAccumulator()
+	EventAccumulator()
 	:	mSum(0),
 		mMin((std::numeric_limits<T>::max)()),
 		mMax((std::numeric_limits<T>::min)()),
@@ -277,7 +286,7 @@ public:
 		mLastValue(0)
 	{}
 
-	void sample(T value)
+	void record(T value)
 	{
 		mNumSamples++;
 		mSum += value;
@@ -301,17 +310,10 @@ public:
 		if (other.mNumSamples)
 		{
 			mSum += other.mSum;
-			if (other.mMin < mMin)
-			{
-				mMin = other.mMin;
-			}
-			if (other.mMax > mMax)
-			{
-				mMax = other.mMax;
-			}
-			F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
-			mNumSamples += other.mNumSamples;
-			mMean = mMean * weight + other.mMean * (1.f - weight);
+
+			// NOTE: both conditions will hold first time through
+			if (other.mMin < mMin) { mMin = other.mMin; }
+			if (other.mMax > mMax) { mMax = other.mMax; }
 
 			// combine variance (and hence standard deviation) of 2 different sized sample groups using
 			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
@@ -333,12 +335,16 @@ public:
 			else
 			{
 				mVarianceSum = (F64)mNumSamples
-					* ((((n_1 - 1.f) * v_1)
-					+ ((n_2 - 1.f) * v_2)
-					+ (((n_1 * n_2) / (n_1 + n_2))
-					* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
-					/ (n_1 + n_2 - 1.f));
+								* ((((n_1 - 1.f) * v_1)
+									+ ((n_2 - 1.f) * v_2)
+									+ (((n_1 * n_2) / (n_1 + n_2))
+										* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+									/ (n_1 + n_2 - 1.f));
 			}
+
+			F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
+			mNumSamples += other.mNumSamples;
+			mMean = mMean * weight + other.mMean * (1.f - weight);
 			mLastValue = other.mLastValue;
 		}
 	}
@@ -347,13 +353,15 @@ public:
 	{
 		mNumSamples = 0;
 		mSum = 0;
-		mMin = 0;
-		mMax = 0;
+		mMin = std::numeric_limits<T>::max();
+		mMax = std::numeric_limits<T>::min();
 		mMean = 0;
 		mVarianceSum = 0;
 		mLastValue = other ? other->mLastValue : 0;
 	}
 
+	void flush() {}
+
 	T	getSum() const { return (T)mSum; }
 	T	getMin() const { return (T)mMin; }
 	T	getMax() const { return (T)mMax; }
@@ -375,6 +383,150 @@ private:
 };
 
 
+template<typename T>
+class SampleAccumulator
+{
+public:
+	typedef T value_t;
+	typedef F64 mean_t;
+	typedef SampleAccumulator<T> self_t;
+
+	SampleAccumulator()
+	:	mSum(0),
+		mMin((std::numeric_limits<T>::max)()),
+		mMax((std::numeric_limits<T>::min)()),
+		mMean(0),
+		mVarianceSum(0),
+		mLastSampleTimeStamp(LLTimer::getTotalSeconds()),
+		mTotalSamplingTime(0),
+		mNumSamples(0),
+		mLastValue(0),
+		mHasValue(false)
+	{}
+
+	void sample(T value)
+	{
+		LLUnitImplicit<LLUnits::Seconds, F64> time_stamp = LLTimer::getTotalSeconds();
+		LLUnitImplicit<LLUnits::Seconds, F64> delta_time = time_stamp - mLastSampleTimeStamp;
+		mLastSampleTimeStamp = time_stamp;
+
+		if (mHasValue)
+		{
+			mTotalSamplingTime += delta_time;
+			mSum += (F64)mLastValue * delta_time;
+
+			// NOTE: both conditions will hold first time through
+			if (value < mMin) { mMin = value; }
+			if (value > mMax) { mMax = value; }
+
+			F64 old_mean = mMean;
+			mMean += (delta_time / mTotalSamplingTime) * ((F64)mLastValue - old_mean);
+			mVarianceSum += delta_time * ((F64)mLastValue - old_mean) * ((F64)mLastValue - mMean);
+		}
+
+		mLastValue = value;
+		mNumSamples++;
+		mHasValue = true;
+	}
+
+	void addSamples(const self_t& other)
+	{
+		if (other.mTotalSamplingTime)
+		{
+			mSum += other.mSum;
+
+			// NOTE: both conditions will hold first time through
+			if (other.mMin < mMin) { mMin = other.mMin; }
+			if (other.mMax > mMax) { mMax = other.mMax; }
+
+			// combine variance (and hence standard deviation) of 2 different sized sample groups using
+			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+			F64 n_1 = mTotalSamplingTime,
+				n_2 = other.mTotalSamplingTime;
+			F64 m_1 = mMean,
+				m_2 = other.mMean;
+			F64 v_1 = mVarianceSum / mTotalSamplingTime,
+				v_2 = other.mVarianceSum / other.mTotalSamplingTime;
+			if (n_1 == 0)
+			{
+				mVarianceSum = other.mVarianceSum;
+			}
+			else if (n_2 == 0)
+			{
+				// variance is unchanged
+				// mVarianceSum = mVarianceSum;
+			}
+			else
+			{
+				mVarianceSum =	mTotalSamplingTime
+								* ((((n_1 - 1.f) * v_1)
+									+ ((n_2 - 1.f) * v_2)
+									+ (((n_1 * n_2) / (n_1 + n_2))
+										* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+									/ (n_1 + n_2 - 1.f));
+			}
+
+			llassert(other.mTotalSamplingTime > 0);
+			F64 weight = mTotalSamplingTime / (mTotalSamplingTime + other.mTotalSamplingTime);
+			mNumSamples += other.mNumSamples;
+			mTotalSamplingTime += other.mTotalSamplingTime;
+			mMean = (mMean * weight) + (other.mMean * (1.0 - weight));
+			mLastValue = other.mLastValue;
+			mLastSampleTimeStamp = other.mLastSampleTimeStamp;
+			mHasValue |= other.mHasValue;
+		}
+	}
+
+	void reset(const self_t* other)
+	{
+		mNumSamples = 0;
+		mSum = 0;
+		mMin = std::numeric_limits<T>::max();
+		mMax = std::numeric_limits<T>::min();
+		mMean = other ? other->mLastValue : 0;
+		mVarianceSum = 0;
+		mLastSampleTimeStamp = LLTimer::getTotalSeconds();
+		mTotalSamplingTime = 0;
+		mLastValue = other ? other->mLastValue : 0;
+		mHasValue = other ? other->mHasValue : false;
+	}
+
+	void flush()
+	{
+		LLUnitImplicit<LLUnits::Seconds, F64> time_stamp = LLTimer::getTotalSeconds();
+		LLUnitImplicit<LLUnits::Seconds, F64> delta_time = time_stamp - mLastSampleTimeStamp;
+
+		mSum += (F64)mLastValue * delta_time;
+
+		mTotalSamplingTime += delta_time;
+		mLastSampleTimeStamp = time_stamp;
+	}
+
+	T	getSum() const { return (T)mSum; }
+	T	getMin() const { return (T)mMin; }
+	T	getMax() const { return (T)mMax; }
+	T	getLastValue() const { return (T)mLastValue; }
+	F64	getMean() const { return mMean; }
+	F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mTotalSamplingTime); }
+	U32 getSampleCount() const { return mNumSamples; }
+
+private:
+	T	mSum,
+		mMin,
+		mMax,
+		mLastValue;
+
+	bool mHasValue;
+
+	F64	mMean,
+		mVarianceSum;
+
+	LLUnitImplicit<LLUnits::Seconds, F64>	mLastSampleTimeStamp,
+											mTotalSamplingTime;
+
+	U32	mNumSamples;
+};
+
 template<typename T>
 class CountAccumulator
 {
@@ -406,6 +558,8 @@ public:
 		mSum = 0;
 	}
 
+	void flush() {}
+
 	T	getSum() const { return (T)mSum; }
 
 	U32 getSampleCount() const { return mNumSamples; }
@@ -439,6 +593,7 @@ public:
 	TimeBlockAccumulator();
 	void addSamples(const self_t& other);
 	void reset(const self_t* other);
+	void flush() {}
 
 	//
 	// members
@@ -493,25 +648,44 @@ public:
 
 
 template <typename T = F64>
-class MeasurementStatHandle
-:	public TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
+class EventStatHandle
+:	public TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
 {
 public:
 	typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
-	typedef TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> > trace_t;
+	typedef TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> > trace_t;
 
-	MeasurementStatHandle(const char* name, const char* description = NULL) 
+	EventStatHandle(const char* name, const char* description = NULL)
 	:	trace_t(name, description)
 	{}
 };
 
 template<typename T, typename VALUE_T>
-void sample(MeasurementStatHandle<T>& measurement, VALUE_T value)
+void record(EventStatHandle<T>& measurement, VALUE_T value)
 {
 	T converted_value(value);
-	measurement.getPrimaryAccumulator()->sample(LLUnits::rawValue(converted_value));
+	measurement.getPrimaryAccumulator()->record(LLUnits::rawValue(converted_value));
 }
 
+template <typename T = F64>
+class SampleStatHandle
+:	public TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
+{
+public:
+	typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
+	typedef TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> > trace_t;
+
+	SampleStatHandle(const char* name, const char* description = NULL)
+	:	trace_t(name, description)
+	{}
+};
+
+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));
+}
 
 template <typename T = F64>
 class CountStatHandle
@@ -560,6 +734,8 @@ struct MemStatAccumulator
 		mDeallocatedCount = 0;
 	}
 
+	void flush() {}
+
 	size_t		mSize,
 				mChildSize;
 	int			mAllocatedCount,
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index cced6546ba..5b0b74524f 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -45,9 +45,11 @@ RecordingBuffers::RecordingBuffers()
 void RecordingBuffers::handOffTo(RecordingBuffers& other)
 {
 	other.mCountsFloat.reset(&mCountsFloat);
-	other.mMeasurementsFloat.reset(&mMeasurementsFloat);
 	other.mCounts.reset(&mCounts);
-	other.mMeasurements.reset(&mMeasurements);
+	other.mSamplesFloat.reset(&mSamplesFloat);
+	other.mSamples.reset(&mSamples);
+	other.mEventsFloat.reset(&mEventsFloat);
+	other.mEvents.reset(&mEvents);
 	other.mStackTimers.reset(&mStackTimers);
 	other.mMemStats.reset(&mMemStats);
 }
@@ -55,9 +57,11 @@ void RecordingBuffers::handOffTo(RecordingBuffers& other)
 void RecordingBuffers::makePrimary()
 {
 	mCountsFloat.makePrimary();
-	mMeasurementsFloat.makePrimary();
 	mCounts.makePrimary();
-	mMeasurements.makePrimary();
+	mSamplesFloat.makePrimary();
+	mSamples.makePrimary();
+	mEventsFloat.makePrimary();
+	mEvents.makePrimary();
 	mStackTimers.makePrimary();
 	mMemStats.makePrimary();
 
@@ -82,9 +86,11 @@ bool RecordingBuffers::isPrimary() const
 void RecordingBuffers::append( const RecordingBuffers& other )
 {
 	mCountsFloat.addSamples(other.mCountsFloat);
-	mMeasurementsFloat.addSamples(other.mMeasurementsFloat);
 	mCounts.addSamples(other.mCounts);
-	mMeasurements.addSamples(other.mMeasurements);
+	mSamplesFloat.addSamples(other.mSamplesFloat);
+	mSamples.addSamples(other.mSamples);
+	mEventsFloat.addSamples(other.mEventsFloat);
+	mEvents.addSamples(other.mEvents);
 	mMemStats.addSamples(other.mMemStats);
 	mStackTimers.addSamples(other.mStackTimers);
 }
@@ -92,22 +98,32 @@ void RecordingBuffers::append( const RecordingBuffers& other )
 void RecordingBuffers::merge( const RecordingBuffers& other)
 {
 	mCountsFloat.addSamples(other.mCountsFloat);
-	mMeasurementsFloat.addSamples(other.mMeasurementsFloat);
 	mCounts.addSamples(other.mCounts);
-	mMeasurements.addSamples(other.mMeasurements);
+	mSamplesFloat.addSamples(other.mSamplesFloat);
+	mSamples.addSamples(other.mSamples);
+	mEventsFloat.addSamples(other.mEventsFloat);
+	mEvents.addSamples(other.mEvents);
 	mMemStats.addSamples(other.mMemStats);
 }
 
 void RecordingBuffers::reset(RecordingBuffers* other)
 {
 	mCountsFloat.reset(other ? &other->mCountsFloat : NULL);
-	mMeasurementsFloat.reset(other ? &other->mMeasurementsFloat : NULL);
 	mCounts.reset(other ? &other->mCounts : NULL);
-	mMeasurements.reset(other ? &other->mMeasurements : NULL);
+	mSamplesFloat.reset(other ? &other->mSamplesFloat : NULL);
+	mSamples.reset(other ? &other->mSamples : NULL);
+	mEventsFloat.reset(other ? &other->mEventsFloat : NULL);
+	mEvents.reset(other ? &other->mEvents : NULL);
 	mStackTimers.reset(other ? &other->mStackTimers : NULL);
 	mMemStats.reset(other ? &other->mMemStats : NULL);
 }
 
+void RecordingBuffers::flush()
+{
+	mSamplesFloat.flush();
+	mSamples.flush();
+}
+
 ///////////////////////////////////////////////////////////////////////
 // Recording
 ///////////////////////////////////////////////////////////////////////
@@ -120,6 +136,9 @@ Recording::Recording()
 
 Recording::Recording( 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);
 	EPlayState other_play_state = other.getPlayState();
 	mutable_other.pause();
@@ -137,15 +156,18 @@ Recording::Recording( const Recording& other )
 
 Recording::~Recording()
 {
-	stop();
-	llassert(isStopped());
+	if (isStarted() && LLTrace::get_thread_recorder().notNull())
+	{
+		LLTrace::get_thread_recorder()->deactivate(this);
+	}
 }
 
 void Recording::update()
 {
 	if (isStarted())
 	{
-		LLTrace::get_thread_recorder()->update(this);
+		mBuffers.write()->flush();
+		LLTrace::get_thread_recorder()->bringUpToDate(this);
 		mSamplingTimer.reset();
 	}
 }
@@ -167,6 +189,7 @@ void Recording::handleStart()
 void Recording::handleStop()
 {
 	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+	mBuffers.write()->flush();
 	LLTrace::TimeBlock::processTimes();
 	LLTrace::get_thread_recorder()->deactivate(this);
 }
@@ -178,13 +201,23 @@ void Recording::handleSplitTo(Recording& other)
 
 void Recording::appendRecording( const Recording& other )
 {
-	mBuffers.write()->append(*other.mBuffers);
-	mElapsedSeconds += other.mElapsedSeconds;
+	EPlayState play_state = getPlayState();
+	{
+		pause();
+		mBuffers.write()->append(*other.mBuffers);
+		mElapsedSeconds += other.mElapsedSeconds;
+	}
+	setPlayState(play_state);
 }
 
 void Recording::mergeRecording( const Recording& other)
 {
-	mBuffers.write()->merge(*other.mBuffers);
+	EPlayState play_state = getPlayState();
+	{
+		pause();
+		mBuffers.write()->merge(*other.mBuffers);
+	}
+	setPlayState(play_state);
 }
 
 LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) const
@@ -248,14 +281,14 @@ S64 Recording::getSum( const TraceType<CountAccumulator<S64> >& stat ) const
 	return mBuffers->mCounts[stat.getIndex()].getSum();
 }
 
-F64 Recording::getSum( const TraceType<MeasurementAccumulator<F64> >& stat ) const
+F64 Recording::getSum( const TraceType<EventAccumulator<F64> >& stat ) const
 {
-	return (F64)mBuffers->mMeasurementsFloat[stat.getIndex()].getSum();
+	return (F64)mBuffers->mEventsFloat[stat.getIndex()].getSum();
 }
 
-S64 Recording::getSum( const TraceType<MeasurementAccumulator<S64> >& stat ) const
+S64 Recording::getSum( const TraceType<EventAccumulator<S64> >& stat ) const
 {
-	return (S64)mBuffers->mMeasurements[stat.getIndex()].getSum();
+	return (S64)mBuffers->mEvents[stat.getIndex()].getSum();
 }
 
 
@@ -283,67 +316,127 @@ U32 Recording::getSampleCount( const TraceType<CountAccumulator<F64> >& stat ) c
 
 U32 Recording::getSampleCount( const TraceType<CountAccumulator<S64> >& stat ) const
 {
-	return mBuffers->mMeasurementsFloat[stat.getIndex()].getSampleCount();
+	return mBuffers->mCounts[stat.getIndex()].getSampleCount();
+}
+
+F64 Recording::getMin( const TraceType<SampleAccumulator<F64> >& stat ) const
+{
+	return mBuffers->mSamplesFloat[stat.getIndex()].getMin();
+}
+
+S64 Recording::getMin( const TraceType<SampleAccumulator<S64> >& stat ) const
+{
+	return mBuffers->mSamples[stat.getIndex()].getMin();
+}
+
+F64 Recording::getMax( const TraceType<SampleAccumulator<F64> >& stat ) const
+{
+	return mBuffers->mSamplesFloat[stat.getIndex()].getMax();
+}
+
+S64 Recording::getMax( const TraceType<SampleAccumulator<S64> >& stat ) const
+{
+	return mBuffers->mSamples[stat.getIndex()].getMax();
+}
+
+F64 Recording::getMean( const TraceType<SampleAccumulator<F64> >& stat ) const
+{
+	return mBuffers->mSamplesFloat[stat.getIndex()].getMean();
+}
+
+F64 Recording::getMean( const TraceType<SampleAccumulator<S64> >& stat ) const
+{
+	return mBuffers->mSamples[stat.getIndex()].getMean();
 }
 
-F64 Recording::getMin( const TraceType<MeasurementAccumulator<F64> >& stat ) const
+F64 Recording::getStandardDeviation( const TraceType<SampleAccumulator<F64> >& stat ) const
 {
-	return mBuffers->mMeasurementsFloat[stat.getIndex()].getMin();
+	return mBuffers->mSamplesFloat[stat.getIndex()].getStandardDeviation();
 }
 
-S64 Recording::getMin( const TraceType<MeasurementAccumulator<S64> >& stat ) const
+F64 Recording::getStandardDeviation( const TraceType<SampleAccumulator<S64> >& stat ) const
 {
-	return mBuffers->mMeasurements[stat.getIndex()].getMin();
+	return mBuffers->mSamples[stat.getIndex()].getStandardDeviation();
 }
 
-F64 Recording::getMax( const TraceType<MeasurementAccumulator<F64> >& stat ) const
+F64 Recording::getLastValue( const TraceType<SampleAccumulator<F64> >& stat ) const
 {
-	return mBuffers->mMeasurementsFloat[stat.getIndex()].getMax();
+	return mBuffers->mSamplesFloat[stat.getIndex()].getLastValue();
 }
 
-S64 Recording::getMax( const TraceType<MeasurementAccumulator<S64> >& stat ) const
+S64 Recording::getLastValue( const TraceType<SampleAccumulator<S64> >& stat ) const
 {
-	return mBuffers->mMeasurements[stat.getIndex()].getMax();
+	return mBuffers->mSamples[stat.getIndex()].getLastValue();
 }
 
-F64 Recording::getMean( const TraceType<MeasurementAccumulator<F64> >& stat ) const
+U32 Recording::getSampleCount( const TraceType<SampleAccumulator<F64> >& stat ) const
 {
-	return mBuffers->mMeasurementsFloat[stat.getIndex()].getMean();
+	return mBuffers->mSamplesFloat[stat.getIndex()].getSampleCount();
 }
 
-F64 Recording::getMean( const TraceType<MeasurementAccumulator<S64> >& stat ) const
+U32 Recording::getSampleCount( const TraceType<SampleAccumulator<S64> >& stat ) const
 {
-	return mBuffers->mMeasurements[stat.getIndex()].getMean();
+	return mBuffers->mSamples[stat.getIndex()].getSampleCount();
 }
 
-F64 Recording::getStandardDeviation( const TraceType<MeasurementAccumulator<F64> >& stat ) const
+F64 Recording::getMin( const TraceType<EventAccumulator<F64> >& stat ) const
 {
-	return mBuffers->mMeasurementsFloat[stat.getIndex()].getStandardDeviation();
+	return mBuffers->mEventsFloat[stat.getIndex()].getMin();
 }
 
-F64 Recording::getStandardDeviation( const TraceType<MeasurementAccumulator<S64> >& stat ) const
+S64 Recording::getMin( const TraceType<EventAccumulator<S64> >& stat ) const
 {
-	return mBuffers->mMeasurements[stat.getIndex()].getStandardDeviation();
+	return mBuffers->mEvents[stat.getIndex()].getMin();
 }
 
-F64 Recording::getLastValue( const TraceType<MeasurementAccumulator<F64> >& stat ) const
+F64 Recording::getMax( const TraceType<EventAccumulator<F64> >& stat ) const
 {
-	return mBuffers->mMeasurementsFloat[stat.getIndex()].getLastValue();
+	return mBuffers->mEventsFloat[stat.getIndex()].getMax();
 }
 
-S64 Recording::getLastValue( const TraceType<MeasurementAccumulator<S64> >& stat ) const
+S64 Recording::getMax( const TraceType<EventAccumulator<S64> >& stat ) const
 {
-	return mBuffers->mMeasurements[stat.getIndex()].getLastValue();
+	return mBuffers->mEvents[stat.getIndex()].getMax();
 }
 
-U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<F64> >& stat ) const
+F64 Recording::getMean( const TraceType<EventAccumulator<F64> >& stat ) const
 {
-	return mBuffers->mMeasurementsFloat[stat.getIndex()].getSampleCount();
+	return mBuffers->mEventsFloat[stat.getIndex()].getMean();
 }
 
-U32 Recording::getSampleCount( const TraceType<MeasurementAccumulator<S64> >& stat ) const
+F64 Recording::getMean( const TraceType<EventAccumulator<S64> >& stat ) const
 {
-	return mBuffers->mMeasurements[stat.getIndex()].getSampleCount();
+	return mBuffers->mEvents[stat.getIndex()].getMean();
+}
+
+F64 Recording::getStandardDeviation( const TraceType<EventAccumulator<F64> >& stat ) const
+{
+	return mBuffers->mEventsFloat[stat.getIndex()].getStandardDeviation();
+}
+
+F64 Recording::getStandardDeviation( const TraceType<EventAccumulator<S64> >& stat ) const
+{
+	return mBuffers->mEvents[stat.getIndex()].getStandardDeviation();
+}
+
+F64 Recording::getLastValue( const TraceType<EventAccumulator<F64> >& stat ) const
+{
+	return mBuffers->mEventsFloat[stat.getIndex()].getLastValue();
+}
+
+S64 Recording::getLastValue( const TraceType<EventAccumulator<S64> >& stat ) const
+{
+	return mBuffers->mEvents[stat.getIndex()].getLastValue();
+}
+
+U32 Recording::getSampleCount( const TraceType<EventAccumulator<F64> >& stat ) const
+{
+	return mBuffers->mEventsFloat[stat.getIndex()].getSampleCount();
+}
+
+U32 Recording::getSampleCount( const TraceType<EventAccumulator<S64> >& stat ) const
+{
+	return mBuffers->mEvents[stat.getIndex()].getSampleCount();
 }
 
 ///////////////////////////////////////////////////////////////////////
@@ -377,7 +470,7 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 	if (other.mRecordingPeriods.empty()) return;
 
 	EPlayState play_state = getPlayState();
-	stop();
+	pause();
 
 	EPlayState other_play_state = other.getPlayState();
 	other.pause();
@@ -466,8 +559,7 @@ LLTrace::Recording PeriodicRecording::snapshotCurRecording() const
 
 Recording& PeriodicRecording::getLastRecording()
 {
-	U32 num_periods = mRecordingPeriods.size();
-	return mRecordingPeriods[(mCurPeriod + num_periods - 1) % num_periods];
+	return getPrevRecording(1);
 }
 
 const Recording& PeriodicRecording::getLastRecording() const
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index b339e72e5c..19a4fae737 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -117,11 +117,14 @@ namespace LLTrace
 		void append(const RecordingBuffers& other);
 		void merge(const RecordingBuffers& other);
 		void reset(RecordingBuffers* other = NULL);
+		void flush();
 
 		AccumulatorBuffer<CountAccumulator<F64> > 		mCountsFloat;
-		AccumulatorBuffer<MeasurementAccumulator<F64> > mMeasurementsFloat;
 		AccumulatorBuffer<CountAccumulator<S64> > 		mCounts;
-		AccumulatorBuffer<MeasurementAccumulator<S64> > mMeasurements;
+		AccumulatorBuffer<SampleAccumulator<F64> >		mSamplesFloat;
+		AccumulatorBuffer<SampleAccumulator<S64> >		mSamples;
+		AccumulatorBuffer<EventAccumulator<F64> >		mEventsFloat;
+		AccumulatorBuffer<EventAccumulator<S64> >		mEvents;
 		AccumulatorBuffer<TimeBlockAccumulator> 		mStackTimers;
 		AccumulatorBuffer<MemStatAccumulator> 			mMemStats;
 	};
@@ -181,57 +184,101 @@ namespace LLTrace
 		U32 getSampleCount(const TraceType<CountAccumulator<S64> >& stat) const;
 
 
-		// MeasurementStatHandle accessors
-		F64 getSum(const TraceType<MeasurementAccumulator<F64> >& stat) const;
-		S64 getSum(const TraceType<MeasurementAccumulator<S64> >& stat) const;
+		// SampleStatHandle accessors
+		F64 getMin(const TraceType<SampleAccumulator<F64> >& stat) const;
+		S64 getMin(const TraceType<SampleAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getSum(const MeasurementStatHandle<T>& stat) const
+		T getMin(const SampleStatHandle<T>& stat) const
 		{
-			return (T)getSum(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getMin(static_cast<const TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getMin(const TraceType<MeasurementAccumulator<F64> >& stat) const;
-		S64 getMin(const TraceType<MeasurementAccumulator<S64> >& stat) const;
+		F64 getMax(const TraceType<SampleAccumulator<F64> >& stat) const;
+		S64 getMax(const TraceType<SampleAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getMin(const MeasurementStatHandle<T>& stat) const
+		T getMax(const SampleStatHandle<T>& stat) const
 		{
-			return (T)getMin(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getMax(static_cast<const TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getMax(const TraceType<MeasurementAccumulator<F64> >& stat) const;
-		S64 getMax(const TraceType<MeasurementAccumulator<S64> >& stat) const;
+		F64 getMean(const TraceType<SampleAccumulator<F64> >& stat) const;
+		F64 getMean(const TraceType<SampleAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getMax(const MeasurementStatHandle<T>& stat) const
+		T getMean(SampleStatHandle<T>& stat) const
 		{
-			return (T)getMax(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getMean(static_cast<const TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getMean(const TraceType<MeasurementAccumulator<F64> >& stat) const;
-		F64 getMean(const TraceType<MeasurementAccumulator<S64> >& stat) const;
+		F64 getStandardDeviation(const TraceType<SampleAccumulator<F64> >& stat) const;
+		F64 getStandardDeviation(const TraceType<SampleAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getMean(MeasurementStatHandle<T>& stat) const
+		T getStandardDeviation(const SampleStatHandle<T>& stat) const
 		{
-			return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getStandardDeviation(static_cast<const TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getStandardDeviation(const TraceType<MeasurementAccumulator<F64> >& stat) const;
-		F64 getStandardDeviation(const TraceType<MeasurementAccumulator<S64> >& stat) const;
+		F64 getLastValue(const TraceType<SampleAccumulator<F64> >& stat) const;
+		S64 getLastValue(const TraceType<SampleAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getStandardDeviation(const MeasurementStatHandle<T>& stat) const
+		T getLastValue(const SampleStatHandle<T>& stat) const
 		{
-			return (T)getMean(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getLastValue(static_cast<const TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getLastValue(const TraceType<MeasurementAccumulator<F64> >& stat) const;
-		S64 getLastValue(const TraceType<MeasurementAccumulator<S64> >& stat) const;
+		U32 getSampleCount(const TraceType<SampleAccumulator<F64> >& stat) const;
+		U32 getSampleCount(const TraceType<SampleAccumulator<S64> >& stat) const;
+
+		// EventStatHandle accessors
+		F64 getSum(const TraceType<EventAccumulator<F64> >& stat) const;
+		S64 getSum(const TraceType<EventAccumulator<S64> >& stat) const;
+		template <typename T>
+		T getSum(const EventStatHandle<T>& stat) const
+		{
+			return (T)getSum(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+		}
+
+		F64 getMin(const TraceType<EventAccumulator<F64> >& stat) const;
+		S64 getMin(const TraceType<EventAccumulator<S64> >& stat) const;
+		template <typename T>
+		T getMin(const EventStatHandle<T>& stat) const
+		{
+			return (T)getMin(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+		}
+
+		F64 getMax(const TraceType<EventAccumulator<F64> >& stat) const;
+		S64 getMax(const TraceType<EventAccumulator<S64> >& stat) const;
+		template <typename T>
+		T getMax(const EventStatHandle<T>& stat) const
+		{
+			return (T)getMax(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+		}
+
+		F64 getMean(const TraceType<EventAccumulator<F64> >& stat) const;
+		F64 getMean(const TraceType<EventAccumulator<S64> >& stat) const;
+		template <typename T>
+		T getMean(EventStatHandle<T>& stat) const
+		{
+			return (T)getMean(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+		}
+
+		F64 getStandardDeviation(const TraceType<EventAccumulator<F64> >& stat) const;
+		F64 getStandardDeviation(const TraceType<EventAccumulator<S64> >& stat) const;
+		template <typename T>
+		T getStandardDeviation(const EventStatHandle<T>& stat) const
+		{
+			return (T)getStandardDeviation(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+		}
+
+		F64 getLastValue(const TraceType<EventAccumulator<F64> >& stat) const;
+		S64 getLastValue(const TraceType<EventAccumulator<S64> >& stat) const;
 		template <typename T>
-		T getLastValue(const MeasurementStatHandle<T>& stat) const
+		T getLastValue(const EventStatHandle<T>& stat) const
 		{
-			return (T)getLastValue(static_cast<const TraceType<MeasurementAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getLastValue(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		U32 getSampleCount(const TraceType<MeasurementAccumulator<F64> >& stat) const;
-		U32 getSampleCount(const TraceType<MeasurementAccumulator<S64> >& stat) const;
+		U32 getSampleCount(const TraceType<EventAccumulator<F64> >& stat) const;
+		U32 getSampleCount(const TraceType<EventAccumulator<S64> >& stat) const;
 
 		LLUnit<LLUnits::Seconds, F64> getDuration() const { return LLUnit<LLUnits::Seconds, F64>(mElapsedSeconds); }
 
@@ -272,13 +319,14 @@ namespace LLTrace
 		const Recording& getPrevRecording(U32 offset) const;
 		Recording snapshotCurRecording() const;
 
+		// catch all for stats that have a defined sum
 		template <typename T>
 		typename T::value_t getPeriodMin(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
 
-			typename T::value_t min_val = (std::numeric_limits<typename T::value_t>::max)();
+			typename T::value_t min_val = std::numeric_limits<typename T::value_t>::max();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				S32 index = (mCurPeriod + total_periods - i) % total_periods;
@@ -287,13 +335,43 @@ namespace LLTrace
 			return min_val;
 		}
 
+		template <typename T>
+		typename T getPeriodMin(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		{
+			size_t total_periods = mRecordingPeriods.size();
+			num_periods = llmin(num_periods, total_periods);
+
+			typename T min_val = std::numeric_limits<T>::max();
+			for (S32 i = 1; i <= num_periods; i++)
+			{
+				S32 index = (mCurPeriod + total_periods - i) % total_periods;
+				min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat));
+			}
+			return min_val;
+		}
+		
+		template <typename T>
+		typename T getPeriodMin(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		{
+			size_t total_periods = mRecordingPeriods.size();
+			num_periods = llmin(num_periods, total_periods);
+
+			typename T min_val = std::numeric_limits<T>::max();
+			for (S32 i = 1; i <= num_periods; i++)
+			{
+				S32 index = (mCurPeriod + total_periods - i) % total_periods;
+				min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat));
+			}
+			return min_val;
+		}
+
 		template <typename T>
 		F64 getPeriodMinPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
 
-			F64 min_val = (std::numeric_limits<F64>::max)();
+			F64 min_val = std::numeric_limits<F64>::max();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				S32 index = (mCurPeriod + total_periods - i) % total_periods;
@@ -302,13 +380,14 @@ namespace LLTrace
 			return min_val;
 		}
 
+		// catch all for stats that have a defined sum
 		template <typename T>
 		typename T::value_t getPeriodMax(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
 
-			typename T::value_t max_val = (std::numeric_limits<typename T::value_t>::min)();
+			typename T::value_t max_val = std::numeric_limits<typename T::value_t>::min();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				S32 index = (mCurPeriod + total_periods - i) % total_periods;
@@ -317,13 +396,43 @@ namespace LLTrace
 			return max_val;
 		}
 
+		template <typename T>
+		typename T getPeriodMax(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		{
+			size_t total_periods = mRecordingPeriods.size();
+			num_periods = llmin(num_periods, total_periods);
+
+			typename T max_val = std::numeric_limits<T>::min();
+			for (S32 i = 1; i <= num_periods; i++)
+			{
+				S32 index = (mCurPeriod + total_periods - i) % total_periods;
+				max_val = llmax(max_val, mRecordingPeriods[index].getMax(stat));
+			}
+			return max_val;
+		}
+
+		template <typename T>
+		typename T getPeriodMax(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		{
+			size_t total_periods = mRecordingPeriods.size();
+			num_periods = llmin(num_periods, total_periods);
+
+			typename T max_val = std::numeric_limits<T>::min();
+			for (S32 i = 1; i <= num_periods; i++)
+			{
+				S32 index = (mCurPeriod + total_periods - i) % total_periods;
+				max_val = llmax(max_val, mRecordingPeriods[index].getMax(stat));
+			}
+			return max_val;
+		}
+
 		template <typename T>
 		F64 getPeriodMaxPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
 
-			F64 max_val = (std::numeric_limits<F64>::min)();
+			F64 max_val = std::numeric_limits<F64>::min();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				S32 index = (mCurPeriod + total_periods - i) % total_periods;
@@ -332,13 +441,14 @@ namespace LLTrace
 			return max_val;
 		}
 
+		// catch all for stats that have a defined sum
 		template <typename T>
-		typename T::mean_t getPeriodMean(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
+		typename T::mean_t getPeriodMean(const TraceType<T >& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
 
-			typename T::mean_t mean = typename T::mean_t();
+			typename T::mean_t mean = 0;
 			if (num_periods <= 0) { return mean; }
 
 			for (S32 i = 1; i <= num_periods; i++)
@@ -349,7 +459,65 @@ namespace LLTrace
 					mean += mRecordingPeriods[index].getSum(stat);
 				}
 			}
-			mean /= num_periods;
+			mean = mean / num_periods;
+			return mean;
+		}
+
+		template <typename T>
+		typename SampleAccumulator<T>::mean_t getPeriodMean(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		{
+			size_t total_periods = mRecordingPeriods.size();
+			num_periods = llmin(num_periods, total_periods);
+
+			LLUnit<LLUnits::Seconds, F64> total_duration = 0.f;
+
+			typename SampleAccumulator<T>::mean_t mean = 0;
+			if (num_periods <= 0) { return mean; }
+
+			for (S32 i = 1; i <= num_periods; i++)
+			{
+				S32 index = (mCurPeriod + total_periods - i) % total_periods;
+				if (mRecordingPeriods[index].getDuration() > 0.f)
+				{
+					LLUnit<LLUnits::Seconds, F64> recording_duration = mRecordingPeriods[index].getDuration();
+					mean += mRecordingPeriods[index].getMean(stat) * recording_duration.value();
+					total_duration += recording_duration;
+				}
+			}
+
+			if (total_duration.value())
+			{
+				mean = mean / total_duration;
+			}
+			return mean;
+		}
+
+		template <typename T>
+		typename EventAccumulator<T>::mean_t getPeriodMean(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		{
+			size_t total_periods = mRecordingPeriods.size();
+			num_periods = llmin(num_periods, total_periods);
+
+			typename EventAccumulator<T>::mean_t mean = 0;
+			if (num_periods <= 0) { return mean; }
+
+			S32 total_sample_count = 0;
+
+			for (S32 i = 1; i <= num_periods; i++)
+			{
+				S32 index = (mCurPeriod + total_periods - i) % total_periods;
+				if (mRecordingPeriods[index].getDuration() > 0.f)
+				{
+					S32 period_sample_count = mRecordingPeriods[index].getSampleCount(stat);
+					mean += mRecordingPeriods[index].getMean(stat) * period_sample_count;
+					total_sample_count += period_sample_count;
+				}
+			}
+
+			if (total_sample_count)
+			{
+				mean = mean / total_sample_count;
+			}
 			return mean;
 		}
 
@@ -359,7 +527,7 @@ namespace LLTrace
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
 
-			typename T::mean_t mean = typename T::mean_t();
+			typename T::mean_t mean = 0;
 			if (num_periods <= 0) { return mean; }
 
 			for (S32 i = 1; i <= num_periods; i++)
@@ -370,7 +538,7 @@ namespace LLTrace
 					mean += mRecordingPeriods[index].getPerSec(stat);
 				}
 			}
-			mean /= num_periods;
+			mean = mean / num_periods;
 			return mean;
 		}
 
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 2001b9cd7f..75c7cb2ff1 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -74,10 +74,12 @@ ThreadRecorder::~ThreadRecorder()
 {
 	delete mRootTimer;
 
-	while(mActiveRecordings.size())
+	if (!mActiveRecordings.empty())
 	{
-		mActiveRecordings.front()->mTargetRecording->stop();
+		std::for_each(mActiveRecordings.begin(), mActiveRecordings.end(), DeletePointer());
+		mActiveRecordings.clear();
 	}
+
 	set_thread_recorder(NULL);
 	delete[] mTimeBlockTreeNodes;
 }
@@ -97,34 +99,40 @@ void ThreadRecorder::activate( Recording* recording )
 	ActiveRecording* active_recording = new ActiveRecording(recording);
 	if (!mActiveRecordings.empty())
 	{
-		mActiveRecordings.front()->mPartialRecording.handOffTo(active_recording->mPartialRecording);
+		mActiveRecordings.back()->mPartialRecording.handOffTo(active_recording->mPartialRecording);
 	}
-	mActiveRecordings.push_front(active_recording);
+	mActiveRecordings.push_back(active_recording);
 
-	mActiveRecordings.front()->mPartialRecording.makePrimary();
+	mActiveRecordings.back()->mPartialRecording.makePrimary();
 }
 
-ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::update( Recording* recording )
+ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringUpToDate( Recording* recording )
 {
-	active_recording_list_t::iterator it, end_it;
-	for (it = mActiveRecordings.begin(), end_it = mActiveRecordings.end();
+	if (mActiveRecordings.empty()) return mActiveRecordings.rend();
+
+	mActiveRecordings.back()->mPartialRecording.flush();
+
+	active_recording_list_t::reverse_iterator it, end_it;
+	for (it = mActiveRecordings.rbegin(), end_it = mActiveRecordings.rend();
 		it != end_it;
 		++it)
 	{
-		active_recording_list_t::iterator next_it = it;
+		ActiveRecording* cur_recording = *it;
+
+		active_recording_list_t::reverse_iterator next_it = it;
 		++next_it;
 
 		// if we have another recording further down in the stack...
-		if (next_it != mActiveRecordings.end())
+		if (next_it != mActiveRecordings.rend())
 		{
 			// ...push our gathered data down to it
-			(*next_it)->mPartialRecording.append((*it)->mPartialRecording);
+			(*next_it)->mPartialRecording.append(cur_recording->mPartialRecording);
 		}
 
 		// copy accumulated measurements into result buffer and clear accumulator (mPartialRecording)
-		(*it)->moveBaselineToTarget();
+		cur_recording->movePartialToTarget();
 
-		if ((*it)->mTargetRecording == recording)
+		if (cur_recording->mTargetRecording == recording)
 		{
 			// found the recording, so return it
 			break;
@@ -139,28 +147,30 @@ ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::update( Record
 	return it;
 }
 
-AccumulatorBuffer<CountAccumulator<F64> > 		gCountsFloat;
-AccumulatorBuffer<MeasurementAccumulator<F64> >	gMeasurementsFloat;
-AccumulatorBuffer<CountAccumulator<S64> >		gCounts;
-AccumulatorBuffer<MeasurementAccumulator<S64> >	gMeasurements;
-AccumulatorBuffer<TimeBlockAccumulator>			gStackTimers;
-AccumulatorBuffer<MemStatAccumulator>			gMemStats;
+AccumulatorBuffer<CountAccumulator<F64> > 	gCountsFloat;
+AccumulatorBuffer<EventAccumulator<F64> >	gMeasurementsFloat;
+AccumulatorBuffer<CountAccumulator<S64> >	gCounts;
+AccumulatorBuffer<EventAccumulator<S64> >	gMeasurements;
+AccumulatorBuffer<TimeBlockAccumulator>		gStackTimers;
+AccumulatorBuffer<MemStatAccumulator>		gMemStats;
 
 void ThreadRecorder::deactivate( Recording* recording )
 {
-	active_recording_list_t::iterator it = update(recording);
-	if (it != mActiveRecordings.end())
+	active_recording_list_t::reverse_iterator it = bringUpToDate(recording);
+	if (it != mActiveRecordings.rend())
 	{
 		// and if we've found the recording we wanted to update
-		active_recording_list_t::iterator next_it = it;
+		active_recording_list_t::reverse_iterator next_it = it;
 		++next_it;
-		if (next_it != mActiveRecordings.end())
+		if (next_it != mActiveRecordings.rend())
 		{
-			(*next_it)->mTargetRecording->mBuffers.write()->makePrimary();
+			(*next_it)->mPartialRecording.makePrimary();
 		}
 
-		delete *it;
-		mActiveRecordings.erase(it);
+		active_recording_list_t::iterator recording_to_remove = (++it).base();
+		llassert((*recording_to_remove)->mTargetRecording == recording);
+		delete *recording_to_remove;
+		mActiveRecordings.erase(recording_to_remove);
 	}
 }
 
@@ -169,10 +179,11 @@ ThreadRecorder::ActiveRecording::ActiveRecording( Recording* target )
 {
 }
 
-void ThreadRecorder::ActiveRecording::moveBaselineToTarget()
+void ThreadRecorder::ActiveRecording::movePartialToTarget()
 {
 	mTargetRecording->mBuffers.write()->append(mPartialRecording);
-	mPartialRecording.reset();
+	// reset based on self to keep history
+	mPartialRecording.reset(&mPartialRecording);
 }
 
 
@@ -180,21 +191,22 @@ void ThreadRecorder::ActiveRecording::moveBaselineToTarget()
 // SlaveThreadRecorder
 ///////////////////////////////////////////////////////////////////////
 
-SlaveThreadRecorder::SlaveThreadRecorder()
+SlaveThreadRecorder::SlaveThreadRecorder(MasterThreadRecorder& master)
+:	mMasterRecorder(master)
 {
-	getMasterThreadRecorder().addSlaveThread(this);
+	mMasterRecorder.addSlaveThread(this);
 }
 
 SlaveThreadRecorder::~SlaveThreadRecorder()
 {
-	getMasterThreadRecorder().removeSlaveThread(this);
+	mMasterRecorder.removeSlaveThread(this);
 }
 
 void SlaveThreadRecorder::pushToMaster()
 {
 	mThreadRecording.stop();
 	{
-		LLMutexLock(getMasterThreadRecorder().getSlaveListMutex());
+		LLMutexLock(mMasterRecorder.getSlaveListMutex());
 		mSharedData.appendFrom(mThreadRecording);
 	}
 	mThreadRecording.start();
@@ -243,7 +255,7 @@ void MasterThreadRecorder::pullFromSlaveThreads()
 
 	LLMutexLock lock(&mSlaveListMutex);
 
-	RecordingBuffers& target_recording_buffers = mActiveRecordings.front()->mPartialRecording;
+	RecordingBuffers& target_recording_buffers = mActiveRecordings.back()->mPartialRecording;
 	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
 		it != end_it;
 		++it)
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index c44bcbd12d..17a2d4a9a9 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -39,15 +39,15 @@ namespace LLTrace
 	{
 	protected:
 		struct ActiveRecording;
-		typedef std::list<ActiveRecording*> active_recording_list_t;
+		typedef std::vector<ActiveRecording*> active_recording_list_t;
 	public:
 		ThreadRecorder();
 
 		virtual ~ThreadRecorder();
 
 		void activate(Recording* recording);
-		active_recording_list_t::iterator update(Recording* recording);
 		void deactivate(Recording* recording);
+		active_recording_list_t::reverse_iterator bringUpToDate(Recording* recording);
 
 		virtual void pushToMaster() = 0;
 
@@ -58,10 +58,10 @@ namespace LLTrace
 		{
 			ActiveRecording(Recording* target);
 
-			Recording*	mTargetRecording;
+			Recording*			mTargetRecording;
 			RecordingBuffers	mPartialRecording;
 
-			void moveBaselineToTarget();
+			void movePartialToTarget();
 		};
 		Recording					mThreadRecording;
 
@@ -98,7 +98,7 @@ namespace LLTrace
 	class LL_COMMON_API SlaveThreadRecorder : public ThreadRecorder
 	{
 	public:
-		SlaveThreadRecorder();
+		SlaveThreadRecorder(MasterThreadRecorder& master);
 		~SlaveThreadRecorder();
 
 		// call this periodically to gather stats data for master thread to consume
@@ -117,7 +117,8 @@ namespace LLTrace
 		private:
 			LLMutex		mRecordingMutex;
 		};
-		SharedData		mSharedData;
+		SharedData				mSharedData;
+		MasterThreadRecorder&	mMasterRecorder;
 	};
 }
 
-- 
cgit v1.2.3


From 074c1f1de45f60059c97cf9cfd0bbb9fddbb52c4 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 29 May 2013 17:02:27 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 made LLCopyOnWritePointer enforce write access through write() again disabled
 some error checking on release for download builds

---
 indra/llcommon/llpointer.h | 3 +++
 indra/llcommon/lltrace.h   | 2 ++
 2 files changed, 5 insertions(+)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index c83e55577d..e640ffd595 100644
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -196,6 +196,9 @@ public:
 			*(pointer_t*)(this) = new Type(*pointer_t::mPointer);
 		}
 	}
+
+	const Type*	operator->() const	{ return pointer_t::mPointer; }
+	const Type&	operator*() const	{ return *pointer_t::mPointer; }
 };
 
 #endif
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index f94576de45..e950a119d3 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -175,10 +175,12 @@ public:
 	// NOTE: this is not thread-safe.  We assume that slots are reserved in the main thread before any child threads are spawned
 	size_t reserveSlot()
 	{
+#ifndef LL_RELEASE_FOR_DOWNLOAD
 		if (LLTrace::isInitialized())
 		{
 			llerrs << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << llendl;
 		}
+#endif
 		size_t next_slot = sNextStorageSlot++;
 		if (next_slot >= mStorageSize)
 		{
-- 
cgit v1.2.3


From ae355188327515d53b9c15c27ed576829fce3668 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 30 May 2013 18:30:11 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 fixed LLTrace::ExtendablePeriodicRecording::extend() to include *all* frame
 extensions gated SlaveThreadRecorder pushing to master based on master update
 rate reverted changes to LLThreadLocalSingletonPointer to not use
 offset-from-default trick

---
 indra/llcommon/llthreadlocalstorage.h    |  8 ++------
 indra/llcommon/lltrace.h                 | 21 ++++++++++++---------
 indra/llcommon/lltracerecording.cpp      |  5 +++--
 indra/llcommon/lltracerecording.h        |  6 +++---
 indra/llcommon/lltracethreadrecorder.cpp | 25 ++++++++++++++++++-------
 indra/llcommon/lltracethreadrecorder.h   | 14 +++++++++-----
 6 files changed, 47 insertions(+), 32 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
index 471784749b..cc67248124 100644
--- a/indra/llcommon/llthreadlocalstorage.h
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -313,11 +313,6 @@ template<typename DERIVED_TYPE>
 class LLThreadLocalSingletonPointer
 {
 public:
-	void operator =(DERIVED_TYPE* value)
-	{
-		setInstance(value);
-	}
-    
 	LL_FORCE_INLINE static DERIVED_TYPE* getInstance()
 	{
 #if LL_DARWIN
@@ -328,7 +323,7 @@ public:
 #endif
 	}
 
-	LL_FORCE_INLINE static void setInstance(DERIVED_TYPE* instance)
+	static void setInstance(DERIVED_TYPE* instance)
 	{
 #if LL_DARWIN
         createTLSKey();
@@ -339,6 +334,7 @@ public:
 	}
 
 private:
+
 #if LL_WINDOWS
 	static __declspec(thread) DERIVED_TYPE* sInstance;
 #elif LL_LINUX
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index e950a119d3..00bab536ff 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -35,6 +35,7 @@
 #include "llunit.h"
 #include "llapr.h"
 #include "llthreadlocalstorage.h"
+#include "lltimer.h"
 
 #include <list>
 
@@ -75,7 +76,6 @@ void set_thread_recorder(class ThreadRecorder*);
 
 class MasterThreadRecorder& getUIThreadRecorder();
 
-// one per thread per type
 template<typename ACCUMULATOR>
 class AccumulatorBuffer : public LLRefCount
 {
@@ -104,9 +104,9 @@ public:
 
 	~AccumulatorBuffer()
 	{
-		if (LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage)
+		if (isPrimary())
 		{
-			LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(getDefaultBuffer()->mStorage);
+			LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
 		}
 		delete[] mStorage;
 	}
@@ -169,7 +169,8 @@ public:
 
 	LL_FORCE_INLINE static ACCUMULATOR* getPrimaryStorage() 
 	{ 
-		return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance(); 
+		ACCUMULATOR* accumulator = LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance();
+		return accumulator ? accumulator : sDefaultBuffer->mStorage;
 	}
 
 	// NOTE: this is not thread-safe.  We assume that slots are reserved in the main thread before any child threads are spawned
@@ -222,25 +223,27 @@ public:
 
 	static self_t* getDefaultBuffer()
 	{
-		// this buffer is allowed to leak so that trace calls from global destructors have somewhere to put their data
-		// so as not to trigger an access violation
-		static self_t* sBuffer = new AccumulatorBuffer(StaticAllocationMarker());
 		static bool sInitialized = false;
 		if (!sInitialized)
 		{
-			sBuffer->resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
+			// this buffer is allowed to leak so that trace calls from global destructors have somewhere to put their data
+			// so as not to trigger an access violation
+			sDefaultBuffer = new AccumulatorBuffer(StaticAllocationMarker());
 			sInitialized = true;
+			sDefaultBuffer->resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
 		}
-		return sBuffer;
+		return sDefaultBuffer;
 	}
 
 private:
 	ACCUMULATOR*	mStorage;
 	size_t			mStorageSize;
 	static size_t	sNextStorageSlot;
+	static self_t*	sDefaultBuffer;
 };
 
 template<typename ACCUMULATOR> size_t AccumulatorBuffer<ACCUMULATOR>::sNextStorageSlot = 0;
+template<typename ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>* AccumulatorBuffer<ACCUMULATOR>::sDefaultBuffer = NULL;
 
 template<typename ACCUMULATOR>
 class TraceType 
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 5b0b74524f..86cdca3e10 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -490,8 +490,9 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 	{
 		if (mAutoResize)
 		{
-			for (S32 other_index = (other.mCurPeriod + 2) % other_recording_count; 
-				other_index != other.mCurPeriod; 
+			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)
 			{
 				llassert(other.mRecordingPeriods[other_index].getDuration() != 0.f 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 19a4fae737..aaeb32e891 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -336,12 +336,12 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename T getPeriodMin(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		T getPeriodMin(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
 
-			typename T min_val = std::numeric_limits<T>::max();
+			T min_val = std::numeric_limits<T>::max();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				S32 index = (mCurPeriod + total_periods - i) % total_periods;
@@ -351,7 +351,7 @@ namespace LLTrace
 		}
 		
 		template <typename T>
-		typename T getPeriodMin(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		T getPeriodMin(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 75c7cb2ff1..89b5df1f94 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -202,14 +202,21 @@ SlaveThreadRecorder::~SlaveThreadRecorder()
 	mMasterRecorder.removeSlaveThread(this);
 }
 
-void SlaveThreadRecorder::pushToMaster()
+bool SlaveThreadRecorder::pushToMaster()
 {
-	mThreadRecording.stop();
+	if (mPushCount != mMasterRecorder.getPullCount())
 	{
-		LLMutexLock(mMasterRecorder.getSlaveListMutex());
-		mSharedData.appendFrom(mThreadRecording);
+		mThreadRecording.stop();
+		{
+			LLMutexLock(mMasterRecorder.getSlaveListMutex());
+			mSharedData.appendFrom(mThreadRecording);
+		}
+		mThreadRecording.start();
+
+		mPushCount = mMasterRecorder.getPullCount();
+		return true;
 	}
-	mThreadRecording.start();
+	return false;
 }
 
 void SlaveThreadRecorder::SharedData::appendFrom( const Recording& source )
@@ -264,6 +271,8 @@ void MasterThreadRecorder::pullFromSlaveThreads()
 		(*it)->mSharedData.mergeTo(target_recording_buffers);
 		(*it)->mSharedData.reset();
 	}
+
+	mPullCount++;
 }
 
 void MasterThreadRecorder::addSlaveThread( class SlaveThreadRecorder* child )
@@ -289,8 +298,10 @@ void MasterThreadRecorder::removeSlaveThread( class SlaveThreadRecorder* child )
 	}
 }
 
-void MasterThreadRecorder::pushToMaster()
-{}
+bool MasterThreadRecorder::pushToMaster()
+{
+	return false;
+}
 
 MasterThreadRecorder::MasterThreadRecorder()
 {}
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 17a2d4a9a9..a044757e62 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -49,7 +49,7 @@ namespace LLTrace
 		void deactivate(Recording* recording);
 		active_recording_list_t::reverse_iterator bringUpToDate(Recording* recording);
 
-		virtual void pushToMaster() = 0;
+		virtual bool pushToMaster() = 0;
 
 		TimeBlockTreeNode* getTimeBlockTreeNode(S32 index);
 
@@ -80,19 +80,22 @@ namespace LLTrace
 		void addSlaveThread(class SlaveThreadRecorder* child);
 		void removeSlaveThread(class SlaveThreadRecorder* child);
 
-		/*virtual */ void pushToMaster();
+		/*virtual */ bool pushToMaster();
 
 		// call this periodically to gather stats data from slave threads
 		void pullFromSlaveThreads();
 
 		LLMutex* getSlaveListMutex() { return &mSlaveListMutex; }
 
+		U32	getPullCount() { return mPullCount; }
+
 	private:
 
 		typedef std::list<class SlaveThreadRecorder*> slave_thread_recorder_list_t;
 
-		slave_thread_recorder_list_t	mSlaveThreadRecorders;
-		LLMutex							mSlaveListMutex;
+		slave_thread_recorder_list_t	mSlaveThreadRecorders;	// list of slave thread recorders associated with this master
+		LLMutex							mSlaveListMutex;		// protects access to slave list
+		LLAtomicU32						mPullCount;				// number of times data has been pulled from slaves
 	};
 
 	class LL_COMMON_API SlaveThreadRecorder : public ThreadRecorder
@@ -102,7 +105,7 @@ namespace LLTrace
 		~SlaveThreadRecorder();
 
 		// call this periodically to gather stats data for master thread to consume
-		/*virtual*/ void pushToMaster();
+		/*virtual*/ bool pushToMaster();
 
 		MasterThreadRecorder* 	mMaster;
 
@@ -119,6 +122,7 @@ namespace LLTrace
 		};
 		SharedData				mSharedData;
 		MasterThreadRecorder&	mMasterRecorder;
+		U32						mPushCount;
 	};
 }
 
-- 
cgit v1.2.3


From e50e6004082223fdc0bfd78bc697d48a7f45b379 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 30 May 2013 20:15:48 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 reverted SlaveThreadRecorder update gating moved processTimes() outside of
 Recording, so it is called only once per frame refined sample merge logic so
 that multi-threaded samples do not stomp on linear history of a stat

---
 indra/llcommon/llfasttimer.cpp           | 40 ++++++++++++++++++--------------
 indra/llcommon/lltrace.h                 | 27 ++++++++++++---------
 indra/llcommon/lltracerecording.cpp      | 17 +++++++-------
 indra/llcommon/lltracethreadrecorder.cpp | 25 ++++++--------------
 indra/llcommon/lltracethreadrecorder.h   |  9 +++----
 5 files changed, 57 insertions(+), 61 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 5dc5fdd5be..3fdd33959d 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -180,6 +180,7 @@ TimeBlockTreeNode& TimeBlock::getTreeNode() const
 
 static LLFastTimer::DeclareTimer FTM_PROCESS_TIMES("Process FastTimer Times");
 
+// not thread safe, so only call on main thread
 //static
 void TimeBlock::processTimes()
 {
@@ -195,8 +196,8 @@ void TimeBlock::processTimes()
 		TimeBlock& timer = *it;
 		if (&timer == &TimeBlock::getRootTimeBlock()) continue;
 			
-			// bootstrap tree construction by attaching to last timer to be on stack
-			// when this timer was called
+		// bootstrap tree construction by attaching to last timer to be on stack
+		// when this timer was called
 		if (timer.getParent() == &TimeBlock::getRootTimeBlock())
 		{
 			TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
@@ -233,30 +234,30 @@ void TimeBlock::processTimes()
 			TimeBlockAccumulator* accumulator = timerp->getPrimaryAccumulator();
 
 			if (accumulator->mMoveUpTree)
-		{
+			{
 				// since ancestors have already been visited, re-parenting 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());
-				accumulator->mParent = timerp->getParent();
-				accumulator->mMoveUpTree = false;
-
-			// don't bubble up any ancestors until descendants are done bubbling up
-				// as ancestors may call this timer only on certain paths, so we want to resolve
-				// child-most block locations before their parents
-			it.skipAncestors();
+				//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());
+					accumulator->mParent = timerp->getParent();
+					accumulator->mMoveUpTree = false;
+
+				// don't bubble up any ancestors until descendants are done bubbling up
+					// as ancestors may call this timer only on certain paths, so we want to resolve
+					// child-most block locations before their parents
+				it.skipAncestors();
+			}
 		}
 	}
-}
 
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
 	BlockTimerStackRecord* stack_record			= ThreadTimerStack::getInstance();
 	BlockTimer* cur_timer						= stack_record->mActiveTimer;
 	TimeBlockAccumulator* accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
 
-	// root defined by parent pointing to self
-	while(cur_timer && cur_timer->mParentTimerData.mActiveTimer != cur_timer)
+	while(cur_timer 
+		&& cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self
 	{
 		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
 		accumulator->mTotalTimeCounter += cumulative_time_delta - (accumulator->mTotalTimeCounter - cur_timer->mBlockStartTotalTimeCounter);
@@ -413,8 +414,11 @@ TimeBlockAccumulator::TimeBlockAccumulator()
 	mParent(NULL)
 {}
 
-void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other )
+void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other, bool append )
 {
+	// we can't merge two unrelated time block samples, as that will screw with the nested timings
+	// due to the call hierarchy of each thread
+	llassert(append);
 	mTotalTimeCounter += other.mTotalTimeCounter - other.mStartTotalTimeCounter;
 	mSelfTimeCounter += other.mSelfTimeCounter;
 	mCalls += other.mCalls;
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 00bab536ff..6dfe9e4b4e 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -121,12 +121,12 @@ public:
 		return mStorage[index]; 
 	}
 
-	void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other)
+	void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, bool append = true)
 	{
 		llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot);
 		for (size_t i = 0; i < sNextStorageSlot; i++)
 		{
-			mStorage[i].addSamples(other.mStorage[i]);
+			mStorage[i].addSamples(other.mStorage[i], append);
 		}
 	}
 
@@ -310,7 +310,7 @@ public:
 		mLastValue = value;
 	}
 
-	void addSamples(const self_t& other)
+	void addSamples(const self_t& other, bool append)
 	{
 		if (other.mNumSamples)
 		{
@@ -350,7 +350,7 @@ public:
 			F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
 			mNumSamples += other.mNumSamples;
 			mMean = mMean * weight + other.mMean * (1.f - weight);
-			mLastValue = other.mLastValue;
+			if (append) mLastValue = other.mLastValue;
 		}
 	}
 
@@ -434,7 +434,7 @@ public:
 		mHasValue = true;
 	}
 
-	void addSamples(const self_t& other)
+	void addSamples(const self_t& other, bool append)
 	{
 		if (other.mTotalSamplingTime)
 		{
@@ -476,9 +476,12 @@ public:
 			mNumSamples += other.mNumSamples;
 			mTotalSamplingTime += other.mTotalSamplingTime;
 			mMean = (mMean * weight) + (other.mMean * (1.0 - weight));
-			mLastValue = other.mLastValue;
-			mLastSampleTimeStamp = other.mLastSampleTimeStamp;
-			mHasValue |= other.mHasValue;
+			if (append)
+			{
+				mLastValue = other.mLastValue;
+				mLastSampleTimeStamp = other.mLastSampleTimeStamp;
+				mHasValue |= other.mHasValue;
+			}
 		}
 	}
 
@@ -551,7 +554,7 @@ public:
 		mSum += value;
 	}
 
-	void addSamples(const CountAccumulator<T>& other)
+	void addSamples(const CountAccumulator<T>& other, bool /*append*/)
 	{
 		mSum += other.mSum;
 		mNumSamples += other.mNumSamples;
@@ -596,7 +599,7 @@ public:
 	};
 
 	TimeBlockAccumulator();
-	void addSamples(const self_t& other);
+	void addSamples(const self_t& other, bool /*append*/);
 	void reset(const self_t* other);
 	void flush() {}
 
@@ -716,6 +719,8 @@ void add(CountStatHandle<T>& count, VALUE_T value)
 
 struct MemStatAccumulator
 {
+	typedef MemStatAccumulator self_t;
+
 	MemStatAccumulator()
 	:	mSize(0),
 		mChildSize(0),
@@ -723,7 +728,7 @@ struct MemStatAccumulator
 		mDeallocatedCount(0)
 	{}
 
-	void addSamples(const MemStatAccumulator& other)
+	void addSamples(const MemStatAccumulator& other, bool /*append*/)
 	{
 		mSize += other.mSize;
 		mChildSize += other.mChildSize;
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 86cdca3e10..3994e4f521 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -97,13 +97,15 @@ void RecordingBuffers::append( const RecordingBuffers& other )
 
 void RecordingBuffers::merge( const RecordingBuffers& other)
 {
-	mCountsFloat.addSamples(other.mCountsFloat);
-	mCounts.addSamples(other.mCounts);
-	mSamplesFloat.addSamples(other.mSamplesFloat);
-	mSamples.addSamples(other.mSamples);
-	mEventsFloat.addSamples(other.mEventsFloat);
-	mEvents.addSamples(other.mEvents);
-	mMemStats.addSamples(other.mMemStats);
+	mCountsFloat.addSamples(other.mCountsFloat, false);
+	mCounts.addSamples(other.mCounts, false);
+	mSamplesFloat.addSamples(other.mSamplesFloat, false);
+	mSamples.addSamples(other.mSamples, false);
+	mEventsFloat.addSamples(other.mEventsFloat, false);
+	mEvents.addSamples(other.mEvents, false);
+	mMemStats.addSamples(other.mMemStats, false);
+	// for now, hold out timers from merge, need to be displayed per thread
+	//mStackTimers.addSamples(other.mStackTimers, false);
 }
 
 void RecordingBuffers::reset(RecordingBuffers* other)
@@ -190,7 +192,6 @@ void Recording::handleStop()
 {
 	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
 	mBuffers.write()->flush();
-	LLTrace::TimeBlock::processTimes();
 	LLTrace::get_thread_recorder()->deactivate(this);
 }
 
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 89b5df1f94..75c7cb2ff1 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -202,21 +202,14 @@ SlaveThreadRecorder::~SlaveThreadRecorder()
 	mMasterRecorder.removeSlaveThread(this);
 }
 
-bool SlaveThreadRecorder::pushToMaster()
+void SlaveThreadRecorder::pushToMaster()
 {
-	if (mPushCount != mMasterRecorder.getPullCount())
+	mThreadRecording.stop();
 	{
-		mThreadRecording.stop();
-		{
-			LLMutexLock(mMasterRecorder.getSlaveListMutex());
-			mSharedData.appendFrom(mThreadRecording);
-		}
-		mThreadRecording.start();
-
-		mPushCount = mMasterRecorder.getPullCount();
-		return true;
+		LLMutexLock(mMasterRecorder.getSlaveListMutex());
+		mSharedData.appendFrom(mThreadRecording);
 	}
-	return false;
+	mThreadRecording.start();
 }
 
 void SlaveThreadRecorder::SharedData::appendFrom( const Recording& source )
@@ -271,8 +264,6 @@ void MasterThreadRecorder::pullFromSlaveThreads()
 		(*it)->mSharedData.mergeTo(target_recording_buffers);
 		(*it)->mSharedData.reset();
 	}
-
-	mPullCount++;
 }
 
 void MasterThreadRecorder::addSlaveThread( class SlaveThreadRecorder* child )
@@ -298,10 +289,8 @@ void MasterThreadRecorder::removeSlaveThread( class SlaveThreadRecorder* child )
 	}
 }
 
-bool MasterThreadRecorder::pushToMaster()
-{
-	return false;
-}
+void MasterThreadRecorder::pushToMaster()
+{}
 
 MasterThreadRecorder::MasterThreadRecorder()
 {}
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index a044757e62..bf3701304f 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -49,7 +49,7 @@ namespace LLTrace
 		void deactivate(Recording* recording);
 		active_recording_list_t::reverse_iterator bringUpToDate(Recording* recording);
 
-		virtual bool pushToMaster() = 0;
+		virtual void pushToMaster() = 0;
 
 		TimeBlockTreeNode* getTimeBlockTreeNode(S32 index);
 
@@ -80,14 +80,13 @@ namespace LLTrace
 		void addSlaveThread(class SlaveThreadRecorder* child);
 		void removeSlaveThread(class SlaveThreadRecorder* child);
 
-		/*virtual */ bool pushToMaster();
+		/*virtual */ void pushToMaster();
 
 		// call this periodically to gather stats data from slave threads
 		void pullFromSlaveThreads();
 
 		LLMutex* getSlaveListMutex() { return &mSlaveListMutex; }
 
-		U32	getPullCount() { return mPullCount; }
 
 	private:
 
@@ -95,7 +94,6 @@ namespace LLTrace
 
 		slave_thread_recorder_list_t	mSlaveThreadRecorders;	// list of slave thread recorders associated with this master
 		LLMutex							mSlaveListMutex;		// protects access to slave list
-		LLAtomicU32						mPullCount;				// number of times data has been pulled from slaves
 	};
 
 	class LL_COMMON_API SlaveThreadRecorder : public ThreadRecorder
@@ -105,7 +103,7 @@ namespace LLTrace
 		~SlaveThreadRecorder();
 
 		// call this periodically to gather stats data for master thread to consume
-		/*virtual*/ bool pushToMaster();
+		/*virtual*/ void pushToMaster();
 
 		MasterThreadRecorder* 	mMaster;
 
@@ -122,7 +120,6 @@ namespace LLTrace
 		};
 		SharedData				mSharedData;
 		MasterThreadRecorder&	mMasterRecorder;
-		U32						mPushCount;
 	};
 }
 
-- 
cgit v1.2.3


From 9def3590f41dee3cba7760e4443fdc71f5fb2db6 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 31 May 2013 16:01:46 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 fixed multithreading lltrace causing values to be interpolated towards 0
 added Radians unit improved sceneloadmonitor restart heuristic to use
 accumulated camera motion

---
 indra/llcommon/lltrace.h                 | 8 +++++---
 indra/llcommon/lltracerecording.cpp      | 2 +-
 indra/llcommon/lltracerecording.h        | 9 ++++-----
 indra/llcommon/lltracethreadrecorder.cpp | 2 +-
 indra/llcommon/llunit.h                  | 3 +++
 5 files changed, 14 insertions(+), 10 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 6dfe9e4b4e..0daac95ea4 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -504,9 +504,11 @@ public:
 		LLUnitImplicit<LLUnits::Seconds, F64> time_stamp = LLTimer::getTotalSeconds();
 		LLUnitImplicit<LLUnits::Seconds, F64> delta_time = time_stamp - mLastSampleTimeStamp;
 
-		mSum += (F64)mLastValue * delta_time;
-
-		mTotalSamplingTime += delta_time;
+		if (mHasValue)
+		{
+			mSum += (F64)mLastValue * delta_time;
+			mTotalSamplingTime += delta_time;
+		}
 		mLastSampleTimeStamp = time_stamp;
 	}
 
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 3994e4f521..e45639a034 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -538,7 +538,7 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 	other.setPlayState(other_play_state);
 }
 
-LLUnit<LLUnits::Seconds, F64> PeriodicRecording::getDuration()
+LLUnit<LLUnits::Seconds, F64> PeriodicRecording::getDuration() const
 {
 	LLUnit<LLUnits::Seconds, F64> duration;
 	size_t num_periods = mRecordingPeriods.size();
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index aaeb32e891..4a77dfb1f6 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -308,7 +308,7 @@ namespace LLTrace
 		void nextPeriod();
 		U32 getNumPeriods() { return mRecordingPeriods.size(); }
 
-		LLUnit<LLUnits::Seconds, F64> getDuration();
+		LLUnit<LLUnits::Seconds, F64> getDuration() const;
 
 		void appendPeriodicRecording(PeriodicRecording& other);
 		Recording& getLastRecording();
@@ -356,7 +356,7 @@ namespace LLTrace
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
 
-			typename T min_val = std::numeric_limits<T>::max();
+			T min_val = std::numeric_limits<T>::max();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				S32 index = (mCurPeriod + total_periods - i) % total_periods;
@@ -397,7 +397,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename T getPeriodMax(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		T getPeriodMax(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
@@ -412,7 +412,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename T getPeriodMax(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		T getPeriodMax(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
@@ -551,7 +551,6 @@ namespace LLTrace
 
 	private:
 		std::vector<Recording>	mRecordingPeriods;
-		Recording	mTotalRecording;
 		const bool	mAutoResize;
 		S32			mCurPeriod;
 	};
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 75c7cb2ff1..c281b768ce 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -247,7 +247,7 @@ void SlaveThreadRecorder::SharedData::reset()
 // MasterThreadRecorder
 ///////////////////////////////////////////////////////////////////////
 
-LLFastTimer::DeclareTimer FTM_PULL_TRACE_DATA_FROM_SLAVES("Pull slave trace data");
+static LLFastTimer::DeclareTimer FTM_PULL_TRACE_DATA_FROM_SLAVES("Pull slave trace data");
 void MasterThreadRecorder::pullFromSlaveThreads()
 {
 	LLFastTimer _(FTM_PULL_TRACE_DATA_FROM_SLAVES);
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index f86f111b90..e2803c74b0 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -471,6 +471,9 @@ struct Hertz { typedef Hertz base_unit_t; };
 LL_DECLARE_DERIVED_UNIT(1000, Hertz, Kilohertz);
 LL_DECLARE_DERIVED_UNIT(1000 * 1000, Hertz, Megahertz);
 LL_DECLARE_DERIVED_UNIT(1000 * 1000 * 1000, Hertz, Gigahertz);
+
+struct Radians { typedef Radians base_unit_t; };
+LL_DECLARE_DERIVED_UNIT(DEG_TO_RAD, Radians, Degrees);
 } // namespace LLUnits
 
 #endif // LL_LLUNIT_H
-- 
cgit v1.2.3


From fd21ddd9d0adf7342fe89d371868c3f7f7ca9f5f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 31 May 2013 23:40:10 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 made recordings auto-update when executing query while active

---
 indra/llcommon/lltracerecording.cpp | 119 ++++++++++++++++++++++-----------
 indra/llcommon/lltracerecording.h   | 130 ++++++++++++++++++------------------
 2 files changed, 144 insertions(+), 105 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index e45639a034..aedb9c7542 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -221,88 +221,101 @@ void Recording::mergeRecording( const Recording& other)
 	setPlayState(play_state);
 }
 
-LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) const
+LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+	update();
 	return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
 				/ (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
-LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const
+LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+	update();
 	return (F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
 
-U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const
+U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat)
 {
+	update();
 	return mBuffers->mStackTimers[stat.getIndex()].mCalls;
 }
 
-LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat) const
+LLUnit<LLUnits::Seconds, F64> 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);
 }
 
-LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const
+LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
+	update();
 	return (F64)(accumulator.mSelfTimeCounter) 
 			/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
 }
 
-F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const
+F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat)
 {
+	update();
 	return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds;
 }
 
-LLUnit<LLUnits::Bytes, U32> Recording::getSum(const TraceType<MemStatAccumulator>& stat) const
+LLUnit<LLUnits::Bytes, U32> Recording::getSum(const TraceType<MemStatAccumulator>& stat)
 {
+	update();
 	return mBuffers->mMemStats[stat.getIndex()].mAllocatedCount;
 }
 
-LLUnit<LLUnits::Bytes, F32> Recording::getPerSec(const TraceType<MemStatAccumulator>& stat) const
+LLUnit<LLUnits::Bytes, F32> Recording::getPerSec(const TraceType<MemStatAccumulator>& stat)
 {
+	update();
 	return (F32)mBuffers->mMemStats[stat.getIndex()].mAllocatedCount / mElapsedSeconds;
 }
 
 
-F64 Recording::getSum( const TraceType<CountAccumulator<F64> >& stat ) const
+F64 Recording::getSum( const TraceType<CountAccumulator<F64> >& stat )
 {
+	update();
 	return mBuffers->mCountsFloat[stat.getIndex()].getSum();
 }
 
-S64 Recording::getSum( const TraceType<CountAccumulator<S64> >& stat ) const
+S64 Recording::getSum( const TraceType<CountAccumulator<S64> >& stat )
 {
+	update();
 	return mBuffers->mCounts[stat.getIndex()].getSum();
 }
 
-F64 Recording::getSum( const TraceType<EventAccumulator<F64> >& stat ) const
+F64 Recording::getSum( const TraceType<EventAccumulator<F64> >& stat )
 {
+	update();
 	return (F64)mBuffers->mEventsFloat[stat.getIndex()].getSum();
 }
 
-S64 Recording::getSum( const TraceType<EventAccumulator<S64> >& stat ) const
+S64 Recording::getSum( const TraceType<EventAccumulator<S64> >& stat )
 {
+	update();
 	return (S64)mBuffers->mEvents[stat.getIndex()].getSum();
 }
 
 
 
-F64 Recording::getPerSec( const TraceType<CountAccumulator<F64> >& stat ) const
+F64 Recording::getPerSec( const TraceType<CountAccumulator<F64> >& stat )
 {
+	update();
 	F64 sum = mBuffers->mCountsFloat[stat.getIndex()].getSum();
 	return  (sum != 0.0) 
 		? (sum / mElapsedSeconds)
 		: 0.0;
 }
 
-F64 Recording::getPerSec( const TraceType<CountAccumulator<S64> >& stat ) const
+F64 Recording::getPerSec( const TraceType<CountAccumulator<S64> >& stat )
 {
 	S64 sum = mBuffers->mCounts[stat.getIndex()].getSum();
 	return (sum != 0) 
@@ -310,133 +323,159 @@ F64 Recording::getPerSec( const TraceType<CountAccumulator<S64> >& stat ) const
 		: 0.0;
 }
 
-U32 Recording::getSampleCount( const TraceType<CountAccumulator<F64> >& stat ) const
+U32 Recording::getSampleCount( const TraceType<CountAccumulator<F64> >& stat )
 {
+	update();
 	return mBuffers->mCountsFloat[stat.getIndex()].getSampleCount();
 }
 
-U32 Recording::getSampleCount( const TraceType<CountAccumulator<S64> >& stat ) const
+U32 Recording::getSampleCount( const TraceType<CountAccumulator<S64> >& stat )
 {
+	update();
 	return mBuffers->mCounts[stat.getIndex()].getSampleCount();
 }
 
-F64 Recording::getMin( const TraceType<SampleAccumulator<F64> >& stat ) const
+F64 Recording::getMin( const TraceType<SampleAccumulator<F64> >& stat )
 {
+	update();
 	return mBuffers->mSamplesFloat[stat.getIndex()].getMin();
 }
 
-S64 Recording::getMin( const TraceType<SampleAccumulator<S64> >& stat ) const
+S64 Recording::getMin( const TraceType<SampleAccumulator<S64> >& stat )
 {
+	update();
 	return mBuffers->mSamples[stat.getIndex()].getMin();
 }
 
-F64 Recording::getMax( const TraceType<SampleAccumulator<F64> >& stat ) const
+F64 Recording::getMax( const TraceType<SampleAccumulator<F64> >& stat )
 {
+	update();
 	return mBuffers->mSamplesFloat[stat.getIndex()].getMax();
 }
 
-S64 Recording::getMax( const TraceType<SampleAccumulator<S64> >& stat ) const
+S64 Recording::getMax( const TraceType<SampleAccumulator<S64> >& stat )
 {
+	update();
 	return mBuffers->mSamples[stat.getIndex()].getMax();
 }
 
-F64 Recording::getMean( const TraceType<SampleAccumulator<F64> >& stat ) const
+F64 Recording::getMean( const TraceType<SampleAccumulator<F64> >& stat )
 {
+	update();
 	return mBuffers->mSamplesFloat[stat.getIndex()].getMean();
 }
 
-F64 Recording::getMean( const TraceType<SampleAccumulator<S64> >& stat ) const
+F64 Recording::getMean( const TraceType<SampleAccumulator<S64> >& stat )
 {
+	update();
 	return mBuffers->mSamples[stat.getIndex()].getMean();
 }
 
-F64 Recording::getStandardDeviation( const TraceType<SampleAccumulator<F64> >& stat ) const
+F64 Recording::getStandardDeviation( const TraceType<SampleAccumulator<F64> >& stat )
 {
+	update();
 	return mBuffers->mSamplesFloat[stat.getIndex()].getStandardDeviation();
 }
 
-F64 Recording::getStandardDeviation( const TraceType<SampleAccumulator<S64> >& stat ) const
+F64 Recording::getStandardDeviation( const TraceType<SampleAccumulator<S64> >& stat )
 {
+	update();
 	return mBuffers->mSamples[stat.getIndex()].getStandardDeviation();
 }
 
-F64 Recording::getLastValue( const TraceType<SampleAccumulator<F64> >& stat ) const
+F64 Recording::getLastValue( const TraceType<SampleAccumulator<F64> >& stat )
 {
+	update();
 	return mBuffers->mSamplesFloat[stat.getIndex()].getLastValue();
 }
 
-S64 Recording::getLastValue( const TraceType<SampleAccumulator<S64> >& stat ) const
+S64 Recording::getLastValue( const TraceType<SampleAccumulator<S64> >& stat )
 {
+	update();
 	return mBuffers->mSamples[stat.getIndex()].getLastValue();
 }
 
-U32 Recording::getSampleCount( const TraceType<SampleAccumulator<F64> >& stat ) const
+U32 Recording::getSampleCount( const TraceType<SampleAccumulator<F64> >& stat )
 {
+	update();
 	return mBuffers->mSamplesFloat[stat.getIndex()].getSampleCount();
 }
 
-U32 Recording::getSampleCount( const TraceType<SampleAccumulator<S64> >& stat ) const
+U32 Recording::getSampleCount( const TraceType<SampleAccumulator<S64> >& stat )
 {
+	update();
 	return mBuffers->mSamples[stat.getIndex()].getSampleCount();
 }
 
-F64 Recording::getMin( const TraceType<EventAccumulator<F64> >& stat ) const
+F64 Recording::getMin( const TraceType<EventAccumulator<F64> >& stat )
 {
+	update();
 	return mBuffers->mEventsFloat[stat.getIndex()].getMin();
 }
 
-S64 Recording::getMin( const TraceType<EventAccumulator<S64> >& stat ) const
+S64 Recording::getMin( const TraceType<EventAccumulator<S64> >& stat )
 {
+	update();
 	return mBuffers->mEvents[stat.getIndex()].getMin();
 }
 
-F64 Recording::getMax( const TraceType<EventAccumulator<F64> >& stat ) const
+F64 Recording::getMax( const TraceType<EventAccumulator<F64> >& stat )
 {
+	update();
 	return mBuffers->mEventsFloat[stat.getIndex()].getMax();
 }
 
-S64 Recording::getMax( const TraceType<EventAccumulator<S64> >& stat ) const
+S64 Recording::getMax( const TraceType<EventAccumulator<S64> >& stat )
 {
+	update();
 	return mBuffers->mEvents[stat.getIndex()].getMax();
 }
 
-F64 Recording::getMean( const TraceType<EventAccumulator<F64> >& stat ) const
+F64 Recording::getMean( const TraceType<EventAccumulator<F64> >& stat )
 {
+	update();
 	return mBuffers->mEventsFloat[stat.getIndex()].getMean();
 }
 
-F64 Recording::getMean( const TraceType<EventAccumulator<S64> >& stat ) const
+F64 Recording::getMean( const TraceType<EventAccumulator<S64> >& stat )
 {
+	update();
 	return mBuffers->mEvents[stat.getIndex()].getMean();
 }
 
-F64 Recording::getStandardDeviation( const TraceType<EventAccumulator<F64> >& stat ) const
+F64 Recording::getStandardDeviation( const TraceType<EventAccumulator<F64> >& stat )
 {
+	update();
 	return mBuffers->mEventsFloat[stat.getIndex()].getStandardDeviation();
 }
 
-F64 Recording::getStandardDeviation( const TraceType<EventAccumulator<S64> >& stat ) const
+F64 Recording::getStandardDeviation( const TraceType<EventAccumulator<S64> >& stat )
 {
+	update();
 	return mBuffers->mEvents[stat.getIndex()].getStandardDeviation();
 }
 
-F64 Recording::getLastValue( const TraceType<EventAccumulator<F64> >& stat ) const
+F64 Recording::getLastValue( const TraceType<EventAccumulator<F64> >& stat )
 {
+	update();
 	return mBuffers->mEventsFloat[stat.getIndex()].getLastValue();
 }
 
-S64 Recording::getLastValue( const TraceType<EventAccumulator<S64> >& stat ) const
+S64 Recording::getLastValue( const TraceType<EventAccumulator<S64> >& stat )
 {
+	update();
 	return mBuffers->mEvents[stat.getIndex()].getLastValue();
 }
 
-U32 Recording::getSampleCount( const TraceType<EventAccumulator<F64> >& stat ) const
+U32 Recording::getSampleCount( const TraceType<EventAccumulator<F64> >& stat )
 {
+	update();
 	return mBuffers->mEventsFloat[stat.getIndex()].getSampleCount();
 }
 
-U32 Recording::getSampleCount( const TraceType<EventAccumulator<S64> >& stat ) const
+U32 Recording::getSampleCount( const TraceType<EventAccumulator<S64> >& stat )
 {
+	update();
 	return mBuffers->mEvents[stat.getIndex()].getSampleCount();
 }
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 4a77dfb1f6..58b40fa378 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -151,134 +151,134 @@ namespace LLTrace
 		void makeUnique() { mBuffers.makeUnique(); }
 
 		// Timer accessors
-		LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator>& stat) const;
-		LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const;
-		U32 getSum(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const;
+		LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator>& stat);
+		LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat);
+		U32 getSum(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat);
 
-		LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimeBlockAccumulator>& stat) const;
-		LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const;
-		F32 getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const;
+		LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimeBlockAccumulator>& stat);
+		LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat);
+		F32 getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat);
 
 		// Memory accessors
-		LLUnit<LLUnits::Bytes, U32> getSum(const TraceType<MemStatAccumulator>& stat) const;
-		LLUnit<LLUnits::Bytes, F32> getPerSec(const TraceType<MemStatAccumulator>& stat) const;
+		LLUnit<LLUnits::Bytes, U32> getSum(const TraceType<MemStatAccumulator>& stat);
+		LLUnit<LLUnits::Bytes, F32> getPerSec(const TraceType<MemStatAccumulator>& stat);
 
 		// CountStatHandle accessors
-		F64 getSum(const TraceType<CountAccumulator<F64> >& stat) const;
-		S64 getSum(const TraceType<CountAccumulator<S64> >& stat) const;
+		F64 getSum(const TraceType<CountAccumulator<F64> >& stat);
+		S64 getSum(const TraceType<CountAccumulator<S64> >& stat);
 		template <typename T>
-		T getSum(const CountStatHandle<T>& stat) const
+		T getSum(const CountStatHandle<T>& stat)
 		{
 			return (T)getSum(static_cast<const TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getPerSec(const TraceType<CountAccumulator<F64> >& stat) const;
-		F64 getPerSec(const TraceType<CountAccumulator<S64> >& stat) const;
+		F64 getPerSec(const TraceType<CountAccumulator<F64> >& stat);
+		F64 getPerSec(const TraceType<CountAccumulator<S64> >& stat);
 		template <typename T>
-		T getPerSec(const CountStatHandle<T>& stat) const
+		T getPerSec(const CountStatHandle<T>& stat)
 		{
 			return (T)getPerSec(static_cast<const TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		U32 getSampleCount(const TraceType<CountAccumulator<F64> >& stat) const;
-		U32 getSampleCount(const TraceType<CountAccumulator<S64> >& stat) const;
+		U32 getSampleCount(const TraceType<CountAccumulator<F64> >& stat);
+		U32 getSampleCount(const TraceType<CountAccumulator<S64> >& stat);
 
 
 		// SampleStatHandle accessors
-		F64 getMin(const TraceType<SampleAccumulator<F64> >& stat) const;
-		S64 getMin(const TraceType<SampleAccumulator<S64> >& stat) const;
+		F64 getMin(const TraceType<SampleAccumulator<F64> >& stat);
+		S64 getMin(const TraceType<SampleAccumulator<S64> >& stat);
 		template <typename T>
-		T getMin(const SampleStatHandle<T>& stat) const
+		T getMin(const SampleStatHandle<T>& stat)
 		{
 			return (T)getMin(static_cast<const TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getMax(const TraceType<SampleAccumulator<F64> >& stat) const;
-		S64 getMax(const TraceType<SampleAccumulator<S64> >& stat) const;
+		F64 getMax(const TraceType<SampleAccumulator<F64> >& stat);
+		S64 getMax(const TraceType<SampleAccumulator<S64> >& stat);
 		template <typename T>
-		T getMax(const SampleStatHandle<T>& stat) const
+		T getMax(const SampleStatHandle<T>& stat)
 		{
 			return (T)getMax(static_cast<const TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getMean(const TraceType<SampleAccumulator<F64> >& stat) const;
-		F64 getMean(const TraceType<SampleAccumulator<S64> >& stat) const;
+		F64 getMean(const TraceType<SampleAccumulator<F64> >& stat);
+		F64 getMean(const TraceType<SampleAccumulator<S64> >& stat);
 		template <typename T>
-		T getMean(SampleStatHandle<T>& stat) const
+		T getMean(SampleStatHandle<T>& stat)
 		{
 			return (T)getMean(static_cast<const TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getStandardDeviation(const TraceType<SampleAccumulator<F64> >& stat) const;
-		F64 getStandardDeviation(const TraceType<SampleAccumulator<S64> >& stat) const;
+		F64 getStandardDeviation(const TraceType<SampleAccumulator<F64> >& stat);
+		F64 getStandardDeviation(const TraceType<SampleAccumulator<S64> >& stat);
 		template <typename T>
-		T getStandardDeviation(const SampleStatHandle<T>& stat) const
+		T getStandardDeviation(const SampleStatHandle<T>& stat)
 		{
 			return (T)getStandardDeviation(static_cast<const TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getLastValue(const TraceType<SampleAccumulator<F64> >& stat) const;
-		S64 getLastValue(const TraceType<SampleAccumulator<S64> >& stat) const;
+		F64 getLastValue(const TraceType<SampleAccumulator<F64> >& stat);
+		S64 getLastValue(const TraceType<SampleAccumulator<S64> >& stat);
 		template <typename T>
-		T getLastValue(const SampleStatHandle<T>& stat) const
+		T getLastValue(const SampleStatHandle<T>& stat)
 		{
 			return (T)getLastValue(static_cast<const TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		U32 getSampleCount(const TraceType<SampleAccumulator<F64> >& stat) const;
-		U32 getSampleCount(const TraceType<SampleAccumulator<S64> >& stat) const;
+		U32 getSampleCount(const TraceType<SampleAccumulator<F64> >& stat);
+		U32 getSampleCount(const TraceType<SampleAccumulator<S64> >& stat);
 
 		// EventStatHandle accessors
-		F64 getSum(const TraceType<EventAccumulator<F64> >& stat) const;
-		S64 getSum(const TraceType<EventAccumulator<S64> >& stat) const;
+		F64 getSum(const TraceType<EventAccumulator<F64> >& stat);
+		S64 getSum(const TraceType<EventAccumulator<S64> >& stat);
 		template <typename T>
-		T getSum(const EventStatHandle<T>& stat) const
+		T getSum(const EventStatHandle<T>& stat)
 		{
 			return (T)getSum(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getMin(const TraceType<EventAccumulator<F64> >& stat) const;
-		S64 getMin(const TraceType<EventAccumulator<S64> >& stat) const;
+		F64 getMin(const TraceType<EventAccumulator<F64> >& stat);
+		S64 getMin(const TraceType<EventAccumulator<S64> >& stat);
 		template <typename T>
-		T getMin(const EventStatHandle<T>& stat) const
+		T getMin(const EventStatHandle<T>& stat)
 		{
 			return (T)getMin(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getMax(const TraceType<EventAccumulator<F64> >& stat) const;
-		S64 getMax(const TraceType<EventAccumulator<S64> >& stat) const;
+		F64 getMax(const TraceType<EventAccumulator<F64> >& stat);
+		S64 getMax(const TraceType<EventAccumulator<S64> >& stat);
 		template <typename T>
-		T getMax(const EventStatHandle<T>& stat) const
+		T getMax(const EventStatHandle<T>& stat)
 		{
 			return (T)getMax(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getMean(const TraceType<EventAccumulator<F64> >& stat) const;
-		F64 getMean(const TraceType<EventAccumulator<S64> >& stat) const;
+		F64 getMean(const TraceType<EventAccumulator<F64> >& stat);
+		F64 getMean(const TraceType<EventAccumulator<S64> >& stat);
 		template <typename T>
-		T getMean(EventStatHandle<T>& stat) const
+		T getMean(EventStatHandle<T>& stat)
 		{
 			return (T)getMean(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getStandardDeviation(const TraceType<EventAccumulator<F64> >& stat) const;
-		F64 getStandardDeviation(const TraceType<EventAccumulator<S64> >& stat) const;
+		F64 getStandardDeviation(const TraceType<EventAccumulator<F64> >& stat);
+		F64 getStandardDeviation(const TraceType<EventAccumulator<S64> >& stat);
 		template <typename T>
-		T getStandardDeviation(const EventStatHandle<T>& stat) const
+		T getStandardDeviation(const EventStatHandle<T>& stat)
 		{
 			return (T)getStandardDeviation(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		F64 getLastValue(const TraceType<EventAccumulator<F64> >& stat) const;
-		S64 getLastValue(const TraceType<EventAccumulator<S64> >& stat) const;
+		F64 getLastValue(const TraceType<EventAccumulator<F64> >& stat);
+		S64 getLastValue(const TraceType<EventAccumulator<S64> >& stat);
 		template <typename T>
-		T getLastValue(const EventStatHandle<T>& stat) const
+		T getLastValue(const EventStatHandle<T>& stat)
 		{
 			return (T)getLastValue(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
 		}
 
-		U32 getSampleCount(const TraceType<EventAccumulator<F64> >& stat) const;
-		U32 getSampleCount(const TraceType<EventAccumulator<S64> >& stat) const;
+		U32 getSampleCount(const TraceType<EventAccumulator<F64> >& stat);
+		U32 getSampleCount(const TraceType<EventAccumulator<S64> >& stat);
 
 		LLUnit<LLUnits::Seconds, F64> getDuration() const { return LLUnit<LLUnits::Seconds, F64>(mElapsedSeconds); }
 
@@ -321,7 +321,7 @@ namespace LLTrace
 
 		// catch all for stats that have a defined sum
 		template <typename T>
-		typename T::value_t getPeriodMin(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
+		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);
@@ -336,7 +336,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		T getPeriodMin(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		T getPeriodMin(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX)
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
@@ -351,7 +351,7 @@ namespace LLTrace
 		}
 		
 		template <typename T>
-		T getPeriodMin(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		T getPeriodMin(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX)
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
@@ -366,7 +366,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		F64 getPeriodMinPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
+		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);
@@ -382,7 +382,7 @@ namespace LLTrace
 
 		// catch all for stats that have a defined sum
 		template <typename T>
-		typename T::value_t getPeriodMax(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
+		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);
@@ -397,7 +397,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		T getPeriodMax(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		T getPeriodMax(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX)
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
@@ -412,7 +412,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		T getPeriodMax(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		T getPeriodMax(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX)
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
@@ -427,7 +427,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		F64 getPeriodMaxPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
+		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);
@@ -443,7 +443,7 @@ namespace LLTrace
 
 		// catch all for stats that have a defined sum
 		template <typename T>
-		typename T::mean_t getPeriodMean(const TraceType<T >& stat, size_t num_periods = U32_MAX) const
+		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);
@@ -464,7 +464,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename SampleAccumulator<T>::mean_t getPeriodMean(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		typename SampleAccumulator<T>::mean_t getPeriodMean(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX)
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
@@ -493,7 +493,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename EventAccumulator<T>::mean_t getPeriodMean(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX) const
+		typename EventAccumulator<T>::mean_t getPeriodMean(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX)
 		{
 			size_t total_periods = mRecordingPeriods.size();
 			num_periods = llmin(num_periods, total_periods);
@@ -522,7 +522,7 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename T::mean_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) const
+		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);
-- 
cgit v1.2.3


From 233201f8227f92e93061d3e2393a17b42dfa3dd1 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sun, 2 Jun 2013 22:49:17 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 removed unnecessary templates from accumulator types...now always track data
 in double precision floating point, using templated accessors to convert to
 and from arbitrary types

---
 indra/llcommon/lltrace.h                 |  96 ++++++-----
 indra/llcommon/lltracerecording.cpp      | 268 +++++++++++++++----------------
 indra/llcommon/lltracerecording.h        | 209 +++++++-----------------
 indra/llcommon/lltracethreadrecorder.cpp |   7 -
 4 files changed, 236 insertions(+), 344 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 0daac95ea4..d6b51a63ee 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -273,25 +273,23 @@ protected:
 	const size_t		mAccumulatorIndex;
 };
 
-template<typename T>
 class EventAccumulator
 {
 public:
-	typedef T value_t;
+	typedef F64 value_t;
 	typedef F64 mean_t;
-	typedef EventAccumulator<T> self_t;
 
 	EventAccumulator()
 	:	mSum(0),
-		mMin((std::numeric_limits<T>::max)()),
-		mMax((std::numeric_limits<T>::min)()),
+		mMin((std::numeric_limits<F64>::max)()),
+		mMax((std::numeric_limits<F64>::min)()),
 		mMean(0),
 		mVarianceSum(0),
 		mNumSamples(0),
 		mLastValue(0)
 	{}
 
-	void record(T value)
+	void record(F64 value)
 	{
 		mNumSamples++;
 		mSum += value;
@@ -305,12 +303,12 @@ public:
 			mMax = value;
 		}
 		F64 old_mean = mMean;
-		mMean += ((F64)value - old_mean) / (F64)mNumSamples;
-		mVarianceSum += ((F64)value - old_mean) * ((F64)value - mMean);
+		mMean += (value - old_mean) / (F64)mNumSamples;
+		mVarianceSum += (value - old_mean) * (value - mMean);
 		mLastValue = value;
 	}
 
-	void addSamples(const self_t& other, bool append)
+	void addSamples(const EventAccumulator& other, bool append)
 	{
 		if (other.mNumSamples)
 		{
@@ -354,12 +352,12 @@ public:
 		}
 	}
 
-	void reset(const self_t* other)
+	void reset(const EventAccumulator* other)
 	{
 		mNumSamples = 0;
 		mSum = 0;
-		mMin = std::numeric_limits<T>::max();
-		mMax = std::numeric_limits<T>::min();
+		mMin = std::numeric_limits<F64>::max();
+		mMax = std::numeric_limits<F64>::min();
 		mMean = 0;
 		mVarianceSum = 0;
 		mLastValue = other ? other->mLastValue : 0;
@@ -367,16 +365,16 @@ public:
 
 	void flush() {}
 
-	T	getSum() const { return (T)mSum; }
-	T	getMin() const { return (T)mMin; }
-	T	getMax() const { return (T)mMax; }
-	T	getLastValue() const { return (T)mLastValue; }
+	F64	getSum() const { return mSum; }
+	F64	getMin() const { return mMin; }
+	F64	getMax() const { return mMax; }
+	F64	getLastValue() const { return mLastValue; }
 	F64	getMean() const { return mMean; }
 	F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mNumSamples); }
 	U32 getSampleCount() const { return mNumSamples; }
 
 private:
-	T	mSum,
+	F64	mSum,
 		mMin,
 		mMax,
 		mLastValue;
@@ -388,18 +386,16 @@ private:
 };
 
 
-template<typename T>
 class SampleAccumulator
 {
 public:
-	typedef T value_t;
+	typedef F64 value_t;
 	typedef F64 mean_t;
-	typedef SampleAccumulator<T> self_t;
 
 	SampleAccumulator()
 	:	mSum(0),
-		mMin((std::numeric_limits<T>::max)()),
-		mMax((std::numeric_limits<T>::min)()),
+		mMin((std::numeric_limits<F64>::max)()),
+		mMax((std::numeric_limits<F64>::min)()),
 		mMean(0),
 		mVarianceSum(0),
 		mLastSampleTimeStamp(LLTimer::getTotalSeconds()),
@@ -409,7 +405,7 @@ public:
 		mHasValue(false)
 	{}
 
-	void sample(T value)
+	void sample(F64 value)
 	{
 		LLUnitImplicit<LLUnits::Seconds, F64> time_stamp = LLTimer::getTotalSeconds();
 		LLUnitImplicit<LLUnits::Seconds, F64> delta_time = time_stamp - mLastSampleTimeStamp;
@@ -418,15 +414,15 @@ public:
 		if (mHasValue)
 		{
 			mTotalSamplingTime += delta_time;
-			mSum += (F64)mLastValue * delta_time;
+			mSum += mLastValue * delta_time;
 
 			// NOTE: both conditions will hold first time through
 			if (value < mMin) { mMin = value; }
 			if (value > mMax) { mMax = value; }
 
 			F64 old_mean = mMean;
-			mMean += (delta_time / mTotalSamplingTime) * ((F64)mLastValue - old_mean);
-			mVarianceSum += delta_time * ((F64)mLastValue - old_mean) * ((F64)mLastValue - mMean);
+			mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean);
+			mVarianceSum += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
 		}
 
 		mLastValue = value;
@@ -434,7 +430,7 @@ public:
 		mHasValue = true;
 	}
 
-	void addSamples(const self_t& other, bool append)
+	void addSamples(const SampleAccumulator& other, bool append)
 	{
 		if (other.mTotalSamplingTime)
 		{
@@ -485,12 +481,12 @@ public:
 		}
 	}
 
-	void reset(const self_t* other)
+	void reset(const SampleAccumulator* other)
 	{
 		mNumSamples = 0;
 		mSum = 0;
-		mMin = std::numeric_limits<T>::max();
-		mMax = std::numeric_limits<T>::min();
+		mMin = std::numeric_limits<F64>::max();
+		mMax = std::numeric_limits<F64>::min();
 		mMean = other ? other->mLastValue : 0;
 		mVarianceSum = 0;
 		mLastSampleTimeStamp = LLTimer::getTotalSeconds();
@@ -506,22 +502,22 @@ public:
 
 		if (mHasValue)
 		{
-			mSum += (F64)mLastValue * delta_time;
+			mSum += mLastValue * delta_time;
 			mTotalSamplingTime += delta_time;
 		}
 		mLastSampleTimeStamp = time_stamp;
 	}
 
-	T	getSum() const { return (T)mSum; }
-	T	getMin() const { return (T)mMin; }
-	T	getMax() const { return (T)mMax; }
-	T	getLastValue() const { return (T)mLastValue; }
+	F64	getSum() const { return mSum; }
+	F64	getMin() const { return mMin; }
+	F64	getMax() const { return mMax; }
+	F64	getLastValue() const { return mLastValue; }
 	F64	getMean() const { return mMean; }
 	F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mTotalSamplingTime); }
 	U32 getSampleCount() const { return mNumSamples; }
 
 private:
-	T	mSum,
+	F64	mSum,
 		mMin,
 		mMax,
 		mLastValue;
@@ -537,12 +533,10 @@ private:
 	U32	mNumSamples;
 };
 
-template<typename T>
 class CountAccumulator
 {
 public:
-	typedef CountAccumulator<T> self_t;
-	typedef T value_t;
+	typedef F64 value_t;
 	typedef F64 mean_t;
 
 	CountAccumulator()
@@ -550,19 +544,19 @@ public:
 		mNumSamples(0)
 	{}
 
-	void add(T value)
+	void add(F64 value)
 	{
 		mNumSamples++;
 		mSum += value;
 	}
 
-	void addSamples(const CountAccumulator<T>& other, bool /*append*/)
+	void addSamples(const CountAccumulator& other, bool /*append*/)
 	{
 		mSum += other.mSum;
 		mNumSamples += other.mNumSamples;
 	}
 
-	void reset(const self_t* other)
+	void reset(const CountAccumulator* other)
 	{
 		mNumSamples = 0;
 		mSum = 0;
@@ -570,12 +564,12 @@ public:
 
 	void flush() {}
 
-	T	getSum() const { return (T)mSum; }
+	F64	getSum() const { return mSum; }
 
 	U32 getSampleCount() const { return mNumSamples; }
 
 private:
-	T	mSum;
+	F64	mSum;
 
 	U32	mNumSamples;
 };
@@ -659,11 +653,11 @@ public:
 
 template <typename T = F64>
 class EventStatHandle
-:	public TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
+:	public TraceType<EventAccumulator>
 {
 public:
 	typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
-	typedef TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> > trace_t;
+	typedef TraceType<EventAccumulator> trace_t;
 
 	EventStatHandle(const char* name, const char* description = NULL)
 	:	trace_t(name, description)
@@ -679,11 +673,11 @@ void record(EventStatHandle<T>& measurement, VALUE_T value)
 
 template <typename T = F64>
 class SampleStatHandle
-:	public TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
+:	public TraceType<SampleAccumulator>
 {
 public:
-	typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
-	typedef TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> > trace_t;
+	typedef F64 storage_t;
+	typedef TraceType<SampleAccumulator> trace_t;
 
 	SampleStatHandle(const char* name, const char* description = NULL)
 	:	trace_t(name, description)
@@ -699,11 +693,11 @@ void sample(SampleStatHandle<T>& measurement, VALUE_T value)
 
 template <typename T = F64>
 class CountStatHandle
-:	public TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >
+:	public TraceType<CountAccumulator>
 {
 public:
 	typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
-	typedef TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> > trace_t;
+	typedef TraceType<CountAccumulator> trace_t;
 
 	CountStatHandle(const char* name, const char* description = NULL) 
 	:	trace_t(name)
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index aedb9c7542..61ba21a365 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -44,11 +44,8 @@ RecordingBuffers::RecordingBuffers()
 
 void RecordingBuffers::handOffTo(RecordingBuffers& other)
 {
-	other.mCountsFloat.reset(&mCountsFloat);
 	other.mCounts.reset(&mCounts);
-	other.mSamplesFloat.reset(&mSamplesFloat);
 	other.mSamples.reset(&mSamples);
-	other.mEventsFloat.reset(&mEventsFloat);
 	other.mEvents.reset(&mEvents);
 	other.mStackTimers.reset(&mStackTimers);
 	other.mMemStats.reset(&mMemStats);
@@ -56,11 +53,8 @@ void RecordingBuffers::handOffTo(RecordingBuffers& other)
 
 void RecordingBuffers::makePrimary()
 {
-	mCountsFloat.makePrimary();
 	mCounts.makePrimary();
-	mSamplesFloat.makePrimary();
 	mSamples.makePrimary();
-	mEventsFloat.makePrimary();
 	mEvents.makePrimary();
 	mStackTimers.makePrimary();
 	mMemStats.makePrimary();
@@ -85,11 +79,8 @@ bool RecordingBuffers::isPrimary() const
 
 void RecordingBuffers::append( const RecordingBuffers& other )
 {
-	mCountsFloat.addSamples(other.mCountsFloat);
 	mCounts.addSamples(other.mCounts);
-	mSamplesFloat.addSamples(other.mSamplesFloat);
 	mSamples.addSamples(other.mSamples);
-	mEventsFloat.addSamples(other.mEventsFloat);
 	mEvents.addSamples(other.mEvents);
 	mMemStats.addSamples(other.mMemStats);
 	mStackTimers.addSamples(other.mStackTimers);
@@ -97,11 +88,8 @@ void RecordingBuffers::append( const RecordingBuffers& other )
 
 void RecordingBuffers::merge( const RecordingBuffers& other)
 {
-	mCountsFloat.addSamples(other.mCountsFloat, false);
 	mCounts.addSamples(other.mCounts, false);
-	mSamplesFloat.addSamples(other.mSamplesFloat, false);
 	mSamples.addSamples(other.mSamples, false);
-	mEventsFloat.addSamples(other.mEventsFloat, false);
 	mEvents.addSamples(other.mEvents, false);
 	mMemStats.addSamples(other.mMemStats, false);
 	// for now, hold out timers from merge, need to be displayed per thread
@@ -110,11 +98,8 @@ void RecordingBuffers::merge( const RecordingBuffers& other)
 
 void RecordingBuffers::reset(RecordingBuffers* other)
 {
-	mCountsFloat.reset(other ? &other->mCountsFloat : NULL);
 	mCounts.reset(other ? &other->mCounts : NULL);
-	mSamplesFloat.reset(other ? &other->mSamplesFloat : NULL);
 	mSamples.reset(other ? &other->mSamples : NULL);
-	mEventsFloat.reset(other ? &other->mEventsFloat : NULL);
 	mEvents.reset(other ? &other->mEvents : NULL);
 	mStackTimers.reset(other ? &other->mStackTimers : NULL);
 	mMemStats.reset(other ? &other->mMemStats : NULL);
@@ -122,7 +107,6 @@ void RecordingBuffers::reset(RecordingBuffers* other)
 
 void RecordingBuffers::flush()
 {
-	mSamplesFloat.flush();
 	mSamples.flush();
 }
 
@@ -280,200 +264,100 @@ LLUnit<LLUnits::Bytes, F32> Recording::getPerSec(const TraceType<MemStatAccumula
 }
 
 
-F64 Recording::getSum( const TraceType<CountAccumulator<F64> >& stat )
-{
-	update();
-	return mBuffers->mCountsFloat[stat.getIndex()].getSum();
-}
-
-S64 Recording::getSum( const TraceType<CountAccumulator<S64> >& stat )
+F64 Recording::getSum( const TraceType<CountAccumulator>& stat )
 {
 	update();
 	return mBuffers->mCounts[stat.getIndex()].getSum();
 }
 
-F64 Recording::getSum( const TraceType<EventAccumulator<F64> >& stat )
+F64 Recording::getSum( const TraceType<EventAccumulator>& stat )
 {
 	update();
-	return (F64)mBuffers->mEventsFloat[stat.getIndex()].getSum();
+	return (F64)mBuffers->mEvents[stat.getIndex()].getSum();
 }
 
-S64 Recording::getSum( const TraceType<EventAccumulator<S64> >& stat )
+F64 Recording::getPerSec( const TraceType<CountAccumulator>& stat )
 {
 	update();
-	return (S64)mBuffers->mEvents[stat.getIndex()].getSum();
-}
-
-
-
-F64 Recording::getPerSec( const TraceType<CountAccumulator<F64> >& stat )
-{
-	update();
-	F64 sum = mBuffers->mCountsFloat[stat.getIndex()].getSum();
+	F64 sum = mBuffers->mCounts[stat.getIndex()].getSum();
 	return  (sum != 0.0) 
 		? (sum / mElapsedSeconds)
 		: 0.0;
 }
 
-F64 Recording::getPerSec( const TraceType<CountAccumulator<S64> >& stat )
-{
-	S64 sum = mBuffers->mCounts[stat.getIndex()].getSum();
-	return (sum != 0) 
-		? ((F64)sum / mElapsedSeconds)
-		: 0.0;
-}
-
-U32 Recording::getSampleCount( const TraceType<CountAccumulator<F64> >& stat )
-{
-	update();
-	return mBuffers->mCountsFloat[stat.getIndex()].getSampleCount();
-}
-
-U32 Recording::getSampleCount( const TraceType<CountAccumulator<S64> >& stat )
+U32 Recording::getSampleCount( const TraceType<CountAccumulator>& stat )
 {
 	update();
 	return mBuffers->mCounts[stat.getIndex()].getSampleCount();
 }
 
-F64 Recording::getMin( const TraceType<SampleAccumulator<F64> >& stat )
-{
-	update();
-	return mBuffers->mSamplesFloat[stat.getIndex()].getMin();
-}
-
-S64 Recording::getMin( const TraceType<SampleAccumulator<S64> >& stat )
+F64 Recording::getMin( const TraceType<SampleAccumulator>& stat )
 {
 	update();
 	return mBuffers->mSamples[stat.getIndex()].getMin();
 }
 
-F64 Recording::getMax( const TraceType<SampleAccumulator<F64> >& stat )
-{
-	update();
-	return mBuffers->mSamplesFloat[stat.getIndex()].getMax();
-}
-
-S64 Recording::getMax( const TraceType<SampleAccumulator<S64> >& stat )
+F64 Recording::getMax( const TraceType<SampleAccumulator>& stat )
 {
 	update();
 	return mBuffers->mSamples[stat.getIndex()].getMax();
 }
 
-F64 Recording::getMean( const TraceType<SampleAccumulator<F64> >& stat )
-{
-	update();
-	return mBuffers->mSamplesFloat[stat.getIndex()].getMean();
-}
-
-F64 Recording::getMean( const TraceType<SampleAccumulator<S64> >& stat )
+F64 Recording::getMean( const TraceType<SampleAccumulator>& stat )
 {
 	update();
 	return mBuffers->mSamples[stat.getIndex()].getMean();
 }
 
-F64 Recording::getStandardDeviation( const TraceType<SampleAccumulator<F64> >& stat )
-{
-	update();
-	return mBuffers->mSamplesFloat[stat.getIndex()].getStandardDeviation();
-}
-
-F64 Recording::getStandardDeviation( const TraceType<SampleAccumulator<S64> >& stat )
+F64 Recording::getStandardDeviation( const TraceType<SampleAccumulator>& stat )
 {
 	update();
 	return mBuffers->mSamples[stat.getIndex()].getStandardDeviation();
 }
 
-F64 Recording::getLastValue( const TraceType<SampleAccumulator<F64> >& stat )
-{
-	update();
-	return mBuffers->mSamplesFloat[stat.getIndex()].getLastValue();
-}
-
-S64 Recording::getLastValue( const TraceType<SampleAccumulator<S64> >& stat )
+F64 Recording::getLastValue( const TraceType<SampleAccumulator>& stat )
 {
 	update();
 	return mBuffers->mSamples[stat.getIndex()].getLastValue();
 }
 
-U32 Recording::getSampleCount( const TraceType<SampleAccumulator<F64> >& stat )
-{
-	update();
-	return mBuffers->mSamplesFloat[stat.getIndex()].getSampleCount();
-}
-
-U32 Recording::getSampleCount( const TraceType<SampleAccumulator<S64> >& stat )
+U32 Recording::getSampleCount( const TraceType<SampleAccumulator>& stat )
 {
 	update();
 	return mBuffers->mSamples[stat.getIndex()].getSampleCount();
 }
 
-F64 Recording::getMin( const TraceType<EventAccumulator<F64> >& stat )
-{
-	update();
-	return mBuffers->mEventsFloat[stat.getIndex()].getMin();
-}
-
-S64 Recording::getMin( const TraceType<EventAccumulator<S64> >& stat )
+F64 Recording::getMin( const TraceType<EventAccumulator>& stat )
 {
 	update();
 	return mBuffers->mEvents[stat.getIndex()].getMin();
 }
 
-F64 Recording::getMax( const TraceType<EventAccumulator<F64> >& stat )
-{
-	update();
-	return mBuffers->mEventsFloat[stat.getIndex()].getMax();
-}
-
-S64 Recording::getMax( const TraceType<EventAccumulator<S64> >& stat )
+F64 Recording::getMax( const TraceType<EventAccumulator>& stat )
 {
 	update();
 	return mBuffers->mEvents[stat.getIndex()].getMax();
 }
 
-F64 Recording::getMean( const TraceType<EventAccumulator<F64> >& stat )
-{
-	update();
-	return mBuffers->mEventsFloat[stat.getIndex()].getMean();
-}
-
-F64 Recording::getMean( const TraceType<EventAccumulator<S64> >& stat )
+F64 Recording::getMean( const TraceType<EventAccumulator>& stat )
 {
 	update();
 	return mBuffers->mEvents[stat.getIndex()].getMean();
 }
 
-F64 Recording::getStandardDeviation( const TraceType<EventAccumulator<F64> >& stat )
-{
-	update();
-	return mBuffers->mEventsFloat[stat.getIndex()].getStandardDeviation();
-}
-
-F64 Recording::getStandardDeviation( const TraceType<EventAccumulator<S64> >& stat )
+F64 Recording::getStandardDeviation( const TraceType<EventAccumulator>& stat )
 {
 	update();
 	return mBuffers->mEvents[stat.getIndex()].getStandardDeviation();
 }
 
-F64 Recording::getLastValue( const TraceType<EventAccumulator<F64> >& stat )
-{
-	update();
-	return mBuffers->mEventsFloat[stat.getIndex()].getLastValue();
-}
-
-S64 Recording::getLastValue( const TraceType<EventAccumulator<S64> >& stat )
+F64 Recording::getLastValue( const TraceType<EventAccumulator>& stat )
 {
 	update();
 	return mBuffers->mEvents[stat.getIndex()].getLastValue();
 }
 
-U32 Recording::getSampleCount( const TraceType<EventAccumulator<F64> >& stat )
-{
-	update();
-	return mBuffers->mEventsFloat[stat.getIndex()].getSampleCount();
-}
-
-U32 Recording::getSampleCount( const TraceType<EventAccumulator<S64> >& stat )
+U32 Recording::getSampleCount( const TraceType<EventAccumulator>& stat )
 {
 	update();
 	return mBuffers->mEvents[stat.getIndex()].getSampleCount();
@@ -667,6 +551,122 @@ void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
 	getCurRecording().splitTo(other.getCurRecording());
 }
 
+
+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);
+
+	F64 mean = 0;
+	if (num_periods <= 0) { return mean; }
+
+	S32 total_sample_count = 0;
+
+	for (S32 i = 1; i <= num_periods; i++)
+	{
+		S32 index = (mCurPeriod + total_periods - i) % total_periods;
+		if (mRecordingPeriods[index].getDuration() > 0.f)
+		{
+			S32 period_sample_count = mRecordingPeriods[index].getSampleCount(stat);
+			mean += mRecordingPeriods[index].getMean(stat) * period_sample_count;
+			total_sample_count += period_sample_count;
+		}
+	}
+
+	if (total_sample_count)
+	{
+		mean = mean / total_sample_count;
+	}
+	return mean;
+}
+
+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);
+
+	F64 min_val = std::numeric_limits<F64>::max();
+	for (S32 i = 1; i <= num_periods; i++)
+	{
+		S32 index = (mCurPeriod + total_periods - i) % total_periods;
+		min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat));
+	}
+	return min_val;
+}
+
+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);
+
+	F64 max_val = std::numeric_limits<F64>::min();
+	for (S32 i = 1; i <= num_periods; i++)
+	{
+		S32 index = (mCurPeriod + total_periods - i) % total_periods;
+		max_val = llmax(max_val, mRecordingPeriods[index].getMax(stat));
+	}
+	return max_val;
+}
+
+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);
+
+	F64 min_val = std::numeric_limits<F64>::max();
+	for (S32 i = 1; i <= num_periods; i++)
+	{
+		S32 index = (mCurPeriod + total_periods - i) % total_periods;
+		min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat));
+	}
+	return min_val;
+}
+
+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);
+
+	F64 max_val = std::numeric_limits<F64>::min();
+	for (S32 i = 1; i <= num_periods; i++)
+	{
+		S32 index = (mCurPeriod + total_periods - i) % total_periods;
+		max_val = llmax(max_val, mRecordingPeriods[index].getMax(stat));
+	}
+	return max_val;
+}
+
+
+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);
+
+	LLUnit<LLUnits::Seconds, F64> total_duration = 0.f;
+
+	F64 mean = 0;
+	if (num_periods <= 0) { return mean; }
+
+	for (S32 i = 1; i <= num_periods; i++)
+	{
+		S32 index = (mCurPeriod + total_periods - i) % total_periods;
+		if (mRecordingPeriods[index].getDuration() > 0.f)
+		{
+			LLUnit<LLUnits::Seconds, F64> recording_duration = mRecordingPeriods[index].getDuration();
+			mean += mRecordingPeriods[index].getMean(stat) * recording_duration.value();
+			total_duration += recording_duration;
+		}
+	}
+
+	if (total_duration.value())
+	{
+		mean = mean / total_duration;
+	}
+	return mean;
+}
+
+
+
 ///////////////////////////////////////////////////////////////////////
 // ExtendableRecording
 ///////////////////////////////////////////////////////////////////////
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 58b40fa378..b4452d67a0 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -119,12 +119,9 @@ namespace LLTrace
 		void reset(RecordingBuffers* other = NULL);
 		void flush();
 
-		AccumulatorBuffer<CountAccumulator<F64> > 		mCountsFloat;
-		AccumulatorBuffer<CountAccumulator<S64> > 		mCounts;
-		AccumulatorBuffer<SampleAccumulator<F64> >		mSamplesFloat;
-		AccumulatorBuffer<SampleAccumulator<S64> >		mSamples;
-		AccumulatorBuffer<EventAccumulator<F64> >		mEventsFloat;
-		AccumulatorBuffer<EventAccumulator<S64> >		mEvents;
+		AccumulatorBuffer<CountAccumulator>	 			mCounts;
+		AccumulatorBuffer<SampleAccumulator>			mSamples;
+		AccumulatorBuffer<EventAccumulator>				mEvents;
 		AccumulatorBuffer<TimeBlockAccumulator> 		mStackTimers;
 		AccumulatorBuffer<MemStatAccumulator> 			mMemStats;
 	};
@@ -164,121 +161,105 @@ namespace LLTrace
 		LLUnit<LLUnits::Bytes, F32> getPerSec(const TraceType<MemStatAccumulator>& stat);
 
 		// CountStatHandle accessors
-		F64 getSum(const TraceType<CountAccumulator<F64> >& stat);
-		S64 getSum(const TraceType<CountAccumulator<S64> >& stat);
+		F64 getSum(const TraceType<CountAccumulator>& stat);
 		template <typename T>
 		T getSum(const CountStatHandle<T>& stat)
 		{
-			return (T)getSum(static_cast<const TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getSum(static_cast<const TraceType<CountAccumulator>&> (stat));
 		}
 
-		F64 getPerSec(const TraceType<CountAccumulator<F64> >& stat);
-		F64 getPerSec(const TraceType<CountAccumulator<S64> >& stat);
+		F64 getPerSec(const TraceType<CountAccumulator>& stat);
 		template <typename T>
 		T getPerSec(const CountStatHandle<T>& stat)
 		{
-			return (T)getPerSec(static_cast<const TraceType<CountAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getPerSec(static_cast<const TraceType<CountAccumulator>&> (stat));
 		}
 
-		U32 getSampleCount(const TraceType<CountAccumulator<F64> >& stat);
-		U32 getSampleCount(const TraceType<CountAccumulator<S64> >& stat);
+		U32 getSampleCount(const TraceType<CountAccumulator>& stat);
 
 
 		// SampleStatHandle accessors
-		F64 getMin(const TraceType<SampleAccumulator<F64> >& stat);
-		S64 getMin(const TraceType<SampleAccumulator<S64> >& stat);
+		F64 getMin(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
 		T getMin(const SampleStatHandle<T>& stat)
 		{
-			return (T)getMin(static_cast<const TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getMin(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
-		F64 getMax(const TraceType<SampleAccumulator<F64> >& stat);
-		S64 getMax(const TraceType<SampleAccumulator<S64> >& stat);
+		F64 getMax(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
 		T getMax(const SampleStatHandle<T>& stat)
 		{
-			return (T)getMax(static_cast<const TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getMax(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
-		F64 getMean(const TraceType<SampleAccumulator<F64> >& stat);
-		F64 getMean(const TraceType<SampleAccumulator<S64> >& stat);
+		F64 getMean(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
 		T getMean(SampleStatHandle<T>& stat)
 		{
-			return (T)getMean(static_cast<const TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getMean(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
-		F64 getStandardDeviation(const TraceType<SampleAccumulator<F64> >& stat);
-		F64 getStandardDeviation(const TraceType<SampleAccumulator<S64> >& stat);
+		F64 getStandardDeviation(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
 		T getStandardDeviation(const SampleStatHandle<T>& stat)
 		{
-			return (T)getStandardDeviation(static_cast<const TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getStandardDeviation(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
-		F64 getLastValue(const TraceType<SampleAccumulator<F64> >& stat);
-		S64 getLastValue(const TraceType<SampleAccumulator<S64> >& stat);
+		F64 getLastValue(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
 		T getLastValue(const SampleStatHandle<T>& stat)
 		{
-			return (T)getLastValue(static_cast<const TraceType<SampleAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getLastValue(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
-		U32 getSampleCount(const TraceType<SampleAccumulator<F64> >& stat);
-		U32 getSampleCount(const TraceType<SampleAccumulator<S64> >& stat);
+		U32 getSampleCount(const TraceType<SampleAccumulator>& stat);
 
 		// EventStatHandle accessors
-		F64 getSum(const TraceType<EventAccumulator<F64> >& stat);
-		S64 getSum(const TraceType<EventAccumulator<S64> >& stat);
+		F64 getSum(const TraceType<EventAccumulator>& stat);
 		template <typename T>
 		T getSum(const EventStatHandle<T>& stat)
 		{
-			return (T)getSum(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getSum(static_cast<const TraceType<EventAccumulator>&> (stat));
 		}
 
-		F64 getMin(const TraceType<EventAccumulator<F64> >& stat);
-		S64 getMin(const TraceType<EventAccumulator<S64> >& stat);
+		F64 getMin(const TraceType<EventAccumulator>& stat);
 		template <typename T>
 		T getMin(const EventStatHandle<T>& stat)
 		{
-			return (T)getMin(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getMin(static_cast<const TraceType<EventAccumulator>&> (stat));
 		}
 
-		F64 getMax(const TraceType<EventAccumulator<F64> >& stat);
-		S64 getMax(const TraceType<EventAccumulator<S64> >& stat);
+		F64 getMax(const TraceType<EventAccumulator>& stat);
 		template <typename T>
 		T getMax(const EventStatHandle<T>& stat)
 		{
-			return (T)getMax(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getMax(static_cast<const TraceType<EventAccumulator>&> (stat));
 		}
 
-		F64 getMean(const TraceType<EventAccumulator<F64> >& stat);
-		F64 getMean(const TraceType<EventAccumulator<S64> >& stat);
+		F64 getMean(const TraceType<EventAccumulator>& stat);
 		template <typename T>
 		T getMean(EventStatHandle<T>& stat)
 		{
-			return (T)getMean(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getMean(static_cast<const TraceType<EventAccumulator>&> (stat));
 		}
 
-		F64 getStandardDeviation(const TraceType<EventAccumulator<F64> >& stat);
-		F64 getStandardDeviation(const TraceType<EventAccumulator<S64> >& stat);
+		F64 getStandardDeviation(const TraceType<EventAccumulator>& stat);
 		template <typename T>
 		T getStandardDeviation(const EventStatHandle<T>& stat)
 		{
-			return (T)getStandardDeviation(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getStandardDeviation(static_cast<const TraceType<EventAccumulator>&> (stat));
 		}
 
-		F64 getLastValue(const TraceType<EventAccumulator<F64> >& stat);
-		S64 getLastValue(const TraceType<EventAccumulator<S64> >& stat);
+		F64 getLastValue(const TraceType<EventAccumulator>& stat);
 		template <typename T>
 		T getLastValue(const EventStatHandle<T>& stat)
 		{
-			return (T)getLastValue(static_cast<const TraceType<EventAccumulator<typename LLUnits::HighestPrecisionType<T>::type_t> >&> (stat));
+			return (T)getLastValue(static_cast<const TraceType<EventAccumulator>&> (stat));
 		}
 
-		U32 getSampleCount(const TraceType<EventAccumulator<F64> >& stat);
-		U32 getSampleCount(const TraceType<EventAccumulator<S64> >& stat);
+		U32 getSampleCount(const TraceType<EventAccumulator>& stat);
 
 		LLUnit<LLUnits::Seconds, F64> getDuration() const { return LLUnit<LLUnits::Seconds, F64>(mElapsedSeconds); }
 
@@ -335,34 +316,18 @@ namespace LLTrace
 			return min_val;
 		}
 
-		template <typename T>
-		T getPeriodMin(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX)
+		F64 getPeriodMin(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX);
+		template<typename T>
+		T getPeriodMin(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX)
 		{
-			size_t total_periods = mRecordingPeriods.size();
-			num_periods = llmin(num_periods, total_periods);
-
-			T min_val = std::numeric_limits<T>::max();
-			for (S32 i = 1; i <= num_periods; i++)
-			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat));
-			}
-			return min_val;
+			return T(getPeriodMin(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods));
 		}
-		
-		template <typename T>
-		T getPeriodMin(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX)
-		{
-			size_t total_periods = mRecordingPeriods.size();
-			num_periods = llmin(num_periods, total_periods);
 
-			T min_val = std::numeric_limits<T>::max();
-			for (S32 i = 1; i <= num_periods; i++)
-			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat));
-			}
-			return min_val;
+		F64 getPeriodMin(const TraceType<EventAccumulator>& stat, size_t num_periods = U32_MAX);
+		template<typename T>
+		T getPeriodMin(const EventStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		{
+			return T(getPeriodMin(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
 		template <typename T>
@@ -396,34 +361,18 @@ namespace LLTrace
 			return max_val;
 		}
 
-		template <typename T>
-		T getPeriodMax(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX)
+		F64 getPeriodMax(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX);
+		template<typename T>
+		T getPeriodMax(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX)
 		{
-			size_t total_periods = mRecordingPeriods.size();
-			num_periods = llmin(num_periods, total_periods);
-
-			typename T max_val = std::numeric_limits<T>::min();
-			for (S32 i = 1; i <= num_periods; i++)
-			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				max_val = llmax(max_val, mRecordingPeriods[index].getMax(stat));
-			}
-			return max_val;
+			return T(getPeriodMax(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods));
 		}
 
-		template <typename T>
-		T getPeriodMax(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX)
+		F64 getPeriodMax(const TraceType<EventAccumulator>& stat, size_t num_periods = U32_MAX);
+		template<typename T>
+		T getPeriodMax(const EventStatHandle<T>& stat, size_t num_periods = U32_MAX)
 		{
-			size_t total_periods = mRecordingPeriods.size();
-			num_periods = llmin(num_periods, total_periods);
-
-			typename T max_val = std::numeric_limits<T>::min();
-			for (S32 i = 1; i <= num_periods; i++)
-			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				max_val = llmax(max_val, mRecordingPeriods[index].getMax(stat));
-			}
-			return max_val;
+			return T(getPeriodMax(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
 		template <typename T>
@@ -463,62 +412,18 @@ namespace LLTrace
 			return mean;
 		}
 
-		template <typename T>
-		typename SampleAccumulator<T>::mean_t getPeriodMean(const TraceType<SampleAccumulator<T> >& stat, size_t num_periods = U32_MAX)
+		F64 getPeriodMean(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX);
+		template<typename T> 
+		T getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX)
 		{
-			size_t total_periods = mRecordingPeriods.size();
-			num_periods = llmin(num_periods, total_periods);
-
-			LLUnit<LLUnits::Seconds, F64> total_duration = 0.f;
-
-			typename SampleAccumulator<T>::mean_t mean = 0;
-			if (num_periods <= 0) { return mean; }
-
-			for (S32 i = 1; i <= num_periods; i++)
-			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				if (mRecordingPeriods[index].getDuration() > 0.f)
-				{
-					LLUnit<LLUnits::Seconds, F64> recording_duration = mRecordingPeriods[index].getDuration();
-					mean += mRecordingPeriods[index].getMean(stat) * recording_duration.value();
-					total_duration += recording_duration;
-				}
-			}
-
-			if (total_duration.value())
-			{
-				mean = mean / total_duration;
-			}
-			return mean;
+			return T(getPeriodMean(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods));
 		}
 
-		template <typename T>
-		typename EventAccumulator<T>::mean_t getPeriodMean(const TraceType<EventAccumulator<T> >& stat, size_t num_periods = U32_MAX)
+		F64 getPeriodMean(const TraceType<EventAccumulator>& stat, size_t num_periods = U32_MAX);
+		template<typename T>
+		T getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = U32_MAX)
 		{
-			size_t total_periods = mRecordingPeriods.size();
-			num_periods = llmin(num_periods, total_periods);
-
-			typename EventAccumulator<T>::mean_t mean = 0;
-			if (num_periods <= 0) { return mean; }
-
-			S32 total_sample_count = 0;
-
-			for (S32 i = 1; i <= num_periods; i++)
-			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				if (mRecordingPeriods[index].getDuration() > 0.f)
-				{
-					S32 period_sample_count = mRecordingPeriods[index].getSampleCount(stat);
-					mean += mRecordingPeriods[index].getMean(stat) * period_sample_count;
-					total_sample_count += period_sample_count;
-				}
-			}
-
-			if (total_sample_count)
-			{
-				mean = mean / total_sample_count;
-			}
-			return mean;
+			return T(getPeriodMean(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
 		template <typename T>
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index c281b768ce..c1a0700eff 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -147,13 +147,6 @@ ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringU
 	return it;
 }
 
-AccumulatorBuffer<CountAccumulator<F64> > 	gCountsFloat;
-AccumulatorBuffer<EventAccumulator<F64> >	gMeasurementsFloat;
-AccumulatorBuffer<CountAccumulator<S64> >	gCounts;
-AccumulatorBuffer<EventAccumulator<S64> >	gMeasurements;
-AccumulatorBuffer<TimeBlockAccumulator>		gStackTimers;
-AccumulatorBuffer<MemStatAccumulator>		gMemStats;
-
 void ThreadRecorder::deactivate( Recording* recording )
 {
 	active_recording_list_t::reverse_iterator it = bringUpToDate(recording);
-- 
cgit v1.2.3


From 5b48107dbf969529267874bff9a0a4b892b348cf Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 4 Jun 2013 08:33:11 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 added labels to LLUnit types added memstat dumps to llscenemonitor

---
 indra/llcommon/lltrace.h |  4 +--
 indra/llcommon/llunit.h  | 65 +++++++++++++++++++++++++++---------------------
 2 files changed, 38 insertions(+), 31 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index d6b51a63ee..c485552061 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -656,7 +656,7 @@ class EventStatHandle
 :	public TraceType<EventAccumulator>
 {
 public:
-	typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
+	typedef typename F64 storage_t;
 	typedef TraceType<EventAccumulator> trace_t;
 
 	EventStatHandle(const char* name, const char* description = NULL)
@@ -696,7 +696,7 @@ class CountStatHandle
 :	public TraceType<CountAccumulator>
 {
 public:
-	typedef typename LLUnits::HighestPrecisionType<T>::type_t storage_t;
+	typedef typename F64 storage_t;
 	typedef TraceType<CountAccumulator> trace_t;
 
 	CountStatHandle(const char* name, const char* description = NULL) 
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index e2803c74b0..c617d2a87f 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -423,11 +423,13 @@ struct HighestPrecisionType<LLUnit<UNIT_TYPE, STORAGE_TYPE> >
 	typedef typename HighestPrecisionType<STORAGE_TYPE>::type_t type_t;
 };
 
-#define LL_DECLARE_DERIVED_UNIT(conversion_factor, base_unit_name, unit_name)                   \
+#define LL_DECLARE_DERIVED_UNIT(conversion_factor, base_unit_name, unit_name, unit_label)		\
 struct unit_name                                                                                \
 {                                                                                               \
 	typedef base_unit_name base_unit_t;                                                         \
+	static const char* sUnitLabel;																\
 };                                                                                              \
+const char* unit_name::sUnitLabel = unit_label;													\
 template<typename STORAGE_TYPE>                                                                 \
 struct ConversionFactor<unit_name, base_unit_name, STORAGE_TYPE>                                \
 {                                                                                               \
@@ -446,34 +448,39 @@ struct ConversionFactor<base_unit_name, unit_name, STORAGE_TYPE>						        \
 	}                                                                                           \
 }
 
-struct Bytes { typedef Bytes base_unit_t; };
-LL_DECLARE_DERIVED_UNIT(1024, Bytes, Kilobytes);
-LL_DECLARE_DERIVED_UNIT(1024 * 1024, Bytes, Megabytes);
-LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024, Bytes, Gigabytes);
-LL_DECLARE_DERIVED_UNIT(1.0 / 8.0, Bytes, Bits);
-LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Kilobits);
-LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Megabits);
-LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024 / 8, Bytes, Gigabits);
-
-struct Seconds { typedef Seconds base_unit_t; };
-LL_DECLARE_DERIVED_UNIT(60, Seconds, Minutes);
-LL_DECLARE_DERIVED_UNIT(60 * 60, Seconds, Hours);
-LL_DECLARE_DERIVED_UNIT(1.0 / 1000.0, Seconds, Milliseconds);
-LL_DECLARE_DERIVED_UNIT(1.0 / 1000000.0, Seconds, Microseconds);
-LL_DECLARE_DERIVED_UNIT(1.0 / 1000000000.0, Seconds, Nanoseconds);
-
-struct Meters { typedef Meters base_unit_t; };
-LL_DECLARE_DERIVED_UNIT(1000, Meters, Kilometers);
-LL_DECLARE_DERIVED_UNIT(1.0 / 100.0, Meters, Centimeters);
-LL_DECLARE_DERIVED_UNIT(1.0 / 1000.0, Meters, Millimeters);
-
-struct Hertz { typedef Hertz base_unit_t; };
-LL_DECLARE_DERIVED_UNIT(1000, Hertz, Kilohertz);
-LL_DECLARE_DERIVED_UNIT(1000 * 1000, Hertz, Megahertz);
-LL_DECLARE_DERIVED_UNIT(1000 * 1000 * 1000, Hertz, Gigahertz);
-
-struct Radians { typedef Radians base_unit_t; };
-LL_DECLARE_DERIVED_UNIT(DEG_TO_RAD, Radians, Degrees);
+struct Bytes { typedef Bytes base_unit_t; static const char* sUnitLabel;};
+const char* Bytes::sUnitLabel = "B";
+LL_DECLARE_DERIVED_UNIT(1024, Bytes, Kilobytes, "KiB");
+LL_DECLARE_DERIVED_UNIT(1024 * 1024, Bytes, Megabytes, "MiB");
+LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024, Bytes, Gigabytes, "GiB");
+LL_DECLARE_DERIVED_UNIT(1.0 / 8.0, Bytes, Bits, "b");
+LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Kilobits, "Kib");
+LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Megabits, "Mib");
+LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024 / 8, Bytes, Gigabits, "Gib");
+
+struct Seconds { typedef Seconds base_unit_t; static const char* sUnitLabel; };
+const char* Seconds::sUnitLabel = "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");
+
+struct Meters { typedef Meters base_unit_t; static const char* sUnitLabel; };
+const char* Meters::sUnitLabel = "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");
+
+struct Hertz { typedef Hertz base_unit_t; static const char* sUnitLabel; };
+const char* Hertz::sUnitLabel = "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");
+
+struct Radians { typedef Radians base_unit_t; static const char* sUnitLabel;};
+const char* Radians::sUnitLabel = "rad";
+LL_DECLARE_DERIVED_UNIT(DEG_TO_RAD, Radians, Degrees, "deg");
 } // namespace LLUnits
 
 #endif // LL_LLUNIT_H
-- 
cgit v1.2.3


From 715385eed7b2276963015861d7e6b8196e6ae5cd Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 4 Jun 2013 10:54:12 -0700
Subject: BUILDFIX: don't multiple define class statics...use inline static
 method instead

---
 indra/llcommon/lltrace.h | 10 ++++++++++
 indra/llcommon/llunit.h  | 34 ++++++++++++++++++++++------------
 2 files changed, 32 insertions(+), 12 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index c485552061..2953e993d4 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -265,6 +265,8 @@ public:
 
 	size_t getIndex() const { return mAccumulatorIndex; }
 
+	virtual const char* getUnitLabel() { return ""; }
+
 	const std::string& getName() const { return mName; }
 
 protected:
@@ -662,6 +664,9 @@ public:
 	EventStatHandle(const char* name, const char* description = NULL)
 	:	trace_t(name, description)
 	{}
+
+	/*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); }
+
 };
 
 template<typename T, typename VALUE_T>
@@ -682,6 +687,8 @@ public:
 	SampleStatHandle(const char* name, const char* description = NULL)
 	:	trace_t(name, description)
 	{}
+
+	/*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); }
 };
 
 template<typename T, typename VALUE_T>
@@ -703,6 +710,7 @@ public:
 	:	trace_t(name)
 	{}
 
+	/*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); }
 };
 
 template<typename T, typename VALUE_T>
@@ -755,6 +763,8 @@ public:
 	MemStatHandle(const char* name)
 	:	trace_t(name)
 	{}
+
+	/*virtual*/ const char* getUnitLabel() { return "B"; }
 };
 
 // measures effective memory footprint of specified type
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index c617d2a87f..77c19b5152 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -406,6 +406,22 @@ COMPARISON_OPERATORS(>=)
 COMPARISON_OPERATORS(==)
 COMPARISON_OPERATORS(!=)
 
+
+template<typename T> 
+struct LLGetUnitLabel
+{
+	static const char* getUnitLabel() { return ""; }
+};
+
+template<typename T, typename STORAGE_T>
+struct LLGetUnitLabel<LLUnit<T, STORAGE_T> >
+{
+	static const char* getUnitLabel() { return T::getUnitLabel(); }
+};
+
+//
+// Unit declarations
+//
 namespace LLUnits
 {
 template<typename T>
@@ -427,9 +443,8 @@ struct HighestPrecisionType<LLUnit<UNIT_TYPE, STORAGE_TYPE> >
 struct unit_name                                                                                \
 {                                                                                               \
 	typedef base_unit_name base_unit_t;                                                         \
-	static const char* sUnitLabel;																\
+	static const char* getUnitLabel() { return unit_label; }									\
 };                                                                                              \
-const char* unit_name::sUnitLabel = unit_label;													\
 template<typename STORAGE_TYPE>                                                                 \
 struct ConversionFactor<unit_name, base_unit_name, STORAGE_TYPE>                                \
 {                                                                                               \
@@ -448,8 +463,7 @@ struct ConversionFactor<base_unit_name, unit_name, STORAGE_TYPE>						        \
 	}                                                                                           \
 }
 
-struct Bytes { typedef Bytes base_unit_t; static const char* sUnitLabel;};
-const char* Bytes::sUnitLabel = "B";
+struct Bytes { typedef Bytes base_unit_t; static const char* getUnitLabel() { return "B"; }};
 LL_DECLARE_DERIVED_UNIT(1024, Bytes, Kilobytes, "KiB");
 LL_DECLARE_DERIVED_UNIT(1024 * 1024, Bytes, Megabytes, "MiB");
 LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024, Bytes, Gigabytes, "GiB");
@@ -458,28 +472,24 @@ LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Kilobits, "Kib");
 LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Megabits, "Mib");
 LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024 / 8, Bytes, Gigabits, "Gib");
 
-struct Seconds { typedef Seconds base_unit_t; static const char* sUnitLabel; };
-const char* Seconds::sUnitLabel = "s";
+struct Seconds { typedef Seconds base_unit_t; static const char* getUnitLabel() { return "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");
 
-struct Meters { typedef Meters base_unit_t; static const char* sUnitLabel; };
-const char* Meters::sUnitLabel = "m";
+struct Meters { typedef Meters base_unit_t; static const char* getUnitLabel() { return "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");
 
-struct Hertz { typedef Hertz base_unit_t; static const char* sUnitLabel; };
-const char* Hertz::sUnitLabel = "Hz";
+struct Hertz { typedef Hertz base_unit_t; static const char* getUnitLabel() { return "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");
 
-struct Radians { typedef Radians base_unit_t; static const char* sUnitLabel;};
-const char* Radians::sUnitLabel = "rad";
+struct Radians { typedef Radians base_unit_t; static const char* getUnitLabel() { return "rad"; } };
 LL_DECLARE_DERIVED_UNIT(DEG_TO_RAD, Radians, Degrees, "deg");
 } // namespace LLUnits
 
-- 
cgit v1.2.3


From a74b5dfa923f8eeccc9b786143f0f832de3ad450 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 4 Jun 2013 19:45:33 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 fixed mem stat tracking...now properly tracks memory footprint with floating
 point precision cleaned up macros for unit declaration renamed units to SI
 standard for 1024 multiples (kibibytes, etc) fixed units output for scene
 monitor dump

---
 indra/llcommon/llfasttimer.h        |  12 +--
 indra/llcommon/lltrace.h            | 143 ++++++++++++++++++++++++++----------
 indra/llcommon/lltracerecording.cpp |  74 +++++++++++++++++--
 indra/llcommon/lltracerecording.h   |  36 ++++++---
 indra/llcommon/llunit.h             |  59 ++++++---------
 5 files changed, 225 insertions(+), 99 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 32a0629a87..f329b30472 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -101,14 +101,14 @@ public:
 	void setCollapsed(bool collapsed)	{ mCollapsed = collapsed; }
 	bool getCollapsed() const			{ return mCollapsed; }
 
-	TraceType<TimeBlockAccumulator::CallCountAspect>& callCount() 
+	TraceType<TimeBlockAccumulator::CallCountFacet>& callCount() 
 	{ 
-		return static_cast<TraceType<TimeBlockAccumulator::CallCountAspect>&>(*(TraceType<TimeBlockAccumulator>*)this);
+		return static_cast<TraceType<TimeBlockAccumulator::CallCountFacet>&>(*(TraceType<TimeBlockAccumulator>*)this);
 	}
 
-	TraceType<TimeBlockAccumulator::SelfTimeAspect>& selfTime() 
+	TraceType<TimeBlockAccumulator::SelfTimeFacet>& selfTime() 
 	{ 
-		return static_cast<TraceType<TimeBlockAccumulator::SelfTimeAspect>&>(*(TraceType<TimeBlockAccumulator>*)this);
+		return static_cast<TraceType<TimeBlockAccumulator::SelfTimeFacet>&>(*(TraceType<TimeBlockAccumulator>*)this);
 	}
 
 	static TimeBlock& getRootTimeBlock();
@@ -277,8 +277,6 @@ public:
 LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 {
 #if FAST_TIMER_ON
-	mStartTime = TimeBlock::getCPUClockCount64();
-
 	BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
 	TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 	accumulator->mActiveCount++;
@@ -292,6 +290,8 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 	cur_timer_data->mActiveTimer = this;
 	cur_timer_data->mTimeBlock = &timer;
 	cur_timer_data->mChildTime = 0;
+
+	mStartTime = TimeBlock::getCPUClockCount64();
 #endif
 }
 
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 2953e993d4..37196d9f63 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -46,13 +46,13 @@ namespace LLTrace
 class Recording;
 
 typedef LLUnit<LLUnits::Bytes, F64>			Bytes;
-typedef LLUnit<LLUnits::Kilobytes, F64>		Kilobytes;
-typedef LLUnit<LLUnits::Megabytes, F64>		Megabytes;
-typedef LLUnit<LLUnits::Gigabytes, F64>		Gigabytes;
+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::Kilobits, F64>		Kilobits;
-typedef LLUnit<LLUnits::Megabits, F64>		Megabits;
-typedef LLUnit<LLUnits::Gigabits, F64>		Gigabits;
+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;
@@ -583,14 +583,14 @@ public:
 	typedef LLUnit<LLUnits::Seconds, F64> mean_t;
 	typedef TimeBlockAccumulator self_t;
 
-	// fake class that allows us to view call count aspect of timeblock accumulator
-	struct CallCountAspect 
+	// fake classes that allows us to view different facets of underlying statistic
+	struct CallCountFacet 
 	{
 		typedef U32 value_t;
 		typedef F32 mean_t;
 	};
 
-	struct SelfTimeAspect
+	struct SelfTimeFacet
 	{
 		typedef LLUnit<LLUnits::Seconds, F64> value_t;
 		typedef LLUnit<LLUnits::Seconds, F64> mean_t;
@@ -616,7 +616,7 @@ public:
 };
 
 template<>
-class TraceType<TimeBlockAccumulator::CallCountAspect>
+class TraceType<TimeBlockAccumulator::CallCountFacet>
 :	public TraceType<TimeBlockAccumulator>
 {
 public:
@@ -627,7 +627,7 @@ public:
 };
 
 template<>
-class TraceType<TimeBlockAccumulator::SelfTimeAspect>
+class TraceType<TimeBlockAccumulator::SelfTimeFacet>
 	:	public TraceType<TimeBlockAccumulator>
 {
 public:
@@ -725,35 +725,90 @@ struct MemStatAccumulator
 {
 	typedef MemStatAccumulator self_t;
 
+	// fake classes that allows us to view different facets of underlying statistic
+	struct AllocationCountFacet 
+	{
+		typedef U32 value_t;
+		typedef F32 mean_t;
+	};
+
+	struct DeallocationCountFacet 
+	{
+		typedef U32 value_t;
+		typedef F32 mean_t;
+	};
+
+	struct ChildMemFacet
+	{
+		typedef LLUnit<LLUnits::Bytes, F64> value_t;
+		typedef LLUnit<LLUnits::Bytes, F64> mean_t;
+	};
+
 	MemStatAccumulator()
-	:	mSize(0),
-		mChildSize(0),
-		mAllocatedCount(0),
+	:	mAllocatedCount(0),
 		mDeallocatedCount(0)
 	{}
 
-	void addSamples(const MemStatAccumulator& other, bool /*append*/)
+	void addSamples(const MemStatAccumulator& other, bool append)
 	{
-		mSize += other.mSize;
-		mChildSize += other.mChildSize;
+		mSize.addSamples(other.mSize, append);
+		mChildSize.addSamples(other.mChildSize, append);
 		mAllocatedCount += other.mAllocatedCount;
 		mDeallocatedCount += other.mDeallocatedCount;
 	}
 
 	void reset(const MemStatAccumulator* other)
 	{
-		mSize = 0;
-		mChildSize = 0;
+		mSize.reset(other ? &other->mSize : NULL);
+		mChildSize.reset(other ? &other->mChildSize : NULL);
 		mAllocatedCount = 0;
 		mDeallocatedCount = 0;
 	}
 
-	void flush() {}
+	void flush() 
+	{
+		mSize.flush();
+		mChildSize.flush();
+	}
+
+	SampleAccumulator	mSize,
+						mChildSize;
+	int					mAllocatedCount,
+						mDeallocatedCount;
+};
+
+
+template<>
+class TraceType<MemStatAccumulator::AllocationCountFacet>
+:	public TraceType<MemStatAccumulator>
+{
+public:
+
+	TraceType(const char* name, const char* description = "")
+	:	TraceType<MemStatAccumulator>(name, description)
+	{}
+};
 
-	size_t		mSize,
-				mChildSize;
-	int			mAllocatedCount,
-				mDeallocatedCount;
+template<>
+class TraceType<MemStatAccumulator::DeallocationCountFacet>
+:	public TraceType<MemStatAccumulator>
+{
+public:
+
+	TraceType(const char* name, const char* description = "")
+	:	TraceType<MemStatAccumulator>(name, description)
+	{}
+};
+
+template<>
+class TraceType<MemStatAccumulator::ChildMemFacet>
+	:	public TraceType<MemStatAccumulator>
+{
+public:
+
+	TraceType(const char* name, const char* description = "")
+		:	TraceType<MemStatAccumulator>(name, description)
+	{}
 };
 
 class MemStatHandle : public TraceType<MemStatAccumulator>
@@ -765,6 +820,21 @@ public:
 	{}
 
 	/*virtual*/ const char* getUnitLabel() { return "B"; }
+
+	TraceType<MemStatAccumulator::AllocationCountFacet>& allocationCount() 
+	{ 
+		return static_cast<TraceType<MemStatAccumulator::AllocationCountFacet>&>(*(TraceType<MemStatAccumulator>*)this);
+	}
+
+	TraceType<MemStatAccumulator::DeallocationCountFacet>& deallocationCount() 
+	{ 
+		return static_cast<TraceType<MemStatAccumulator::DeallocationCountFacet>&>(*(TraceType<MemStatAccumulator>*)this);
+	}
+
+	TraceType<MemStatAccumulator::ChildMemFacet>& childMem() 
+	{ 
+		return static_cast<TraceType<MemStatAccumulator::ChildMemFacet>&>(*(TraceType<MemStatAccumulator>*)this);
+	}
 };
 
 // measures effective memory footprint of specified type
@@ -865,7 +935,7 @@ public:
 		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
-			accumulator->mSize += size;
+			accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
 			accumulator->mAllocatedCount++;
 		}
 
@@ -877,7 +947,7 @@ public:
 		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
-			accumulator->mSize -= size;
+			accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
 			accumulator->mAllocatedCount--;
 			accumulator->mDeallocatedCount++;
 		}
@@ -889,7 +959,7 @@ public:
 		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
-			accumulator->mSize += size;
+			accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
 			accumulator->mAllocatedCount++;
 		}
 
@@ -901,7 +971,7 @@ public:
 		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
-			accumulator->mSize -= size;
+			accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
 			accumulator->mAllocatedCount--;
 			accumulator->mDeallocatedCount++;
 		}
@@ -924,13 +994,13 @@ public:
 	}
 
 
-	void memClaim(size_t size)
+	void memClaimAmount(size_t size)
 	{
 		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		mMemFootprint += size;
 		if (accumulator)
 		{
-			accumulator->mSize += size;
+			accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
 		}
 	}
 
@@ -949,14 +1019,13 @@ public:
 		return value;
 	}
 
-	void memDisclaim(size_t size)
+	void memDisclaimAmount(size_t size)
 	{
 		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
-			accumulator->mSize -= size;
+			accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
 		}
-		mMemFootprint -= size;
 	}
 
 private:
@@ -971,7 +1040,7 @@ private:
 			if (accumulator)
 			{
 				size_t footprint = MemFootprint<TRACKED>::measure(tracked);
-				accumulator->mSize += footprint;
+				accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)footprint);
 				tracker.mMemFootprint += footprint;
 			}
 		}
@@ -982,7 +1051,7 @@ private:
 			if (accumulator)
 			{
 				size_t footprint = MemFootprint<TRACKED>::measure(tracked);
-				accumulator->mSize -= footprint;
+				accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)footprint);
 				tracker.mMemFootprint -= footprint;
 			}
 		}
@@ -996,7 +1065,7 @@ private:
 			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
-				accumulator->mChildSize += MemFootprint<TRACKED>::measure(tracked);
+				accumulator->mChildSize.sample(accumulator->mChildSize.getLastValue() + (F64)MemFootprint<TRACKED>::measure(tracked));
 			}
 		}
 
@@ -1005,7 +1074,7 @@ private:
 			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
-				accumulator->mChildSize -= MemFootprint<TRACKED>::measure(tracked);
+				accumulator->mChildSize.sample(accumulator->mChildSize.getLastValue() - (F64)MemFootprint<TRACKED>::measure(tracked));
 			}
 		}
 	};
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 61ba21a365..d32504b014 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -213,7 +213,7 @@ LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumul
 				/ (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
-LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat)
+LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 	update();
@@ -221,7 +221,7 @@ LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumul
 }
 
 
-U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat)
+U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat)
 {
 	update();
 	return mBuffers->mStackTimers[stat.getIndex()].mCalls;
@@ -236,7 +236,7 @@ LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccu
 				/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
 }
 
-LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat)
+LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
@@ -245,22 +245,82 @@ LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccu
 			/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds);
 }
 
-F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat)
+F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat)
 {
 	update();
 	return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds;
 }
 
-LLUnit<LLUnits::Bytes, U32> Recording::getSum(const TraceType<MemStatAccumulator>& stat)
+LLUnit<LLUnits::Bytes, F64> Recording::getMin(const TraceType<MemStatAccumulator>& stat)
+{
+	update();
+	return mBuffers->mMemStats[stat.getIndex()].mSize.getMin();
+}
+
+LLUnit<LLUnits::Bytes, F64> Recording::getMean(const TraceType<MemStatAccumulator>& stat)
+{
+	update();
+	return mBuffers->mMemStats[stat.getIndex()].mSize.getMean();
+}
+
+LLUnit<LLUnits::Bytes, F64> Recording::getMax(const TraceType<MemStatAccumulator>& stat)
+{
+	update();
+	return mBuffers->mMemStats[stat.getIndex()].mSize.getMax();
+}
+
+LLUnit<LLUnits::Bytes, F64> Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat)
+{
+	update();
+	return mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation();
+}
+
+LLUnit<LLUnits::Bytes, F64> 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)
+{
+	update();
+	return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMin();
+}
+
+LLUnit<LLUnits::Bytes, F64> 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)
+{
+	update();
+	return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMax();
+}
+
+LLUnit<LLUnits::Bytes, F64> 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)
+{
+	update();
+	return mBuffers->mMemStats[stat.getIndex()].mChildSize.getLastValue();
+}
+
+U32 Recording::getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat)
 {
 	update();
 	return mBuffers->mMemStats[stat.getIndex()].mAllocatedCount;
 }
 
-LLUnit<LLUnits::Bytes, F32> Recording::getPerSec(const TraceType<MemStatAccumulator>& stat)
+U32 Recording::getSum(const TraceType<MemStatAccumulator::DeallocationCountFacet>& stat)
 {
 	update();
-	return (F32)mBuffers->mMemStats[stat.getIndex()].mAllocatedCount / mElapsedSeconds;
+	return mBuffers->mMemStats[stat.getIndex()].mAllocatedCount;
 }
 
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index b4452d67a0..4651bfcb61 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -149,16 +149,28 @@ namespace LLTrace
 
 		// Timer accessors
 		LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator>& stat);
-		LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat);
-		U32 getSum(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat);
+		LLUnit<LLUnits::Seconds, F64> 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::SelfTimeAspect>& stat);
-		F32 getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat);
+		LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat);
+		F32 getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat);
 
 		// Memory accessors
-		LLUnit<LLUnits::Bytes, U32> getSum(const TraceType<MemStatAccumulator>& stat);
-		LLUnit<LLUnits::Bytes, F32> getPerSec(const TraceType<MemStatAccumulator>& stat);
+		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);
+
+		U32 getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat);
+		U32 getSum(const TraceType<MemStatAccumulator::DeallocationCountFacet>& stat);
 
 		// CountStatHandle accessors
 		F64 getSum(const TraceType<CountAccumulator>& stat);
@@ -186,18 +198,18 @@ namespace LLTrace
 			return (T)getMin(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
-		F64 getMax(const TraceType<SampleAccumulator>& stat);
+		F64 getMean(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
-		T getMax(const SampleStatHandle<T>& stat)
+		T getMean(SampleStatHandle<T>& stat)
 		{
-			return (T)getMax(static_cast<const TraceType<SampleAccumulator>&> (stat));
+			return (T)getMean(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
-		F64 getMean(const TraceType<SampleAccumulator>& stat);
+		F64 getMax(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
-		T getMean(SampleStatHandle<T>& stat)
+		T getMax(const SampleStatHandle<T>& stat)
 		{
-			return (T)getMean(static_cast<const TraceType<SampleAccumulator>&> (stat));
+			return (T)getMax(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
 		F64 getStandardDeviation(const TraceType<SampleAccumulator>& stat);
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 77c19b5152..a5406fb3f0 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -34,24 +34,10 @@
 namespace LLUnits
 {
 
-template<typename T>
-struct HighestPrecisionType
-{
-	typedef 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 typename HighestPrecisionType<VALUE_TYPE>::type_t get()
+	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.");
@@ -61,7 +47,7 @@ struct ConversionFactor
 template<typename BASE_UNITS_TAG, typename VALUE_TYPE>
 struct ConversionFactor<BASE_UNITS_TAG, BASE_UNITS_TAG, VALUE_TYPE>
 {
-	static typename HighestPrecisionType<VALUE_TYPE>::type_t get() 
+	static F64 get() 
 	{ 
 		return 1; 
 	}
@@ -433,12 +419,6 @@ STORAGE_TYPE rawValue(LLUnit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value();
 template<typename UNIT_TYPE, typename STORAGE_TYPE> 
 STORAGE_TYPE rawValue(LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value(); }
 
-template<typename UNIT_TYPE, typename STORAGE_TYPE> 
-struct HighestPrecisionType<LLUnit<UNIT_TYPE, STORAGE_TYPE> >
-{
-	typedef typename HighestPrecisionType<STORAGE_TYPE>::type_t type_t;
-};
-
 #define LL_DECLARE_DERIVED_UNIT(conversion_factor, base_unit_name, unit_name, unit_label)		\
 struct unit_name                                                                                \
 {                                                                                               \
@@ -448,49 +428,54 @@ struct unit_name
 template<typename STORAGE_TYPE>                                                                 \
 struct ConversionFactor<unit_name, base_unit_name, STORAGE_TYPE>                                \
 {                                                                                               \
-	static typename HighestPrecisionType<STORAGE_TYPE>::type_t get()                            \
+	static F64 get()                                                                            \
 	{                                                                                           \
-		return typename HighestPrecisionType<STORAGE_TYPE>::type_t(conversion_factor);          \
+		return (F64)conversion_factor;                                                          \
 	}                                                                                           \
 };                                                                                              \
 	                                                                                            \
 template<typename STORAGE_TYPE>                                                                 \
 struct ConversionFactor<base_unit_name, unit_name, STORAGE_TYPE>						        \
 {                                                                                               \
-	static typename HighestPrecisionType<STORAGE_TYPE>::type_t get()                            \
+	static F64 get()                                                                            \
 	{                                                                                           \
-		return typename HighestPrecisionType<STORAGE_TYPE>::type_t(1.0 / (conversion_factor));  \
+		return (F64)(1.0 / (conversion_factor));                                                \
 	}                                                                                           \
 }
 
-struct Bytes { typedef Bytes base_unit_t; static const char* getUnitLabel() { return "B"; }};
-LL_DECLARE_DERIVED_UNIT(1024, Bytes, Kilobytes, "KiB");
-LL_DECLARE_DERIVED_UNIT(1024 * 1024, Bytes, Megabytes, "MiB");
-LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024, Bytes, Gigabytes, "GiB");
+#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; }}
+
+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, Kilobits, "Kib");
-LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Megabits, "Mib");
-LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024 / 8, Bytes, Gigabits, "Gib");
+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");
 
-struct Seconds { typedef Seconds base_unit_t; static const char* getUnitLabel() { return "s"; } };
+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");
 
-struct Meters { typedef Meters base_unit_t; static const char* getUnitLabel() { return "m"; } };
+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");
 
-struct Hertz { typedef Hertz base_unit_t; static const char* getUnitLabel() { return "Hz"; } };
+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");
 
-struct Radians { typedef Radians base_unit_t; static const char* getUnitLabel() { return "rad"; } };
+LL_DECLARE_BASE_UNIT(Radians, "rad");
 LL_DECLARE_DERIVED_UNIT(DEG_TO_RAD, Radians, Degrees, "deg");
+
+
 } // namespace LLUnits
 
 #endif // LL_LLUNIT_H
-- 
cgit v1.2.3


From e1d96d72692d70f7e16fb93d6ef1d42c89d26409 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 5 Jun 2013 19:06:10 -0700
Subject: BUILDFIX: re-added missing lldeleteutils.h

---
 indra/llcommon/lldeleteutils.h | 47 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 indra/llcommon/lldeleteutils.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lldeleteutils.h b/indra/llcommon/lldeleteutils.h
new file mode 100644
index 0000000000..f250dc3028
--- /dev/null
+++ b/indra/llcommon/lldeleteutils.h
@@ -0,0 +1,47 @@
+/** 
+ * @file lldeleteutils.h
+ * @brief Utility functions to simplify some common pointer-munging idioms.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+#ifndef LL_DELETE_UTILS_H
+#define LL_DELETE_UTILS_H
+
+// Simple utility functions to eventually replace the common 2-line
+// idiom scattered throughout the viewer codebase.  Note that where
+// possible we would rather be using smart pointers of some sort.
+
+template <class T>
+inline void deleteAndClear(T*& ptr)
+{
+	delete ptr;
+	ptr = NULL;
+}
+
+template <class T>
+inline void deleteAndClearArray(T*& array_ptr)
+{
+	delete[] array_ptr;
+	array_ptr = NULL;
+}
+
+#endif
-- 
cgit v1.2.3


From 60b625588faec2472597dae50331b2ce95ce40a2 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 5 Jun 2013 19:57:07 -0700
Subject: BUILDFIX: build fixes for mac

---
 indra/llcommon/llpointer.h            | 2 +-
 indra/llcommon/lltrace.h              | 4 ++--
 indra/llcommon/llunit.h               | 3 ++-
 indra/llcommon/tests/llunits_test.cpp | 6 +++---
 4 files changed, 8 insertions(+), 7 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index e640ffd595..6a0a8fcb0d 100755
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -193,7 +193,7 @@ public:
 	{
 		if (pointer_t::notNull() && pointer_t::mPointer->getNumRefs() > 1)
 		{
-			*(pointer_t*)(this) = new Type(*pointer_t::mPointer);
+			*(pointer_t* )(this) = new Type(*pointer_t::mPointer);
 		}
 	}
 
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 343e1b16e8..c20e836f77 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -657,7 +657,7 @@ class EventStatHandle
 :	public TraceType<EventAccumulator>
 {
 public:
-	typedef typename F64 storage_t;
+	typedef F64 storage_t;
 	typedef TraceType<EventAccumulator> trace_t;
 
 	EventStatHandle(const char* name, const char* description = NULL)
@@ -702,7 +702,7 @@ class CountStatHandle
 :	public TraceType<CountAccumulator>
 {
 public:
-	typedef typename F64 storage_t;
+	typedef F64 storage_t;
 	typedef TraceType<CountAccumulator> trace_t;
 
 	CountStatHandle(const char* name, const char* description = NULL) 
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index a5406fb3f0..f48cbe0e11 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -41,6 +41,7 @@ struct ConversionFactor
 	{
 		// 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;
 	}
 };
 
@@ -473,7 +474,7 @@ LL_DECLARE_DERIVED_UNIT(1000 * 1000, Hertz, Megahertz, "MHz");
 LL_DECLARE_DERIVED_UNIT(1000 * 1000 * 1000, Hertz, Gigahertz, "GHz");
 
 LL_DECLARE_BASE_UNIT(Radians, "rad");
-LL_DECLARE_DERIVED_UNIT(DEG_TO_RAD, Radians, Degrees, "deg");
+LL_DECLARE_DERIVED_UNIT(0.01745329251994, Radians, Degrees, "deg");
 
 
 } // namespace LLUnits
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index 2a941e8229..33e30f9688 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -33,9 +33,9 @@
 namespace LLUnits
 {
 	// using powers of 2 to allow strict floating point equality
-	struct Quatloos { typedef Quatloos base_unit_t; };
-	LL_DECLARE_DERIVED_UNIT(4, Quatloos, Latinum);
-	LL_DECLARE_DERIVED_UNIT((1.0 / 4.0), Quatloos, Solari);
+	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");
 }
 
 namespace tut
-- 
cgit v1.2.3


From 042b7aec26905cdfded007d6507abccb44947d8a Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 5 Jun 2013 20:25:21 -0700
Subject: BUILDFIX: fixed llviewerassetstats test and render2dutils changes
 that were dropped in merge

---
 indra/llcommon/llinitparam.h | 2 --
 1 file changed, 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index a32557b4ac..879ea4fe2a 100755
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -1429,7 +1429,6 @@ namespace LLInitParam
 		{
 			bool serialized = false;
 			const self_t& typed_param = static_cast<const self_t&>(param);
-			if (!typed_param.isProvided()) return false;
 
 			LLPredicate::Value<ESerializePredicates> predicate;
 
@@ -1686,7 +1685,6 @@ namespace LLInitParam
 		{
 			bool serialized = false;
 			const self_t& typed_param = static_cast<const self_t&>(param);
-			if (!typed_param.isProvided()) return false;
 			LLPredicate::Value<ESerializePredicates> predicate;
 
 			predicate.set(REQUIRED, typed_param.mMinCount > 0);
-- 
cgit v1.2.3


From ebf35d51b14f224c36a19a453a20885e667f6bec Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 6 Jun 2013 21:26:57 -0700
Subject: SH-4232 FIX: Interesting: Viewer Crash on Login

---
 indra/llcommon/lltrace.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index c20e836f77..cfe1273b4b 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -169,7 +169,7 @@ public:
 	LL_FORCE_INLINE static ACCUMULATOR* getPrimaryStorage() 
 	{ 
 		ACCUMULATOR* accumulator = LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance();
-		return accumulator ? accumulator : sDefaultBuffer->mStorage;
+		return accumulator ? accumulator : getDefaultBuffer()->mStorage;
 	}
 
 	// NOTE: this is not thread-safe.  We assume that slots are reserved in the main thread before any child threads are spawned
-- 
cgit v1.2.3


From 9fd3af3c389ed491b515cbb5136b344b069913e4 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 13 Jun 2013 15:29:15 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 changed Units macros and argument order to make it more clear optimized units
 for integer types fixed merging of periodicrecordings...should eliminate
 duplicate entries in sceneloadmonitor history

---
 indra/llcommon/llcriticaldamp.cpp     |   2 +-
 indra/llcommon/llcriticaldamp.h       |   4 +-
 indra/llcommon/lldate.cpp             |   2 +-
 indra/llcommon/lldate.h               |   2 +-
 indra/llcommon/llfasttimer.cpp        |  14 +-
 indra/llcommon/llfasttimer.h          |   2 +-
 indra/llcommon/llprocessor.cpp        |   2 +-
 indra/llcommon/llprocessor.h          |   2 +-
 indra/llcommon/lltimer.cpp            |  14 +-
 indra/llcommon/lltimer.h              |  16 +-
 indra/llcommon/lltrace.h              |  76 +++----
 indra/llcommon/lltracerecording.cpp   | 189 +++++++++--------
 indra/llcommon/lltracerecording.h     |  56 ++---
 indra/llcommon/llunit.h               | 372 +++++++++++++++++++++-------------
 indra/llcommon/tests/llunits_test.cpp | 104 +++++-----
 15 files changed, 475 insertions(+), 382 deletions(-)

(limited to 'indra/llcommon')

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..809a0327ca 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,7 +365,7 @@ 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_ms = last_frame_recording.getSum(*timerp);
 		U32 num_calls = last_frame_recording.getSum(timerp->callCount());
 
 		// Don't bother with really brief times, keep output concise
@@ -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..1bf853c5c0 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -44,27 +44,27 @@ 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;
 
 void init();
 void cleanup();
@@ -216,6 +216,11 @@ public:
 	}
 
 	size_t size() const
+	{
+		return getNumIndices();
+	}
+
+	static size_t getNumIndices() 
 	{
 		return sNextStorageSlot;
 	}
@@ -263,6 +268,7 @@ public:
 	}
 
 	size_t getIndex() const { return mAccumulatorIndex; }
+	static size_t getNumIndices() { return AccumulatorBuffer<ACCUMULATOR>::getNumIndices(); }
 
 	virtual const char* getUnitLabel() { return ""; }
 
@@ -408,8 +414,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 +504,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 +534,7 @@ private:
 	F64	mMean,
 		mVarianceSum;
 
-	LLUnitImplicit<LLUnits::Seconds, F64>	mLastSampleTimeStamp,
+	LLUnitImplicit<F64, LLUnits::Seconds>	mLastSampleTimeStamp,
 											mTotalSamplingTime;
 
 	U32	mNumSamples;
@@ -578,8 +584,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 +597,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 +678,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(LLUnits::storageValue(converted_value));
 }
 
 template <typename T = F64>
@@ -694,7 +700,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(LLUnits::storageValue(converted_value));
 }
 
 template <typename T = F64>
@@ -716,7 +722,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(LLUnits::storageValue(converted_value));
 }
 
 
@@ -739,8 +745,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..ff90da3822 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -186,26 +186,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 +205,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 +219,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 +333,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 +422,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 +436,20 @@ 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)
+{
+	// if I have a recording of any length, then close it off and start a fresh one
+	if (getCurRecording().getDuration().value())
+	{
+		nextPeriod();
+	}
+	getCurRecording().appendRecording(recording);
 }
 
 
@@ -453,77 +457,77 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 {
 	if (other.mRecordingPeriods.empty()) return;
 
-	EPlayState play_state = getPlayState();
-	pause();
-
-	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()];
+	getCurRecording().update();
+	other.getCurRecording().update();
 
 	// if I have a recording of any length, then close it off and start a fresh one
 	if (getCurRecording().getDuration().value())
 	{
 		nextPeriod();
 	}
-	getCurRecording().appendRecording(other_oldest_recording);
 
-	if (other_recording_count > 1)
+	if (mAutoResize)
 	{
-		if (mAutoResize)
+		S32 other_index = (other.mCurPeriod + 1) % other.mRecordingPeriods.size();
+		S32 end_index = (other.mCurPeriod) % other.mRecordingPeriods.size(); 
+
+		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 +619,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 +647,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 +661,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 +675,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 +689,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 +704,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 +716,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 +738,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 +779,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..e3cef77b06 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -148,26 +148,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 +273,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 +288,7 @@ namespace LLTrace
 		class ThreadRecorder* getThreadRecorder(); 
 
 		LLTimer				mSamplingTimer;
-		F64					mElapsedSeconds;
+		LLUnit<F64, LLUnits::Seconds>			mElapsedSeconds;
 		LLCopyOnWritePointer<RecordingBuffers>	mBuffers;
 	};
 
@@ -299,11 +299,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 +318,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 +347,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 +363,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 +392,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 +408,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 +443,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 +469,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..5b961c81f0 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -35,31 +35,31 @@ namespace LLUnits
 {
 
 template<typename DERIVED_UNITS_TAG, typename BASE_UNITS_TAG, typename VALUE_TYPE>
-struct ConversionFactor
+struct Convert
 {
-	static F64 get()
+	static VALUE_TYPE get(VALUE_TYPE val)
 	{
 		// 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;
+        return val;
 	}
 };
 
 template<typename BASE_UNITS_TAG, typename VALUE_TYPE>
-struct ConversionFactor<BASE_UNITS_TAG, BASE_UNITS_TAG, VALUE_TYPE>
+struct Convert<BASE_UNITS_TAG, BASE_UNITS_TAG, VALUE_TYPE>
 {
-	static F64 get() 
+	static VALUE_TYPE get(VALUE_TYPE val)
 	{ 
-		return 1; 
+		return val; 
 	}
 };
 
 }
 
-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 +68,16 @@ struct LLUnit
 	{}
 
 	// unit initialization and conversion
-	template<typename OTHER_UNIT, typename OTHER_STORAGE>
-	LLUnit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other)
+	template<typename OTHER_STORAGE, typename OTHER_UNIT>
+	LLUnit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
 	:	mValue(convert(other))
 	{}
 	
+	bool operator == (const self_t& other)
+	{
+		return mValue = other.mValue;
+	}
+
 	// value assignment
 	self_t& operator = (storage_t value)
 	{
@@ -81,8 +86,8 @@ 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);
 		return *this;
@@ -93,9 +98,9 @@ struct LLUnit
 		return mValue;
 	}
 
-	template<typename NEW_UNIT_TYPE> LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE> as()
+	template<typename NEW_UNIT_TYPE> LLUnit<STORAGE_TYPE, NEW_UNIT_TYPE> as()
 	{
-		return LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE>(*this);
+		return LLUnit<STORAGE_TYPE, NEW_UNIT_TYPE>(*this);
 	}
 
 
@@ -104,8 +109,8 @@ 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);
 	}
@@ -115,8 +120,8 @@ 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);
 	}
@@ -127,7 +132,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 +144,43 @@ 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 storage_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()); 
+		return (storage_t)LLUnits::Convert<typename UNIT_TYPE::base_unit_t, UNIT_TYPE, STORAGE_TYPE>::get((STORAGE_TYPE)
+							LLUnits::Convert<SOURCE_UNITS, typename UNIT_TYPE::base_unit_t, SOURCE_STORAGE>::get(v.value())); 
 	}
 
+	template<typename SOURCE_STORAGE>
+	static storage_t convert(LLUnit<SOURCE_STORAGE, UNIT_TYPE> v) 
+	{ 
+		return (storage_t)(v.value());
+	}
+
+
 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))
 	{}
 
@@ -184,50 +195,50 @@ struct LLUnitImplicit : public LLUnit<UNIT_TYPE, STORAGE_TYPE>
 //
 // 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 +246,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 +297,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,7 +410,7 @@ 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(); }
 };
@@ -411,70 +420,147 @@ struct LLGetUnitLabel<LLUnit<T, STORAGE_T> >
 //
 namespace LLUnits
 {
+
+template<typename VALUE_TYPE>
+struct LinearOps
+{
+	typedef LinearOps<VALUE_TYPE> self_t;
+	LinearOps(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;
+	}
+};
+
+template<typename VALUE_TYPE>
+struct InverseLinearOps
+{
+	typedef InverseLinearOps<VALUE_TYPE> self_t;
+
+	InverseLinearOps(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;
+	}
+};
+
+
 template<typename T>
-T rawValue(T val) { return val; }
+T storageValue(T val) { return val; }
 
 template<typename UNIT_TYPE, typename STORAGE_TYPE> 
-STORAGE_TYPE rawValue(LLUnit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value(); }
+STORAGE_TYPE storageValue(LLUnit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); }
 
 template<typename UNIT_TYPE, typename STORAGE_TYPE> 
-STORAGE_TYPE rawValue(LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value(); }
+STORAGE_TYPE storageValue(LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); }
 
-#define LL_DECLARE_DERIVED_UNIT(conversion_factor, base_unit_name, unit_name, unit_label)		\
+#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>                                \
+struct Convert<unit_name, base_unit_name, STORAGE_TYPE>                                         \
 {                                                                                               \
-	static F64 get()                                                                            \
+	static STORAGE_TYPE get(STORAGE_TYPE val)                                                   \
 	{                                                                                           \
-		return (F64)conversion_factor;                                                          \
+		return (LinearOps<STORAGE_TYPE>(val) conversion_operation).mValue;                      \
 	}                                                                                           \
 };                                                                                              \
 	                                                                                            \
 template<typename STORAGE_TYPE>                                                                 \
-struct ConversionFactor<base_unit_name, unit_name, STORAGE_TYPE>						        \
+struct Convert<base_unit_name, unit_name, STORAGE_TYPE>						                    \
 {                                                                                               \
-	static F64 get()                                                                            \
+	static STORAGE_TYPE get(STORAGE_TYPE val)                                                   \
 	{                                                                                           \
-		return (F64)(1.0 / (conversion_factor));                                                \
+		return (InverseLinearOps<STORAGE_TYPE>(val) 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; }}
-
 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", Bytes, * 1000 * 1000);
+LL_DECLARE_DERIVED_UNIT(Gigabytes, "GB", Bytes, * 1000 * 1000 * 1000);
+LL_DECLARE_DERIVED_UNIT(Kibibytes, "KiB", Bytes, * 1024);
+LL_DECLARE_DERIVED_UNIT(Mibibytes, "MiB", Bytes, * 1024 * 1024);
+LL_DECLARE_DERIVED_UNIT(Gibibytes, "GiB", Bytes, * 1024 * 1024 * 1024);
+
+LL_DECLARE_DERIVED_UNIT(Bits, "b", Bytes, / 8);
+LL_DECLARE_DERIVED_UNIT(Kilobits, "Kb", Bytes, * (1000 / 8));
+LL_DECLARE_DERIVED_UNIT(Megabits, "Mb", Bytes, * (1000 / 8));
+LL_DECLARE_DERIVED_UNIT(Gigabits, "Gb", Bytes, * (1000 * 1000 * 1000 / 8));
+LL_DECLARE_DERIVED_UNIT(Kibibits, "Kib", Bytes, * (1024 / 8));
+LL_DECLARE_DERIVED_UNIT(Mibibits, "Mib", Bytes, * (1024 / 8));
+LL_DECLARE_DERIVED_UNIT(Gibibits, "Gib", Bytes, * (1024 * 1024 * 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", Seconds, / 1000000);
+LL_DECLARE_DERIVED_UNIT(Nanoseconds, "ns", Seconds, / 1000000000);
 
 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", Hertz, * 1000 * 1000);
+LL_DECLARE_DERIVED_UNIT(Gigahertz, "GHz", Hertz, * 1000 * 1000 * 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..747e8d1827 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", Quatloos, / 4);
 }
 
 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;
-- 
cgit v1.2.3


From 3f2de87340b1c831ea59e4a3ca960d49f343c9fd Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 17 Jun 2013 01:18:21 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 added getAs and setAs to LLUnit to make it clearer how you specify units
 removed accidental 0-based indexing of periodicRecording history... should
 now be consistently 1-based, with 0 accessing current active recording
 removed per frame timer updates of all historical timer bars in fast timer
 display added missing assignment operator to recordings

---
 indra/llcommon/llfasttimer.cpp        |   6 +-
 indra/llcommon/lltrace.h              |  16 ++-
 indra/llcommon/lltracerecording.cpp   |  23 ++---
 indra/llcommon/lltracerecording.h     |   2 +
 indra/llcommon/llunit.h               | 182 ++++++++++++++++------------------
 indra/llcommon/tests/llunits_test.cpp |   8 +-
 6 files changed, 122 insertions(+), 115 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 809a0327ca..d9670891f8 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -365,11 +365,11 @@ void TimeBlock::dumpCurTimes()
 		++it)
 	{
 		TimeBlock* timerp = (*it);
-		LLUnit<F64, LLUnits::Seconds> 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;
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 1bf853c5c0..cd377531e8 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -66,6 +66,16 @@ 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();
 bool isInitialized();
@@ -678,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::storageValue(converted_value));
+	measurement.getPrimaryAccumulator()->record(storage_value(converted_value));
 }
 
 template <typename T = F64>
@@ -700,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::storageValue(converted_value));
+	measurement.getPrimaryAccumulator()->sample(storage_value(converted_value));
 }
 
 template <typename T = F64>
@@ -722,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::storageValue(converted_value));
+	count.getPrimaryAccumulator()->add(storage_value(converted_value));
 }
 
 
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index ff90da3822..f2c5941011 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -121,22 +121,27 @@ 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;
 }
 
 
@@ -444,12 +449,8 @@ void PeriodicRecording::nextPeriod()
 
 void PeriodicRecording::appendRecording(Recording& recording)
 {
-	// if I have a recording of any length, then close it off and start a fresh one
-	if (getCurRecording().getDuration().value())
-	{
-		nextPeriod();
-	}
 	getCurRecording().appendRecording(recording);
+	nextPeriod();
 }
 
 
@@ -460,12 +461,6 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 	getCurRecording().update();
 	other.getCurRecording().update();
 
-	// if I have a recording of any length, then close it off and start a fresh one
-	if (getCurRecording().getDuration().value())
-	{
-		nextPeriod();
-	}
-
 	if (mAutoResize)
 	{
 		S32 other_index = (other.mCurPeriod + 1) % other.mRecordingPeriods.size();
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index e3cef77b06..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);
 
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 5b961c81f0..5229fe69d7 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -30,31 +30,7 @@
 #include "stdtypes.h"
 #include "llpreprocessor.h"
 #include "llerrorlegacy.h"
-
-namespace LLUnits
-{
-
-template<typename DERIVED_UNITS_TAG, typename BASE_UNITS_TAG, typename VALUE_TYPE>
-struct Convert
-{
-	static VALUE_TYPE get(VALUE_TYPE val)
-	{
-		// 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 val;
-	}
-};
-
-template<typename BASE_UNITS_TAG, typename VALUE_TYPE>
-struct Convert<BASE_UNITS_TAG, BASE_UNITS_TAG, VALUE_TYPE>
-{
-	static VALUE_TYPE get(VALUE_TYPE val)
-	{ 
-		return val; 
-	}
-};
-
-}
+#include <boost/type_traits/is_same.hpp>
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE>
 struct LLUnit
@@ -70,7 +46,7 @@ struct LLUnit
 	// unit initialization and conversion
 	template<typename OTHER_STORAGE, typename OTHER_UNIT>
 	LLUnit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
-	:	mValue(convert(other))
+	:	mValue(convert(other).mValue)
 	{}
 	
 	bool operator == (const self_t& other)
@@ -89,7 +65,7 @@ struct LLUnit
 	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;
 	}
 
@@ -98,11 +74,17 @@ struct LLUnit
 		return mValue;
 	}
 
-	template<typename NEW_UNIT_TYPE> LLUnit<STORAGE_TYPE, NEW_UNIT_TYPE> as()
+	template<typename NEW_UNIT_TYPE> 
+	STORAGE_TYPE getAs()
 	{
-		return LLUnit<STORAGE_TYPE, NEW_UNIT_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)
 	{
@@ -112,7 +94,7 @@ struct LLUnit
 	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)
@@ -123,7 +105,7 @@ struct LLUnit
 	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)
@@ -151,19 +133,13 @@ struct LLUnit
 	}
 
 	template<typename SOURCE_STORAGE, typename SOURCE_UNITS>
-	static storage_t convert(LLUnit<SOURCE_STORAGE, SOURCE_UNITS> v) 
+	static self_t convert(LLUnit<SOURCE_STORAGE, SOURCE_UNITS> v) 
 	{ 
-		return (storage_t)LLUnits::Convert<typename UNIT_TYPE::base_unit_t, UNIT_TYPE, STORAGE_TYPE>::get((STORAGE_TYPE)
-							LLUnits::Convert<SOURCE_UNITS, typename UNIT_TYPE::base_unit_t, SOURCE_STORAGE>::get(v.value())); 
+		self_t result;
+		ll_convert_units(v, result);
+		return result;
 	}
 
-	template<typename SOURCE_STORAGE>
-	static storage_t convert(LLUnit<SOURCE_STORAGE, UNIT_TYPE> v) 
-	{ 
-		return (storage_t)(v.value());
-	}
-
-
 protected:
 	storage_t mValue;
 };
@@ -192,6 +168,39 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_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 +
 //
@@ -415,17 +424,11 @@ struct LLGetUnitLabel<LLUnit<STORAGE_T, T> >
 	static const char* getUnitLabel() { return T::getUnitLabel(); }
 };
 
-//
-// Unit declarations
-//
-namespace LLUnits
-{
-
 template<typename VALUE_TYPE>
-struct LinearOps
+struct LLUnitLinearOps
 {
-	typedef LinearOps<VALUE_TYPE> self_t;
-	LinearOps(VALUE_TYPE val) : mValue (val) {}
+	typedef LLUnitLinearOps<VALUE_TYPE> self_t;
+	LLUnitLinearOps(VALUE_TYPE val) : mValue (val) {}
 
 	operator VALUE_TYPE() const { return mValue; }
 	VALUE_TYPE mValue;
@@ -456,11 +459,11 @@ struct LinearOps
 };
 
 template<typename VALUE_TYPE>
-struct InverseLinearOps
+struct LLUnitInverseLinearOps
 {
-	typedef InverseLinearOps<VALUE_TYPE> self_t;
+	typedef LLUnitInverseLinearOps<VALUE_TYPE> self_t;
 
-	InverseLinearOps(VALUE_TYPE val) : mValue (val) {}
+	LLUnitInverseLinearOps(VALUE_TYPE val) : mValue (val) {}
 	operator VALUE_TYPE() const { return mValue; }
 	VALUE_TYPE mValue;
 
@@ -489,16 +492,6 @@ struct InverseLinearOps
 	}
 };
 
-
-template<typename T>
-T storageValue(T val) { return val; }
-
-template<typename UNIT_TYPE, typename STORAGE_TYPE> 
-STORAGE_TYPE storageValue(LLUnit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); }
-
-template<typename UNIT_TYPE, typename STORAGE_TYPE> 
-STORAGE_TYPE storageValue(LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); }
-
 #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; }}
 
@@ -507,57 +500,58 @@ struct unit_name
 {                                                                                               \
 	typedef base_unit_name base_unit_t;                                                         \
 	static const char* getUnitLabel() { return unit_label; }									\
-};                                                                                              \
-template<typename STORAGE_TYPE>                                                                 \
-struct Convert<unit_name, base_unit_name, STORAGE_TYPE>                                         \
-{                                                                                               \
-	static STORAGE_TYPE get(STORAGE_TYPE val)                                                   \
-	{                                                                                           \
-		return (LinearOps<STORAGE_TYPE>(val) conversion_operation).mValue;                      \
-	}                                                                                           \
 };                                                                                              \
 	                                                                                            \
-template<typename STORAGE_TYPE>                                                                 \
-struct Convert<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 STORAGE_TYPE get(STORAGE_TYPE val)                                                   \
-	{                                                                                           \
-		return (InverseLinearOps<STORAGE_TYPE>(val) conversion_operation).mValue;               \
-	}                                                                                           \
-}
+	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;             \
+}                                                                                               
 
+//
+// Unit declarations
+//
+
+namespace LLUnits
+{
 LL_DECLARE_BASE_UNIT(Bytes, "B");
 LL_DECLARE_DERIVED_UNIT(Kilobytes, "KB", Bytes, * 1000);
-LL_DECLARE_DERIVED_UNIT(Megabytes, "MB", Bytes, * 1000 * 1000);
-LL_DECLARE_DERIVED_UNIT(Gigabytes, "GB", Bytes, * 1000 * 1000 * 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", Bytes, * 1024 * 1024);
-LL_DECLARE_DERIVED_UNIT(Gibibytes, "GiB", Bytes, * 1024 * 1024 * 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", Bytes, * (1000 / 8));
-LL_DECLARE_DERIVED_UNIT(Gigabits, "Gb", Bytes, * (1000 * 1000 * 1000 / 8));
-LL_DECLARE_DERIVED_UNIT(Kibibits, "Kib", Bytes, * (1024 / 8));
-LL_DECLARE_DERIVED_UNIT(Mibibits, "Mib", Bytes, * (1024 / 8));
-LL_DECLARE_DERIVED_UNIT(Gibibits, "Gib", Bytes, * (1024 * 1024 * 1024 / 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(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", Seconds, / 1000000);
-LL_DECLARE_DERIVED_UNIT(Nanoseconds, "ns", Seconds, / 1000000000);
+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(Kilometers, "km", Meters, * 1000);
-LL_DECLARE_DERIVED_UNIT(Centimeters, "cm", Meters, * 100);
-LL_DECLARE_DERIVED_UNIT(Millimeters, "mm", 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(Kilohertz, "KHz", Hertz, * 1000);
-LL_DECLARE_DERIVED_UNIT(Megahertz, "MHz", Hertz, * 1000 * 1000);
-LL_DECLARE_DERIVED_UNIT(Gigahertz, "GHz", Hertz, * 1000 * 1000 * 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(Degrees, "deg", Radians, * 0.01745329251994);
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index 747e8d1827..04764f6c2f 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -35,7 +35,7 @@ namespace LLUnits
 	// using powers of 2 to allow strict floating point equality
 	LL_DECLARE_BASE_UNIT(Quatloos, "Quat");
 	LL_DECLARE_DERIVED_UNIT(Latinum, "Lat", Quatloos, * 4);
-	LL_DECLARE_DERIVED_UNIT(Solari, "Sol", Quatloos, / 4);
+	LL_DECLARE_DERIVED_UNIT(Solari, "Sol", Latinum, / 16);
 }
 
 namespace tut
@@ -206,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);
 	}
 }
-- 
cgit v1.2.3


From d136c4c29686c565b5a46503aa67a9c958b4145d Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 18 Jun 2013 23:41:53 -0700
Subject: SH-4246 FIX interesting: fast timers significantly decreases
 framerate removed implicit flushes on reads from recorders for better
 performance made sure stack timers were updated on recorder deactivate faster
 rendering and better ui for fast timer view

---
 indra/llcommon/llfasttimer.cpp           | 77 ++++++++++++++++++++------------
 indra/llcommon/llfasttimer.h             |  4 ++
 indra/llcommon/lltrace.h                 | 19 ++++----
 indra/llcommon/lltracerecording.cpp      | 38 ++--------------
 indra/llcommon/lltracethreadrecorder.cpp |  1 +
 indra/llcommon/tests/llunits_test.cpp    |  3 ++
 6 files changed, 68 insertions(+), 74 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index d9670891f8..4da9c3fd6c 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -178,43 +178,38 @@ TimeBlockTreeNode& TimeBlock::getTreeNode() const
 	return *nodep;
 }
 
-static LLFastTimer::DeclareTimer FTM_PROCESS_TIMES("Process FastTimer Times");
 
-// not thread safe, so only call on main thread
-//static
-void TimeBlock::processTimes()
+void TimeBlock::bootstrapTimerTree()
 {
-	LLFastTimer _(FTM_PROCESS_TIMES);
-	get_clock_count(); // good place to calculate clock frequency
-	U64 cur_time = getCPUClockCount64();
-
-	// set up initial tree
 	for (LLInstanceTracker<TimeBlock>::instance_iter begin_it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(), it = begin_it; 
 		it != end_it; 
 		++it)
 	{
 		TimeBlock& timer = *it;
 		if (&timer == &TimeBlock::getRootTimeBlock()) continue;
-			
+
 		// bootstrap tree construction by attaching to last timer to be on stack
 		// when this timer was called
 		if (timer.getParent() == &TimeBlock::getRootTimeBlock())
 		{
 			TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
-			
+
 			if (accumulator->mLastCaller)
 			{
 				timer.setParent(accumulator->mLastCaller);
 				accumulator->mParent = accumulator->mLastCaller;
 			}
-				// no need to push up tree on first use, flag can be set spuriously
+			// no need to push up tree on first use, flag can be set spuriously
 			accumulator->mMoveUpTree = false;
 		}
 	}
+}
 
-	// bump timers up tree if they have 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
+// bump timers up tree if they have 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
+void TimeBlock::incrementalUpdateTimerTree()
+{
 	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(TimeBlock::getRootTimeBlock());
 		it != end_timer_tree_bottom_up();
 		++it)
@@ -240,27 +235,35 @@ void TimeBlock::processTimes()
 				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());
-					accumulator->mParent = timerp->getParent();
-					accumulator->mMoveUpTree = false;
+				accumulator->mParent = timerp->getParent();
+				accumulator->mMoveUpTree = false;
 
 				// don't bubble up any ancestors until descendants are done bubbling up
-					// as ancestors may call this timer only on certain paths, so we want to resolve
-					// child-most block locations before their parents
+				// as ancestors may call this timer only on certain paths, so we want to resolve
+				// child-most block locations before their parents
 				it.skipAncestors();
 			}
 		}
 	}
+}
+
+
+void TimeBlock::updateTimes()
+{
+	U64 cur_time = getCPUClockCount64();
 
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
-	BlockTimerStackRecord* stack_record			= ThreadTimerStack::getInstance();
-	BlockTimer* cur_timer						= stack_record->mActiveTimer;
-	TimeBlockAccumulator* accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
+	BlockTimerStackRecord* stack_record	= ThreadTimerStack::getInstance();
+	BlockTimer* cur_timer				= stack_record->mActiveTimer;
+	TimeBlockAccumulator* accumulator	= stack_record->mTimeBlock->getPrimaryAccumulator();
 
 	while(cur_timer 
 		&& cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self
 	{
 		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
-		accumulator->mTotalTimeCounter += cumulative_time_delta - (accumulator->mTotalTimeCounter - cur_timer->mBlockStartTotalTimeCounter);
+		accumulator->mTotalTimeCounter += cumulative_time_delta 
+			- (accumulator->mTotalTimeCounter 
+			- cur_timer->mBlockStartTotalTimeCounter);
 		accumulator->mSelfTimeCounter += cumulative_time_delta - stack_record->mChildTime;
 		stack_record->mChildTime = 0;
 
@@ -268,11 +271,28 @@ void TimeBlock::processTimes()
 		cur_timer->mBlockStartTotalTimeCounter = accumulator->mTotalTimeCounter;
 
 		stack_record = &cur_timer->mParentTimerData;
-		accumulator = stack_record->mTimeBlock->getPrimaryAccumulator();
-		cur_timer = stack_record->mActiveTimer;
+		accumulator  = stack_record->mTimeBlock->getPrimaryAccumulator();
+		cur_timer    = stack_record->mActiveTimer;
 
 		stack_record->mChildTime += cumulative_time_delta;
 	}
+}
+
+static LLFastTimer::DeclareTimer FTM_PROCESS_TIMES("Process FastTimer Times");
+
+// not thread safe, so only call on main thread
+//static
+void TimeBlock::processTimes()
+{
+	LLFastTimer _(FTM_PROCESS_TIMES);
+	get_clock_count(); // good place to calculate clock frequency
+
+	// set up initial tree
+	bootstrapTimerTree();
+
+	incrementalUpdateTimerTree();
+
+	updateTimes();
 
 	// reset for next frame
 	for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(),
@@ -288,14 +308,13 @@ void TimeBlock::processTimes()
 	}
 }
 
-
 std::vector<TimeBlock*>::iterator TimeBlock::beginChildren()
-		{
+{
 	return getTreeNode().mChildren.begin(); 
-		}
+}
 
 std::vector<TimeBlock*>::iterator TimeBlock::endChildren()
-		{
+{
 	return getTreeNode().mChildren.end();
 }
 
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index fdc6997d45..e800befd9f 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -115,6 +115,7 @@ public:
 	static void pushLog(LLSD sd);
 	static void setLogLock(LLMutex* mutex);
 	static void writeLog(std::ostream& os);
+	static void updateTimes();
 
 	// dumps current cumulative frame stats to log
 	// call nextFrame() to reset timers
@@ -262,6 +263,9 @@ public:
 	// can be called multiple times in a frame, at any point
 	static void processTimes();
 
+	static void bootstrapTimerTree();
+	static void incrementalUpdateTimerTree();
+
 	// call this once a frame to periodically log timers
 	static void logStats();
 
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index cd377531e8..6292534a03 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -157,12 +157,12 @@ public:
 		}
 	}
 
-	void flush()
+	void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
 	{
 		llassert(mStorageSize >= sNextStorageSlot);
 		for (size_t i = 0; i < sNextStorageSlot; i++)
 		{
-			mStorage[i].flush();
+			mStorage[i].flush(time_stamp);
 		}
 	}
 
@@ -380,7 +380,7 @@ public:
 		mLastValue = other ? other->mLastValue : 0;
 	}
 
-	void flush() {}
+	void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {}
 
 	F64	getSum() const { return mSum; }
 	F64	getMin() const { return mMin; }
@@ -512,9 +512,8 @@ public:
 		mHasValue = other ? other->mHasValue : false;
 	}
 
-	void flush()
+	void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
 	{
-		LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds();
 		LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp;
 
 		if (mHasValue)
@@ -579,7 +578,7 @@ public:
 		mSum = 0;
 	}
 
-	void flush() {}
+	void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {}
 
 	F64	getSum() const { return mSum; }
 
@@ -614,7 +613,7 @@ public:
 	TimeBlockAccumulator();
 	void addSamples(const self_t& other, bool /*append*/);
 	void reset(const self_t* other);
-	void flush() {}
+	void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {}
 
 	//
 	// members
@@ -780,10 +779,10 @@ struct MemStatAccumulator
 		mDeallocatedCount = 0;
 	}
 
-	void flush() 
+	void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp) 
 	{
-		mSize.flush();
-		mChildSize.flush();
+		mSize.flush(time_stamp);
+		mChildSize.flush(time_stamp);
 	}
 
 	SampleAccumulator	mSize,
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index f2c5941011..33002929ea 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -107,7 +107,9 @@ void RecordingBuffers::reset(RecordingBuffers* other)
 
 void RecordingBuffers::flush()
 {
-	mSamples.flush();
+	LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds();
+
+	mSamples.flush(time_stamp);
 }
 
 ///////////////////////////////////////////////////////////////////////
@@ -205,7 +207,6 @@ void Recording::mergeRecording( const Recording& other)
 LLUnit<F64, LLUnits::Seconds> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
-	update();
 	return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
 				/ (F64)LLTrace::TimeBlock::countsPerSecond();
 }
@@ -213,14 +214,12 @@ LLUnit<F64, LLUnits::Seconds> Recording::getSum(const TraceType<TimeBlockAccumul
 LLUnit<F64, LLUnits::Seconds> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
-	update();
 	return (F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond();
 }
 
 
 U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat)
 {
-	update();
 	return mBuffers->mStackTimers[stat.getIndex()].mCalls;
 }
 
@@ -228,7 +227,6 @@ LLUnit<F64, LLUnits::Seconds> Recording::getPerSec(const TraceType<TimeBlockAccu
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
-	update();
 	return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
 				/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value());
 }
@@ -237,105 +235,88 @@ LLUnit<F64, LLUnits::Seconds> Recording::getPerSec(const TraceType<TimeBlockAccu
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
-	update();
 	return (F64)(accumulator.mSelfTimeCounter) 
 			/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value());
 }
 
 F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat)
 {
-	update();
 	return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds.value();
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getMin(const TraceType<MemStatAccumulator>& stat)
 {
-	update();
 	return mBuffers->mMemStats[stat.getIndex()].mSize.getMin();
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getMean(const TraceType<MemStatAccumulator>& stat)
 {
-	update();
 	return mBuffers->mMemStats[stat.getIndex()].mSize.getMean();
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getMax(const TraceType<MemStatAccumulator>& stat)
 {
-	update();
 	return mBuffers->mMemStats[stat.getIndex()].mSize.getMax();
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat)
 {
-	update();
 	return mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation();
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getLastValue(const TraceType<MemStatAccumulator>& stat)
 {
-	update();
 	return mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue();
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	update();
 	return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMin();
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	update();
 	return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMean();
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	update();
 	return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMax();
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	update();
 	return mBuffers->mMemStats[stat.getIndex()].mChildSize.getStandardDeviation();
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	update();
 	return mBuffers->mMemStats[stat.getIndex()].mChildSize.getLastValue();
 }
 
 U32 Recording::getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat)
 {
-	update();
 	return mBuffers->mMemStats[stat.getIndex()].mAllocatedCount;
 }
 
 U32 Recording::getSum(const TraceType<MemStatAccumulator::DeallocationCountFacet>& stat)
 {
-	update();
 	return mBuffers->mMemStats[stat.getIndex()].mAllocatedCount;
 }
 
 
 F64 Recording::getSum( const TraceType<CountAccumulator>& stat )
 {
-	update();
 	return mBuffers->mCounts[stat.getIndex()].getSum();
 }
 
 F64 Recording::getSum( const TraceType<EventAccumulator>& stat )
 {
-	update();
 	return (F64)mBuffers->mEvents[stat.getIndex()].getSum();
 }
 
 F64 Recording::getPerSec( const TraceType<CountAccumulator>& stat )
 {
-	update();
 	F64 sum = mBuffers->mCounts[stat.getIndex()].getSum();
 	return  (sum != 0.0) 
 		? (sum / mElapsedSeconds.value())
@@ -344,79 +325,66 @@ F64 Recording::getPerSec( const TraceType<CountAccumulator>& stat )
 
 U32 Recording::getSampleCount( const TraceType<CountAccumulator>& stat )
 {
-	update();
 	return mBuffers->mCounts[stat.getIndex()].getSampleCount();
 }
 
 F64 Recording::getMin( const TraceType<SampleAccumulator>& stat )
 {
-	update();
 	return mBuffers->mSamples[stat.getIndex()].getMin();
 }
 
 F64 Recording::getMax( const TraceType<SampleAccumulator>& stat )
 {
-	update();
 	return mBuffers->mSamples[stat.getIndex()].getMax();
 }
 
 F64 Recording::getMean( const TraceType<SampleAccumulator>& stat )
 {
-	update();
 	return mBuffers->mSamples[stat.getIndex()].getMean();
 }
 
 F64 Recording::getStandardDeviation( const TraceType<SampleAccumulator>& stat )
 {
-	update();
 	return mBuffers->mSamples[stat.getIndex()].getStandardDeviation();
 }
 
 F64 Recording::getLastValue( const TraceType<SampleAccumulator>& stat )
 {
-	update();
 	return mBuffers->mSamples[stat.getIndex()].getLastValue();
 }
 
 U32 Recording::getSampleCount( const TraceType<SampleAccumulator>& stat )
 {
-	update();
 	return mBuffers->mSamples[stat.getIndex()].getSampleCount();
 }
 
 F64 Recording::getMin( const TraceType<EventAccumulator>& stat )
 {
-	update();
 	return mBuffers->mEvents[stat.getIndex()].getMin();
 }
 
 F64 Recording::getMax( const TraceType<EventAccumulator>& stat )
 {
-	update();
 	return mBuffers->mEvents[stat.getIndex()].getMax();
 }
 
 F64 Recording::getMean( const TraceType<EventAccumulator>& stat )
 {
-	update();
 	return mBuffers->mEvents[stat.getIndex()].getMean();
 }
 
 F64 Recording::getStandardDeviation( const TraceType<EventAccumulator>& stat )
 {
-	update();
 	return mBuffers->mEvents[stat.getIndex()].getStandardDeviation();
 }
 
 F64 Recording::getLastValue( const TraceType<EventAccumulator>& stat )
 {
-	update();
 	return mBuffers->mEvents[stat.getIndex()].getLastValue();
 }
 
 U32 Recording::getSampleCount( const TraceType<EventAccumulator>& stat )
 {
-	update();
 	return mBuffers->mEvents[stat.getIndex()].getSampleCount();
 }
 
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index c1a0700eff..54006f4e5b 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -111,6 +111,7 @@ ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringU
 	if (mActiveRecordings.empty()) return mActiveRecordings.rend();
 
 	mActiveRecordings.back()->mPartialRecording.flush();
+	TimeBlock::updateTimes();
 
 	active_recording_list_t::reverse_iterator it, end_it;
 	for (it = mActiveRecordings.rbegin(), end_it = mActiveRecordings.rend();
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index 04764f6c2f..a5df51f6de 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -56,6 +56,9 @@ namespace tut
 		LLUnit<F32, Quatloos> float_quatloos;
 		ensure(float_quatloos == 0.f);
 
+		LLUnit<F32, Quatloos> float_initialize_quatloos(1);
+		ensure(float_initialize_quatloos == 1.f);
+
 		LLUnit<S32, Quatloos> int_quatloos;
 		ensure(int_quatloos == 0);
 
-- 
cgit v1.2.3


From c5fc8f90060aa7a6c8fbb72313172423b01eddc5 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 19 Jun 2013 08:23:53 -0700
Subject: SH-4246 FIX interesting: fast timers significantly decreases
 framerate moved collapsed flag to fast timer tree node

---
 indra/llcommon/llfasttimer.cpp | 8 +++-----
 indra/llcommon/llfasttimer.h   | 5 +----
 indra/llcommon/lltrace.cpp     | 3 ++-
 indra/llcommon/lltrace.h       | 1 +
 4 files changed, 7 insertions(+), 10 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 4da9c3fd6c..becfa9c288 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -118,7 +118,7 @@ struct SortTimerByName
 
 TimeBlock& TimeBlock::getRootTimeBlock()
 	{
-	static TimeBlock root_timer("root", true, NULL);
+	static TimeBlock root_timer("root", NULL);
 	return root_timer;
 	}
 
@@ -164,11 +164,9 @@ U64 TimeBlock::countsPerSecond()
 }
 #endif
 
-TimeBlock::TimeBlock(const char* name, bool open, TimeBlock* parent)
-:	TraceType<TimeBlockAccumulator>(name),
-	mCollapsed(true)
+TimeBlock::TimeBlock(const char* name, TimeBlock* parent)
+:	TraceType<TimeBlockAccumulator>(name)
 {
-	setCollapsed(!open);
 }
 
 TimeBlockTreeNode& TimeBlock::getTreeNode() const
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index e800befd9f..642c99ccce 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -86,7 +86,7 @@ class TimeBlock
 	public LLInstanceTracker<TimeBlock>
 {
 public:
-	TimeBlock(const char* name, bool open = false, TimeBlock* parent = &getRootTimeBlock());
+	TimeBlock(const char* name, TimeBlock* parent = &getRootTimeBlock());
 
 	TimeBlockTreeNode& getTreeNode() const;
 	TimeBlock* getParent() const { return getTreeNode().getParent(); }
@@ -98,9 +98,6 @@ public:
 	child_iter endChildren();
 	std::vector<TimeBlock*>& getChildren();
 
-	void setCollapsed(bool collapsed)	{ mCollapsed = collapsed; }
-	bool getCollapsed() const			{ return mCollapsed; }
-
 	TraceType<TimeBlockAccumulator::CallCountFacet>& callCount() 
 	{
 		return static_cast<TraceType<TimeBlockAccumulator::CallCountFacet>&>(*(TraceType<TimeBlockAccumulator>*)this);
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index c831a1548d..59a4b42c97 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -85,7 +85,8 @@ void set_thread_recorder(ThreadRecorder* recorder)
 TimeBlockTreeNode::TimeBlockTreeNode() 
 :	mBlock(NULL),
 	mParent(NULL),
-	mNeedsSorting(false)
+	mNeedsSorting(false),
+	mCollapsed(true)
 {}
 
 void TimeBlockTreeNode::setParent( TimeBlock* parent )
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 6292534a03..fb7ffb0a29 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -663,6 +663,7 @@ public:
 	TimeBlock*					mBlock;
 	TimeBlock*					mParent;	
 	std::vector<TimeBlock*>		mChildren;
+	bool						mCollapsed;
 	bool						mNeedsSorting;
 };
 
-- 
cgit v1.2.3


From e62190098b4ffad8be83b54499c61ef645847efd Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 19 Jun 2013 12:17:13 -0700
Subject: BUILDFIX: changed unsupported static_assert to LL_STATIC_ASSERT.
 renamed llstatic_assert_template to LL_BAD_TEMPLATE_INSTANTIATION

---
 indra/llcommon/llerrorlegacy.h |  8 ++++----
 indra/llcommon/llunit.h        | 17 +++++++++--------
 2 files changed, 13 insertions(+), 12 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h
index 097a533b1a..50c95339e4 100755
--- a/indra/llcommon/llerrorlegacy.h
+++ b/indra/llcommon/llerrorlegacy.h
@@ -113,11 +113,11 @@ const int LL_ERR_PRICE_MISMATCH = -23018;
 #endif
 
 #ifdef LL_WINDOWS
-#define llstatic_assert(func, msg) static_assert(func, msg)
-#define llstatic_assert_template(type, func, msg) static_assert(func, msg)
+#define LL_STATIC_ASSERT(func, msg) static_assert(func, msg)
+#define LL_BAD_TEMPLATE_INSTANTIATION(type, msg) static_assert(false, msg)
 #else
-#define llstatic_assert(func, msg) BOOST_STATIC_ASSERT(func)
-#define llstatic_assert_template(type, func, msg) BOOST_STATIC_ASSERT(sizeof(type) != 0 && func);
+#define LL_STATIC_ASSERT(func, msg) BOOST_STATIC_ASSERT(func)
+#define LL_BAD_TEMPLATE_INSTANTIATION(type, msg) BOOST_STATIC_ASSERT(sizeof(type) != 0 && false);
 #endif
 
 // handy compile-time assert - enforce those template parameters! 
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 5229fe69d7..2402cdbb95 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -117,7 +117,7 @@ struct LLUnit
 	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.");
+		LL_BAD_TEMPLATE_INSTANTIATION(OTHER_UNIT, "Multiplication of unit types not supported.");
 	}
 
 	void operator /= (storage_t divisor)
@@ -129,7 +129,7 @@ struct LLUnit
 	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.");
+		LL_BAD_TEMPLATE_INSTANTIATION(OTHER_UNIT, "Illegal in-place division of unit types.");
 	}
 
 	template<typename SOURCE_STORAGE, typename SOURCE_UNITS>
@@ -172,10 +172,11 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_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");
+	typedef boost::integral_constant<bool, 
+									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> conversion_valid_t;
+	LL_STATIC_ASSERT(conversion_valid_t::value, "invalid conversion");
 
 	if (boost::is_same<T1, typename T1::base_unit_t>::value)
 	{
@@ -322,7 +323,7 @@ template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, ty
 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.");
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "Multiplication of unit types results in new unit type - not supported.");
 	return LLUnit<STORAGE_TYPE1, UNIT_TYPE1>();
 }
 
@@ -342,7 +343,7 @@ template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, ty
 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.");
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "Multiplication of unit types results in new unit type - not supported.");
 	return LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>();
 }
 
-- 
cgit v1.2.3


From 3fe19d883d2856cd7d104810b794eee82d642a3e Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 19 Jun 2013 20:30:41 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 scene monitor output is cleaned up, no duplicate first frame, less scientific
 notation periodic recording extension now works more cleanly

---
 indra/llcommon/lltracerecording.cpp | 58 ++++++++++++++++++++++---------------
 1 file changed, 34 insertions(+), 24 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 33002929ea..0fe95ee75f 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -428,36 +428,49 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 
 	getCurRecording().update();
 	other.getCurRecording().update();
+	
+	const U32 other_recording_slots = other.mRecordingPeriods.size();
+	const U32 other_num_recordings = other.getNumRecordedPeriods();
+	const U32 other_current_recording_index = other.mCurPeriod;
+	const U32 other_oldest_recording_index = (other_current_recording_index + other_recording_slots - other_num_recordings + 1) % other_recording_slots;
+
+	// append first recording into our current slot
+	getCurRecording().appendRecording(other.mRecordingPeriods[other_oldest_recording_index]);
+
+	// from now on, add new recordings for everything after the first
+	U32 other_index = (other_oldest_recording_index + 1) % other_recording_slots;
 
 	if (mAutoResize)
 	{
-		S32 other_index = (other.mCurPeriod + 1) % other.mRecordingPeriods.size();
-		S32 end_index = (other.mCurPeriod) % other.mRecordingPeriods.size(); 
+		// append first recording into our current slot
+		getCurRecording().appendRecording(other.mRecordingPeriods[other_oldest_recording_index]);
 
-		do
+		// push back recordings for everything in the middle
+		U32 other_index = (other_oldest_recording_index + 1) % other_recording_slots;
+		while (other_index != other_current_recording_index)
 		{
-			if (other.mRecordingPeriods[other_index].getDuration().value())
-			{
-				mRecordingPeriods.push_back(other.mRecordingPeriods[other_index]);
-			}
-			other_index = (other_index + 1) % other.mRecordingPeriods.size();
+			mRecordingPeriods.push_back(other.mRecordingPeriods[other_index]);
+			other_index = (other_index + 1) % other_recording_slots;
+		}
+
+		// add final recording, if it wasn't already added as the first
+		if (other_num_recordings > 1)
+		{
+			mRecordingPeriods.push_back(other.mRecordingPeriods[other_current_recording_index]);
 		}
-		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());
+		size_t num_to_copy = llmin(	mRecordingPeriods.size(), other_num_recordings);
+
+		std::vector<Recording>::iterator src_it = other.mRecordingPeriods.begin() + other_index ;
 		std::vector<Recording>::iterator dest_it = mRecordingPeriods.begin() + mCurPeriod;
 
-		for(size_t i = 0; i < num_to_copy; i++)
+		// already consumed the first recording from other, so start counting at 1
+		for(size_t i = 1; i < num_to_copy; i++)
 		{
 			*dest_it = *src_it;
 
@@ -474,17 +487,14 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 		
 		// 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)
+		// advance to last recording period copied, and make that our current period
 		mCurPeriod = (mCurPeriod + num_to_copy - 1) % mRecordingPeriods.size();
-		mNumPeriods = llmin(mRecordingPeriods.size(), mNumPeriods + num_to_copy);
+		mNumPeriods = llmin(mRecordingPeriods.size(), mNumPeriods + num_to_copy - 1);
 	}
 
-	if (getCurRecording().getDuration().value())
-	{
-		//call this to chain last period copied to new active period
-		nextPeriod();
-	}
+	// end with fresh period, otherwise next appendPeriodicRecording() will merge the first
+	// recording period with the last one appended here
+	nextPeriod();
 	getCurRecording().setPlayState(getPlayState());
 }
 
-- 
cgit v1.2.3


From 1c51938babfa8c55c61b6b4cda34a7d22c1a427a Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 19 Jun 2013 20:35:13 -0700
Subject: BUILDFIX: size_t/u32 confusion

---
 indra/llcommon/lltracerecording.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 0fe95ee75f..d34434f161 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -464,7 +464,7 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 	}
 	else
 	{
-		size_t num_to_copy = llmin(	mRecordingPeriods.size(), other_num_recordings);
+		size_t num_to_copy = llmin(	mRecordingPeriods.size(), (size_t)other_num_recordings);
 
 		std::vector<Recording>::iterator src_it = other.mRecordingPeriods.begin() + other_index ;
 		std::vector<Recording>::iterator dest_it = mRecordingPeriods.begin() + mCurPeriod;
-- 
cgit v1.2.3


From 5de2f0a8970244866dc8b511caa3c8626955264f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 21 Jun 2013 10:58:44 -0700
Subject: SH-3931 FIX Interesting: Add graphs to visualize scene load metrics -
 potential fix for bad times

---
 indra/llcommon/lltracerecording.cpp | 1 +
 1 file changed, 1 insertion(+)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 33002929ea..52ecb463be 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -161,6 +161,7 @@ void Recording::update()
 	{
 		mBuffers.write()->flush();
 		LLTrace::get_thread_recorder()->bringUpToDate(this);
+		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
 		mSamplingTimer.reset();
 	}
 }
-- 
cgit v1.2.3


From fe3cfb30d504155850ddf3752d2f55e6311990d6 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sat, 22 Jun 2013 00:34:25 -0700
Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics
 removed LLTrace unit typedefs

---
 indra/llcommon/lltrace.h | 23 -----------------------
 1 file changed, 23 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index fb7ffb0a29..884a316a3b 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -44,29 +44,6 @@ namespace LLTrace
 {
 class Recording;
 
-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; }
 
-- 
cgit v1.2.3


From 8bddaeec6647e735415f9bd72a4e1313e11fe720 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sat, 22 Jun 2013 12:00:18 -0700
Subject: fixed scene load monitor resetting to eagerly due to spurious camer
 amotion pulled swap() out of ui time block cleaned up internal lltrace
 dependencies, factored out common accumulator definitions

---
 indra/llcommon/CMakeLists.txt            |   2 +
 indra/llcommon/llthread.cpp              |   4 +-
 indra/llcommon/llthreadlocalstorage.cpp  |   2 +
 indra/llcommon/llthreadlocalstorage.h    |  31 +-
 indra/llcommon/lltrace.cpp               |  24 --
 indra/llcommon/lltrace.h                 | 594 +---------------------------
 indra/llcommon/lltraceaccumulators.cpp   | 112 ++++++
 indra/llcommon/lltraceaccumulators.h     | 648 +++++++++++++++++++++++++++++++
 indra/llcommon/lltracerecording.cpp      | 113 +-----
 indra/llcommon/lltracerecording.h        |  29 +-
 indra/llcommon/lltracethreadrecorder.cpp | 108 +++---
 indra/llcommon/lltracethreadrecorder.h   |  45 +--
 12 files changed, 871 insertions(+), 841 deletions(-)
 create mode 100644 indra/llcommon/lltraceaccumulators.cpp
 create mode 100644 indra/llcommon/lltraceaccumulators.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index bf99a4c3a0..0c76fd46c0 100755
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -103,6 +103,7 @@ set(llcommon_SOURCE_FILES
     llthreadsafequeue.cpp
     lltimer.cpp
     lltrace.cpp
+    lltraceaccumulators.cpp
     lltracerecording.cpp
     lltracethreadrecorder.cpp
     lluri.cpp
@@ -231,6 +232,7 @@ set(llcommon_HEADER_FILES
     llthreadsafequeue.h
     lltimer.h
     lltrace.h
+	lltraceaccumulators.h
     lltracerecording.h
     lltracethreadrecorder.h
     lltreeiterators.h
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 118568d5ef..e8e546e769 100755
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -93,7 +93,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 {
 	LLThread *threadp = (LLThread *)datap;
 
-	LLTrace::ThreadRecorder* thread_recorder = new LLTrace::SlaveThreadRecorder(LLTrace::getUIThreadRecorder());
+	LLTrace::SlaveThreadRecorder thread_recorder(LLTrace::getUIThreadRecorder());
 
 #if !LL_DARWIN
 	sThreadID = threadp->mID;
@@ -107,8 +107,6 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 	// We're done with the run function, this thread is done executing now.
 	threadp->mStatus = STOPPED;
 
-	delete thread_recorder;
-
 	return NULL;
 }
 
diff --git a/indra/llcommon/llthreadlocalstorage.cpp b/indra/llcommon/llthreadlocalstorage.cpp
index 32d94331a6..03c306cc7f 100644
--- a/indra/llcommon/llthreadlocalstorage.cpp
+++ b/indra/llcommon/llthreadlocalstorage.cpp
@@ -88,6 +88,7 @@ void LLThreadLocalPointerBase::destroyStorage()
 	}
 }
 
+//static
 void LLThreadLocalPointerBase::initAllThreadLocalStorage()
 {
 	if (!sInitialized)
@@ -102,6 +103,7 @@ void LLThreadLocalPointerBase::initAllThreadLocalStorage()
 	}
 }
 
+//static
 void LLThreadLocalPointerBase::destroyAllThreadLocalStorage()
 {
 	if (sInitialized)
diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
index a15f9185b1..d6399d5131 100644
--- a/indra/llcommon/llthreadlocalstorage.h
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -145,7 +145,7 @@ public:
 #if LL_DARWIN
         pthread_setspecific(sInstanceKey, NULL);
 #else
-        sInstance = NULL;
+        sData.mInstance = NULL;
 #endif
 		setInitState(DELETED);
 	}
@@ -182,7 +182,7 @@ public:
                 llerrs << "Could not set thread local storage" << llendl;
             }
 #else
-			sInstance = instancep;
+			sData.mInstance = instancep;
 #endif
 			setInitState(INITIALIZING);
 			instancep->initSingleton();
@@ -197,7 +197,7 @@ public:
 #if LL_DARWIN
         return (DERIVED_TYPE*)pthread_getspecific(sInstanceKey);
 #else
-		return sInstance;
+		return sData.mInstance;
 #endif
 	}
 
@@ -247,7 +247,7 @@ private:
         createTLSInitState();
         return (EInitState)(int)pthread_getspecific(sInitStateKey);
 #else
-        return sInitState;
+        return sData.mInitState;
 #endif
     }
     
@@ -257,18 +257,21 @@ private:
         createTLSInitState();
         pthread_setspecific(sInitStateKey, (void*)state);
 #else
-        sInitState = state;
+        sData.mInitState = state;
 #endif
     }
 	LLThreadLocalSingleton(const LLThreadLocalSingleton& other);
 	virtual void initSingleton() {}
 
+	struct SingletonData
+	{
+		DERIVED_TYPE*	mInstance;
+		EInitState		mInitState;
+	};
 #ifdef LL_WINDOWS
-	static __declspec(thread) DERIVED_TYPE* sInstance;
-	static __declspec(thread) EInitState sInitState;
+	static __declspec(thread) SingletonData sData;
 #elif LL_LINUX
-	static __thread DERIVED_TYPE* sInstance;
-	static __thread EInitState sInitState;
+	static __thread SingletonData sData;
 #elif LL_DARWIN
     static pthread_key_t sInstanceKey;
     static pthread_key_t sInitStateKey;
@@ -277,16 +280,10 @@ private:
 
 #if LL_WINDOWS
 template<typename DERIVED_TYPE>
-__declspec(thread) DERIVED_TYPE* LLThreadLocalSingleton<DERIVED_TYPE>::sInstance = NULL;
-
-template<typename DERIVED_TYPE>
-__declspec(thread) typename LLThreadLocalSingleton<DERIVED_TYPE>::EInitState LLThreadLocalSingleton<DERIVED_TYPE>::sInitState = LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED;
+__declspec(thread) typename LLThreadLocalSingleton<DERIVED_TYPE>::SingletonData LLThreadLocalSingleton<DERIVED_TYPE>::sData = {NULL, LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED};
 #elif LL_LINUX
 template<typename DERIVED_TYPE>
-__thread DERIVED_TYPE* LLThreadLocalSingleton<DERIVED_TYPE>::sInstance = NULL;
-
-template<typename DERIVED_TYPE>
-__thread typename LLThreadLocalSingleton<DERIVED_TYPE>::EInitState LLThreadLocalSingleton<DERIVED_TYPE>::sInitState = LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED;
+__thread typename LLThreadLocalSingleton<DERIVED_TYPE>::SingletonData LLThreadLocalSingleton<DERIVED_TYPE>::sData = {NULL, LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED};
 #elif LL_DARWIN
 template<typename DERIVED_TYPE>
 pthread_key_t LLThreadLocalSingleton<DERIVED_TYPE>::sInstanceKey;
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 59a4b42c97..25807c7b2c 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -35,8 +35,6 @@ static S32 sInitializationCount = 0;
 namespace LLTrace
 {
 
-static MasterThreadRecorder* gUIThreadRecorder = NULL;
-
 void init()
 {
 	if (sInitializationCount++ == 0)
@@ -59,28 +57,6 @@ void cleanup()
 	}
 }
 
-MasterThreadRecorder& getUIThreadRecorder()
-{
-	llassert(gUIThreadRecorder != NULL);
-	return *gUIThreadRecorder;
-}
-
-LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder_ptr()
-{
-	static LLThreadLocalPointer<ThreadRecorder> s_thread_recorder;
-	return s_thread_recorder;
-}
-
-const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
-{
-	return get_thread_recorder_ptr();
-}
-
-void set_thread_recorder(ThreadRecorder* recorder)
-{
-	get_thread_recorder_ptr() = recorder;
-}
-
 
 TimeBlockTreeNode::TimeBlockTreeNode() 
 :	mBlock(NULL),
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index fb7ffb0a29..36a3eb8fe8 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -32,7 +32,7 @@
 
 #include "llmemory.h"
 #include "llrefcount.h"
-#include "llunit.h"
+#include "lltraceaccumulators.h"
 #include "llthreadlocalstorage.h"
 #include "lltimer.h"
 
@@ -80,185 +80,6 @@ void init();
 void cleanup();
 bool isInitialized();
 
-const LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder();
-void set_thread_recorder(class ThreadRecorder*);
-
-class MasterThreadRecorder& getUIThreadRecorder();
-
-template<typename ACCUMULATOR>
-class AccumulatorBuffer : public LLRefCount
-{
-	typedef AccumulatorBuffer<ACCUMULATOR> self_t;
-	static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64;
-private:
-	struct StaticAllocationMarker { };
-
-	AccumulatorBuffer(StaticAllocationMarker m)
-	:	mStorageSize(0),
-		mStorage(NULL)
-	{}
-
-public:
-
-	AccumulatorBuffer(const AccumulatorBuffer& other = *getDefaultBuffer())
-	:	mStorageSize(0),
-		mStorage(NULL)
-	{
-		resize(other.mStorageSize);
-		for (S32 i = 0; i < sNextStorageSlot; i++)
-		{
-			mStorage[i] = other.mStorage[i];
-		}
-	}
-
-	~AccumulatorBuffer()
-	{
-		if (isPrimary())
-		{
-			LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
-		}
-		delete[] mStorage;
-	}
-
-	LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index) 
-	{ 
-		return mStorage[index]; 
-	}
-
-	LL_FORCE_INLINE const ACCUMULATOR& operator[](size_t index) const
-	{ 
-		return mStorage[index]; 
-	}
-
-	void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, bool append = true)
-	{
-		llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot);
-		for (size_t i = 0; i < sNextStorageSlot; i++)
-		{
-			mStorage[i].addSamples(other.mStorage[i], append);
-		}
-	}
-
-	void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
-	{
-		llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot);
-		for (size_t i = 0; i < sNextStorageSlot; i++)
-		{
-			mStorage[i] = other.mStorage[i];
-		}
-	}
-
-	void reset(const AccumulatorBuffer<ACCUMULATOR>* other = NULL)
-	{
-		llassert(mStorageSize >= sNextStorageSlot);
-		for (size_t i = 0; i < sNextStorageSlot; i++)
-		{
-			mStorage[i].reset(other ? &other->mStorage[i] : NULL);
-		}
-	}
-
-	void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
-	{
-		llassert(mStorageSize >= sNextStorageSlot);
-		for (size_t i = 0; i < sNextStorageSlot; i++)
-		{
-			mStorage[i].flush(time_stamp);
-		}
-	}
-
-	void makePrimary()
-	{
-		LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(mStorage);
-	}
-
-	bool isPrimary() const
-	{
-		return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage;
-	}
-
-	LL_FORCE_INLINE static ACCUMULATOR* getPrimaryStorage() 
-	{ 
-		ACCUMULATOR* accumulator = LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance();
-		return accumulator ? accumulator : getDefaultBuffer()->mStorage;
-	}
-
-	// NOTE: this is not thread-safe.  We assume that slots are reserved in the main thread before any child threads are spawned
-	size_t reserveSlot()
-	{
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-		if (LLTrace::isInitialized())
-		{
-			llerrs << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << llendl;
-		}
-#endif
-		size_t next_slot = sNextStorageSlot++;
-		if (next_slot >= mStorageSize)
-		{
-			resize(mStorageSize + (mStorageSize >> 2));
-		}
-		llassert(mStorage && next_slot < mStorageSize);
-		return next_slot;
-	}
-
-	void resize(size_t new_size)
-	{
-		if (new_size <= mStorageSize) return;
-
-		ACCUMULATOR* old_storage = mStorage;
-		mStorage = new ACCUMULATOR[new_size];
-		if (old_storage)
-		{
-			for (S32 i = 0; i < mStorageSize; i++)
-			{
-				mStorage[i] = old_storage[i];
-			}
-		}
-		mStorageSize = new_size;
-		delete[] old_storage;
-
-		self_t* default_buffer = getDefaultBuffer();
-		if (this != default_buffer
-			&& new_size > default_buffer->size())
-		{
-			//NB: this is not thread safe, but we assume that all resizing occurs during static initialization
-			default_buffer->resize(new_size);
-		}
-	}
-
-	size_t size() const
-	{
-		return getNumIndices();
-	}
-
-	static size_t getNumIndices() 
-	{
-		return sNextStorageSlot;
-	}
-
-	static self_t* getDefaultBuffer()
-	{
-		static bool sInitialized = false;
-		if (!sInitialized)
-		{
-			// this buffer is allowed to leak so that trace calls from global destructors have somewhere to put their data
-			// so as not to trigger an access violation
-			sDefaultBuffer = new AccumulatorBuffer(StaticAllocationMarker());
-			sInitialized = true;
-			sDefaultBuffer->resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
-		}
-		return sDefaultBuffer;
-	}
-
-private:
-	ACCUMULATOR*	mStorage;
-	size_t			mStorageSize;
-	static size_t	sNextStorageSlot;
-	static self_t*	sDefaultBuffer;
-};
-
-template<typename ACCUMULATOR> size_t AccumulatorBuffer<ACCUMULATOR>::sNextStorageSlot = 0;
-template<typename ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>* AccumulatorBuffer<ACCUMULATOR>::sDefaultBuffer = NULL;
-
 template<typename ACCUMULATOR>
 class TraceType 
 :	 public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
@@ -290,344 +111,6 @@ protected:
 	const size_t		mAccumulatorIndex;
 };
 
-class EventAccumulator
-{
-public:
-	typedef F64 value_t;
-	typedef F64 mean_t;
-
-	EventAccumulator()
-	:	mSum(0),
-		mMin((std::numeric_limits<F64>::max)()),
-		mMax((std::numeric_limits<F64>::min)()),
-		mMean(0),
-		mVarianceSum(0),
-		mNumSamples(0),
-		mLastValue(0)
-	{}
-
-	void record(F64 value)
-	{
-		mNumSamples++;
-		mSum += value;
-		// NOTE: both conditions will hold on first pass through
-		if (value < mMin)
-		{
-			mMin = value;
-		}
-		if (value > mMax)
-		{
-			mMax = value;
-		}
-		F64 old_mean = mMean;
-		mMean += (value - old_mean) / (F64)mNumSamples;
-		mVarianceSum += (value - old_mean) * (value - mMean);
-		mLastValue = value;
-	}
-
-	void addSamples(const EventAccumulator& other, bool append)
-	{
-		if (other.mNumSamples)
-		{
-			mSum += other.mSum;
-
-			// NOTE: both conditions will hold first time through
-			if (other.mMin < mMin) { mMin = other.mMin; }
-			if (other.mMax > mMax) { mMax = other.mMax; }
-
-			// combine variance (and hence standard deviation) of 2 different sized sample groups using
-			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
-			F64 n_1 = (F64)mNumSamples,
-				n_2 = (F64)other.mNumSamples;
-			F64 m_1 = mMean,
-				m_2 = other.mMean;
-			F64 v_1 = mVarianceSum / mNumSamples,
-				v_2 = other.mVarianceSum / other.mNumSamples;
-			if (n_1 == 0)
-			{
-				mVarianceSum = other.mVarianceSum;
-			}
-			else if (n_2 == 0)
-			{
-				// don't touch variance
-				// mVarianceSum = mVarianceSum;
-			}
-			else
-			{
-				mVarianceSum = (F64)mNumSamples
-								* ((((n_1 - 1.f) * v_1)
-									+ ((n_2 - 1.f) * v_2)
-									+ (((n_1 * n_2) / (n_1 + n_2))
-										* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
-									/ (n_1 + n_2 - 1.f));
-			}
-
-			F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
-			mNumSamples += other.mNumSamples;
-			mMean = mMean * weight + other.mMean * (1.f - weight);
-			if (append) mLastValue = other.mLastValue;
-		}
-	}
-
-	void reset(const EventAccumulator* other)
-	{
-		mNumSamples = 0;
-		mSum = 0;
-		mMin = std::numeric_limits<F64>::max();
-		mMax = std::numeric_limits<F64>::min();
-		mMean = 0;
-		mVarianceSum = 0;
-		mLastValue = other ? other->mLastValue : 0;
-	}
-
-	void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {}
-
-	F64	getSum() const { return mSum; }
-	F64	getMin() const { return mMin; }
-	F64	getMax() const { return mMax; }
-	F64	getLastValue() const { return mLastValue; }
-	F64	getMean() const { return mMean; }
-	F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mNumSamples); }
-	U32 getSampleCount() const { return mNumSamples; }
-
-private:
-	F64	mSum,
-		mMin,
-		mMax,
-		mLastValue;
-
-	F64	mMean,
-		mVarianceSum;
-
-	U32	mNumSamples;
-};
-
-
-class SampleAccumulator
-{
-public:
-	typedef F64 value_t;
-	typedef F64 mean_t;
-
-	SampleAccumulator()
-	:	mSum(0),
-		mMin((std::numeric_limits<F64>::max)()),
-		mMax((std::numeric_limits<F64>::min)()),
-		mMean(0),
-		mVarianceSum(0),
-		mLastSampleTimeStamp(LLTimer::getTotalSeconds()),
-		mTotalSamplingTime(0),
-		mNumSamples(0),
-		mLastValue(0),
-		mHasValue(false)
-	{}
-
-	void sample(F64 value)
-	{
-		LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds();
-		LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp;
-		mLastSampleTimeStamp = time_stamp;
-
-		if (mHasValue)
-		{
-			mTotalSamplingTime += delta_time;
-			mSum += mLastValue * delta_time;
-
-			// NOTE: both conditions will hold first time through
-			if (value < mMin) { mMin = value; }
-			if (value > mMax) { mMax = value; }
-
-			F64 old_mean = mMean;
-			mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean);
-			mVarianceSum += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
-		}
-
-		mLastValue = value;
-		mNumSamples++;
-		mHasValue = true;
-	}
-
-	void addSamples(const SampleAccumulator& other, bool append)
-	{
-		if (other.mTotalSamplingTime)
-		{
-			mSum += other.mSum;
-
-			// NOTE: both conditions will hold first time through
-			if (other.mMin < mMin) { mMin = other.mMin; }
-			if (other.mMax > mMax) { mMax = other.mMax; }
-
-			// combine variance (and hence standard deviation) of 2 different sized sample groups using
-			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
-			F64 n_1 = mTotalSamplingTime,
-				n_2 = other.mTotalSamplingTime;
-			F64 m_1 = mMean,
-				m_2 = other.mMean;
-			F64 v_1 = mVarianceSum / mTotalSamplingTime,
-				v_2 = other.mVarianceSum / other.mTotalSamplingTime;
-			if (n_1 == 0)
-			{
-				mVarianceSum = other.mVarianceSum;
-			}
-			else if (n_2 == 0)
-			{
-				// variance is unchanged
-				// mVarianceSum = mVarianceSum;
-			}
-			else
-			{
-				mVarianceSum =	mTotalSamplingTime
-								* ((((n_1 - 1.f) * v_1)
-									+ ((n_2 - 1.f) * v_2)
-									+ (((n_1 * n_2) / (n_1 + n_2))
-										* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
-									/ (n_1 + n_2 - 1.f));
-			}
-
-			llassert(other.mTotalSamplingTime > 0);
-			F64 weight = mTotalSamplingTime / (mTotalSamplingTime + other.mTotalSamplingTime);
-			mNumSamples += other.mNumSamples;
-			mTotalSamplingTime += other.mTotalSamplingTime;
-			mMean = (mMean * weight) + (other.mMean * (1.0 - weight));
-			if (append)
-			{
-				mLastValue = other.mLastValue;
-				mLastSampleTimeStamp = other.mLastSampleTimeStamp;
-				mHasValue |= other.mHasValue;
-			}
-		}
-	}
-
-	void reset(const SampleAccumulator* other)
-	{
-		mNumSamples = 0;
-		mSum = 0;
-		mMin = std::numeric_limits<F64>::max();
-		mMax = std::numeric_limits<F64>::min();
-		mMean = other ? other->mLastValue : 0;
-		mVarianceSum = 0;
-		mLastSampleTimeStamp = LLTimer::getTotalSeconds();
-		mTotalSamplingTime = 0;
-		mLastValue = other ? other->mLastValue : 0;
-		mHasValue = other ? other->mHasValue : false;
-	}
-
-	void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
-	{
-		LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp;
-
-		if (mHasValue)
-		{
-			mSum += mLastValue * delta_time;
-			mTotalSamplingTime += delta_time;
-		}
-		mLastSampleTimeStamp = time_stamp;
-	}
-
-	F64	getSum() const { return mSum; }
-	F64	getMin() const { return mMin; }
-	F64	getMax() const { return mMax; }
-	F64	getLastValue() const { return mLastValue; }
-	F64	getMean() const { return mMean; }
-	F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mTotalSamplingTime); }
-	U32 getSampleCount() const { return mNumSamples; }
-
-private:
-	F64	mSum,
-		mMin,
-		mMax,
-		mLastValue;
-
-	bool mHasValue;
-
-	F64	mMean,
-		mVarianceSum;
-
-	LLUnitImplicit<F64, LLUnits::Seconds>	mLastSampleTimeStamp,
-											mTotalSamplingTime;
-
-	U32	mNumSamples;
-};
-
-class CountAccumulator
-{
-public:
-	typedef F64 value_t;
-	typedef F64 mean_t;
-
-	CountAccumulator()
-	:	mSum(0),
-		mNumSamples(0)
-	{}
-
-	void add(F64 value)
-	{
-		mNumSamples++;
-		mSum += value;
-	}
-
-	void addSamples(const CountAccumulator& other, bool /*append*/)
-	{
-		mSum += other.mSum;
-		mNumSamples += other.mNumSamples;
-	}
-
-	void reset(const CountAccumulator* other)
-	{
-		mNumSamples = 0;
-		mSum = 0;
-	}
-
-	void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {}
-
-	F64	getSum() const { return mSum; }
-
-	U32 getSampleCount() const { return mNumSamples; }
-
-private:
-	F64	mSum;
-
-	U32	mNumSamples;
-};
-
-class TimeBlockAccumulator
-{
-public:
-	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
-	struct CallCountFacet 
-	{
-		typedef U32 value_t;
-		typedef F32 mean_t;
-	};
-
-	struct SelfTimeFacet
-	{
-		typedef LLUnit<F64, LLUnits::Seconds> value_t;
-		typedef LLUnit<F64, LLUnits::Seconds> mean_t;
-	};
-
-	TimeBlockAccumulator();
-	void addSamples(const self_t& other, bool /*append*/);
-	void reset(const self_t* other);
-	void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {}
-
-	//
-	// members
-	//
-	U64							mStartTotalTimeCounter,
-								mTotalTimeCounter,
-								mSelfTimeCounter;
-	U32							mCalls;
-	class TimeBlock*			mParent;		// last acknowledged parent of this time block
-	class TimeBlock*			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
-
-};
 
 template<>
 class TraceType<TimeBlockAccumulator::CallCountFacet>
@@ -651,23 +134,6 @@ public:
 	{}
 };
 
-class TimeBlock;
-class TimeBlockTreeNode
-{
-public:
-	TimeBlockTreeNode();
-
-	void setParent(TimeBlock* parent);
-	TimeBlock* getParent() { return mParent; }
-
-	TimeBlock*					mBlock;
-	TimeBlock*					mParent;	
-	std::vector<TimeBlock*>		mChildren;
-	bool						mCollapsed;
-	bool						mNeedsSorting;
-};
-
-
 template <typename T = F64>
 class EventStatHandle
 :	public TraceType<EventAccumulator>
@@ -735,64 +201,6 @@ void add(CountStatHandle<T>& count, VALUE_T value)
 	count.getPrimaryAccumulator()->add(storage_value(converted_value));
 }
 
-
-struct MemStatAccumulator
-{
-	typedef MemStatAccumulator self_t;
-
-	// fake classes that allows us to view different facets of underlying statistic
-	struct AllocationCountFacet 
-	{
-		typedef U32 value_t;
-		typedef F32 mean_t;
-	};
-
-	struct DeallocationCountFacet 
-	{
-		typedef U32 value_t;
-		typedef F32 mean_t;
-	};
-
-	struct ChildMemFacet
-	{
-		typedef LLUnit<F64, LLUnits::Bytes> value_t;
-		typedef LLUnit<F64, LLUnits::Bytes> mean_t;
-	};
-
-	MemStatAccumulator()
-	:	mAllocatedCount(0),
-		mDeallocatedCount(0)
-	{}
-
-	void addSamples(const MemStatAccumulator& other, bool append)
-	{
-		mSize.addSamples(other.mSize, append);
-		mChildSize.addSamples(other.mChildSize, append);
-		mAllocatedCount += other.mAllocatedCount;
-		mDeallocatedCount += other.mDeallocatedCount;
-	}
-
-	void reset(const MemStatAccumulator* other)
-	{
-		mSize.reset(other ? &other->mSize : NULL);
-		mChildSize.reset(other ? &other->mChildSize : NULL);
-		mAllocatedCount = 0;
-		mDeallocatedCount = 0;
-	}
-
-	void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp) 
-	{
-		mSize.flush(time_stamp);
-		mChildSize.flush(time_stamp);
-	}
-
-	SampleAccumulator	mSize,
-						mChildSize;
-	int					mAllocatedCount,
-						mDeallocatedCount;
-};
-
-
 template<>
 class TraceType<MemStatAccumulator::AllocationCountFacet>
 :	public TraceType<MemStatAccumulator>
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
new file mode 100644
index 0000000000..5948696418
--- /dev/null
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -0,0 +1,112 @@
+/** 
+ * @file lltracesampler.cpp
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltraceaccumulators.h"
+#include "lltracethreadrecorder.h"
+
+namespace LLTrace
+{
+
+
+///////////////////////////////////////////////////////////////////////
+// AccumulatorBufferGroup
+///////////////////////////////////////////////////////////////////////
+
+AccumulatorBufferGroup::AccumulatorBufferGroup() 
+{}
+
+void AccumulatorBufferGroup::handOffTo(AccumulatorBufferGroup& other)
+{
+	other.mCounts.reset(&mCounts);
+	other.mSamples.reset(&mSamples);
+	other.mEvents.reset(&mEvents);
+	other.mStackTimers.reset(&mStackTimers);
+	other.mMemStats.reset(&mMemStats);
+}
+
+void AccumulatorBufferGroup::makePrimary()
+{
+	mCounts.makePrimary();
+	mSamples.makePrimary();
+	mEvents.makePrimary();
+	mStackTimers.makePrimary();
+	mMemStats.makePrimary();
+
+	ThreadRecorder* thread_recorder = get_thread_recorder().get();
+	AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers;
+	// update stacktimer parent pointers
+	for (S32 i = 0, end_i = mStackTimers.size(); i < end_i; i++)
+	{
+		TimeBlockTreeNode* tree_node = thread_recorder->getTimeBlockTreeNode(i);
+		if (tree_node)
+		{
+			timer_accumulator_buffer[i].mParent = tree_node->mParent;
+		}
+	}
+}
+
+bool AccumulatorBufferGroup::isPrimary() const
+{
+	return mCounts.isPrimary();
+}
+
+void AccumulatorBufferGroup::append( const AccumulatorBufferGroup& other )
+{
+	mCounts.addSamples(other.mCounts);
+	mSamples.addSamples(other.mSamples);
+	mEvents.addSamples(other.mEvents);
+	mMemStats.addSamples(other.mMemStats);
+	mStackTimers.addSamples(other.mStackTimers);
+}
+
+void AccumulatorBufferGroup::merge( const AccumulatorBufferGroup& other)
+{
+	mCounts.addSamples(other.mCounts, false);
+	mSamples.addSamples(other.mSamples, false);
+	mEvents.addSamples(other.mEvents, false);
+	mMemStats.addSamples(other.mMemStats, false);
+	// for now, hold out timers from merge, need to be displayed per thread
+	//mStackTimers.addSamples(other.mStackTimers, false);
+}
+
+void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other)
+{
+	mCounts.reset(other ? &other->mCounts : NULL);
+	mSamples.reset(other ? &other->mSamples : NULL);
+	mEvents.reset(other ? &other->mEvents : NULL);
+	mStackTimers.reset(other ? &other->mStackTimers : NULL);
+	mMemStats.reset(other ? &other->mMemStats : NULL);
+}
+
+void AccumulatorBufferGroup::flush()
+{
+	LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds();
+
+	mSamples.flush(time_stamp);
+}
+
+}
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
new file mode 100644
index 0000000000..7994dcc217
--- /dev/null
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -0,0 +1,648 @@
+/** 
+ * @file lltraceaccumulators.h
+ * @brief Storage for accumulating statistics
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRACEACCUMULATORS_H
+#define LL_LLTRACEACCUMULATORS_H
+
+
+#include "stdtypes.h"
+#include "llpreprocessor.h"
+#include "llunit.h"
+#include "lltimer.h"
+#include "llrefcount.h"
+
+namespace LLTrace
+{
+
+	template<typename ACCUMULATOR>
+	class AccumulatorBuffer : public LLRefCount
+	{
+		typedef AccumulatorBuffer<ACCUMULATOR> self_t;
+		static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64;
+	private:
+		struct StaticAllocationMarker { };
+
+		AccumulatorBuffer(StaticAllocationMarker m)
+		:	mStorageSize(0),
+			mStorage(NULL)
+		{}
+
+	public:
+
+		AccumulatorBuffer(const AccumulatorBuffer& other = *getDefaultBuffer())
+		:	mStorageSize(0),
+			mStorage(NULL)
+		{
+			resize(other.mStorageSize);
+			for (S32 i = 0; i < sNextStorageSlot; i++)
+			{
+				mStorage[i] = other.mStorage[i];
+			}
+		}
+
+		~AccumulatorBuffer()
+		{
+			if (isPrimary())
+			{
+				LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
+			}
+			delete[] mStorage;
+		}
+
+		LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index) 
+		{ 
+			return mStorage[index]; 
+		}
+
+		LL_FORCE_INLINE const ACCUMULATOR& operator[](size_t index) const
+		{ 
+			return mStorage[index]; 
+		}
+
+		void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, bool append = true)
+		{
+			llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot);
+			for (size_t i = 0; i < sNextStorageSlot; i++)
+			{
+				mStorage[i].addSamples(other.mStorage[i], append);
+			}
+		}
+
+		void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
+		{
+			llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot);
+			for (size_t i = 0; i < sNextStorageSlot; i++)
+			{
+				mStorage[i] = other.mStorage[i];
+			}
+		}
+
+		void reset(const AccumulatorBuffer<ACCUMULATOR>* other = NULL)
+		{
+			llassert(mStorageSize >= sNextStorageSlot);
+			for (size_t i = 0; i < sNextStorageSlot; i++)
+			{
+				mStorage[i].reset(other ? &other->mStorage[i] : NULL);
+			}
+		}
+
+		void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
+		{
+			llassert(mStorageSize >= sNextStorageSlot);
+			for (size_t i = 0; i < sNextStorageSlot; i++)
+			{
+				mStorage[i].flush(time_stamp);
+			}
+		}
+
+		void makePrimary()
+		{
+			LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(mStorage);
+		}
+
+		bool isPrimary() const
+		{
+			return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage;
+		}
+
+		LL_FORCE_INLINE static ACCUMULATOR* getPrimaryStorage() 
+		{ 
+			ACCUMULATOR* accumulator = LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance();
+			return accumulator ? accumulator : getDefaultBuffer()->mStorage;
+		}
+
+		// NOTE: this is not thread-safe.  We assume that slots are reserved in the main thread before any child threads are spawned
+		size_t reserveSlot()
+		{
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+			if (LLTrace::isInitialized())
+			{
+				llerrs << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << llendl;
+			}
+#endif
+			size_t next_slot = sNextStorageSlot++;
+			if (next_slot >= mStorageSize)
+			{
+				resize(mStorageSize + (mStorageSize >> 2));
+			}
+			llassert(mStorage && next_slot < mStorageSize);
+			return next_slot;
+		}
+
+		void resize(size_t new_size)
+		{
+			if (new_size <= mStorageSize) return;
+
+			ACCUMULATOR* old_storage = mStorage;
+			mStorage = new ACCUMULATOR[new_size];
+			if (old_storage)
+			{
+				for (S32 i = 0; i < mStorageSize; i++)
+				{
+					mStorage[i] = old_storage[i];
+				}
+			}
+			mStorageSize = new_size;
+			delete[] old_storage;
+
+			self_t* default_buffer = getDefaultBuffer();
+			if (this != default_buffer
+				&& new_size > default_buffer->size())
+			{
+				//NB: this is not thread safe, but we assume that all resizing occurs during static initialization
+				default_buffer->resize(new_size);
+			}
+		}
+
+		size_t size() const
+		{
+			return getNumIndices();
+		}
+
+		static size_t getNumIndices() 
+		{
+			return sNextStorageSlot;
+		}
+
+		static self_t* getDefaultBuffer()
+		{
+			static bool sInitialized = false;
+			if (!sInitialized)
+			{
+				// this buffer is allowed to leak so that trace calls from global destructors have somewhere to put their data
+				// so as not to trigger an access violation
+				sDefaultBuffer = new AccumulatorBuffer(StaticAllocationMarker());
+				sInitialized = true;
+				sDefaultBuffer->resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
+			}
+			return sDefaultBuffer;
+		}
+
+	private:
+		ACCUMULATOR*	mStorage;
+		size_t			mStorageSize;
+		static size_t	sNextStorageSlot;
+		static self_t*	sDefaultBuffer;
+	};
+
+	template<typename ACCUMULATOR> size_t AccumulatorBuffer<ACCUMULATOR>::sNextStorageSlot = 0;
+	template<typename ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>* AccumulatorBuffer<ACCUMULATOR>::sDefaultBuffer = NULL;
+
+
+	class EventAccumulator
+	{
+	public:
+		typedef F64 value_t;
+		typedef F64 mean_t;
+
+		EventAccumulator()
+		:	mSum(0),
+			mMin((std::numeric_limits<F64>::max)()),
+			mMax((std::numeric_limits<F64>::min)()),
+			mMean(0),
+			mVarianceSum(0),
+			mNumSamples(0),
+			mLastValue(0)
+		{}
+
+		void record(F64 value)
+		{
+			mNumSamples++;
+			mSum += value;
+			// NOTE: both conditions will hold on first pass through
+			if (value < mMin)
+			{
+				mMin = value;
+			}
+			if (value > mMax)
+			{
+				mMax = value;
+			}
+			F64 old_mean = mMean;
+			mMean += (value - old_mean) / (F64)mNumSamples;
+			mVarianceSum += (value - old_mean) * (value - mMean);
+			mLastValue = value;
+		}
+
+		void addSamples(const EventAccumulator& other, bool append)
+		{
+			if (other.mNumSamples)
+			{
+				mSum += other.mSum;
+
+				// NOTE: both conditions will hold first time through
+				if (other.mMin < mMin) { mMin = other.mMin; }
+				if (other.mMax > mMax) { mMax = other.mMax; }
+
+				// combine variance (and hence standard deviation) of 2 different sized sample groups using
+				// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+				F64 n_1 = (F64)mNumSamples,
+					n_2 = (F64)other.mNumSamples;
+				F64 m_1 = mMean,
+					m_2 = other.mMean;
+				F64 v_1 = mVarianceSum / mNumSamples,
+					v_2 = other.mVarianceSum / other.mNumSamples;
+				if (n_1 == 0)
+				{
+					mVarianceSum = other.mVarianceSum;
+				}
+				else if (n_2 == 0)
+				{
+					// don't touch variance
+					// mVarianceSum = mVarianceSum;
+				}
+				else
+				{
+					mVarianceSum = (F64)mNumSamples
+						* ((((n_1 - 1.f) * v_1)
+						+ ((n_2 - 1.f) * v_2)
+						+ (((n_1 * n_2) / (n_1 + n_2))
+						* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+						/ (n_1 + n_2 - 1.f));
+				}
+
+				F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
+				mNumSamples += other.mNumSamples;
+				mMean = mMean * weight + other.mMean * (1.f - weight);
+				if (append) mLastValue = other.mLastValue;
+			}
+		}
+
+		void reset(const EventAccumulator* other)
+		{
+			mNumSamples = 0;
+			mSum = 0;
+			mMin = std::numeric_limits<F64>::max();
+			mMax = std::numeric_limits<F64>::min();
+			mMean = 0;
+			mVarianceSum = 0;
+			mLastValue = other ? other->mLastValue : 0;
+		}
+
+		void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {}
+
+		F64	getSum() const { return mSum; }
+		F64	getMin() const { return mMin; }
+		F64	getMax() const { return mMax; }
+		F64	getLastValue() const { return mLastValue; }
+		F64	getMean() const { return mMean; }
+		F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mNumSamples); }
+		U32 getSampleCount() const { return mNumSamples; }
+
+	private:
+		F64	mSum,
+			mMin,
+			mMax,
+			mLastValue;
+
+		F64	mMean,
+			mVarianceSum;
+
+		U32	mNumSamples;
+	};
+
+
+	class SampleAccumulator
+	{
+	public:
+		typedef F64 value_t;
+		typedef F64 mean_t;
+
+		SampleAccumulator()
+		:	mSum(0),
+			mMin((std::numeric_limits<F64>::max)()),
+			mMax((std::numeric_limits<F64>::min)()),
+			mMean(0),
+			mVarianceSum(0),
+			mLastSampleTimeStamp(LLTimer::getTotalSeconds()),
+			mTotalSamplingTime(0),
+			mNumSamples(0),
+			mLastValue(0),
+			mHasValue(false)
+		{}
+
+		void sample(F64 value)
+		{
+			LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds();
+			LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp;
+			mLastSampleTimeStamp = time_stamp;
+
+			if (mHasValue)
+			{
+				mTotalSamplingTime += delta_time;
+				mSum += mLastValue * delta_time;
+
+				// NOTE: both conditions will hold first time through
+				if (value < mMin) { mMin = value; }
+				if (value > mMax) { mMax = value; }
+
+				F64 old_mean = mMean;
+				mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean);
+				mVarianceSum += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
+			}
+
+			mLastValue = value;
+			mNumSamples++;
+			mHasValue = true;
+		}
+
+		void addSamples(const SampleAccumulator& other, bool append)
+		{
+			if (other.mTotalSamplingTime)
+			{
+				mSum += other.mSum;
+
+				// NOTE: both conditions will hold first time through
+				if (other.mMin < mMin) { mMin = other.mMin; }
+				if (other.mMax > mMax) { mMax = other.mMax; }
+
+				// combine variance (and hence standard deviation) of 2 different sized sample groups using
+				// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+				F64 n_1 = mTotalSamplingTime,
+					n_2 = other.mTotalSamplingTime;
+				F64 m_1 = mMean,
+					m_2 = other.mMean;
+				F64 v_1 = mVarianceSum / mTotalSamplingTime,
+					v_2 = other.mVarianceSum / other.mTotalSamplingTime;
+				if (n_1 == 0)
+				{
+					mVarianceSum = other.mVarianceSum;
+				}
+				else if (n_2 == 0)
+				{
+					// variance is unchanged
+					// mVarianceSum = mVarianceSum;
+				}
+				else
+				{
+					mVarianceSum =	mTotalSamplingTime
+						* ((((n_1 - 1.f) * v_1)
+						+ ((n_2 - 1.f) * v_2)
+						+ (((n_1 * n_2) / (n_1 + n_2))
+						* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+						/ (n_1 + n_2 - 1.f));
+				}
+
+				llassert(other.mTotalSamplingTime > 0);
+				F64 weight = mTotalSamplingTime / (mTotalSamplingTime + other.mTotalSamplingTime);
+				mNumSamples += other.mNumSamples;
+				mTotalSamplingTime += other.mTotalSamplingTime;
+				mMean = (mMean * weight) + (other.mMean * (1.0 - weight));
+				if (append)
+				{
+					mLastValue = other.mLastValue;
+					mLastSampleTimeStamp = other.mLastSampleTimeStamp;
+					mHasValue |= other.mHasValue;
+				}
+			}
+		}
+
+		void reset(const SampleAccumulator* other)
+		{
+			mNumSamples = 0;
+			mSum = 0;
+			mMin = std::numeric_limits<F64>::max();
+			mMax = std::numeric_limits<F64>::min();
+			mMean = other ? other->mLastValue : 0;
+			mVarianceSum = 0;
+			mLastSampleTimeStamp = LLTimer::getTotalSeconds();
+			mTotalSamplingTime = 0;
+			mLastValue = other ? other->mLastValue : 0;
+			mHasValue = other ? other->mHasValue : false;
+		}
+
+		void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
+		{
+			LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp;
+
+			if (mHasValue)
+			{
+				mSum += mLastValue * delta_time;
+				mTotalSamplingTime += delta_time;
+			}
+			mLastSampleTimeStamp = time_stamp;
+		}
+
+		F64	getSum() const { return mSum; }
+		F64	getMin() const { return mMin; }
+		F64	getMax() const { return mMax; }
+		F64	getLastValue() const { return mLastValue; }
+		F64	getMean() const { return mMean; }
+		F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mTotalSamplingTime); }
+		U32 getSampleCount() const { return mNumSamples; }
+
+	private:
+		F64	mSum,
+			mMin,
+			mMax,
+			mLastValue;
+
+		bool mHasValue;
+
+		F64	mMean,
+			mVarianceSum;
+
+		LLUnitImplicit<F64, LLUnits::Seconds>	mLastSampleTimeStamp,
+			mTotalSamplingTime;
+
+		U32	mNumSamples;
+	};
+
+	class CountAccumulator
+	{
+	public:
+		typedef F64 value_t;
+		typedef F64 mean_t;
+
+		CountAccumulator()
+		:	mSum(0),
+			mNumSamples(0)
+		{}
+
+		void add(F64 value)
+		{
+			mNumSamples++;
+			mSum += value;
+		}
+
+		void addSamples(const CountAccumulator& other, bool /*append*/)
+		{
+			mSum += other.mSum;
+			mNumSamples += other.mNumSamples;
+		}
+
+		void reset(const CountAccumulator* other)
+		{
+			mNumSamples = 0;
+			mSum = 0;
+		}
+
+		void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {}
+
+		F64	getSum() const { return mSum; }
+
+		U32 getSampleCount() const { return mNumSamples; }
+
+	private:
+		F64	mSum;
+
+		U32	mNumSamples;
+	};
+
+	class TimeBlockAccumulator
+	{
+	public:
+		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
+		struct CallCountFacet 
+		{
+			typedef U32 value_t;
+			typedef F32 mean_t;
+		};
+
+		struct SelfTimeFacet
+		{
+			typedef LLUnit<F64, LLUnits::Seconds> value_t;
+			typedef LLUnit<F64, LLUnits::Seconds> mean_t;
+		};
+
+		TimeBlockAccumulator();
+		void addSamples(const self_t& other, bool /*append*/);
+		void reset(const self_t* other);
+		void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {}
+
+		//
+		// members
+		//
+		U64							mStartTotalTimeCounter,
+			mTotalTimeCounter,
+			mSelfTimeCounter;
+		U32							mCalls;
+		class TimeBlock*			mParent;		// last acknowledged parent of this time block
+		class TimeBlock*			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
+
+	};
+
+	class TimeBlock;
+	class TimeBlockTreeNode
+	{
+	public:
+		TimeBlockTreeNode();
+
+		void setParent(TimeBlock* parent);
+		TimeBlock* getParent() { return mParent; }
+
+		TimeBlock*					mBlock;
+		TimeBlock*					mParent;	
+		std::vector<TimeBlock*>		mChildren;
+		bool						mCollapsed;
+		bool						mNeedsSorting;
+	};
+
+	struct MemStatAccumulator
+	{
+		typedef MemStatAccumulator self_t;
+
+		// fake classes that allows us to view different facets of underlying statistic
+		struct AllocationCountFacet 
+		{
+			typedef U32 value_t;
+			typedef F32 mean_t;
+		};
+
+		struct DeallocationCountFacet 
+		{
+			typedef U32 value_t;
+			typedef F32 mean_t;
+		};
+
+		struct ChildMemFacet
+		{
+			typedef LLUnit<F64, LLUnits::Bytes> value_t;
+			typedef LLUnit<F64, LLUnits::Bytes> mean_t;
+		};
+
+		MemStatAccumulator()
+		:	mAllocatedCount(0),
+			mDeallocatedCount(0)
+		{}
+
+		void addSamples(const MemStatAccumulator& other, bool append)
+		{
+			mSize.addSamples(other.mSize, append);
+			mChildSize.addSamples(other.mChildSize, append);
+			mAllocatedCount += other.mAllocatedCount;
+			mDeallocatedCount += other.mDeallocatedCount;
+		}
+
+		void reset(const MemStatAccumulator* other)
+		{
+			mSize.reset(other ? &other->mSize : NULL);
+			mChildSize.reset(other ? &other->mChildSize : NULL);
+			mAllocatedCount = 0;
+			mDeallocatedCount = 0;
+		}
+
+		void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp) 
+		{
+			mSize.flush(time_stamp);
+			mChildSize.flush(time_stamp);
+		}
+
+		SampleAccumulator	mSize,
+			mChildSize;
+		int					mAllocatedCount,
+			mDeallocatedCount;
+	};
+
+	struct AccumulatorBufferGroup : public LLRefCount
+	{
+		AccumulatorBufferGroup();
+
+		void handOffTo(AccumulatorBufferGroup& other);
+		void makePrimary();
+		bool isPrimary() const;
+
+		void append(const AccumulatorBufferGroup& other);
+		void merge(const AccumulatorBufferGroup& other);
+		void reset(AccumulatorBufferGroup* other = NULL);
+		void flush();
+
+		AccumulatorBuffer<CountAccumulator>	 			mCounts;
+		AccumulatorBuffer<SampleAccumulator>			mSamples;
+		AccumulatorBuffer<EventAccumulator>				mEvents;
+		AccumulatorBuffer<TimeBlockAccumulator> 		mStackTimers;
+		AccumulatorBuffer<MemStatAccumulator> 			mMemStats;
+	};
+}
+
+#endif // LL_LLTRACEACCUMULATORS_H
+
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index ff1589d12d..c30f204fa4 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -33,85 +33,7 @@
 
 namespace LLTrace
 {
-
-
-///////////////////////////////////////////////////////////////////////
-// RecordingBuffers
-///////////////////////////////////////////////////////////////////////
-
-RecordingBuffers::RecordingBuffers() 
-{}
-
-void RecordingBuffers::handOffTo(RecordingBuffers& other)
-{
-	other.mCounts.reset(&mCounts);
-	other.mSamples.reset(&mSamples);
-	other.mEvents.reset(&mEvents);
-	other.mStackTimers.reset(&mStackTimers);
-	other.mMemStats.reset(&mMemStats);
-}
-
-void RecordingBuffers::makePrimary()
-{
-	mCounts.makePrimary();
-	mSamples.makePrimary();
-	mEvents.makePrimary();
-	mStackTimers.makePrimary();
-	mMemStats.makePrimary();
-
-	ThreadRecorder* thread_recorder = get_thread_recorder().get();
-	AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers;
-	// update stacktimer parent pointers
-	for (S32 i = 0, end_i = mStackTimers.size(); i < end_i; i++)
-	{
-		TimeBlockTreeNode* tree_node = thread_recorder->getTimeBlockTreeNode(i);
-		if (tree_node)
-		{
-			timer_accumulator_buffer[i].mParent = tree_node->mParent;
-		}
-	}
-}
-
-bool RecordingBuffers::isPrimary() const
-{
-	return mCounts.isPrimary();
-}
-
-void RecordingBuffers::append( const RecordingBuffers& other )
-{
-	mCounts.addSamples(other.mCounts);
-	mSamples.addSamples(other.mSamples);
-	mEvents.addSamples(other.mEvents);
-	mMemStats.addSamples(other.mMemStats);
-	mStackTimers.addSamples(other.mStackTimers);
-}
-
-void RecordingBuffers::merge( const RecordingBuffers& other)
-{
-	mCounts.addSamples(other.mCounts, false);
-	mSamples.addSamples(other.mSamples, false);
-	mEvents.addSamples(other.mEvents, false);
-	mMemStats.addSamples(other.mMemStats, false);
-	// for now, hold out timers from merge, need to be displayed per thread
-	//mStackTimers.addSamples(other.mStackTimers, false);
-}
-
-void RecordingBuffers::reset(RecordingBuffers* other)
-{
-	mCounts.reset(other ? &other->mCounts : NULL);
-	mSamples.reset(other ? &other->mSamples : NULL);
-	mEvents.reset(other ? &other->mEvents : NULL);
-	mStackTimers.reset(other ? &other->mStackTimers : NULL);
-	mMemStats.reset(other ? &other->mMemStats : NULL);
-}
-
-void RecordingBuffers::flush()
-{
-	LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds();
-
-	mSamples.flush(time_stamp);
-}
-
+	
 ///////////////////////////////////////////////////////////////////////
 // Recording
 ///////////////////////////////////////////////////////////////////////
@@ -119,7 +41,7 @@ void RecordingBuffers::flush()
 Recording::Recording() 
 :	mElapsedSeconds(0)
 {
-	mBuffers = new RecordingBuffers();
+	mBuffers = new AccumulatorBufferGroup();
 }
 
 Recording::Recording( const Recording& other )
@@ -132,11 +54,10 @@ 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();
+	const_cast<Recording&>(other).update();
 	EPlayState other_play_state = other.getPlayState();
 
-	mBuffers = mutable_other.mBuffers;
+	mBuffers = other.mBuffers;
 
 	LLStopWatchControlsMixin<Recording>::setPlayState(other_play_state);
 
@@ -151,7 +72,7 @@ Recording::~Recording()
 {
 	if (isStarted() && LLTrace::get_thread_recorder().notNull())
 	{
-		LLTrace::get_thread_recorder()->deactivate(this);
+		LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
 	}
 }
 
@@ -159,9 +80,11 @@ void Recording::update()
 {
 	if (isStarted())
 	{
-		mBuffers.write()->flush();
-		LLTrace::get_thread_recorder()->bringUpToDate(this);
 		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+		AccumulatorBufferGroup* buffers = mBuffers.write();
+		buffers->flush();
+		LLTrace::get_thread_recorder()->bringUpToDate(buffers);
+
 		mSamplingTimer.reset();
 	}
 }
@@ -177,14 +100,15 @@ void Recording::handleReset()
 void Recording::handleStart()
 {
 	mSamplingTimer.reset();
-	LLTrace::get_thread_recorder()->activate(this);
+	LLTrace::get_thread_recorder()->activate(mBuffers.write());
 }
 
 void Recording::handleStop()
 {
 	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
-	mBuffers.write()->flush();
-	LLTrace::get_thread_recorder()->deactivate(this);
+	AccumulatorBufferGroup* buffers = mBuffers.write();
+	buffers->flush();
+	LLTrace::get_thread_recorder()->deactivate(buffers);
 }
 
 void Recording::handleSplitTo(Recording& other)
@@ -192,19 +116,14 @@ void Recording::handleSplitTo(Recording& other)
 	mBuffers.write()->handOffTo(*other.mBuffers.write());
 }
 
-void Recording::appendRecording( const Recording& other )
+void Recording::appendRecording( Recording& other )
 {
 	update();
+	other.update();
 	mBuffers.write()->append(*other.mBuffers);
 	mElapsedSeconds += other.mElapsedSeconds;
 }
 
-void Recording::mergeRecording( const Recording& other)
-{
-	update();
-	mBuffers.write()->merge(*other.mBuffers);
-}
-
 LLUnit<F64, LLUnits::Seconds> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
@@ -711,8 +630,6 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat,
 
 void ExtendableRecording::extend()
 {
-	// stop recording to get latest data
-	mPotentialRecording.update();
 	// push the data back to accepted recording
 	mAcceptedRecording.appendRecording(mPotentialRecording);
 	// flush data, so we can start from scratch
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index b839e85de0..38eaa47f9f 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -32,7 +32,7 @@
 
 #include "llpointer.h"
 #include "lltimer.h"
-#include "lltrace.h"
+#include "lltraceaccumulators.h"
 
 class LLStopWatchControlsMixinCommon
 {
@@ -106,26 +106,6 @@ private:
 
 namespace LLTrace
 {
-	struct RecordingBuffers : public LLRefCount
-	{
-		RecordingBuffers();
-
-		void handOffTo(RecordingBuffers& other);
-		void makePrimary();
-		bool isPrimary() const;
-
-		void append(const RecordingBuffers& other);
-		void merge(const RecordingBuffers& other);
-		void reset(RecordingBuffers* other = NULL);
-		void flush();
-
-		AccumulatorBuffer<CountAccumulator>	 			mCounts;
-		AccumulatorBuffer<SampleAccumulator>			mSamples;
-		AccumulatorBuffer<EventAccumulator>				mEvents;
-		AccumulatorBuffer<TimeBlockAccumulator> 		mStackTimers;
-		AccumulatorBuffer<MemStatAccumulator> 			mMemStats;
-	};
-
 	class Recording 
 	:	public LLStopWatchControlsMixin<Recording>
 	{
@@ -138,10 +118,7 @@ namespace LLTrace
 		Recording& operator = (const Recording& other);
 
 		// accumulate data from subsequent, non-overlapping recording
-		void appendRecording(const Recording& other);
-
-		// gather data from recording, ignoring time relationship (for example, pulling data from slave threads)
-		void mergeRecording(const Recording& other);
+		void appendRecording(Recording& other);
 
 		// grab latest recorded data
 		void update();
@@ -291,7 +268,7 @@ namespace LLTrace
 
 		LLTimer				mSamplingTimer;
 		LLUnit<F64, LLUnits::Seconds>			mElapsedSeconds;
-		LLCopyOnWritePointer<RecordingBuffers>	mBuffers;
+		LLCopyOnWritePointer<AccumulatorBufferGroup>	mBuffers;
 	};
 
 	class LL_COMMON_API PeriodicRecording
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 54006f4e5b..c571e013e1 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -31,6 +31,7 @@
 namespace LLTrace
 {
 
+MasterThreadRecorder* gUIThreadRecorder = NULL;
 
 ///////////////////////////////////////////////////////////////////////
 // ThreadRecorder
@@ -49,7 +50,7 @@ ThreadRecorder::ThreadRecorder()
 	mNumTimeBlockTreeNodes = AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer()->size();
 	mTimeBlockTreeNodes = new TimeBlockTreeNode[mNumTimeBlockTreeNodes];
 
-	mThreadRecording.start();
+	activate(&mThreadRecordingBuffers);
 
 	// initialize time block parent pointers
 	for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(); 
@@ -72,6 +73,8 @@ ThreadRecorder::ThreadRecorder()
 
 ThreadRecorder::~ThreadRecorder()
 {
+	deactivate(&mThreadRecordingBuffers);
+
 	delete mRootTimer;
 
 	if (!mActiveRecordings.empty())
@@ -94,7 +97,7 @@ TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode(S32 index)
 }
 
 
-void ThreadRecorder::activate( Recording* recording )
+void ThreadRecorder::activate( AccumulatorBufferGroup* recording )
 {
 	ActiveRecording* active_recording = new ActiveRecording(recording);
 	if (!mActiveRecordings.empty())
@@ -106,7 +109,7 @@ void ThreadRecorder::activate( Recording* recording )
 	mActiveRecordings.back()->mPartialRecording.makePrimary();
 }
 
-ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringUpToDate( Recording* recording )
+ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringUpToDate( AccumulatorBufferGroup* recording )
 {
 	if (mActiveRecordings.empty()) return mActiveRecordings.rend();
 
@@ -148,7 +151,7 @@ ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringU
 	return it;
 }
 
-void ThreadRecorder::deactivate( Recording* recording )
+void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording )
 {
 	active_recording_list_t::reverse_iterator it = bringUpToDate(recording);
 	if (it != mActiveRecordings.rend())
@@ -168,14 +171,14 @@ void ThreadRecorder::deactivate( Recording* recording )
 	}
 }
 
-ThreadRecorder::ActiveRecording::ActiveRecording( Recording* target ) 
+ThreadRecorder::ActiveRecording::ActiveRecording( AccumulatorBufferGroup* target ) 
 :	mTargetRecording(target)
 {
 }
 
 void ThreadRecorder::ActiveRecording::movePartialToTarget()
 {
-	mTargetRecording->mBuffers.write()->append(mPartialRecording);
+	mTargetRecording->append(mPartialRecording);
 	// reset based on self to keep history
 	mPartialRecording.reset(&mPartialRecording);
 }
@@ -197,46 +200,14 @@ SlaveThreadRecorder::~SlaveThreadRecorder()
 }
 
 void SlaveThreadRecorder::pushToMaster()
-{
-	mThreadRecording.stop();
-	{
-		LLMutexLock(mMasterRecorder.getSlaveListMutex());
-		mSharedData.appendFrom(mThreadRecording);
+{ 
+	{ LLMutexLock lock(&mSharedRecordingMutex);	
+		mThreadRecordingBuffers.flush();
+		LLTrace::get_thread_recorder()->bringUpToDate(&mThreadRecordingBuffers);
+		mSharedRecordingBuffers.append(mThreadRecordingBuffers);
 	}
-	mThreadRecording.start();
-}
-
-void SlaveThreadRecorder::SharedData::appendFrom( const Recording& source )
-{
-	LLMutexLock lock(&mRecordingMutex);
-	appendRecording(source);
 }
 
-void SlaveThreadRecorder::SharedData::appendTo( Recording& sink )
-{
-	LLMutexLock lock(&mRecordingMutex);
-	sink.appendRecording(*this);
-}
-
-void SlaveThreadRecorder::SharedData::mergeFrom( const RecordingBuffers& source )
-{
-	LLMutexLock lock(&mRecordingMutex);
-	mBuffers.write()->merge(source);
-}
-
-void SlaveThreadRecorder::SharedData::mergeTo( RecordingBuffers& sink )
-{
-	LLMutexLock lock(&mRecordingMutex);
-	sink.merge(*mBuffers);
-}
-
-void SlaveThreadRecorder::SharedData::reset()
-{
-	LLMutexLock lock(&mRecordingMutex);
-	Recording::reset();
-}
-
-
 ///////////////////////////////////////////////////////////////////////
 // MasterThreadRecorder
 ///////////////////////////////////////////////////////////////////////
@@ -247,29 +218,30 @@ void MasterThreadRecorder::pullFromSlaveThreads()
 	LLFastTimer _(FTM_PULL_TRACE_DATA_FROM_SLAVES);
 	if (mActiveRecordings.empty()) return;
 
-	LLMutexLock lock(&mSlaveListMutex);
+	{ LLMutexLock lock(&mSlaveListMutex);
 
-	RecordingBuffers& target_recording_buffers = mActiveRecordings.back()->mPartialRecording;
-	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
-		it != end_it;
-		++it)
-	{
-		// ignore block timing info for now
-		(*it)->mSharedData.mergeTo(target_recording_buffers);
-		(*it)->mSharedData.reset();
+		AccumulatorBufferGroup& target_recording_buffers = mActiveRecordings.back()->mPartialRecording;
+		for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
+			it != end_it;
+			++it)
+		{ LLMutexLock lock(&(*it)->mSharedRecordingMutex);
+
+			target_recording_buffers.merge((*it)->mSharedRecordingBuffers);
+			(*it)->mSharedRecordingBuffers.reset();
+		}
 	}
 }
 
+// called by slave thread
 void MasterThreadRecorder::addSlaveThread( class SlaveThreadRecorder* child )
-{
-	LLMutexLock lock(&mSlaveListMutex);
+{ LLMutexLock lock(&mSlaveListMutex);
 
 	mSlaveThreadRecorders.push_back(child);
 }
 
+// called by slave thread
 void MasterThreadRecorder::removeSlaveThread( class SlaveThreadRecorder* child )
-{
-	LLMutexLock lock(&mSlaveListMutex);
+{ LLMutexLock lock(&mSlaveListMutex);
 
 	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
 		it != end_it;
@@ -289,4 +261,28 @@ void MasterThreadRecorder::pushToMaster()
 MasterThreadRecorder::MasterThreadRecorder()
 {}
 
+
+MasterThreadRecorder& getUIThreadRecorder()
+{
+	llassert(gUIThreadRecorder != NULL);
+	return *gUIThreadRecorder;
+}
+
+LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder_ptr()
+{
+	static LLThreadLocalPointer<ThreadRecorder> s_thread_recorder;
+	return s_thread_recorder;
+}
+
+const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
+{
+	return get_thread_recorder_ptr();
+}
+
+void set_thread_recorder(ThreadRecorder* recorder)
+{
+	get_thread_recorder_ptr() = recorder;
+}
+
+
 }
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index bf3701304f..0680c2c590 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -31,7 +31,8 @@
 #include "llpreprocessor.h"
 
 #include "llmutex.h"
-#include "lltracerecording.h"
+#include "lltraceaccumulators.h"
+#include "llthreadlocalstorage.h"
 
 namespace LLTrace
 {
@@ -45,9 +46,9 @@ namespace LLTrace
 
 		virtual ~ThreadRecorder();
 
-		void activate(Recording* recording);
-		void deactivate(Recording* recording);
-		active_recording_list_t::reverse_iterator bringUpToDate(Recording* recording);
+		void activate(AccumulatorBufferGroup* recording);
+		void deactivate(AccumulatorBufferGroup* recording);
+		active_recording_list_t::reverse_iterator bringUpToDate(AccumulatorBufferGroup* recording);
 
 		virtual void pushToMaster() = 0;
 
@@ -56,14 +57,14 @@ namespace LLTrace
 	protected:
 		struct ActiveRecording
 		{
-			ActiveRecording(Recording* target);
+			ActiveRecording(AccumulatorBufferGroup* target);
 
-			Recording*			mTargetRecording;
-			RecordingBuffers	mPartialRecording;
+			AccumulatorBufferGroup*	mTargetRecording;
+			AccumulatorBufferGroup	mPartialRecording;
 
 			void movePartialToTarget();
 		};
-		Recording					mThreadRecording;
+		AccumulatorBufferGroup			mThreadRecordingBuffers;
 
 		active_recording_list_t		mActiveRecordings;
 
@@ -85,9 +86,6 @@ namespace LLTrace
 		// call this periodically to gather stats data from slave threads
 		void pullFromSlaveThreads();
 
-		LLMutex* getSlaveListMutex() { return &mSlaveListMutex; }
-
-
 	private:
 
 		typedef std::list<class SlaveThreadRecorder*> slave_thread_recorder_list_t;
@@ -105,22 +103,21 @@ namespace LLTrace
 		// call this periodically to gather stats data for master thread to consume
 		/*virtual*/ void pushToMaster();
 
+	private:
+		friend class MasterThreadRecorder;
 		MasterThreadRecorder* 	mMaster;
-
-		class SharedData : public Recording
-		{
-		public:
-			void appendFrom(const Recording& source);
-			void appendTo(Recording& sink);
-			void mergeFrom(const RecordingBuffers& source);
-			void mergeTo(RecordingBuffers& sink);
-			void reset();
-		private:
-			LLMutex		mRecordingMutex;
-		};
-		SharedData				mSharedData;
+		LLMutex					mSharedRecordingMutex;
+		AccumulatorBufferGroup	mSharedRecordingBuffers;
 		MasterThreadRecorder&	mMasterRecorder;
 	};
+
+	//FIXME: let user code set up thread recorder topology
+	extern MasterThreadRecorder* gUIThreadRecorder ;
+
+	const LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder();
+	void set_thread_recorder(class ThreadRecorder*);
+	class MasterThreadRecorder& getUIThreadRecorder();
+
 }
 
 #endif // LL_LLTRACETHREADRECORDER_H
-- 
cgit v1.2.3


From 808d3eff198d65e5a870abb670786935fc8356bd Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 27 Jun 2013 00:07:21 -0700
Subject: SH-4299 WIP: Interesting: High fps shown temporarily off scale in
 statistics console fixed some lltrace logic errors more consistent syncing of
 timestamps of sample values in recording stack selection of primary buffers
 was completely incorrect assignment of recordings got wrong play state due to
 implicit operator = defined in base class fixed asset stats only working up
 to the first send

---
 indra/llcommon/llfasttimer.h             |  7 ----
 indra/llcommon/lltraceaccumulators.cpp   | 15 +++++++--
 indra/llcommon/lltraceaccumulators.h     | 37 ++++++++++++++-------
 indra/llcommon/lltracerecording.cpp      |  7 ++--
 indra/llcommon/lltracerecording.h        |  6 ++++
 indra/llcommon/lltracethreadrecorder.cpp | 57 ++++++++++++++++++++------------
 indra/llcommon/lltracethreadrecorder.h   |  2 +-
 7 files changed, 84 insertions(+), 47 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 642c99ccce..ab8612a8ad 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -38,13 +38,6 @@ class LLMutex;
 namespace LLTrace
 {
 
-struct BlockTimerStackRecord
-{
-	class BlockTimer*	mActiveTimer;
-	class TimeBlock*	mTimeBlock;
-	U64					mChildTime;
-};
-
 class ThreadTimerStack 
 :	public BlockTimerStackRecord, 
 	public LLThreadLocalSingleton<ThreadTimerStack>
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index 5948696418..950c1d97d1 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -69,6 +69,16 @@ void AccumulatorBufferGroup::makePrimary()
 	}
 }
 
+//static
+void AccumulatorBufferGroup::clearPrimary()
+{
+	AccumulatorBuffer<CountAccumulator>::clearPrimary();	
+	AccumulatorBuffer<SampleAccumulator>::clearPrimary();
+	AccumulatorBuffer<EventAccumulator>::clearPrimary();
+	AccumulatorBuffer<TimeBlockAccumulator>::clearPrimary();
+	AccumulatorBuffer<MemStatAccumulator>::clearPrimary();
+}
+
 bool AccumulatorBufferGroup::isPrimary() const
 {
 	return mCounts.isPrimary();
@@ -102,11 +112,12 @@ void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other)
 	mMemStats.reset(other ? &other->mMemStats : NULL);
 }
 
-void AccumulatorBufferGroup::flush()
+void AccumulatorBufferGroup::sync()
 {
 	LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds();
 
-	mSamples.flush(time_stamp);
+	mSamples.sync(time_stamp);
+	mMemStats.sync(time_stamp);
 }
 
 }
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 7994dcc217..825cc9e3a8 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -109,12 +109,12 @@ namespace LLTrace
 			}
 		}
 
-		void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
+		void sync(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
 		{
 			llassert(mStorageSize >= sNextStorageSlot);
 			for (size_t i = 0; i < sNextStorageSlot; i++)
 			{
-				mStorage[i].flush(time_stamp);
+				mStorage[i].sync(time_stamp);
 			}
 		}
 
@@ -128,6 +128,11 @@ namespace LLTrace
 			return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage;
 		}
 
+		static void clearPrimary()
+		{
+			LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
+		}
+
 		LL_FORCE_INLINE static ACCUMULATOR* getPrimaryStorage() 
 		{ 
 			ACCUMULATOR* accumulator = LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance();
@@ -302,7 +307,7 @@ namespace LLTrace
 			mLastValue = other ? other->mLastValue : 0;
 		}
 
-		void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {}
+		void sync(LLUnitImplicit<F64, LLUnits::Seconds>) {}
 
 		F64	getSum() const { return mSum; }
 		F64	getMin() const { return mMin; }
@@ -434,7 +439,7 @@ namespace LLTrace
 			mHasValue = other ? other->mHasValue : false;
 		}
 
-		void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
+		void sync(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
 		{
 			LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp;
 
@@ -500,7 +505,7 @@ namespace LLTrace
 			mSum = 0;
 		}
 
-		void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {}
+		void sync(LLUnitImplicit<F64, LLUnits::Seconds>) {}
 
 		F64	getSum() const { return mSum; }
 
@@ -535,7 +540,7 @@ namespace LLTrace
 		TimeBlockAccumulator();
 		void addSamples(const self_t& other, bool /*append*/);
 		void reset(const self_t* other);
-		void flush(LLUnitImplicit<F64, LLUnits::Seconds>) {}
+		void sync(LLUnitImplicit<F64, LLUnits::Seconds>) {}
 
 		//
 		// members
@@ -566,6 +571,13 @@ namespace LLTrace
 		bool						mCollapsed;
 		bool						mNeedsSorting;
 	};
+	
+	struct BlockTimerStackRecord
+	{
+		class BlockTimer*	mActiveTimer;
+		class TimeBlock*	mTimeBlock;
+		U64					mChildTime;
+	};
 
 	struct MemStatAccumulator
 	{
@@ -611,16 +623,16 @@ namespace LLTrace
 			mDeallocatedCount = 0;
 		}
 
-		void flush(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp) 
+		void sync(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp) 
 		{
-			mSize.flush(time_stamp);
-			mChildSize.flush(time_stamp);
+			mSize.sync(time_stamp);
+			mChildSize.sync(time_stamp);
 		}
 
 		SampleAccumulator	mSize,
-			mChildSize;
+							mChildSize;
 		int					mAllocatedCount,
-			mDeallocatedCount;
+							mDeallocatedCount;
 	};
 
 	struct AccumulatorBufferGroup : public LLRefCount
@@ -630,11 +642,12 @@ namespace LLTrace
 		void handOffTo(AccumulatorBufferGroup& other);
 		void makePrimary();
 		bool isPrimary() const;
+		static void clearPrimary();
 
 		void append(const AccumulatorBufferGroup& other);
 		void merge(const AccumulatorBufferGroup& other);
 		void reset(AccumulatorBufferGroup* other = NULL);
-		void flush();
+		void sync();
 
 		AccumulatorBuffer<CountAccumulator>	 			mCounts;
 		AccumulatorBuffer<SampleAccumulator>			mSamples;
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index c30f204fa4..0938317eaa 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -59,11 +59,12 @@ Recording& Recording::operator = (const Recording& other)
 
 	mBuffers = other.mBuffers;
 
-	LLStopWatchControlsMixin<Recording>::setPlayState(other_play_state);
-
 	// above call will clear mElapsedSeconds as a side effect, so copy it here
 	mElapsedSeconds = other.mElapsedSeconds;
 	mSamplingTimer = other.mSamplingTimer;
+
+	setPlayState(other_play_state);
+
 	return *this;
 }
 
@@ -82,7 +83,6 @@ void Recording::update()
 	{
 		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
 		AccumulatorBufferGroup* buffers = mBuffers.write();
-		buffers->flush();
 		LLTrace::get_thread_recorder()->bringUpToDate(buffers);
 
 		mSamplingTimer.reset();
@@ -107,7 +107,6 @@ void Recording::handleStop()
 {
 	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
 	AccumulatorBufferGroup* buffers = mBuffers.write();
-	buffers->flush();
 	LLTrace::get_thread_recorder()->deactivate(buffers);
 }
 
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 38eaa47f9f..355dbabb1c 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -81,6 +81,7 @@ class LLStopWatchControlsMixin
 :	public LLStopWatchControlsMixinCommon
 {
 public:
+
 	typedef LLStopWatchControlsMixin<DERIVED> self_t;
 	virtual void splitTo(DERIVED& other)
 	{
@@ -98,6 +99,11 @@ public:
 		static_cast<self_t&>(other).handleSplitTo(*static_cast<DERIVED*>(this));
 	}
 private:
+	self_t& operator = (const self_t& other)
+	{
+		// don't do anything, derived class must implement logic
+	}
+
 	// atomically stop this object while starting the other
 	// no data can be missed in between stop and start
 	virtual void handleSplitTo(DERIVED& other) {};
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index c571e013e1..7192564c94 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -87,7 +87,7 @@ ThreadRecorder::~ThreadRecorder()
 	delete[] mTimeBlockTreeNodes;
 }
 
-TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode(S32 index)
+TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode( S32 index )
 {
 	if (0 <= index && index < mNumTimeBlockTreeNodes)
 	{
@@ -99,10 +99,20 @@ TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode(S32 index)
 
 void ThreadRecorder::activate( AccumulatorBufferGroup* recording )
 {
+	active_recording_list_t::reverse_iterator it, end_it;
+	for (it = mActiveRecordings.rbegin(), end_it = mActiveRecordings.rend();
+		it != end_it;
+		++it)
+	{
+		llassert((*it)->mTargetRecording != recording);
+	}
+
 	ActiveRecording* active_recording = new ActiveRecording(recording);
 	if (!mActiveRecordings.empty())
 	{
-		mActiveRecordings.back()->mPartialRecording.handOffTo(active_recording->mPartialRecording);
+		AccumulatorBufferGroup& prev_active_recording = mActiveRecordings.back()->mPartialRecording;
+		prev_active_recording.sync();
+		prev_active_recording.handOffTo(active_recording->mPartialRecording);
 	}
 	mActiveRecordings.push_back(active_recording);
 
@@ -113,7 +123,7 @@ ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringU
 {
 	if (mActiveRecordings.empty()) return mActiveRecordings.rend();
 
-	mActiveRecordings.back()->mPartialRecording.flush();
+	mActiveRecordings.back()->mPartialRecording.sync();
 	TimeBlock::updateTimes();
 
 	active_recording_list_t::reverse_iterator it, end_it;
@@ -156,18 +166,22 @@ void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording )
 	active_recording_list_t::reverse_iterator it = bringUpToDate(recording);
 	if (it != mActiveRecordings.rend())
 	{
-		// and if we've found the recording we wanted to update
-		active_recording_list_t::reverse_iterator next_it = it;
-		++next_it;
-		if (next_it != mActiveRecordings.rend())
-		{
-			(*next_it)->mPartialRecording.makePrimary();
-		}
-
 		active_recording_list_t::iterator recording_to_remove = (++it).base();
+		bool was_primary = (*recording_to_remove)->mPartialRecording.isPrimary();
 		llassert((*recording_to_remove)->mTargetRecording == recording);
 		delete *recording_to_remove;
 		mActiveRecordings.erase(recording_to_remove);
+		if (was_primary)
+		{
+			if (mActiveRecordings.empty())
+			{
+				AccumulatorBufferGroup::clearPrimary();
+			}
+			else
+			{
+				mActiveRecordings.back()->mPartialRecording.makePrimary();
+			}
+		}
 	}
 }
 
@@ -202,7 +216,6 @@ SlaveThreadRecorder::~SlaveThreadRecorder()
 void SlaveThreadRecorder::pushToMaster()
 { 
 	{ LLMutexLock lock(&mSharedRecordingMutex);	
-		mThreadRecordingBuffers.flush();
 		LLTrace::get_thread_recorder()->bringUpToDate(&mThreadRecordingBuffers);
 		mSharedRecordingBuffers.append(mThreadRecordingBuffers);
 	}
@@ -213,23 +226,25 @@ void SlaveThreadRecorder::pushToMaster()
 ///////////////////////////////////////////////////////////////////////
 
 static LLFastTimer::DeclareTimer FTM_PULL_TRACE_DATA_FROM_SLAVES("Pull slave trace data");
+
 void MasterThreadRecorder::pullFromSlaveThreads()
 {
-	LLFastTimer _(FTM_PULL_TRACE_DATA_FROM_SLAVES);
+	/*LLFastTimer _(FTM_PULL_TRACE_DATA_FROM_SLAVES);
 	if (mActiveRecordings.empty()) return;
 
 	{ LLMutexLock lock(&mSlaveListMutex);
 
-		AccumulatorBufferGroup& target_recording_buffers = mActiveRecordings.back()->mPartialRecording;
-		for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
-			it != end_it;
-			++it)
-		{ LLMutexLock lock(&(*it)->mSharedRecordingMutex);
+	AccumulatorBufferGroup& target_recording_buffers = mActiveRecordings.back()->mPartialRecording;
+	target_recording_buffers.sync();
+	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
+	it != end_it;
+	++it)
+	{ LLMutexLock lock(&(*it)->mSharedRecordingMutex);
 
-			target_recording_buffers.merge((*it)->mSharedRecordingBuffers);
-			(*it)->mSharedRecordingBuffers.reset();
-		}
+	target_recording_buffers.merge((*it)->mSharedRecordingBuffers);
+	(*it)->mSharedRecordingBuffers.reset();
 	}
+	}*/
 }
 
 // called by slave thread
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 0680c2c590..6b7a8e5865 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -71,6 +71,7 @@ namespace LLTrace
 		class BlockTimer*			mRootTimer;
 		TimeBlockTreeNode*			mTimeBlockTreeNodes;
 		size_t						mNumTimeBlockTreeNodes;
+		BlockTimerStackRecord		mBlockTimerStackRecord;
 	};
 
 	class LL_COMMON_API MasterThreadRecorder : public ThreadRecorder
@@ -105,7 +106,6 @@ namespace LLTrace
 
 	private:
 		friend class MasterThreadRecorder;
-		MasterThreadRecorder* 	mMaster;
 		LLMutex					mSharedRecordingMutex;
 		AccumulatorBufferGroup	mSharedRecordingBuffers;
 		MasterThreadRecorder&	mMasterRecorder;
-- 
cgit v1.2.3


From ffa7123bb5187e1da491a8f475d696053d9c9ee4 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 28 Jun 2013 20:45:20 -0700
Subject: SH-4299 FIX Interesting: High fps shown temporarily off scale in
 statistics console added ability to force uniqueness of LLCopyOnWritePointer
 converted more variables to units added convenience function for unit
 constants

---
 indra/llcommon/llfasttimer.cpp           |  4 +-
 indra/llcommon/llpointer.h               | 18 +++++++--
 indra/llcommon/lltracerecording.cpp      |  5 ++-
 indra/llcommon/lltracethreadrecorder.cpp |  8 ----
 indra/llcommon/llunit.h                  | 68 +++++++++++++++++++-------------
 5 files changed, 61 insertions(+), 42 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 60c451b137..23e27622bf 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -386,7 +386,7 @@ void TimeBlock::dumpCurTimes()
 		U32 num_calls = last_frame_recording.getSum(timerp->callCount());
 
 		// Don't bother with really brief times, keep output concise
-		if (total_time < LLUnit<F32, LLUnits::Milliseconds>(0.1)) continue;
+		if (total_time < LLUnits::Milliseconds::fromValue(0.1f)) continue;
 
 		std::ostringstream out_str;
 		TimeBlock* parent_timerp = timerp;
@@ -397,7 +397,7 @@ void TimeBlock::dumpCurTimes()
 		}
 
 		out_str << timerp->getName() << " " 
-			<< std::setprecision(3) << total_time.getAs<LLUnits::Milliseconds>() << " ms, "
+			<< std::setprecision(3) << total_time.valueAs<LLUnits::Milliseconds>() << " ms, "
 			<< num_calls << " calls";
 
 		llinfos << out_str.str() << llendl;
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index 6a0a8fcb0d..c827996db1 100755
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -173,15 +173,23 @@ public:
     typedef LLPointer<Type> pointer_t;
     
 	LLCopyOnWritePointer() 
+	:	mStayUnique(false)
 	{}
 
 	LLCopyOnWritePointer(Type* ptr) 
-	:	LLPointer<Type>(ptr)
+	:	LLPointer<Type>(ptr),
+		mStayUnique(false)
 	{}
 
 	LLCopyOnWritePointer(LLPointer<Type>& ptr)
-	:	LLPointer<Type>(ptr)
-	{}
+	:	LLPointer<Type>(ptr),
+		mStayUnique(false)
+	{
+		if (ptr.mForceUnique)
+		{
+			makeUnique();
+		}
+	}
 
 	Type* write()
 	{
@@ -199,6 +207,10 @@ public:
 
 	const Type*	operator->() const	{ return pointer_t::mPointer; }
 	const Type&	operator*() const	{ return *pointer_t::mPointer; }
+
+	void setStayUnique(bool stay) { makeUnique(); mStayUnique = stay; }
+private:
+	bool mStayUnique;
 };
 
 #endif
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 0938317eaa..f1388e7935 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -100,14 +100,15 @@ void Recording::handleReset()
 void Recording::handleStart()
 {
 	mSamplingTimer.reset();
+	mBuffers.setStayUnique(true);
 	LLTrace::get_thread_recorder()->activate(mBuffers.write());
 }
 
 void Recording::handleStop()
 {
 	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
-	AccumulatorBufferGroup* buffers = mBuffers.write();
-	LLTrace::get_thread_recorder()->deactivate(buffers);
+	LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
+	mBuffers.setStayUnique(false);
 }
 
 void Recording::handleSplitTo(Recording& other)
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 7192564c94..d0f0328d1c 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -99,14 +99,6 @@ TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode( S32 index )
 
 void ThreadRecorder::activate( AccumulatorBufferGroup* recording )
 {
-	active_recording_list_t::reverse_iterator it, end_it;
-	for (it = mActiveRecordings.rbegin(), end_it = mActiveRecordings.rend();
-		it != end_it;
-		++it)
-	{
-		llassert((*it)->mTargetRecording != recording);
-	}
-
 	ActiveRecording* active_recording = new ActiveRecording(recording);
 	if (!mActiveRecordings.empty())
 	{
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 2402cdbb95..c9bbed5574 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -75,17 +75,11 @@ struct LLUnit
 	}
 
 	template<typename NEW_UNIT_TYPE> 
-	STORAGE_TYPE getAs()
+	STORAGE_TYPE valueAs()
 	{
 		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;
@@ -181,6 +175,7 @@ LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ..
 	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();
@@ -493,26 +488,45 @@ struct LLUnitInverseLinearOps
 	}
 };
 
-#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 S1, typename S2>                                                              \
-void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)                \
-{                                                                                               \
-	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; }                                         \
+	template<typename T>                                                                             \
+	static LLUnit<T, base_unit_name> fromValue(T value) { return LLUnit<T, base_unit_name>(value); } \
+	template<typename STORAGE_T, typename UNIT_T>                                                    \
+	static LLUnit<STORAGE_T, base_unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)              \
+	{ return LLUnit<STORAGE_T, base_unit_name>(value); }                                             \
+};                                                                                                   \
+template<typename T> std::ostream& operator<<(std::ostream& s, const LLUnit<T, base_unit_name>& val) \
+{ s << val.value() << base_unit_name::getUnitLabel; return s; }
+
+
+#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 T>                                                                         \
+	static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); }		 \
+	template<typename STORAGE_T, typename UNIT_T>                                                \
+	static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)				 \
+	{ return LLUnit<STORAGE_T, unit_name>(value); }												 \
+};                                                                                               \
+template<typename T> std::ostream& operator<<(std::ostream& s, const LLUnit<T, unit_name>& val)  \
+{ s << val.value() << unit_name::getUnitLabel; return s; }                                       \
+	                                                                                             \
+template<typename S1, typename S2>                                                               \
+void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)                 \
+{                                                                                                \
+	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;              \
 }                                                                                               
 
 //
-- 
cgit v1.2.3


From 2fc422f39ddaca25c69e8cf2092a9d66840379f3 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sun, 30 Jun 2013 13:32:34 -0700
Subject: fixed memory leak due to implementation of LLThreadLocalSingleton
 removed LLThreadLocalSingleton collapsed all thread recorder classes to
 single type, LLTrace::ThreadRecorder moved fasttimer stack head to
 llthreadlocalsingletonpointer via ThreadRecorder

---
 indra/llcommon/llfasttimer.cpp           |  11 +-
 indra/llcommon/llfasttimer.h             |  23 +----
 indra/llcommon/llqueuedthread.cpp        |   4 +-
 indra/llcommon/llthread.cpp              |   2 +-
 indra/llcommon/llthreadlocalstorage.h    | 169 -------------------------------
 indra/llcommon/lltrace.cpp               |   2 +-
 indra/llcommon/lltracethreadrecorder.cpp | 117 +++++++++++----------
 indra/llcommon/lltracethreadrecorder.h   |  69 +++++--------
 8 files changed, 98 insertions(+), 299 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 23e27622bf..7a7f1c79c1 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -247,17 +247,18 @@ void TimeBlock::incrementalUpdateTimerTree()
 
 
 void TimeBlock::updateTimes()
-	{
-	U64 cur_time = getCPUClockCount64();
-
+{
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
-	BlockTimerStackRecord* stack_record	= ThreadTimerStack::getInstance();
+	BlockTimerStackRecord* stack_record	= LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
+	if (stack_record) return;
+
+	U64 cur_time = getCPUClockCount64();
 	BlockTimer* cur_timer				= stack_record->mActiveTimer;
 	TimeBlockAccumulator* accumulator	= stack_record->mTimeBlock->getPrimaryAccumulator();
 
 	while(cur_timer 
 		&& cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self
-		{
+	{
 		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
 		accumulator->mTotalTimeCounter += cumulative_time_delta 
 			- (accumulator->mTotalTimeCounter 
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index ab8612a8ad..73c40749ed 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -38,22 +38,6 @@ class LLMutex;
 namespace LLTrace
 {
 
-class ThreadTimerStack 
-:	public BlockTimerStackRecord, 
-	public LLThreadLocalSingleton<ThreadTimerStack>
-{
-	friend class LLThreadLocalSingleton<ThreadTimerStack>;
-	ThreadTimerStack() 
-	{}
-
-public:
-	ThreadTimerStack& operator=(const BlockTimerStackRecord& other)
-	{
-		BlockTimerStackRecord::operator=(other);
-		return *this;
-	}
-};
-
 class BlockTimer
 {
 public:
@@ -271,7 +255,8 @@ public:
 LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 {
 #if FAST_TIMER_ON
-	BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
+	BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
+	if (!cur_timer_data) return;
 	TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 	accumulator->mActiveCount++;
 	mBlockStartTotalTimeCounter = accumulator->mTotalTimeCounter;
@@ -293,7 +278,9 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 {
 #if FAST_TIMER_ON
 	U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
-	BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists();
+	BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
+	if (!cur_timer_data) return;
+
 	TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
 
 	accumulator->mCalls++;
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 4339f203db..3689c4728e 100755
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -470,7 +470,7 @@ S32 LLQueuedThread::processNextRequest()
 			}
 		}
 		
-		LLTrace::get_thread_recorder()->pushToMaster();
+		LLTrace::get_thread_recorder()->pushToParent();
 	}
 
 	S32 pending = getPending();
@@ -502,7 +502,7 @@ void LLQueuedThread::run()
 		
 		if (isQuitting())
 		{
-			LLTrace::get_thread_recorder()->pushToMaster();
+			LLTrace::get_thread_recorder()->pushToParent();
 			endThread();
 			break;
 		}
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index e8e546e769..d07cccdf15 100755
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -93,7 +93,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 {
 	LLThread *threadp = (LLThread *)datap;
 
-	LLTrace::SlaveThreadRecorder thread_recorder(LLTrace::getUIThreadRecorder());
+	LLTrace::ThreadRecorder thread_recorder(LLTrace::getUIThreadRecorder());
 
 #if !LL_DARWIN
 	sThreadID = threadp->mID;
diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
index d6399d5131..3b2f5f4193 100644
--- a/indra/llcommon/llthreadlocalstorage.h
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -124,175 +124,6 @@ public:
 	bool notNull() const { return sInitialized && get() != NULL; }
 };
 
-template<typename DERIVED_TYPE>
-class LLThreadLocalSingleton
-{
-	typedef enum e_init_state
-	{
-		UNINITIALIZED = 0,
-		CONSTRUCTING,
-		INITIALIZING,
-		INITIALIZED,
-		DELETED
-	} EInitState;
-
-public:
-	LLThreadLocalSingleton()
-	{}
-	
-	virtual ~LLThreadLocalSingleton()
-	{
-#if LL_DARWIN
-        pthread_setspecific(sInstanceKey, NULL);
-#else
-        sData.mInstance = NULL;
-#endif
-		setInitState(DELETED);
-	}
-
-	static void deleteSingleton()
-	{
-		delete getIfExists();
-	}
-
-	static DERIVED_TYPE* getInstance()
-	{
-        EInitState init_state = getInitState();
-		if (init_state == CONSTRUCTING)
-		{
-			llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl;
-		}
-
-		if (init_state == DELETED)
-		{
-			llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
-		}
-
-#if LL_DARWIN
-        createTLSInstance();
-#endif
-		if (!getIfExists())
-		{
-			setInitState(CONSTRUCTING);
-            DERIVED_TYPE* instancep = new DERIVED_TYPE();
-#if LL_DARWIN
-            S32 result = pthread_setspecific(sInstanceKey, (void*)instancep);
-            if (result != 0)
-            {
-                llerrs << "Could not set thread local storage" << llendl;
-            }
-#else
-			sData.mInstance = instancep;
-#endif
-			setInitState(INITIALIZING);
-			instancep->initSingleton();
-			setInitState(INITIALIZED);
-		}
-
-        return getIfExists();
-	}
-
-	static DERIVED_TYPE* getIfExists()
-	{
-#if LL_DARWIN
-        return (DERIVED_TYPE*)pthread_getspecific(sInstanceKey);
-#else
-		return sData.mInstance;
-#endif
-	}
-
-	// Reference version of getInstance()
-	// Preferred over getInstance() as it disallows checking for NULL
-	static DERIVED_TYPE& instance()
-	{
-		return *getInstance();
-	}
-
-	// Has this singleton been created uet?
-	// Use this to avoid accessing singletons before the can safely be constructed
-	static bool instanceExists()
-	{
-		return getInitState() == INITIALIZED;
-	}
-
-	// Has this singleton already been deleted?
-	// Use this to avoid accessing singletons from a static object's destructor
-	static bool destroyed()
-	{
-		return getInitState() == DELETED;
-	}
-private:
-#if LL_DARWIN
-    static void createTLSInitState()
-    {
-        static S32 key_created = pthread_key_create(&sInitStateKey, NULL);
-        if (key_created != 0)
-        {
-            llerrs << "Could not create thread local storage" << llendl;
-        }
-    }
-    
-    static void createTLSInstance()
-    {
-        static S32 key_created = pthread_key_create(&sInstanceKey, NULL);
-        if (key_created != 0)
-        {
-            llerrs << "Could not create thread local storage" << llendl;
-        }
-    }
-#endif
-    static EInitState getInitState()
-    {
-#if LL_DARWIN
-        createTLSInitState();
-        return (EInitState)(int)pthread_getspecific(sInitStateKey);
-#else
-        return sData.mInitState;
-#endif
-    }
-    
-    static void setInitState(EInitState state)
-    {
-#if LL_DARWIN
-        createTLSInitState();
-        pthread_setspecific(sInitStateKey, (void*)state);
-#else
-        sData.mInitState = state;
-#endif
-    }
-	LLThreadLocalSingleton(const LLThreadLocalSingleton& other);
-	virtual void initSingleton() {}
-
-	struct SingletonData
-	{
-		DERIVED_TYPE*	mInstance;
-		EInitState		mInitState;
-	};
-#ifdef LL_WINDOWS
-	static __declspec(thread) SingletonData sData;
-#elif LL_LINUX
-	static __thread SingletonData sData;
-#elif LL_DARWIN
-    static pthread_key_t sInstanceKey;
-    static pthread_key_t sInitStateKey;
-#endif
-};
-
-#if LL_WINDOWS
-template<typename DERIVED_TYPE>
-__declspec(thread) typename LLThreadLocalSingleton<DERIVED_TYPE>::SingletonData LLThreadLocalSingleton<DERIVED_TYPE>::sData = {NULL, LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED};
-#elif LL_LINUX
-template<typename DERIVED_TYPE>
-__thread typename LLThreadLocalSingleton<DERIVED_TYPE>::SingletonData LLThreadLocalSingleton<DERIVED_TYPE>::sData = {NULL, LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED};
-#elif LL_DARWIN
-template<typename DERIVED_TYPE>
-pthread_key_t LLThreadLocalSingleton<DERIVED_TYPE>::sInstanceKey;
-
-template<typename DERIVED_TYPE>
-pthread_key_t LLThreadLocalSingleton<DERIVED_TYPE>::sInitStateKey;
-
-#endif
-
 template<typename DERIVED_TYPE>
 class LLThreadLocalSingletonPointer
 {
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 25807c7b2c..26c19e5121 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -39,7 +39,7 @@ void init()
 {
 	if (sInitializationCount++ == 0)
 	{
-		gUIThreadRecorder = new MasterThreadRecorder();
+		gUIThreadRecorder = new ThreadRecorder();
 	}
 }
 
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index d0f0328d1c..e88c5bf177 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -31,7 +31,7 @@
 namespace LLTrace
 {
 
-MasterThreadRecorder* gUIThreadRecorder = NULL;
+ThreadRecorder* gUIThreadRecorder = NULL;
 
 ///////////////////////////////////////////////////////////////////////
 // ThreadRecorder
@@ -39,11 +39,17 @@ MasterThreadRecorder* gUIThreadRecorder = NULL;
 
 ThreadRecorder::ThreadRecorder()
 {
+	init();
+}
+
+void ThreadRecorder::init()
+{
+	LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(&mBlockTimerStackRecord);
 	//NB: the ordering of initialization in this function is very fragile due to a large number of implicit dependencies
 	set_thread_recorder(this);
 	TimeBlock& root_time_block = TimeBlock::getRootTimeBlock();
 
-	ThreadTimerStack* timer_stack = ThreadTimerStack::getInstance();
+	BlockTimerStackRecord* timer_stack = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
 	timer_stack->mTimeBlock = &root_time_block;
 	timer_stack->mActiveTimer = NULL;
 
@@ -71,8 +77,19 @@ ThreadRecorder::ThreadRecorder()
 	TimeBlock::getRootTimeBlock().getPrimaryAccumulator()->mActiveCount = 1;
 }
 
+
+ThreadRecorder::ThreadRecorder(ThreadRecorder& master)
+:	mMasterRecorder(&master)
+{
+	init();
+	mMasterRecorder->addChildRecorder(this);
+}
+
+
 ThreadRecorder::~ThreadRecorder()
 {
+	LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(NULL);
+
 	deactivate(&mThreadRecordingBuffers);
 
 	delete mRootTimer;
@@ -85,6 +102,11 @@ ThreadRecorder::~ThreadRecorder()
 
 	set_thread_recorder(NULL);
 	delete[] mTimeBlockTreeNodes;
+
+	if (mMasterRecorder)
+	{
+		mMasterRecorder->removeChildRecorder(this);
+	}
 }
 
 TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode( S32 index )
@@ -190,86 +212,63 @@ void ThreadRecorder::ActiveRecording::movePartialToTarget()
 }
 
 
-///////////////////////////////////////////////////////////////////////
-// SlaveThreadRecorder
-///////////////////////////////////////////////////////////////////////
-
-SlaveThreadRecorder::SlaveThreadRecorder(MasterThreadRecorder& master)
-:	mMasterRecorder(master)
-{
-	mMasterRecorder.addSlaveThread(this);
+// called by child thread
+void ThreadRecorder::addChildRecorder( class ThreadRecorder* child )
+{ LLMutexLock lock(&mChildListMutex);
+	mChildThreadRecorders.push_back(child);
 }
 
-SlaveThreadRecorder::~SlaveThreadRecorder()
+// called by child thread
+void ThreadRecorder::removeChildRecorder( class ThreadRecorder* child )
+{ LLMutexLock lock(&mChildListMutex);
+
+for (child_thread_recorder_list_t::iterator it = mChildThreadRecorders.begin(), end_it = mChildThreadRecorders.end();
+	it != end_it;
+	++it)
 {
-	mMasterRecorder.removeSlaveThread(this);
+	if ((*it) == child)
+	{
+		mChildThreadRecorders.erase(it);
+		break;
+	}
+}
 }
 
-void SlaveThreadRecorder::pushToMaster()
-{ 
+void ThreadRecorder::pushToParent()
+{
 	{ LLMutexLock lock(&mSharedRecordingMutex);	
 		LLTrace::get_thread_recorder()->bringUpToDate(&mThreadRecordingBuffers);
 		mSharedRecordingBuffers.append(mThreadRecordingBuffers);
 	}
 }
+	
+
 
-///////////////////////////////////////////////////////////////////////
-// MasterThreadRecorder
-///////////////////////////////////////////////////////////////////////
 
-static LLFastTimer::DeclareTimer FTM_PULL_TRACE_DATA_FROM_SLAVES("Pull slave trace data");
+static LLFastTimer::DeclareTimer FTM_PULL_TRACE_DATA_FROM_CHILDREN("Pull child thread trace data");
 
-void MasterThreadRecorder::pullFromSlaveThreads()
+void ThreadRecorder::pullFromChildren()
 {
-	/*LLFastTimer _(FTM_PULL_TRACE_DATA_FROM_SLAVES);
+	LLFastTimer _(FTM_PULL_TRACE_DATA_FROM_CHILDREN);
 	if (mActiveRecordings.empty()) return;
 
-	{ LLMutexLock lock(&mSlaveListMutex);
-
-	AccumulatorBufferGroup& target_recording_buffers = mActiveRecordings.back()->mPartialRecording;
-	target_recording_buffers.sync();
-	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
-	it != end_it;
-	++it)
-	{ LLMutexLock lock(&(*it)->mSharedRecordingMutex);
-
-	target_recording_buffers.merge((*it)->mSharedRecordingBuffers);
-	(*it)->mSharedRecordingBuffers.reset();
-	}
-	}*/
-}
+	{ LLMutexLock lock(&mChildListMutex);
 
-// called by slave thread
-void MasterThreadRecorder::addSlaveThread( class SlaveThreadRecorder* child )
-{ LLMutexLock lock(&mSlaveListMutex);
+		AccumulatorBufferGroup& target_recording_buffers = mActiveRecordings.back()->mPartialRecording;
+		target_recording_buffers.sync();
+		for (child_thread_recorder_list_t::iterator it = mChildThreadRecorders.begin(), end_it = mChildThreadRecorders.end();
+			it != end_it;
+			++it)
+		{ LLMutexLock lock(&(*it)->mSharedRecordingMutex);
 
-	mSlaveThreadRecorders.push_back(child);
-}
-
-// called by slave thread
-void MasterThreadRecorder::removeSlaveThread( class SlaveThreadRecorder* child )
-{ LLMutexLock lock(&mSlaveListMutex);
-
-	for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end();
-		it != end_it;
-		++it)
-	{
-		if ((*it) == child)
-		{
-			mSlaveThreadRecorders.erase(it);
-			break;
+			target_recording_buffers.merge((*it)->mSharedRecordingBuffers);
+			(*it)->mSharedRecordingBuffers.reset();
 		}
 	}
 }
 
-void MasterThreadRecorder::pushToMaster()
-{}
-
-MasterThreadRecorder::MasterThreadRecorder()
-{}
-
 
-MasterThreadRecorder& getUIThreadRecorder()
+ThreadRecorder& getUIThreadRecorder()
 {
 	llassert(gUIThreadRecorder != NULL);
 	return *gUIThreadRecorder;
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 6b7a8e5865..b5ed77416c 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -43,17 +43,26 @@ namespace LLTrace
 		typedef std::vector<ActiveRecording*> active_recording_list_t;
 	public:
 		ThreadRecorder();
+		explicit ThreadRecorder(ThreadRecorder& master);
 
-		virtual ~ThreadRecorder();
+		~ThreadRecorder();
 
 		void activate(AccumulatorBufferGroup* recording);
 		void deactivate(AccumulatorBufferGroup* recording);
 		active_recording_list_t::reverse_iterator bringUpToDate(AccumulatorBufferGroup* recording);
 
-		virtual void pushToMaster() = 0;
+		void addChildRecorder(class ThreadRecorder* child);
+		void removeChildRecorder(class ThreadRecorder* child);
+
+		// call this periodically to gather stats data from child threads
+		void pullFromChildren();
+		void pushToParent();
 
 		TimeBlockTreeNode* getTimeBlockTreeNode(S32 index);
 
+	protected:
+		void init();
+
 	protected:
 		struct ActiveRecording
 		{
@@ -64,59 +73,31 @@ namespace LLTrace
 
 			void movePartialToTarget();
 		};
-		AccumulatorBufferGroup			mThreadRecordingBuffers;
-
-		active_recording_list_t		mActiveRecordings;
-
-		class BlockTimer*			mRootTimer;
-		TimeBlockTreeNode*			mTimeBlockTreeNodes;
-		size_t						mNumTimeBlockTreeNodes;
-		BlockTimerStackRecord		mBlockTimerStackRecord;
-	};
-
-	class LL_COMMON_API MasterThreadRecorder : public ThreadRecorder
-	{
-	public:
-		MasterThreadRecorder();
-
-		void addSlaveThread(class SlaveThreadRecorder* child);
-		void removeSlaveThread(class SlaveThreadRecorder* child);
-
-		/*virtual */ void pushToMaster();
-
-		// call this periodically to gather stats data from slave threads
-		void pullFromSlaveThreads();
-
-	private:
 
-		typedef std::list<class SlaveThreadRecorder*> slave_thread_recorder_list_t;
+		AccumulatorBufferGroup			mThreadRecordingBuffers;
 
-		slave_thread_recorder_list_t	mSlaveThreadRecorders;	// list of slave thread recorders associated with this master
-		LLMutex							mSlaveListMutex;		// protects access to slave list
-	};
+		BlockTimerStackRecord			mBlockTimerStackRecord;
+		active_recording_list_t			mActiveRecordings;
 
-	class LL_COMMON_API SlaveThreadRecorder : public ThreadRecorder
-	{
-	public:
-		SlaveThreadRecorder(MasterThreadRecorder& master);
-		~SlaveThreadRecorder();
+		class BlockTimer*				mRootTimer;
+		TimeBlockTreeNode*				mTimeBlockTreeNodes;
+		size_t							mNumTimeBlockTreeNodes;
+		typedef std::list<class ThreadRecorder*> child_thread_recorder_list_t;
 
-		// call this periodically to gather stats data for master thread to consume
-		/*virtual*/ void pushToMaster();
+		child_thread_recorder_list_t	mChildThreadRecorders;	// list of child thread recorders associated with this master
+		LLMutex							mChildListMutex;		// protects access to child list
+		LLMutex							mSharedRecordingMutex;
+		AccumulatorBufferGroup			mSharedRecordingBuffers;
+		ThreadRecorder*					mMasterRecorder;
 
-	private:
-		friend class MasterThreadRecorder;
-		LLMutex					mSharedRecordingMutex;
-		AccumulatorBufferGroup	mSharedRecordingBuffers;
-		MasterThreadRecorder&	mMasterRecorder;
 	};
 
 	//FIXME: let user code set up thread recorder topology
-	extern MasterThreadRecorder* gUIThreadRecorder ;
+	extern ThreadRecorder* gUIThreadRecorder ;
 
 	const LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder();
 	void set_thread_recorder(class ThreadRecorder*);
-	class MasterThreadRecorder& getUIThreadRecorder();
+	ThreadRecorder& getUIThreadRecorder();
 
 }
 
-- 
cgit v1.2.3


From 04bdc8ba83c297945dd60489c241b88adf892ff4 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 1 Jul 2013 17:04:01 -0700
Subject: SH-4294 FIX Interesting: Statistics Texture cache hit rate is always
 0% also, removed LLTrace::init and cleanup removed derived class
 implementation of memory stat for LLMemTrackable is automatic now

---
 indra/llcommon/llcommon.cpp              | 14 ++++++-
 indra/llcommon/llfasttimer.cpp           |  2 +-
 indra/llcommon/llthread.cpp              |  2 +-
 indra/llcommon/lltrace.cpp               | 26 +++++-------
 indra/llcommon/lltrace.h                 | 68 +++++++++++++++++++-------------
 indra/llcommon/lltraceaccumulators.h     |  7 +---
 indra/llcommon/lltracethreadrecorder.cpp | 14 +++++--
 indra/llcommon/lltracethreadrecorder.h   | 10 ++---
 8 files changed, 79 insertions(+), 64 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index c720df7555..96ec0cdefe 100755
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -30,10 +30,13 @@
 #include "llmemory.h"
 #include "llthread.h"
 #include "lltrace.h"
+#include "lltracethreadrecorder.h"
 
 //static
 BOOL LLCommon::sAprInitialized = FALSE;
 
+static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL;
+
 //static
 void LLCommon::initClass()
 {
@@ -45,13 +48,20 @@ void LLCommon::initClass()
 	}
 	LLTimer::initClass();
 	LLThreadSafeRefCount::initThreadSafeRefCount();
-	LLTrace::init();
+
+	if (!sMasterThreadRecorder)
+	{
+		sMasterThreadRecorder = new LLTrace::ThreadRecorder();
+		LLTrace::set_master_thread_recorder(sMasterThreadRecorder);
+	}
 }
 
 //static
 void LLCommon::cleanupClass()
 {
-	LLTrace::cleanup();
+	delete sMasterThreadRecorder;
+	sMasterThreadRecorder = NULL;
+	LLTrace::set_master_thread_recorder(NULL);
 	LLThreadSafeRefCount::cleanupThreadSafeRefCount();
 	LLTimer::cleanupClass();
 	if (sAprInitialized)
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 7a7f1c79c1..a72f16d385 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -250,7 +250,7 @@ void TimeBlock::updateTimes()
 {
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
 	BlockTimerStackRecord* stack_record	= LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
-	if (stack_record) return;
+	if (!stack_record) return;
 
 	U64 cur_time = getCPUClockCount64();
 	BlockTimer* cur_timer				= stack_record->mActiveTimer;
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index d07cccdf15..166a4eb26d 100755
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -93,7 +93,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 {
 	LLThread *threadp = (LLThread *)datap;
 
-	LLTrace::ThreadRecorder thread_recorder(LLTrace::getUIThreadRecorder());
+	LLTrace::ThreadRecorder thread_recorder(*LLTrace::get_master_thread_recorder());
 
 #if !LL_DARWIN
 	sThreadID = threadp->mID;
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 26c19e5121..3dffbe6d4a 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -30,34 +30,26 @@
 #include "lltracethreadrecorder.h"
 #include "llfasttimer.h"
 
-static S32 sInitializationCount = 0;
-
 namespace LLTrace
 {
 
-void init()
+TraceBase::TraceBase( const char* name, const char* description ) 
+:	mName(name),
+	mDescription(description ? description : "")
 {
-	if (sInitializationCount++ == 0)
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+	if (LLTrace::get_master_thread_recorder() != NULL)
 	{
-		gUIThreadRecorder = new ThreadRecorder();
+		llerrs << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << llendl;
 	}
+#endif
 }
 
-bool isInitialized()
+const char* TraceBase::getUnitLabel()
 {
-	return sInitializationCount > 0; 
+	return "";
 }
 
-void cleanup()
-{
-	if (--sInitializationCount == 0)
-	{
-		delete gUIThreadRecorder;
-		gUIThreadRecorder = NULL;
-	}
-}
-
-
 TimeBlockTreeNode::TimeBlockTreeNode() 
 :	mBlock(NULL),
 	mParent(NULL),
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 72ef51c232..1cde450dc2 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -53,19 +53,29 @@ STORAGE_TYPE storage_value(LLUnit<STORAGE_TYPE, UNIT_TYPE> val) { return val.val
 template<typename UNIT_TYPE, typename STORAGE_TYPE> 
 STORAGE_TYPE storage_value(LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); }
 
-void init();
-void cleanup();
-bool isInitialized();
+class TraceBase
+{
+public:
+	TraceBase(const char* name, const char* description);
+	virtual ~TraceBase() {};
+	virtual const char* getUnitLabel();
+
+	const std::string& getName() const { return mName; }
+
+protected:
+	const std::string	mName;
+	const std::string	mDescription;
+};
 
 template<typename ACCUMULATOR>
 class TraceType 
-:	 public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
+:	public TraceBase,
+	public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
 {
 public:
 	TraceType(const char* name, const char* description = NULL)
 	:	LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>(name),
-		mName(name),
-		mDescription(description ? description : ""),
+		TraceBase(name, description),
 		mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot())
 	{}
 
@@ -78,13 +88,7 @@ public:
 	size_t getIndex() const { return mAccumulatorIndex; }
 	static size_t getNumIndices() { return AccumulatorBuffer<ACCUMULATOR>::getNumIndices(); }
 
-	virtual const char* getUnitLabel() { return ""; }
-
-	const std::string& getName() const { return mName; }
-
-protected:
-	const std::string	mName;
-	const std::string	mDescription;
+private:
 	const size_t		mAccumulatorIndex;
 };
 
@@ -320,7 +324,7 @@ class MemTrackable
 	template<typename TRACKED, typename TRACKED_IS_TRACKER>
 	struct TrackMemImpl;
 
-	typedef MemTrackable<DERIVED> mem_trackable_t;
+	typedef MemTrackable<DERIVED, ALIGNMENT> mem_trackable_t;
 
 public:
 	typedef void mem_trackable_tag_t;
@@ -332,7 +336,7 @@ public:
 
 	void* operator new(size_t size) 
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = mem_trackable_t::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
@@ -344,7 +348,7 @@ public:
 
 	void operator delete(void* ptr, size_t size)
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = mem_trackable_t::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
@@ -356,7 +360,7 @@ public:
 
 	void *operator new [](size_t size)
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = mem_trackable_t::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
@@ -368,7 +372,7 @@ public:
 
 	void operator delete[](void* ptr, size_t size)
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = mem_trackable_t::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
@@ -394,14 +398,16 @@ public:
 	}
 
 
-	void memClaimAmount(size_t size)
+	template<typename AMOUNT_T>
+	AMOUNT_T& memClaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
-		mMemFootprint += size;
+		MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
+		mMemFootprint += (size_t)size;
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
 		}
+		return size;
 	}
 
 	// remove memory we had claimed from our calculated footprint
@@ -419,24 +425,28 @@ public:
 		return value;
 	}
 
-	void memDisclaimAmount(size_t size)
+	template<typename AMOUNT_T>
+	AMOUNT_T& memDisclaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
 		}
+		return size;
 	}
 
 private:
 	size_t mMemFootprint;
+	static MemStatHandle sMemStat;
+
 
 	template<typename TRACKED, typename TRACKED_IS_TRACKER = void>
 	struct TrackMemImpl
 	{
 		static void claim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				size_t footprint = MemFootprint<TRACKED>::measure(tracked);
@@ -447,7 +457,7 @@ private:
 
 		static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				size_t footprint = MemFootprint<TRACKED>::measure(tracked);
@@ -462,7 +472,7 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				accumulator->mChildSize.sample(accumulator->mChildSize.getLastValue() + (F64)MemFootprint<TRACKED>::measure(tracked));
@@ -471,7 +481,7 @@ private:
 
 		static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				accumulator->mChildSize.sample(accumulator->mChildSize.getLastValue() - (F64)MemFootprint<TRACKED>::measure(tracked));
@@ -480,5 +490,9 @@ private:
 	};
 };
 
+template<typename DERIVED, size_t ALIGNMENT>
+MemStatHandle MemTrackable<DERIVED, ALIGNMENT>::sMemStat(typeid(DERIVED).name());
+
+
 }
 #endif // LL_LLTRACE_H
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 825cc9e3a8..fac6347ff9 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -33,6 +33,7 @@
 #include "llunit.h"
 #include "lltimer.h"
 #include "llrefcount.h"
+#include "llthreadlocalstorage.h"
 
 namespace LLTrace
 {
@@ -142,12 +143,6 @@ namespace LLTrace
 		// NOTE: this is not thread-safe.  We assume that slots are reserved in the main thread before any child threads are spawned
 		size_t reserveSlot()
 		{
-#ifndef LL_RELEASE_FOR_DOWNLOAD
-			if (LLTrace::isInitialized())
-			{
-				llerrs << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << llendl;
-			}
-#endif
 			size_t next_slot = sNextStorageSlot++;
 			if (next_slot >= mStorageSize)
 			{
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index e88c5bf177..7ac0e75154 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -31,13 +31,14 @@
 namespace LLTrace
 {
 
-ThreadRecorder* gUIThreadRecorder = NULL;
+static ThreadRecorder* sMasterThreadRecorder = NULL;
 
 ///////////////////////////////////////////////////////////////////////
 // ThreadRecorder
 ///////////////////////////////////////////////////////////////////////
 
 ThreadRecorder::ThreadRecorder()
+:	mMasterRecorder(NULL)
 {
 	init();
 }
@@ -268,10 +269,15 @@ void ThreadRecorder::pullFromChildren()
 }
 
 
-ThreadRecorder& getUIThreadRecorder()
+void set_master_thread_recorder(ThreadRecorder* recorder)
 {
-	llassert(gUIThreadRecorder != NULL);
-	return *gUIThreadRecorder;
+	sMasterThreadRecorder = recorder;
+}
+
+
+ThreadRecorder* get_master_thread_recorder()
+{
+	return sMasterThreadRecorder;
 }
 
 LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder_ptr()
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index b5ed77416c..535f855200 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -92,13 +92,11 @@ namespace LLTrace
 
 	};
 
-	//FIXME: let user code set up thread recorder topology
-	extern ThreadRecorder* gUIThreadRecorder ;
-
-	const LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder();
-	void set_thread_recorder(class ThreadRecorder*);
-	ThreadRecorder& getUIThreadRecorder();
+	const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder();
+	void set_thread_recorder(ThreadRecorder*);
 
+	void set_master_thread_recorder(ThreadRecorder*);
+	ThreadRecorder* get_master_thread_recorder();
 }
 
 #endif // LL_LLTRACETHREADRECORDER_H
-- 
cgit v1.2.3


From 8208a40412fac35593d4b8b13f43c6be5e4d6990 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 1 Jul 2013 18:50:51 -0700
Subject: BUILDFIX: reverted changes that attempted to automate mem track stat
 definition as they don't work on gcc/clang

---
 indra/llcommon/lltrace.h | 22 ++++++++--------------
 1 file changed, 8 insertions(+), 14 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 1cde450dc2..e2c4b63276 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -336,7 +336,7 @@ public:
 
 	void* operator new(size_t size) 
 	{
-		MemStatAccumulator* accumulator = mem_trackable_t::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
@@ -348,7 +348,7 @@ public:
 
 	void operator delete(void* ptr, size_t size)
 	{
-		MemStatAccumulator* accumulator = mem_trackable_t::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
@@ -360,7 +360,7 @@ public:
 
 	void *operator new [](size_t size)
 	{
-		MemStatAccumulator* accumulator = mem_trackable_t::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
@@ -372,7 +372,7 @@ public:
 
 	void operator delete[](void* ptr, size_t size)
 	{
-		MemStatAccumulator* accumulator = mem_trackable_t::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
@@ -438,15 +438,13 @@ public:
 
 private:
 	size_t mMemFootprint;
-	static MemStatHandle sMemStat;
-
 
 	template<typename TRACKED, typename TRACKED_IS_TRACKER = void>
 	struct TrackMemImpl
 	{
 		static void claim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				size_t footprint = MemFootprint<TRACKED>::measure(tracked);
@@ -457,7 +455,7 @@ private:
 
 		static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				size_t footprint = MemFootprint<TRACKED>::measure(tracked);
@@ -472,7 +470,7 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				accumulator->mChildSize.sample(accumulator->mChildSize.getLastValue() + (F64)MemFootprint<TRACKED>::measure(tracked));
@@ -481,7 +479,7 @@ private:
 
 		static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 			if (accumulator)
 			{
 				accumulator->mChildSize.sample(accumulator->mChildSize.getLastValue() - (F64)MemFootprint<TRACKED>::measure(tracked));
@@ -490,9 +488,5 @@ private:
 	};
 };
 
-template<typename DERIVED, size_t ALIGNMENT>
-MemStatHandle MemTrackable<DERIVED, ALIGNMENT>::sMemStat(typeid(DERIVED).name());
-
-
 }
 #endif // LL_LLTRACE_H
-- 
cgit v1.2.3


From 048638e5ffec0cc08d79484412790b51558942fe Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 1 Jul 2013 19:26:56 -0700
Subject: BUILDFIX: missed a couple of scope qualifiers

---
 indra/llcommon/lltrace.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index e2c4b63276..2c45923aac 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -401,7 +401,7 @@ public:
 	template<typename AMOUNT_T>
 	AMOUNT_T& memClaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		mMemFootprint += (size_t)size;
 		if (accumulator)
 		{
@@ -428,7 +428,7 @@ public:
 	template<typename AMOUNT_T>
 	AMOUNT_T& memDisclaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator* accumulator = sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		if (accumulator)
 		{
 			accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
-- 
cgit v1.2.3


From 72eea31b1542f56e987a8701f079b27d8b7276bd Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 1 Jul 2013 20:10:24 -0700
Subject: BUILDFIX: forward declare TraceType to appease gcc template
 instantiation gods

---
 indra/llcommon/lltracerecording.h | 3 +++
 1 file changed, 3 insertions(+)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 355dbabb1c..b646075228 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -112,6 +112,9 @@ private:
 
 namespace LLTrace
 {
+	template<typename T>
+	class TraceType;
+
 	class Recording 
 	:	public LLStopWatchControlsMixin<Recording>
 	{
-- 
cgit v1.2.3


From bc7d2b76961c0397dcd108e625db4304855f4539 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 1 Jul 2013 20:43:24 -0700
Subject: BUILDFIX: more template forward declarations

---
 indra/llcommon/lltracerecording.h | 9 +++++++++
 1 file changed, 9 insertions(+)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index b646075228..7b0970ffdf 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -115,6 +115,15 @@ namespace LLTrace
 	template<typename T>
 	class TraceType;
 
+	template<typename T>
+	class CountStatHandle;
+
+	template<typename T>
+	class SampleStatHandle;
+
+	template<typename T>
+	class EventStatHandle;
+
 	class Recording 
 	:	public LLStopWatchControlsMixin<Recording>
 	{
-- 
cgit v1.2.3


From d122318bef2ff0eced7641dc24f411f792bd2935 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 8 Jul 2013 00:55:17 -0700
Subject: SH-4299 WIP: Interesting: High fps shown temporarily off scale in
 statistics console added percentage/ratio units added auto-range and auto
 tick calculation to stat bar to automate display stats

---
 indra/llcommon/llmemory.cpp | 137 --------------------------------------------
 indra/llcommon/llmemory.h   |  45 ---------------
 indra/llcommon/lltrace.h    |   3 +-
 indra/llcommon/llunit.h     |   5 ++
 4 files changed, 7 insertions(+), 183 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index c6b02df939..3fe7470d06 100755
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -27,9 +27,7 @@
 #include "linden_common.h"
 
 
-//#if MEM_TRACK_MEM
 #include "llthread.h"
-//#endif
 
 #if defined(LL_WINDOWS)
 # include <psapi.h>
@@ -421,141 +419,6 @@ U32 LLMemory::getWorkingSetSize()
 
 #endif
 
-//--------------------------------------------------------------------------------------------------
-#if MEM_TRACK_MEM
-#include "llframetimer.h"
-
-//static 
-LLMemTracker* LLMemTracker::sInstance = NULL ;
-
-LLMemTracker::LLMemTracker()
-{
-	mLastAllocatedMem = LLMemory::getWorkingSetSize() ;
-	mCapacity = 128 ;	
-	mCurIndex = 0 ;
-	mCounter = 0 ;
-	mDrawnIndex = 0 ;
-	mPaused = FALSE ;
-
-	mMutexp = new LLMutex() ;
-	mStringBuffer = new char*[128] ;
-	mStringBuffer[0] = new char[mCapacity * 128] ;
-	for(S32 i = 1 ; i < mCapacity ; i++)
-	{
-		mStringBuffer[i] = mStringBuffer[i-1] + 128 ;
-	}
-}
-
-LLMemTracker::~LLMemTracker()
-{
-	delete[] mStringBuffer[0] ;
-	delete[] mStringBuffer;
-	delete mMutexp ;
-}
-
-//static 
-LLMemTracker* LLMemTracker::getInstance()
-{
-	if(!sInstance)
-	{
-		sInstance = new LLMemTracker() ;
-	}
-	return sInstance ;
-}
-
-//static 
-void LLMemTracker::release() 
-{
-	if(sInstance)
-	{
-		delete sInstance ;
-		sInstance = NULL ;
-	}
-}
-
-//static
-void LLMemTracker::track(const char* function, const int line)
-{
-	static const S32 MIN_ALLOCATION = 0 ; //1KB
-
-	if(mPaused)
-	{
-		return ;
-	}
-
-	U32 allocated_mem = LLMemory::getWorkingSetSize() ;
-
-	LLMutexLock lock(mMutexp) ;
-
-	S32 delta_mem = allocated_mem - mLastAllocatedMem ;
-	mLastAllocatedMem = allocated_mem ;
-
-	if(delta_mem <= 0)
-	{
-		return ; //occupied memory does not grow
-	}
-
-	if(delta_mem < MIN_ALLOCATION)
-	{
-		return ;
-	}
-		
-	char* buffer = mStringBuffer[mCurIndex++] ;
-	F32 time = (F32)LLFrameTimer::getElapsedSeconds() ;
-	S32 hours = (S32)(time / (60*60));
-	S32 mins = (S32)((time - hours*(60*60)) / 60);
-	S32 secs = (S32)((time - hours*(60*60) - mins*60));
-	strcpy(buffer, function) ;
-	sprintf(buffer + strlen(function), " line: %d DeltaMem: %d (bytes) Time: %d:%02d:%02d", line, delta_mem, hours,mins,secs) ;
-
-	if(mCounter < mCapacity)
-	{
-		mCounter++ ;
-	}
-	if(mCurIndex >= mCapacity)
-	{
-		mCurIndex = 0 ;		
-	}
-}
-
-
-//static 
-void LLMemTracker::preDraw(BOOL pause) 
-{
-	mMutexp->lock() ;
-
-	mPaused = pause ;
-	mDrawnIndex = mCurIndex - 1;
-	mNumOfDrawn = 0 ;
-}
-	
-//static 
-void LLMemTracker::postDraw() 
-{
-	mMutexp->unlock() ;
-}
-
-//static 
-const char* LLMemTracker::getNextLine() 
-{
-	if(mNumOfDrawn >= mCounter)
-	{
-		return NULL ;
-	}
-	mNumOfDrawn++;
-
-	if(mDrawnIndex < 0)
-	{
-		mDrawnIndex = mCapacity - 1 ;
-	}
-
-	return mStringBuffer[mDrawnIndex--] ;
-}
-
-#endif //MEM_TRACK_MEM
-//--------------------------------------------------------------------------------------------------
-
-
 //--------------------------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------------------------
 //minimum slot size and minimal slot size interval
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 95500753e4..a24d97576f 100755
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -184,51 +184,6 @@ private:
 	static BOOL sEnableMemoryFailurePrevention;
 };
 
-//----------------------------------------------------------------------------
-#if MEM_TRACK_MEM
-class LLMutex ;
-class LL_COMMON_API LLMemTracker
-{
-private:
-	LLMemTracker() ;
-	~LLMemTracker() ;
-
-public:
-	static void release() ;
-	static LLMemTracker* getInstance() ;
-
-	void track(const char* function, const int line) ;
-	void preDraw(BOOL pause) ;
-	void postDraw() ;
-	const char* getNextLine() ;
-
-private:
-	static LLMemTracker* sInstance ;
-	
-	char**     mStringBuffer ;
-	S32        mCapacity ;
-	U32        mLastAllocatedMem ;
-	S32        mCurIndex ;
-	S32        mCounter;
-	S32        mDrawnIndex;
-	S32        mNumOfDrawn;
-	BOOL       mPaused;
-	LLMutex*   mMutexp ;
-};
-
-#define MEM_TRACK_RELEASE LLMemTracker::release() ;
-#define MEM_TRACK         LLMemTracker::getInstance()->track(__FUNCTION__, __LINE__) ;
-
-#else // MEM_TRACK_MEM
-
-#define MEM_TRACK_RELEASE
-#define MEM_TRACK
-
-#endif // MEM_TRACK_MEM
-
-//----------------------------------------------------------------------------
-
-
 //
 //class LLPrivateMemoryPool defines a private memory pool for an application to use, so the application does not
 //need to access the heap directly fro each memory allocation. Throught this, the allocation speed is faster, 
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 2c45923aac..2c84b1596a 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -61,6 +61,7 @@ public:
 	virtual const char* getUnitLabel();
 
 	const std::string& getName() const { return mName; }
+	const std::string& getDescription() const { return mDescription; }
 
 protected:
 	const std::string	mName;
@@ -169,7 +170,7 @@ public:
 	typedef TraceType<CountAccumulator> trace_t;
 
 	CountStatHandle(const char* name, const char* description = NULL) 
-	:	trace_t(name)
+	:	trace_t(name, description)
 	{}
 
 	/*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); }
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index c9bbed5574..79465715cf 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -571,6 +571,11 @@ LL_DECLARE_DERIVED_UNIT(Gigahertz, "GHz", Megahertz, * 1000);
 LL_DECLARE_BASE_UNIT(Radians, "rad");
 LL_DECLARE_DERIVED_UNIT(Degrees, "deg", Radians, * 0.01745329251994);
 
+LL_DECLARE_BASE_UNIT(Percent, "%");
+LL_DECLARE_DERIVED_UNIT(Ratio, "x", Percent, / 100);
+
+LL_DECLARE_BASE_UNIT(Triangles, "tris");
+LL_DECLARE_DERIVED_UNIT(Kilotriangles, "ktris", Triangles, * 1000);
 
 } // namespace LLUnits
 
-- 
cgit v1.2.3


From 11e14cd3b0f58225a96b9b7a9839a7f030fe4045 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 15 Jul 2013 11:05:57 -0700
Subject: SH-4299Interesting: High fps shown temporarily off scale in
 statistics console various fixes to lltrace start() on started recording no
 longer resets fixed various instances of unit forgetfullness in lltrace
 recording split now has gapless timing scene monitor now guarantees min
 sample time renamed a bunch of stats added names to debug thread view on
 windows

---
 indra/llcommon/llthread.cpp              |  39 +++++++++
 indra/llcommon/lltraceaccumulators.h     |   1 -
 indra/llcommon/lltracerecording.cpp      |  15 +++-
 indra/llcommon/lltracerecording.h        | 143 +++++++++++++++++++++++--------
 indra/llcommon/lltracethreadrecorder.cpp |   7 +-
 indra/llcommon/lltracethreadrecorder.h   |   2 +-
 6 files changed, 163 insertions(+), 44 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 166a4eb26d..e0f53fb9c4 100755
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -39,6 +39,39 @@
 #include <sched.h>
 #endif
 
+
+#ifdef LL_WINDOWS
+const DWORD MS_VC_EXCEPTION=0x406D1388;
+
+#pragma pack(push,8)
+typedef struct tagTHREADNAME_INFO
+{
+	DWORD dwType; // Must be 0x1000.
+	const char* szName; // Pointer to name (in user addr space).
+	DWORD dwThreadID; // Thread ID (-1=caller thread).
+	DWORD dwFlags; // Reserved for future use, must be zero.
+} THREADNAME_INFO;
+#pragma pack(pop)
+
+void SetThreadName( DWORD dwThreadID, const char* threadName)
+{
+	THREADNAME_INFO info;
+	info.dwType = 0x1000;
+	info.szName = threadName;
+	info.dwThreadID = dwThreadID;
+	info.dwFlags = 0;
+
+	__try
+	{
+		RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info );
+	}
+	__except(EXCEPTION_CONTINUE_EXECUTION)
+	{
+	}
+}
+#endif
+
+
 //----------------------------------------------------------------------------
 // Usage:
 // void run_func(LLThread* thread)
@@ -93,6 +126,11 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 {
 	LLThread *threadp = (LLThread *)datap;
 
+#ifdef LL_WINDOWS
+	SetThreadName(-1, threadp->mName.c_str());
+#endif
+
+
 	LLTrace::ThreadRecorder thread_recorder(*LLTrace::get_master_thread_recorder());
 
 #if !LL_DARWIN
@@ -224,6 +262,7 @@ void LLThread::start()
 		llwarns << "failed to start thread " << mName << llendl;
 		ll_apr_warn_status(status);
 	}
+
 }
 
 //============================================================================
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index fac6347ff9..a2f9f4c090 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -37,7 +37,6 @@
 
 namespace LLTrace
 {
-
 	template<typename ACCUMULATOR>
 	class AccumulatorBuffer : public LLRefCount
 	{
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index f1388e7935..875c371068 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -38,10 +38,13 @@ namespace LLTrace
 // Recording
 ///////////////////////////////////////////////////////////////////////
 
-Recording::Recording() 
-:	mElapsedSeconds(0)
+Recording::Recording(EPlayState state) 
+:	mElapsedSeconds(0),
+	mInHandOff(false)
+
 {
 	mBuffers = new AccumulatorBufferGroup();
+	setPlayState(state);
 }
 
 Recording::Recording( const Recording& other )
@@ -101,7 +104,8 @@ void Recording::handleStart()
 {
 	mSamplingTimer.reset();
 	mBuffers.setStayUnique(true);
-	LLTrace::get_thread_recorder()->activate(mBuffers.write());
+	LLTrace::get_thread_recorder()->activate(mBuffers.write(), mInHandOff);
+	mInHandOff = false;
 }
 
 void Recording::handleStop()
@@ -113,6 +117,7 @@ void Recording::handleStop()
 
 void Recording::handleSplitTo(Recording& other)
 {
+	other.mInHandOff = true;
 	mBuffers.write()->handOffTo(*other.mBuffers.write());
 }
 
@@ -485,6 +490,8 @@ void PeriodicRecording::handleStop()
 
 void PeriodicRecording::handleReset()
 {
+	getCurRecording().stop();
+
 	if (mAutoResize)
 	{
 		mRecordingPeriods.clear();
@@ -500,6 +507,7 @@ void PeriodicRecording::handleReset()
 		}
 	}
 	mCurPeriod = 0;
+	mNumPeriods = 0;
 	getCurRecording().setPlayState(getPlayState());
 }
 
@@ -719,7 +727,6 @@ void LLStopWatchControlsMixinCommon::start()
 		handleStart();
 		break;
 	case STARTED:
-		handleReset();
 		break;
 	default:
 		llassert(false);
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 7b0970ffdf..31616a52cc 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -124,11 +124,32 @@ namespace LLTrace
 	template<typename T>
 	class EventStatHandle;
 
+	template<typename T>
+	struct RelatedTypes
+	{
+		typedef F64 fractional_t;
+		typedef T	sum_t;
+	};
+
+	template<typename T, typename UNIT_T>
+	struct RelatedTypes<LLUnit<T, UNIT_T> >
+	{
+		typedef LLUnit<typename RelatedTypes<T>::fractional_t, UNIT_T> fractional_t;
+		typedef LLUnit<typename RelatedTypes<T>::sum_t, UNIT_T> sum_t;
+	};
+
+	template<>
+	struct RelatedTypes<bool>
+	{
+		typedef F64 fractional_t;
+		typedef U32 sum_t;
+	};
+
 	class Recording 
 	:	public LLStopWatchControlsMixin<Recording>
 	{
 	public:
-		Recording();
+		Recording(EPlayState state = LLStopWatchControlsMixinCommon::STOPPED);
 
 		Recording(const Recording& other);
 		~Recording();
@@ -172,16 +193,16 @@ namespace LLTrace
 		// CountStatHandle accessors
 		F64 getSum(const TraceType<CountAccumulator>& stat);
 		template <typename T>
-		T getSum(const CountStatHandle<T>& stat)
+		typename RelatedTypes<T>::sum_t getSum(const CountStatHandle<T>& stat)
 		{
-			return (T)getSum(static_cast<const TraceType<CountAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const TraceType<CountAccumulator>&> (stat));
 		}
 
 		F64 getPerSec(const TraceType<CountAccumulator>& stat);
 		template <typename T>
-		T getPerSec(const CountStatHandle<T>& stat)
+		typename RelatedTypes<T>::fractional_t getPerSec(const CountStatHandle<T>& stat)
 		{
-			return (T)getPerSec(static_cast<const TraceType<CountAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::fractional_t)getPerSec(static_cast<const TraceType<CountAccumulator>&> (stat));
 		}
 
 		U32 getSampleCount(const TraceType<CountAccumulator>& stat);
@@ -197,9 +218,9 @@ namespace LLTrace
 
 		F64 getMean(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
-		T getMean(SampleStatHandle<T>& stat)
+		typename RelatedTypes<T>::fractional_t getMean(SampleStatHandle<T>& stat)
 		{
-			return (T)getMean(static_cast<const TraceType<SampleAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
 		F64 getMax(const TraceType<SampleAccumulator>& stat);
@@ -211,9 +232,9 @@ namespace LLTrace
 
 		F64 getStandardDeviation(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
-		T getStandardDeviation(const SampleStatHandle<T>& stat)
+		typename RelatedTypes<T>::fractional_t getStandardDeviation(const SampleStatHandle<T>& stat)
 		{
-			return (T)getStandardDeviation(static_cast<const TraceType<SampleAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
 		F64 getLastValue(const TraceType<SampleAccumulator>& stat);
@@ -228,9 +249,9 @@ namespace LLTrace
 		// EventStatHandle accessors
 		F64 getSum(const TraceType<EventAccumulator>& stat);
 		template <typename T>
-		T getSum(const EventStatHandle<T>& stat)
+		typename RelatedTypes<T>::sum_t getSum(const EventStatHandle<T>& stat)
 		{
-			return (T)getSum(static_cast<const TraceType<EventAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const TraceType<EventAccumulator>&> (stat));
 		}
 
 		F64 getMin(const TraceType<EventAccumulator>& stat);
@@ -249,16 +270,16 @@ namespace LLTrace
 
 		F64 getMean(const TraceType<EventAccumulator>& stat);
 		template <typename T>
-		T getMean(EventStatHandle<T>& stat)
+		typename RelatedTypes<T>::fractional_t getMean(EventStatHandle<T>& stat)
 		{
-			return (T)getMean(static_cast<const TraceType<EventAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const TraceType<EventAccumulator>&> (stat));
 		}
 
 		F64 getStandardDeviation(const TraceType<EventAccumulator>& stat);
 		template <typename T>
-		T getStandardDeviation(const EventStatHandle<T>& stat)
+		typename RelatedTypes<T>::fractional_t getStandardDeviation(const EventStatHandle<T>& stat)
 		{
-			return (T)getStandardDeviation(static_cast<const TraceType<EventAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const TraceType<EventAccumulator>&> (stat));
 		}
 
 		F64 getLastValue(const TraceType<EventAccumulator>& stat);
@@ -284,9 +305,11 @@ namespace LLTrace
 		// returns data for current thread
 		class ThreadRecorder* getThreadRecorder(); 
 
-		LLTimer				mSamplingTimer;
-		LLUnit<F64, LLUnits::Seconds>			mElapsedSeconds;
+		LLTimer											mSamplingTimer;
+		LLUnit<F64, LLUnits::Seconds>					mElapsedSeconds;
 		LLCopyOnWritePointer<AccumulatorBufferGroup>	mBuffers;
+		bool											mInHandOff;
+
 	};
 
 	class LL_COMMON_API PeriodicRecording
@@ -310,11 +333,15 @@ namespace LLTrace
 		const Recording& getPrevRecording(U32 offset) const;
 		Recording snapshotCurRecording() const;
 
+		//
+		// PERIODIC MIN
+		//
+
 		// catch all for stats that have a defined sum
 		template <typename T>
 		typename T::value_t getPeriodMin(const TraceType<T>& stat, size_t num_periods = U32_MAX)
 		{
-			size_t total_periods = mRecordingPeriods.size();
+			size_t total_periods = mNumPeriods;
 			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();
@@ -326,6 +353,12 @@ namespace LLTrace
 			return min_val;
 		}
 
+		template<typename T>
+		T getPeriodMin(const CountStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		{
+			return T(getPeriodMin(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
+		}
+
 		F64 getPeriodMin(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX);
 		template<typename T>
 		T getPeriodMin(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX)
@@ -341,9 +374,9 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		F64 getPeriodMinPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
 		{
-			size_t total_periods = mRecordingPeriods.size();
+			size_t total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 			F64 min_val = std::numeric_limits<F64>::max();
@@ -352,14 +385,24 @@ namespace LLTrace
 				S32 index = (mCurPeriod + total_periods - i) % total_periods;
 				min_val = llmin(min_val, mRecordingPeriods[index].getPerSec(stat));
 			}
-			return min_val;
+			return (typename RelatedTypes<typename T::value_t>::fractional_t) min_val;
+		}
+
+		template<typename T>
+		typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		{
+			return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
 		}
 
+		//
+		// PERIODIC MAX
+		//
+
 		// catch all for stats that have a defined sum
 		template <typename T>
 		typename T::value_t getPeriodMax(const TraceType<T>& stat, size_t num_periods = U32_MAX)
 		{
-			size_t total_periods = mRecordingPeriods.size();
+			size_t total_periods = mNumPeriods;
 			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();
@@ -371,6 +414,12 @@ namespace LLTrace
 			return max_val;
 		}
 
+		template<typename T>
+		T getPeriodMax(const CountStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		{
+			return T(getPeriodMax(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
+		}
+
 		F64 getPeriodMax(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX);
 		template<typename T>
 		T getPeriodMax(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX)
@@ -386,9 +435,9 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		F64 getPeriodMaxPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
 		{
-			size_t total_periods = mRecordingPeriods.size();
+			size_t total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 			F64 max_val = std::numeric_limits<F64>::min();
@@ -397,14 +446,24 @@ namespace LLTrace
 				S32 index = (mCurPeriod + total_periods - i) % total_periods;
 				max_val = llmax(max_val, mRecordingPeriods[index].getPerSec(stat));
 			}
-			return max_val;
+			return (typename RelatedTypes<typename T::value_t>::fractional_t)max_val;
+		}
+
+		template<typename T>
+		typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		{
+			return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
 		}
 
+		//
+		// PERIODIC MEAN
+		//
+
 		// catch all for stats that have a defined sum
 		template <typename T>
 		typename T::mean_t getPeriodMean(const TraceType<T >& stat, size_t num_periods = U32_MAX)
 		{
-			size_t total_periods = mRecordingPeriods.size();
+			size_t total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 			typename T::mean_t mean = 0;
@@ -422,24 +481,29 @@ namespace LLTrace
 			return mean;
 		}
 
+		template<typename T>
+		typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		{
+			return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
+		}
 		F64 getPeriodMean(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX);
 		template<typename T> 
-		T getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX)
 		{
-			return T(getPeriodMean(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods));
+			return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods));
 		}
 
 		F64 getPeriodMean(const TraceType<EventAccumulator>& stat, size_t num_periods = U32_MAX);
 		template<typename T>
-		T getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = U32_MAX)
 		{
-			return T(getPeriodMean(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
+			return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
 		template <typename T>
-		typename T::mean_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<typename T::mean_t>::fractional_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
 		{
-			size_t total_periods = mRecordingPeriods.size();
+			size_t total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 			typename T::mean_t mean = 0;
@@ -454,7 +518,13 @@ namespace LLTrace
 				}
 			}
 			mean = mean / num_periods;
-			return mean;
+			return (typename RelatedTypes<typename T::mean_t>::fractional_t)mean;
+		}
+
+		template<typename T>
+		typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		{
+			return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
 		}
 
 	private:
@@ -504,11 +574,10 @@ namespace LLTrace
 		ExtendablePeriodicRecording();
 		void extend();
 
-		PeriodicRecording& getAcceptedRecording()				{ return mAcceptedRecording; }
-		const PeriodicRecording& getAcceptedRecording() const	{return mAcceptedRecording;}
+		PeriodicRecording& getResults()				{ return mAcceptedRecording; }
+		const PeriodicRecording& getResults() const	{return mAcceptedRecording;}
 		
-		PeriodicRecording& getPotentialRecording()				{ return mPotentialRecording; }
-		const PeriodicRecording& getPotentialRecording() const	{return mPotentialRecording;}
+		void nextPeriod() { mPotentialRecording.nextPeriod(); }
 
 	private:
 		// implementation for LLStopWatchControlsMixin
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 7ac0e75154..e20d8b63de 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -120,13 +120,17 @@ TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode( S32 index )
 }
 
 
-void ThreadRecorder::activate( AccumulatorBufferGroup* recording )
+void ThreadRecorder::activate( AccumulatorBufferGroup* recording, bool from_handoff )
 {
 	ActiveRecording* active_recording = new ActiveRecording(recording);
 	if (!mActiveRecordings.empty())
 	{
 		AccumulatorBufferGroup& prev_active_recording = mActiveRecordings.back()->mPartialRecording;
 		prev_active_recording.sync();
+		if (!from_handoff)
+		{
+			TimeBlock::updateTimes();
+		}
 		prev_active_recording.handOffTo(active_recording->mPartialRecording);
 	}
 	mActiveRecordings.push_back(active_recording);
@@ -240,6 +244,7 @@ void ThreadRecorder::pushToParent()
 	{ LLMutexLock lock(&mSharedRecordingMutex);	
 		LLTrace::get_thread_recorder()->bringUpToDate(&mThreadRecordingBuffers);
 		mSharedRecordingBuffers.append(mThreadRecordingBuffers);
+		mThreadRecordingBuffers.reset();
 	}
 }
 	
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index 535f855200..c40228785e 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -47,7 +47,7 @@ namespace LLTrace
 
 		~ThreadRecorder();
 
-		void activate(AccumulatorBufferGroup* recording);
+		void activate(AccumulatorBufferGroup* recording, bool from_handoff = false);
 		void deactivate(AccumulatorBufferGroup* recording);
 		active_recording_list_t::reverse_iterator bringUpToDate(AccumulatorBufferGroup* recording);
 
-- 
cgit v1.2.3


From bd078122e3a87e958fb6b0ea9caeef885298d527 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 15 Jul 2013 21:00:19 -0700
Subject: SH-4299 FIX: Interesting: High fps shown temporarily off scale in
 statistics console timing of scene load recording extension now guaranteed >
 requested time step removed double add of recorded data removed spam

---
 indra/llcommon/lltracerecording.cpp | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 875c371068..5d43771cb2 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -367,9 +367,6 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 
 	if (mAutoResize)
 	{
-		// append first recording into our current slot
-		getCurRecording().appendRecording(other.mRecordingPeriods[other_oldest_recording_index]);
-
 		// push back recordings for everything in the middle
 		U32 other_index = (other_oldest_recording_index + 1) % other_recording_slots;
 		while (other_index != other_current_recording_index)
-- 
cgit v1.2.3


From 29930baf23fbd8cd147cd78f60d01496479ae78e Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 17 Jul 2013 10:56:47 -0700
Subject: SH-4299 WIP: Interesting: High fps shown temporarily off scale in
 statistics console made unit types work with ostreams fixed timing of scene
 monitor recordings to better respect requested time diff

---
 indra/llcommon/lltracerecording.cpp |  1 -
 indra/llcommon/llunit.h             | 13 +++++++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 5d43771cb2..48b5a7c3fa 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -41,7 +41,6 @@ namespace LLTrace
 Recording::Recording(EPlayState state) 
 :	mElapsedSeconds(0),
 	mInHandOff(false)
-
 {
 	mBuffers = new AccumulatorBufferGroup();
 	setPlayState(state);
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 79465715cf..2e09973ef6 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -138,6 +138,13 @@ protected:
 	storage_t mValue;
 };
 
+template<typename STORAGE_TYPE, typename UNIT_TYPE>
+std::ostream& operator <<(std::ostream& s, const LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit)
+{
+	s << unit.value() << UNIT_TYPE::getUnitLabel();
+	return s;
+}
+
 template<typename STORAGE_TYPE, typename UNIT_TYPE>
 struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
 {
@@ -162,6 +169,12 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
 	}
 };
 
+template<typename STORAGE_TYPE, typename UNIT_TYPE>
+std::ostream& operator <<(std::ostream& s, const LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>& unit)
+{
+	s << unit.value() << UNIT_TYPE::getUnitLabel();
+	return s;
+}
 
 template<typename S1, typename T1, typename S2, typename T2>
 LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ...)
-- 
cgit v1.2.3


From 862cdf3061d66dfe4ae482f24436960b136a3ce4 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 18 Jul 2013 15:08:46 -0700
Subject: SH-4297 WIP interesting: viewer-interesting starts loading cached
 scene late fixed ostream precision munging in llsys

---
 indra/llcommon/llfasttimer.cpp | 67 +++++++++++++++++++++---------------------
 indra/llcommon/llsys.cpp       |  7 ++++-
 indra/llcommon/llthread.cpp    |  8 ++---
 3 files changed, 43 insertions(+), 39 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index a72f16d385..79aa0c8722 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -117,22 +117,22 @@ struct SortTimerByName
 };
 
 TimeBlock& TimeBlock::getRootTimeBlock()
-	{
+{
 	static TimeBlock root_timer("root", NULL);
 	return root_timer;
-	}
+}
 
 void TimeBlock::pushLog(LLSD log)
-	{
+{
 	LLMutexLock lock(sLogLock);
 
 	sLogQueue.push(log);
-	}
+}
 
 void TimeBlock::setLogLock(LLMutex* lock)
-	{
+{
 	sLogLock = lock;
-	}
+}
 
 
 //static
@@ -166,8 +166,7 @@ U64 TimeBlock::countsPerSecond()
 
 TimeBlock::TimeBlock(const char* name, TimeBlock* parent)
 :	TraceType<TimeBlockAccumulator>(name)
-{
-}
+{}
 
 TimeBlockTreeNode& TimeBlock::getTreeNode() const
 {
@@ -182,7 +181,7 @@ void TimeBlock::bootstrapTimerTree()
 	for (LLInstanceTracker<TimeBlock>::instance_iter begin_it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(), it = begin_it; 
 		it != end_it; 
 		++it)
-		{
+	{
 		TimeBlock& timer = *it;
 		if (&timer == &TimeBlock::getRootTimeBlock()) continue;
 
@@ -193,13 +192,13 @@ void TimeBlock::bootstrapTimerTree()
 			TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
 
 			if (accumulator->mLastCaller)
-	{
+			{
 				timer.setParent(accumulator->mLastCaller);
 				accumulator->mParent = accumulator->mLastCaller;
-	}
+			}
 			// no need to push up tree on first use, flag can be set spuriously
 			accumulator->mMoveUpTree = false;
-}
+		}
 	}
 }
 
@@ -217,32 +216,32 @@ void TimeBlock::incrementalUpdateTimerTree()
 		// sort timers by time last called, so call graph makes sense
 		TimeBlockTreeNode& tree_node = timerp->getTreeNode();
 		if (tree_node.mNeedsSorting)
-			{
+		{
 			std::sort(tree_node.mChildren.begin(), tree_node.mChildren.end(), SortTimerByName());
-	}
+		}
 
 		// skip root timer
 		if (timerp != &TimeBlock::getRootTimeBlock())
-	{
+		{
 			TimeBlockAccumulator* accumulator = timerp->getPrimaryAccumulator();
 
 			if (accumulator->mMoveUpTree)
-		{
-				// since ancestors have already been visited, re-parenting 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());
-				accumulator->mParent = timerp->getParent();
-				accumulator->mMoveUpTree = false;
-
-			// don't bubble up any ancestors until descendants are done bubbling up
-				// as ancestors may call this timer only on certain paths, so we want to resolve
-				// child-most block locations before their parents
-			it.skipAncestors();
+			{
+					// since ancestors have already been visited, re-parenting 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());
+					accumulator->mParent = timerp->getParent();
+					accumulator->mMoveUpTree = false;
+
+				// don't bubble up any ancestors until descendants are done bubbling up
+					// as ancestors may call this timer only on certain paths, so we want to resolve
+					// child-most block locations before their parents
+				it.skipAncestors();
+			}
 		}
 	}
-	}
 }
 
 
@@ -308,12 +307,12 @@ void TimeBlock::processTimes()
 }
 
 std::vector<TimeBlock*>::iterator TimeBlock::beginChildren()
-		{
+{
 	return getTreeNode().mChildren.begin(); 
-		}
+}
 
 std::vector<TimeBlock*>::iterator TimeBlock::endChildren()
-		{
+{
 	return getTreeNode().mChildren.end();
 }
 
@@ -373,7 +372,7 @@ void TimeBlock::logStats()
 
 //static
 void TimeBlock::dumpCurTimes()
-	{
+{
 	LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
 	LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording();
 
@@ -462,7 +461,7 @@ void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
 		mParent = other->mParent;
 	}
 	else
-{
+	{
 		mStartTotalTimeCounter = mTotalTimeCounter;
 	}
 }
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 95bbcbc816..5d805ba841 100755
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -1395,9 +1395,14 @@ public:
             LL_CONT << "slowest framerate for last " << int(prevSize * MEM_INFO_THROTTLE)
                     << " seconds ";
         }
+
+		S32 precision = LL_CONT.precision();
+
         LL_CONT << std::fixed << std::setprecision(1) << framerate << '\n'
-                << LLMemoryInfo() << LL_ENDL;
+                << LLMemoryInfo();
 
+		LL_CONT.precision(precision);
+		LL_CONT << LL_ENDL;
         return false;
     }
 
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index e0f53fb9c4..db7ddbbfd3 100755
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -47,13 +47,13 @@ const DWORD MS_VC_EXCEPTION=0x406D1388;
 typedef struct tagTHREADNAME_INFO
 {
 	DWORD dwType; // Must be 0x1000.
-	const char* szName; // Pointer to name (in user addr space).
+	LPCSTR szName; // Pointer to name (in user addr space).
 	DWORD dwThreadID; // Thread ID (-1=caller thread).
 	DWORD dwFlags; // Reserved for future use, must be zero.
 } THREADNAME_INFO;
 #pragma pack(pop)
 
-void SetThreadName( DWORD dwThreadID, const char* threadName)
+void set_thread_name( DWORD dwThreadID, const char* threadName)
 {
 	THREADNAME_INFO info;
 	info.dwType = 0x1000;
@@ -63,7 +63,7 @@ void SetThreadName( DWORD dwThreadID, const char* threadName)
 
 	__try
 	{
-		RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info );
+		::RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info );
 	}
 	__except(EXCEPTION_CONTINUE_EXECUTION)
 	{
@@ -127,7 +127,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 	LLThread *threadp = (LLThread *)datap;
 
 #ifdef LL_WINDOWS
-	SetThreadName(-1, threadp->mName.c_str());
+	set_thread_name(-1, threadp->mName.c_str());
 #endif
 
 
-- 
cgit v1.2.3


From 075a7bcc980b0ca0d2888d344b6afa8ab5b52d85 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 18 Jul 2013 15:09:45 -0700
Subject: SH-4297 WIP interesting: viewer-interesting starts loading cached
 scene late dependency cleanup - removed a lot of unecessary includes

---
 indra/llcommon/llevent.h           |  1 -
 indra/llcommon/llinstancetracker.h |  3 --
 indra/llcommon/llmutex.h           | 21 +++++-----
 indra/llcommon/llpointer.h         | 79 +++++++++++++++++++++++++++++++++++++
 indra/llcommon/llptrto.h           |  1 -
 indra/llcommon/llsdparam.cpp       |  1 +
 indra/llcommon/llthread.h          | 81 +-------------------------------------
 indra/llcommon/lltrace.h           |  3 ++
 indra/llcommon/llunit.h            | 26 ++++++++----
 9 files changed, 114 insertions(+), 102 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llevent.h b/indra/llcommon/llevent.h
index 8cd682b8bf..9d3a7a654a 100755
--- a/indra/llcommon/llevent.h
+++ b/indra/llcommon/llevent.h
@@ -30,7 +30,6 @@
 
 #include "llsd.h"
 #include "llpointer.h"
-#include "llthread.h"
 
 namespace LLOldEvents
 {
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index c8e1d9cd84..f4e37d21fe 100755
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -32,9 +32,6 @@
 #include <typeinfo>
 
 #include "string_table.h"
-#include <boost/utility.hpp>
-#include <boost/function.hpp>
-#include <boost/bind.hpp>
 #include <boost/iterator/transform_iterator.hpp>
 #include <boost/iterator/indirect_iterator.hpp>
 
diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h
index cbde4c47a9..db5b9357d9 100644
--- a/indra/llcommon/llmutex.h
+++ b/indra/llcommon/llmutex.h
@@ -27,13 +27,16 @@
 #ifndef LL_LLMUTEX_H
 #define LL_LLMUTEX_H
 
-#include "llapr.h"
-#include "apr_thread_cond.h"
+#include "stdtypes.h"
 
 //============================================================================
 
 #define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
 
+struct apr_thread_mutex_t;
+struct apr_pool_t;
+struct apr_thread_cond_t;
+
 class LL_COMMON_API LLMutex
 {
 public:
@@ -45,18 +48,18 @@ public:
 	LLMutex(apr_pool_t *apr_poolp = NULL); // NULL pool constructs a new pool for the mutex
 	virtual ~LLMutex();
 	
-	void lock();		// blocks
+	void lock();		       // blocks
 	void unlock();
-	bool isLocked(); 	// non-blocking, but does do a lock/unlock so not free
-	bool isSelfLocked(); //return true if locked in a same thread
+	bool isLocked(); 	       // non-blocking, but does do a lock/unlock so not free
+	bool isSelfLocked();       //return true if locked in a same thread
 	U32 lockingThread() const; //get ID of locking thread
 	
 protected:
-	apr_thread_mutex_t *mAPRMutexp;
+	apr_thread_mutex_t*	mAPRMutexp;
 	mutable U32			mCount;
 	mutable U32			mLockingThread;
 	
-	apr_pool_t			*mAPRPoolp;
+	apr_pool_t*			mAPRPoolp;
 	BOOL				mIsLocalPool;
 	
 #if MUTEX_DEBUG
@@ -68,7 +71,7 @@ protected:
 class LL_COMMON_API LLCondition : public LLMutex
 {
 public:
-	LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well.
+	LLCondition(apr_pool_t* apr_poolp); // Defaults to global pool, could use the thread pool as well.
 	~LLCondition();
 	
 	void wait();		// blocks
@@ -76,7 +79,7 @@ public:
 	void broadcast();
 	
 protected:
-	apr_thread_cond_t *mAPRCondp;
+	apr_thread_cond_t* mAPRCondp;
 };
 
 class LLMutexLock
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index c827996db1..9a0726c338 100755
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -27,6 +27,7 @@
 #define LLPOINTER_H
 
 #include "llerror.h"	// *TODO: consider eliminating this
+#include "llmutex.h"
 
 //----------------------------------------------------------------------------
 // RefCount objects should generally only be accessed by way of LLPointer<>'s
@@ -213,4 +214,82 @@ private:
 	bool mStayUnique;
 };
 
+//============================================================================
+
+// see llmemory.h for LLPointer<> definition
+
+class LL_COMMON_API LLThreadSafeRefCount
+{
+public:
+	static void initThreadSafeRefCount(); // creates sMutex
+	static void cleanupThreadSafeRefCount(); // destroys sMutex
+	
+private:
+	static LLMutex* sMutex;
+
+protected:
+	virtual ~LLThreadSafeRefCount(); // use unref()
+	
+public:
+	LLThreadSafeRefCount();
+	LLThreadSafeRefCount(const LLThreadSafeRefCount&);
+	LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref) 
+	{
+		if (sMutex)
+		{
+			sMutex->lock();
+		}
+		mRef = 0;
+		if (sMutex)
+		{
+			sMutex->unlock();
+		}
+		return *this;
+	}
+	
+	void ref()
+	{
+		if (sMutex) sMutex->lock();
+		mRef++; 
+		if (sMutex) sMutex->unlock();
+	} 
+
+	S32 unref()
+	{
+		llassert(mRef >= 1);
+		if (sMutex) sMutex->lock();
+		S32 res = --mRef;
+		if (sMutex) sMutex->unlock();
+		if (0 == res) 
+		{
+			delete this; 
+			return 0;
+		}
+		return res;
+	}	
+	S32 getNumRefs() const
+	{
+		return mRef;
+	}
+
+private: 
+	S32	mRef; 
+};
+
+/**
+ * intrusive pointer support for LLThreadSafeRefCount
+ * this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type
+ */
+namespace boost
+{
+	inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p) 
+	{
+		p->ref();
+	}
+
+	inline void intrusive_ptr_release(LLThreadSafeRefCount* p) 
+	{
+		p->unref(); 
+	}
+};
 #endif
diff --git a/indra/llcommon/llptrto.h b/indra/llcommon/llptrto.h
index 7091d36f6b..4082e30de6 100755
--- a/indra/llcommon/llptrto.h
+++ b/indra/llcommon/llptrto.h
@@ -33,7 +33,6 @@
 
 #include "llpointer.h"
 #include "llrefcount.h"             // LLRefCount
-#include "llthread.h"               // LLThreadSafeRefCount
 #include <boost/type_traits/is_base_of.hpp>
 #include <boost/type_traits/remove_pointer.hpp>
 #include <boost/utility/enable_if.hpp>
diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp
index 50815b2cc6..c1ba777543 100755
--- a/indra/llcommon/llsdparam.cpp
+++ b/indra/llcommon/llsdparam.cpp
@@ -30,6 +30,7 @@
 // Project includes
 #include "llsdparam.h"
 #include "llsdutil.h"
+#include "boost/bind.hpp"
 
 static 	LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
 static 	LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 4a84a14a65..c2c6b8e7ac 100755
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -32,6 +32,7 @@
 #include "apr_thread_cond.h"
 #include "boost/intrusive_ptr.hpp"
 #include "llmutex.h"
+#include "llpointer.h"
 
 LL_COMMON_API void assert_main_thread();
 
@@ -148,86 +149,6 @@ void LLThread::unlockData()
 
 //============================================================================
 
-// see llmemory.h for LLPointer<> definition
-
-class LL_COMMON_API LLThreadSafeRefCount
-{
-public:
-	static void initThreadSafeRefCount(); // creates sMutex
-	static void cleanupThreadSafeRefCount(); // destroys sMutex
-	
-private:
-	static LLMutex* sMutex;
-
-protected:
-	virtual ~LLThreadSafeRefCount(); // use unref()
-	
-public:
-	LLThreadSafeRefCount();
-	LLThreadSafeRefCount(const LLThreadSafeRefCount&);
-	LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref) 
-	{
-		if (sMutex)
-		{
-			sMutex->lock();
-		}
-		mRef = 0;
-		if (sMutex)
-		{
-			sMutex->unlock();
-		}
-		return *this;
-	}
-
-
-	
-	void ref()
-	{
-		if (sMutex) sMutex->lock();
-		mRef++; 
-		if (sMutex) sMutex->unlock();
-	} 
-
-	S32 unref()
-	{
-		llassert(mRef >= 1);
-		if (sMutex) sMutex->lock();
-		S32 res = --mRef;
-		if (sMutex) sMutex->unlock();
-		if (0 == res) 
-		{
-			delete this; 
-			return 0;
-		}
-		return res;
-	}	
-	S32 getNumRefs() const
-	{
-		return mRef;
-	}
-
-private: 
-	S32	mRef; 
-};
-
-/**
- * intrusive pointer support for LLThreadSafeRefCount
- * this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type
- */
-namespace boost
-{
-	inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p) 
-	{
-		p->ref();
-	}
-
-	inline void intrusive_ptr_release(LLThreadSafeRefCount* p) 
-	{
-		p->unref(); 
-	}
-};
-//============================================================================
-
 // Simple responder for self destructing callbacks
 // Pure virtual class
 class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 2c84b1596a..75e913a348 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -123,6 +123,7 @@ class EventStatHandle
 public:
 	typedef F64 storage_t;
 	typedef TraceType<EventAccumulator> trace_t;
+	typedef EventStatHandle<T> self_t;
 
 	EventStatHandle(const char* name, const char* description = NULL)
 	:	trace_t(name, description)
@@ -146,6 +147,7 @@ class SampleStatHandle
 public:
 	typedef F64 storage_t;
 	typedef TraceType<SampleAccumulator> trace_t;
+	typedef SampleStatHandle<T> self_t;
 
 	SampleStatHandle(const char* name, const char* description = NULL)
 	:	trace_t(name, description)
@@ -168,6 +170,7 @@ class CountStatHandle
 public:
 	typedef F64 storage_t;
 	typedef TraceType<CountAccumulator> trace_t;
+	typedef CountStatHandle<T> self_t;
 
 	CountStatHandle(const char* name, const char* description = NULL) 
 	:	trace_t(name, description)
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 79465715cf..731cc0eded 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -30,12 +30,12 @@
 #include "stdtypes.h"
 #include "llpreprocessor.h"
 #include "llerrorlegacy.h"
-#include <boost/type_traits/is_same.hpp>
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE>
 struct LLUnit
 {
 	typedef LLUnit<STORAGE_TYPE, UNIT_TYPE> self_t;
+
 	typedef STORAGE_TYPE storage_t;
 
 	// value initialization
@@ -163,18 +163,28 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
 };
 
 
+template<typename S, typename T> 
+struct LLIsSameType
+{
+	static const bool value = false;
+};
+
+template<typename T>
+struct LLIsSameType<T, T>
+{
+	static const bool value = true;
+};
+
 template<typename S1, typename T1, typename S2, typename T2>
 LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ...)
 {
-	typedef boost::integral_constant<bool, 
-									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> conversion_valid_t;
-	LL_STATIC_ASSERT(conversion_valid_t::value, "invalid conversion");
+	LL_STATIC_ASSERT((LLIsSameType<T1, T2>::value 
+		|| !LLIsSameType<T1, typename T1::base_unit_t>::value 
+		|| !LLIsSameType<T2, typename T2::base_unit_t>::value), "invalid conversion");
 
-	if (boost::is_same<T1, typename T1::base_unit_t>::value)
+	if (LLIsSameType<T1, typename T1::base_unit_t>::value)
 	{
-		if (boost::is_same<T2, typename T2::base_unit_t>::value)
+		if (LLIsSameType<T2, typename T2::base_unit_t>::value)
 
 		{
 			// T1 and T2 fully reduced and equal...just copy
-- 
cgit v1.2.3


From e40065f82c797eab41006a448c838f4f1089a2e8 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 19 Jul 2013 15:03:05 -0700
Subject: BUILDFIX: #include and dependency cleanup

---
 indra/llcommon/llcommonutils.h       |   2 +
 indra/llcommon/llcriticaldamp.cpp    |   2 +-
 indra/llcommon/llcriticaldamp.h      |   4 +-
 indra/llcommon/lldate.cpp            |   2 +-
 indra/llcommon/lldate.h              |   2 +-
 indra/llcommon/llfasttimer.cpp       |  22 +++----
 indra/llcommon/llinitparam.h         |   1 +
 indra/llcommon/llsdutil.h            |   2 +-
 indra/llcommon/llstring.cpp          |   1 +
 indra/llcommon/llstring.h            |   6 +-
 indra/llcommon/llsys.cpp             |   6 +-
 indra/llcommon/lltraceaccumulators.h |   1 +
 indra/llcommon/lltracerecording.cpp  |  38 ++++++------
 indra/llcommon/llunit.h              | 110 ++++++++++++++++++++---------------
 indra/llcommon/lluuid.h              |   1 +
 15 files changed, 111 insertions(+), 89 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llcommonutils.h b/indra/llcommon/llcommonutils.h
index 755dc41fb4..20ada27830 100755
--- a/indra/llcommon/llcommonutils.h
+++ b/indra/llcommon/llcommonutils.h
@@ -27,6 +27,8 @@
 #ifndef LL_LLCOMMONUTILS_H
 #define LL_LLCOMMONUTILS_H
 
+#include "lluuid.h"
+
 namespace LLCommonUtils
 {
 	/**
diff --git a/indra/llcommon/llcriticaldamp.cpp b/indra/llcommon/llcriticaldamp.cpp
index 575fc4149e..5ffad88973 100755
--- a/indra/llcommon/llcriticaldamp.cpp
+++ b/indra/llcommon/llcriticaldamp.cpp
@@ -81,7 +81,7 @@ void LLSmoothInterpolation::updateInterpolants()
 //-----------------------------------------------------------------------------
 // getInterpolant()
 //-----------------------------------------------------------------------------
-F32 LLSmoothInterpolation::getInterpolant(LLUnit<F32, LLUnits::Seconds> time_constant, bool use_cache)
+F32 LLSmoothInterpolation::getInterpolant(LLUnitImplicit<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 e174643cd0..7b2a414459 100755
--- a/indra/llcommon/llcriticaldamp.h
+++ b/indra/llcommon/llcriticaldamp.h
@@ -42,10 +42,10 @@ public:
 	static void updateInterpolants();
 
 	// ACCESSORS
-	static F32 getInterpolant(LLUnit<F32, LLUnits::Seconds> time_constant, bool use_cache = true);
+	static F32 getInterpolant(LLUnitImplicit<F32, LLUnits::Seconds> time_constant, bool use_cache = true);
 
 	template<typename T> 
-	static T lerp(T a, T b, LLUnit<F32, LLUnits::Seconds> time_constant, bool use_cache = true)
+	static T lerp(T a, T b, LLUnitImplicit<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 7892269e35..cec4047c1f 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<F64, LLUnits::Seconds> seconds_since_epoch) :
+LLDate::LLDate(LLUnitImplicit<F64, LLUnits::Seconds> seconds_since_epoch) :
 	mSecondsSinceEpoch(seconds_since_epoch.value())
 {}
 
diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h
index 1067ac5280..816bc62b14 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<F64, LLUnits::Seconds> seconds_since_epoch);
+	LLDate(LLUnitImplicit<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 79aa0c8722..6f046c18ff 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -111,9 +111,9 @@ static timer_tree_dfs_iterator_t end_timer_tree()
 struct SortTimerByName
 {
 	bool operator()(const TimeBlock* i1, const TimeBlock* i2)
-	{
+        {
 		return i1->getName() < i2->getName();
-	}
+        }
 };
 
 TimeBlock& TimeBlock::getRootTimeBlock()
@@ -227,17 +227,17 @@ void TimeBlock::incrementalUpdateTimerTree()
 
 			if (accumulator->mMoveUpTree)
 			{
-					// since ancestors have already been visited, re-parenting won't affect tree traversal
+				// since ancestors have already been visited, re-parenting 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());
-					accumulator->mParent = timerp->getParent();
-					accumulator->mMoveUpTree = false;
+				accumulator->mParent = timerp->getParent();
+				accumulator->mMoveUpTree = false;
 
 				// don't bubble up any ancestors until descendants are done bubbling up
-					// as ancestors may call this timer only on certain paths, so we want to resolve
-					// child-most block locations before their parents
+				// as ancestors may call this timer only on certain paths, so we want to resolve
+				// child-most block locations before their parents
 				it.skipAncestors();
 			}
 		}
@@ -357,7 +357,7 @@ void TimeBlock::logStats()
 				// doesn't work correctly on the first frame
 				total_time += frame_recording.getLastRecording().getSum(timer);
 			}
-		}
+}
 
 		sd["Total"]["Time"] = (LLSD::Real) total_time.value();
 		sd["Total"]["Calls"] = (LLSD::Integer) 1;
@@ -366,7 +366,7 @@ void TimeBlock::logStats()
 			LLMutexLock lock(sLogLock);
 			sLogQueue.push(sd);
 		}
-	}
+}
 
 }
 
@@ -413,7 +413,7 @@ void TimeBlock::writeLog(std::ostream& os)
 		LLSDSerialize::toXML(sd, os);
 		LLMutexLock lock(sLogLock);
 		sLogQueue.pop();
-	}
+			}
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -470,7 +470,7 @@ LLUnit<F64, LLUnits::Seconds> BlockTimer::getElapsedTime()
 {
 	U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
 
-	return (F64)total_time / (F64)TimeBlock::countsPerSecond();
+	return LLUnits::Seconds::fromValue((F64)total_time / (F64)TimeBlock::countsPerSecond());
 }
 
 
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index 879ea4fe2a..812071efdd 100755
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -38,6 +38,7 @@
 #include "llerror.h"
 #include "llstl.h"
 #include "llpredicate.h"
+#include "llsd.h"
 
 namespace LLTypeTags
 {
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index 532d3f9341..d0b536c39a 100755
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -29,7 +29,7 @@
 #ifndef LL_LLSDUTIL_H
 #define LL_LLSDUTIL_H
 
-class LLSD;
+#include "llsd.h"
 
 // U32
 LL_COMMON_API LLSD ll_sd_from_U32(const U32);
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index 66c416bfdd..6f92c7d5d4 100755
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -29,6 +29,7 @@
 #include "llstring.h"
 #include "llerror.h"
 #include "llfasttimer.h"
+#include "llsd.h"
 
 #if LL_WINDOWS
 #include "llwin32headerslean.h"
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 17893c1910..fdf9f3ce89 100755
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -29,10 +29,11 @@
 
 #include <string>
 #include <cstdio>
-#include <locale>
+//#include <locale>
 #include <iomanip>
 #include <algorithm>
-#include "llsd.h"
+#include <vector>
+#include <map>
 #include "llformat.h"
 
 #if LL_LINUX || LL_SOLARIS
@@ -50,6 +51,7 @@
 #endif
 
 const char LL_UNKNOWN_CHAR = '?';
+class LLSD;
 
 #if LL_DARWIN || LL_LINUX || LL_SOLARIS
 // Template specialization of char_traits for U16s. Only necessary on Mac and Linux (exists on Windows already)
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 5d805ba841..8d2045dfa0 100755
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -1396,13 +1396,13 @@ public:
                     << " seconds ";
         }
 
-		S32 precision = LL_CONT.precision();
+	S32 precision = LL_CONT.precision();
 
         LL_CONT << std::fixed << std::setprecision(1) << framerate << '\n'
                 << LLMemoryInfo();
 
-		LL_CONT.precision(precision);
-		LL_CONT << LL_ENDL;
+	LL_CONT.precision(precision);
+	LL_CONT << LL_ENDL;
         return false;
     }
 
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index a2f9f4c090..efc8b43f6a 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -34,6 +34,7 @@
 #include "lltimer.h"
 #include "llrefcount.h"
 #include "llthreadlocalstorage.h"
+#include <limits>
 
 namespace LLTrace
 {
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 48b5a7c3fa..2150a44f12 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -95,7 +95,7 @@ void Recording::handleReset()
 {
 	mBuffers.write()->reset();
 
-	mElapsedSeconds = 0.0;
+	mElapsedSeconds = LLUnits::Seconds::fromValue(0.0);
 	mSamplingTimer.reset();
 }
 
@@ -131,14 +131,14 @@ void Recording::appendRecording( Recording& other )
 LLUnit<F64, LLUnits::Seconds> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
-	return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
-				/ (F64)LLTrace::TimeBlock::countsPerSecond();
+	return LLUnits::Seconds::fromValue((F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
+				/ (F64)LLTrace::TimeBlock::countsPerSecond());
 }
 
 LLUnit<F64, LLUnits::Seconds> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
-	return (F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond();
+	return LLUnits::Seconds::fromValue((F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond());
 }
 
 
@@ -151,16 +151,16 @@ LLUnit<F64, LLUnits::Seconds> Recording::getPerSec(const TraceType<TimeBlockAccu
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
-	return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
-				/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value());
+	return LLUnits::Seconds::fromValue((F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
+				/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()));
 }
 
 LLUnit<F64, LLUnits::Seconds> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
-	return (F64)(accumulator.mSelfTimeCounter) 
-			/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value());
+	return LLUnits::Seconds::fromValue((F64)(accumulator.mSelfTimeCounter) 
+			/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()));
 }
 
 F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat)
@@ -170,52 +170,52 @@ F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>&
 
 LLUnit<F64, LLUnits::Bytes> Recording::getMin(const TraceType<MemStatAccumulator>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mSize.getMin();
+	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mSize.getMin());
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getMean(const TraceType<MemStatAccumulator>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mSize.getMean();
+	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mSize.getMean());
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getMax(const TraceType<MemStatAccumulator>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mSize.getMax();
+	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mSize.getMax());
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation();
+	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation());
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getLastValue(const TraceType<MemStatAccumulator>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue();
+	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue());
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMin();
+	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMin());
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMean();
+	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMean());
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMax();
+	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMax());
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mChildSize.getStandardDeviation();
+	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mChildSize.getStandardDeviation());
 }
 
 LLUnit<F64, LLUnits::Bytes> Recording::getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mChildSize.getLastValue();
+	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mChildSize.getLastValue());
 }
 
 U32 Recording::getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat)
@@ -603,7 +603,7 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat,
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-	LLUnit<F64, LLUnits::Seconds> total_duration = 0.f;
+	LLUnit<F64, LLUnits::Seconds> total_duration(0.f);
 
 	F64 mean = 0;
 	if (num_periods <= 0) { return mean; }
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 51f14a5948..f81e746c77 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -141,8 +141,17 @@ protected:
 template<typename STORAGE_TYPE, typename UNIT_TYPE>
 std::ostream& operator <<(std::ostream& s, const LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit)
 {
-	s << unit.value() << UNIT_TYPE::getUnitLabel();
-	return s;
+        s << unit.value() << UNIT_TYPE::getUnitLabel();
+        return s;
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE>
+std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit)
+{
+        STORAGE_TYPE val;
+        s >> val;
+        unit = val;
+        return s;
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE>
@@ -172,8 +181,17 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
 template<typename STORAGE_TYPE, typename UNIT_TYPE>
 std::ostream& operator <<(std::ostream& s, const LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>& unit)
 {
-	s << unit.value() << UNIT_TYPE::getUnitLabel();
-	return s;
+        s << unit.value() << UNIT_TYPE::getUnitLabel();
+        return s;
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE>
+std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>& unit)
+{
+        STORAGE_TYPE val;
+        s >> val;
+        unit = val;
+        return s;
 }
 
 template<typename S, typename T> 
@@ -201,7 +219,7 @@ LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ..
 
 		{
 			// T1 and T2 fully reduced and equal...just copy
-			out = (S2)in.value();
+			out = LLUnit<S2, T2>((S2)in.value());
 		}
 		else
 		{
@@ -447,33 +465,33 @@ template<typename VALUE_TYPE>
 struct LLUnitLinearOps
 {
 	typedef LLUnitLinearOps<VALUE_TYPE> self_t;
-	LLUnitLinearOps(VALUE_TYPE val) : mValue (val) {}
+	LLUnitLinearOps(VALUE_TYPE val) : mResult (val) {}
 
-	operator VALUE_TYPE() const { return mValue; }
-	VALUE_TYPE mValue;
+	operator VALUE_TYPE() const { return mResult; }
+	VALUE_TYPE mResult;
 
 	template<typename T>
 	self_t operator * (T other)
 	{
-		return mValue * other;
+		return mResult * other;
 	}
 
 	template<typename T>
 	self_t operator / (T other)
 	{
-		return mValue / other;
+		return mResult / other;
 	}
 
 	template<typename T>
 	self_t operator + (T other)
 	{
-		return mValue + other;
+		return mResult + other;
 	}
 
 	template<typename T>
 	self_t operator - (T other)
 	{
-		return mValue - other;
+		return mResult - other;
 	}
 };
 
@@ -482,32 +500,32 @@ struct LLUnitInverseLinearOps
 {
 	typedef LLUnitInverseLinearOps<VALUE_TYPE> self_t;
 
-	LLUnitInverseLinearOps(VALUE_TYPE val) : mValue (val) {}
-	operator VALUE_TYPE() const { return mValue; }
-	VALUE_TYPE mValue;
+	LLUnitInverseLinearOps(VALUE_TYPE val) : mResult (val) {}
+	operator VALUE_TYPE() const { return mResult; }
+	VALUE_TYPE mResult;
 
 	template<typename T>
 	self_t operator * (T other)
 	{
-		return mValue / other;
+		return mResult / other;
 	}
 
 	template<typename T>
 	self_t operator / (T other)
 	{
-		return mValue * other;
+		return mResult * other;
 	}
 
 	template<typename T>
 	self_t operator + (T other)
 	{
-		return mValue - other;
+		return mResult - other;
 	}
 
 	template<typename T>
 	self_t operator - (T other)
 	{
-		return mValue + other;
+		return mResult + other;
 	}
 };
 
@@ -521,35 +539,31 @@ struct base_unit_name
 	template<typename STORAGE_T, typename UNIT_T>                                                    \
 	static LLUnit<STORAGE_T, base_unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)              \
 	{ return LLUnit<STORAGE_T, base_unit_name>(value); }                                             \
-};                                                                                                   \
-template<typename T> std::ostream& operator<<(std::ostream& s, const LLUnit<T, base_unit_name>& val) \
-{ s << val.value() << base_unit_name::getUnitLabel; return s; }
-
-
-#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 T>                                                                         \
-	static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); }		 \
-	template<typename STORAGE_T, typename UNIT_T>                                                \
-	static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)				 \
-	{ return LLUnit<STORAGE_T, unit_name>(value); }												 \
-};                                                                                               \
-template<typename T> std::ostream& operator<<(std::ostream& s, const LLUnit<T, unit_name>& val)  \
-{ s << val.value() << unit_name::getUnitLabel; return s; }                                       \
-	                                                                                             \
-template<typename S1, typename S2>                                                               \
-void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)                 \
-{                                                                                                \
-	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_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 T>                                                                            \
+	static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); }		    \
+	template<typename STORAGE_T, typename UNIT_T>                                                   \
+	static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)				    \
+	{ return LLUnit<STORAGE_T, unit_name>(value); }												    \
+};                                                                                                  \
+	                                                                                                \
+template<typename S1, typename S2>                                                                  \
+void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)                    \
+{                                                                                                   \
+	out = LLUnit<S2, base_unit_name>((S2)(LLUnitLinearOps<S1>(in.value()) conversion_operation));   \
+}                                                                                                   \
+                                                                                                    \
+template<typename S1, typename S2>                                                                  \
+void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)                    \
+{                                                                                                   \
+	out = LLUnit<S2, unit_name>((S2)(LLUnitInverseLinearOps<S1>(in.value()) conversion_operation)); \
 }                                                                                               
 
 //
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index 7889828c85..0699dcda83 100755
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -28,6 +28,7 @@
 
 #include <iostream>
 #include <set>
+#include <vector>
 #include "stdtypes.h"
 #include "llpreprocessor.h"
 
-- 
cgit v1.2.3


From 4ff19b8f63f3814e98049064254323716f0fd422 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sat, 20 Jul 2013 09:41:55 -0700
Subject: removed debug spam fast timer data now resets on login

---
 indra/llcommon/tests/llunits_test.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index a5df51f6de..2074a4f4d9 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -164,7 +164,7 @@ namespace tut
 	void units_object_t::test<5>()
 	{
 		// 0-initialized
-		LLUnit<F32, Quatloos> quatloos(0);
+		LLUnit<F32, Quatloos> quatloos;
 		// initialize implicit unit from explicit
 		LLUnitImplicit<F32, Quatloos> quatloos_implicit = quatloos + 1;
 		ensure(quatloos_implicit == 1);
-- 
cgit v1.2.3


From e5b51c7f6cfd1ecf374fe8b705f94968a402c573 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 22 Jul 2013 11:01:52 -0700
Subject: BUIDLFIX: moved LLThreadSafeRefCount to proper file

---
 indra/llcommon/llevent.h    |  1 +
 indra/llcommon/llpointer.h  | 78 -----------------------------------------
 indra/llcommon/llrefcount.h | 85 +++++++++++++++++++++++++++++++++++++++++++--
 indra/llcommon/llthread.h   |  2 +-
 4 files changed, 84 insertions(+), 82 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llevent.h b/indra/llcommon/llevent.h
index 9d3a7a654a..28ce7de102 100755
--- a/indra/llcommon/llevent.h
+++ b/indra/llcommon/llevent.h
@@ -29,6 +29,7 @@
 #define LL_EVENT_H
 
 #include "llsd.h"
+#include "llrefcount.h"
 #include "llpointer.h"
 
 namespace LLOldEvents
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index 9a0726c338..e09741b0ec 100755
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -214,82 +214,4 @@ private:
 	bool mStayUnique;
 };
 
-//============================================================================
-
-// see llmemory.h for LLPointer<> definition
-
-class LL_COMMON_API LLThreadSafeRefCount
-{
-public:
-	static void initThreadSafeRefCount(); // creates sMutex
-	static void cleanupThreadSafeRefCount(); // destroys sMutex
-	
-private:
-	static LLMutex* sMutex;
-
-protected:
-	virtual ~LLThreadSafeRefCount(); // use unref()
-	
-public:
-	LLThreadSafeRefCount();
-	LLThreadSafeRefCount(const LLThreadSafeRefCount&);
-	LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref) 
-	{
-		if (sMutex)
-		{
-			sMutex->lock();
-		}
-		mRef = 0;
-		if (sMutex)
-		{
-			sMutex->unlock();
-		}
-		return *this;
-	}
-	
-	void ref()
-	{
-		if (sMutex) sMutex->lock();
-		mRef++; 
-		if (sMutex) sMutex->unlock();
-	} 
-
-	S32 unref()
-	{
-		llassert(mRef >= 1);
-		if (sMutex) sMutex->lock();
-		S32 res = --mRef;
-		if (sMutex) sMutex->unlock();
-		if (0 == res) 
-		{
-			delete this; 
-			return 0;
-		}
-		return res;
-	}	
-	S32 getNumRefs() const
-	{
-		return mRef;
-	}
-
-private: 
-	S32	mRef; 
-};
-
-/**
- * intrusive pointer support for LLThreadSafeRefCount
- * this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type
- */
-namespace boost
-{
-	inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p) 
-	{
-		p->ref();
-	}
-
-	inline void intrusive_ptr_release(LLThreadSafeRefCount* p) 
-	{
-		p->unref(); 
-	}
-};
 #endif
diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h
index 32ae15435a..3e472d0766 100755
--- a/indra/llcommon/llrefcount.h
+++ b/indra/llcommon/llrefcount.h
@@ -28,6 +28,7 @@
 
 #include <boost/noncopyable.hpp>
 #include <boost/intrusive_ptr.hpp>
+#include "llmutex.h"
 
 #define LL_REF_COUNT_DEBUG 0
 #if LL_REF_COUNT_DEBUG
@@ -87,22 +88,100 @@ private:
 #endif
 };
 
+
+//============================================================================
+
+// see llmemory.h for LLPointer<> definition
+
+class LL_COMMON_API LLThreadSafeRefCount
+{
+public:
+	static void initThreadSafeRefCount(); // creates sMutex
+	static void cleanupThreadSafeRefCount(); // destroys sMutex
+
+private:
+	static LLMutex* sMutex;
+
+protected:
+	virtual ~LLThreadSafeRefCount(); // use unref()
+
+public:
+	LLThreadSafeRefCount();
+	LLThreadSafeRefCount(const LLThreadSafeRefCount&);
+	LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref) 
+	{
+		if (sMutex)
+		{
+			sMutex->lock();
+		}
+		mRef = 0;
+		if (sMutex)
+		{
+			sMutex->unlock();
+		}
+		return *this;
+	}
+
+	void ref()
+	{
+		if (sMutex) sMutex->lock();
+		mRef++; 
+		if (sMutex) sMutex->unlock();
+	} 
+
+	S32 unref()
+	{
+		llassert(mRef >= 1);
+		if (sMutex) sMutex->lock();
+		S32 res = --mRef;
+		if (sMutex) sMutex->unlock();
+		if (0 == res) 
+		{
+			delete this; 
+			return 0;
+		}
+		return res;
+	}	
+	S32 getNumRefs() const
+	{
+		return mRef;
+	}
+
+private: 
+	S32	mRef; 
+};
+
 /**
  * intrusive pointer support
  * this allows you to use boost::intrusive_ptr with any LLRefCount-derived type
  */
+/**
+ * intrusive pointer support for LLThreadSafeRefCount
+ * this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type
+ */
 namespace boost
 {
-	inline void intrusive_ptr_add_ref(LLRefCount* p)
+	inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p) 
 	{
 		p->ref();
 	}
 
-	inline void intrusive_ptr_release(LLRefCount* p)
+	inline void intrusive_ptr_release(LLThreadSafeRefCount* p) 
 	{
-		p->unref();
+		p->unref(); 
+	}
+
+	inline void intrusive_ptr_add_ref(LLRefCount* p) 
+	{
+		p->ref();
+	}
+
+	inline void intrusive_ptr_release(LLRefCount* p) 
+	{
+		p->unref(); 
 	}
 };
 
 
+
 #endif
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index c2c6b8e7ac..d7abdc4970 100755
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -32,7 +32,7 @@
 #include "apr_thread_cond.h"
 #include "boost/intrusive_ptr.hpp"
 #include "llmutex.h"
-#include "llpointer.h"
+#include "llrefcount.h"
 
 LL_COMMON_API void assert_main_thread();
 
-- 
cgit v1.2.3


From 0127e66228acd41402da9acab8ce91d394c3096f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 23 Jul 2013 16:42:22 -0700
Subject: stat bars with no stats now show n/a instead of o

---
 indra/llcommon/lltracerecording.h | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 31616a52cc..f5e4ea603c 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -333,6 +333,21 @@ namespace LLTrace
 		const Recording& getPrevRecording(U32 offset) const;
 		Recording snapshotCurRecording() const;
 
+		template <typename T>
+		size_t getSampleCount(const TraceType<T>& stat, size_t num_periods = U32_MAX)
+        {
+			size_t total_periods = mNumPeriods;
+			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+
+            size_t num_samples = 0;
+			for (S32 i = 1; i <= num_periods; i++)
+			{
+				S32 index = (mCurPeriod + total_periods - i) % total_periods;
+				num_samples += mRecordingPeriods[index].getSampleCount(stat);
+			}
+			return num_samples;
+        }
+        
 		//
 		// PERIODIC MIN
 		//
-- 
cgit v1.2.3


From 50c472c24216ad0c3890cb8bb9cf638e75642f0c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 23 Jul 2013 18:47:16 -0700
Subject: renamed mVarianceSum to mSumOfSquares to be more clear fixed
 normalization assertions to work with megaprims added is_zero() utility
 function fixed unit declarations to be more clear fixed texture cache hit
 rate always being 0

---
 indra/llcommon/lltraceaccumulators.h |  40 +++++++-------
 indra/llcommon/llunit.h              | 100 +++++++++++++++++------------------
 2 files changed, 70 insertions(+), 70 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index efc8b43f6a..b1aa078f9a 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -223,7 +223,7 @@ namespace LLTrace
 			mMin((std::numeric_limits<F64>::max)()),
 			mMax((std::numeric_limits<F64>::min)()),
 			mMean(0),
-			mVarianceSum(0),
+			mSumOfSquares(0),
 			mNumSamples(0),
 			mLastValue(0)
 		{}
@@ -243,7 +243,7 @@ namespace LLTrace
 			}
 			F64 old_mean = mMean;
 			mMean += (value - old_mean) / (F64)mNumSamples;
-			mVarianceSum += (value - old_mean) * (value - mMean);
+			mSumOfSquares += (value - old_mean) * (value - mMean);
 			mLastValue = value;
 		}
 
@@ -263,20 +263,20 @@ namespace LLTrace
 					n_2 = (F64)other.mNumSamples;
 				F64 m_1 = mMean,
 					m_2 = other.mMean;
-				F64 v_1 = mVarianceSum / mNumSamples,
-					v_2 = other.mVarianceSum / other.mNumSamples;
+				F64 v_1 = mSumOfSquares / mNumSamples,
+					v_2 = other.mSumOfSquares / other.mNumSamples;
 				if (n_1 == 0)
 				{
-					mVarianceSum = other.mVarianceSum;
+					mSumOfSquares = other.mSumOfSquares;
 				}
 				else if (n_2 == 0)
 				{
 					// don't touch variance
-					// mVarianceSum = mVarianceSum;
+					// mSumOfSquares = mSumOfSquares;
 				}
 				else
 				{
-					mVarianceSum = (F64)mNumSamples
+					mSumOfSquares = (F64)mNumSamples
 						* ((((n_1 - 1.f) * v_1)
 						+ ((n_2 - 1.f) * v_2)
 						+ (((n_1 * n_2) / (n_1 + n_2))
@@ -298,7 +298,7 @@ namespace LLTrace
 			mMin = std::numeric_limits<F64>::max();
 			mMax = std::numeric_limits<F64>::min();
 			mMean = 0;
-			mVarianceSum = 0;
+			mSumOfSquares = 0;
 			mLastValue = other ? other->mLastValue : 0;
 		}
 
@@ -309,7 +309,7 @@ namespace LLTrace
 		F64	getMax() const { return mMax; }
 		F64	getLastValue() const { return mLastValue; }
 		F64	getMean() const { return mMean; }
-		F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mNumSamples); }
+		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mNumSamples); }
 		U32 getSampleCount() const { return mNumSamples; }
 
 	private:
@@ -319,7 +319,7 @@ namespace LLTrace
 			mLastValue;
 
 		F64	mMean,
-			mVarianceSum;
+			mSumOfSquares;
 
 		U32	mNumSamples;
 	};
@@ -336,7 +336,7 @@ namespace LLTrace
 			mMin((std::numeric_limits<F64>::max)()),
 			mMax((std::numeric_limits<F64>::min)()),
 			mMean(0),
-			mVarianceSum(0),
+			mSumOfSquares(0),
 			mLastSampleTimeStamp(LLTimer::getTotalSeconds()),
 			mTotalSamplingTime(0),
 			mNumSamples(0),
@@ -361,7 +361,7 @@ namespace LLTrace
 
 				F64 old_mean = mMean;
 				mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean);
-				mVarianceSum += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
+				mSumOfSquares += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
 			}
 
 			mLastValue = value;
@@ -385,20 +385,20 @@ namespace LLTrace
 					n_2 = other.mTotalSamplingTime;
 				F64 m_1 = mMean,
 					m_2 = other.mMean;
-				F64 v_1 = mVarianceSum / mTotalSamplingTime,
-					v_2 = other.mVarianceSum / other.mTotalSamplingTime;
+				F64 v_1 = mSumOfSquares / mTotalSamplingTime,
+					v_2 = other.mSumOfSquares / other.mTotalSamplingTime;
 				if (n_1 == 0)
 				{
-					mVarianceSum = other.mVarianceSum;
+					mSumOfSquares = other.mSumOfSquares;
 				}
 				else if (n_2 == 0)
 				{
 					// variance is unchanged
-					// mVarianceSum = mVarianceSum;
+					// mSumOfSquares = mSumOfSquares;
 				}
 				else
 				{
-					mVarianceSum =	mTotalSamplingTime
+					mSumOfSquares =	mTotalSamplingTime
 						* ((((n_1 - 1.f) * v_1)
 						+ ((n_2 - 1.f) * v_2)
 						+ (((n_1 * n_2) / (n_1 + n_2))
@@ -427,7 +427,7 @@ namespace LLTrace
 			mMin = std::numeric_limits<F64>::max();
 			mMax = std::numeric_limits<F64>::min();
 			mMean = other ? other->mLastValue : 0;
-			mVarianceSum = 0;
+			mSumOfSquares = 0;
 			mLastSampleTimeStamp = LLTimer::getTotalSeconds();
 			mTotalSamplingTime = 0;
 			mLastValue = other ? other->mLastValue : 0;
@@ -451,7 +451,7 @@ namespace LLTrace
 		F64	getMax() const { return mMax; }
 		F64	getLastValue() const { return mLastValue; }
 		F64	getMean() const { return mMean; }
-		F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mTotalSamplingTime); }
+		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); }
 		U32 getSampleCount() const { return mNumSamples; }
 
 	private:
@@ -463,7 +463,7 @@ namespace LLTrace
 		bool mHasValue;
 
 		F64	mMean,
-			mVarianceSum;
+			mSumOfSquares;
 
 		LLUnitImplicit<F64, LLUnits::Seconds>	mLastSampleTimeStamp,
 			mTotalSamplingTime;
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index f81e746c77..d6d8d9da6a 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -542,28 +542,28 @@ struct base_unit_name
 }
 
 
-#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 T>                                                                            \
-	static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); }		    \
-	template<typename STORAGE_T, typename UNIT_T>                                                   \
-	static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)				    \
-	{ return LLUnit<STORAGE_T, unit_name>(value); }												    \
-};                                                                                                  \
-	                                                                                                \
-template<typename S1, typename S2>                                                                  \
-void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)                    \
-{                                                                                                   \
-	out = LLUnit<S2, base_unit_name>((S2)(LLUnitLinearOps<S1>(in.value()) conversion_operation));   \
-}                                                                                                   \
-                                                                                                    \
-template<typename S1, typename S2>                                                                  \
-void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)                    \
-{                                                                                                   \
-	out = LLUnit<S2, unit_name>((S2)(LLUnitInverseLinearOps<S1>(in.value()) conversion_operation)); \
+#define LL_DECLARE_DERIVED_UNIT(base_unit_name, conversion_operation, unit_name, unit_label)	        \
+struct unit_name                                                                                        \
+{                                                                                                       \
+	typedef base_unit_name base_unit_t;                                                                 \
+	static const char* getUnitLabel() { return unit_label; }									        \
+	template<typename T>                                                                                \
+	static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); }		        \
+	template<typename STORAGE_T, typename UNIT_T>                                                       \
+	static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)				        \
+	{ return LLUnit<STORAGE_T, unit_name>(value); }												        \
+};                                                                                                      \
+	                                                                                                    \
+template<typename S1, typename S2>                                                                      \
+void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)                        \
+{                                                                                                       \
+	out = LLUnit<S2, base_unit_name>((S2)(LLUnitLinearOps<S1>(in.value()) conversion_operation));		\
+}                                                                                                       \
+                                                                                                        \
+template<typename S1, typename S2>                                                                      \
+void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)                        \
+{                                                                                                       \
+	out = LLUnit<S2, unit_name>((S2)(LLUnitInverseLinearOps<S1>(in.value()) conversion_operation));     \
 }                                                                                               
 
 //
@@ -573,46 +573,46 @@ void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)
 namespace LLUnits
 {
 LL_DECLARE_BASE_UNIT(Bytes, "B");
-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_DERIVED_UNIT(Bytes, * 1000,			Kilobytes, "KB");
+LL_DECLARE_DERIVED_UNIT(Kilobytes, * 1000,		Megabytes, "MB");
+LL_DECLARE_DERIVED_UNIT(Megabytes, * 1000,		Gigabytes, "GB");
+LL_DECLARE_DERIVED_UNIT(Bytes, * 1024,			Kibibytes, "KiB");
+LL_DECLARE_DERIVED_UNIT(Kibibytes, * 1024,		Mibibytes, "MiB");
+LL_DECLARE_DERIVED_UNIT(Mibibytes, * 1024,		Gibibytes, "GiB");
+
+LL_DECLARE_DERIVED_UNIT(Bytes, / 8,				Bits, "b");
+LL_DECLARE_DERIVED_UNIT(Bits, * 1000,			Kilobits, "Kb");
+LL_DECLARE_DERIVED_UNIT(Kilobits, * 1000,		Megabits, "Mb");
+LL_DECLARE_DERIVED_UNIT(Megabits, * 1000,		Gigabits, "Gb");
+LL_DECLARE_DERIVED_UNIT(Bits, * 1024,			Kibibits, "Kib");
+LL_DECLARE_DERIVED_UNIT(Kibibits, * 1024,		Mibibits, "Mib");  
+LL_DECLARE_DERIVED_UNIT(Mibibits, * 1024,		Gibibits, "Gib");
 
 LL_DECLARE_BASE_UNIT(Seconds, "s");
-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_DERIVED_UNIT(Seconds, * 60,			Minutes, "min");
+LL_DECLARE_DERIVED_UNIT(Minutes, * 60,			Hours, "h");
+LL_DECLARE_DERIVED_UNIT(Seconds, / 1000,		Milliseconds, "ms");
+LL_DECLARE_DERIVED_UNIT(Milliseconds, / 1000,	Microseconds, "\x09\x3cs");
+LL_DECLARE_DERIVED_UNIT(Microseconds, / 1000,	Nanoseconds, "ns");
 
 LL_DECLARE_BASE_UNIT(Meters, "m");
-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_DERIVED_UNIT(Meters, * 1000,			Kilometers, "km");
+LL_DECLARE_DERIVED_UNIT(Meters, / 100,			Centimeters, "cm");
+LL_DECLARE_DERIVED_UNIT(Meters, / 1000,			Millimeters, "mm");
 
 LL_DECLARE_BASE_UNIT(Hertz, "Hz");
-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_DERIVED_UNIT(Hertz, * 1000,			Kilohertz, "KHz");
+LL_DECLARE_DERIVED_UNIT(Kilohertz, * 1000,		Megahertz, "MHz");
+LL_DECLARE_DERIVED_UNIT(Megahertz, * 1000,		Gigahertz, "GHz");
 
 LL_DECLARE_BASE_UNIT(Radians, "rad");
-LL_DECLARE_DERIVED_UNIT(Degrees, "deg", Radians, * 0.01745329251994);
+LL_DECLARE_DERIVED_UNIT(Radians, / 57.29578f,	Degrees, "deg");
 
 LL_DECLARE_BASE_UNIT(Percent, "%");
-LL_DECLARE_DERIVED_UNIT(Ratio, "x", Percent, / 100);
+LL_DECLARE_DERIVED_UNIT(Percent, * 100,			Ratio, "x");
 
 LL_DECLARE_BASE_UNIT(Triangles, "tris");
-LL_DECLARE_DERIVED_UNIT(Kilotriangles, "ktris", Triangles, * 1000);
+LL_DECLARE_DERIVED_UNIT(Triangles, * 1000,		Kilotriangles, "ktris");
 
 } // namespace LLUnits
 
-- 
cgit v1.2.3


From 7e7b9ddc32c1eac5f7269cce69f9321d3d17f577 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 24 Jul 2013 11:24:41 -0700
Subject: BUILDFIX fixed llunits unit test to use new unit declaration syntax

---
 indra/llcommon/tests/llunits_test.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index 2074a4f4d9..e631f18ad4 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(Latinum, "Lat", Quatloos, * 4);
-	LL_DECLARE_DERIVED_UNIT(Solari, "Sol", Latinum, / 16);
+	LL_DECLARE_DERIVED_UNIT(Quatloos, * 4, Latinum, "Lat");
+	LL_DECLARE_DERIVED_UNIT(Latinum, / 16, Solari, "Sol");
 }
 
 namespace tut
-- 
cgit v1.2.3


From 1e8f9fd80d0ac4e0eab656ed8e8e32f91ab8b533 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 24 Jul 2013 19:36:43 -0700
Subject: SH-4376 FIX: Interesting: in Statistics, replace the text "0" with
 "n/a" when there are no samples during the time period. added hasValue to
 SampleAccumulator so we don't print a value when we don't have a single
 sample yet added some disabled log output for scene load timing

---
 indra/llcommon/llerror.cpp           | 25 +++++++++++++++----------
 indra/llcommon/llerror.h             | 12 ++++++------
 indra/llcommon/lltraceaccumulators.h |  1 +
 3 files changed, 22 insertions(+), 16 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index d2af004cde..5b4be1ac80 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -158,14 +158,20 @@ namespace {
 		}
 	
 	private:
-		bool mTimestamp;
-		enum ANSIState {ANSI_PROBE, ANSI_YES, ANSI_NO};
-		ANSIState mUseANSI;
+		bool				mTimestamp;
+		enum ANSIState 
+		{
+			ANSI_PROBE, 
+			ANSI_YES, 
+			ANSI_NO
+		}					mUseANSI;
+
 		void colorANSI(const std::string color)
 		{
 			// ANSI color code escape sequence
 			fprintf(stderr, "\033[%sm", color.c_str() );
 		};
+
 		bool checkANSI(void)
 		{
 #if LL_LINUX || LL_DARWIN
@@ -727,13 +733,13 @@ namespace LLError
 namespace LLError
 {
 	Recorder::~Recorder()
-		{ }
+	{}
 
 	// virtual
 	bool Recorder::wantsTime()
-		{ return false; }
-
-
+	{ 
+		return false; 
+	}
 
 	void addRecorder(Recorder* recorder)
 	{
@@ -752,9 +758,8 @@ namespace LLError
 			return;
 		}
 		Settings& s = Settings::get();
-		s.recorders.erase(
-			std::remove(s.recorders.begin(), s.recorders.end(), recorder),
-			s.recorders.end());
+		s.recorders.erase(std::remove(s.recorders.begin(), s.recorders.end(), recorder),
+							s.recorders.end());
 	}
 }
 
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 0b723aeb5d..ceff40e900 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -155,12 +155,12 @@ namespace LLError
 		// these describe the call site and never change
 		const ELevel			mLevel;
 		const char* const		mFile;
-		const int			mLine;
-		const std::type_info&   	mClassInfo;
+		const int				mLine;
+		const std::type_info&   mClassInfo;
 		const char* const		mFunction;
 		const char* const		mBroadTag;
 		const char* const		mNarrowTag;
-		const bool			mPrintOnce;
+		const bool				mPrintOnce;
 		
 		// these implement a cache of the call to shouldLog()
 		bool mCached;
@@ -213,7 +213,7 @@ namespace LLError
 #endif
 
 //this is cheaper than llcallstacks if no need to output other variables to call stacks. 
-#define llpushcallstacks LLError::LLCallStacks::push(__FUNCTION__, __LINE__)
+#define LL_PUSH_CALLSTACKS() LLError::LLCallStacks::push(__FUNCTION__, __LINE__)
 #define llcallstacks \
 	{\
        std::ostringstream* _out = LLError::LLCallStacks::insert(__FUNCTION__, __LINE__) ; \
@@ -222,8 +222,8 @@ namespace LLError
 		LLError::End(); \
 		LLError::LLCallStacks::end(_out) ; \
 	}
-#define llclearcallstacks LLError::LLCallStacks::clear()
-#define llprintcallstacks LLError::LLCallStacks::print() 
+#define LL_CLEAR_CALLSTACKS() LLError::LLCallStacks::clear()
+#define LL_PRINT_CALLSTACKS() LLError::LLCallStacks::print() 
 
 /*
 	Class type information for logging
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index b1aa078f9a..9ea787188c 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -453,6 +453,7 @@ namespace LLTrace
 		F64	getMean() const { return mMean; }
 		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); }
 		U32 getSampleCount() const { return mNumSamples; }
+		bool hasValue() const { return mHasValue; }
 
 	private:
 		F64	mSum,
-- 
cgit v1.2.3


From 3430444212a14a7f40d8b1afdbefc68c3319562d Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 24 Jul 2013 22:41:02 -0700
Subject: BUIDLFIX: forgot to extract value from units object for calling
 llformat

---
 indra/llcommon/lltimer.cpp | 11 +++++++++++
 indra/llcommon/lltimer.h   |  6 +++---
 2 files changed, 14 insertions(+), 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 693809b622..25383fc4d8 100755
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -281,7 +281,18 @@ LLTimer::LLTimer()
 }
 
 LLTimer::~LLTimer()
+{}
+
+// static
+void LLTimer::initClass()
+{
+	if (!sTimer) sTimer = new LLTimer;
+}
+
+// static
+void LLTimer::cleanupClass()
 {
+	delete sTimer; sTimer = NULL;
 }
 
 // static
diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h
index 9e464c4b1a..9f1f243dbb 100755
--- a/indra/llcommon/lltimer.h
+++ b/indra/llcommon/lltimer.h
@@ -62,14 +62,14 @@ public:
 	LLTimer();
 	~LLTimer();
 
-	static void initClass() { if (!sTimer) sTimer = new LLTimer; }
-	static void cleanupClass() { delete sTimer; sTimer = NULL; }
+	static void initClass();
+	static void cleanupClass();
 
 	// Return a high precision number of seconds since the start of
 	// this application instance.
 	static LLUnitImplicit<F64, LLUnits::Seconds> getElapsedSeconds()
 	{
-		return sTimer->getElapsedTimeF64();
+		return sTimer ? sTimer->getElapsedTimeF64() : 0.0;
 	}
 
 	// Return a high precision usec since epoch
-- 
cgit v1.2.3


From 19f7fb6ccce52224cc067e496d1480191badb165 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 25 Jul 2013 13:48:38 -0700
Subject: BUIDLFIX: bad ternary expression

---
 indra/llcommon/lltimer.h | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h
index 9f1f243dbb..f2dc59e405 100755
--- a/indra/llcommon/lltimer.h
+++ b/indra/llcommon/lltimer.h
@@ -69,7 +69,14 @@ public:
 	// this application instance.
 	static LLUnitImplicit<F64, LLUnits::Seconds> getElapsedSeconds()
 	{
-		return sTimer ? sTimer->getElapsedTimeF64() : 0.0;
+		if (sTimer) 
+		{
+			return sTimer->getElapsedTimeF64();
+		}
+		else
+		{
+			return 0;
+		}
 	}
 
 	// Return a high precision usec since epoch
-- 
cgit v1.2.3


From a2e22732f195dc075a733c79f15156752f522a43 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 30 Jul 2013 19:13:45 -0700
Subject: Summer cleaning - removed a lot of llcommon dependencies to speed up
 build times consolidated most indra-specific constants in llcommon under
 indra_constants.h fixed issues with operations on mixed unit types (implicit
 and explicit) made LL_INFOS() style macros variadic in order to subsume other
 logging methods such as ll_infos added optional tag output to error recorders

---
 indra/llcommon/CMakeLists.txt         |  39 +-
 indra/llcommon/bitpack.cpp            |  30 --
 indra/llcommon/bitpack.h              | 208 --------
 indra/llcommon/imageids.cpp           |  73 ---
 indra/llcommon/imageids.h             |  70 ---
 indra/llcommon/indra_constants.cpp    |  31 +-
 indra/llcommon/indra_constants.h      | 356 +++++--------
 indra/llcommon/linked_lists.h         | 937 ----------------------------------
 indra/llcommon/ll_template_cast.h     | 177 -------
 indra/llcommon/llaccountingcost.h     |  86 ----
 indra/llcommon/llagentconstants.h     | 159 ------
 indra/llcommon/llapp.h                |   5 +-
 indra/llcommon/llassettype.h          |   2 -
 indra/llcommon/llavatarconstants.h    |  55 --
 indra/llcommon/llavatarname.cpp       | 239 ---------
 indra/llcommon/llavatarname.h         | 133 -----
 indra/llcommon/llbitpack.cpp          |  30 ++
 indra/llcommon/llbitpack.h            | 208 ++++++++
 indra/llcommon/llchat.h               | 109 ----
 indra/llcommon/llclickaction.h        |  41 --
 indra/llcommon/llcursortypes.cpp      |  91 ----
 indra/llcommon/llcursortypes.h        |  79 ---
 indra/llcommon/lldarray.h             | 223 --------
 indra/llcommon/lldeleteutils.h        |  47 --
 indra/llcommon/lldepthstack.h         |  11 +-
 indra/llcommon/llerror.cpp            | 171 +++++--
 indra/llcommon/llerror.h              | 180 ++++---
 indra/llcommon/llerrorcontrol.h       |   4 +
 indra/llcommon/llerrorlegacy.h        |  95 ----
 indra/llcommon/llevents.h             |   2 +-
 indra/llcommon/llextendedstatus.h     |  67 ---
 indra/llcommon/llfoldertype.cpp       | 168 ------
 indra/llcommon/llfoldertype.h         | 111 ----
 indra/llcommon/llframetimer.h         |   1 -
 indra/llcommon/llindexedvector.h      | 100 ++++
 indra/llcommon/llinitparam.cpp        |  10 +-
 indra/llcommon/llinstancetracker.h    |   2 +-
 indra/llcommon/lllinkedqueue.h        | 309 -----------
 indra/llcommon/lllog.cpp              | 111 ----
 indra/llcommon/lllog.h                |  52 --
 indra/llcommon/lllslconstants.h       | 213 --------
 indra/llcommon/llmap.h                | 245 ---------
 indra/llcommon/llnametable.h          | 105 ----
 indra/llcommon/lloptioninterface.cpp  |  33 --
 indra/llcommon/lloptioninterface.h    |  40 --
 indra/llcommon/llsecondlifeurls.cpp   |  84 ---
 indra/llcommon/llsecondlifeurls.h     |  76 ---
 indra/llcommon/llstatenums.h          |  75 ---
 indra/llcommon/llstl.h                | 199 +++++++-
 indra/llcommon/llstringtable.cpp      |   4 +-
 indra/llcommon/lltimer.cpp            |   9 +-
 indra/llcommon/lltimer.h              |   4 +-
 indra/llcommon/llunit.h               |  88 +++-
 indra/llcommon/llversionserver.h      |  38 --
 indra/llcommon/roles_constants.h      | 192 -------
 indra/llcommon/stdenums.h             | 137 -----
 indra/llcommon/string_table.h         |  26 -
 indra/llcommon/tests/bitpack_test.cpp |   2 +-
 indra/llcommon/timing.h               |  42 --
 59 files changed, 1021 insertions(+), 5413 deletions(-)
 delete mode 100755 indra/llcommon/bitpack.cpp
 delete mode 100755 indra/llcommon/bitpack.h
 delete mode 100755 indra/llcommon/imageids.cpp
 delete mode 100755 indra/llcommon/imageids.h
 delete mode 100755 indra/llcommon/linked_lists.h
 delete mode 100755 indra/llcommon/ll_template_cast.h
 delete mode 100755 indra/llcommon/llaccountingcost.h
 delete mode 100755 indra/llcommon/llagentconstants.h
 delete mode 100755 indra/llcommon/llavatarconstants.h
 delete mode 100755 indra/llcommon/llavatarname.cpp
 delete mode 100755 indra/llcommon/llavatarname.h
 create mode 100755 indra/llcommon/llbitpack.cpp
 create mode 100755 indra/llcommon/llbitpack.h
 delete mode 100755 indra/llcommon/llchat.h
 delete mode 100755 indra/llcommon/llclickaction.h
 delete mode 100755 indra/llcommon/llcursortypes.cpp
 delete mode 100755 indra/llcommon/llcursortypes.h
 delete mode 100755 indra/llcommon/lldarray.h
 delete mode 100644 indra/llcommon/lldeleteutils.h
 delete mode 100755 indra/llcommon/llextendedstatus.h
 delete mode 100755 indra/llcommon/llfoldertype.cpp
 delete mode 100755 indra/llcommon/llfoldertype.h
 create mode 100755 indra/llcommon/llindexedvector.h
 delete mode 100755 indra/llcommon/lllinkedqueue.h
 delete mode 100755 indra/llcommon/lllog.cpp
 delete mode 100755 indra/llcommon/lllog.h
 delete mode 100755 indra/llcommon/lllslconstants.h
 delete mode 100755 indra/llcommon/llmap.h
 delete mode 100755 indra/llcommon/llnametable.h
 delete mode 100755 indra/llcommon/lloptioninterface.cpp
 delete mode 100755 indra/llcommon/lloptioninterface.h
 delete mode 100755 indra/llcommon/llsecondlifeurls.cpp
 delete mode 100755 indra/llcommon/llsecondlifeurls.h
 delete mode 100755 indra/llcommon/llstatenums.h
 delete mode 100755 indra/llcommon/llversionserver.h
 delete mode 100755 indra/llcommon/roles_constants.h
 delete mode 100755 indra/llcommon/stdenums.h
 delete mode 100755 indra/llcommon/string_table.h
 delete mode 100755 indra/llcommon/timing.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 0c76fd46c0..4336550d07 100755
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -26,22 +26,20 @@ include_directories(
 #     ${LLCOMMON_LIBRARIES})
 
 set(llcommon_SOURCE_FILES
-    imageids.cpp
     indra_constants.cpp
     llallocator.cpp
     llallocator_heap_profile.cpp
     llapp.cpp
     llapr.cpp
     llassettype.cpp
-    llavatarname.cpp
     llbase32.cpp
     llbase64.cpp
+	llbitpack.cpp
     llcommon.cpp
     llcommonutils.cpp
     llcoros.cpp
     llcrc.cpp
     llcriticaldamp.cpp
-    llcursortypes.cpp
     lldate.cpp
     lldependencies.cpp
     lldictionary.cpp
@@ -58,7 +56,6 @@ set(llcommon_SOURCE_FILES
     llfile.cpp
     llfindlocale.cpp
     llfixedbuffer.cpp
-    llfoldertype.cpp
     llformat.cpp
     llframetimer.cpp
     llheartbeat.cpp
@@ -68,7 +65,6 @@ set(llcommon_SOURCE_FILES
     llleaplistener.cpp
     llliveappconfig.cpp
     lllivefile.cpp
-    lllog.cpp
     llmd5.cpp
     llmemory.cpp
     llmemorystream.cpp
@@ -76,7 +72,6 @@ set(llcommon_SOURCE_FILES
     llmetricperformancetester.cpp
     llmortician.cpp
     llmutex.cpp
-    lloptioninterface.cpp
     llptrto.cpp 
     llpredicate.cpp
     llprocess.cpp
@@ -90,7 +85,6 @@ set(llcommon_SOURCE_FILES
     llsdserialize.cpp
     llsdserialize_xml.cpp
     llsdutil.cpp
-    llsecondlifeurls.cpp
     llsingleton.cpp
     llstacktrace.cpp
     llstreamqueue.cpp
@@ -116,45 +110,33 @@ set(llcommon_SOURCE_FILES
 set(llcommon_HEADER_FILES
     CMakeLists.txt
 
-    bitpack.h
     ctype_workaround.h
     fix_macros.h
-    imageids.h
     indra_constants.h
     linden_common.h
-    linked_lists.h
-    llaccountingcost.h
     llallocator.h
     llallocator_heap_profile.h
-    llagentconstants.h
-    llavatarname.h
     llapp.h
     llapr.h
     llassettype.h
-    llavatarconstants.h
     llbase32.h
     llbase64.h
+    llbitpack.h
     llboost.h
-    llchat.h
-    llclickaction.h
     llcommon.h
     llcommonutils.h
     llcoros.h
     llcrc.h
     llcriticaldamp.h
-    llcursortypes.h
-    lldarray.h
     lldate.h
     lldefs.h
     lldependencies.h
-    lldeleteutils.h
     lldepthstack.h
     lldictionary.h
     lldoubledispatch.h
     llendianswizzle.h
     llerror.h
     llerrorcontrol.h
-    llerrorlegacy.h
     llerrorthread.h
     llevent.h
     lleventapi.h
@@ -163,30 +145,25 @@ set(llcommon_HEADER_FILES
     lleventfilter.h
     llevents.h
     lleventemitter.h
-    llextendedstatus.h
     llfasttimer.h
     llfile.h
     llfindlocale.h
     llfixedbuffer.h
-    llfoldertype.h
     llformat.h
     llframetimer.h
     llhandle.h
     llhash.h
     llheartbeat.h
     llhttpstatuscodes.h
+    llindexedvector.h
     llinitparam.h
     llinstancetracker.h
     llkeythrottle.h
     llleap.h
     llleaplistener.h
     lllistenerwrapper.h
-    lllinkedqueue.h
     llliveappconfig.h
     lllivefile.h
-    lllog.h
-    lllslconstants.h
-    llmap.h
     llmd5.h
     llmemory.h
     llmemorystream.h
@@ -194,8 +171,6 @@ set(llcommon_HEADER_FILES
     llmetricperformancetester.h
     llmortician.h
     llmutex.h
-    llnametable.h
-    lloptioninterface.h
     llpointer.h
     llpredicate.h
     llpreprocessor.h
@@ -215,11 +190,9 @@ set(llcommon_HEADER_FILES
     llsdserialize.h
     llsdserialize_xml.h
     llsdutil.h
-    llsecondlifeurls.h
     llsimplehash.h
     llsingleton.h
     llstacktrace.h
-    llstatenums.h
     llstl.h
     llstreamqueue.h
     llstreamtools.h
@@ -239,18 +212,12 @@ set(llcommon_HEADER_FILES
     llunit.h
     lluri.h
     lluuid.h
-    llversionserver.h
 	llwin32headers.h
     llwin32headerslean.h
     llworkerthread.h
-    ll_template_cast.h
-    roles_constants.h
-    stdenums.h
     stdtypes.h
-    string_table.h
     stringize.h
     timer.h
-    timing.h
     u64.h
     )
 
diff --git a/indra/llcommon/bitpack.cpp b/indra/llcommon/bitpack.cpp
deleted file mode 100755
index cdcaba0765..0000000000
--- a/indra/llcommon/bitpack.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-/** 
- * @file bitpack.cpp
- * @brief LLBitPack class implementation
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes.
-#include "bitpack.h"
diff --git a/indra/llcommon/bitpack.h b/indra/llcommon/bitpack.h
deleted file mode 100755
index 037300dd14..0000000000
--- a/indra/llcommon/bitpack.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/** 
- * @file bitpack.h
- * @brief Convert data to packed bit stream
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_BITPACK_H
-#define LL_BITPACK_H
-
-#include "llerror.h"
-
-const U32 MAX_DATA_BITS = 8;
-
-
-class LLBitPack
-{
-public:
-	LLBitPack(U8 *buffer, U32 max_size) : mBuffer(buffer), mBufferSize(0), mLoad(0), mLoadSize(0), mTotalBits(0), mMaxSize(max_size)
-	{
-	}
-
-	~LLBitPack()
-	{
-	}
-
-	void resetBitPacking()
-	{
-		mLoad = 0;
-		mLoadSize = 0;
-		mTotalBits = 0;
-		mBufferSize = 0;
-	}
-
-	U32 bitPack(U8 *total_data, U32 total_dsize)
-	{
-		U32 dsize;
-		U8 data;
-
-		while (total_dsize > 0)
-		{
-			if (total_dsize > MAX_DATA_BITS)
-			{
-				dsize = MAX_DATA_BITS;
-				total_dsize -= MAX_DATA_BITS;
-			}
-			else
-			{
-				dsize = total_dsize;
-				total_dsize = 0;
-			}
-
-			data = *total_data++;
-
-			data <<= (MAX_DATA_BITS - dsize);
-			while (dsize > 0) 
-			{
-				if (mLoadSize == MAX_DATA_BITS) 
-				{
-					*(mBuffer + mBufferSize++) = mLoad;
-					if (mBufferSize > mMaxSize)
-					{
-						llerror("mBufferSize exceeding mMaxSize!", 0);
-					}
-					mLoadSize = 0;
-					mLoad = 0x00;
-				}
-				mLoad <<= 1;			
-				mLoad |= (data >> (MAX_DATA_BITS - 1));
-				data <<= 1;
-				mLoadSize++;
-				mTotalBits++;
-				dsize--;
-			}
-		}
-		return mBufferSize;
-	}
-
-	U32 bitCopy(U8 *total_data, U32 total_dsize)
-	{
-		U32 dsize;
-		U8  data;
-
-		while (total_dsize > 0)
-		{
-			if (total_dsize > MAX_DATA_BITS)
-			{
-				dsize = MAX_DATA_BITS;
-				total_dsize -= MAX_DATA_BITS;
-			}
-			else
-			{
-				dsize = total_dsize;
-				total_dsize = 0;
-			}
-
-			data = *total_data++;
-
-			while (dsize > 0) 
-			{
-				if (mLoadSize == MAX_DATA_BITS) 
-				{
-					*(mBuffer + mBufferSize++) = mLoad;
-					if (mBufferSize > mMaxSize)
-					{
-						llerror("mBufferSize exceeding mMaxSize!", 0);
-					}
-					mLoadSize = 0;
-					mLoad = 0x00;
-				}
-				mLoad <<= 1;			
-				mLoad |= (data >> (MAX_DATA_BITS - 1));
-				data <<= 1;
-				mLoadSize++;
-				mTotalBits++;
-				dsize--;
-			}
-		}
-		return mBufferSize;
-	}
-
-	U32 bitUnpack(U8 *total_retval, U32 total_dsize)
-	{
-		U32 dsize;
-		U8	*retval;
-
-		while (total_dsize > 0)
-		{
-			if (total_dsize > MAX_DATA_BITS)
-			{
-				dsize = MAX_DATA_BITS;
-				total_dsize -= MAX_DATA_BITS;
-			}
-			else
-			{
-				dsize = total_dsize;
-				total_dsize = 0;
-			}
-
-			retval = total_retval++;
-			*retval = 0x00;
-			while (dsize > 0) 
-			{
-				if (mLoadSize == 0) 
-				{
-#ifdef _DEBUG
-					if (mBufferSize > mMaxSize)
-					{
-						llerrs << "mBufferSize exceeding mMaxSize" << llendl;
-						llerrs << mBufferSize << " > " << mMaxSize << llendl;
-					}
-#endif
-					mLoad = *(mBuffer + mBufferSize++);
-					mLoadSize = MAX_DATA_BITS;
-				}
-				*retval <<= 1;
-				*retval |= (mLoad >> (MAX_DATA_BITS - 1));
-				mLoadSize--;
-				mLoad <<= 1;
-				dsize--;
-			}
-		}
-		return mBufferSize;
-	}
-
-	U32 flushBitPack()
-	{
-		if (mLoadSize) 
-		{
-			mLoad <<= (MAX_DATA_BITS - mLoadSize);
-			*(mBuffer + mBufferSize++) = mLoad;
-			if (mBufferSize > mMaxSize)
-			{
-				llerror("mBufferSize exceeding mMaxSize!", 0);
-			}
-			mLoadSize = 0;
-		}
-		return mBufferSize;
-	}
-
-	U8		*mBuffer;
-	U32		mBufferSize;
-	U8		mLoad;
-	U32		mLoadSize;
-	U32		mTotalBits;
-	U32		mMaxSize;
-};
-
-#endif
diff --git a/indra/llcommon/imageids.cpp b/indra/llcommon/imageids.cpp
deleted file mode 100755
index 7d647e5c36..0000000000
--- a/indra/llcommon/imageids.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/** 
- * @file imageids.cpp
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "imageids.h"
-
-#include "lluuid.h"
-
-//
-// USE OF THIS FILE IS DEPRECATED
-//
-// Please use viewerart.ini and the standard
-// art import path.																			// indicates if file is only
-			 															// on dataserver, or also
-																			// pre-cached on viewer
-
-// Grass Images
-const LLUUID IMG_SMOKE			("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d");  // VIEWER
-
-const LLUUID IMG_DEFAULT		("d2114404-dd59-4a4d-8e6c-49359e91bbf0");  // VIEWER
-
-const LLUUID IMG_SUN			("cce0f112-878f-4586-a2e2-a8f104bba271"); // dataserver
-const LLUUID IMG_MOON			("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver
-const LLUUID IMG_CLOUD_POOF		("fc4b9f0b-d008-45c6-96a4-01dd947ac621"); // dataserver
-const LLUUID IMG_SHOT			("35f217a3-f618-49cf-bbca-c86d486551a9"); // dataserver
-const LLUUID IMG_SPARK			("d2e75ac1-d0fb-4532-820e-a20034ac814d"); // dataserver
-const LLUUID IMG_FIRE			("aca40aa8-44cf-44ca-a0fa-93e1a2986f82"); // dataserver
-const LLUUID IMG_FACE_SELECT    ("a85ac674-cb75-4af6-9499-df7c5aaf7a28"); // face selector
-const LLUUID IMG_DEFAULT_AVATAR ("c228d1cf-4b5d-4ba8-84f4-899a0796aa97"); // dataserver
-const LLUUID IMG_INVISIBLE		("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"); // dataserver
-
-const LLUUID IMG_EXPLOSION				("68edcf47-ccd7-45b8-9f90-1649d7f12806"); // On dataserver
-const LLUUID IMG_EXPLOSION_2			("21ce046c-83fe-430a-b629-c7660ac78d7c"); // On dataserver
-const LLUUID IMG_EXPLOSION_3			("fedea30a-1be8-47a6-bc06-337a04a39c4b"); // On dataserver
-const LLUUID IMG_EXPLOSION_4			("abf0d56b-82e5-47a2-a8ad-74741bb2c29e"); // On dataserver
-const LLUUID IMG_SMOKE_POOF				("1e63e323-5fe0-452e-92f8-b98bd0f764e3"); // On dataserver
-
-const LLUUID IMG_BIG_EXPLOSION_1		("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); // On dataserver
-const LLUUID IMG_BIG_EXPLOSION_2		("9c8eca51-53d5-42a7-bb58-cef070395db8"); // On dataserver
-
-const LLUUID IMG_BLOOM1	  			    ("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"); // VIEWER
-const LLUUID TERRAIN_DIRT_DETAIL		("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER
-const LLUUID TERRAIN_GRASS_DETAIL		("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER
-const LLUUID TERRAIN_MOUNTAIN_DETAIL	("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER
-const LLUUID TERRAIN_ROCK_DETAIL		("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER
-
-const LLUUID DEFAULT_WATER_NORMAL		("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER
-
-const LLUUID IMG_CHECKERBOARD_RGBA     ("2585a0f3-4163-6dd1-0f34-ad48cb909e25"); // dataserver
-
diff --git a/indra/llcommon/imageids.h b/indra/llcommon/imageids.h
deleted file mode 100755
index 18c8ecb074..0000000000
--- a/indra/llcommon/imageids.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/** 
- * @file imageids.h
- * @brief Temporary holder for image IDs
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_IMAGEIDS_H
-#define LL_IMAGEIDS_H
-
-//
-// USE OF THIS FILE IS DEPRECATED
-//
-// Please use viewerart.ini and the standard
-// art import path.
-
-class LLUUID;
-
-LL_COMMON_API extern const LLUUID IMG_SMOKE;
-
-LL_COMMON_API extern const LLUUID IMG_DEFAULT;
-
-LL_COMMON_API extern const LLUUID IMG_SUN;
-LL_COMMON_API extern const LLUUID IMG_MOON;
-LL_COMMON_API extern const LLUUID IMG_CLOUD_POOF;
-LL_COMMON_API extern const LLUUID IMG_SHOT;
-LL_COMMON_API extern const LLUUID IMG_SPARK;
-LL_COMMON_API extern const LLUUID IMG_FIRE;
-LL_COMMON_API extern const LLUUID IMG_FACE_SELECT;
-LL_COMMON_API extern const LLUUID IMG_DEFAULT_AVATAR;
-LL_COMMON_API extern const LLUUID IMG_INVISIBLE;
-
-LL_COMMON_API extern const LLUUID IMG_EXPLOSION;
-LL_COMMON_API extern const LLUUID IMG_EXPLOSION_2;
-LL_COMMON_API extern const LLUUID IMG_EXPLOSION_3;
-LL_COMMON_API extern const LLUUID IMG_EXPLOSION_4;
-LL_COMMON_API extern const LLUUID IMG_SMOKE_POOF;
-
-LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_1;
-LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_2;
-
-LL_COMMON_API extern const LLUUID IMG_BLOOM1;
-LL_COMMON_API extern const LLUUID TERRAIN_DIRT_DETAIL;
-LL_COMMON_API extern const LLUUID TERRAIN_GRASS_DETAIL;
-LL_COMMON_API extern const LLUUID TERRAIN_MOUNTAIN_DETAIL;
-LL_COMMON_API extern const LLUUID TERRAIN_ROCK_DETAIL;
-
-LL_COMMON_API extern const LLUUID DEFAULT_WATER_NORMAL;
-
-LL_COMMON_API extern const LLUUID IMG_CHECKERBOARD_RGBA;
-#endif
diff --git a/indra/llcommon/indra_constants.cpp b/indra/llcommon/indra_constants.cpp
index d32ae6c041..b61dca3243 100755
--- a/indra/llcommon/indra_constants.cpp
+++ b/indra/llcommon/indra_constants.cpp
@@ -35,6 +35,35 @@ const LLUUID LL_UUID_ALL_AGENTS("44e87126-e794-4ded-05b3-7c42da3d5cdb");
 // Governor Linden's agent id.
 const LLUUID ALEXANDRIA_LINDEN_ID("ba2a564a-f0f1-4b82-9c61-b7520bfcd09f");
 const LLUUID GOVERNOR_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1");
-const LLUUID REALESTATE_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1");
 // Maintenance's group id.
 const LLUUID MAINTENANCE_GROUP_ID("dc7b21cd-3c89-fcaa-31c8-25f9ffd224cd");
+// Grass Images
+const LLUUID IMG_SMOKE			("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d");  // VIEWER
+
+const LLUUID IMG_DEFAULT		("d2114404-dd59-4a4d-8e6c-49359e91bbf0");  // VIEWER
+
+const LLUUID IMG_SUN			("cce0f112-878f-4586-a2e2-a8f104bba271"); // dataserver
+const LLUUID IMG_MOON			("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver
+const LLUUID IMG_SHOT			("35f217a3-f618-49cf-bbca-c86d486551a9"); // dataserver
+const LLUUID IMG_SPARK			("d2e75ac1-d0fb-4532-820e-a20034ac814d"); // dataserver
+const LLUUID IMG_FIRE			("aca40aa8-44cf-44ca-a0fa-93e1a2986f82"); // dataserver
+const LLUUID IMG_FACE_SELECT    ("a85ac674-cb75-4af6-9499-df7c5aaf7a28"); // face selector
+const LLUUID IMG_DEFAULT_AVATAR ("c228d1cf-4b5d-4ba8-84f4-899a0796aa97"); // dataserver
+const LLUUID IMG_INVISIBLE		("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"); // dataserver
+
+const LLUUID IMG_EXPLOSION				("68edcf47-ccd7-45b8-9f90-1649d7f12806"); // On dataserver
+const LLUUID IMG_EXPLOSION_2			("21ce046c-83fe-430a-b629-c7660ac78d7c"); // On dataserver
+const LLUUID IMG_EXPLOSION_3			("fedea30a-1be8-47a6-bc06-337a04a39c4b"); // On dataserver
+const LLUUID IMG_EXPLOSION_4			("abf0d56b-82e5-47a2-a8ad-74741bb2c29e"); // On dataserver
+const LLUUID IMG_SMOKE_POOF				("1e63e323-5fe0-452e-92f8-b98bd0f764e3"); // On dataserver
+
+const LLUUID IMG_BIG_EXPLOSION_1		("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); // On dataserver
+const LLUUID IMG_BIG_EXPLOSION_2		("9c8eca51-53d5-42a7-bb58-cef070395db8"); // On dataserver
+
+const LLUUID IMG_BLOOM1	  			    ("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"); // VIEWER
+const LLUUID TERRAIN_DIRT_DETAIL		("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER
+const LLUUID TERRAIN_GRASS_DETAIL		("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER
+const LLUUID TERRAIN_MOUNTAIN_DETAIL	("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER
+const LLUUID TERRAIN_ROCK_DETAIL		("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER
+
+const LLUUID DEFAULT_WATER_NORMAL		("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER
\ No newline at end of file
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index 0da83720bd..02f063f5e8 100755
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -31,122 +31,28 @@
 
 class LLUUID;
 
-// At 45 Hz collisions seem stable and objects seem
-// to settle down at a reasonable rate.
-// JC 3/18/2003
-
-// const F32 PHYSICS_TIMESTEP = 1.f / 45.f;
-// This must be a #define due to anal retentive restrictions on const expressions
-// CG 2008-06-05
-#define PHYSICS_TIMESTEP (1.f / 45.f)
-
-const F32 COLLISION_TOLERANCE = 0.1f;
-const F32 HALF_COLLISION_TOLERANCE = 0.05f;
-
-// Time constants
-const U32 HOURS_PER_LINDEN_DAY		= 4;	
-const U32 DAYS_PER_LINDEN_YEAR		= 11;
-
-const U32 SEC_PER_LINDEN_DAY		= HOURS_PER_LINDEN_DAY * 60 * 60;
-const U32 SEC_PER_LINDEN_YEAR		= DAYS_PER_LINDEN_YEAR * SEC_PER_LINDEN_DAY;
-
 static const F32 REGION_WIDTH_METERS = 256.f;
 static const S32 REGION_WIDTH_UNITS = 256;
 static const U32 REGION_WIDTH_U32 = 256;
 
 const F32 REGION_HEIGHT_METERS = 4096.f;
 
-// Bits for simulator performance query flags
-enum LAND_STAT_FLAGS
-{
-	STAT_FILTER_BY_PARCEL	= 0x00000001,
-	STAT_FILTER_BY_OWNER	= 0x00000002,
-	STAT_FILTER_BY_OBJECT	= 0x00000004,
-	STAT_FILTER_BY_PARCEL_NAME	= 0x00000008,
-	STAT_REQUEST_LAST_ENTRY	= 0x80000000,
-};
-
-enum LAND_STAT_REPORT_TYPE
-{
-	STAT_REPORT_TOP_SCRIPTS = 0,
-	STAT_REPORT_TOP_COLLIDERS
-};
-
-const U32 STAT_FILTER_MASK	= 0x1FFFFFFF;
-
-// Region absolute limits
-static const S32		REGION_AGENT_COUNT_MIN = 1;
-static const S32		REGION_AGENT_COUNT_MAX = 200;			// Must fit in U8 for the moment (RegionInfo msg)
-static const S32		REGION_PRIM_COUNT_MIN = 0;
-static const S32		REGION_PRIM_COUNT_MAX = 40000;
-static const F32		REGION_PRIM_BONUS_MIN = 1.0;
-static const F32		REGION_PRIM_BONUS_MAX = 10.0;
-
-// Default maximum number of tasks/prims per region.
-const U32 DEFAULT_MAX_REGION_WIDE_PRIM_COUNT = 15000;
-
-const 	F32 	MIN_AGENT_DEPTH			= 0.30f;
 const 	F32 	DEFAULT_AGENT_DEPTH 	= 0.45f;
-const 	F32 	MAX_AGENT_DEPTH			= 0.60f;
-
-const 	F32 	MIN_AGENT_WIDTH 		= 0.40f;
 const 	F32 	DEFAULT_AGENT_WIDTH 	= 0.60f;
-const 	F32 	MAX_AGENT_WIDTH 		= 0.80f;
-
-const 	F32 	MIN_AGENT_HEIGHT		= 1.1f;
 const 	F32 	DEFAULT_AGENT_HEIGHT	= 1.9f;
-const 	F32 	MAX_AGENT_HEIGHT		= 2.45f;
-
-// For linked sets
-const S32 MAX_CHILDREN_PER_TASK = 255;
-const S32 MAX_CHILDREN_PER_PHYSICAL_TASK = 32;
-
-const S32 MAX_JOINTS_PER_OBJECT = 1;	// limiting to 1 until Havok 2.x
-
-const	char* const	DEFAULT_DMZ_SPACE_SERVER	= "192.168.0.140";
-const	char* const	DEFAULT_DMZ_USER_SERVER		= "192.168.0.140";
-const	char* const	DEFAULT_DMZ_DATA_SERVER		= "192.168.0.140";
-const	char* const	DEFAULT_DMZ_ASSET_SERVER	= "http://asset.dmz.lindenlab.com:80";
-
-const	char* const	DEFAULT_AGNI_SPACE_SERVER	= "63.211.139.100";
-const	char* const	DEFAULT_AGNI_USER_SERVER	= "63.211.139.100";
-const	char* const	DEFAULT_AGNI_DATA_SERVER	= "63.211.139.100";
-const	char* const	DEFAULT_AGNI_ASSET_SERVER	= "http://asset.agni.lindenlab.com:80";
-
-// Information about what ports are for what services is in the wiki Name Space Ports page
-// https://wiki.lindenlab.com/wiki/Name_Space_Ports
-const	char* const DEFAULT_LOCAL_ASSET_SERVER	= "http://localhost:12041/asset/tmp";
-const	char* const	LOCAL_ASSET_URL_FORMAT		= "http://%s:12041/asset";
-
-const	U32		DEFAULT_LAUNCHER_PORT			= 12029;
-//const	U32		DEFAULT_BIGBOARD_PORT			= 12030; // Deprecated
-//const	U32		DEFAULT_QUERYSIM_PORT			= 12031; // Deprecated
-const	U32		DEFAULT_DATA_SERVER_PORT		= 12032;
-const	U32		DEFAULT_SPACE_SERVER_PORT		= 12033;
-const	U32		DEFAULT_VIEWER_PORT				= 12034;
-const	U32		DEFAULT_SIMULATOR_PORT			= 12035;
-const	U32		DEFAULT_USER_SERVER_PORT		= 12036;
-const	U32		DEFAULT_RPC_SERVER_PORT			= 12037;
-const	U32		DEFAULT_LOG_DATA_SERVER_PORT	= 12039;
-const	U32		DEFAULT_BACKBONE_PORT			= 12040;
-const   U32		DEFAULT_LOCAL_ASSET_PORT		= 12041;
-//const   U32		DEFAULT_BACKBONE_CAP_PORT		= 12042; // Deprecated
-const   U32		DEFAULT_CAP_PROXY_PORT			= 12043;
-const   U32		DEFAULT_INV_DATA_SERVER_PORT	= 12044;
-const	U32		DEFAULT_CGI_SERVICES_PORT		= 12045;
-
-// Mapserver uses ports 12124 - 12139 to allow multiple mapservers to run
-// on a single host for map tile generation. JC
-const	U32		DEFAULT_MAPSERVER_PORT			= 12124;
-
-// For automatic port discovery when running multiple viewers on one host
-const	U32		PORT_DISCOVERY_RANGE_MIN		= 13000;
-const	U32		PORT_DISCOVERY_RANGE_MAX		= PORT_DISCOVERY_RANGE_MIN + 50;
-
-const	char	LAND_LAYER_CODE					= 'L';
-const	char	WATER_LAYER_CODE				= 'W';
-const	char	WIND_LAYER_CODE					= '7';
-const	char	CLOUD_LAYER_CODE				= '8';
+
+enum ETerrainBrushType
+{
+	// the valid brush numbers cannot be reordered, because they 
+	// are used in the binary LSL format as arguments to llModifyLand()
+	E_LANDBRUSH_LEVEL	= 0,
+	E_LANDBRUSH_RAISE	= 1,
+	E_LANDBRUSH_LOWER	= 2,
+	E_LANDBRUSH_SMOOTH 	= 3,
+	E_LANDBRUSH_NOISE	= 4,
+	E_LANDBRUSH_REVERT 	= 5,
+	E_LANDBRUSH_INVALID = 6
+};
 
 // keys
 // Bit masks for various keyboard modifier keys.
@@ -265,89 +171,43 @@ LL_COMMON_API extern const LLUUID LL_UUID_ALL_AGENTS;
 LL_COMMON_API extern const LLUUID ALEXANDRIA_LINDEN_ID;
 
 LL_COMMON_API extern const LLUUID GOVERNOR_LINDEN_ID;
-LL_COMMON_API extern const LLUUID REALESTATE_LINDEN_ID;
 // Maintenance's group id.
 LL_COMMON_API extern const LLUUID MAINTENANCE_GROUP_ID;
 
-// Flags for kick message
-const U32 KICK_FLAGS_DEFAULT	= 0x0;
-const U32 KICK_FLAGS_FREEZE		= 1 << 0;
-const U32 KICK_FLAGS_UNFREEZE	= 1 << 1;
-
-const U8 UPD_NONE      		= 0x00;
-const U8 UPD_POSITION  		= 0x01;
-const U8 UPD_ROTATION  		= 0x02;
-const U8 UPD_SCALE     		= 0x04;
-const U8 UPD_LINKED_SETS 	= 0x08;
-const U8 UPD_UNIFORM 		= 0x10;	// used with UPD_SCALE
-
-// Agent Update Flags (U8)
-const U8 AU_FLAGS_NONE      		= 0x00;
-const U8 AU_FLAGS_HIDETITLE      	= 0x01;
-const U8 AU_FLAGS_CLIENT_AUTOPILOT	= 0x02;
-
-// start location constants
-const U32 START_LOCATION_ID_LAST 		= 0;
-const U32 START_LOCATION_ID_HOME 		= 1;
-const U32 START_LOCATION_ID_DIRECT	 	= 2;	// for direct teleport
-const U32 START_LOCATION_ID_PARCEL	 	= 3;	// for teleports to a parcel
-const U32 START_LOCATION_ID_TELEHUB 	= 4;	// for teleports to a spawnpoint
-const U32 START_LOCATION_ID_URL			= 5;
-const U32 START_LOCATION_ID_COUNT 		= 6;
-
-// group constants
-const U32 GROUP_MIN_SIZE = 2;
-
-// gMaxAgentGroups is now sent by login.cgi, which
-// looks it up from globals.xml.
-//
-// For now we need an old default value however,
-// so the viewer can be deployed ahead of login.cgi.
-//
-const S32 DEFAULT_MAX_AGENT_GROUPS = 25;
+// image ids
+LL_COMMON_API extern const LLUUID IMG_SMOKE;
 
-// radius within which a chat message is fully audible
-const F32 CHAT_WHISPER_RADIUS = 10.f;
-const F32 CHAT_NORMAL_RADIUS = 20.f;
-const F32 CHAT_SHOUT_RADIUS = 100.f;
-const F32 CHAT_MAX_RADIUS = CHAT_SHOUT_RADIUS;
-const F32 CHAT_MAX_RADIUS_BY_TWO = CHAT_MAX_RADIUS / 2.f;
+LL_COMMON_API extern const LLUUID IMG_DEFAULT;
 
-// squared editions of the above for distance checks
-const F32 CHAT_WHISPER_RADIUS_SQUARED = CHAT_WHISPER_RADIUS * CHAT_WHISPER_RADIUS;
-const F32 CHAT_NORMAL_RADIUS_SQUARED = CHAT_NORMAL_RADIUS * CHAT_NORMAL_RADIUS;
-const F32 CHAT_SHOUT_RADIUS_SQUARED = CHAT_SHOUT_RADIUS * CHAT_SHOUT_RADIUS;
-const F32 CHAT_MAX_RADIUS_SQUARED = CHAT_SHOUT_RADIUS_SQUARED;
-const F32 CHAT_MAX_RADIUS_BY_TWO_SQUARED = CHAT_MAX_RADIUS_BY_TWO * CHAT_MAX_RADIUS_BY_TWO;
+LL_COMMON_API extern const LLUUID IMG_SUN;
+LL_COMMON_API extern const LLUUID IMG_MOON;
+LL_COMMON_API extern const LLUUID IMG_SHOT;
+LL_COMMON_API extern const LLUUID IMG_SPARK;
+LL_COMMON_API extern const LLUUID IMG_FIRE;
+LL_COMMON_API extern const LLUUID IMG_FACE_SELECT;
+LL_COMMON_API extern const LLUUID IMG_DEFAULT_AVATAR;
+LL_COMMON_API extern const LLUUID IMG_INVISIBLE;
 
+LL_COMMON_API extern const LLUUID IMG_EXPLOSION;
+LL_COMMON_API extern const LLUUID IMG_EXPLOSION_2;
+LL_COMMON_API extern const LLUUID IMG_EXPLOSION_3;
+LL_COMMON_API extern const LLUUID IMG_EXPLOSION_4;
+LL_COMMON_API extern const LLUUID IMG_SMOKE_POOF;
 
-// this times above gives barely audible radius
-const F32 CHAT_BARELY_AUDIBLE_FACTOR = 2.0f;
+LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_1;
+LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_2;
 
-// distance in front of speaking agent the sphere is centered
-const F32 CHAT_WHISPER_OFFSET = 5.f;
-const F32 CHAT_NORMAL_OFFSET = 10.f;
-const F32 CHAT_SHOUT_OFFSET = 50.f;
+LL_COMMON_API extern const LLUUID IMG_BLOOM1;
+LL_COMMON_API extern const LLUUID TERRAIN_DIRT_DETAIL;
+LL_COMMON_API extern const LLUUID TERRAIN_GRASS_DETAIL;
+LL_COMMON_API extern const LLUUID TERRAIN_MOUNTAIN_DETAIL;
+LL_COMMON_API extern const LLUUID TERRAIN_ROCK_DETAIL;
 
-// first clean starts at 3 AM
-const S32 SANDBOX_FIRST_CLEAN_HOUR = 3;
-// clean every <n> hours
-const S32 SANDBOX_CLEAN_FREQ = 12;
+LL_COMMON_API extern const LLUUID DEFAULT_WATER_NORMAL;
 
-const F32 WIND_SCALE_HACK		= 2.0f;	// hack to make wind speeds more realistic
 
-enum ETerrainBrushType
-{
-	// the valid brush numbers cannot be reordered, because they 
-	// are used in the binary LSL format as arguments to llModifyLand()
-	E_LANDBRUSH_LEVEL	= 0,
-	E_LANDBRUSH_RAISE	= 1,
-	E_LANDBRUSH_LOWER	= 2,
-	E_LANDBRUSH_SMOOTH 	= 3,
-	E_LANDBRUSH_NOISE	= 4,
-	E_LANDBRUSH_REVERT 	= 5,
-	E_LANDBRUSH_INVALID = 6
-};
+// radius within which a chat message is fully audible
+const F32 CHAT_NORMAL_RADIUS = 20.f;
 
 // media commands
 const U32 PARCEL_MEDIA_COMMAND_STOP  = 0;
@@ -365,51 +225,101 @@ const U32 PARCEL_MEDIA_COMMAND_SIZE = 11;
 const U32 PARCEL_MEDIA_COMMAND_DESC = 12;
 const U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13;
 
-// map item types
-const U32 MAP_ITEM_TELEHUB = 0x01;
-const U32 MAP_ITEM_PG_EVENT = 0x02;
-const U32 MAP_ITEM_MATURE_EVENT = 0x03;
-//const U32 MAP_ITEM_POPULAR = 0x04;		// No longer supported, 2009-03-02 KLW
-//const U32 MAP_ITEM_AGENT_COUNT = 0x05;
-const U32 MAP_ITEM_AGENT_LOCATIONS = 0x06;
-const U32 MAP_ITEM_LAND_FOR_SALE = 0x07;
-const U32 MAP_ITEM_CLASSIFIED = 0x08;
-const U32 MAP_ITEM_ADULT_EVENT = 0x09;
-const U32 MAP_ITEM_LAND_FOR_SALE_ADULT = 0x0a;
-
-// Region map layer numbers
-const S32 MAP_SIM_OBJECTS = 0;	
-const S32 MAP_SIM_TERRAIN = 1;
-const S32 MAP_SIM_LAND_FOR_SALE = 2;			// Transparent alpha overlay of land for sale
-const S32 MAP_SIM_IMAGE_TYPES = 3;				// Number of map layers
-const S32 MAP_SIM_INFO_MASK  		= 0x00FFFFFF;		// Agent access may be stuffed into upper byte
-const S32 MAP_SIM_LAYER_MASK 		= 0x0000FFFF;		// Layer info is in lower 16 bits
-const S32 MAP_SIM_RETURN_NULL_SIMS 	= 0x00010000;
-const S32 MAP_SIM_PRELUDE 			= 0x00020000;
-
-// Crash reporter behavior
-const S32 CRASH_BEHAVIOR_ASK = 0;
-const S32 CRASH_BEHAVIOR_ALWAYS_SEND = 1;
-const S32 CRASH_BEHAVIOR_NEVER_SEND = 2;
-
-// Export/Import return values
-const S32 EXPORT_SUCCESS = 0;
-const S32 EXPORT_ERROR_PERMISSIONS = -1;
-const S32 EXPORT_ERROR_UNKNOWN = -2;
-
-// This is how long the sim will try to teleport you before giving up.
-const F32 TELEPORT_EXPIRY = 15.0f;
-// Additional time (in seconds) to wait per attachment
-const F32 TELEPORT_EXPIRY_PER_ATTACHMENT = 3.f;
-
-// The maximum size of an object extra parameters binary (packed) block
-#define MAX_OBJECT_PARAMS_SIZE 1024
-
 const S32 CHAT_CHANNEL_DEBUG = S32_MAX;
 
-// PLEASE don't add constants here.  Every dev will have to do
-// a complete rebuild.  Try to find another shared header file,
-// like llregionflags.h, lllslconstants.h, llagentconstants.h,
-// or create a new one.  JC
+// agent constants
+const U32 CONTROL_AT_POS_INDEX				= 0;
+const U32 CONTROL_AT_NEG_INDEX				= 1;
+const U32 CONTROL_LEFT_POS_INDEX			= 2;
+const U32 CONTROL_LEFT_NEG_INDEX			= 3;
+const U32 CONTROL_UP_POS_INDEX				= 4;
+const U32 CONTROL_UP_NEG_INDEX				= 5;
+const U32 CONTROL_PITCH_POS_INDEX			= 6;
+const U32 CONTROL_PITCH_NEG_INDEX			= 7;
+const U32 CONTROL_YAW_POS_INDEX				= 8;
+const U32 CONTROL_YAW_NEG_INDEX				= 9;
+const U32 CONTROL_FAST_AT_INDEX				= 10;
+const U32 CONTROL_FAST_LEFT_INDEX			= 11;
+const U32 CONTROL_FAST_UP_INDEX				= 12;
+const U32 CONTROL_FLY_INDEX					= 13;
+const U32 CONTROL_STOP_INDEX				= 14;
+const U32 CONTROL_FINISH_ANIM_INDEX			= 15;
+const U32 CONTROL_STAND_UP_INDEX			= 16;
+const U32 CONTROL_SIT_ON_GROUND_INDEX		= 17;
+const U32 CONTROL_MOUSELOOK_INDEX			= 18;
+const U32 CONTROL_NUDGE_AT_POS_INDEX		= 19;
+const U32 CONTROL_NUDGE_AT_NEG_INDEX		= 20;
+const U32 CONTROL_NUDGE_LEFT_POS_INDEX		= 21;
+const U32 CONTROL_NUDGE_LEFT_NEG_INDEX		= 22;
+const U32 CONTROL_NUDGE_UP_POS_INDEX		= 23;
+const U32 CONTROL_NUDGE_UP_NEG_INDEX		= 24;
+const U32 CONTROL_TURN_LEFT_INDEX			= 25;
+const U32 CONTROL_TURN_RIGHT_INDEX			= 26;
+const U32 CONTROL_AWAY_INDEX				= 27;
+const U32 CONTROL_LBUTTON_DOWN_INDEX		= 28;
+const U32 CONTROL_LBUTTON_UP_INDEX			= 29;
+const U32 CONTROL_ML_LBUTTON_DOWN_INDEX		= 30;
+const U32 CONTROL_ML_LBUTTON_UP_INDEX		= 31;
+const U32 TOTAL_CONTROLS					= 32;
+
+const U32 AGENT_CONTROL_AT_POS              = 0x1 << CONTROL_AT_POS_INDEX;			// 0x00000001
+const U32 AGENT_CONTROL_AT_NEG              = 0x1 << CONTROL_AT_NEG_INDEX;			// 0x00000002
+const U32 AGENT_CONTROL_LEFT_POS            = 0x1 << CONTROL_LEFT_POS_INDEX;		// 0x00000004
+const U32 AGENT_CONTROL_LEFT_NEG            = 0x1 << CONTROL_LEFT_NEG_INDEX;		// 0x00000008
+const U32 AGENT_CONTROL_UP_POS              = 0x1 << CONTROL_UP_POS_INDEX;			// 0x00000010
+const U32 AGENT_CONTROL_UP_NEG              = 0x1 << CONTROL_UP_NEG_INDEX;			// 0x00000020
+const U32 AGENT_CONTROL_PITCH_POS           = 0x1 << CONTROL_PITCH_POS_INDEX;		// 0x00000040
+const U32 AGENT_CONTROL_PITCH_NEG           = 0x1 << CONTROL_PITCH_NEG_INDEX;		// 0x00000080
+const U32 AGENT_CONTROL_YAW_POS             = 0x1 << CONTROL_YAW_POS_INDEX;			// 0x00000100
+const U32 AGENT_CONTROL_YAW_NEG             = 0x1 << CONTROL_YAW_NEG_INDEX;			// 0x00000200
+
+const U32 AGENT_CONTROL_FAST_AT             = 0x1 << CONTROL_FAST_AT_INDEX;			// 0x00000400
+const U32 AGENT_CONTROL_FAST_LEFT           = 0x1 << CONTROL_FAST_LEFT_INDEX;		// 0x00000800
+const U32 AGENT_CONTROL_FAST_UP             = 0x1 << CONTROL_FAST_UP_INDEX;			// 0x00001000
+
+const U32 AGENT_CONTROL_FLY					= 0x1 << CONTROL_FLY_INDEX;				// 0x00002000
+const U32 AGENT_CONTROL_STOP				= 0x1 << CONTROL_STOP_INDEX;			// 0x00004000
+const U32 AGENT_CONTROL_FINISH_ANIM			= 0x1 << CONTROL_FINISH_ANIM_INDEX;		// 0x00008000
+const U32 AGENT_CONTROL_STAND_UP			= 0x1 << CONTROL_STAND_UP_INDEX;		// 0x00010000
+const U32 AGENT_CONTROL_SIT_ON_GROUND		= 0x1 << CONTROL_SIT_ON_GROUND_INDEX;	// 0x00020000
+const U32 AGENT_CONTROL_MOUSELOOK			= 0x1 << CONTROL_MOUSELOOK_INDEX;		// 0x00040000
+
+const U32 AGENT_CONTROL_NUDGE_AT_POS        = 0x1 << CONTROL_NUDGE_AT_POS_INDEX;	// 0x00080000
+const U32 AGENT_CONTROL_NUDGE_AT_NEG        = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX;	// 0x00100000
+const U32 AGENT_CONTROL_NUDGE_LEFT_POS      = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX;	// 0x00200000
+const U32 AGENT_CONTROL_NUDGE_LEFT_NEG      = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX;	// 0x00400000
+const U32 AGENT_CONTROL_NUDGE_UP_POS        = 0x1 << CONTROL_NUDGE_UP_POS_INDEX;	// 0x00800000
+const U32 AGENT_CONTROL_NUDGE_UP_NEG        = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX;	// 0x01000000
+const U32 AGENT_CONTROL_TURN_LEFT	        = 0x1 << CONTROL_TURN_LEFT_INDEX;		// 0x02000000
+const U32 AGENT_CONTROL_TURN_RIGHT	        = 0x1 << CONTROL_TURN_RIGHT_INDEX;		// 0x04000000
+
+const U32 AGENT_CONTROL_AWAY				= 0x1 << CONTROL_AWAY_INDEX;			// 0x08000000
+
+const U32 AGENT_CONTROL_LBUTTON_DOWN		= 0x1 << CONTROL_LBUTTON_DOWN_INDEX;	// 0x10000000
+const U32 AGENT_CONTROL_LBUTTON_UP			= 0x1 << CONTROL_LBUTTON_UP_INDEX;		// 0x20000000
+const U32 AGENT_CONTROL_ML_LBUTTON_DOWN		= 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX;	// 0x40000000
+const U32 AGENT_CONTROL_ML_LBUTTON_UP		= ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX;	// 0x80000000
+
+// move these up so that we can hide them in "State" for object updates 
+// (for now)
+const U32 AGENT_ATTACH_OFFSET				= 4;
+const U32 AGENT_ATTACH_MASK					= 0xf << AGENT_ATTACH_OFFSET;
+
+// RN: this method swaps the upper and lower nibbles to maintain backward 
+// compatibility with old objects that only used the upper nibble
+#define ATTACHMENT_ID_FROM_STATE(state) ((S32)((((U8)state & AGENT_ATTACH_MASK) >> 4) | (((U8)state & ~AGENT_ATTACH_MASK) << 4)))
+
+// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
+const U8 CLICK_ACTION_NONE = 0;
+const U8 CLICK_ACTION_TOUCH = 0;
+const U8 CLICK_ACTION_SIT = 1;
+const U8 CLICK_ACTION_BUY = 2;
+const U8 CLICK_ACTION_PAY = 3;
+const U8 CLICK_ACTION_OPEN = 4;
+const U8 CLICK_ACTION_PLAY = 5;
+const U8 CLICK_ACTION_OPEN_MEDIA = 6;
+const U8 CLICK_ACTION_ZOOM = 7;
+// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
+
 
 #endif
diff --git a/indra/llcommon/linked_lists.h b/indra/llcommon/linked_lists.h
deleted file mode 100755
index 6b25295b7b..0000000000
--- a/indra/llcommon/linked_lists.h
+++ /dev/null
@@ -1,937 +0,0 @@
-/** 
- * @file linked_lists.h
- * @brief LLLinkedList class header amd implementation file.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LINKED_LISTS_H
-#define LL_LINKED_LISTS_H
-
-/** 
- * Provides a standard doubly linked list for fun and profit
- * Utilizes a neat trick off of Flipcode where the back pointer is a
- * pointer to a pointer, allowing easier transfer of nodes between lists, &c
- * And a template class, of course
- */
-
-#include "llerror.h"
-
-
-template <class DATA_TYPE> class LLLinkedList
-{
-public:
-	friend class LLLinkNode;
-	// External interface
-
-	// basic constructor
-	LLLinkedList() : mHead(NULL), mCurrentp(NULL), mInsertBefore(NULL)
-	{
-		mCurrentp = mHead.mNextp;
-		mCurrentOperatingp = mHead.mNextp;
-		mCount = 0;
-	}
-
-	// basic constructor
-	LLLinkedList(BOOL	(*insert_before)(DATA_TYPE *data_new, DATA_TYPE *data_tested)) : mHead(NULL), mCurrentp(NULL), mInsertBefore(insert_before)
-	{
-		mCurrentp = mHead.mNextp;
-		mCurrentOperatingp = mHead.mNextp;
-		mCount = 0;
-	}
-
-	// destructor destroys list and nodes, but not data in nodes
-	~LLLinkedList()
-	{
-		removeAllNodes();
-	}
-
-	// set mInsertBefore
-	void setInsertBefore(BOOL (*insert_before)(DATA_TYPE *data_new, DATA_TYPE *data_tested))
-	{
-		mInsertBefore = insert_before;
-	}
-
-	//
-	// WARNING!!!!!!!
-	// addData and addDataSorted are NOT O(1) operations, but O(n) because they check
-	// for existence of the data in the linked list first.  Why, I don't know - djs
-	// If you don't care about dupes, use addDataNoCheck
-	//
-
-	// put data into a node and stick it at the front of the list
-	inline BOOL addData(DATA_TYPE *data);
-
-	// put data into a node and sort into list by mInsertBefore()
-	// calls normal add if mInsertBefore isn't set
-	inline BOOL addDataSorted(DATA_TYPE *data);
-
-	inline BOOL addDataNoCheck(DATA_TYPE *data);
-
-	// bubbleSortList
-	// does an improved bubble sort of the list . . . works best with almost sorted data
-	// does nothing if mInsertBefore isn't set
-	// Nota Bene: Swaps are accomplished by swapping data pointers
-	inline void bubbleSortList();
-
-	// put data into a node and stick it at the end of the list
-	inline BOOL addDataAtEnd(DATA_TYPE *data);
-
-	// returns number of items in the list
-	inline S32 getLength() const;
-
-	inline BOOL isEmpty();
-
-	// search the list starting at mHead.mNextp and remove the link with mDatap == data
-	// leave mCurrentp and mCurrentOperatingp on the next entry
-	// return TRUE if found, FALSE if not found
-	inline BOOL removeData(DATA_TYPE *data);
-
-		// search the list starting at mHead.mNextp and delete the link with mDatap == data
-	// leave mCurrentp and mCurrentOperatingp on the next entry
-	// return TRUE if found, FALSE if not found
-	inline BOOL deleteData(DATA_TYPE *data);
-
-	// remove all nodes from the list and delete the associated data
-	inline void deleteAllData();
-
-	// remove all nodes from the list but do not delete data
-	inline void removeAllNodes();
-
-	// check to see if data is in list
-	// if TRUE then mCurrentp and mCurrentOperatingp point to data
-	inline BOOL	checkData(DATA_TYPE *data);
-
-	// place mCurrentp on first node
-	inline void resetList();
-
-	// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-	inline DATA_TYPE	*getCurrentData();
-
-	// same as getCurrentData() but a more intuitive name for the operation
-	inline DATA_TYPE	*getNextData();
-
-	// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-	inline DATA_TYPE	*getFirstData();
-
-	// reset the list and return the data at position n, set mCurentOperatingp to that node and bump mCurrentp
-	// Note: n is zero-based
-	inline DATA_TYPE	*getNthData( U32 n);
-
-	// reset the list and return the last data in it, set mCurentOperatingp to that node and bump mCurrentp
-	inline DATA_TYPE	*getLastData();
-
-	// remove the Node at mCurentOperatingp
-	// leave mCurrentp and mCurentOperatingp on the next entry
-	inline void removeCurrentData();
-
-	// remove the Node at mCurentOperatingp and add it to newlist
-	// leave mCurrentp and mCurentOperatingp on the next entry
-	void moveCurrentData(LLLinkedList *newlist, BOOL b_sort);
-
-	BOOL moveData(DATA_TYPE *data, LLLinkedList *newlist, BOOL b_sort);
-
-	// delete the Node at mCurentOperatingp
-	// leave mCurrentp anf mCurentOperatingp on the next entry
-	void deleteCurrentData();
-
-private:
-	// node that actually contains the data
-	class LLLinkNode
-	{
-	public:
-		// assign the mDatap pointer
-		LLLinkNode(DATA_TYPE *data) : mDatap(data), mNextp(NULL), mPrevpp(NULL)
-		{
-		}
-
-		// destructor does not, by default, destroy associated data
-		// however, the mDatap must be NULL to ensure that we aren't causing memory leaks
-		~LLLinkNode()
-		{
-			if (mDatap)
-			{
-				llerror("Attempting to call LLLinkNode destructor with a non-null mDatap!", 1);
-			}
-		}
-
-		// delete associated data and NULL out pointer
-		void deleteData()
-		{
-			delete mDatap;
-			mDatap = NULL;
-		}
-
-		// NULL out pointer
-		void removeData()
-		{
-			mDatap = NULL;
-		}
-
-		DATA_TYPE	*mDatap;
-		LLLinkNode	*mNextp;
-		LLLinkNode	**mPrevpp;
-	};
-
-	// add a node at the front of the list
-	void addData(LLLinkNode *node)
-	{
-		// don't allow NULL to be passed to addData
-		if (!node)
-		{
-			llerror("NULL pointer passed to LLLinkedList::addData", 0);
-		}
-
-		// add the node to the front of the list
-		node->mPrevpp = &mHead.mNextp;
-		node->mNextp = mHead.mNextp;
-
-		// if there's something in the list, fix its back pointer
-		if (node->mNextp)
-		{
-			node->mNextp->mPrevpp = &node->mNextp;
-		}
-
-		mHead.mNextp = node;
-	}
-
-	LLLinkNode			mHead;															// fake head node. . . makes pointer operations faster and easier
-	LLLinkNode			*mCurrentp;														// mCurrentp is the Node that getCurrentData returns
-	LLLinkNode			*mCurrentOperatingp;											// this is the node that the various mumbleCurrentData functions act on
-	BOOL				(*mInsertBefore)(DATA_TYPE *data_new, DATA_TYPE *data_tested);	// user function set to allow sorted lists
-	U32					mCount;
-};
-
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::addData(DATA_TYPE *data)
-{
-	// don't allow NULL to be passed to addData
-	if (!data)
-	{
-		llerror("NULL pointer passed to LLLinkedList::addData", 0);
-	}
-
-	LLLinkNode *tcurr = mCurrentp;
-	LLLinkNode *tcurrop = mCurrentOperatingp;
-
-	if ( checkData(data))
-	{
-		mCurrentp = tcurr;
-		mCurrentOperatingp = tcurrop;
-		return FALSE;
-	}
-
-	// make the new node
-	LLLinkNode *temp = new LLLinkNode(data);
-
-	// add the node to the front of the list
-	temp->mPrevpp = &mHead.mNextp;
-	temp->mNextp = mHead.mNextp;
-
-	// if there's something in the list, fix its back pointer
-	if (temp->mNextp)
-	{
-		temp->mNextp->mPrevpp = &temp->mNextp;
-	}
-
-	mHead.mNextp = temp;
-	mCurrentp = tcurr;
-	mCurrentOperatingp = tcurrop;
-	mCount++;
-	return TRUE;
-}
-
-
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::addDataNoCheck(DATA_TYPE *data)
-{
-	// don't allow NULL to be passed to addData
-	if (!data)
-	{
-		llerror("NULL pointer passed to LLLinkedList::addData", 0);
-	}
-
-	LLLinkNode *tcurr = mCurrentp;
-	LLLinkNode *tcurrop = mCurrentOperatingp;
-
-	// make the new node
-	LLLinkNode *temp = new LLLinkNode(data);
-
-	// add the node to the front of the list
-	temp->mPrevpp = &mHead.mNextp;
-	temp->mNextp = mHead.mNextp;
-
-	// if there's something in the list, fix its back pointer
-	if (temp->mNextp)
-	{
-		temp->mNextp->mPrevpp = &temp->mNextp;
-	}
-
-	mHead.mNextp = temp;
-	mCurrentp = tcurr;
-	mCurrentOperatingp = tcurrop;
-	mCount++;
-	return TRUE;
-}
-
-
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::addDataSorted(DATA_TYPE *data)
-{
-	LLLinkNode *tcurr = mCurrentp;
-	LLLinkNode *tcurrop = mCurrentOperatingp;
-	// don't allow NULL to be passed to addData
-	if (!data)
-	{
-		llerror("NULL pointer passed to LLLinkedList::addDataSorted", 0);
-	}
-
-	if (checkData(data))
-	{
-		// restore
-		mCurrentp = tcurr;
-		mCurrentOperatingp = tcurrop;
-		return FALSE;
-	}
-
-	// mInsertBefore not set?
-	if (!mInsertBefore)
-	{
-		addData(data);
-		// restore
-		mCurrentp = tcurr;
-		mCurrentOperatingp = tcurrop;
-		return FALSE;
-	}
-
-	// empty list?
-	if (!mHead.mNextp)
-	{
-		addData(data);
-		// restore
-		mCurrentp = tcurr;
-		mCurrentOperatingp = tcurrop;
-		return TRUE;
-	}
-
-	// make the new node
-	LLLinkNode *temp = new LLLinkNode(data);
-
-	// walk the list until mInsertBefore returns true 
-	mCurrentp = mHead.mNextp;
-	while (mCurrentp->mNextp)
-	{
-		if (mInsertBefore(data, mCurrentp->mDatap))
-		{
-			// insert before the current one
-			temp->mPrevpp = mCurrentp->mPrevpp;
-			temp->mNextp = mCurrentp;
-			*(temp->mPrevpp) = temp;
-			mCurrentp->mPrevpp = &temp->mNextp;
-			// restore
-			mCurrentp = tcurr;
-			mCurrentOperatingp = tcurrop;
-			mCount++;
-			return TRUE;
-		}
-		else
-		{
-			mCurrentp = mCurrentp->mNextp;
-		}
-	}
-
-	// on the last element, add before?
-	if (mInsertBefore(data, mCurrentp->mDatap))
-	{
-		// insert before the current one
-		temp->mPrevpp = mCurrentp->mPrevpp;
-		temp->mNextp = mCurrentp;
-		*(temp->mPrevpp) = temp;
-		mCurrentp->mPrevpp = &temp->mNextp;
-		// restore
-		mCurrentp = tcurr;
-		mCurrentOperatingp = tcurrop;
-	}
-	else // insert after
-	{
-		temp->mPrevpp = &mCurrentp->mNextp;
-		temp->mNextp = NULL;
-		mCurrentp->mNextp = temp;
-
-		// restore
-		mCurrentp = tcurr;
-		mCurrentOperatingp = tcurrop;
-	}
-	mCount++;
-	return TRUE;
-}
-
-template <class DATA_TYPE>
-void LLLinkedList<DATA_TYPE>::bubbleSortList()
-{
-	// mInsertBefore not set
-	if (!mInsertBefore)
-	{
-		return;
-	}
-
-	LLLinkNode *tcurr = mCurrentp;
-	LLLinkNode *tcurrop = mCurrentOperatingp;
-
-	BOOL		b_swapped = FALSE;
-	DATA_TYPE	*temp;
-
-	// Nota Bene: This will break if more than 0x7FFFFFFF members in list!
-	S32			length = 0x7FFFFFFF;
-	S32			count = 0;
-	do
-	{
-		b_swapped = FALSE;
-		mCurrentp = mHead.mNextp;
-		count = 0;
-		while (  (count + 1 < length)
-			   &&(mCurrentp))
-		{
-			if (mCurrentp->mNextp)
-			{
-				if (!mInsertBefore(mCurrentp->mDatap, mCurrentp->mNextp->mDatap))
-				{
-					// swap data pointers!
-					temp = mCurrentp->mDatap;
-					mCurrentp->mDatap = mCurrentp->mNextp->mDatap;
-					mCurrentp->mNextp->mDatap = temp;
-					b_swapped = TRUE;
-				}
-			}
-			else
-			{
-				break;
-			}
-			count++;
-			mCurrentp = mCurrentp->mNextp;
-		}
-		length = count;
-	} while (b_swapped);
-
-	// restore
-	mCurrentp = tcurr;
-	mCurrentOperatingp = tcurrop;
-}
-
-
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::addDataAtEnd(DATA_TYPE *data)
-{
-	LLLinkNode *tcurr = mCurrentp;
-	LLLinkNode *tcurrop = mCurrentOperatingp;
-
-	// don't allow NULL to be passed to addData
-	if (!data)
-	{
-		llerror("NULL pointer passed to LLLinkedList::addData", 0);
-	}
-
-	if (checkData(data))
-	{
-		mCurrentp = tcurr;
-		mCurrentOperatingp = tcurrop;
-		return FALSE;
-	}
-
-	// make the new node
-	LLLinkNode *temp = new LLLinkNode(data);
-
-	// add the node to the end of the list
-
-	// if empty, add to the front and be done with it
-	if (!mHead.mNextp)
-	{
-		temp->mPrevpp = &mHead.mNextp;
-		temp->mNextp = NULL;
-		mHead.mNextp = temp;
-	}
-	else
-	{
-		// otherwise, walk to the end of the list
-		mCurrentp = mHead.mNextp;
-		while (mCurrentp->mNextp)
-		{
-			mCurrentp = mCurrentp->mNextp;
-		}
-		temp->mPrevpp = &mCurrentp->mNextp;
-		temp->mNextp = NULL;
-		mCurrentp->mNextp = temp;
-	}
-
-	// restore
-	mCurrentp = tcurr;
-	mCurrentOperatingp = tcurrop;
-	mCount++;
-	return TRUE;
-}
-
-
-// returns number of items in the list
-template <class DATA_TYPE>
-S32 LLLinkedList<DATA_TYPE>::getLength() const
-{
-//	S32	length = 0;
-//	for (LLLinkNode* temp = mHead.mNextp; temp != NULL; temp = temp->mNextp)
-//	{
-//		length++;
-//	}
-	return mCount;
-}
-
-
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::isEmpty()
-{
-	return (mCount == 0);
-}
-
-
-// search the list starting at mHead.mNextp and remove the link with mDatap == data
-// leave mCurrentp and mCurrentOperatingp on the next entry
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::removeData(DATA_TYPE *data)
-{
-	BOOL b_found = FALSE;
-	// don't allow NULL to be passed to addData
-	if (!data)
-	{
-		llerror("NULL pointer passed to LLLinkedList::removeData", 0);
-	}
-
-	LLLinkNode *tcurr = mCurrentp;
-	LLLinkNode *tcurrop = mCurrentOperatingp;
-
-	mCurrentp = mHead.mNextp;
-	mCurrentOperatingp = mHead.mNextp;
-
-	while (mCurrentOperatingp)
-	{
-		if (mCurrentOperatingp->mDatap == data)
-		{
-			b_found = TRUE;
-
-			// remove the node
-
-			// if there is a next one, fix it
-			if (mCurrentOperatingp->mNextp)
-			{
-				mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
-			}
-			*(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
-
-			// remove the LLLinkNode
-
-			// if we were on the one we want to delete, bump the cached copies
-			if (mCurrentOperatingp == tcurrop)
-			{
-				tcurrop = tcurr = mCurrentOperatingp->mNextp;
-			}
-			else if (mCurrentOperatingp == tcurr)
-			{
-				tcurrop = tcurr = mCurrentOperatingp->mNextp;
-			}
-
-			mCurrentp = mCurrentOperatingp->mNextp;
-
-			mCurrentOperatingp->removeData();
-			delete mCurrentOperatingp;
-			mCurrentOperatingp = mCurrentp;
-			mCount--;
-			break;
-		}
-		mCurrentOperatingp = mCurrentOperatingp->mNextp;
-	}
-	// restore
-	mCurrentp = tcurr;
-	mCurrentOperatingp = tcurrop;
-	return b_found;
-}
-
-// search the list starting at mHead.mNextp and delete the link with mDatap == data
-// leave mCurrentp and mCurrentOperatingp on the next entry
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::deleteData(DATA_TYPE *data)
-{
-	BOOL b_found = FALSE;
-	// don't allow NULL to be passed to addData
-	if (!data)
-	{
-		llerror("NULL pointer passed to LLLinkedList::removeData", 0);
-	}
-
-	LLLinkNode *tcurr = mCurrentp;
-	LLLinkNode *tcurrop = mCurrentOperatingp;
-
-	mCurrentp = mHead.mNextp;
-	mCurrentOperatingp = mHead.mNextp;
-
-	while (mCurrentOperatingp)
-	{
-		if (mCurrentOperatingp->mDatap == data)
-		{
-			b_found = TRUE;
-
-			// remove the node
-			// if there is a next one, fix it
-			if (mCurrentOperatingp->mNextp)
-			{
-				mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
-			}
-			*(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
-
-			// delete the LLLinkNode
-			// if we were on the one we want to delete, bump the cached copies
-			if (mCurrentOperatingp == tcurrop)
-			{
-				tcurrop = tcurr = mCurrentOperatingp->mNextp;
-			}
-
-			// and delete the associated data
-			llassert(mCurrentOperatingp);
-			mCurrentp = mCurrentOperatingp->mNextp;
-			mCurrentOperatingp->deleteData();
-			delete mCurrentOperatingp;
-			mCurrentOperatingp = mCurrentp;
-			mCount--;
-			break;
-		}
-		mCurrentOperatingp = mCurrentOperatingp->mNextp;
-	}
-	// restore
-	mCurrentp = tcurr;
-	mCurrentOperatingp = tcurrop;
-	return b_found;
-}
-
-	// remove all nodes from the list and delete the associated data
-template <class DATA_TYPE>
-void LLLinkedList<DATA_TYPE>::deleteAllData()
-{
-	LLLinkNode *temp;
-	// reset mCurrentp
-	mCurrentp = mHead.mNextp;
-
-	while (mCurrentp)
-	{
-		temp = mCurrentp->mNextp;
-		mCurrentp->deleteData();
-		delete mCurrentp;
-		mCurrentp = temp;
-	}
-
-	// reset mHead and mCurrentp
-	mHead.mNextp = NULL;
-	mCurrentp = mHead.mNextp;
-	mCurrentOperatingp = mHead.mNextp;
-	mCount = 0;
-}
-
-// remove all nodes from the list but do not delete data
-template <class DATA_TYPE>
-void LLLinkedList<DATA_TYPE>::removeAllNodes()
-{
-	LLLinkNode *temp;
-	// reset mCurrentp
-	mCurrentp = mHead.mNextp;
-
-	while (mCurrentp)
-	{
-		temp = mCurrentp->mNextp;
-		mCurrentp->removeData();
-		delete mCurrentp;
-		mCurrentp = temp;
-	}
-
-	// reset mHead and mCurrentp
-	mHead.mNextp = NULL;
-	mCurrentp = mHead.mNextp;
-	mCurrentOperatingp = mHead.mNextp;
-	mCount = 0;
-}
-
-// check to see if data is in list
-// if TRUE then mCurrentp and mCurrentOperatingp point to data
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::checkData(DATA_TYPE *data)
-{
-	// reset mCurrentp
-	mCurrentp = mHead.mNextp;
-
-	while (mCurrentp)
-	{
-		if (mCurrentp->mDatap == data)
-		{
-			mCurrentOperatingp = mCurrentp;
-			return TRUE;
-		}
-		mCurrentp = mCurrentp->mNextp;
-	}
-	mCurrentOperatingp = mCurrentp;
-	return FALSE;
-}
-
-// place mCurrentp on first node
-template <class DATA_TYPE>
-void LLLinkedList<DATA_TYPE>::resetList()
-{
-	mCurrentp = mHead.mNextp;
-	mCurrentOperatingp = mHead.mNextp;
-}
-
-// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class DATA_TYPE>
-DATA_TYPE *LLLinkedList<DATA_TYPE>::getCurrentData()
-{
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mNextp;
-		return mCurrentOperatingp->mDatap;
-	}
-	else
-	{
-		return NULL;
-	}
-}
-
-// same as getCurrentData() but a more intuitive name for the operation
-template <class DATA_TYPE>
-DATA_TYPE *LLLinkedList<DATA_TYPE>::getNextData()
-{
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mNextp;
-		return mCurrentOperatingp->mDatap;
-	}
-	else
-	{
-		return NULL;
-	}
-}
-
-// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class DATA_TYPE>
-DATA_TYPE *LLLinkedList<DATA_TYPE>::getFirstData()
-{
-	mCurrentp = mHead.mNextp;
-	mCurrentOperatingp = mHead.mNextp;
-	if (mCurrentp)
-	{
-		mCurrentOperatingp = mCurrentp;
-		mCurrentp = mCurrentp->mNextp;
-		return mCurrentOperatingp->mDatap;
-	}
-	else
-	{
-		return NULL;
-	}
-}
-
-// Note: n is zero-based
-template <class DATA_TYPE>
-DATA_TYPE	*LLLinkedList<DATA_TYPE>::getNthData( U32 n )
-{
-	mCurrentOperatingp = mHead.mNextp;
-
-	// if empty, return NULL
-	if (!mCurrentOperatingp)
-	{
-		return NULL;
-	}
-
-	for( U32 i = 0; i < n; i++ )
-	{
-		mCurrentOperatingp = mCurrentOperatingp->mNextp;
-		if( !mCurrentOperatingp )
-		{
-			return NULL;
-		}
-	}
-
-	mCurrentp = mCurrentOperatingp->mNextp;
-	return mCurrentOperatingp->mDatap;
-}
-
-
-// reset the list and return the last data in it, set mCurentOperatingp to that node and bump mCurrentp
-template <class DATA_TYPE>
-DATA_TYPE *LLLinkedList<DATA_TYPE>::getLastData()
-{
-	mCurrentOperatingp = mHead.mNextp;
-
-	// if empty, return NULL
-	if (!mCurrentOperatingp)
-		return NULL;
-
-	// walk until we're pointing at the last entry
-	while (mCurrentOperatingp->mNextp)
-	{
-		mCurrentOperatingp = mCurrentOperatingp->mNextp;
-	}
-	mCurrentp = mCurrentOperatingp->mNextp;
-	return mCurrentOperatingp->mDatap;
-}
-
-// remove the Node at mCurentOperatingp
-// leave mCurrentp and mCurentOperatingp on the next entry
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-void LLLinkedList<DATA_TYPE>::removeCurrentData()
-{
-	if (mCurrentOperatingp)
-	{
-		// remove the node
-		// if there is a next one, fix it
-		if (mCurrentOperatingp->mNextp)
-		{
-			mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
-		}
-		*(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
-
-		// remove the LLLinkNode
-		mCurrentp = mCurrentOperatingp->mNextp;
-
-		mCurrentOperatingp->removeData();
-		delete mCurrentOperatingp;
-		mCount--;
-		mCurrentOperatingp = mCurrentp;
-	}
-}
-
-// remove the Node at mCurentOperatingp and add it to newlist
-// leave mCurrentp and mCurentOperatingp on the next entry
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-void LLLinkedList<DATA_TYPE>::moveCurrentData(LLLinkedList *newlist, BOOL b_sort)
-{
-	if (mCurrentOperatingp)
-	{
-		// remove the node
-		// if there is a next one, fix it
-		if (mCurrentOperatingp->mNextp)
-		{
-			mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
-		}
-		*(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
-
-		// remove the LLLinkNode
-		mCurrentp = mCurrentOperatingp->mNextp;
-		// move the node to the new list
-		newlist->addData(mCurrentOperatingp);
-		if (b_sort)
-			bubbleSortList();
-		mCurrentOperatingp = mCurrentp;
-	}
-}
-
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::moveData(DATA_TYPE *data, LLLinkedList *newlist, BOOL b_sort)
-{
-	BOOL b_found = FALSE;
-	// don't allow NULL to be passed to addData
-	if (!data)
-	{
-		llerror("NULL pointer passed to LLLinkedList::removeData", 0);
-	}
-
-	LLLinkNode *tcurr = mCurrentp;
-	LLLinkNode *tcurrop = mCurrentOperatingp;
-
-	mCurrentp = mHead.mNextp;
-	mCurrentOperatingp = mHead.mNextp;
-
-	while (mCurrentOperatingp)
-	{
-		if (mCurrentOperatingp->mDatap == data)
-		{
-			b_found = TRUE;
-
-			// remove the node
-
-			// if there is a next one, fix it
-			if (mCurrentOperatingp->mNextp)
-			{
-				mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
-			}
-			*(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
-
-			// if we were on the one we want to delete, bump the cached copies
-			if (  (mCurrentOperatingp == tcurrop)
-				||(mCurrentOperatingp == tcurr))
-			{
-				tcurrop = tcurr = mCurrentOperatingp->mNextp;
-			}
-
-			// remove the LLLinkNode
-			mCurrentp = mCurrentOperatingp->mNextp;
-			// move the node to the new list
-			newlist->addData(mCurrentOperatingp);
-			if (b_sort)
-				newlist->bubbleSortList();
-			mCurrentOperatingp = mCurrentp;
-			break;
-		}
-		mCurrentOperatingp = mCurrentOperatingp->mNextp;
-	}
-	// restore
-	mCurrentp = tcurr;
-	mCurrentOperatingp = tcurrop;
-	return b_found;
-}
-
-// delete the Node at mCurentOperatingp
-// leave mCurrentp anf mCurentOperatingp on the next entry
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-void LLLinkedList<DATA_TYPE>::deleteCurrentData()
-{
-	if (mCurrentOperatingp)
-	{
-		// remove the node
-		// if there is a next one, fix it
-		if (mCurrentOperatingp->mNextp)
-		{
-			mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
-		}
-		*(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
-
-		// remove the LLLinkNode
-		mCurrentp = mCurrentOperatingp->mNextp;
-
-		mCurrentOperatingp->deleteData();
-		if (mCurrentOperatingp->mDatap)
-			llerror("This is impossible!", 0);
-		delete mCurrentOperatingp;
-		mCurrentOperatingp = mCurrentp;
-		mCount--;
-	}
-}
-
-#endif
diff --git a/indra/llcommon/ll_template_cast.h b/indra/llcommon/ll_template_cast.h
deleted file mode 100755
index c8f9a2f7eb..0000000000
--- a/indra/llcommon/ll_template_cast.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/**
- * @file   ll_template_cast.h
- * @author Nat Goodspeed
- * @date   2009-11-21
- * @brief  Define ll_template_cast function
- * 
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LL_TEMPLATE_CAST_H)
-#define LL_LL_TEMPLATE_CAST_H
-
-/**
- * Implementation for ll_template_cast() (q.v.).
- *
- * Default implementation: trying to cast two completely unrelated types
- * returns 0. Typically you'd specify T and U as pointer types, but in fact T
- * can be any type that can be initialized with 0.
- */
-template <typename T, typename U>
-struct ll_template_cast_impl
-{
-    T operator()(U)
-    {
-        return 0;
-    }
-};
-
-/**
- * ll_template_cast<T>(some_value) is for use in a template function when
- * some_value might be of arbitrary type, but you want to recognize type T
- * specially.
- *
- * It's designed for use with pointer types. Example:
- * @code
- * struct SpecialClass
- * {
- *     void someMethod(const std::string&) const;
- * };
- *
- * template <class REALCLASS>
- * void somefunc(const REALCLASS& instance)
- * {
- *     const SpecialClass* ptr = ll_template_cast<const SpecialClass*>(&instance);
- *     if (ptr)
- *     {
- *         ptr->someMethod("Call method only available on SpecialClass");
- *     }
- * }
- * @endcode
- *
- * Why is this better than dynamic_cast<>? Because unless OtherClass is
- * polymorphic, the following won't even compile (gcc 4.0.1):
- * @code
- * OtherClass other;
- * SpecialClass* ptr = dynamic_cast<SpecialClass*>(&other);
- * @endcode
- * to say nothing of this:
- * @code
- * void function(int);
- * SpecialClass* ptr = dynamic_cast<SpecialClass*>(&function);
- * @endcode
- * ll_template_cast handles these kinds of cases by returning 0.
- */
-template <typename T, typename U>
-T ll_template_cast(U value)
-{
-    return ll_template_cast_impl<T, U>()(value);
-}
-
-/**
- * Implementation for ll_template_cast() (q.v.).
- *
- * Implementation for identical types: return same value.
- */
-template <typename T>
-struct ll_template_cast_impl<T, T>
-{
-    T operator()(T value)
-    {
-        return value;
-    }
-};
-
-/**
- * LL_TEMPLATE_CONVERTIBLE(dest, source) asserts that, for a value @c s of
- * type @c source, <tt>ll_template_cast<dest>(s)</tt> will return @c s --
- * presuming that @c source can be converted to @c dest by the normal rules of
- * C++.
- *
- * By default, <tt>ll_template_cast<dest>(s)</tt> will return 0 unless @c s's
- * type is literally identical to @c dest. (This is because of the
- * straightforward application of template specialization rules.) That can
- * lead to surprising results, e.g.:
- *
- * @code
- * Foo myFoo;
- * const Foo* fooptr = ll_template_cast<const Foo*>(&myFoo);
- * @endcode
- *
- * Here @c fooptr will be 0 because <tt>&myFoo</tt> is of type <tt>Foo*</tt>
- * -- @em not <tt>const Foo*</tt>. (Declaring <tt>const Foo myFoo;</tt> would
- * force the compiler to do the right thing.)
- *
- * More disappointingly:
- * @code
- * struct Base {};
- * struct Subclass: public Base {};
- * Subclass object;
- * Base* ptr = ll_template_cast<Base*>(&object);
- * @endcode
- *
- * Here @c ptr will be 0 because <tt>&object</tt> is of type
- * <tt>Subclass*</tt> rather than <tt>Base*</tt>. We @em want this cast to
- * succeed, but without our help ll_template_cast can't recognize it.
- *
- * The following would suffice:
- * @code
- * LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
- * ...
- * Base* ptr = ll_template_cast<Base*>(&object);
- * @endcode
- *
- * However, as noted earlier, this is easily fooled:
- * @code
- * const Base* ptr = ll_template_cast<const Base*>(&object);
- * @endcode
- * would still produce 0 because we haven't yet seen:
- * @code
- * LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
- * @endcode
- *
- * @TODO
- * This macro should use Boost type_traits facilities for stripping and
- * re-adding @c const and @c volatile qualifiers so that invoking
- * LL_TEMPLATE_CONVERTIBLE(dest, source) will automatically generate all
- * permitted permutations. It's really not fair to the coder to require
- * separate:
- * @code
- * LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
- * LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
- * LL_TEMPLATE_CONVERTIBLE(const Base*, const Subclass*);
- * @endcode
- *
- * (Naturally we omit <tt>LL_TEMPLATE_CONVERTIBLE(Base*, const Subclass*)</tt>
- * because that's not permitted by normal C++ assignment anyway.)
- */
-#define LL_TEMPLATE_CONVERTIBLE(DEST, SOURCE)   \
-template <>                                     \
-struct ll_template_cast_impl<DEST, SOURCE>      \
-{                                               \
-    DEST operator()(SOURCE wrapper)             \
-    {                                           \
-        return wrapper;                         \
-    }                                           \
-}
-
-#endif /* ! defined(LL_LL_TEMPLATE_CAST_H) */
diff --git a/indra/llcommon/llaccountingcost.h b/indra/llcommon/llaccountingcost.h
deleted file mode 100755
index 0ef3b50c6d..0000000000
--- a/indra/llcommon/llaccountingcost.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/** 
- * @file llaccountingcost.h
- * @
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_ACCOUNTINGQUOTA_H
-#define LL_ACCOUNTINGQUOTA_H
-
-struct ParcelQuota
-{
-	ParcelQuota( F32 ownerRenderCost,	 F32 ownerPhysicsCost,	  F32 ownerNetworkCost,	   F32 ownerSimulationCost,
-				 F32 groupRenderCost,	 F32 groupPhysicsCost,	  F32 groupNetworkCost,	   F32 groupSimulationCost,
-				 F32 otherRenderCost,	 F32 otherPhysicsCost,	  F32 otherNetworkCost,	   F32 otherSimulationCost,
-				 F32 tempRenderCost,	 F32 tempPhysicsCost,	  F32 tempNetworkCost,	   F32 tempSimulationCost,
-				 F32 selectedRenderCost, F32 selectedPhysicsCost, F32 selectedNetworkCost, F32 selectedSimulationCost,
-				 F32 parcelCapacity )
-	: mOwnerRenderCost( ownerRenderCost ), mOwnerPhysicsCost( ownerPhysicsCost ) 
-	, mOwnerNetworkCost( ownerNetworkCost ), mOwnerSimulationCost( ownerSimulationCost )
-	, mGroupRenderCost( groupRenderCost ), mGroupPhysicsCost( groupPhysicsCost )
-	, mGroupNetworkCost( groupNetworkCost ), mGroupSimulationCost( groupSimulationCost )
-	, mOtherRenderCost( otherRenderCost ), mOtherPhysicsCost( otherPhysicsCost )
-	, mOtherNetworkCost( otherNetworkCost ), mOtherSimulationCost( otherSimulationCost )
-	, mTempRenderCost( tempRenderCost ), mTempPhysicsCost( tempPhysicsCost ) 
-	, mTempNetworkCost( tempNetworkCost ), mTempSimulationCost( tempSimulationCost )
-	, mSelectedRenderCost( tempRenderCost ), mSelectedPhysicsCost( tempPhysicsCost ) 
-	, mSelectedNetworkCost( tempNetworkCost ), mSelectedSimulationCost( selectedSimulationCost )
-	, mParcelCapacity( parcelCapacity )
-	{
-	}
-
-	ParcelQuota(){}			
-	F32 mOwnerRenderCost, mOwnerPhysicsCost, mOwnerNetworkCost, mOwnerSimulationCost;
-	F32 mGroupRenderCost, mGroupPhysicsCost, mGroupNetworkCost, mGroupSimulationCost;
-	F32 mOtherRenderCost, mOtherPhysicsCost, mOtherNetworkCost, mOtherSimulationCost;
-	F32 mTempRenderCost,  mTempPhysicsCost,  mTempNetworkCost,  mTempSimulationCost;
-	F32 mSelectedRenderCost, mSelectedPhysicsCost, mSelectedNetworkCost, mSelectedSimulationCost;
-	F32 mParcelCapacity;
-};
-
-//SelectionQuota atm does not require a id
-struct SelectionCost
-{
-	SelectionCost( /*LLTransactionID transactionId, */ F32 physicsCost, F32 networkCost, F32 simulationCost )
-	//: mTransactionId( transactionId)
-	: mPhysicsCost( physicsCost )
-	, mNetworkCost( networkCost )
-	, mSimulationCost( simulationCost )
-	{
-	}
-	SelectionCost()
-	: mPhysicsCost( 0.0f )
-	, mNetworkCost( 0.0f )
-	, mSimulationCost( 0.0f )
-	{}
-	
-	F32 mPhysicsCost, mNetworkCost, mSimulationCost;	
-	//LLTransactionID mTransactionId;
-};
-
-typedef enum { Roots = 0 , Prims } eSelectionType;
-
-#endif
-
-
-
diff --git a/indra/llcommon/llagentconstants.h b/indra/llcommon/llagentconstants.h
deleted file mode 100755
index cd237da4eb..0000000000
--- a/indra/llcommon/llagentconstants.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/** 
- * @file llagentconstants.h
- * @author James Cook, Andrew Meadows, Richard Nelson
- * @brief Shared constants through the system for agents.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLAGENTCONSTANTS_H
-#define LL_LLAGENTCONSTANTS_H
-
-const U32 CONTROL_AT_POS_INDEX				= 0;
-const U32 CONTROL_AT_NEG_INDEX				= 1;
-const U32 CONTROL_LEFT_POS_INDEX			= 2;
-const U32 CONTROL_LEFT_NEG_INDEX			= 3;
-const U32 CONTROL_UP_POS_INDEX				= 4;
-const U32 CONTROL_UP_NEG_INDEX				= 5;
-const U32 CONTROL_PITCH_POS_INDEX			= 6;
-const U32 CONTROL_PITCH_NEG_INDEX			= 7;
-const U32 CONTROL_YAW_POS_INDEX				= 8;
-const U32 CONTROL_YAW_NEG_INDEX				= 9;
-const U32 CONTROL_FAST_AT_INDEX				= 10;
-const U32 CONTROL_FAST_LEFT_INDEX			= 11;
-const U32 CONTROL_FAST_UP_INDEX				= 12;
-const U32 CONTROL_FLY_INDEX					= 13;
-const U32 CONTROL_STOP_INDEX				= 14;
-const U32 CONTROL_FINISH_ANIM_INDEX			= 15;
-const U32 CONTROL_STAND_UP_INDEX			= 16;
-const U32 CONTROL_SIT_ON_GROUND_INDEX		= 17;
-const U32 CONTROL_MOUSELOOK_INDEX			= 18;
-const U32 CONTROL_NUDGE_AT_POS_INDEX		= 19;
-const U32 CONTROL_NUDGE_AT_NEG_INDEX		= 20;
-const U32 CONTROL_NUDGE_LEFT_POS_INDEX		= 21;
-const U32 CONTROL_NUDGE_LEFT_NEG_INDEX		= 22;
-const U32 CONTROL_NUDGE_UP_POS_INDEX		= 23;
-const U32 CONTROL_NUDGE_UP_NEG_INDEX		= 24;
-const U32 CONTROL_TURN_LEFT_INDEX			= 25;
-const U32 CONTROL_TURN_RIGHT_INDEX			= 26;
-const U32 CONTROL_AWAY_INDEX				= 27;
-const U32 CONTROL_LBUTTON_DOWN_INDEX		= 28;
-const U32 CONTROL_LBUTTON_UP_INDEX			= 29;
-const U32 CONTROL_ML_LBUTTON_DOWN_INDEX		= 30;
-const U32 CONTROL_ML_LBUTTON_UP_INDEX		= 31;
-const U32 TOTAL_CONTROLS					= 32;
-
-const U32 AGENT_CONTROL_AT_POS              = 0x1 << CONTROL_AT_POS_INDEX;			// 0x00000001
-const U32 AGENT_CONTROL_AT_NEG              = 0x1 << CONTROL_AT_NEG_INDEX;			// 0x00000002
-const U32 AGENT_CONTROL_LEFT_POS            = 0x1 << CONTROL_LEFT_POS_INDEX;		// 0x00000004
-const U32 AGENT_CONTROL_LEFT_NEG            = 0x1 << CONTROL_LEFT_NEG_INDEX;		// 0x00000008
-const U32 AGENT_CONTROL_UP_POS              = 0x1 << CONTROL_UP_POS_INDEX;			// 0x00000010
-const U32 AGENT_CONTROL_UP_NEG              = 0x1 << CONTROL_UP_NEG_INDEX;			// 0x00000020
-const U32 AGENT_CONTROL_PITCH_POS           = 0x1 << CONTROL_PITCH_POS_INDEX;		// 0x00000040
-const U32 AGENT_CONTROL_PITCH_NEG           = 0x1 << CONTROL_PITCH_NEG_INDEX;		// 0x00000080
-const U32 AGENT_CONTROL_YAW_POS             = 0x1 << CONTROL_YAW_POS_INDEX;			// 0x00000100
-const U32 AGENT_CONTROL_YAW_NEG             = 0x1 << CONTROL_YAW_NEG_INDEX;			// 0x00000200
-
-const U32 AGENT_CONTROL_FAST_AT             = 0x1 << CONTROL_FAST_AT_INDEX;			// 0x00000400
-const U32 AGENT_CONTROL_FAST_LEFT           = 0x1 << CONTROL_FAST_LEFT_INDEX;		// 0x00000800
-const U32 AGENT_CONTROL_FAST_UP             = 0x1 << CONTROL_FAST_UP_INDEX;			// 0x00001000
-
-const U32 AGENT_CONTROL_FLY					= 0x1 << CONTROL_FLY_INDEX;				// 0x00002000
-const U32 AGENT_CONTROL_STOP				= 0x1 << CONTROL_STOP_INDEX;			// 0x00004000
-const U32 AGENT_CONTROL_FINISH_ANIM			= 0x1 << CONTROL_FINISH_ANIM_INDEX;		// 0x00008000
-const U32 AGENT_CONTROL_STAND_UP			= 0x1 << CONTROL_STAND_UP_INDEX;		// 0x00010000
-const U32 AGENT_CONTROL_SIT_ON_GROUND		= 0x1 << CONTROL_SIT_ON_GROUND_INDEX;	// 0x00020000
-const U32 AGENT_CONTROL_MOUSELOOK			= 0x1 << CONTROL_MOUSELOOK_INDEX;		// 0x00040000
-
-const U32 AGENT_CONTROL_NUDGE_AT_POS        = 0x1 << CONTROL_NUDGE_AT_POS_INDEX;	// 0x00080000
-const U32 AGENT_CONTROL_NUDGE_AT_NEG        = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX;	// 0x00100000
-const U32 AGENT_CONTROL_NUDGE_LEFT_POS      = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX;	// 0x00200000
-const U32 AGENT_CONTROL_NUDGE_LEFT_NEG      = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX;	// 0x00400000
-const U32 AGENT_CONTROL_NUDGE_UP_POS        = 0x1 << CONTROL_NUDGE_UP_POS_INDEX;	// 0x00800000
-const U32 AGENT_CONTROL_NUDGE_UP_NEG        = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX;	// 0x01000000
-const U32 AGENT_CONTROL_TURN_LEFT	        = 0x1 << CONTROL_TURN_LEFT_INDEX;		// 0x02000000
-const U32 AGENT_CONTROL_TURN_RIGHT	        = 0x1 << CONTROL_TURN_RIGHT_INDEX;		// 0x04000000
-
-const U32 AGENT_CONTROL_AWAY				= 0x1 << CONTROL_AWAY_INDEX;			// 0x08000000
-
-const U32 AGENT_CONTROL_LBUTTON_DOWN		= 0x1 << CONTROL_LBUTTON_DOWN_INDEX;	// 0x10000000
-const U32 AGENT_CONTROL_LBUTTON_UP			= 0x1 << CONTROL_LBUTTON_UP_INDEX;		// 0x20000000
-const U32 AGENT_CONTROL_ML_LBUTTON_DOWN		= 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX;	// 0x40000000
-const U32 AGENT_CONTROL_ML_LBUTTON_UP		= ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX;	// 0x80000000
-
-const U32 AGENT_CONTROL_AT 		= AGENT_CONTROL_AT_POS 
-								  | AGENT_CONTROL_AT_NEG 
-								  | AGENT_CONTROL_NUDGE_AT_POS 
-								  | AGENT_CONTROL_NUDGE_AT_NEG;
-
-const U32 AGENT_CONTROL_LEFT 	= AGENT_CONTROL_LEFT_POS 
-								  | AGENT_CONTROL_LEFT_NEG 
-								  | AGENT_CONTROL_NUDGE_LEFT_POS 
-								  | AGENT_CONTROL_NUDGE_LEFT_NEG;
-
-const U32 AGENT_CONTROL_UP 		= AGENT_CONTROL_UP_POS 
-								  | AGENT_CONTROL_UP_NEG 
-								  | AGENT_CONTROL_NUDGE_UP_POS 
-								  | AGENT_CONTROL_NUDGE_UP_NEG;
-
-const U32 AGENT_CONTROL_HORIZONTAL = AGENT_CONTROL_AT 
-									 | AGENT_CONTROL_LEFT;
-
-const U32 AGENT_CONTROL_NOT_USED_BY_LSL = AGENT_CONTROL_FLY 
-										  | AGENT_CONTROL_STOP 
-										  | AGENT_CONTROL_FINISH_ANIM 
-										  | AGENT_CONTROL_STAND_UP 
-										  | AGENT_CONTROL_SIT_ON_GROUND 
-										  | AGENT_CONTROL_MOUSELOOK 
-										  | AGENT_CONTROL_AWAY;
-
-const U32 AGENT_CONTROL_MOVEMENT = AGENT_CONTROL_AT 
-								   | AGENT_CONTROL_LEFT 
-								   | AGENT_CONTROL_UP;
-
-const U32 AGENT_CONTROL_ROTATION = AGENT_CONTROL_PITCH_POS 
-								   | AGENT_CONTROL_PITCH_NEG 
-								   | AGENT_CONTROL_YAW_POS 
-								   | AGENT_CONTROL_YAW_NEG;
-
-const U32 AGENT_CONTROL_NUDGE = AGENT_CONTROL_NUDGE_AT_POS
-								| AGENT_CONTROL_NUDGE_AT_NEG
-								| AGENT_CONTROL_NUDGE_LEFT_POS
-								| AGENT_CONTROL_NUDGE_LEFT_NEG;
-
-
-// move these up so that we can hide them in "State" for object updates 
-// (for now)
-const U32 AGENT_ATTACH_OFFSET				= 4;
-const U32 AGENT_ATTACH_MASK					= 0xf << AGENT_ATTACH_OFFSET;
-const U32 AGENT_ATTACH_CLEAR				= 0x00;
-
-// RN: this method swaps the upper and lower nibbles to maintain backward 
-// compatibility with old objects that only used the upper nibble
-#define ATTACHMENT_ID_FROM_STATE(state) ((S32)((((U8)state & AGENT_ATTACH_MASK) >> 4) | (((U8)state & ~AGENT_ATTACH_MASK) << 4)))
-
-// test state for use in testing grabbing the camera
-const U32 AGENT_CAMERA_OBJECT				= 0x1 << 3;
-
-const F32 MAX_ATTACHMENT_DIST = 3.5f; // meters?
-
-#endif
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index afa06df23e..82df78a335 100755
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -30,7 +30,6 @@
 #include <map>
 #include "llrun.h"
 #include "llsd.h"
-#include "lloptioninterface.h"
 
 // Forward declarations
 template <typename Type> class LLAtomic32;
@@ -64,7 +63,7 @@ namespace google_breakpad {
 	class ExceptionHandler; // See exception_handler.h
 }
 
-class LL_COMMON_API LLApp : public LLOptionInterface
+class LL_COMMON_API LLApp
 {
 	friend class LLErrorThread;
 public:
@@ -113,7 +112,7 @@ public:
 	 * @param name The name of the option.
 	 * @return Returns the option data.
 	 */
-	virtual LLSD getOption(const std::string& name) const;
+	LLSD getOption(const std::string& name) const;
 
 	/** 
 	 * @brief Parse command line options and insert them into
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 69b01731e5..5a95a58d93 100755
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -29,8 +29,6 @@
 
 #include <string>
 
-#include "stdenums.h" 	// for EDragAndDropType
-
 class LL_COMMON_API LLAssetType
 {
 public:
diff --git a/indra/llcommon/llavatarconstants.h b/indra/llcommon/llavatarconstants.h
deleted file mode 100755
index f47f447b45..0000000000
--- a/indra/llcommon/llavatarconstants.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/** 
- * @file llavatarconstants.h
- * @brief some useful short term constants for Indra
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_AVATAR_CONSTANTS_H
-#define LL_AVATAR_CONSTANTS_H
-
-// If this string is passed to dataserver in AvatarPropertiesUpdate 
-// then no change is made to user.profile_web
-const char* const BLACKLIST_PROFILE_WEB_STR = "featureWebProfilesDisabled";
-
-// If profile web pages are feature blacklisted then this URL is 
-// shown in the profile instead of the user's set URL
-const char* const BLACKLIST_PROFILE_WEB_URL = "http://secondlife.com/app/webdisabled";
-
-// Maximum number of avatar picks
-const S32 MAX_AVATAR_PICKS = 10;
-
-// For Flags in AvatarPropertiesReply
-const U32 AVATAR_ALLOW_PUBLISH			= 0x1 << 0;	// whether profile is externally visible or not
-const U32 AVATAR_MATURE_PUBLISH			= 0x1 << 1;	// profile is "mature"
-const U32 AVATAR_IDENTIFIED				= 0x1 << 2;	// whether avatar has provided payment info
-const U32 AVATAR_TRANSACTED				= 0x1 << 3;	// whether avatar has actively used payment info
-const U32 AVATAR_ONLINE					= 0x1 << 4; // the online status of this avatar, if known.
-const U32 AVATAR_AGEVERIFIED			= 0x1 << 5;	// whether avatar has been age-verified
-
-char const* const VISIBILITY_DEFAULT = "default";
-char const* const VISIBILITY_HIDDEN = "hidden";
-char const* const VISIBILITY_VISIBLE = "visible";
-char const* const VISIBILITY_INVISIBLE = "invisible";
-
-#endif
-
diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp
deleted file mode 100755
index 642bd82e90..0000000000
--- a/indra/llcommon/llavatarname.cpp
+++ /dev/null
@@ -1,239 +0,0 @@
-/** 
- * @file llavatarname.cpp
- * @brief Represents name-related data for an avatar, such as the
- * username/SLID ("bobsmith123" or "james.linden") and the display
- * name ("James Cook")
- *
- * $LicenseInfo:firstyear=2010&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-#include "linden_common.h"
-
-#include "llavatarname.h"
-
-#include "lldate.h"
-#include "llframetimer.h"
-#include "llsd.h"
-
-// Store these in pre-built std::strings to avoid memory allocations in
-// LLSD map lookups
-static const std::string USERNAME("username");
-static const std::string DISPLAY_NAME("display_name");
-static const std::string LEGACY_FIRST_NAME("legacy_first_name");
-static const std::string LEGACY_LAST_NAME("legacy_last_name");
-static const std::string IS_DISPLAY_NAME_DEFAULT("is_display_name_default");
-static const std::string DISPLAY_NAME_EXPIRES("display_name_expires");
-static const std::string DISPLAY_NAME_NEXT_UPDATE("display_name_next_update");
-
-bool LLAvatarName::sUseDisplayNames = true;
-
-// Minimum time-to-live (in seconds) for a name entry.
-// Avatar name should always guarantee to expire reasonably soon by default
-// so if the failure to get a valid expiration time was due to something temporary 
-// we will eventually request and get the right data.
-const F64 MIN_ENTRY_LIFETIME = 60.0;
-
-LLAvatarName::LLAvatarName()
-:	mUsername(),
-	mDisplayName(),
-	mLegacyFirstName(),
-	mLegacyLastName(),
-	mIsDisplayNameDefault(false),
-	mIsTemporaryName(false),
-	mExpires(F64_MAX),
-	mNextUpdate(0.0)
-{ }
-
-bool LLAvatarName::operator<(const LLAvatarName& rhs) const
-{
-	if (mUsername == rhs.mUsername)
-		return mDisplayName < rhs.mDisplayName;
-	else
-		return mUsername < rhs.mUsername;
-}
-
-//static 
-void LLAvatarName::setUseDisplayNames(bool use)
-{
-	sUseDisplayNames = use;
-}
-//static 
-bool LLAvatarName::useDisplayNames() 
-{ 
-	return sUseDisplayNames; 
-}
-
-LLSD LLAvatarName::asLLSD() const
-{
-	LLSD sd;
-	sd[USERNAME] = mUsername;
-	sd[DISPLAY_NAME] = mDisplayName;
-	sd[LEGACY_FIRST_NAME] = mLegacyFirstName;
-	sd[LEGACY_LAST_NAME] = mLegacyLastName;
-	sd[IS_DISPLAY_NAME_DEFAULT] = mIsDisplayNameDefault;
-	sd[DISPLAY_NAME_EXPIRES] = LLDate(mExpires);
-	sd[DISPLAY_NAME_NEXT_UPDATE] = LLDate(mNextUpdate);
-	return sd;
-}
-
-void LLAvatarName::fromLLSD(const LLSD& sd)
-{
-	mUsername = sd[USERNAME].asString();
-	mDisplayName = sd[DISPLAY_NAME].asString();
-	mLegacyFirstName = sd[LEGACY_FIRST_NAME].asString();
-	mLegacyLastName = sd[LEGACY_LAST_NAME].asString();
-	mIsDisplayNameDefault = sd[IS_DISPLAY_NAME_DEFAULT].asBoolean();
-	LLDate expires = sd[DISPLAY_NAME_EXPIRES];
-	mExpires = expires.secondsSinceEpoch();
-	LLDate next_update = sd[DISPLAY_NAME_NEXT_UPDATE];
-	mNextUpdate = next_update.secondsSinceEpoch();
-	
-	// Some avatars don't have explicit display names set. Force a legible display name here.
-	if (mDisplayName.empty())
-	{
-		mDisplayName = mUsername;
-	}
-}
-
-// Transform a string (typically provided by the legacy service) into a decent
-// avatar name instance.
-void LLAvatarName::fromString(const std::string& full_name)
-{
-	mDisplayName = full_name;
-	std::string::size_type index = full_name.find(' ');
-	if (index != std::string::npos)
-	{
-		// The name is in 2 parts (first last)
-		mLegacyFirstName = full_name.substr(0, index);
-		mLegacyLastName = full_name.substr(index+1);
-		if (mLegacyLastName != "Resident")
-		{
-			mUsername = mLegacyFirstName + "." + mLegacyLastName;
-			mDisplayName = full_name;
-			LLStringUtil::toLower(mUsername);
-		}
-		else
-		{
-			// Very old names do have a dummy "Resident" last name 
-			// that we choose to hide from users.
-			mUsername = mLegacyFirstName;
-			mDisplayName = mLegacyFirstName;
-		}
-	}
-	else
-	{
-		mLegacyFirstName = full_name;
-		mLegacyLastName = "";
-		mUsername = full_name;
-		mDisplayName = full_name;
-	}
-	mIsDisplayNameDefault = true;
-	mIsTemporaryName = true;
-	setExpires(MIN_ENTRY_LIFETIME);
-}
-
-void LLAvatarName::setExpires(F64 expires)
-{
-	mExpires = LLFrameTimer::getTotalSeconds() + expires;
-}
-
-std::string LLAvatarName::getCompleteName() const
-{
-	std::string name;
-	if (sUseDisplayNames)
-	{
-		if (mUsername.empty() || mIsDisplayNameDefault)
-		{
-			// If this particular display name is defaulted (i.e. based on user name),
-			// then display only the easier to read instance of the person's name.
-			name = mDisplayName;
-		}
-		else
-		{
-			name = mDisplayName + " (" + mUsername + ")";
-		}
-	}
-	else
-	{
-		name = getUserName();
-	}
-	return name;
-}
-
-std::string LLAvatarName::getLegacyName() const
-{
-	if (mLegacyFirstName.empty() && mLegacyLastName.empty()) // display names disabled?
-	{
-		return mDisplayName;
-	}
-
-	std::string name;
-	name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() );
-	name = mLegacyFirstName;
-	name += " ";
-	name += mLegacyLastName;
-	return name;
-}
-
-std::string LLAvatarName::getDisplayName() const
-{
-	if (sUseDisplayNames)
-	{
-		return mDisplayName;
-	}
-	else
-	{
-		return getUserName();
-	}
-}
-
-std::string LLAvatarName::getUserName() const
-{
-	std::string name;
-	if (mLegacyLastName.empty() || (mLegacyLastName == "Resident"))
-	{
-		if (mLegacyFirstName.empty())
-		{
-			// If we cannot create a user name from the legacy strings, use the display name
-			name = mDisplayName;
-		}
-		else
-		{
-			// The last name might be empty if it defaulted to "Resident"
-			name = mLegacyFirstName;
-		}
-	}
-	else
-	{
-		name = mLegacyFirstName + " " + mLegacyLastName;
-	}
-	return name;
-}
-
-void LLAvatarName::dump() const
-{
-	LL_DEBUGS("AvNameCache") << "LLAvatarName: "
-	                         << "user '" << mUsername << "' "
-							 << "display '" << mDisplayName << "' "
-	                         << "expires in " << mExpires - LLFrameTimer::getTotalSeconds() << " seconds"
-							 << LL_ENDL;
-}
-
diff --git a/indra/llcommon/llavatarname.h b/indra/llcommon/llavatarname.h
deleted file mode 100755
index 5d2fccc5ba..0000000000
--- a/indra/llcommon/llavatarname.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/** 
- * @file llavatarname.h
- * @brief Represents name-related data for an avatar, such as the
- * username/SLID ("bobsmith123" or "james.linden") and the display
- * name ("James Cook")
- *
- * $LicenseInfo:firstyear=2010&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-#ifndef LLAVATARNAME_H
-#define LLAVATARNAME_H
-
-#include <string>
-
-class LLSD;
-
-class LL_COMMON_API LLAvatarName
-{
-public:
-	LLAvatarName();
-	
-	bool operator<(const LLAvatarName& rhs) const;
-
-	// Conversion to and from LLSD (cache file or server response)
-	LLSD asLLSD() const;
-	void fromLLSD(const LLSD& sd);
-
-	// Used only in legacy mode when the display name capability is not provided server side
-	// or to otherwise create a temporary valid item.
-	void fromString(const std::string& full_name);
-	
-	// Set the name object to become invalid in "expires" seconds from now
-	void setExpires(F64 expires);
-
-	// Set and get the display name flag set by the user in preferences.
-	static void setUseDisplayNames(bool use);
-	static bool useDisplayNames();
-	
-	// A name object is valid if not temporary and not yet expired (default is expiration not checked)
-	bool isValidName(F64 max_unrefreshed = 0.0f) const { return !mIsTemporaryName && (mExpires >= max_unrefreshed); }
-	
-	// Return true if the name is made up from legacy or temporary data
-	bool isDisplayNameDefault() const { return mIsDisplayNameDefault; }
-	
-	// For normal names, returns "James Linden (james.linden)"
-	// When display names are disabled returns just "James Linden"
-	std::string getCompleteName() const;
-	
-	// Returns "James Linden" or "bobsmith123 Resident" for backwards
-	// compatibility with systems like voice and muting
-	// *TODO: Eliminate this in favor of username only
-	std::string getLegacyName() const;
-	
-	// "José Sanchez" or "James Linden", UTF-8 encoded Unicode
-	// Takes the display name preference into account. This is truly the name that should 
-	// be used for all UI where an avatar name has to be used unless we truly want something else (rare)
-	std::string getDisplayName() const;
-	
-	// Returns "James Linden" or "bobsmith123 Resident"
-	// Used where we explicitely prefer or need a non UTF-8 legacy (ASCII) name
-	// Also used for backwards compatibility with systems like voice and muting
-	std::string getUserName() const;
-	
-	// Returns "james.linden" or the legacy name for very old names
-	std::string getAccountName() const { return mUsername; }
-
-	// Debug print of the object
-	void dump() const;
-	
-	// Names can change, so need to keep track of when name was
-	// last checked.
-	// Unix time-from-epoch seconds for efficiency
-	F64 mExpires;
-	
-	// You can only change your name every N hours, so record
-	// when the next update is allowed
-	// Unix time-from-epoch seconds
-	F64 mNextUpdate;
-	
-private:
-	// "bobsmith123" or "james.linden", US-ASCII only
-	std::string mUsername;
-
-	// "José Sanchez" or "James Linden", UTF-8 encoded Unicode
-	// Contains data whether or not user has explicitly set
-	// a display name; may duplicate their username.
-	std::string mDisplayName;
-
-	// For "James Linden", "James"
-	// For "bobsmith123", "bobsmith123"
-	// Used to communicate with legacy systems like voice and muting which
-	// rely on old-style names.
-	// *TODO: Eliminate this in favor of username only
-	std::string mLegacyFirstName;
-
-	// For "James Linden", "Linden"
-	// For "bobsmith123", "Resident"
-	// see above for rationale
-	std::string mLegacyLastName;
-
-	// If true, both display name and SLID were generated from
-	// a legacy first and last name, like "James Linden (james.linden)"
-	bool mIsDisplayNameDefault;
-
-	// Under error conditions, we may insert "dummy" records with
-	// names like "???" into caches as placeholders.  These can be
-	// shown in UI, but are not serialized.
-	bool mIsTemporaryName;
-
-	// Global flag indicating if display name should be used or not
-	// This will affect the output of the high level "get" methods
-	static bool sUseDisplayNames;
-};
-
-#endif
diff --git a/indra/llcommon/llbitpack.cpp b/indra/llcommon/llbitpack.cpp
new file mode 100755
index 0000000000..622a099945
--- /dev/null
+++ b/indra/llcommon/llbitpack.cpp
@@ -0,0 +1,30 @@
+/** 
+ * @file bitpack.cpp
+ * @brief LLBitPack class implementation
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes.
+#include "llbitpack.h"
diff --git a/indra/llcommon/llbitpack.h b/indra/llcommon/llbitpack.h
new file mode 100755
index 0000000000..fea56a4f1f
--- /dev/null
+++ b/indra/llcommon/llbitpack.h
@@ -0,0 +1,208 @@
+/** 
+ * @file llbitpack.h
+ * @brief Convert data to packed bit stream
+ *
+ * $LicenseInfo:firstyear=2000&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_BITPACK_H
+#define LL_BITPACK_H
+
+#include "llerror.h"
+
+const U32 MAX_DATA_BITS = 8;
+
+
+class LLBitPack
+{
+public:
+	LLBitPack(U8 *buffer, U32 max_size) : mBuffer(buffer), mBufferSize(0), mLoad(0), mLoadSize(0), mTotalBits(0), mMaxSize(max_size)
+	{
+	}
+
+	~LLBitPack()
+	{
+	}
+
+	void resetBitPacking()
+	{
+		mLoad = 0;
+		mLoadSize = 0;
+		mTotalBits = 0;
+		mBufferSize = 0;
+	}
+
+	U32 bitPack(U8 *total_data, U32 total_dsize)
+	{
+		U32 dsize;
+		U8 data;
+
+		while (total_dsize > 0)
+		{
+			if (total_dsize > MAX_DATA_BITS)
+			{
+				dsize = MAX_DATA_BITS;
+				total_dsize -= MAX_DATA_BITS;
+			}
+			else
+			{
+				dsize = total_dsize;
+				total_dsize = 0;
+			}
+
+			data = *total_data++;
+
+			data <<= (MAX_DATA_BITS - dsize);
+			while (dsize > 0) 
+			{
+				if (mLoadSize == MAX_DATA_BITS) 
+				{
+					*(mBuffer + mBufferSize++) = mLoad;
+					if (mBufferSize > mMaxSize)
+					{
+						LL_ERRS() << "mBufferSize exceeding mMaxSize!" << LL_ENDL;
+					}
+					mLoadSize = 0;
+					mLoad = 0x00;
+				}
+				mLoad <<= 1;			
+				mLoad |= (data >> (MAX_DATA_BITS - 1));
+				data <<= 1;
+				mLoadSize++;
+				mTotalBits++;
+				dsize--;
+			}
+		}
+		return mBufferSize;
+	}
+
+	U32 bitCopy(U8 *total_data, U32 total_dsize)
+	{
+		U32 dsize;
+		U8  data;
+
+		while (total_dsize > 0)
+		{
+			if (total_dsize > MAX_DATA_BITS)
+			{
+				dsize = MAX_DATA_BITS;
+				total_dsize -= MAX_DATA_BITS;
+			}
+			else
+			{
+				dsize = total_dsize;
+				total_dsize = 0;
+			}
+
+			data = *total_data++;
+
+			while (dsize > 0) 
+			{
+				if (mLoadSize == MAX_DATA_BITS) 
+				{
+					*(mBuffer + mBufferSize++) = mLoad;
+					if (mBufferSize > mMaxSize)
+					{
+						LL_ERRS() << "mBufferSize exceeding mMaxSize!" << LL_ENDL;
+					}
+					mLoadSize = 0;
+					mLoad = 0x00;
+				}
+				mLoad <<= 1;			
+				mLoad |= (data >> (MAX_DATA_BITS - 1));
+				data <<= 1;
+				mLoadSize++;
+				mTotalBits++;
+				dsize--;
+			}
+		}
+		return mBufferSize;
+	}
+
+	U32 bitUnpack(U8 *total_retval, U32 total_dsize)
+	{
+		U32 dsize;
+		U8	*retval;
+
+		while (total_dsize > 0)
+		{
+			if (total_dsize > MAX_DATA_BITS)
+			{
+				dsize = MAX_DATA_BITS;
+				total_dsize -= MAX_DATA_BITS;
+			}
+			else
+			{
+				dsize = total_dsize;
+				total_dsize = 0;
+			}
+
+			retval = total_retval++;
+			*retval = 0x00;
+			while (dsize > 0) 
+			{
+				if (mLoadSize == 0) 
+				{
+#ifdef _DEBUG
+					if (mBufferSize > mMaxSize)
+					{
+						llerrs << "mBufferSize exceeding mMaxSize" << llendl;
+						llerrs << mBufferSize << " > " << mMaxSize << llendl;
+					}
+#endif
+					mLoad = *(mBuffer + mBufferSize++);
+					mLoadSize = MAX_DATA_BITS;
+				}
+				*retval <<= 1;
+				*retval |= (mLoad >> (MAX_DATA_BITS - 1));
+				mLoadSize--;
+				mLoad <<= 1;
+				dsize--;
+			}
+		}
+		return mBufferSize;
+	}
+
+	U32 flushBitPack()
+	{
+		if (mLoadSize) 
+		{
+			mLoad <<= (MAX_DATA_BITS - mLoadSize);
+			*(mBuffer + mBufferSize++) = mLoad;
+			if (mBufferSize > mMaxSize)
+			{
+				LL_ERRS() << "mBufferSize exceeding mMaxSize!" << LL_ENDL;
+			}
+			mLoadSize = 0;
+		}
+		return mBufferSize;
+	}
+
+	U8		*mBuffer;
+	U32		mBufferSize;
+	U8		mLoad;
+	U32		mLoadSize;
+	U32		mTotalBits;
+	U32		mMaxSize;
+};
+
+#endif
diff --git a/indra/llcommon/llchat.h b/indra/llcommon/llchat.h
deleted file mode 100755
index f5b242fdfc..0000000000
--- a/indra/llcommon/llchat.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/** 
- * @file llchat.h
- * @author James Cook
- * @brief Chat constants and data structures.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLCHAT_H
-#define LL_LLCHAT_H
-
-#include "lluuid.h"
-#include "v3math.h"
-
-// enumerations used by the chat system
-typedef enum e_chat_source_type
-{
-	CHAT_SOURCE_SYSTEM = 0,
-	CHAT_SOURCE_AGENT = 1,
-	CHAT_SOURCE_OBJECT = 2,
-	CHAT_SOURCE_UNKNOWN = 3
-} EChatSourceType;
-
-typedef enum e_chat_type
-{
-	CHAT_TYPE_WHISPER = 0,
-	CHAT_TYPE_NORMAL = 1,
-	CHAT_TYPE_SHOUT = 2,
-	CHAT_TYPE_START = 4,
-	CHAT_TYPE_STOP = 5,
-	CHAT_TYPE_DEBUG_MSG = 6,
-	CHAT_TYPE_REGION = 7,
-	CHAT_TYPE_OWNER = 8,
-	CHAT_TYPE_DIRECT = 9		// From llRegionSayTo()
-} EChatType;
-
-typedef enum e_chat_audible_level
-{
-	CHAT_AUDIBLE_NOT = -1,
-	CHAT_AUDIBLE_BARELY = 0,
-	CHAT_AUDIBLE_FULLY = 1
-} EChatAudible;
-
-typedef enum e_chat_style
-{
-	CHAT_STYLE_NORMAL,
-	CHAT_STYLE_IRC,
-	CHAT_STYLE_HISTORY
-}EChatStyle;
-
-// A piece of chat
-class LLChat
-{
-public:
-	LLChat(const std::string& text = std::string())
-	:	mText(text),
-		mFromName(),
-		mFromID(),
-		mNotifId(),
-		mOwnerID(),
-		mSourceType(CHAT_SOURCE_AGENT),
-		mChatType(CHAT_TYPE_NORMAL),
-		mAudible(CHAT_AUDIBLE_FULLY),
-		mMuted(FALSE),
-		mTime(0.0),
-		mTimeStr(),
-		mPosAgent(),
-		mURL(),
-		mChatStyle(CHAT_STYLE_NORMAL),
-		mSessionID()
-	{ }
-	
-	std::string		mText;		// UTF-8 line of text
-	std::string		mFromName;	// agent or object name
-	LLUUID			mFromID;	// agent id or object id
-	LLUUID			mNotifId;
-	LLUUID			mOwnerID;
-	EChatSourceType	mSourceType;
-	EChatType		mChatType;
-	EChatAudible	mAudible;
-	BOOL			mMuted;		// pass muted chat to maintain list of chatters
-	F64				mTime;		// viewer only, seconds from viewer start
-	std::string		mTimeStr;
-	LLVector3		mPosAgent;
-	std::string		mURL;
-	EChatStyle		mChatStyle;
-	LLUUID			mSessionID;
-};
-
-#endif
diff --git a/indra/llcommon/llclickaction.h b/indra/llcommon/llclickaction.h
deleted file mode 100755
index 1f87d8eec3..0000000000
--- a/indra/llcommon/llclickaction.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/** 
- * @file llclickaction.h
- * @author James Cook
- * @brief Constants for single-click actions on objects
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLCLICKACTION_H
-#define LL_LLCLICKACTION_H
-// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
-const U8 CLICK_ACTION_NONE = 0;
-const U8 CLICK_ACTION_TOUCH = 0;
-const U8 CLICK_ACTION_SIT = 1;
-const U8 CLICK_ACTION_BUY = 2;
-const U8 CLICK_ACTION_PAY = 3;
-const U8 CLICK_ACTION_OPEN = 4;
-const U8 CLICK_ACTION_PLAY = 5;
-const U8 CLICK_ACTION_OPEN_MEDIA = 6;
-const U8 CLICK_ACTION_ZOOM = 7;
-// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
-#endif
diff --git a/indra/llcommon/llcursortypes.cpp b/indra/llcommon/llcursortypes.cpp
deleted file mode 100755
index ec60097195..0000000000
--- a/indra/llcommon/llcursortypes.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/** 
- * @file llcursortypes.cpp
- * @brief Cursor types and lookup of types from a string
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llcursortypes.h"
-
-ECursorType getCursorFromString(const std::string& cursor_string)
-{
-	static std::map<std::string,U32> cursor_string_table;
-	if (cursor_string_table.empty())
-	{
-		cursor_string_table["UI_CURSOR_ARROW"] = UI_CURSOR_ARROW;
-		cursor_string_table["UI_CURSOR_WAIT"] = UI_CURSOR_WAIT;
-		cursor_string_table["UI_CURSOR_HAND"] = UI_CURSOR_HAND;
-		cursor_string_table["UI_CURSOR_IBEAM"] = UI_CURSOR_IBEAM;
-		cursor_string_table["UI_CURSOR_CROSS"] = UI_CURSOR_CROSS;
-		cursor_string_table["UI_CURSOR_SIZENWSE"] = UI_CURSOR_SIZENWSE;
-		cursor_string_table["UI_CURSOR_SIZENESW"] = UI_CURSOR_SIZENESW;
-		cursor_string_table["UI_CURSOR_SIZEWE"] = UI_CURSOR_SIZEWE;
-		cursor_string_table["UI_CURSOR_SIZENS"] = UI_CURSOR_SIZENS;
-		cursor_string_table["UI_CURSOR_NO"] = UI_CURSOR_NO;
-		cursor_string_table["UI_CURSOR_WORKING"] = UI_CURSOR_WORKING;
-		cursor_string_table["UI_CURSOR_TOOLGRAB"] = UI_CURSOR_TOOLGRAB;
-		cursor_string_table["UI_CURSOR_TOOLLAND"] = UI_CURSOR_TOOLLAND;
-		cursor_string_table["UI_CURSOR_TOOLFOCUS"] = UI_CURSOR_TOOLFOCUS;
-		cursor_string_table["UI_CURSOR_TOOLCREATE"] = UI_CURSOR_TOOLCREATE;
-		cursor_string_table["UI_CURSOR_ARROWDRAG"] = UI_CURSOR_ARROWDRAG;
-		cursor_string_table["UI_CURSOR_ARROWCOPY"] = UI_CURSOR_ARROWCOPY;
-		cursor_string_table["UI_CURSOR_ARROWDRAGMULTI"] = UI_CURSOR_ARROWDRAGMULTI;
-		cursor_string_table["UI_CURSOR_ARROWCOPYMULTI"] = UI_CURSOR_ARROWCOPYMULTI;
-		cursor_string_table["UI_CURSOR_NOLOCKED"] = UI_CURSOR_NOLOCKED;
-		cursor_string_table["UI_CURSOR_ARROWLOCKED"] = UI_CURSOR_ARROWLOCKED;
-		cursor_string_table["UI_CURSOR_GRABLOCKED"] = UI_CURSOR_GRABLOCKED;
-		cursor_string_table["UI_CURSOR_TOOLTRANSLATE"] = UI_CURSOR_TOOLTRANSLATE;
-		cursor_string_table["UI_CURSOR_TOOLROTATE"] = UI_CURSOR_TOOLROTATE;
-		cursor_string_table["UI_CURSOR_TOOLSCALE"] = UI_CURSOR_TOOLSCALE;
-		cursor_string_table["UI_CURSOR_TOOLCAMERA"] = UI_CURSOR_TOOLCAMERA;
-		cursor_string_table["UI_CURSOR_TOOLPAN"] = UI_CURSOR_TOOLPAN;
-		cursor_string_table["UI_CURSOR_TOOLZOOMIN"] = UI_CURSOR_TOOLZOOMIN;
-		cursor_string_table["UI_CURSOR_TOOLPICKOBJECT3"] = UI_CURSOR_TOOLPICKOBJECT3;
-		cursor_string_table["UI_CURSOR_TOOLPLAY"] = UI_CURSOR_TOOLPLAY;
-		cursor_string_table["UI_CURSOR_TOOLPAUSE"] = UI_CURSOR_TOOLPAUSE;
-		cursor_string_table["UI_CURSOR_TOOLMEDIAOPEN"] = UI_CURSOR_TOOLMEDIAOPEN;
-		cursor_string_table["UI_CURSOR_PIPETTE"] = UI_CURSOR_PIPETTE;
-		cursor_string_table["UI_CURSOR_TOOLSIT"] = UI_CURSOR_TOOLSIT;
-		cursor_string_table["UI_CURSOR_TOOLBUY"] = UI_CURSOR_TOOLBUY;
-		cursor_string_table["UI_CURSOR_TOOLOPEN"] = UI_CURSOR_TOOLOPEN;
-		cursor_string_table["UI_CURSOR_TOOLPATHFINDING"] = UI_CURSOR_TOOLPATHFINDING;
-		cursor_string_table["UI_CURSOR_TOOLPATHFINDINGPATHSTART"] = UI_CURSOR_TOOLPATHFINDING_PATH_START;
-		cursor_string_table["UI_CURSOR_TOOLPATHFINDINGPATHSTARTADD"] = UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD;
-		cursor_string_table["UI_CURSOR_TOOLPATHFINDINGPATHEND"] = UI_CURSOR_TOOLPATHFINDING_PATH_END;
-		cursor_string_table["UI_CURSOR_TOOLPATHFINDINGPATHENDADD"] = UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD;
-		cursor_string_table["UI_CURSOR_TOOLNO"] = UI_CURSOR_TOOLNO;
-	}
-
-	std::map<std::string,U32>::const_iterator iter = cursor_string_table.find(cursor_string);
-	
-	if (iter != cursor_string_table.end())
-	{
-		return (ECursorType)iter->second;
-	}
-
-	return UI_CURSOR_ARROW;
-}
-
-
-
diff --git a/indra/llcommon/llcursortypes.h b/indra/llcommon/llcursortypes.h
deleted file mode 100755
index cb6d6636a0..0000000000
--- a/indra/llcommon/llcursortypes.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/** 
- * @file llcursortypes.h
- * @brief Cursor types
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLCURSORTYPES_H
-#define LL_LLCURSORTYPES_H
-
-// If you add types here, add them in LLCursor::getCursorFromString
-enum ECursorType {
-	UI_CURSOR_ARROW,
-	UI_CURSOR_WAIT,
-	UI_CURSOR_HAND,
-	UI_CURSOR_IBEAM,
-	UI_CURSOR_CROSS,
-	UI_CURSOR_SIZENWSE,
-	UI_CURSOR_SIZENESW,
-	UI_CURSOR_SIZEWE,
-	UI_CURSOR_SIZENS,
-	UI_CURSOR_NO,
-	UI_CURSOR_WORKING,
-	UI_CURSOR_TOOLGRAB,
-	UI_CURSOR_TOOLLAND,
-	UI_CURSOR_TOOLFOCUS,
-	UI_CURSOR_TOOLCREATE,
-	UI_CURSOR_ARROWDRAG,
-	UI_CURSOR_ARROWCOPY,	// drag with copy
-	UI_CURSOR_ARROWDRAGMULTI,
-	UI_CURSOR_ARROWCOPYMULTI,	// drag with copy
-	UI_CURSOR_NOLOCKED,
-	UI_CURSOR_ARROWLOCKED,
-	UI_CURSOR_GRABLOCKED,
-	UI_CURSOR_TOOLTRANSLATE,
-	UI_CURSOR_TOOLROTATE,
-	UI_CURSOR_TOOLSCALE,
-	UI_CURSOR_TOOLCAMERA,
-	UI_CURSOR_TOOLPAN,
-	UI_CURSOR_TOOLZOOMIN,
-	UI_CURSOR_TOOLPICKOBJECT3,
-	UI_CURSOR_TOOLPLAY,
-	UI_CURSOR_TOOLPAUSE,
-	UI_CURSOR_TOOLMEDIAOPEN,
-	UI_CURSOR_PIPETTE,
-	UI_CURSOR_TOOLSIT,
-	UI_CURSOR_TOOLBUY,
-	UI_CURSOR_TOOLOPEN,
-	UI_CURSOR_TOOLPATHFINDING,
-	UI_CURSOR_TOOLPATHFINDING_PATH_START,
-	UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD,
-	UI_CURSOR_TOOLPATHFINDING_PATH_END,
-	UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD,
-	UI_CURSOR_TOOLNO,
-	UI_CURSOR_COUNT			// Number of elements in this enum (NOT a cursor)
-};
-
-LL_COMMON_API ECursorType getCursorFromString(const std::string& cursor_string);
-
-#endif // LL_LLCURSORTYPES_H
diff --git a/indra/llcommon/lldarray.h b/indra/llcommon/lldarray.h
deleted file mode 100755
index 131b819c99..0000000000
--- a/indra/llcommon/lldarray.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/** 
- * @file lldarray.h
- * @brief Wrapped std::vector for backward compatibility.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLDARRAY_H
-#define LL_LLDARRAY_H
-
-#include "llerror.h"
-
-#include <vector>
-#include <map>
-
-// class LLDynamicArray<>; // = std::vector + reserves <BlockSize> elements
-// class LLDynamicArrayIndexed<>; // = std::vector + std::map if indices, only supports operator[] and begin(),end()
-
-//--------------------------------------------------------
-// LLDynamicArray declaration
-//--------------------------------------------------------
-// NOTE: BlockSize is used to reserve a minimal initial amount
-template <typename Type, int BlockSize = 32> 
-class LLDynamicArray : public std::vector<Type>
-{
-public:
-	enum
-	{
-		OKAY = 0,
-		FAIL = -1
-	};
-	
-	LLDynamicArray(S32 size=0) : std::vector<Type>(size) { if (size < BlockSize) std::vector<Type>::reserve(BlockSize); }
-
-	void reset() { std::vector<Type>::clear(); }
-
-	// ACCESSORS
-	const Type& get(S32 index) const	 			{ return std::vector<Type>::operator[](index); }
-	Type&       get(S32 index)						{ return std::vector<Type>::operator[](index); }
-	S32			find(const Type &obj) const;
-
-	S32			count() const						{ return std::vector<Type>::size(); }
-	S32			getLength() const					{ return std::vector<Type>::size(); }
-	S32			getMax() const						{ return std::vector<Type>::capacity(); }
-
-	// MANIPULATE
-	S32         put(const Type &obj);					// add to end of array, returns index
-// 	Type*		reserve(S32 num);					// reserve a block of indices in advance
-	Type*		reserve_block(U32 num);			// reserve a block of indices in advance
-
-	S32			remove(S32 index);				// remove by index, no bounds checking
-	S32			removeObj(const Type &obj);				// remove by object
-	S32			removeLast();
-
-	void		operator+=(const LLDynamicArray<Type,BlockSize> &other);
-};
-
-//--------------------------------------------------------
-// LLDynamicArray implementation
-//--------------------------------------------------------
-
-template <typename Type,int BlockSize>
-inline S32 LLDynamicArray<Type,BlockSize>::find(const Type &obj) const
-{
-	typename std::vector<Type>::const_iterator iter = std::find(this->begin(), this->end(), obj);
-	if (iter != this->end())
-	{
-		return iter - this->begin();
-	}
-	return FAIL;
-}
-
-
-template <typename Type,int BlockSize>
-inline S32 LLDynamicArray<Type,BlockSize>::remove(S32 i)
-{
-	// This is a fast removal by swapping with the last element
-	S32 sz = this->size();
-	if (i < 0 || i >= sz)
-	{
-		return FAIL;
-	}
-	if (i < sz-1)
-	{
-		this->operator[](i) = this->back();
-	}
-	this->pop_back();
-	return i;
-}
-
-template <typename Type,int BlockSize>
-inline S32 LLDynamicArray<Type,BlockSize>::removeObj(const Type& obj)
-{
-	typename std::vector<Type>::iterator iter = std::find(this->begin(), this->end(), obj);
-	if (iter != this->end())
-	{
-		S32 res = iter - this->begin();
-		typename std::vector<Type>::iterator last = this->end(); 
-		--last;
-		*iter = *last;
-		this->pop_back();
-		return res;
-	}
-	return FAIL;
-}
-
-template <typename Type,int BlockSize>
-inline S32	LLDynamicArray<Type,BlockSize>::removeLast()
-{
-	if (!this->empty())
-	{
-		this->pop_back();
-		return OKAY;
-	}
-	return FAIL;
-}
-
-template <typename Type,int BlockSize>
-inline Type* LLDynamicArray<Type,BlockSize>::reserve_block(U32 num)
-{
-	U32 sz = this->size();
-	this->resize(sz+num);
-	return &(this->operator[](sz));
-}
-
-template <typename Type,int BlockSize>
-inline S32	LLDynamicArray<Type,BlockSize>::put(const Type &obj) 
-{
-	this->push_back(obj);
-	return this->size() - 1;
-}
-
-template <typename Type,int BlockSize>
-inline void LLDynamicArray<Type,BlockSize>::operator+=(const LLDynamicArray<Type,BlockSize> &other)
-{
-	insert(this->end(), other.begin(), other.end());
-}
-
-//--------------------------------------------------------
-// LLDynamicArrayIndexed declaration
-//--------------------------------------------------------
-
-template <typename Type, typename Key, int BlockSize = 32> 
-class LLDynamicArrayIndexed
-{
-public:
-	typedef typename std::vector<Type>::iterator iterator;
-	typedef typename std::vector<Type>::const_iterator const_iterator;
-	typedef typename std::vector<Type>::reverse_iterator reverse_iterator;
-	typedef typename std::vector<Type>::const_reverse_iterator const_reverse_iterator;
-	typedef typename std::vector<Type>::size_type size_type;
-protected:
-	std::vector<Type> mVector;
-	std::map<Key, U32> mIndexMap;
-	
-public:
-	LLDynamicArrayIndexed() { mVector.reserve(BlockSize); }
-	
-	iterator begin() { return mVector.begin(); }
-	const_iterator begin() const { return mVector.begin(); }
-	iterator end() { return mVector.end(); }
-	const_iterator end() const { return mVector.end(); }
-
-	reverse_iterator rbegin() { return mVector.rbegin(); }
-	const_reverse_iterator rbegin() const { return mVector.rbegin(); }
-	reverse_iterator rend() { return mVector.rend(); }
-	const_reverse_iterator rend() const { return mVector.rend(); }
-
-	void reset() { mVector.resize(0); mIndexMap.resize(0); }
-	bool empty() const { return mVector.empty(); }
-	size_type size() const { return mVector.size(); }
-	
-	Type& operator[](const Key& k)
-	{
-		typename std::map<Key, U32>::const_iterator iter = mIndexMap.find(k);
-		if (iter == mIndexMap.end())
-		{
-			U32 n = mVector.size();
-			mIndexMap[k] = n;
-			mVector.push_back(Type());
-			llassert(mVector.size() == mIndexMap.size());
-			return mVector[n];
-		}
-		else
-		{
-			return mVector[iter->second];
-		}
-	}
-
-	const_iterator find(const Key& k) const
-	{
-		typename std::map<Key, U32>::const_iterator iter = mIndexMap.find(k);
-		if(iter == mIndexMap.end())
-		{
-			return mVector.end();
-		}
-		else
-		{
-			return mVector.begin() + iter->second;
-		}
-	}
-};
-
-#endif
diff --git a/indra/llcommon/lldeleteutils.h b/indra/llcommon/lldeleteutils.h
deleted file mode 100644
index f250dc3028..0000000000
--- a/indra/llcommon/lldeleteutils.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/** 
- * @file lldeleteutils.h
- * @brief Utility functions to simplify some common pointer-munging idioms.
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-#ifndef LL_DELETE_UTILS_H
-#define LL_DELETE_UTILS_H
-
-// Simple utility functions to eventually replace the common 2-line
-// idiom scattered throughout the viewer codebase.  Note that where
-// possible we would rather be using smart pointers of some sort.
-
-template <class T>
-inline void deleteAndClear(T*& ptr)
-{
-	delete ptr;
-	ptr = NULL;
-}
-
-template <class T>
-inline void deleteAndClearArray(T*& array_ptr)
-{
-	delete[] array_ptr;
-	array_ptr = NULL;
-}
-
-#endif
diff --git a/indra/llcommon/lldepthstack.h b/indra/llcommon/lldepthstack.h
index ac435a30fa..b65840d342 100755
--- a/indra/llcommon/lldepthstack.h
+++ b/indra/llcommon/lldepthstack.h
@@ -41,8 +41,6 @@ public:
 	:	mCurrentDepth(0), mMaxDepth(0) 
 	{}
 
-	~LLDepthStack()	{}
-
 	void setDepth(U32 depth)
 	{
 		mMaxDepth = depth;
@@ -87,14 +85,7 @@ public:
 	{ 
 		return mStack.empty() ? NULL : mStack.back();
 	}
-	
-	void deleteAllData()
-	{ 
-		mCurrentDepth = 0;
-		std::for_each(mStack.begin(), mStack.end(), DeletePointer());
-		mStack.clear(); 
-	}
-	
+
 	void removeAllNodes()
 	{ 
 		mCurrentDepth = 0;
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 5b4be1ac80..6da9df4dce 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -96,7 +96,7 @@ namespace {
 			mFile.open(filename, llofstream::out | llofstream::app);
 			if (!mFile)
 			{
-				llinfos << "Error setting log file to " << filename << llendl;
+				LL_INFOS() << "Error setting log file to " << filename << LL_ENDL;
 			}
 		}
 		
@@ -331,7 +331,7 @@ namespace
 		}
 		
 		LLError::configure(configuration);
-		llinfos << "logging reconfigured from " << filename() << llendl;
+		LL_INFOS() << "logging reconfigured from " << filename() << LL_ENDL;
 		return true;
 	}
 
@@ -495,14 +495,44 @@ namespace LLError
 					int line,
 					const std::type_info& class_info, 
 					const char* function, 
+					bool printOnce,
 					const char* broadTag, 
-					const char* narrowTag,
-					bool printOnce)
-		: mLevel(level), mFile(file), mLine(line),
-		  mClassInfo(class_info), mFunction(function),
-		  mCached(false), mShouldLog(false), 
-		  mBroadTag(broadTag), mNarrowTag(narrowTag), mPrintOnce(printOnce)
-		{ }
+					const char* narrowTag)
+	:	mLevel(level), 
+		mFile(file), 
+		mLine(line),
+		mClassInfo(class_info), 
+		mFunction(function),
+		mCached(false), 
+		mShouldLog(false), 
+		mPrintOnce(printOnce),
+		mBroadTag(broadTag), 
+		mNarrowTag(narrowTag)
+	{}
+
+	CallSite::CallSite(ELevel level,
+		const char* file,
+		int line,
+		const std::type_info& class_info, 
+		const char* function, 
+		bool printOnce,
+		const char* broadTag, 
+		const char* narrowTag,
+		const char*,
+		...)
+	:	mLevel(level), 
+		mFile(file), 
+		mLine(line),
+		mClassInfo(class_info), 
+		mFunction(function),
+		mCached(false), 
+		mShouldLog(false), 
+		mPrintOnce(printOnce),
+		mBroadTag(broadTag), 
+		mNarrowTag(narrowTag)
+	{
+		LL_ERRS() << "No support for more than 2 logging tags" << LL_ENDL;
+	}
 
 
 	void CallSite::invalidate()
@@ -677,7 +707,7 @@ namespace LLError
 		LevelMap::const_iterator i = level_names.find(name);
 		if (i == level_names.end())
 		{
-			llwarns << "unrecognized logging level: '" << name << "'" << llendl;
+			LL_WARNS() << "unrecognized logging level: '" << name << "'" << LL_ENDL;
 			return LLError::LEVEL_INFO;
 		}
 		
@@ -741,6 +771,12 @@ namespace LLError
 		return false; 
 	}
 
+	// virtual
+	bool Recorder::wantsTags()
+	{
+		return false;
+	}
+
 	void addRecorder(Recorder* recorder)
 	{
 		if (recorder == NULL)
@@ -817,11 +853,14 @@ namespace LLError
 
 namespace
 {
-	void writeToRecorders(LLError::ELevel level, const std::string& message)
+	void writeToRecorders(const LLError::CallSite& site, const std::string& message)
 	{
+		LLError::ELevel level = site.mLevel;
 		LLError::Settings& s = LLError::Settings::get();
 	
 		std::string messageWithTime;
+		std::string messageWithTags;
+		std::string messageWithTagsAndTime;
 		
 		for (Recorders::const_iterator i = s.recorders.begin();
 			i != s.recorders.end();
@@ -829,18 +868,47 @@ namespace
 		{
 			LLError::Recorder* r = *i;
 			
-			if (r->wantsTime()  &&  s.timeFunction != NULL)
+			if (r->wantsTime() && s.timeFunction != NULL)
 			{
-				if (messageWithTime.empty())
+				if (r->wantsTags())
 				{
-					messageWithTime = s.timeFunction() + " " + message;
+					if (messageWithTagsAndTime.empty())
+					{
+						messageWithTagsAndTime = s.timeFunction() + " " 
+												+ (site.mBroadTag ? (std::string("#") + std::string(site.mBroadTag) + " ") : std::string())  
+												+ (site.mNarrowTag ? (std::string("#") + std::string(site.mNarrowTag) + " ") : std::string()) 
+												+ message;
+					}
+
+					r->recordMessage(level, messageWithTagsAndTime);
+				}
+				else
+				{
+					if (messageWithTime.empty())
+					{
+						messageWithTime = s.timeFunction() + " " + message;
+					}
+
+					r->recordMessage(level, messageWithTime);
 				}
-				
-				r->recordMessage(level, messageWithTime);
 			}
 			else
 			{
-				r->recordMessage(level, message);
+				if (r->wantsTags())
+				{
+					if (messageWithTags.empty())
+					{
+						messageWithTags = (site.mBroadTag ? (std::string("#") + std::string(site.mBroadTag) + " ") : std::string())  
+										+ (site.mNarrowTag ? (std::string("#") + std::string(site.mNarrowTag) + " ") : std::string()) 
+										+ message;
+					}
+
+					r->recordMessage(level, messageWithTags);
+				}
+				else
+				{
+					r->recordMessage(level, message);				
+				}
 			}
 		}
 	}
@@ -1017,10 +1085,11 @@ namespace LLError
 	   else
 	   {
 		   strncpy(message, out->str().c_str(), 127);
-		   message[127] = '\0' ;
+		   message[127] = '\0';
 	   }
 	   
 	   Globals& g = Globals::get();
+
        if (out == &g.messageStream)
        {
            g.messageStream.clear();
@@ -1031,7 +1100,7 @@ namespace LLError
        {
            delete out;
        }
-	   return ;
+	   return;
     }
 
 	void Log::flush(std::ostringstream* out, const CallSite& site)
@@ -1063,7 +1132,7 @@ namespace LLError
 			fatalMessage << abbreviateFile(site.mFile)
 						<< "(" << site.mLine << ") : error";
 			
-			writeToRecorders(site.mLevel, fatalMessage.str());
+			writeToRecorders(site, fatalMessage.str());
 		}
 		
 		
@@ -1125,7 +1194,7 @@ namespace LLError
 		prefix << message;
 		message = prefix.str();
 		
-		writeToRecorders(site.mLevel, message);
+		writeToRecorders(site, message);
 		
 		if (site.mLevel == LEVEL_ERROR  &&  s.crashFunction)
 		{
@@ -1164,7 +1233,7 @@ namespace LLError
 	{
 		std::string::size_type i = 0;
 		std::string::size_type len = s.length();
-		for ( ; i < len; i++ )
+		for (; i < len; i++ )
 		{
 			if (s[i] == old)
 			{
@@ -1235,8 +1304,8 @@ namespace LLError
 
 namespace LLError
 {     
-	char** LLCallStacks::sBuffer = NULL ;
-	S32    LLCallStacks::sIndex  = 0 ;
+	char** LLCallStacks::sBuffer = NULL;
+	S32    LLCallStacks::sIndex  = 0;
 
 #define SINGLE_THREADED 1
 
@@ -1312,34 +1381,34 @@ namespace LLError
 
 	   if(!sBuffer)
 	   {
-		   sBuffer = new char*[512] ;
-		   sBuffer[0] = new char[512 * 128] ;
-		   for(S32 i = 1 ; i < 512 ; i++)
+		   sBuffer = new char*[512];
+		   sBuffer[0] = new char[512 * 128];
+		   for(S32 i = 1; i < 512; i++)
 		   {
-			   sBuffer[i] = sBuffer[i-1] + 128 ;
+			   sBuffer[i] = sBuffer[i-1] + 128;
 		   }
-		   sIndex = 0 ;
+		   sIndex = 0;
 	   }
 
 	   if(sIndex > 511)
 	   {
-		   clear() ;
+		   clear();
 	   }
 
-	   strcpy(sBuffer[sIndex], function) ;
-	   sprintf(sBuffer[sIndex] + strlen(function), " line: %d ", line) ;
-	   sIndex++ ;
+	   strcpy(sBuffer[sIndex], function);
+	   sprintf(sBuffer[sIndex] + strlen(function), " line: %d ", line);
+	   sIndex++;
 
-	   return ;
+	   return;
    }
 
 	//static
    std::ostringstream* LLCallStacks::insert(const char* function, const int line)
    {
        std::ostringstream* _out = LLError::Log::out();
-	   *_out << function << " line " << line << " " ;
+	   *_out << function << " line " << line << " ";
              
-	   return _out ;
+	   return _out;
    }
 
    //static
@@ -1353,21 +1422,21 @@ namespace LLError
 
 	   if(!sBuffer)
 	   {
-		   sBuffer = new char*[512] ;
-		   sBuffer[0] = new char[512 * 128] ;
-		   for(S32 i = 1 ; i < 512 ; i++)
+		   sBuffer = new char*[512];
+		   sBuffer[0] = new char[512 * 128];
+		   for(S32 i = 1; i < 512; i++)
 		   {
-			   sBuffer[i] = sBuffer[i-1] + 128 ;
+			   sBuffer[i] = sBuffer[i-1] + 128;
 		   }
-		   sIndex = 0 ;
+		   sIndex = 0;
 	   }
 
 	   if(sIndex > 511)
 	   {
-		   clear() ;
+		   clear();
 	   }
 
-	   LLError::Log::flush(_out, sBuffer[sIndex++]) ;	   
+	   LLError::Log::flush(_out, sBuffer[sIndex++]);
    }
 
    //static
@@ -1381,27 +1450,27 @@ namespace LLError
 
        if(sIndex > 0)
        {
-           llinfos << " ************* PRINT OUT LL CALL STACKS ************* " << llendl ;
+           LL_INFOS() << " ************* PRINT OUT LL CALL STACKS ************* " << LL_ENDL;
            while(sIndex > 0)
            {                  
-			   sIndex-- ;
-               llinfos << sBuffer[sIndex] << llendl ;
+			   sIndex--;
+               LL_INFOS() << sBuffer[sIndex] << LL_ENDL;
            }
-           llinfos << " *************** END OF LL CALL STACKS *************** " << llendl ;
+           LL_INFOS() << " *************** END OF LL CALL STACKS *************** " << LL_ENDL;
        }
 
 	   if(sBuffer)
 	   {
-		   delete[] sBuffer[0] ;
-		   delete[] sBuffer ;
-		   sBuffer = NULL ;
+		   delete[] sBuffer[0];
+		   delete[] sBuffer;
+		   sBuffer = NULL;
 	   }
    }
 
    //static
    void LLCallStacks::clear()
    {
-       sIndex = 0 ;
+       sIndex = 0;
    }
 
 #if LL_WINDOWS
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index ceff40e900..d7dc38a4c6 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -31,9 +31,66 @@
 #include <sstream>
 #include <typeinfo>
 
-#include "llerrorlegacy.h"
 #include "stdtypes.h"
 
+#include "llpreprocessor.h"
+#include <boost/static_assert.hpp>
+
+const int LL_ERR_NOERR = 0;
+
+// Define one of these for different error levels in release...
+// #define RELEASE_SHOW_DEBUG // Define this if you want your release builds to show lldebug output.
+#define RELEASE_SHOW_INFO // Define this if you want your release builds to show llinfo output
+#define RELEASE_SHOW_WARN // Define this if you want your release builds to show llwarn output.
+
+#ifdef _DEBUG
+#define SHOW_DEBUG
+#define SHOW_WARN
+#define SHOW_INFO
+#define SHOW_ASSERT
+#else // _DEBUG
+
+#ifdef LL_RELEASE_WITH_DEBUG_INFO
+#define SHOW_ASSERT
+#endif // LL_RELEASE_WITH_DEBUG_INFO
+
+#ifdef RELEASE_SHOW_DEBUG
+#define SHOW_DEBUG
+#endif
+
+#ifdef RELEASE_SHOW_WARN
+#define SHOW_WARN
+#endif
+
+#ifdef RELEASE_SHOW_INFO
+#define SHOW_INFO
+#endif
+
+#ifdef RELEASE_SHOW_ASSERT
+#define SHOW_ASSERT
+#endif
+
+#endif // !_DEBUG
+
+#define llassert_always(func)	if (LL_UNLIKELY(!(func))) LL_ERRS() << "ASSERT (" << #func << ")" << LL_ENDL;
+
+#ifdef SHOW_ASSERT
+#define llassert(func)			llassert_always(func)
+#define llverify(func)			llassert_always(func)
+#else
+#define llassert(func)
+#define llverify(func)			do {if (func) {}} while(0)
+#endif
+
+#ifdef LL_WINDOWS
+#define LL_STATIC_ASSERT(func, msg) static_assert(func, msg)
+#define LL_BAD_TEMPLATE_INSTANTIATION(type, msg) static_assert(false, msg)
+#else
+#define LL_STATIC_ASSERT(func, msg) BOOST_STATIC_ASSERT(func)
+#define LL_BAD_TEMPLATE_INSTANTIATION(type, msg) BOOST_STATIC_ASSERT(sizeof(type) != 0 && false);
+#endif
+
+
 /** Error Logging Facility
 
 	Information for most users:
@@ -121,26 +178,25 @@ namespace LLError
 		They are not intended for general use.
 	*/
 	
-	class CallSite;
+	struct CallSite;
 	
 	class LL_COMMON_API Log
 	{
 	public:
 		static bool shouldLog(CallSite&);
 		static std::ostringstream* out();
-		static void flush(std::ostringstream* out, char* message)  ;
+		static void flush(std::ostringstream* out, char* message);
 		static void flush(std::ostringstream*, const CallSite&);
 	};
 	
-	class LL_COMMON_API CallSite
+	struct LL_COMMON_API CallSite
 	{
 		// Represents a specific place in the code where a message is logged
 		// This is public because it is used by the macros below.  It is not
 		// intended for public use.
-	public:
 		CallSite(ELevel, const char* file, int line,
-				const std::type_info& class_info, const char* function, const char* broadTag, const char* narrowTag, bool printOnce);
-						
+				const std::type_info& class_info, const char* function, bool printOnce, const char* broadTag = NULL, const char* narrowTag = NULL );
+
 #ifdef LL_LIBRARY_INCLUDE
 		bool shouldLog();
 #else // LL_LIBRARY_INCLUDE
@@ -151,7 +207,6 @@ namespace LLError
 		
 		void invalidate();
 		
-	private:
 		// these describe the call site and never change
 		const ELevel			mLevel;
 		const char* const		mFile;
@@ -167,6 +222,11 @@ namespace LLError
 		bool mShouldLog;
 		
 		friend class Log;
+
+	private:
+		// 3 or more tags not currently supported
+		CallSite(ELevel, const char* file, int line,
+			const std::type_info& class_info, const char* function, bool printOnce, const char* broadTag, const char* narrowTag, const char*, ...);
 	};
 	
 	
@@ -237,78 +297,64 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 	// Outside a class declaration, or in class without LOG_CLASS(), this
 	// typedef causes the messages to not be associated with any class.
 
+/////////////////////////////////
+// Error Logging Macros
+// See top of file for common usage.	
+/////////////////////////////////
 
+#define lllog(level, once, ...)																	   \
+	do {                                                                                           \
+		static LLError::CallSite _site(                                                            \
+			level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, __VA_ARGS__ );\
+		if (LL_UNLIKELY(_site.shouldLog()))			                                               \
+		{                                                                                          \
+			std::ostringstream* _out = LLError::Log::out();                                        \
+			(*_out)
 
+//Use this construct if you need to do computation in the middle of a
+//message:
+//	
+//	LL_INFOS("AgentGesture") << "the agent " << agend_id;
+//	switch (f)
+//	{
+//		case FOP_SHRUGS:	LL_CONT << "shrugs";				break;
+//		case FOP_TAPS:		LL_CONT << "points at " << who;	break;
+//		case FOP_SAYS:		LL_CONT << "says " << message;	break;
+//	}
+//	LL_CONT << " for " << t << " seconds" << LL_ENDL;
+//	
+//Such computation is done iff the message will be logged.
+#define LL_CONT	(*_out)
 
+#define LL_NEWLINE '\n'
 
-/*
-	Error Logging Macros
-	See top of file for common usage.	
-*/
-
-#define lllog(level, broadTag, narrowTag, once) \
-	do { \
-		static LLError::CallSite _site( \
-			level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, broadTag, narrowTag, once);\
-		if (LL_UNLIKELY(_site.shouldLog()))			\
-		{ \
-			std::ostringstream* _out = LLError::Log::out(); \
-			(*_out)
-
-// DEPRECATED: Don't call directly, use LL_ENDL instead, which actually looks like a macro
-#define llendl \
-			LLError::End(); \
+#define LL_ENDL                               \
+			LLError::End();                   \
 			LLError::Log::flush(_out, _site); \
-		} \
+		}                                     \
 	} while(0)
 
-// DEPRECATED: Use the new macros that allow tags and *look* like macros.
-#define lldebugs	lllog(LLError::LEVEL_DEBUG, NULL, NULL, false)
-#define llinfos		lllog(LLError::LEVEL_INFO, NULL, NULL, false)
-#define llwarns		lllog(LLError::LEVEL_WARN, NULL, NULL, false)
-#define llerrs		lllog(LLError::LEVEL_ERROR, NULL, NULL, false)
-#define llcont		(*_out)
-
 // NEW Macros for debugging, allow the passing of a string tag
 
-// One Tag
-#define LL_DEBUGS(broadTag)	lllog(LLError::LEVEL_DEBUG, broadTag, NULL, false)
-#define LL_INFOS(broadTag)	lllog(LLError::LEVEL_INFO, broadTag, NULL, false)
-#define LL_WARNS(broadTag)	lllog(LLError::LEVEL_WARN, broadTag, NULL, false)
-#define LL_ERRS(broadTag)	lllog(LLError::LEVEL_ERROR, broadTag, NULL, false)
-// Two Tags
-#define LL_DEBUGS2(broadTag, narrowTag)	lllog(LLError::LEVEL_DEBUG, broadTag, narrowTag, false)
-#define LL_INFOS2(broadTag, narrowTag)	lllog(LLError::LEVEL_INFO, broadTag, narrowTag, false)
-#define LL_WARNS2(broadTag, narrowTag)	lllog(LLError::LEVEL_WARN, broadTag, narrowTag, false)
-#define LL_ERRS2(broadTag, narrowTag)	lllog(LLError::LEVEL_ERROR, broadTag, narrowTag, false)
+// Pass comma separated list of tags (currently only supports up to 0, 1, or 2)
+#define LL_DEBUGS(...)	lllog(LLError::LEVEL_DEBUG, false, __VA_ARGS__)
+#define LL_INFOS(...)	lllog(LLError::LEVEL_INFO, false, __VA_ARGS__)
+#define LL_WARNS(...)	lllog(LLError::LEVEL_WARN, false, __VA_ARGS__)
+#define LL_ERRS(...)	lllog(LLError::LEVEL_ERROR, false, __VA_ARGS__)
 
 // Only print the log message once (good for warnings or infos that would otherwise
 // spam the log file over and over, such as tighter loops).
-#define LL_DEBUGS_ONCE(broadTag)	lllog(LLError::LEVEL_DEBUG, broadTag, NULL, true)
-#define LL_INFOS_ONCE(broadTag)	lllog(LLError::LEVEL_INFO, broadTag, NULL, true)
-#define LL_WARNS_ONCE(broadTag)	lllog(LLError::LEVEL_WARN, broadTag, NULL, true)
-#define LL_DEBUGS2_ONCE(broadTag, narrowTag)	lllog(LLError::LEVEL_DEBUG, broadTag, narrowTag, true)
-#define LL_INFOS2_ONCE(broadTag, narrowTag)	lllog(LLError::LEVEL_INFO, broadTag, narrowTag, true)
-#define LL_WARNS2_ONCE(broadTag, narrowTag)	lllog(LLError::LEVEL_WARN, broadTag, narrowTag, true)
-
-#define LL_ENDL llendl
-#define LL_CONT	(*_out)
+#define LL_DEBUGS_ONCE(...)	lllog(LLError::LEVEL_DEBUG, true, __VA_ARGS__)
+#define LL_INFOS_ONCE(...)	lllog(LLError::LEVEL_INFO, true, __VA_ARGS__)
+#define LL_WARNS_ONCE(...)	lllog(LLError::LEVEL_WARN, true, __VA_ARGS__)
 
-	/*
-		Use this construct if you need to do computation in the middle of a
-		message:
-		
-			LL_INFOS("AgentGesture") << "the agent " << agend_id;
-			switch (f)
-			{
-				case FOP_SHRUGS:	LL_CONT << "shrugs";				break;
-				case FOP_TAPS:		LL_CONT << "points at " << who;	break;
-				case FOP_SAYS:		LL_CONT << "says " << message;	break;
-			}
-			LL_CONT << " for " << t << " seconds" << LL_ENDL;
-		
-		Such computation is done iff the message will be logged.
-	*/
 
+// DEPRECATED: Use the new macros that allow tags and *look* like macros.
+#define lldebugs	LL_DEBUGS()
+#define llinfos		LL_INFOS()
+#define llwarns		LL_WARNS()
+#define llerrs		LL_ERRS()
+#define llcont		LL_CONT
+#define llendl		LL_ENDL 
 
 #endif // LL_LLERROR_H
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index 480654b1a2..7c9df57115 100755
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -144,6 +144,10 @@ namespace LLError
 		virtual bool wantsTime(); // default returns false
 			// override and return true if the recorder wants the time string
 			// included in the text of the message
+
+		virtual bool wantsTags(); // default returns false
+			// override ands return true if the recorder wants the tags included
+			// in the text of the message
 	};
 
 	/**
diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h
index 50c95339e4..31dd207008 100755
--- a/indra/llcommon/llerrorlegacy.h
+++ b/indra/llcommon/llerrorlegacy.h
@@ -28,100 +28,5 @@
 #ifndef LL_LLERRORLEGACY_H
 #define LL_LLERRORLEGACY_H
 
-#include "llpreprocessor.h"
-#include <boost/static_assert.hpp>
-
-/*
-	LEGACY -- DO NOT USE THIS STUFF ANYMORE
-*/
-
-// Specific error codes
-const int LL_ERR_NOERR = 0;
-const int LL_ERR_ASSET_REQUEST_FAILED = -1;
-//const int LL_ERR_ASSET_REQUEST_INVALID = -2;
-const int LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3;
-const int LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4;
-const int LL_ERR_INSUFFICIENT_PERMISSIONS = -5;
-const int LL_ERR_EOF = -39;
-const int LL_ERR_CANNOT_OPEN_FILE = -42;
-const int LL_ERR_FILE_NOT_FOUND = -43;
-const int LL_ERR_FILE_EMPTY     = -44;
-const int LL_ERR_TCP_TIMEOUT    = -23016;
-const int LL_ERR_CIRCUIT_GONE   = -23017;
-const int LL_ERR_PRICE_MISMATCH = -23018;
-
-
-
-// Define one of these for different error levels in release...
-// #define RELEASE_SHOW_DEBUG // Define this if you want your release builds to show lldebug output.
-#define RELEASE_SHOW_INFO // Define this if you want your release builds to show llinfo output
-#define RELEASE_SHOW_WARN // Define this if you want your release builds to show llwarn output.
-
-
-//////////////////////////////////////////
-//
-//  Implementation - ignore
-//
-//
-#ifdef _DEBUG
-#define SHOW_DEBUG
-#define SHOW_WARN
-#define SHOW_INFO
-#define SHOW_ASSERT
-#else // _DEBUG
-
-#ifdef LL_RELEASE_WITH_DEBUG_INFO
-#define SHOW_ASSERT
-#endif // LL_RELEASE_WITH_DEBUG_INFO
-
-#ifdef RELEASE_SHOW_DEBUG
-#define SHOW_DEBUG
-#endif
-
-#ifdef RELEASE_SHOW_WARN
-#define SHOW_WARN
-#endif
-
-#ifdef RELEASE_SHOW_INFO
-#define SHOW_INFO
-#endif
-
-#ifdef RELEASE_SHOW_ASSERT
-#define SHOW_ASSERT
-#endif
-
-#endif // _DEBUG
-
-
-
-#define lldebugst(type)			lldebugs
-#define llendflush				llendl
-
-
-#define llerror(msg, num)		llerrs << "Error # " << num << ": " << msg << llendl;
-
-#define llwarning(msg, num)		llwarns << "Warning # " << num << ": " << msg << llendl;
-
-#define llassert_always(func)	if (LL_UNLIKELY(!(func))) llerrs << "ASSERT (" << #func << ")" << llendl;
-
-#ifdef SHOW_ASSERT
-#define llassert(func)			llassert_always(func)
-#define llverify(func)			llassert_always(func)
-#else
-#define llassert(func)
-#define llverify(func)			do {if (func) {}} while(0)
-#endif
-
-#ifdef LL_WINDOWS
-#define LL_STATIC_ASSERT(func, msg) static_assert(func, msg)
-#define LL_BAD_TEMPLATE_INSTANTIATION(type, msg) static_assert(false, msg)
-#else
-#define LL_STATIC_ASSERT(func, msg) BOOST_STATIC_ASSERT(func)
-#define LL_BAD_TEMPLATE_INSTANTIATION(type, msg) BOOST_STATIC_ASSERT(sizeof(type) != 0 && false);
-#endif
-
-// handy compile-time assert - enforce those template parameters! 
-#define cassert(expn) typedef char __C_ASSERT__[(expn)?1:-1]   /* Flawfinder: ignore */
-	//XXX: used in two places in llcommon/llskipmap.h
 
 #endif // LL_LLERRORLEGACY_H
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index 65b0fef354..0cbd1da32d 100755
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -61,7 +61,7 @@
 #include "llsd.h"
 #include "llsingleton.h"
 #include "lldependencies.h"
-#include "ll_template_cast.h"
+#include "llstl.h"
 
 /*==========================================================================*|
 // override this to allow binding free functions with more parameters
diff --git a/indra/llcommon/llextendedstatus.h b/indra/llcommon/llextendedstatus.h
deleted file mode 100755
index 8ce173d1ff..0000000000
--- a/indra/llcommon/llextendedstatus.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/** 
- * @file llextendedstatus.h
- * @date   August 2007
- * @brief extended status codes for curl/vfs/resident asset storage and delivery
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLEXTENDEDSTATUS_H
-#define LL_LLEXTENDEDSTATUS_H
-
-
-typedef S32 LLExtStat;
-
-
-// Status provider groups - Top bits indicate which status type it is
-// Zero is common status code (next section)
-const LLExtStat LL_EXSTAT_CURL_RESULT	= 1L<<30; // serviced by curl - use 1L if we really implement the below
-const LLExtStat LL_EXSTAT_RES_RESULT	= 2L<<30; // serviced by resident copy
-const LLExtStat LL_EXSTAT_VFS_RESULT	= 3L<<30; // serviced by vfs
-
-
-// Common Status Codes
-//
-const LLExtStat LL_EXSTAT_NONE				= 0x00000; // No extra info here - sorry!
-const LLExtStat LL_EXSTAT_NULL_UUID			= 0x10001; // null asset ID
-const LLExtStat LL_EXSTAT_NO_UPSTREAM		= 0x10002; // attempt to upload without a valid upstream method/provider
-const LLExtStat LL_EXSTAT_REQUEST_DROPPED	= 0x10003; // request was dropped unserviced
-const LLExtStat LL_EXSTAT_NONEXISTENT_FILE	= 0x10004; // trying to upload a file that doesn't exist
-const LLExtStat LL_EXSTAT_BLOCKED_FILE		= 0x10005; // trying to upload a file that we can't open
-
-
-// curl status codes:
-//
-// Mask off LL_EXSTAT_CURL_RESULT for original result and
-// see: libraries/include/curl/curl.h
-
-
-// Memory-Resident status codes:
-// None at present
-
-
-// VFS status codes:
-const LLExtStat LL_EXSTAT_VFS_CACHED	= LL_EXSTAT_VFS_RESULT | 0x0001;
-const LLExtStat LL_EXSTAT_VFS_CORRUPT	= LL_EXSTAT_VFS_RESULT | 0x0002;
-
-
-#endif // LL_LLEXTENDEDSTATUS_H
diff --git a/indra/llcommon/llfoldertype.cpp b/indra/llcommon/llfoldertype.cpp
deleted file mode 100755
index f6d0f5bce8..0000000000
--- a/indra/llcommon/llfoldertype.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/** 
- * @file llfoldertype.cpp
- * @brief Implementatino of LLFolderType functionality.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llfoldertype.h"
-#include "lldictionary.h"
-#include "llmemory.h"
-#include "llsingleton.h"
-
-///----------------------------------------------------------------------------
-/// Class LLFolderType
-///----------------------------------------------------------------------------
-struct FolderEntry : public LLDictionaryEntry
-{
-	FolderEntry(const std::string &type_name, // 8 character limit!
-				bool is_protected) // can the viewer change categories of this type?
-		:
-	LLDictionaryEntry(type_name),
-	mIsProtected(is_protected)
-	{
-		llassert(type_name.length() <= 8);
-	}
-
-	const bool mIsProtected;
-};
-
-class LLFolderDictionary : public LLSingleton<LLFolderDictionary>,
-						   public LLDictionary<LLFolderType::EType, FolderEntry>
-{
-public:
-	LLFolderDictionary();
-protected:
-	virtual LLFolderType::EType notFound() const
-	{
-		return LLFolderType::FT_NONE;
-	}
-};
-
-LLFolderDictionary::LLFolderDictionary()
-{
-	//       													    TYPE NAME	PROTECTED
-	//      													   |-----------|---------|
-	addEntry(LLFolderType::FT_TEXTURE, 				new FolderEntry("texture",	TRUE));
-	addEntry(LLFolderType::FT_SOUND, 				new FolderEntry("sound",	TRUE));
-	addEntry(LLFolderType::FT_CALLINGCARD, 			new FolderEntry("callcard",	TRUE));
-	addEntry(LLFolderType::FT_LANDMARK, 			new FolderEntry("landmark",	TRUE));
-	addEntry(LLFolderType::FT_CLOTHING, 			new FolderEntry("clothing",	TRUE));
-	addEntry(LLFolderType::FT_OBJECT, 				new FolderEntry("object",	TRUE));
-	addEntry(LLFolderType::FT_NOTECARD, 			new FolderEntry("notecard",	TRUE));
-	addEntry(LLFolderType::FT_ROOT_INVENTORY, 		new FolderEntry("root_inv",	TRUE));
-	addEntry(LLFolderType::FT_LSL_TEXT, 			new FolderEntry("lsltext",	TRUE));
-	addEntry(LLFolderType::FT_BODYPART, 			new FolderEntry("bodypart",	TRUE));
-	addEntry(LLFolderType::FT_TRASH, 				new FolderEntry("trash",	TRUE));
-	addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, 	new FolderEntry("snapshot", TRUE));
-	addEntry(LLFolderType::FT_LOST_AND_FOUND, 		new FolderEntry("lstndfnd",	TRUE));
-	addEntry(LLFolderType::FT_ANIMATION, 			new FolderEntry("animatn",	TRUE));
-	addEntry(LLFolderType::FT_GESTURE, 				new FolderEntry("gesture",	TRUE));
-	addEntry(LLFolderType::FT_FAVORITE, 			new FolderEntry("favorite",	TRUE));
-	
-	for (S32 ensemble_num = S32(LLFolderType::FT_ENSEMBLE_START); ensemble_num <= S32(LLFolderType::FT_ENSEMBLE_END); ensemble_num++)
-	{
-		addEntry(LLFolderType::EType(ensemble_num), new FolderEntry("ensemble", FALSE)); 
-	}
-
-	addEntry(LLFolderType::FT_CURRENT_OUTFIT, 		new FolderEntry("current",	TRUE));
-	addEntry(LLFolderType::FT_OUTFIT, 				new FolderEntry("outfit",	FALSE));
-	addEntry(LLFolderType::FT_MY_OUTFITS, 			new FolderEntry("my_otfts",	TRUE));
-
-	addEntry(LLFolderType::FT_MESH, 				new FolderEntry("mesh",	TRUE));
-
-	addEntry(LLFolderType::FT_INBOX, 				new FolderEntry("inbox",	TRUE));
-	addEntry(LLFolderType::FT_OUTBOX, 				new FolderEntry("outbox",	TRUE));
-	addEntry(LLFolderType::FT_BASIC_ROOT,			new FolderEntry("basic_rt", TRUE));
-		 
-	addEntry(LLFolderType::FT_NONE, 				new FolderEntry("-1",		FALSE));
-};
-
-// static
-LLFolderType::EType LLFolderType::lookup(const std::string& name)
-{
-	return LLFolderDictionary::getInstance()->lookup(name);
-}
-
-// static
-const std::string &LLFolderType::lookup(LLFolderType::EType folder_type)
-{
-	const FolderEntry *entry = LLFolderDictionary::getInstance()->lookup(folder_type);
-	if (entry)
-	{
-		return entry->mName;
-	}
-	else
-	{
-		return badLookup();
-	}
-}
-
-// static
-// Only ensembles and plain folders aren't protected.  "Protected" means
-// you can't change certain properties such as their type.
-bool LLFolderType::lookupIsProtectedType(EType folder_type)
-{
-	const LLFolderDictionary *dict = LLFolderDictionary::getInstance();
-	const FolderEntry *entry = dict->lookup(folder_type);
-	if (entry)
-	{
-		return entry->mIsProtected;
-	}
-	return true;
-}
-
-// static
-bool LLFolderType::lookupIsEnsembleType(EType folder_type)
-{
-	return (folder_type >= FT_ENSEMBLE_START &&
-			folder_type <= FT_ENSEMBLE_END);
-}
-
-// static
-LLAssetType::EType LLFolderType::folderTypeToAssetType(LLFolderType::EType folder_type)
-{
-	if (LLAssetType::lookup(LLAssetType::EType(folder_type)) == LLAssetType::badLookup())
-	{
-		llwarns << "Converting to unknown asset type " << folder_type << llendl;
-	}
-	return (LLAssetType::EType)folder_type;
-}
-
-// static
-LLFolderType::EType LLFolderType::assetTypeToFolderType(LLAssetType::EType asset_type)
-{
-	if (LLFolderType::lookup(LLFolderType::EType(asset_type)) == LLFolderType::badLookup())
-	{
-		llwarns << "Converting to unknown folder type " << asset_type << llendl;
-	}
-	return (LLFolderType::EType)asset_type;
-}
-
-// static
-const std::string &LLFolderType::badLookup()
-{
-	static const std::string sBadLookup = "llfoldertype_bad_lookup";
-	return sBadLookup;
-}
diff --git a/indra/llcommon/llfoldertype.h b/indra/llcommon/llfoldertype.h
deleted file mode 100755
index a0c847914f..0000000000
--- a/indra/llcommon/llfoldertype.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/** 
- * @file llfoldertype.h
- * @brief Declaration of LLFolderType.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLFOLDERTYPE_H
-#define LL_LLFOLDERTYPE_H
-
-#include <string>
-#include "llassettype.h"
-
-// This class handles folder types (similar to assettype, except for folders)
-// and operations on those.
-class LL_COMMON_API LLFolderType
-{
-public:
-	// ! BACKWARDS COMPATIBILITY ! Folder type enums must match asset type enums.
-	enum EType
-	{
-		FT_TEXTURE = 0,
-
-		FT_SOUND = 1, 
-
-		FT_CALLINGCARD = 2,
-
-		FT_LANDMARK = 3,
-
-		FT_CLOTHING = 5,
-
-		FT_OBJECT = 6,
-
-		FT_NOTECARD = 7,
-
-		FT_ROOT_INVENTORY = 8,
-			// We'd really like to change this to 9 since AT_CATEGORY is 8,
-			// but "My Inventory" has been type 8 for a long time.
-
-		FT_LSL_TEXT = 10,
-
-		FT_BODYPART = 13,
-
-		FT_TRASH = 14,
-
-		FT_SNAPSHOT_CATEGORY = 15,
-
-		FT_LOST_AND_FOUND = 16,
-
-		FT_ANIMATION = 20,
-
-		FT_GESTURE = 21,
-
-		FT_FAVORITE = 23,
-
-		FT_ENSEMBLE_START = 26,
-		FT_ENSEMBLE_END = 45,
-			// This range is reserved for special clothing folder types.
-
-		FT_CURRENT_OUTFIT = 46,
-		FT_OUTFIT = 47,
-		FT_MY_OUTFITS = 48,
-		
-		FT_MESH = 49,
-
-		FT_INBOX = 50,
-		FT_OUTBOX = 51,
-
-		FT_BASIC_ROOT = 52,
-
-		FT_COUNT,
-
-		FT_NONE = -1
-	};
-
-	static EType 				lookup(const std::string& type_name);
-	static const std::string&	lookup(EType folder_type);
-
-	static bool 				lookupIsProtectedType(EType folder_type);
-	static bool 				lookupIsEnsembleType(EType folder_type);
-
-	static LLAssetType::EType	folderTypeToAssetType(LLFolderType::EType folder_type);
-	static LLFolderType::EType	assetTypeToFolderType(LLAssetType::EType asset_type);
-
-	static const std::string&	badLookup(); // error string when a lookup fails
-
-protected:
-	LLFolderType() {}
-	~LLFolderType() {}
-};
-
-#endif // LL_LLFOLDERTYPE_H
diff --git a/indra/llcommon/llframetimer.h b/indra/llcommon/llframetimer.h
index 45754f3785..7f61861072 100755
--- a/indra/llcommon/llframetimer.h
+++ b/indra/llcommon/llframetimer.h
@@ -35,7 +35,6 @@
  */
 
 #include "lltimer.h"
-#include "timing.h"
 
 class LL_COMMON_API LLFrameTimer 
 {
diff --git a/indra/llcommon/llindexedvector.h b/indra/llcommon/llindexedvector.h
new file mode 100755
index 0000000000..68c3821802
--- /dev/null
+++ b/indra/llcommon/llindexedvector.h
@@ -0,0 +1,100 @@
+/** 
+ * @file lldarray.h
+ * @brief Wrapped std::vector for backward compatibility.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLDARRAY_H
+#define LL_LLDARRAY_H
+
+#include "llerror.h"
+
+#include <vector>
+#include <map>
+
+//--------------------------------------------------------
+// LLIndexedVector
+//--------------------------------------------------------
+
+template <typename Type, typename Key, int BlockSize = 32> 
+class LLIndexedVector
+{
+public:
+	typedef typename std::vector<Type>::iterator iterator;
+	typedef typename std::vector<Type>::const_iterator const_iterator;
+	typedef typename std::vector<Type>::reverse_iterator reverse_iterator;
+	typedef typename std::vector<Type>::const_reverse_iterator const_reverse_iterator;
+	typedef typename std::vector<Type>::size_type size_type;
+protected:
+	std::vector<Type> mVector;
+	std::map<Key, U32> mIndexMap;
+	
+public:
+	LLIndexedVector() { mVector.reserve(BlockSize); }
+	
+	iterator begin() { return mVector.begin(); }
+	const_iterator begin() const { return mVector.begin(); }
+	iterator end() { return mVector.end(); }
+	const_iterator end() const { return mVector.end(); }
+
+	reverse_iterator rbegin() { return mVector.rbegin(); }
+	const_reverse_iterator rbegin() const { return mVector.rbegin(); }
+	reverse_iterator rend() { return mVector.rend(); }
+	const_reverse_iterator rend() const { return mVector.rend(); }
+
+	void reset() { mVector.resize(0); mIndexMap.resize(0); }
+	bool empty() const { return mVector.empty(); }
+	size_type size() const { return mVector.size(); }
+	
+	Type& operator[](const Key& k)
+	{
+		typename std::map<Key, U32>::const_iterator iter = mIndexMap.find(k);
+		if (iter == mIndexMap.end())
+		{
+			U32 n = mVector.size();
+			mIndexMap[k] = n;
+			mVector.push_back(Type());
+			llassert(mVector.size() == mIndexMap.size());
+			return mVector[n];
+		}
+		else
+		{
+			return mVector[iter->second];
+		}
+	}
+
+	const_iterator find(const Key& k) const
+	{
+		typename std::map<Key, U32>::const_iterator iter = mIndexMap.find(k);
+		if(iter == mIndexMap.end())
+		{
+			return mVector.end();
+		}
+		else
+		{
+			return mVector.begin() + iter->second;
+		}
+	}
+};
+
+#endif
diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index dbd4eba7a0..aa2f4eb289 100755
--- a/indra/llcommon/llinitparam.cpp
+++ b/indra/llcommon/llinitparam.cpp
@@ -100,13 +100,13 @@ namespace LLInitParam
 	void Parser::parserWarning(const std::string& message)
 	{
 		if (mParseSilently) return;
-		llwarns << message << llendl;
+		LL_WARNS() << message << LL_ENDL;
 	}
 	
 	void Parser::parserError(const std::string& message)
 	{
 		if (mParseSilently) return;
-		llerrs << message << llendl;
+		LL_ERRS() << message << LL_ENDL;
 	}
 
 
@@ -131,7 +131,7 @@ namespace LLInitParam
 		std::string name(char_name);
 		if ((size_t)param->mParamHandle > mMaxParamOffset)
 		{
-			llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;
+			LL_ERRS() << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << LL_ENDL;
 		}
 
 		if (name.empty())
@@ -214,7 +214,7 @@ namespace LLInitParam
 			{
 				if (emit_errors)
 				{
-					llwarns << "Invalid param \"" << getParamName(block_data, param) << "\"" << llendl;
+					LL_WARNS() << "Invalid param \"" << getParamName(block_data, param) << "\"" << LL_ENDL;
 				}
 				return false;
 			}
@@ -417,7 +417,7 @@ namespace LLInitParam
 			// Block<T, Base_Class>
 			if ((size_t)handle > block_data.mMaxParamOffset)
 			{
-				llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;
+				LL_ERRS() << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << LL_ENDL;
 			}
 
 			ParamDescriptorPtr param_descriptor = findParamDescriptor(param);
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index f4e37d21fe..349ad530af 100755
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -31,7 +31,7 @@
 #include <map>
 #include <typeinfo>
 
-#include "string_table.h"
+#include "llstringtable.h"
 #include <boost/iterator/transform_iterator.hpp>
 #include <boost/iterator/indirect_iterator.hpp>
 
diff --git a/indra/llcommon/lllinkedqueue.h b/indra/llcommon/lllinkedqueue.h
deleted file mode 100755
index 8336608809..0000000000
--- a/indra/llcommon/lllinkedqueue.h
+++ /dev/null
@@ -1,309 +0,0 @@
-/** 
- * @file lllinkedqueue.h
- * @brief Declaration of linked queue classes.
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLLINKEDQUEUE_H
-#define LL_LLLINKEDQUEUE_H
-
-#include "llerror.h"
-
-// node that actually contains the data
-template <class DATA_TYPE> class LLLinkedQueueNode
-{
-public:
-	DATA_TYPE			mData;
-	LLLinkedQueueNode	*mNextp;
-	LLLinkedQueueNode	*mPrevp;
-
-
-public:
-	LLLinkedQueueNode();
-	LLLinkedQueueNode(const DATA_TYPE data);
-
-	// destructor does not, by default, destroy associated data
-	// however, the mDatap must be NULL to ensure that we aren't causing memory leaks
-	~LLLinkedQueueNode();
-};
-
-
-
-template <class DATA_TYPE> class LLLinkedQueue
-{
-
-public:
-	LLLinkedQueue();
-
-	// destructor destroys list and nodes, but not data in nodes
-	~LLLinkedQueue();
-
-	// Puts at end of FIFO
-	void push(const DATA_TYPE data);
-
-	// Takes off front of FIFO
-	BOOL pop(DATA_TYPE &data);
-	BOOL peek(DATA_TYPE &data);
-
-	void reset();
-
-	S32 getLength() const;
-
-	BOOL isEmpty() const;
-
-	BOOL remove(const DATA_TYPE data);
-
-	BOOL checkData(const DATA_TYPE data) const;
-
-private:
-	// add node to end of list
-	// set mCurrentp to mQueuep
-	void addNodeAtEnd(LLLinkedQueueNode<DATA_TYPE> *nodep);
-
-private:
-	LLLinkedQueueNode<DATA_TYPE> mHead;		// head node
-	LLLinkedQueueNode<DATA_TYPE> mTail;		// tail node
-	S32 mLength;
-};
-
-
-//
-// Nodes
-//
-
-template <class DATA_TYPE>
-LLLinkedQueueNode<DATA_TYPE>::LLLinkedQueueNode() : 
-	mData(), mNextp(NULL), mPrevp(NULL)
-{ }
-
-template <class DATA_TYPE>
-LLLinkedQueueNode<DATA_TYPE>::LLLinkedQueueNode(const DATA_TYPE data) : 
-	mData(data), mNextp(NULL), mPrevp(NULL)
-{ }
-
-template <class DATA_TYPE>
-LLLinkedQueueNode<DATA_TYPE>::~LLLinkedQueueNode()
-{ }
-
-
-//
-// Queue itself
-//
-
-template <class DATA_TYPE>
-LLLinkedQueue<DATA_TYPE>::LLLinkedQueue()
-:	mHead(), 
-	mTail(), 
-	mLength(0)
-{ }
-
-
-// destructor destroys list and nodes, but not data in nodes
-template <class DATA_TYPE>
-LLLinkedQueue<DATA_TYPE>::~LLLinkedQueue()
-{
-	reset();
-}
-
-
-// put data into a node and stick it at the end of the list
-template <class DATA_TYPE>
-void LLLinkedQueue<DATA_TYPE>::push(const DATA_TYPE data)
-{
-	// make the new node
-	LLLinkedQueueNode<DATA_TYPE> *nodep = new LLLinkedQueueNode<DATA_TYPE>(data);
-
-	addNodeAtEnd(nodep);
-}
-
-
-// search the list starting at mHead.mNextp and remove the link with mDatap == data
-// set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-BOOL LLLinkedQueue<DATA_TYPE>::remove(const DATA_TYPE data)
-{
-	BOOL b_found = FALSE;
-
-	LLLinkedQueueNode<DATA_TYPE> *currentp = mHead.mNextp;
-
-	while (currentp)
-	{
-		if (currentp->mData == data)
-		{
-			b_found = TRUE;
-
-			// if there is a next one, fix it
-			if (currentp->mNextp)
-			{
-				currentp->mNextp->mPrevp = currentp->mPrevp;
-			}
-			else // we are at end of list
-			{
-				mTail.mPrevp = currentp->mPrevp;
-			}
-
-			// if there is a previous one, fix it
-			if (currentp->mPrevp)
-			{
-				currentp->mPrevp->mNextp = currentp->mNextp;
-			}
-			else // we are at beginning of list
-			{
-				mHead.mNextp = currentp->mNextp;
-			}
-
-			// remove the node
-			delete currentp;
-			mLength--;
-			break;
-		}
-		currentp = currentp->mNextp; 
-	}
-
-	return b_found;
-}
-
-
-// remove all nodes from the list but do not delete associated data
-template <class DATA_TYPE>
-void LLLinkedQueue<DATA_TYPE>::reset()
-{
-	LLLinkedQueueNode<DATA_TYPE> *currentp;
-	LLLinkedQueueNode<DATA_TYPE> *nextp;
-	currentp = mHead.mNextp;
-
-	while (currentp)
-	{
-		nextp = currentp->mNextp;
-		delete currentp;
-		currentp = nextp;
-	}
-
-	// reset mHead and mCurrentp
-	mHead.mNextp = NULL;
-	mTail.mPrevp = NULL;
-	mLength = 0;
-}
-
-template <class DATA_TYPE>
-S32 LLLinkedQueue<DATA_TYPE>::getLength() const
-{
-	return mLength;
-}
-
-template <class DATA_TYPE>
-BOOL LLLinkedQueue<DATA_TYPE>::isEmpty() const
-{
-	return mLength <= 0;
-}
-
-// check to see if data is in list
-// set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-BOOL LLLinkedQueue<DATA_TYPE>::checkData(const DATA_TYPE data) const
-{
-	LLLinkedQueueNode<DATA_TYPE> *currentp = mHead.mNextp;
-
-	while (currentp)
-	{
-		if (currentp->mData == data)
-		{
-			return TRUE;
-		}
-		currentp = currentp->mNextp;
-	}
-	return FALSE;
-}
-
-template <class DATA_TYPE>
-BOOL LLLinkedQueue<DATA_TYPE>::pop(DATA_TYPE &data)
-{
-	LLLinkedQueueNode<DATA_TYPE> *currentp;
-
-	currentp = mHead.mNextp;
-	if (!currentp)
-	{
-		return FALSE;
-	}
-
-	mHead.mNextp = currentp->mNextp;
-	if (currentp->mNextp)
-	{
-		currentp->mNextp->mPrevp = currentp->mPrevp;
-	}
-	else
-	{
-		mTail.mPrevp = currentp->mPrevp;
-	}
-
-	data = currentp->mData;
-	delete currentp;
-	mLength--;
-	return TRUE;
-}
-
-template <class DATA_TYPE>
-BOOL LLLinkedQueue<DATA_TYPE>::peek(DATA_TYPE &data)
-{
-	LLLinkedQueueNode<DATA_TYPE> *currentp;
-
-	currentp = mHead.mNextp;
-	if (!currentp)
-	{
-		return FALSE;
-	}
-	data = currentp->mData;
-	return TRUE;
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// private members
-//////////////////////////////////////////////////////////////////////////////////////////
-
-
-// add node to end of list
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-void LLLinkedQueue<DATA_TYPE>::addNodeAtEnd(LLLinkedQueueNode<DATA_TYPE> *nodep)
-{
-	// add the node to the end of the list
-	nodep->mNextp = NULL;
-	nodep->mPrevp = mTail.mPrevp;
-	mTail.mPrevp = nodep;
-
-	// if there's something in the list, fix its back pointer
-	if (nodep->mPrevp)
-	{
-		nodep->mPrevp->mNextp = nodep;
-	}
-	else	// otherwise fix the head node
-	{
-		mHead.mNextp = nodep;
-	}
-	mLength++;
-}
-
-#endif
diff --git a/indra/llcommon/lllog.cpp b/indra/llcommon/lllog.cpp
deleted file mode 100755
index fc4058b5c9..0000000000
--- a/indra/llcommon/lllog.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/** 
- * @file lllog.cpp
- * @author Don
- * @date 2007-11-27
- * @brief  Class to log messages to syslog for streambase to process.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "lllog.h"
-
-#include "llapp.h"
-#include "llsd.h"
-#include "llsdserialize.h"
-
-
-class LLLogImpl
-{
-public:
-	LLLogImpl(LLApp* app) : mApp(app) {}
-	~LLLogImpl() {}
-
-	void log(const std::string &message, LLSD& info);
-	bool useLegacyLogMessage(const std::string &message);
-
-private:
-	LLApp* mApp;
-};
-
-
-//@brief Function to log a message to syslog for streambase to collect.
-void LLLogImpl::log(const std::string &message, LLSD& info)
-{
-	static S32 sequence = 0;
-    LLSD log_config = mApp->getOption("log-messages");
-	if (log_config.has(message))
-	{
-		LLSD message_config = log_config[message];
-		if (message_config.has("use-syslog"))
-		{
-			if (! message_config["use-syslog"].asBoolean())
-			{
-				return;
-			}
-		}
-	}
-	llinfos << "LLLOGMESSAGE (" << (sequence++) << ") " << message 
-		<< " " << LLSDNotationStreamer(info) << llendl;
-}
-
-//@brief Function to check if specified legacy log message should be sent.
-bool LLLogImpl::useLegacyLogMessage(const std::string &message)
-{
-    LLSD log_config = mApp->getOption("log-messages");
-	if (log_config.has(message))
-	{
-		LLSD message_config = log_config[message];
-		if (message_config.has("use-legacy"))
-		{
-			return message_config["use-legacy"].asBoolean();
-		}
-	}
-	return true;
-}
-
-
-LLLog::LLLog(LLApp* app)
-{
-	mImpl = new LLLogImpl(app);
-}
-
-LLLog::~LLLog()
-{
-	delete mImpl;
-	mImpl = NULL;
-}
-
-void LLLog::log(const std::string &message, LLSD& info)
-{
-	if (mImpl) mImpl->log(message, info);
-}
-
-bool LLLog::useLegacyLogMessage(const std::string &message)
-{
-	if (mImpl)
-	{
-		return mImpl->useLegacyLogMessage(message);
-	}
-	return true;
-}
-
diff --git a/indra/llcommon/lllog.h b/indra/llcommon/lllog.h
deleted file mode 100755
index 7964412e83..0000000000
--- a/indra/llcommon/lllog.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * @file lllog.h
- * @author Don
- * @date 2007-11-27
- * @brief  Class to log messages to syslog for streambase to process.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLLOG_H
-#define LL_LLLOG_H
-
-#include <string>
-
-class LLLogImpl;
-class LLApp;
-class LLSD;
-
-class LL_COMMON_API LLLog
-{
-public:
-	LLLog(LLApp* app);
-	virtual ~LLLog();
-
-	virtual void log(const std::string &message, LLSD& info);
-	virtual bool useLegacyLogMessage(const std::string &message);
-
-private:
-	LLLogImpl* mImpl;
-};
-
-#endif /* LL_LLLOG_H */
-
diff --git a/indra/llcommon/lllslconstants.h b/indra/llcommon/lllslconstants.h
deleted file mode 100755
index 9f32598e61..0000000000
--- a/indra/llcommon/lllslconstants.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/** 
- * @file lllslconstants.h
- * @author James Cook
- * @brief Constants used in lsl.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLLSLCONSTANTS_H
-#define LL_LLLSLCONSTANTS_H
-
-// LSL: Return flags for llGetAgentInfo
-const U32 AGENT_FLYING		= 0x0001;
-const U32 AGENT_ATTACHMENTS	= 0x0002;
-const U32 AGENT_SCRIPTED	= 0x0004;
-const U32 AGENT_MOUSELOOK	= 0x0008;
-const U32 AGENT_SITTING		= 0x0010;
-const U32 AGENT_ON_OBJECT	= 0x0020;
-const U32 AGENT_AWAY		= 0x0040;
-const U32 AGENT_WALKING		= 0x0080;
-const U32 AGENT_IN_AIR		= 0x0100;
-const U32 AGENT_TYPING		= 0x0200;
-const U32 AGENT_CROUCHING	= 0x0400;
-const U32 AGENT_BUSY		= 0x0800;
-const U32 AGENT_ALWAYS_RUN	= 0x1000;
-const U32 AGENT_AUTOPILOT	= 0x2000;
-
-const S32 LSL_REMOTE_DATA_CHANNEL		= 1;
-const S32 LSL_REMOTE_DATA_REQUEST		= 2;
-const S32 LSL_REMOTE_DATA_REPLY			= 3;
-
-// Constants used in extended LSL primitive setter and getters
-const S32 LSL_PRIM_TYPE_LEGACY	= 1; // No longer supported.
-const S32 LSL_PRIM_MATERIAL		= 2;
-const S32 LSL_PRIM_PHYSICS		= 3;
-const S32 LSL_PRIM_TEMP_ON_REZ	= 4;
-const S32 LSL_PRIM_PHANTOM		= 5;
-const S32 LSL_PRIM_POSITION		= 6;
-const S32 LSL_PRIM_SIZE			= 7;
-const S32 LSL_PRIM_ROTATION		= 8;
-const S32 LSL_PRIM_TYPE			= 9; // Replacement for LSL_PRIM_TYPE_LEGACY
-const S32 LSL_PRIM_TEXTURE		= 17;
-const S32 LSL_PRIM_COLOR		= 18;
-const S32 LSL_PRIM_BUMP_SHINY	= 19;
-const S32 LSL_PRIM_FULLBRIGHT	= 20;
-const S32 LSL_PRIM_FLEXIBLE		= 21;
-const S32 LSL_PRIM_TEXGEN		= 22;
-const S32 LSL_PRIM_POINT_LIGHT	= 23;
-const S32 LSL_PRIM_CAST_SHADOWS	= 24;
-const S32 LSL_PRIM_GLOW     	= 25;
-
-const S32 LSL_PRIM_TYPE_BOX		= 0;
-const S32 LSL_PRIM_TYPE_CYLINDER= 1;
-const S32 LSL_PRIM_TYPE_PRISM	= 2;
-const S32 LSL_PRIM_TYPE_SPHERE	= 3;
-const S32 LSL_PRIM_TYPE_TORUS	= 4;
-const S32 LSL_PRIM_TYPE_TUBE	= 5;
-const S32 LSL_PRIM_TYPE_RING	= 6;
-const S32 LSL_PRIM_TYPE_SCULPT  = 7;
-
-const S32 LSL_PRIM_HOLE_DEFAULT = 0x00;
-const S32 LSL_PRIM_HOLE_CIRCLE	= 0x10;
-const S32 LSL_PRIM_HOLE_SQUARE  = 0x20;
-const S32 LSL_PRIM_HOLE_TRIANGLE= 0x30;
-
-const S32 LSL_PRIM_MATERIAL_STONE	= 0;
-const S32 LSL_PRIM_MATERIAL_METAL	= 1;
-const S32 LSL_PRIM_MATERIAL_GLASS	= 2;
-const S32 LSL_PRIM_MATERIAL_WOOD	= 3;
-const S32 LSL_PRIM_MATERIAL_FLESH	= 4;
-const S32 LSL_PRIM_MATERIAL_PLASTIC	= 5;
-const S32 LSL_PRIM_MATERIAL_RUBBER	= 6;
-const S32 LSL_PRIM_MATERIAL_LIGHT	= 7;
-
-const S32 LSL_PRIM_SHINY_NONE		= 0;
-const S32 LSL_PRIM_SHINY_LOW		= 1;
-const S32 LSL_PRIM_SHINY_MEDIUM		= 2;
-const S32 LSL_PRIM_SHINY_HIGH		= 3;
-
-const S32 LSL_PRIM_TEXGEN_DEFAULT	= 0;
-const S32 LSL_PRIM_TEXGEN_PLANAR	= 1;
-
-const S32 LSL_PRIM_BUMP_NONE		= 0;
-const S32 LSL_PRIM_BUMP_BRIGHT		= 1;
-const S32 LSL_PRIM_BUMP_DARK		= 2;
-const S32 LSL_PRIM_BUMP_WOOD		= 3;
-const S32 LSL_PRIM_BUMP_BARK		= 4;
-const S32 LSL_PRIM_BUMP_BRICKS		= 5;
-const S32 LSL_PRIM_BUMP_CHECKER		= 6;
-const S32 LSL_PRIM_BUMP_CONCRETE	= 7;
-const S32 LSL_PRIM_BUMP_TILE		= 8;
-const S32 LSL_PRIM_BUMP_STONE		= 9;
-const S32 LSL_PRIM_BUMP_DISKS		= 10;
-const S32 LSL_PRIM_BUMP_GRAVEL		= 11;
-const S32 LSL_PRIM_BUMP_BLOBS		= 12;
-const S32 LSL_PRIM_BUMP_SIDING		= 13;
-const S32 LSL_PRIM_BUMP_LARGETILE	= 14;
-const S32 LSL_PRIM_BUMP_STUCCO		= 15;
-const S32 LSL_PRIM_BUMP_SUCTION		= 16;
-const S32 LSL_PRIM_BUMP_WEAVE		= 17;
-
-const S32 LSL_PRIM_SCULPT_TYPE_SPHERE   = 1;
-const S32 LSL_PRIM_SCULPT_TYPE_TORUS    = 2;
-const S32 LSL_PRIM_SCULPT_TYPE_PLANE    = 3;
-const S32 LSL_PRIM_SCULPT_TYPE_CYLINDER = 4;
-const S32 LSL_PRIM_SCULPT_TYPE_MASK     = 7;
-const S32 LSL_PRIM_SCULPT_FLAG_INVERT   = 64;
-const S32 LSL_PRIM_SCULPT_FLAG_MIRROR   = 128;
-
-const S32 LSL_ALL_SIDES				= -1;
-const S32 LSL_LINK_ROOT				= 1;
-const S32 LSL_LINK_FIRST_CHILD		= 2;
-const S32 LSL_LINK_SET				= -1;
-const S32 LSL_LINK_ALL_OTHERS		= -2;
-const S32 LSL_LINK_ALL_CHILDREN		= -3;
-const S32 LSL_LINK_THIS				= -4;
-
-// LSL constants for llSetForSell
-const S32 SELL_NOT			= 0;
-const S32 SELL_ORIGINAL		= 1;
-const S32 SELL_COPY			= 2;
-const S32 SELL_CONTENTS		= 3;
-
-// LSL constants for llSetPayPrice
-const S32 PAY_PRICE_HIDE = -1;
-const S32 PAY_PRICE_DEFAULT = -2;
-const S32 MAX_PAY_BUTTONS = 4;
-const S32 PAY_BUTTON_DEFAULT_0 = 1;
-const S32 PAY_BUTTON_DEFAULT_1 = 5;
-const S32 PAY_BUTTON_DEFAULT_2 = 10;
-const S32 PAY_BUTTON_DEFAULT_3 = 20;
-
-// lsl email registration.
-const S32 EMAIL_REG_SUBSCRIBE_OBJECT	= 0x01;
-const S32 EMAIL_REG_UNSUBSCRIBE_OBJECT	= 0x02;
-const S32 EMAIL_REG_UNSUBSCRIBE_SIM		= 0x04;
-
-const S32 LIST_STAT_RANGE = 0;
-const S32 LIST_STAT_MIN		= 1;
-const S32 LIST_STAT_MAX		= 2;
-const S32 LIST_STAT_MEAN	= 3;
-const S32 LIST_STAT_MEDIAN	= 4;
-const S32 LIST_STAT_STD_DEV	= 5;
-const S32 LIST_STAT_SUM = 6;
-const S32 LIST_STAT_SUM_SQUARES = 7;
-const S32 LIST_STAT_NUM_COUNT = 8;
-const S32 LIST_STAT_GEO_MEAN = 9;
-
-const S32 STRING_TRIM_HEAD = 0x01;
-const S32 STRING_TRIM_TAIL = 0x02;
-const S32 STRING_TRIM = STRING_TRIM_HEAD | STRING_TRIM_TAIL;
-
-// llGetObjectDetails
-const S32 OBJECT_UNKNOWN_DETAIL = -1;
-const S32 OBJECT_NAME = 1;
-const S32 OBJECT_DESC = 2;
-const S32 OBJECT_POS = 3;
-const S32 OBJECT_ROT = 4;
-const S32 OBJECT_VELOCITY = 5;
-const S32 OBJECT_OWNER = 6;
-const S32 OBJECT_GROUP = 7;
-const S32 OBJECT_CREATOR = 8;
-
-// llTextBox() magic token string - yes this is a hack.  sue me.
-char const* const TEXTBOX_MAGIC_TOKEN = "!!llTextBox!!";
-
-// changed() event flags
-const U32	CHANGED_NONE = 0x0;
-const U32	CHANGED_INVENTORY = 0x1;
-const U32	CHANGED_COLOR = 0x2;
-const U32	CHANGED_SHAPE = 0x4;
-const U32	CHANGED_SCALE = 0x8;
-const U32	CHANGED_TEXTURE = 0x10;
-const U32	CHANGED_LINK = 0x20;
-const U32	CHANGED_ALLOWED_DROP = 0x40;
-const U32	CHANGED_OWNER = 0x80;
-const U32	CHANGED_REGION = 0x100;
-const U32	CHANGED_TELEPORT = 0x200;
-const U32	CHANGED_REGION_START = 0x400;
-const U32   CHANGED_MEDIA = 0x800;
-
-// Possible error results
-const U32 LSL_STATUS_OK                 = 0;
-const U32 LSL_STATUS_MALFORMED_PARAMS   = 1000;
-const U32 LSL_STATUS_TYPE_MISMATCH      = 1001;
-const U32 LSL_STATUS_BOUNDS_ERROR       = 1002;
-const U32 LSL_STATUS_NOT_FOUND          = 1003;
-const U32 LSL_STATUS_NOT_SUPPORTED      = 1004;
-const U32 LSL_STATUS_INTERNAL_ERROR     = 1999;
-
-// Start per-function errors below, starting at 2000:
-const U32 LSL_STATUS_WHITELIST_FAILED   = 2001;
-
-#endif
diff --git a/indra/llcommon/llmap.h b/indra/llcommon/llmap.h
deleted file mode 100755
index 6294a15d3b..0000000000
--- a/indra/llcommon/llmap.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/** 
- * @file llmap.h
- * @brief LLMap class header file
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLMAP_H
-#define LL_LLMAP_H
-
-// llmap uses the fast stl library code in a manner consistant with LLSkipMap, et. al. 
-
-template<class INDEX_TYPE, class MAPPED_TYPE> class LLMap
-{
-private:
-	typedef typename std::map<INDEX_TYPE, MAPPED_TYPE> stl_map_t;
-	typedef typename stl_map_t::iterator stl_iter_t;
-	typedef typename stl_map_t::value_type stl_value_t;
-	
-	stl_map_t mStlMap;
-	stl_iter_t mCurIter;	// *iterator = pair<const INDEX_TYPE, MAPPED_TYPE>
-	MAPPED_TYPE dummy_data;
-	INDEX_TYPE dummy_index;
-	
-public:
-	LLMap() : mStlMap()
-	{
-		memset((void*)(&dummy_data),  0x0, sizeof(MAPPED_TYPE));
-		memset((void*)(&dummy_index), 0x0, sizeof(INDEX_TYPE));
-		mCurIter = mStlMap.begin();
-	}
-	~LLMap()
-	{
-		mStlMap.clear();
-	}
-
-	// use these functions to itterate through a list
-	void resetMap()
-	{
-		mCurIter = mStlMap.begin();
-	}
-
-	// get the current data and bump mCurrentp
-	// This is kind of screwy since it returns a reference;
-	//   We have to have a dummy value for when we reach the end
-	//   or in case we have an empty list. Presumably, this value
-	//   will initialize to some NULL value that will end the iterator.
-	// We really shouldn't be using getNextData() or getNextKey() anyway...
-	MAPPED_TYPE &getNextData()
-	{
-		if (mCurIter == mStlMap.end())
-		{
-			return dummy_data;
-		}
-		else
-		{
-			return (*mCurIter++).second;
-		}
-	}
-
-	const INDEX_TYPE &getNextKey()
-	{
-		if (mCurIter == mStlMap.end())
-		{
-			return dummy_index;
-		}
-		else
-		{
-			return (*mCurIter++).first;
-		}
-	}
-
-	MAPPED_TYPE &getFirstData()
-	{
-		resetMap();
-		return getNextData();
-	}
-
-	const INDEX_TYPE &getFirstKey()
-	{
-		resetMap();
-		return getNextKey();
-	}
-
-	S32 getLength()
-	{
-		return mStlMap.size();
-	}
-
-	void addData(const INDEX_TYPE &index, MAPPED_TYPE pointed_to)
-	{
-		mStlMap.insert(stl_value_t(index, pointed_to));
-	}
-
-	void addData(const INDEX_TYPE &index)
-	{
-		mStlMap.insert(stl_value_t(index, dummy_data));
-	}
-
-	// if index doesn't exist, then insert a new node and return it
-	MAPPED_TYPE &getData(const INDEX_TYPE &index)
-	{
-		std::pair<stl_iter_t, bool> res;
-		res = mStlMap.insert(stl_value_t(index, dummy_data));
-		return res.first->second;
-	}
-
-	// if index doesn't exist, then insert a new node, return it, and set b_new_entry to true
-	MAPPED_TYPE &getData(const INDEX_TYPE &index, BOOL &b_new_entry)
-	{
-		std::pair<stl_iter_t, bool> res;
-		res = mStlMap.insert(stl_value_t(index, dummy_data));
-		b_new_entry = res.second;
-		return res.first->second;
-	}
-
-	// If there, returns the data.
-	// If not, returns NULL.
-	// Never adds entries to the map.
-	MAPPED_TYPE getIfThere(const INDEX_TYPE &index)
-	{
-		stl_iter_t iter;
-		iter = mStlMap.find(index);
-		if (iter == mStlMap.end())
-		{
-			return (MAPPED_TYPE)0;
-		}
-		else
-		{
-			return (*iter).second;
-		}
-	}
-
-
-	// if index doesn't exist, then make a new node and return it
-	MAPPED_TYPE &operator[](const INDEX_TYPE &index)
-	{
-		return getData(index);
-	}
-
-	// do a reverse look-up, return NULL if failed
-	INDEX_TYPE reverseLookup(const MAPPED_TYPE data)
-	{
-		stl_iter_t iter;
-		stl_iter_t end_iter;
-		iter = mStlMap.begin();
-		end_iter = mStlMap.end();
-		while (iter != end_iter)
-		{
-			if ((*iter).second == data)
-				return (*iter).first;
-			iter++;
-		}
-		return (INDEX_TYPE)0;
-	}
-
-	BOOL removeData(const INDEX_TYPE &index)
-	{
-		mCurIter = mStlMap.find(index);
-		if (mCurIter == mStlMap.end())
-		{
-			return FALSE;
-		}
-		else
-		{
-			stl_iter_t iter = mCurIter++; // incrament mCurIter to the next element
-			mStlMap.erase(iter);
-			return TRUE;
-		}
-	}
-
-	// does this index exist?
-	BOOL checkData(const INDEX_TYPE &index)
-	{
-		stl_iter_t iter;
-		iter = mStlMap.find(index);
-		if (iter == mStlMap.end())
-		{
-			return FALSE;
-		}
-		else
-		{
-			mCurIter = iter;
-			return TRUE;
-		}
-	}
-
-	BOOL deleteData(const INDEX_TYPE &index)
-	{
-		mCurIter = mStlMap.find(index);
-		if (mCurIter == mStlMap.end())
-		{
-			return FALSE;
-		}
-		else
-		{
-			stl_iter_t iter = mCurIter++; // incrament mCurIter to the next element
-			delete (*iter).second;
-			mStlMap.erase(iter);
-			return TRUE;
-		}
-	}
-
-	void deleteAllData()
-	{
-		stl_iter_t iter;
-		stl_iter_t end_iter;
-		iter = mStlMap.begin();
-		end_iter = mStlMap.end();
-		while (iter != end_iter)
-		{
-			delete (*iter).second;
-			iter++;
-		}
-		mStlMap.clear();
-		mCurIter = mStlMap.end();
-	}
-	
-	void removeAllData()
-	{
-		mStlMap.clear();
-	}
-};
-
-
-#endif
diff --git a/indra/llcommon/llnametable.h b/indra/llcommon/llnametable.h
deleted file mode 100755
index d3283543f3..0000000000
--- a/indra/llcommon/llnametable.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/** 
- * @file llnametable.h
- * @brief LLNameTable class is a table to associate pointers with string names
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLNAMETABLE_H
-#define LL_LLNAMETABLE_H
-
-#include <map>
-
-#include "string_table.h"
-
-template <class DATA>
-class LLNameTable
-{
-public:
-	LLNameTable()
-	:	mNameMap()
-	{
-	}
-
-	~LLNameTable() 
-	{ 
-	}
-
-	void addEntry(const std::string& name, DATA data)
-	{
-		addEntry(name.c_str(), data);
-	}
-
-	void addEntry(const char *name, DATA data)
-	{
-		char *tablename = gStringTable.addString(name);
-		mNameMap[tablename] = data;
-	}
-
-	BOOL checkName(const std::string& name) const
-	{
-		return checkName(name.c_str());
-	}
-
-	// "logically const" even though it modifies the global nametable
-	BOOL checkName(const char *name) const
-	{
-		char *tablename = gStringTable.addString(name);
-		return mNameMap.count(tablename) ? TRUE : FALSE;
-	}
-
-	DATA resolveName(const std::string& name) const
-	{
-		return resolveName(name.c_str());
-	}
-
-	// "logically const" even though it modifies the global nametable
-	DATA resolveName(const char *name) const
-	{
-		char *tablename = gStringTable.addString(name);
-		const_iter_t iter = mNameMap.find(tablename);
-		if (iter != mNameMap.end())
-			return iter->second;
-		else
-			return 0;
-	}
-
-	// O(N)! (currently only used in one place... (newsim/llstate.cpp))
-	const char *resolveData(const DATA &data) const
-	{
-		const_iter_t iter = mNameMap.begin();
-		const_iter_t end = mNameMap.end();
-		for (; iter != end; ++iter)
-		{
-			if (iter->second == data)
-				return iter->first;
-		}
-   		return NULL;
-	}		
-
-	typedef std::map<const char *, DATA> name_map_t;
-	typedef typename std::map<const char *,DATA>::iterator iter_t;
-	typedef typename std::map<const char *,DATA>::const_iterator const_iter_t;
-	name_map_t		mNameMap;
-};
-
-#endif
diff --git a/indra/llcommon/lloptioninterface.cpp b/indra/llcommon/lloptioninterface.cpp
deleted file mode 100755
index 23fae76dc0..0000000000
--- a/indra/llcommon/lloptioninterface.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/** 
- * @file lloptioninterface.cpp
- * @brief 
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "lloptioninterface.h"
-
-
-LLOptionInterface::~LLOptionInterface()
-{
-
-}
diff --git a/indra/llcommon/lloptioninterface.h b/indra/llcommon/lloptioninterface.h
deleted file mode 100755
index 93b465db32..0000000000
--- a/indra/llcommon/lloptioninterface.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/** 
- * @file lloptioninterface.h
- * @brief 
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLOPTIONINTERFACE_H
-#define LL_LLOPTIONINTERFACE_H
-
-#include "linden_common.h"
-
-class LLSD;
-class LLOptionInterface
-{
-public:
-    virtual ~LLOptionInterface() = 0;
-	virtual LLSD getOption(const std::string& name) const = 0;
-};
-
-#endif
diff --git a/indra/llcommon/llsecondlifeurls.cpp b/indra/llcommon/llsecondlifeurls.cpp
deleted file mode 100755
index 9154e05e43..0000000000
--- a/indra/llcommon/llsecondlifeurls.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/** 
- * @file llsecondlifeurls.cpp
- * @brief Urls used in the product
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llsecondlifeurls.h"
-/*
-const std::string CREATE_ACCOUNT_URL ( 
-	"http://join.secondlife.com/");
-
-const std::string MANAGE_ACCOUNT ( 
-	"http://secondlife.com/account/");  // *TODO: NOT USED
-
-const std::string AUCTION_URL ( 
-	"http://secondlife.com/auctions/auction-detail.php?id=");
-
-const std::string EVENTS_URL ( 
-	"http://secondlife.com/events/");
-*/
-const std::string TIER_UP_URL ( 
-	"http://secondlife.com/app/landtier"); // *TODO: Translate (simulator)
-
-const std::string DIRECTX_9_URL ( 
-								 "http://secondlife.com/support/"); // *TODO: NOT USED
-/*
-const std::string LAND_URL ( 
-	"http://secondlife.com/app/landtier"); // *TODO: NOT USED
-
-const std::string UPGRADE_TO_PREMIUM_URL (
-	"http://secondlife.com/app/upgrade/"); // *TODO: NOT USED
-
-const std::string AMD_AGP_URL ( 
-	"http://secondlife.com/support/"); // *TODO: NOT USED
-
-const std::string VIA_URL ( 
-	"http://secondlife.com/support/"); // *TODO: NOT USED
-
-const std::string SUPPORT_URL ( 
-    "http://secondlife.com/support/");
-
-const std::string INTEL_CHIPSET_URL ( 
-	"http://secondlife.com/support/"); // *TODO: NOT USED
-
-const std::string SIS_CHIPSET_URL ( 
-	"http://secondlife.com/support/"); // *TODO: NOT USED
-
-const std::string BLOGS_URL ( 
-	"http://blog.secondlife.com/"); // *TODO: NOT USED
-
-const std::string BUY_CURRENCY_URL (
-	"http://secondlife.com/app/currency/");
-
-const std::string LSL_DOC_URL (
-	"http://secondlife.com/app/lsldoc/");  // *TODO: NOT USED
-
-const std::string SL_KB_URL (
-	"http://secondlife.com/knowledgebase/"); // *TODO: NOT USED
-
-const std::string RELEASE_NOTES_BASE_URL (
-	"http://secondlife.com/app/releasenotes/");
-*/
-
diff --git a/indra/llcommon/llsecondlifeurls.h b/indra/llcommon/llsecondlifeurls.h
deleted file mode 100755
index 62f357ffed..0000000000
--- a/indra/llcommon/llsecondlifeurls.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/** 
- * @file llsecondlifeurls.h
- * @brief Global URLs to pages on our web site
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLSECONDLIFEURLS_H
-#define LL_LLSECONDLIFEURLS_H
-/*
-// Account registration web page
-LL_COMMON_API extern const std::string CREATE_ACCOUNT_URL;
-
-// Manage Account
-LL_COMMON_API extern const std::string MANAGE_ACCOUNT;
-
-LL_COMMON_API extern const std::string AUCTION_URL; 
-
-LL_COMMON_API extern const std::string EVENTS_URL;
-*/
-// Tier up to a new land level.
-LL_COMMON_API extern const std::string TIER_UP_URL;
-
-
-// Tier up to a new land level.
-LL_COMMON_API extern const std::string LAND_URL;
-
-// How to get DirectX 9
-LL_COMMON_API extern const std::string DIRECTX_9_URL;
-
-/*
-// Upgrade from basic membership to premium membership
-LL_COMMON_API extern const std::string UPGRADE_TO_PREMIUM_URL;
-
-
-// Out of date VIA chipset
-LL_COMMON_API extern const std::string VIA_URL;
-
-// Support URL
-LL_COMMON_API extern const std::string SUPPORT_URL;
-
-// Linden Blogs page
-LL_COMMON_API extern const std::string BLOGS_URL;
-
-// Currency page
-LL_COMMON_API extern const std::string BUY_CURRENCY_URL;
-
-// LSL script wiki
-LL_COMMON_API extern const std::string LSL_DOC_URL;
-
-// SL KnowledgeBase page
-LL_COMMON_API extern const std::string SL_KB_URL;
-
-// Release Notes Redirect URL for Server and Viewer
-LL_COMMON_API extern const std::string RELEASE_NOTES_BASE_URL;
-*/
-#endif
diff --git a/indra/llcommon/llstatenums.h b/indra/llcommon/llstatenums.h
deleted file mode 100755
index ab9b6709e8..0000000000
--- a/indra/llcommon/llstatenums.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/** 
- * @file llstatenums.h
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLSTATENUMS_H
-#define LL_LLSTATENUMS_H
-
-enum ESimStatID
-{
-	LL_SIM_STAT_TIME_DILATION         =  0,
-	LL_SIM_STAT_FPS                   =  1,
-	LL_SIM_STAT_PHYSFPS               =  2,
-	LL_SIM_STAT_AGENTUPS              =  3,
-	LL_SIM_STAT_FRAMEMS               =  4,
-	LL_SIM_STAT_NETMS                 =  5,
-	LL_SIM_STAT_SIMOTHERMS            =  6,
-	LL_SIM_STAT_SIMPHYSICSMS          =  7,
-	LL_SIM_STAT_AGENTMS               =  8,
-	LL_SIM_STAT_IMAGESMS              =  9,
-	LL_SIM_STAT_SCRIPTMS              = 10,
-	LL_SIM_STAT_NUMTASKS              = 11,
-	LL_SIM_STAT_NUMTASKSACTIVE        = 12,
-	LL_SIM_STAT_NUMAGENTMAIN          = 13,
-	LL_SIM_STAT_NUMAGENTCHILD         = 14,
-	LL_SIM_STAT_NUMSCRIPTSACTIVE      = 15,
-	LL_SIM_STAT_LSLIPS                = 16,
-	LL_SIM_STAT_INPPS                 = 17,
-	LL_SIM_STAT_OUTPPS                = 18,
-	LL_SIM_STAT_PENDING_DOWNLOADS     = 19,
-	LL_SIM_STAT_PENDING_UPLOADS       = 20,
-	LL_SIM_STAT_VIRTUAL_SIZE_KB       = 21,
-	LL_SIM_STAT_RESIDENT_SIZE_KB      = 22,
-	LL_SIM_STAT_PENDING_LOCAL_UPLOADS = 23,
-	LL_SIM_STAT_TOTAL_UNACKED_BYTES   = 24,
-	LL_SIM_STAT_PHYSICS_PINNED_TASKS  = 25,
-	LL_SIM_STAT_PHYSICS_LOD_TASKS     = 26,
-	LL_SIM_STAT_SIMPHYSICSSTEPMS      = 27,
-	LL_SIM_STAT_SIMPHYSICSSHAPEMS     = 28,
-	LL_SIM_STAT_SIMPHYSICSOTHERMS     = 29,
-	LL_SIM_STAT_SIMPHYSICSMEMORY      = 30,
-	LL_SIM_STAT_SCRIPT_EPS            = 31,
-	LL_SIM_STAT_SIMSPARETIME          = 32,
-	LL_SIM_STAT_SIMSLEEPTIME          = 33,
-	LL_SIM_STAT_IOPUMPTIME            = 34,
-	LL_SIM_STAT_PCTSCRIPTSRUN         = 35,
-	LL_SIM_STAT_REGION_IDLE           = 36, // dataserver only
-	LL_SIM_STAT_REGION_IDLE_POSSIBLE  = 37, // dataserver only
-	LL_SIM_STAT_SIMAISTEPTIMEMS       = 38,
-	LL_SIM_STAT_SKIPPEDAISILSTEPS_PS  = 39,
-	LL_SIM_STAT_PCTSTEPPEDCHARACTERS  = 40
-
-};
-
-#endif
diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h
index 424138dad1..143e71f40c 100755
--- a/indra/llcommon/llstl.h
+++ b/indra/llcommon/llstl.h
@@ -33,7 +33,6 @@
 #include <vector>
 #include <list>
 #include <set>
-#include <deque>
 #include <typeinfo>
 
 // Use to compare the first element only of a pair
@@ -125,7 +124,7 @@ struct DeletePairedPointerArray
 // compiler, the second unary_function template parameter can be set
 // to void.
 //
-// Here's a snippit showing how you use this object:
+// Here's a snippet showing how you use this object:
 //
 // typedef std::map<int, widget*> map_type;
 // map_type widget_map;
@@ -170,6 +169,49 @@ struct CopyNewPointer
 	}
 };
 
+template<typename T, typename ALLOC>
+void delete_and_clear(std::list<T*, ALLOC>& list)
+{
+	std::for_each(list.begin(), list.end(), DeletePointer());
+	list.clear();
+}
+
+template<typename T, typename ALLOC>
+void delete_and_clear(std::vector<T*, ALLOC>& vector)
+{
+	std::for_each(vector.begin(), vector.end(), DeletePointer());
+	vector.clear();
+}
+
+template<typename T, typename COMPARE, typename ALLOC>
+void delete_and_clear(std::set<T*, COMPARE, ALLOC>& set)
+{
+	std::for_each(set.begin(), set.end(), DeletePointer());
+	set.clear();
+}
+
+template<typename K, typename V, typename COMPARE, typename ALLOC>
+void delete_and_clear(std::map<K, V*, COMPARE, ALLOC>& map)
+{
+	std::for_each(map.begin(), map.end(), DeletePairedPointer());
+	map.clear();
+}
+
+template<typename T>
+void delete_and_clear(T*& ptr)
+{
+	delete ptr;
+	ptr = NULL;
+}
+
+
+template<typename T>
+void delete_and_clear_array(T*& ptr)
+{
+	delete[] ptr;
+	ptr = NULL;
+}
+
 // Simple function to help with finding pointers in maps.
 // For example:
 // 	typedef  map_t;
@@ -229,7 +271,6 @@ inline T get_if_there(const std::map<K,T>& inmap, const K& key, T default_value)
 	}
 };
 
-// Useful for replacing the removeObj() functionality of LLDynamicArray
 // Example:
 //  for (std::vector<T>::iterator iter = mList.begin(); iter != mList.end(); )
 //  {
@@ -238,8 +279,8 @@ inline T get_if_there(const std::map<K,T>& inmap, const K& key, T default_value)
 //    else
 //      ++iter;
 //  }
-template <typename T, typename Iter>
-inline Iter vector_replace_with_last(std::vector<T>& invec, Iter iter)
+template <typename T>
+inline typename std::vector<T>::iterator vector_replace_with_last(std::vector<T>& invec, typename std::vector<T>::iterator iter)
 {
 	typename std::vector<T>::iterator last = invec.end(); --last;
 	if (iter == invec.end())
@@ -259,7 +300,6 @@ inline Iter vector_replace_with_last(std::vector<T>& invec, Iter iter)
 	}
 };
 
-// Useful for replacing the removeObj() functionality of LLDynamicArray
 // Example:
 //   vector_replace_with_last(mList, x);
 template <typename T>
@@ -522,4 +562,151 @@ namespace std
 	};
 } // std
 
+
+/**
+ * Implementation for ll_template_cast() (q.v.).
+ *
+ * Default implementation: trying to cast two completely unrelated types
+ * returns 0. Typically you'd specify T and U as pointer types, but in fact T
+ * can be any type that can be initialized with 0.
+ */
+template <typename T, typename U>
+struct ll_template_cast_impl
+{
+    T operator()(U)
+    {
+        return 0;
+    }
+};
+
+/**
+ * ll_template_cast<T>(some_value) is for use in a template function when
+ * some_value might be of arbitrary type, but you want to recognize type T
+ * specially.
+ *
+ * It's designed for use with pointer types. Example:
+ * @code
+ * struct SpecialClass
+ * {
+ *     void someMethod(const std::string&) const;
+ * };
+ *
+ * template <class REALCLASS>
+ * void somefunc(const REALCLASS& instance)
+ * {
+ *     const SpecialClass* ptr = ll_template_cast<const SpecialClass*>(&instance);
+ *     if (ptr)
+ *     {
+ *         ptr->someMethod("Call method only available on SpecialClass");
+ *     }
+ * }
+ * @endcode
+ *
+ * Why is this better than dynamic_cast<>? Because unless OtherClass is
+ * polymorphic, the following won't even compile (gcc 4.0.1):
+ * @code
+ * OtherClass other;
+ * SpecialClass* ptr = dynamic_cast<SpecialClass*>(&other);
+ * @endcode
+ * to say nothing of this:
+ * @code
+ * void function(int);
+ * SpecialClass* ptr = dynamic_cast<SpecialClass*>(&function);
+ * @endcode
+ * ll_template_cast handles these kinds of cases by returning 0.
+ */
+template <typename T, typename U>
+T ll_template_cast(U value)
+{
+    return ll_template_cast_impl<T, U>()(value);
+}
+
+/**
+ * Implementation for ll_template_cast() (q.v.).
+ *
+ * Implementation for identical types: return same value.
+ */
+template <typename T>
+struct ll_template_cast_impl<T, T>
+{
+    T operator()(T value)
+    {
+        return value;
+    }
+};
+
+/**
+ * LL_TEMPLATE_CONVERTIBLE(dest, source) asserts that, for a value @c s of
+ * type @c source, <tt>ll_template_cast<dest>(s)</tt> will return @c s --
+ * presuming that @c source can be converted to @c dest by the normal rules of
+ * C++.
+ *
+ * By default, <tt>ll_template_cast<dest>(s)</tt> will return 0 unless @c s's
+ * type is literally identical to @c dest. (This is because of the
+ * straightforward application of template specialization rules.) That can
+ * lead to surprising results, e.g.:
+ *
+ * @code
+ * Foo myFoo;
+ * const Foo* fooptr = ll_template_cast<const Foo*>(&myFoo);
+ * @endcode
+ *
+ * Here @c fooptr will be 0 because <tt>&myFoo</tt> is of type <tt>Foo*</tt>
+ * -- @em not <tt>const Foo*</tt>. (Declaring <tt>const Foo myFoo;</tt> would
+ * force the compiler to do the right thing.)
+ *
+ * More disappointingly:
+ * @code
+ * struct Base {};
+ * struct Subclass: public Base {};
+ * Subclass object;
+ * Base* ptr = ll_template_cast<Base*>(&object);
+ * @endcode
+ *
+ * Here @c ptr will be 0 because <tt>&object</tt> is of type
+ * <tt>Subclass*</tt> rather than <tt>Base*</tt>. We @em want this cast to
+ * succeed, but without our help ll_template_cast can't recognize it.
+ *
+ * The following would suffice:
+ * @code
+ * LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
+ * ...
+ * Base* ptr = ll_template_cast<Base*>(&object);
+ * @endcode
+ *
+ * However, as noted earlier, this is easily fooled:
+ * @code
+ * const Base* ptr = ll_template_cast<const Base*>(&object);
+ * @endcode
+ * would still produce 0 because we haven't yet seen:
+ * @code
+ * LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
+ * @endcode
+ *
+ * @TODO
+ * This macro should use Boost type_traits facilities for stripping and
+ * re-adding @c const and @c volatile qualifiers so that invoking
+ * LL_TEMPLATE_CONVERTIBLE(dest, source) will automatically generate all
+ * permitted permutations. It's really not fair to the coder to require
+ * separate:
+ * @code
+ * LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
+ * LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
+ * LL_TEMPLATE_CONVERTIBLE(const Base*, const Subclass*);
+ * @endcode
+ *
+ * (Naturally we omit <tt>LL_TEMPLATE_CONVERTIBLE(Base*, const Subclass*)</tt>
+ * because that's not permitted by normal C++ assignment anyway.)
+ */
+#define LL_TEMPLATE_CONVERTIBLE(DEST, SOURCE)   \
+template <>                                     \
+struct ll_template_cast_impl<DEST, SOURCE>      \
+{                                               \
+    DEST operator()(SOURCE wrapper)             \
+    {                                           \
+        return wrapper;                         \
+    }                                           \
+}
+
+
 #endif // LL_LLSTL_H
diff --git a/indra/llcommon/llstringtable.cpp b/indra/llcommon/llstringtable.cpp
index 7ad3805351..f288999964 100755
--- a/indra/llcommon/llstringtable.cpp
+++ b/indra/llcommon/llstringtable.cpp
@@ -317,7 +317,7 @@ void LLStringTable::removeString(const char *str)
 						mUniqueEntries--;
 						if (mUniqueEntries < 0)
 						{
-							llerror("LLStringTable:removeString trying to remove too many strings!", 0);
+							LL_ERRS() << "LLStringTable:removeString trying to remove too many strings!" << LL_ENDL;
 						}
 						delete iter->second;
 						mStringHash.erase(iter);
@@ -343,7 +343,7 @@ void LLStringTable::removeString(const char *str)
 						mUniqueEntries--;
 						if (mUniqueEntries < 0)
 						{
-							llerror("LLStringTable:removeString trying to remove too many strings!", 0);
+							LL_ERRS() << "LLStringTable:removeString trying to remove too many strings!" << LL_ENDL;
 						}
 						strlist->remove(entry);
 						delete entry;
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 25383fc4d8..8f5a886a37 100755
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -43,7 +43,6 @@
 //
 // Locally used constants
 //
-const U32 SEC_PER_DAY = 86400;
 const F64 SEC_TO_MICROSEC = 1000000.f;
 const U64 SEC_TO_MICROSEC_U64 = 1000000;
 const F64 USEC_TO_SEC_F64 = 0.000001;
@@ -204,6 +203,8 @@ F64 calc_clock_frequency(unsigned int uiMeasureMSecs)
 	return 1000000.0; // microseconds, so 1 MHz.
 }
 
+const U64 SEC_TO_MICROSEC_U64 = 1000000;
+
 U64 get_clock_count()
 {
 	// Linux clocks are in microseconds
@@ -226,7 +227,7 @@ void update_clock_frequencies()
 
 // returns a U64 number that represents the number of 
 // microseconds since the unix epoch - Jan 1, 1970
-U64 totalTime()
+LLUnitImplicit<U64, LLUnits::Microseconds> totalTime()
 {
 	U64 current_clock_count = get_clock_count();
 	if (!gTotalTimeClockCount)
@@ -263,7 +264,7 @@ U64 totalTime()
 	}
 
 	// Return the total clock tick count in microseconds.
-	return (U64)(gTotalTimeClockCount*gClocksToMicroseconds);
+	return LLUnits::Microseconds::fromValue(gTotalTimeClockCount*gClocksToMicroseconds);
 }
 
 
@@ -375,7 +376,7 @@ LLUnitImplicit<F32, LLUnits::Seconds> LLTimer::getElapsedTimeAndResetF32()
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void  LLTimer::setTimerExpirySec(F32 expiration)
+void  LLTimer::setTimerExpirySec(LLUnitImplicit<F32, LLUnits::Seconds> expiration)
 {
 	mExpirationTicks = get_clock_count()
 		+ (U64)((F32)(expiration * gClockFrequency));
diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h
index f2dc59e405..1f2c56432b 100755
--- a/indra/llcommon/lltimer.h
+++ b/indra/llcommon/lltimer.h
@@ -91,7 +91,7 @@ public:
 	void stop() { mStarted = FALSE; }
 	void reset();								// Resets the timer
 	void setLastClockCount(U64 current_count);		// Sets the timer so that the next elapsed call will be relative to this time
-	void setTimerExpirySec(F32 expiration);
+	void setTimerExpirySec(LLUnitImplicit<F32, LLUnits::Seconds> expiration);
 	BOOL checkExpirationAndReset(F32 expiration);
 	BOOL hasExpired() const;
 	LLUnitImplicit<F32, LLUnits::Seconds> getElapsedTimeAndResetF32();	// Returns elapsed time in seconds with reset
@@ -171,6 +171,6 @@ LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_dayli
 LL_COMMON_API void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);
 LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstring);
 
-U64 LL_COMMON_API totalTime();					// Returns current system time in microseconds
+LLUnitImplicit<U64, LLUnits::Microseconds> LL_COMMON_API totalTime();					// Returns current system time in microseconds
 
 #endif
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index d6d8d9da6a..781a4ab731 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -29,7 +29,7 @@
 
 #include "stdtypes.h"
 #include "llpreprocessor.h"
-#include "llerrorlegacy.h"
+#include "llerror.h"
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE>
 struct LLUnit
@@ -266,13 +266,29 @@ LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (SCALAR_TYPE first, LLUnit<STORAGE_TY
 }
 
 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<STORAGE_TYPE1, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	result += second;
+	return result;
+}
+
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
 	LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first);
 	result += second;
 	return result;
 }
 
+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<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	result += LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
+	return result;
+}
+
 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)
 {
@@ -281,10 +297,10 @@ LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE,
 	return result;
 }
 
-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)
+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<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> result(first);
 	result += second;
 	return result;
 }
@@ -324,6 +340,22 @@ LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYP
 	return result;
 }
 
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	result -= second;
+	return result;
+}
+
+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<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	result -= LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
+	return result;
+}
+
 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)
 {
@@ -343,18 +375,6 @@ LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator - (SCALAR_TYPE first, LLUnitImp
 //
 // operator *
 //
-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<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first * second.value()));
-}
-
-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<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first.value() * 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>, LLUnit<STORAGE_TYPE2, UNIT_TYPE2>)
 {
@@ -364,15 +384,15 @@ LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnit<STORAGE_TYPE1, UNIT_TYPE1>,
 }
 
 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)
+LLUnit<STORAGE_TYPE, UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second)
 {
-	return LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>(first * second.value());
+	return LLUnit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first.value() * 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)
+LLUnit<STORAGE_TYPE, UNIT_TYPE> operator * (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	return LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>(first.value() * second);
+	return LLUnit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first * second.value()));
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
@@ -383,6 +403,19 @@ LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnitImplicit<STORAGE_TYP
 	return LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>();
 }
 
+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<STORAGE_TYPE, UNIT_TYPE>(first.value() * 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<STORAGE_TYPE, UNIT_TYPE>(first * second.value());
+}
+
+
 //
 // operator /
 //
@@ -416,6 +449,18 @@ STORAGE_TYPE1 operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUni
 	return STORAGE_TYPE1(first.value() / first.convert(second));
 }
 
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+STORAGE_TYPE1 operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	return STORAGE_TYPE1(first.value() / first.convert(second));
+}
+
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+STORAGE_TYPE1 operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	return STORAGE_TYPE1(first.value() / first.convert(second));
+}
+
 #define COMPARISON_OPERATORS(op)                                                                                     \
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE>                                            \
 bool operator op (SCALAR_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)                                         \
@@ -591,6 +636,7 @@ LL_DECLARE_DERIVED_UNIT(Mibibits, * 1024,		Gibibits, "Gib");
 LL_DECLARE_BASE_UNIT(Seconds, "s");
 LL_DECLARE_DERIVED_UNIT(Seconds, * 60,			Minutes, "min");
 LL_DECLARE_DERIVED_UNIT(Minutes, * 60,			Hours, "h");
+LL_DECLARE_DERIVED_UNIT(Hours, * 24,			Days, "d");
 LL_DECLARE_DERIVED_UNIT(Seconds, / 1000,		Milliseconds, "ms");
 LL_DECLARE_DERIVED_UNIT(Milliseconds, / 1000,	Microseconds, "\x09\x3cs");
 LL_DECLARE_DERIVED_UNIT(Microseconds, / 1000,	Nanoseconds, "ns");
diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h
deleted file mode 100755
index ef68a0eaf5..0000000000
--- a/indra/llcommon/llversionserver.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/** 
- * @file llversionserver.h
- * @brief
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLVERSIONSERVER_H
-#define LL_LLVERSIONSERVER_H
-
-const S32 LL_VERSION_MAJOR = 2;
-const S32 LL_VERSION_MINOR = 1;
-const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 264760;
-
-const char * const LL_CHANNEL = "Second Life Server";
-
-
-#endif
diff --git a/indra/llcommon/roles_constants.h b/indra/llcommon/roles_constants.h
deleted file mode 100755
index effd15ea72..0000000000
--- a/indra/llcommon/roles_constants.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/** 
- * @file roles_constants.h
- * @brief General Roles Constants
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_ROLES_CONSTANTS_H
-#define LL_ROLES_CONSTANTS_H
-
-// This value includes the everyone group.
-const S32 MAX_ROLES = 10;
-
-enum LLRoleMemberChangeType
-{
-	RMC_ADD,
-	RMC_REMOVE,
-	RMC_NONE
-};
-
-enum LLRoleChangeType
-{
-	RC_UPDATE_NONE,
-	RC_UPDATE_DATA,
-	RC_UPDATE_POWERS,
-	RC_UPDATE_ALL,
-	RC_CREATE,
-	RC_DELETE
-};
-
-//
-// Powers
-//
-
-// KNOWN HOLES: use these for any single bit powers you need
-// bit 0x1 << 46
-// bit 0x1 << 49 and above
-
-// These powers were removed to make group roles simpler
-// bit 0x1 << 41 (GP_ACCOUNTING_VIEW)
-// bit 0x1 << 46 (GP_PROPOSAL_VIEW)
-
-const U64 GP_NO_POWERS = 0x0;
-const U64 GP_ALL_POWERS = 0xFFFFFFFFFFFFFFFFLL;
-
-// Membership
-const U64 GP_MEMBER_INVITE		= 0x1 << 1;		// Invite member
-const U64 GP_MEMBER_EJECT			= 0x1 << 2;		// Eject member from group
-const U64 GP_MEMBER_OPTIONS		= 0x1 << 3;		// Toggle "Open enrollment" and change "Signup Fee"
-const U64 GP_MEMBER_VISIBLE_IN_DIR = 0x1LL << 47;
-
-// Roles
-const U64 GP_ROLE_CREATE			= 0x1 << 4;		// Create new roles
-const U64 GP_ROLE_DELETE			= 0x1 << 5;		// Delete roles
-const U64 GP_ROLE_PROPERTIES		= 0x1 << 6;		// Change Role Names, Titles, and Descriptions (Of roles the user is in, only, or any role in group?)
-const U64 GP_ROLE_ASSIGN_MEMBER_LIMITED = 0x1 << 7; // Assign Member to a Role that the assigner is in
-const U64 GP_ROLE_ASSIGN_MEMBER	= 0x1 << 8;		// Assign Member to Role
-const U64 GP_ROLE_REMOVE_MEMBER	= 0x1 << 9;		// Remove Member from Role
-const U64 GP_ROLE_CHANGE_ACTIONS	= 0x1 << 10;	// Change actions a role can perform
-
-// Group Identity
-const U64 GP_GROUP_CHANGE_IDENTITY = 0x1 << 11;	// Charter, insignia, 'Show In Group List', 'Publish on the web', 'Mature', all 'Show Member In Group Profile' checkboxes
-
-// Parcel Management
-const U64 GP_LAND_DEED			= 0x1 << 12;	// Deed Land and Buy Land for Group
-const U64 GP_LAND_RELEASE			= 0x1 << 13;	// Release Land (to Gov. Linden)
-const U64 GP_LAND_SET_SALE_INFO	= 0x1 << 14;	// Set for sale info (Toggle "For Sale", Set Price, Set Target, Toggle "Sell objects with the land")
-const U64 GP_LAND_DIVIDE_JOIN		= 0x1 << 15;	// Divide and Join Parcels
-
-// Parcel Identity
-const U64 GP_LAND_FIND_PLACES		= 0x1 << 17;	// Toggle "Show in Find Places" and Set Category.
-const U64 GP_LAND_CHANGE_IDENTITY = 0x1 << 18;	// Change Parcel Identity: Parcel Name, Parcel Description, Snapshot, 'Publish on the web', and 'Mature' checkbox
-const U64 GP_LAND_SET_LANDING_POINT = 0x1 << 19;	// Set Landing Point
-
-// Parcel Settings
-const U64 GP_LAND_CHANGE_MEDIA	= 0x1 << 20;	// Change Media Settings
-const U64 GP_LAND_EDIT			= 0x1 << 21;	// Toggle Edit Land
-const U64 GP_LAND_OPTIONS			= 0x1 << 22;	// Toggle Set Home Point, Fly, Outside Scripts, Create/Edit Objects, Landmark, and Damage checkboxes
-
-// Parcel Powers
-const U64 GP_LAND_ALLOW_EDIT_LAND = 0x1 << 23;	// Bypass Edit Land Restriction
-const U64 GP_LAND_ALLOW_FLY		= 0x1 << 24;	// Bypass Fly Restriction
-const U64 GP_LAND_ALLOW_CREATE	= 0x1 << 25;	// Bypass Create/Edit Objects Restriction
-const U64 GP_LAND_ALLOW_LANDMARK	= 0x1 << 26;	// Bypass Landmark Restriction
-const U64 GP_LAND_ALLOW_SET_HOME	= 0x1 << 28;	// Bypass Set Home Point Restriction
-const U64 GP_LAND_ALLOW_HOLD_EVENT	= 0x1LL << 41;	// Allowed to hold events on group-owned land
-
-
-// Parcel Access
-const U64 GP_LAND_MANAGE_ALLOWED	= 0x1 << 29;	// Manage Allowed List
-const U64 GP_LAND_MANAGE_BANNED	= 0x1 << 30;	// Manage Banned List
-const U64 GP_LAND_MANAGE_PASSES	= 0x1LL << 31;	// Change Sell Pass Settings
-const U64 GP_LAND_ADMIN			= 0x1LL << 32;	// Eject and Freeze Users on the land
-
-// Parcel Content
-const U64 GP_LAND_RETURN_GROUP_SET	= 0x1LL << 33;	// Return objects on parcel that are set to group
-const U64 GP_LAND_RETURN_NON_GROUP	= 0x1LL << 34;	// Return objects on parcel that are not set to group
-const U64 GP_LAND_RETURN_GROUP_OWNED= 0x1LL << 48;	// Return objects on parcel that are owned by the group
-
-// Select a power-bit based on an object's relationship to a parcel.
-const U64 GP_LAND_RETURN		= GP_LAND_RETURN_GROUP_OWNED 
-								| GP_LAND_RETURN_GROUP_SET	
-								| GP_LAND_RETURN_NON_GROUP;
-
-const U64 GP_LAND_GARDENING		= 0x1LL << 35;	// Parcel Gardening - plant and move linden trees
-
-// Object Management
-const U64 GP_OBJECT_DEED			= 0x1LL << 36;	// Deed Object
-const U64 GP_OBJECT_MANIPULATE		= 0x1LL << 38;	// Manipulate Group Owned Objects (Move, Copy, Mod)
-const U64 GP_OBJECT_SET_SALE		= 0x1LL << 39;	// Set Group Owned Object for Sale
-
-// Accounting
-const U64 GP_ACCOUNTING_ACCOUNTABLE = 0x1LL << 40;	// Pay Group Liabilities and Receive Group Dividends
-
-// Notices
-const U64 GP_NOTICES_SEND			= 0x1LL << 42;	// Send Notices
-const U64 GP_NOTICES_RECEIVE		= 0x1LL << 43;	// Receive Notices and View Notice History
-
-// Proposals
-// TODO: _DEPRECATED suffix as part of vote removal - DEV-24856:
-const U64 GP_PROPOSAL_START		= 0x1LL << 44;	// Start Proposal
-// TODO: _DEPRECATED suffix as part of vote removal - DEV-24856:
-const U64 GP_PROPOSAL_VOTE		= 0x1LL << 45;	// Vote on Proposal
-
-// Group chat moderation related
-const U64 GP_SESSION_JOIN = 0x1LL << 16; //can join session
-const U64 GP_SESSION_VOICE = 0x1LL << 27; //can hear/talk
-const U64 GP_SESSION_MODERATOR = 0x1LL << 37; //can mute people's session
-
-const U64 GP_DEFAULT_MEMBER = GP_ACCOUNTING_ACCOUNTABLE
-								| GP_LAND_ALLOW_SET_HOME
-								| GP_NOTICES_RECEIVE
-								| GP_SESSION_JOIN
-								| GP_SESSION_VOICE
-								;
-
-const U64 GP_DEFAULT_OFFICER = GP_DEFAULT_MEMBER // Superset of GP_DEFAULT_MEMBER
-								| GP_GROUP_CHANGE_IDENTITY
-								| GP_LAND_ADMIN
-								| GP_LAND_ALLOW_EDIT_LAND
-								| GP_LAND_ALLOW_FLY
-								| GP_LAND_ALLOW_CREATE
-								| GP_LAND_ALLOW_LANDMARK
-								| GP_LAND_CHANGE_IDENTITY
-								| GP_LAND_CHANGE_MEDIA
-								| GP_LAND_DEED
-								| GP_LAND_DIVIDE_JOIN
-								| GP_LAND_EDIT
-								| GP_LAND_FIND_PLACES
-								| GP_LAND_GARDENING
-								| GP_LAND_MANAGE_ALLOWED
-								| GP_LAND_MANAGE_BANNED
-								| GP_LAND_MANAGE_PASSES
-								| GP_LAND_OPTIONS
-								| GP_LAND_RELEASE
-								| GP_LAND_RETURN_GROUP_OWNED
-								| GP_LAND_RETURN_GROUP_SET
-								| GP_LAND_RETURN_NON_GROUP
-								| GP_LAND_SET_LANDING_POINT
-								| GP_LAND_SET_SALE_INFO
-								| GP_MEMBER_EJECT
-								| GP_MEMBER_INVITE	
-								| GP_MEMBER_OPTIONS
-								| GP_MEMBER_VISIBLE_IN_DIR
-								| GP_NOTICES_SEND
-								| GP_OBJECT_DEED
-								| GP_OBJECT_MANIPULATE
-								| GP_OBJECT_SET_SALE
-								| GP_ROLE_ASSIGN_MEMBER_LIMITED
-								| GP_ROLE_PROPERTIES
-								| GP_SESSION_MODERATOR
-								;
-#endif
diff --git a/indra/llcommon/stdenums.h b/indra/llcommon/stdenums.h
deleted file mode 100755
index efcbe76795..0000000000
--- a/indra/llcommon/stdenums.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/** 
- * @file stdenums.h
- * @brief Enumerations for indra.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_STDENUMS_H
-#define LL_STDENUMS_H
-
-//----------------------------------------------------------------------------
-// DEPRECATED - create new, more specific files for shared enums/constants
-//----------------------------------------------------------------------------
-
-// this enum is used by the llview.h (viewer) and the llassetstorage.h (viewer and sim) 
-enum EDragAndDropType
-{
-	DAD_NONE			= 0,
-	DAD_TEXTURE			= 1,
-	DAD_SOUND			= 2,
-	DAD_CALLINGCARD		= 3,
-	DAD_LANDMARK		= 4,
-	DAD_SCRIPT			= 5,
-	DAD_CLOTHING 		= 6,
-	DAD_OBJECT			= 7,
-	DAD_NOTECARD		= 8,
-	DAD_CATEGORY		= 9,
-	DAD_ROOT_CATEGORY 	= 10,
-	DAD_BODYPART		= 11,
-	DAD_ANIMATION		= 12,
-	DAD_GESTURE			= 13,
-	DAD_LINK			= 14,
-	DAD_MESH            = 15,
-	DAD_WIDGET          = 16,
-	DAD_PERSON          = 17,
-	DAD_COUNT           = 18,   // number of types in this enum
-};
-
-// Reasons for drags to be denied.
-// ordered by priority for multi-drag
-enum EAcceptance
-{
-	ACCEPT_POSTPONED,	// we are asynchronously determining acceptance
-	ACCEPT_NO,			// Uninformative, general purpose denial.
-	ACCEPT_NO_LOCKED,	// Operation would be valid, but permissions are set to disallow it.
-	ACCEPT_YES_COPY_SINGLE,	// We'll take a copy of a single item
-	ACCEPT_YES_SINGLE,		// Accepted. OK to drag and drop single item here.
-	ACCEPT_YES_COPY_MULTI,	// We'll take a copy of multiple items
-	ACCEPT_YES_MULTI		// Accepted. OK to drag and drop multiple items here.
-};
-
-// This is used by the DeRezObject message to determine where to put
-// derezed tasks.
-enum EDeRezDestination
-{
-	DRD_SAVE_INTO_AGENT_INVENTORY = 0,
-	DRD_ACQUIRE_TO_AGENT_INVENTORY = 1,		// try to leave copy in world
-	DRD_SAVE_INTO_TASK_INVENTORY = 2,
-	DRD_ATTACHMENT = 3,
-	DRD_TAKE_INTO_AGENT_INVENTORY = 4,		// delete from world
-	DRD_FORCE_TO_GOD_INVENTORY = 5,			// force take copy
-	DRD_TRASH = 6,
-	DRD_ATTACHMENT_TO_INV = 7,
-	DRD_ATTACHMENT_EXISTS = 8,
-	DRD_RETURN_TO_OWNER = 9,				// back to owner's inventory
-	DRD_RETURN_TO_LAST_OWNER = 10,			// deeded object back to last owner's inventory
-
-	DRD_COUNT = 11
-};
-
-
-// This is used by the return to owner code to determine the reason
-// that this object is being returned.
-enum EReturnReason
-{
-	RR_GENERIC = 0,
-	RR_SANDBOX = 1,
-	RR_PARCEL_OWNER = 2,
-	RR_PARCEL_AUTO = 3,
-	RR_PARCEL_FULL = 4,
-	RR_OFF_WORLD = 5,
-	
-	RR_COUNT = 6
-};
-
-// This is used for filling in the first byte of the ExtraID field of
-// the ObjectProperties message.
-enum EObjectPropertiesExtraID
-{
-	OPEID_NONE = 0,
-	OPEID_ASSET_ID = 1,
-	OPEID_FROM_TASK_ID = 2,
-
-	OPEID_COUNT = 3
-};
-
-enum EAddPosition
-{
-	ADD_TOP,
-	ADD_BOTTOM,
-	ADD_DEFAULT
-};
-
-enum LLGroupChange
-{
-	GC_PROPERTIES,
-	GC_MEMBER_DATA,
-	GC_ROLE_DATA,
-	GC_ROLE_MEMBER_DATA,
-	GC_TITLES,
-	GC_ALL
-};
-
-//----------------------------------------------------------------------------
-// DEPRECATED - create new, more specific files for shared enums/constants
-//----------------------------------------------------------------------------
-
-#endif
diff --git a/indra/llcommon/string_table.h b/indra/llcommon/string_table.h
deleted file mode 100755
index fe6416fb50..0000000000
--- a/indra/llcommon/string_table.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/** 
- * @file string_table.h
- * @brief Legacy wrapper header.
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-#include "llstringtable.h"
diff --git a/indra/llcommon/tests/bitpack_test.cpp b/indra/llcommon/tests/bitpack_test.cpp
index afc0c18cd0..9bfd567068 100755
--- a/indra/llcommon/tests/bitpack_test.cpp
+++ b/indra/llcommon/tests/bitpack_test.cpp
@@ -28,7 +28,7 @@
  
 #include "linden_common.h"
 
-#include "../bitpack.h"
+#include "../llbitpack.h"
 
 #include "../test/lltut.h"
 
diff --git a/indra/llcommon/timing.h b/indra/llcommon/timing.h
deleted file mode 100755
index c408d4c446..0000000000
--- a/indra/llcommon/timing.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/** 
- * @file timing.h
- * @brief Cross-platform routines for doing timing.
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_TIMING_H					
-#define LL_TIMING_H
-
-
-#if LL_LINUX || LL_DARWIN || LL_SOLARIS
-#include <sys/time.h>
-#endif
-
-
-const F32 SEC_TO_MICROSEC = 1000000.f;
-const U64 SEC_TO_MICROSEC_U64 = 1000000;
-const U32 SEC_PER_DAY = 86400;
-
-// functionality has been moved lltimer.{cpp,h}.  This file will be deprecated in the future.
-
-#endif
-- 
cgit v1.2.3


From 910874a7e32bdfc456474e2d0ee84d190be3011e Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 30 Jul 2013 19:14:19 -0700
Subject: more cleanup

---
 indra/llcommon/llclickaction.h | 30 ++++++++++++++++++++++++++++++
 indra/llcommon/llerror.cpp     |  2 --
 indra/llcommon/llstatenums.h   | 31 +++++++++++++++++++++++++++++++
 3 files changed, 61 insertions(+), 2 deletions(-)
 create mode 100644 indra/llcommon/llclickaction.h
 create mode 100644 indra/llcommon/llstatenums.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llclickaction.h b/indra/llcommon/llclickaction.h
new file mode 100644
index 0000000000..2f83113af9
--- /dev/null
+++ b/indra/llcommon/llclickaction.h
@@ -0,0 +1,30 @@
+/** 
+ * @file llclickaction.h
+ * @author James Cook
+ * @brief Constants for single-click actions on objects
+ *
+ * $LicenseInfo:firstyear=2006&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLCLICKACTION_H
+#define LL_LLCLICKACTION_H
+#endif
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 6da9df4dce..947aa11e94 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -113,8 +113,6 @@ namespace {
 									const std::string& message)
 		{
 			mFile << message << std::endl;
-			// mFile.flush();
-				// *FIX: should we do this? 
 		}
 	
 	private:
diff --git a/indra/llcommon/llstatenums.h b/indra/llcommon/llstatenums.h
new file mode 100644
index 0000000000..6515a3e3cb
--- /dev/null
+++ b/indra/llcommon/llstatenums.h
@@ -0,0 +1,31 @@
+/** 
+ * @file llstatenums.h
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSTATENUMS_H
+#define LL_LLSTATENUMS_H
+
+
+
+#endif
-- 
cgit v1.2.3


From bcb2c23c6695f6b600a2f8b480596b8f2a10c368 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 30 Jul 2013 19:49:10 -0700
Subject: BUILDFIX: fixes use of variadic macros for gcc (use ##__VA_ARGS__ to
 do comma removal)

---
 indra/llcommon/llerror.h | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index d7dc38a4c6..40495b8c7d 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -302,13 +302,13 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 // See top of file for common usage.	
 /////////////////////////////////
 
-#define lllog(level, once, ...)																	   \
-	do {                                                                                           \
-		static LLError::CallSite _site(                                                            \
-			level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, __VA_ARGS__ );\
-		if (LL_UNLIKELY(_site.shouldLog()))			                                               \
-		{                                                                                          \
-			std::ostringstream* _out = LLError::Log::out();                                        \
+#define lllog(level, once, ...)																	     \
+	do {                                                                                             \
+		static LLError::CallSite _site(                                                              \
+		    level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, ##__VA_ARGS__ );\
+		if (LL_UNLIKELY(_site.shouldLog()))			                                                 \
+		{                                                                                            \
+			std::ostringstream* _out = LLError::Log::out();                                          \
 			(*_out)
 
 //Use this construct if you need to do computation in the middle of a
@@ -337,16 +337,16 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 // NEW Macros for debugging, allow the passing of a string tag
 
 // Pass comma separated list of tags (currently only supports up to 0, 1, or 2)
-#define LL_DEBUGS(...)	lllog(LLError::LEVEL_DEBUG, false, __VA_ARGS__)
-#define LL_INFOS(...)	lllog(LLError::LEVEL_INFO, false, __VA_ARGS__)
-#define LL_WARNS(...)	lllog(LLError::LEVEL_WARN, false, __VA_ARGS__)
-#define LL_ERRS(...)	lllog(LLError::LEVEL_ERROR, false, __VA_ARGS__)
+#define LL_DEBUGS(...)	lllog(LLError::LEVEL_DEBUG, false, ##__VA_ARGS__)
+#define LL_INFOS(...)	lllog(LLError::LEVEL_INFO, false, ##__VA_ARGS__)
+#define LL_WARNS(...)	lllog(LLError::LEVEL_WARN, false, ##__VA_ARGS__)
+#define LL_ERRS(...)	lllog(LLError::LEVEL_ERROR, false, ##__VA_ARGS__)
 
 // Only print the log message once (good for warnings or infos that would otherwise
 // spam the log file over and over, such as tighter loops).
-#define LL_DEBUGS_ONCE(...)	lllog(LLError::LEVEL_DEBUG, true, __VA_ARGS__)
-#define LL_INFOS_ONCE(...)	lllog(LLError::LEVEL_INFO, true, __VA_ARGS__)
-#define LL_WARNS_ONCE(...)	lllog(LLError::LEVEL_WARN, true, __VA_ARGS__)
+#define LL_DEBUGS_ONCE(...)	lllog(LLError::LEVEL_DEBUG, true, ##__VA_ARGS__)
+#define LL_INFOS_ONCE(...)	lllog(LLError::LEVEL_INFO, true, ##__VA_ARGS__)
+#define LL_WARNS_ONCE(...)	lllog(LLError::LEVEL_WARN, true, ##__VA_ARGS__)
 
 
 // DEPRECATED: Use the new macros that allow tags and *look* like macros.
-- 
cgit v1.2.3


From e8aa0c493b66dd414ef75ddb3fb1c77875b0c42d Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 30 Jul 2013 19:50:37 -0700
Subject: BUILDFIX: some gcc build fixes

---
 indra/llcommon/llframetimer.h | 2 +-
 indra/llcommon/llrefcount.h   | 2 +-
 indra/llcommon/lltimer.cpp    | 2 --
 3 files changed, 2 insertions(+), 4 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llframetimer.h b/indra/llcommon/llframetimer.h
index 7f61861072..d64009440c 100755
--- a/indra/llcommon/llframetimer.h
+++ b/indra/llcommon/llframetimer.h
@@ -52,7 +52,7 @@ public:
 	// Return a low precision usec since epoch
 	static U64 getTotalTime()
 	{
-		return sTotalTime ? sTotalTime : totalTime();
+		return sTotalTime ? LLUnitImplicit<U64, LLUnits::Microseconds>(sTotalTime) : totalTime();
 	}
 
 	// Return a low precision seconds since epoch
diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h
index 3e472d0766..3d59e48f74 100755
--- a/indra/llcommon/llrefcount.h
+++ b/indra/llcommon/llrefcount.h
@@ -62,7 +62,7 @@ public:
 	inline S32 unref() const
 	{
 		llassert(mRef >= 1);
-		if (0 == --mRef) 
+		if (0 == --mRef)
 		{
 			delete this; 
 			return 0;
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 8f5a886a37..f27c433ee1 100755
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -203,8 +203,6 @@ F64 calc_clock_frequency(unsigned int uiMeasureMSecs)
 	return 1000000.0; // microseconds, so 1 MHz.
 }
 
-const U64 SEC_TO_MICROSEC_U64 = 1000000;
-
 U64 get_clock_count()
 {
 	// Linux clocks are in microseconds
-- 
cgit v1.2.3


From bd5808765f7a74226d312afbb863c471528b8d1a Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 31 Jul 2013 19:32:50 -0700
Subject: cleanup - renamed valueAs to valueInUnits and made it a symmetrical
 getter/setter

---
 indra/llcommon/llfasttimer.cpp |  2 +-
 indra/llcommon/llunit.h        | 15 +++++++++++++--
 2 files changed, 14 insertions(+), 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 6f046c18ff..f4c87ab6f6 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -397,7 +397,7 @@ void TimeBlock::dumpCurTimes()
 		}
 
 		out_str << timerp->getName() << " " 
-			<< std::setprecision(3) << total_time.valueAs<LLUnits::Milliseconds>() << " ms, "
+			<< std::setprecision(3) << total_time.valueInUnits<LLUnits::Milliseconds>() << " ms, "
 			<< num_calls << " calls";
 
 		llinfos << out_str.str() << llendl;
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 781a4ab731..2e4c0de28f 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -74,10 +74,21 @@ struct LLUnit
 		return mValue;
 	}
 
+	void value(storage_t value)
+	{
+		mValue = value;
+	}
+
+	template<typename NEW_UNIT_TYPE> 
+	storage_t valueInUnits()
+	{
+		return LLUnit<storage_t, NEW_UNIT_TYPE>(*this).value();
+	}
+
 	template<typename NEW_UNIT_TYPE> 
-	STORAGE_TYPE valueAs()
+	void valueInUnits(storage_t value)
 	{
-		return LLUnit<STORAGE_TYPE, NEW_UNIT_TYPE>(*this).value();
+		*this = LLUnit<storage_t, NEW_UNIT_TYPE>(value);
 	}
 
 	void operator += (storage_t value)
-- 
cgit v1.2.3


From f58eb60b1e0bbdf2148255c61100cbc20d1ba1b0 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 1 Aug 2013 08:17:21 -0700
Subject: SH-4374 WIP Interesting: Statistics Object cache hit rate is always
 100%

---
 indra/llcommon/lltracerecording.cpp | 17 ++++++++++++++---
 indra/llcommon/lltracerecording.h   |  1 +
 2 files changed, 15 insertions(+), 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 2150a44f12..9fce6c11cc 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -252,6 +252,11 @@ U32 Recording::getSampleCount( const TraceType<CountAccumulator>& stat )
 	return mBuffers->mCounts[stat.getIndex()].getSampleCount();
 }
 
+bool Recording::hasValue(const TraceType<SampleAccumulator>& stat)
+{
+	return mBuffers->mSamples[stat.getIndex()].hasValue();
+}
+
 F64 Recording::getMin( const TraceType<SampleAccumulator>& stat )
 {
 	return mBuffers->mSamples[stat.getIndex()].getMin();
@@ -578,7 +583,10 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, s
 	for (S32 i = 1; i <= num_periods; i++)
 	{
 		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat));
+		if (mRecordingPeriods[index].hasValue(stat))
+		{
+			min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat));
+		}
 	}
 	return min_val;
 }
@@ -592,7 +600,10 @@ F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, si
 	for (S32 i = 1; i <= num_periods; i++)
 	{
 		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		max_val = llmax(max_val, mRecordingPeriods[index].getMax(stat));
+		if (mRecordingPeriods[index].hasValue(stat))
+		{
+			max_val = llmax(max_val, mRecordingPeriods[index].getMax(stat));
+		}
 	}
 	return max_val;
 }
@@ -611,7 +622,7 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat,
 	for (S32 i = 1; i <= num_periods; i++)
 	{
 		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		if (mRecordingPeriods[index].getDuration() > 0.f)
+		if (mRecordingPeriods[index].getDuration() > 0.f && mRecordingPeriods[index].hasValue(stat))
 		{
 			LLUnit<F64, LLUnits::Seconds> recording_duration = mRecordingPeriods[index].getDuration();
 			mean += mRecordingPeriods[index].getMean(stat) * recording_duration.value();
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index f5e4ea603c..51b411b7bd 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -209,6 +209,7 @@ namespace LLTrace
 
 
 		// SampleStatHandle accessors
+		bool hasValue(const TraceType<SampleAccumulator>& stat);
 		F64 getMin(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
 		T getMin(const SampleStatHandle<T>& stat)
-- 
cgit v1.2.3


From 8d3daa141e9ea14f533559843d77ab5c0f715421 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 9 Aug 2013 16:14:19 -0700
Subject: SH-4374 FIX Interesting: Statistics Object cache hit rate is always
 100% moved object cache sampling code so that it actually gets executed
 default values for stats are NaN instead of 0 in many cases

---
 indra/llcommon/llfasttimer.cpp         |   4 +-
 indra/llcommon/lltraceaccumulators.cpp | 146 +++++++++++++++--
 indra/llcommon/lltraceaccumulators.h   | 291 +++++++++++----------------------
 indra/llcommon/lltracerecording.cpp    |  42 +++--
 indra/llcommon/lltracerecording.h      |   2 +
 5 files changed, 267 insertions(+), 218 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index f4c87ab6f6..3b17b6022c 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -431,11 +431,11 @@ TimeBlockAccumulator::TimeBlockAccumulator()
 	mParent(NULL)
 {}
 
-void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other, bool append )
+void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other, EBufferAppendType append_type )
 {
 	// we can't merge two unrelated time block samples, as that will screw with the nested timings
 	// due to the call hierarchy of each thread
-	llassert(append);
+	llassert(append_type == SEQUENTIAL);
 	mTotalTimeCounter += other.mTotalTimeCounter - other.mStartTotalTimeCounter;
 	mSelfTimeCounter += other.mSelfTimeCounter;
 	mCalls += other.mCalls;
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index 950c1d97d1..a632f5634c 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -86,21 +86,21 @@ bool AccumulatorBufferGroup::isPrimary() const
 
 void AccumulatorBufferGroup::append( const AccumulatorBufferGroup& other )
 {
-	mCounts.addSamples(other.mCounts);
-	mSamples.addSamples(other.mSamples);
-	mEvents.addSamples(other.mEvents);
-	mMemStats.addSamples(other.mMemStats);
-	mStackTimers.addSamples(other.mStackTimers);
+	mCounts.addSamples(other.mCounts, SEQUENTIAL);
+	mSamples.addSamples(other.mSamples, SEQUENTIAL);
+	mEvents.addSamples(other.mEvents, SEQUENTIAL);
+	mMemStats.addSamples(other.mMemStats, SEQUENTIAL);
+	mStackTimers.addSamples(other.mStackTimers, SEQUENTIAL);
 }
 
 void AccumulatorBufferGroup::merge( const AccumulatorBufferGroup& other)
 {
-	mCounts.addSamples(other.mCounts, false);
-	mSamples.addSamples(other.mSamples, false);
-	mEvents.addSamples(other.mEvents, false);
-	mMemStats.addSamples(other.mMemStats, false);
+	mCounts.addSamples(other.mCounts, NON_SEQUENTIAL);
+	mSamples.addSamples(other.mSamples, NON_SEQUENTIAL);
+	mEvents.addSamples(other.mEvents, NON_SEQUENTIAL);
+	mMemStats.addSamples(other.mMemStats, NON_SEQUENTIAL);
 	// for now, hold out timers from merge, need to be displayed per thread
-	//mStackTimers.addSamples(other.mStackTimers, false);
+	//mStackTimers.addSamples(other.mStackTimers, NON_SEQUENTIAL);
 }
 
 void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other)
@@ -120,4 +120,130 @@ void AccumulatorBufferGroup::sync()
 	mMemStats.sync(time_stamp);
 }
 
+void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppendType append_type )
+{
+	if (!mHasValue)
+	{
+		*this = other;
+
+		if (append_type == NON_SEQUENTIAL)
+		{
+			// restore own last value state
+			mLastValue = NaN;
+			mHasValue = false;
+		}
+	}
+	else if (other.mHasValue)
+	{
+		mSum += other.mSum;
+
+		if (other.mMin < mMin) { mMin = other.mMin; }
+		if (other.mMax > mMax) { mMax = other.mMax; }
+
+		F64 epsilon = 0.0000001;
+
+		if (other.mTotalSamplingTime > epsilon)
+		{
+			// combine variance (and hence standard deviation) of 2 different sized sample groups using
+			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+			F64 n_1 = mTotalSamplingTime,
+				n_2 = other.mTotalSamplingTime;
+			F64 m_1 = mMean,
+				m_2 = other.mMean;
+			F64 v_1 = mSumOfSquares / mTotalSamplingTime,
+				v_2 = other.mSumOfSquares / other.mTotalSamplingTime;
+			if (n_1 < epsilon)
+			{
+				mSumOfSquares = other.mSumOfSquares;
+			}
+			else
+			{
+				mSumOfSquares =	mTotalSamplingTime
+					* ((((n_1 - epsilon) * v_1)
+					+ ((n_2 - epsilon) * v_2)
+					+ (((n_1 * n_2) / (n_1 + n_2))
+					* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+					/ (n_1 + n_2 - epsilon));
+			}
+
+			llassert(other.mTotalSamplingTime > 0);
+			F64 weight = mTotalSamplingTime / (mTotalSamplingTime + other.mTotalSamplingTime);
+			mNumSamples += other.mNumSamples;
+			mTotalSamplingTime += other.mTotalSamplingTime;
+			mMean = (mMean * weight) + (other.mMean * (1.0 - weight));
+		}
+		if (append_type == SEQUENTIAL)
+		{
+			mLastValue = other.mLastValue;
+			mLastSampleTimeStamp = other.mLastSampleTimeStamp;
+			mHasValue = true;
+		}
+	}
+}
+
+void SampleAccumulator::reset( const SampleAccumulator* other )
+{
+	mLastValue = other ? other->mLastValue : NaN;
+	mHasValue = other ? other->mHasValue : false;
+	mNumSamples = 0;
+	mSum = 0;
+	mMin = mLastValue;
+	mMax = mLastValue;
+	mMean = mLastValue;
+	mSumOfSquares = 0;
+	mLastSampleTimeStamp = LLTimer::getTotalSeconds();
+	mTotalSamplingTime = 0;
+}
+
+void EventAccumulator::addSamples( const EventAccumulator& other, EBufferAppendType append_type )
+{
+	if (other.mNumSamples)
+	{
+		if (!mNumSamples)
+		{
+			*this = other;
+		}
+		else
+		{
+			mSum += other.mSum;
+
+			// NOTE: both conditions will hold first time through
+			if (other.mMin < mMin) { mMin = other.mMin; }
+			if (other.mMax > mMax) { mMax = other.mMax; }
+
+			// combine variance (and hence standard deviation) of 2 different sized sample groups using
+			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+			F64 n_1 = (F64)mNumSamples,
+				n_2 = (F64)other.mNumSamples;
+			F64 m_1 = mMean,
+				m_2 = other.mMean;
+			F64 v_1 = mSumOfSquares / mNumSamples,
+				v_2 = other.mSumOfSquares / other.mNumSamples;
+			mSumOfSquares = (F64)mNumSamples
+				* ((((n_1 - 1.f) * v_1)
+				+ ((n_2 - 1.f) * v_2)
+				+ (((n_1 * n_2) / (n_1 + n_2))
+				* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+				/ (n_1 + n_2 - 1.f));
+
+			F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
+			mNumSamples += other.mNumSamples;
+			mMean = mMean * weight + other.mMean * (1.f - weight);
+			if (append_type == SEQUENTIAL) mLastValue = other.mLastValue;
+		}
+	}
+}
+
+void EventAccumulator::reset( const EventAccumulator* other )
+{
+	mNumSamples = 0;
+	mSum = NaN;
+	mMin = NaN;
+	mMax = NaN;
+	mMean = NaN;
+	mSumOfSquares = 0;
+	mLastValue = other ? other->mLastValue : NaN;
+}
+
+
 }
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 9ea787188c..5871dc4bea 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -38,6 +38,14 @@
 
 namespace LLTrace
 {
+	const F64 NaN	= std::numeric_limits<double>::quiet_NaN();
+
+	enum EBufferAppendType
+	{
+		SEQUENTIAL,
+		NON_SEQUENTIAL
+	};
+
 	template<typename ACCUMULATOR>
 	class AccumulatorBuffer : public LLRefCount
 	{
@@ -83,12 +91,12 @@ namespace LLTrace
 			return mStorage[index]; 
 		}
 
-		void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, bool append = true)
+		void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, EBufferAppendType append_type)
 		{
 			llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot);
 			for (size_t i = 0; i < sNextStorageSlot; i++)
 			{
-				mStorage[i].addSamples(other.mStorage[i], append);
+				mStorage[i].addSamples(other.mStorage[i], append_type);
 			}
 		}
 
@@ -211,7 +219,6 @@ namespace LLTrace
 	template<typename ACCUMULATOR> size_t AccumulatorBuffer<ACCUMULATOR>::sNextStorageSlot = 0;
 	template<typename ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>* AccumulatorBuffer<ACCUMULATOR>::sDefaultBuffer = NULL;
 
-
 	class EventAccumulator
 	{
 	public:
@@ -219,98 +226,51 @@ namespace LLTrace
 		typedef F64 mean_t;
 
 		EventAccumulator()
-		:	mSum(0),
-			mMin((std::numeric_limits<F64>::max)()),
-			mMax((std::numeric_limits<F64>::min)()),
-			mMean(0),
+		:	mSum(NaN),
+			mMin(NaN),
+			mMax(NaN),
+			mMean(NaN),
 			mSumOfSquares(0),
 			mNumSamples(0),
-			mLastValue(0)
+			mLastValue(NaN)
 		{}
 
 		void record(F64 value)
 		{
-			mNumSamples++;
-			mSum += value;
-			// NOTE: both conditions will hold on first pass through
-			if (value < mMin)
+			if (mNumSamples == 0)
 			{
+				mSum = value;
+				mMean = value;
 				mMin = value;
-			}
-			if (value > mMax)
-			{
 				mMax = value;
 			}
-			F64 old_mean = mMean;
-			mMean += (value - old_mean) / (F64)mNumSamples;
-			mSumOfSquares += (value - old_mean) * (value - mMean);
-			mLastValue = value;
-		}
-
-		void addSamples(const EventAccumulator& other, bool append)
-		{
-			if (other.mNumSamples)
+			else
 			{
-				mSum += other.mSum;
-
-				// NOTE: both conditions will hold first time through
-				if (other.mMin < mMin) { mMin = other.mMin; }
-				if (other.mMax > mMax) { mMax = other.mMax; }
-
-				// combine variance (and hence standard deviation) of 2 different sized sample groups using
-				// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
-				F64 n_1 = (F64)mNumSamples,
-					n_2 = (F64)other.mNumSamples;
-				F64 m_1 = mMean,
-					m_2 = other.mMean;
-				F64 v_1 = mSumOfSquares / mNumSamples,
-					v_2 = other.mSumOfSquares / other.mNumSamples;
-				if (n_1 == 0)
-				{
-					mSumOfSquares = other.mSumOfSquares;
-				}
-				else if (n_2 == 0)
-				{
-					// don't touch variance
-					// mSumOfSquares = mSumOfSquares;
-				}
-				else
-				{
-					mSumOfSquares = (F64)mNumSamples
-						* ((((n_1 - 1.f) * v_1)
-						+ ((n_2 - 1.f) * v_2)
-						+ (((n_1 * n_2) / (n_1 + n_2))
-						* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
-						/ (n_1 + n_2 - 1.f));
-				}
+				mSum += value;
+				F64 old_mean = mMean;
+				mMean += (value - old_mean) / (F64)mNumSamples;
+				mSumOfSquares += (value - old_mean) * (value - mMean);
 
-				F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
-				mNumSamples += other.mNumSamples;
-				mMean = mMean * weight + other.mMean * (1.f - weight);
-				if (append) mLastValue = other.mLastValue;
+				if (value < mMin) { mMin = value; }
+				else if (value > mMax) { mMax = value; }
 			}
-		}
 
-		void reset(const EventAccumulator* other)
-		{
-			mNumSamples = 0;
-			mSum = 0;
-			mMin = std::numeric_limits<F64>::max();
-			mMax = std::numeric_limits<F64>::min();
-			mMean = 0;
-			mSumOfSquares = 0;
-			mLastValue = other ? other->mLastValue : 0;
+			mNumSamples++;
+			mLastValue = value;
 		}
 
+		void addSamples(const EventAccumulator& other, EBufferAppendType append_type);
+		void reset(const EventAccumulator* other);
 		void sync(LLUnitImplicit<F64, LLUnits::Seconds>) {}
 
-		F64	getSum() const { return mSum; }
-		F64	getMin() const { return mMin; }
-		F64	getMax() const { return mMax; }
-		F64	getLastValue() const { return mLastValue; }
-		F64	getMean() const { return mMean; }
+		F64	getSum() const               { return mSum; }
+		F64	getMin() const               { return mMin; }
+		F64	getMax() const               { return mMax; }
+		F64	getLastValue() const         { return mLastValue; }
+		F64	getMean() const              { return mMean; }
 		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mNumSamples); }
-		U32 getSampleCount() const { return mNumSamples; }
+		U32 getSampleCount() const       { return mNumSamples; }
+		bool hasValue() const			 { return mNumSamples > 0; }
 
 	private:
 		F64	mSum,
@@ -333,143 +293,85 @@ namespace LLTrace
 
 		SampleAccumulator()
 		:	mSum(0),
-			mMin((std::numeric_limits<F64>::max)()),
-			mMax((std::numeric_limits<F64>::min)()),
-			mMean(0),
+			mMin(NaN),
+			mMax(NaN),
+			mMean(NaN),
 			mSumOfSquares(0),
-			mLastSampleTimeStamp(LLTimer::getTotalSeconds()),
+			mLastSampleTimeStamp(0),
 			mTotalSamplingTime(0),
 			mNumSamples(0),
-			mLastValue(0),
+			mLastValue(NaN),
 			mHasValue(false)
 		{}
 
 		void sample(F64 value)
 		{
 			LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds();
-			LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp;
-			mLastSampleTimeStamp = time_stamp;
 
-			if (mHasValue)
+			// store effect of last value
+			sync(time_stamp);
+
+			if (!mHasValue)
 			{
-				mTotalSamplingTime += delta_time;
-				mSum += mLastValue * delta_time;
+				mHasValue = true;
 
-				// NOTE: both conditions will hold first time through
+				mMin = value;
+				mMax = value;
+				mMean = value;
+				mLastSampleTimeStamp = time_stamp;
+			}
+			else
+			{
 				if (value < mMin) { mMin = value; }
-				if (value > mMax) { mMax = value; }
-
-				F64 old_mean = mMean;
-				mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean);
-				mSumOfSquares += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
+				else if (value > mMax) { mMax = value; }
 			}
 
 			mLastValue = value;
 			mNumSamples++;
-			mHasValue = true;
 		}
 
-		void addSamples(const SampleAccumulator& other, bool append)
-		{
-			if (other.mTotalSamplingTime)
-			{
-				mSum += other.mSum;
-
-				// NOTE: both conditions will hold first time through
-				if (other.mMin < mMin) { mMin = other.mMin; }
-				if (other.mMax > mMax) { mMax = other.mMax; }
-
-				// combine variance (and hence standard deviation) of 2 different sized sample groups using
-				// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
-				F64 n_1 = mTotalSamplingTime,
-					n_2 = other.mTotalSamplingTime;
-				F64 m_1 = mMean,
-					m_2 = other.mMean;
-				F64 v_1 = mSumOfSquares / mTotalSamplingTime,
-					v_2 = other.mSumOfSquares / other.mTotalSamplingTime;
-				if (n_1 == 0)
-				{
-					mSumOfSquares = other.mSumOfSquares;
-				}
-				else if (n_2 == 0)
-				{
-					// variance is unchanged
-					// mSumOfSquares = mSumOfSquares;
-				}
-				else
-				{
-					mSumOfSquares =	mTotalSamplingTime
-						* ((((n_1 - 1.f) * v_1)
-						+ ((n_2 - 1.f) * v_2)
-						+ (((n_1 * n_2) / (n_1 + n_2))
-						* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
-						/ (n_1 + n_2 - 1.f));
-				}
-
-				llassert(other.mTotalSamplingTime > 0);
-				F64 weight = mTotalSamplingTime / (mTotalSamplingTime + other.mTotalSamplingTime);
-				mNumSamples += other.mNumSamples;
-				mTotalSamplingTime += other.mTotalSamplingTime;
-				mMean = (mMean * weight) + (other.mMean * (1.0 - weight));
-				if (append)
-				{
-					mLastValue = other.mLastValue;
-					mLastSampleTimeStamp = other.mLastSampleTimeStamp;
-					mHasValue |= other.mHasValue;
-				}
-			}
-		}
-
-		void reset(const SampleAccumulator* other)
-		{
-			mNumSamples = 0;
-			mSum = 0;
-			mMin = std::numeric_limits<F64>::max();
-			mMax = std::numeric_limits<F64>::min();
-			mMean = other ? other->mLastValue : 0;
-			mSumOfSquares = 0;
-			mLastSampleTimeStamp = LLTimer::getTotalSeconds();
-			mTotalSamplingTime = 0;
-			mLastValue = other ? other->mLastValue : 0;
-			mHasValue = other ? other->mHasValue : false;
-		}
+		void addSamples(const SampleAccumulator& other, EBufferAppendType append_type);
+		void reset(const SampleAccumulator* other);
 
 		void sync(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
 		{
-			LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp;
-
 			if (mHasValue)
 			{
+				LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp;
 				mSum += mLastValue * delta_time;
 				mTotalSamplingTime += delta_time;
+				F64 old_mean = mMean;
+				mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean);
+				mSumOfSquares += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
 			}
 			mLastSampleTimeStamp = time_stamp;
 		}
 
-		F64	getSum() const { return mSum; }
-		F64	getMin() const { return mMin; }
-		F64	getMax() const { return mMax; }
-		F64	getLastValue() const { return mLastValue; }
-		F64	getMean() const { return mMean; }
+		F64	getSum() const               { return mSum; }
+		F64	getMin() const               { return mMin; }
+		F64	getMax() const               { return mMax; }
+		F64	getLastValue() const         { return mLastValue; }
+		F64	getMean() const              { return mMean; }
 		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); }
-		U32 getSampleCount() const { return mNumSamples; }
-		bool hasValue() const { return mHasValue; }
+		U32 getSampleCount() const       { return mNumSamples; }
+		bool hasValue() const            { return mHasValue; }
 
 	private:
-		F64	mSum,
-			mMin,
-			mMax,
-			mLastValue;
+		F64		mSum,
+				mMin,
+				mMax,
+				mLastValue;
 
-		bool mHasValue;
+		bool	mHasValue;		// distinct from mNumSamples, since we might have inherited an old sample
 
-		F64	mMean,
-			mSumOfSquares;
+		F64		mMean,
+				mSumOfSquares;
 
-		LLUnitImplicit<F64, LLUnits::Seconds>	mLastSampleTimeStamp,
-			mTotalSamplingTime;
+		LLUnitImplicit<F64, LLUnits::Seconds>	
+				mLastSampleTimeStamp,
+				mTotalSamplingTime;
 
-		U32	mNumSamples;
+		U32		mNumSamples;
 	};
 
 	class CountAccumulator
@@ -489,7 +391,7 @@ namespace LLTrace
 			mSum += value;
 		}
 
-		void addSamples(const CountAccumulator& other, bool /*append*/)
+		void addSamples(const CountAccumulator& other, bool /*follows_in_sequence*/)
 		{
 			mSum += other.mSum;
 			mNumSamples += other.mNumSamples;
@@ -534,25 +436,26 @@ namespace LLTrace
 		};
 
 		TimeBlockAccumulator();
-		void addSamples(const self_t& other, bool /*append*/);
+		void addSamples(const self_t& other, EBufferAppendType append_type);
 		void reset(const self_t* other);
 		void sync(LLUnitImplicit<F64, LLUnits::Seconds>) {}
 
 		//
 		// members
 		//
-		U64							mStartTotalTimeCounter,
-			mTotalTimeCounter,
-			mSelfTimeCounter;
-		U32							mCalls;
-		class TimeBlock*			mParent;		// last acknowledged parent of this time block
-		class TimeBlock*			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
+		U64					mStartTotalTimeCounter,
+							mTotalTimeCounter,
+							mSelfTimeCounter;
+		U32					mCalls;
+		class TimeBlock*	mParent;		// last acknowledged parent of this time block
+		class TimeBlock*	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
 
 	};
 
 	class TimeBlock;
+
 	class TimeBlockTreeNode
 	{
 	public:
@@ -603,10 +506,10 @@ namespace LLTrace
 			mDeallocatedCount(0)
 		{}
 
-		void addSamples(const MemStatAccumulator& other, bool append)
+		void addSamples(const MemStatAccumulator& other, EBufferAppendType append_type)
 		{
-			mSize.addSamples(other.mSize, append);
-			mChildSize.addSamples(other.mChildSize, append);
+			mSize.addSamples(other.mSize, append_type);
+			mChildSize.addSamples(other.mChildSize, append_type);
 			mAllocatedCount += other.mAllocatedCount;
 			mDeallocatedCount += other.mDeallocatedCount;
 		}
@@ -645,11 +548,11 @@ namespace LLTrace
 		void reset(AccumulatorBufferGroup* other = NULL);
 		void sync();
 
-		AccumulatorBuffer<CountAccumulator>	 			mCounts;
-		AccumulatorBuffer<SampleAccumulator>			mSamples;
-		AccumulatorBuffer<EventAccumulator>				mEvents;
-		AccumulatorBuffer<TimeBlockAccumulator> 		mStackTimers;
-		AccumulatorBuffer<MemStatAccumulator> 			mMemStats;
+		AccumulatorBuffer<CountAccumulator>	 	mCounts;
+		AccumulatorBuffer<SampleAccumulator>	mSamples;
+		AccumulatorBuffer<EventAccumulator>		mEvents;
+		AccumulatorBuffer<TimeBlockAccumulator> mStackTimers;
+		AccumulatorBuffer<MemStatAccumulator> 	mMemStats;
 	};
 }
 
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 9fce6c11cc..a4d58d8ab1 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -287,6 +287,11 @@ U32 Recording::getSampleCount( const TraceType<SampleAccumulator>& stat )
 	return mBuffers->mSamples[stat.getIndex()].getSampleCount();
 }
 
+bool Recording::hasValue(const TraceType<EventAccumulator>& stat)
+{
+	return mBuffers->mEvents[stat.getIndex()].hasValue();
+}
+
 F64 Recording::getMin( const TraceType<EventAccumulator>& stat )
 {
 	return mBuffers->mEvents[stat.getIndex()].getMin();
@@ -531,10 +536,12 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, s
 	for (S32 i = 1; i <= num_periods; i++)
 	{
 		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		if (mRecordingPeriods[index].getDuration() > 0.f)
+		Recording& recording = mRecordingPeriods[index];
+
+		if (recording.hasValue(stat))
 		{
-			S32 period_sample_count = mRecordingPeriods[index].getSampleCount(stat);
-			mean += mRecordingPeriods[index].getMean(stat) * period_sample_count;
+			S32 period_sample_count = recording.getSampleCount(stat);
+			mean += recording.getMean(stat) * period_sample_count;
 			total_sample_count += period_sample_count;
 		}
 	}
@@ -555,7 +562,11 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, si
 	for (S32 i = 1; i <= num_periods; i++)
 	{
 		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat));
+		Recording& recording = mRecordingPeriods[index];
+		if (recording.hasValue(stat))
+		{
+			min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat));
+		}
 	}
 	return min_val;
 }
@@ -569,7 +580,11 @@ F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, si
 	for (S32 i = 1; i <= num_periods; i++)
 	{
 		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		max_val = llmax(max_val, mRecordingPeriods[index].getMax(stat));
+		Recording& recording = mRecordingPeriods[index];
+		if (recording.hasValue(stat))
+		{
+			max_val = llmax(max_val, recording.getMax(stat));
+		}
 	}
 	return max_val;
 }
@@ -583,9 +598,10 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, s
 	for (S32 i = 1; i <= num_periods; i++)
 	{
 		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		if (mRecordingPeriods[index].hasValue(stat))
+		Recording& recording = mRecordingPeriods[index];
+		if (recording.hasValue(stat))
 		{
-			min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat));
+			min_val = llmin(min_val, recording.getMin(stat));
 		}
 	}
 	return min_val;
@@ -600,9 +616,10 @@ F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, si
 	for (S32 i = 1; i <= num_periods; i++)
 	{
 		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		if (mRecordingPeriods[index].hasValue(stat))
+		Recording& recording = mRecordingPeriods[index];
+		if (recording.hasValue(stat))
 		{
-			max_val = llmax(max_val, mRecordingPeriods[index].getMax(stat));
+			max_val = llmax(max_val, recording.getMax(stat));
 		}
 	}
 	return max_val;
@@ -622,10 +639,11 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat,
 	for (S32 i = 1; i <= num_periods; i++)
 	{
 		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		if (mRecordingPeriods[index].getDuration() > 0.f && mRecordingPeriods[index].hasValue(stat))
+		Recording& recording = mRecordingPeriods[index];
+		if (recording.hasValue(stat))
 		{
-			LLUnit<F64, LLUnits::Seconds> recording_duration = mRecordingPeriods[index].getDuration();
-			mean += mRecordingPeriods[index].getMean(stat) * recording_duration.value();
+			LLUnit<F64, LLUnits::Seconds> recording_duration = recording.getDuration();
+			mean += recording.getMean(stat) * recording_duration.value();
 			total_duration += recording_duration;
 		}
 	}
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 51b411b7bd..7ee8aba874 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -248,6 +248,8 @@ namespace LLTrace
 		U32 getSampleCount(const TraceType<SampleAccumulator>& stat);
 
 		// EventStatHandle accessors
+		bool hasValue(const TraceType<EventAccumulator>& stat);
+
 		F64 getSum(const TraceType<EventAccumulator>& stat);
 		template <typename T>
 		typename RelatedTypes<T>::sum_t getSum(const EventStatHandle<T>& stat)
-- 
cgit v1.2.3


From e340009fc59d59e59b2e8d903a884acb76b178eb Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 9 Aug 2013 17:11:19 -0700
Subject: second phase summer cleaning replace llinfos, lldebugs, etc with new
 LL_INFOS(), LL_DEBUGS(), etc.

---
 indra/llcommon/llallocator_heap_profile.cpp  |  2 +-
 indra/llcommon/llapp.cpp                     | 56 +++++++++---------
 indra/llcommon/llapr.cpp                     |  4 +-
 indra/llcommon/llbase32.cpp                  |  4 +-
 indra/llcommon/llbitpack.h                   |  4 +-
 indra/llcommon/llcrc.cpp                     |  4 +-
 indra/llcommon/llcrc.h                       |  2 +-
 indra/llcommon/lldate.cpp                    |  4 +-
 indra/llcommon/lldictionary.h                |  2 +-
 indra/llcommon/llerror.cpp                   |  4 +-
 indra/llcommon/llerror.h                     |  8 +--
 indra/llcommon/llerrorthread.cpp             | 24 ++++----
 indra/llcommon/llfasttimer.cpp               |  2 +-
 indra/llcommon/llformat.h                    |  2 +-
 indra/llcommon/llframetimer.cpp              |  8 +--
 indra/llcommon/llheartbeat.cpp               |  8 +--
 indra/llcommon/llliveappconfig.cpp           | 10 ++--
 indra/llcommon/llmemory.cpp                  | 88 ++++++++++++++--------------
 indra/llcommon/llmemorystream.cpp            |  2 +-
 indra/llcommon/llmetricperformancetester.cpp | 10 ++--
 indra/llcommon/llmetrics.cpp                 |  4 +-
 indra/llcommon/llmetrics.h                   |  2 +-
 indra/llcommon/llmutex.cpp                   |  4 +-
 indra/llcommon/llpointer.h                   |  2 +-
 indra/llcommon/llpriqueuemap.h               |  6 +-
 indra/llcommon/llprocessor.cpp               |  2 +-
 indra/llcommon/llqueuedthread.cpp            | 16 ++---
 indra/llcommon/llrefcount.cpp                | 10 ++--
 indra/llcommon/llregistry.h                  |  4 +-
 indra/llcommon/llsafehandle.h                |  2 +-
 indra/llcommon/llsdserialize.cpp             | 68 ++++++++++-----------
 indra/llcommon/llsdserialize_xml.cpp         |  6 +-
 indra/llcommon/llsingleton.h                 |  4 +-
 indra/llcommon/llstring.cpp                  |  4 +-
 indra/llcommon/llsys.cpp                     | 16 ++---
 indra/llcommon/llsys.h                       |  4 +-
 indra/llcommon/llthread.cpp                  | 12 ++--
 indra/llcommon/llthreadlocalstorage.cpp      |  8 +--
 indra/llcommon/llthreadlocalstorage.h        |  4 +-
 indra/llcommon/llthreadsafequeue.cpp         |  2 +-
 indra/llcommon/lltimer.cpp                   |  2 +-
 indra/llcommon/lltrace.cpp                   |  2 +-
 indra/llcommon/lltracethreadrecorder.cpp     |  2 +-
 indra/llcommon/lluri.cpp                     | 12 ++--
 indra/llcommon/lluuid.cpp                    |  8 +--
 indra/llcommon/llworkerthread.cpp            | 24 ++++----
 indra/llcommon/u64.cpp                       |  2 +-
 47 files changed, 240 insertions(+), 240 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llallocator_heap_profile.cpp b/indra/llcommon/llallocator_heap_profile.cpp
index b574ef668b..b2eafde1aa 100755
--- a/indra/llcommon/llallocator_heap_profile.cpp
+++ b/indra/llcommon/llallocator_heap_profile.cpp
@@ -59,7 +59,7 @@ void LLAllocatorHeapProfile::parse(std::string const & prof_text)
     {
         // *TODO - determine if there should be some better error state than
         // mLines being empty. -brad
-        llwarns << "invalid heap profile data passed into parser." << llendl;
+        LL_WARNS() << "invalid heap profile data passed into parser." << LL_ENDL;
         return;
     }
 
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 67a98d5fb8..bd8811040b 100755
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -218,8 +218,8 @@ bool LLApp::parseCommandOptions(int argc, char** argv)
 	{
 		if(argv[ii][0] != '-')
 		{
-			llinfos << "Did not find option identifier while parsing token: "
-				<< argv[ii] << llendl;
+			LL_INFOS() << "Did not find option identifier while parsing token: "
+				<< argv[ii] << LL_ENDL;
 			return false;
 		}
 		int offset = 1;
@@ -303,7 +303,7 @@ void LLApp::setupErrorHandling()
 	// Install the Google Breakpad crash handler for Windows
 	if(mExceptionHandler == 0)
 	{
-		llwarns << "adding breakpad exception handler" << llendl;
+		LL_WARNS() << "adding breakpad exception handler" << LL_ENDL;
 		mExceptionHandler = new google_breakpad::ExceptionHandler(
 			L"C:\\Temp\\", 0, windows_post_minidump_callback, 0, google_breakpad::ExceptionHandler::HANDLER_ALL);
 	}
@@ -378,7 +378,7 @@ void LLApp::startErrorThread()
 	//
 	if(!mThreadErrorp)
 	{
-		llinfos << "Starting error thread" << llendl;
+		LL_INFOS() << "Starting error thread" << LL_ENDL;
 		mThreadErrorp = new LLErrorThread();
 		mThreadErrorp->setUserData((void *) this);
 		mThreadErrorp->start();
@@ -398,7 +398,7 @@ void LLApp::runErrorHandler()
 		LLApp::sErrorHandler();
 	}
 
-	//llinfos << "App status now STOPPED" << llendl;
+	//LL_INFOS() << "App status now STOPPED" << LL_ENDL;
 	LLApp::setStopped();
 }
 
@@ -443,7 +443,7 @@ void LLApp::setQuitting()
 	if (!isExiting())
 	{
 		// If we're already exiting, we don't want to reset our state back to quitting.
-		llinfos << "Setting app state to QUITTING" << llendl;
+		LL_INFOS() << "Setting app state to QUITTING" << LL_ENDL;
 		setStatus(APP_STATUS_QUITTING);
 	}
 }
@@ -551,7 +551,7 @@ LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *except
 
 	if (LLApp::isError())
 	{
-		llwarns << "Got another fatal signal while in the error handler, die now!" << llendl;
+		LL_WARNS() << "Got another fatal signal while in the error handler, die now!" << LL_ENDL;
 		retval = EXCEPTION_EXECUTE_HANDLER;
 		return retval;
 	}
@@ -597,7 +597,7 @@ BOOL ConsoleCtrlHandler(DWORD fdwCtrlType)
 				// We're already trying to die, just ignore this signal
 				if (LLApp::sLogInSignal)
 				{
-					llinfos << "Signal handler - Already trying to quit, ignoring signal!" << llendl;
+					LL_INFOS() << "Signal handler - Already trying to quit, ignoring signal!" << LL_ENDL;
 				}
 				return TRUE;
 			}
@@ -629,8 +629,8 @@ pid_t LLApp::fork()
 	if( pid < 0 )
 	{
 		int system_error = errno;
-		llwarns << "Unable to fork! Operating system error code: "
-				<< system_error << llendl;
+		LL_WARNS() << "Unable to fork! Operating system error code: "
+				<< system_error << LL_ENDL;
 	}
 	else if (pid == 0)
 	{
@@ -643,7 +643,7 @@ pid_t LLApp::fork()
 	}
 	else
 	{
-		llinfos << "Forked child process " << pid << llendl;
+		LL_INFOS() << "Forked child process " << pid << LL_ENDL;
 	}
 	return pid;
 }
@@ -735,7 +735,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
 
 	if (LLApp::sLogInSignal)
 	{
-		llinfos << "Signal handler - Got signal " << signum << " - " << apr_signal_description_get(signum) << llendl;
+		LL_INFOS() << "Signal handler - Got signal " << signum << " - " << apr_signal_description_get(signum) << LL_ENDL;
 	}
 
 
@@ -744,7 +744,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
 	case SIGCHLD:
 		if (LLApp::sLogInSignal)
 		{
-			llinfos << "Signal handler - Got SIGCHLD from " << info->si_pid << llendl;
+			LL_INFOS() << "Signal handler - Got SIGCHLD from " << info->si_pid << LL_ENDL;
 		}
 
 		// Check result code for all child procs for which we've
@@ -765,7 +765,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
 		// Abort just results in termination of the app, no funky error handling.
 		if (LLApp::sLogInSignal)
 		{
-			llwarns << "Signal handler - Got SIGABRT, terminating" << llendl;
+			LL_WARNS() << "Signal handler - Got SIGABRT, terminating" << LL_ENDL;
 		}
 		clear_signals();
 		raise(signum);
@@ -775,7 +775,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
 	case SIGTERM:
 		if (LLApp::sLogInSignal)
 		{
-			llwarns << "Signal handler - Got SIGINT, HUP, or TERM, exiting gracefully" << llendl;
+			LL_WARNS() << "Signal handler - Got SIGINT, HUP, or TERM, exiting gracefully" << LL_ENDL;
 		}
 		// Graceful exit
 		// Just set our state to quitting, not error
@@ -784,7 +784,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
 			// We're already trying to die, just ignore this signal
 			if (LLApp::sLogInSignal)
 			{
-				llinfos << "Signal handler - Already trying to quit, ignoring signal!" << llendl;
+				LL_INFOS() << "Signal handler - Already trying to quit, ignoring signal!" << LL_ENDL;
 			}
 			return;
 		}
@@ -806,7 +806,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
 				// Smackdown treated just like any other app termination, for now
 				if (LLApp::sLogInSignal)
 				{
-					llwarns << "Signal handler - Handling smackdown signal!" << llendl;
+					LL_WARNS() << "Signal handler - Handling smackdown signal!" << LL_ENDL;
 				}
 				else
 				{
@@ -820,7 +820,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
 			
 			if (LLApp::sLogInSignal)
 			{
-				llwarns << "Signal handler - Handling fatal signal!" << llendl;
+				LL_WARNS() << "Signal handler - Handling fatal signal!" << LL_ENDL;
 			}
 			if (LLApp::isError())
 			{
@@ -830,7 +830,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
 				
 				if (LLApp::sLogInSignal)
 				{
-					llwarns << "Signal handler - Got another fatal signal while in the error handler, die now!" << llendl;
+					LL_WARNS() << "Signal handler - Got another fatal signal while in the error handler, die now!" << LL_ENDL;
 				}
 				raise(signum);
 				return;
@@ -838,13 +838,13 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
 			
 			if (LLApp::sLogInSignal)
 			{
-				llwarns << "Signal handler - Flagging error status and waiting for shutdown" << llendl;
+				LL_WARNS() << "Signal handler - Flagging error status and waiting for shutdown" << LL_ENDL;
 			}
 									
 			if (LLApp::isCrashloggerDisabled())	// Don't gracefully handle any signal, crash and core for a gdb post mortem
 			{
 				clear_signals();
-				llwarns << "Fatal signal received, not handling the crash here, passing back to operating system" << llendl;
+				LL_WARNS() << "Fatal signal received, not handling the crash here, passing back to operating system" << LL_ENDL;
 				raise(signum);
 				return;
 			}		
@@ -859,7 +859,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
 			
 			if (LLApp::sLogInSignal)
 			{
-				llwarns << "Signal handler - App is stopped, reraising signal" << llendl;
+				LL_WARNS() << "Signal handler - App is stopped, reraising signal" << LL_ENDL;
 			}
 			clear_signals();
 			raise(signum);
@@ -867,7 +867,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
 		} else {
 			if (LLApp::sLogInSignal)
 			{
-				llinfos << "Signal handler - Unhandled signal " << signum << ", ignoring!" << llendl;
+				LL_INFOS() << "Signal handler - Unhandled signal " << signum << ", ignoring!" << LL_ENDL;
 			}
 		}
 	}
@@ -896,7 +896,7 @@ bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_
 		--remaining;
 	}
 	
-	llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl;
+	LL_INFOS() << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL;
 	LLApp::runErrorHandler();
 	
 #ifndef LL_RELEASE_FOR_DOWNLOAD
@@ -942,7 +942,7 @@ bool unix_post_minidump_callback(const char *dump_dir,
 		strncpy(path, ".dmp", remaining);
 	}
 	
-	llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl;
+	LL_INFOS() << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL;
 	LLApp::runErrorHandler();
 	
 #ifndef LL_RELEASE_FOR_DOWNLOAD
@@ -985,16 +985,16 @@ bool windows_post_minidump_callback(const wchar_t* dump_path,
 		strncpy(path, ".dmp", remaining);
 	}
 
-	llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl;
+	LL_INFOS() << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL;
    // *NOTE:Mani - this code is stolen from LLApp, where its never actually used.
 	//OSMessageBox("Attach Debugger Now", "Error", OSMB_OK);
    // *TODO: Translate the signals/exceptions into cross-platform stuff
 	// Windows implementation
-	llinfos << "Entering Windows Exception Handler..." << llendl;
+	LL_INFOS() << "Entering Windows Exception Handler..." << LL_ENDL;
 
 	if (LLApp::isError())
 	{
-		llwarns << "Got another fatal signal while in the error handler, die now!" << llendl;
+		LL_WARNS() << "Got another fatal signal while in the error handler, die now!" << LL_ENDL;
 	}
 
 	// Flag status to error, so thread_error starts its work
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index b6adb37eba..4346740e47 100755
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -446,7 +446,7 @@ S32 LLAPRFile::read(void *buf, S32 nbytes)
 {
 	if(!mFile) 
 	{
-		llwarns << "apr mFile is removed by somebody else. Can not read." << llendl ;
+		LL_WARNS() << "apr mFile is removed by somebody else. Can not read." << LL_ENDL ;
 		return 0;
 	}
 	
@@ -468,7 +468,7 @@ S32 LLAPRFile::write(const void *buf, S32 nbytes)
 {
 	if(!mFile) 
 	{
-		llwarns << "apr mFile is removed by somebody else. Can not write." << llendl ;
+		LL_WARNS() << "apr mFile is removed by somebody else. Can not write." << LL_ENDL ;
 		return 0;
 	}
 	
diff --git a/indra/llcommon/llbase32.cpp b/indra/llcommon/llbase32.cpp
index 053ac0d32f..349567c90b 100755
--- a/indra/llcommon/llbase32.cpp
+++ b/indra/llcommon/llbase32.cpp
@@ -231,8 +231,8 @@ std::string LLBase32::encode(const U8* input, size_t input_size)
 
 		size_t encoded = base32_encode(&output[0], output_size, input, input_size);
 
-		llinfos << "encoded " << encoded << " into buffer of size "
-			<< output_size << llendl;
+		LL_INFOS() << "encoded " << encoded << " into buffer of size "
+			<< output_size << LL_ENDL;
 	}
 	return output;
 }
diff --git a/indra/llcommon/llbitpack.h b/indra/llcommon/llbitpack.h
index fea56a4f1f..f99a354cd4 100755
--- a/indra/llcommon/llbitpack.h
+++ b/indra/llcommon/llbitpack.h
@@ -165,8 +165,8 @@ public:
 #ifdef _DEBUG
 					if (mBufferSize > mMaxSize)
 					{
-						llerrs << "mBufferSize exceeding mMaxSize" << llendl;
-						llerrs << mBufferSize << " > " << mMaxSize << llendl;
+						LL_ERRS() << "mBufferSize exceeding mMaxSize" << LL_ENDL;
+						LL_ERRS() << mBufferSize << " > " << mMaxSize << LL_ENDL;
 					}
 #endif
 					mLoad = *(mBuffer + mBufferSize++);
diff --git a/indra/llcommon/llcrc.cpp b/indra/llcommon/llcrc.cpp
index e80da0bb0d..626bb1e564 100755
--- a/indra/llcommon/llcrc.cpp
+++ b/indra/llcommon/llcrc.cpp
@@ -162,7 +162,7 @@ void LLCRC::update(const std::string& filename)
 {
 	if (filename.empty())
 	{
-		llerrs << "No filename specified" << llendl;
+		LL_ERRS() << "No filename specified" << LL_ENDL;
 		return;
 	}
 
@@ -185,7 +185,7 @@ void LLCRC::update(const std::string& filename)
 			
 			if (nread < (size_t) size)
 			{
-				llwarns << "Short read on " << filename << llendl;
+				LL_WARNS() << "Short read on " << filename << LL_ENDL;
 			}
 
 			update(data, nread);
diff --git a/indra/llcommon/llcrc.h b/indra/llcommon/llcrc.h
index 2d291d92a1..3f41b28ffa 100755
--- a/indra/llcommon/llcrc.h
+++ b/indra/llcommon/llcrc.h
@@ -41,7 +41,7 @@
 //    crc.update(fgetc(fp));
 //  }
 //  fclose(fp);
-//  llinfos << "File crc: " << crc.getCRC() << llendl;
+//  LL_INFOS() << "File crc: " << crc.getCRC() << LL_ENDL;
 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 class LL_COMMON_API LLCRC
diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp
index cec4047c1f..cb6f239396 100755
--- a/indra/llcommon/lldate.cpp
+++ b/indra/llcommon/lldate.cpp
@@ -63,8 +63,8 @@ LLDate::LLDate(const std::string& iso8601_date)
 {
 	if(!fromString(iso8601_date))
 	{
-		llwarns << "date " << iso8601_date << " failed to parse; "
-			<< "ZEROING IT OUT" << llendl;
+		LL_WARNS() << "date " << iso8601_date << " failed to parse; "
+			<< "ZEROING IT OUT" << LL_ENDL;
 		mSecondsSinceEpoch = DATE_EPOCH;
 	}
 }
diff --git a/indra/llcommon/lldictionary.h b/indra/llcommon/lldictionary.h
index c752859a36..5800ec5e5d 100755
--- a/indra/llcommon/lldictionary.h
+++ b/indra/llcommon/lldictionary.h
@@ -89,7 +89,7 @@ protected:
 	{
 		if (lookup(index))
 		{
-			llerrs << "Dictionary entry already added (attempted to add duplicate entry)" << llendl;
+			LL_ERRS() << "Dictionary entry already added (attempted to add duplicate entry)" << LL_ENDL;
 		}
 		(*this)[index] = entry;
 	}
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 947aa11e94..652d0e212a 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -321,9 +321,9 @@ namespace
 
 			if (configuration.isUndefined())
 			{
-				llwarns << filename() << " missing, ill-formed,"
+				LL_WARNS() << filename() << " missing, ill-formed,"
 							" or simply undefined; not changing configuration"
-						<< llendl;
+						<< LL_ENDL;
 				return false;
 			}
 		}
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 40495b8c7d..ef25a0173c 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -350,11 +350,11 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 
 
 // DEPRECATED: Use the new macros that allow tags and *look* like macros.
-#define lldebugs	LL_DEBUGS()
+//#define lldebugs	LL_DEBUGS()
 #define llinfos		LL_INFOS()
-#define llwarns		LL_WARNS()
-#define llerrs		LL_ERRS()
-#define llcont		LL_CONT
+//#define llwarns		LL_WARNS()
+//#define llerrs		LL_ERRS()
+//#define llcont		LL_CONT
 #define llendl		LL_ENDL 
 
 #endif // LL_LLERROR_H
diff --git a/indra/llcommon/llerrorthread.cpp b/indra/llcommon/llerrorthread.cpp
index 950fcd6e83..d461f31bbc 100755
--- a/indra/llcommon/llerrorthread.cpp
+++ b/indra/llcommon/llerrorthread.cpp
@@ -65,7 +65,7 @@ void get_child_status(const int waitpid_status, int &process_status, bool &exite
 		exited = true;
 		if (do_logging)
 		{
-			llinfos << "get_child_status - Child exited cleanly with return of " << process_status << llendl;
+			LL_INFOS() << "get_child_status - Child exited cleanly with return of " << process_status << LL_ENDL;
 		}
 		return;
 	}
@@ -75,15 +75,15 @@ void get_child_status(const int waitpid_status, int &process_status, bool &exite
 		exited = true;
 		if (do_logging)
 		{
-			llinfos << "get_child_status - Child died because of uncaught signal " << process_status << llendl;
+			LL_INFOS() << "get_child_status - Child died because of uncaught signal " << process_status << LL_ENDL;
 #ifdef WCOREDUMP
 			if (WCOREDUMP(waitpid_status))
 			{
-				llinfos << "get_child_status - Child dumped core" << llendl;
+				LL_INFOS() << "get_child_status - Child dumped core" << LL_ENDL;
 			}
 			else
 			{
-				llinfos << "get_child_status - Child didn't dump core" << llendl;
+				LL_INFOS() << "get_child_status - Child didn't dump core" << LL_ENDL;
 			}
 #endif
 		}
@@ -93,7 +93,7 @@ void get_child_status(const int waitpid_status, int &process_status, bool &exite
 	{
 		// This is weird.  I just dump the waitpid status into the status code,
 		// not that there's any way of telling what it is...
-		llinfos << "get_child_status - Got SIGCHILD but child didn't exit" << llendl;
+		LL_INFOS() << "get_child_status - Got SIGCHILD but child didn't exit" << LL_ENDL;
 		process_status = waitpid_status;
 	}
 
@@ -106,7 +106,7 @@ void LLErrorThread::run()
 	// This thread sits and waits for the sole purpose
 	// of waiting for the signal/exception handlers to flag the
 	// application state as APP_STATUS_ERROR.
-	llinfos << "thread_error - Waiting for an error" << llendl;
+	LL_INFOS() << "thread_error - Waiting for an error" << LL_ENDL;
 
 	S32 counter = 0;
 #if !LL_WINDOWS
@@ -124,7 +124,7 @@ void LLErrorThread::run()
 			last_sig_child_count = current_sig_child_count;
 			if (LLApp::sLogInSignal)
 			{
-				llinfos << "thread_error handling SIGCHLD #" << current_sig_child_count << llendl;
+				LL_INFOS() << "thread_error handling SIGCHLD #" << current_sig_child_count << LL_ENDL;
 			}
 			for (LLApp::child_map::iterator iter = LLApp::sChildMap.begin(); iter != LLApp::sChildMap.end();)
 			{
@@ -141,7 +141,7 @@ void LLErrorThread::run()
 					{
 						if (LLApp::sLogInSignal)
 						{
-							llinfos << "Signal handler - Running child callback" << llendl;
+							LL_INFOS() << "Signal handler - Running child callback" << LL_ENDL;
 						}
 						child_info.mCallback(child_pid, exited, status);
 					}
@@ -172,7 +172,7 @@ void LLErrorThread::run()
 					{
 						if (LLApp::sLogInSignal)
 						{
-							llinfos << "Signal handler - Running default child callback" << llendl;
+							LL_INFOS() << "Signal handler - Running default child callback" << LL_ENDL;
 						}
 						LLApp::sDefaultChildCallback(child_pid, true, status);
 					}
@@ -188,17 +188,17 @@ void LLErrorThread::run()
 	if (LLApp::isError())
 	{
 		// The app is in an error state, run the application's error handler.
-		//llinfos << "thread_error - An error has occurred, running error callback!" << llendl;
+		//LL_INFOS() << "thread_error - An error has occurred, running error callback!" << LL_ENDL;
 		// Run the error handling callback
 		LLApp::runErrorHandler();
 	}
 	else
 	{
 		// Everything is okay, a clean exit.
-		//llinfos << "thread_error - Application exited cleanly" << llendl;
+		//LL_INFOS() << "thread_error - Application exited cleanly" << LL_ENDL;
 	}
 	
-	//llinfos << "thread_error - Exiting" << llendl;
+	//LL_INFOS() << "thread_error - Exiting" << LL_ENDL;
 	LLApp::sErrorThreadRunning = FALSE;
 }
 
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 3b17b6022c..8f86a1dfbc 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -400,7 +400,7 @@ void TimeBlock::dumpCurTimes()
 			<< std::setprecision(3) << total_time.valueInUnits<LLUnits::Milliseconds>() << " ms, "
 			<< num_calls << " calls";
 
-		llinfos << out_str.str() << llendl;
+		LL_INFOS() << out_str.str() << LL_ENDL;
 	}
 }
 
diff --git a/indra/llcommon/llformat.h b/indra/llcommon/llformat.h
index a4ec5e01de..fb8e7cd045 100755
--- a/indra/llcommon/llformat.h
+++ b/indra/llcommon/llformat.h
@@ -29,7 +29,7 @@
 #define LL_LLFORMAT_H
 
 // Use as follows:
-// llinfos << llformat("Test:%d (%.2f %.2f)", idx, x, y) << llendl;
+// LL_INFOS() << llformat("Test:%d (%.2f %.2f)", idx, x, y) << LL_ENDL;
 //
 // *NOTE: buffer limited to 1024, (but vsnprintf prevents overrun)
 // should perhaps be replaced with boost::format.
diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp
index ec64195b21..1af2cb8afd 100755
--- a/indra/llcommon/llframetimer.cpp
+++ b/indra/llcommon/llframetimer.cpp
@@ -115,10 +115,10 @@ F64 LLFrameTimer::expiresAt() const
 
 BOOL LLFrameTimer::checkExpirationAndReset(F32 expiration)
 {
-	//llinfos << "LLFrameTimer::checkExpirationAndReset()" << llendl;
-	//llinfos << "  mStartTime:" << mStartTime << llendl;
-	//llinfos << "  sFrameTime:" << sFrameTime << llendl;
-	//llinfos << "  mExpiry:   " <<  mExpiry << llendl;
+	//LL_INFOS() << "LLFrameTimer::checkExpirationAndReset()" << LL_ENDL;
+	//LL_INFOS() << "  mStartTime:" << mStartTime << LL_ENDL;
+	//LL_INFOS() << "  sFrameTime:" << sFrameTime << LL_ENDL;
+	//LL_INFOS() << "  mExpiry:   " <<  mExpiry << LL_ENDL;
 
 	if(hasExpired())
 	{
diff --git a/indra/llcommon/llheartbeat.cpp b/indra/llcommon/llheartbeat.cpp
index 18a0c489bd..19b7452748 100755
--- a/indra/llcommon/llheartbeat.cpp
+++ b/indra/llcommon/llheartbeat.cpp
@@ -98,7 +98,7 @@ LLHeartbeat::rawSendWithTimeout(F32 timeout_sec)
 	mTimeoutTimer.setTimerExpirySec(timeout_sec);
 	do {
 		result = rawSend();
-		//llinfos << " HEARTSENDc=" << result << llendl;
+		//LL_INFOS() << " HEARTSENDc=" << result << LL_ENDL;
 	} while (result==1 && !mTimeoutTimer.hasExpired());
 
 	return result;
@@ -118,7 +118,7 @@ LLHeartbeat::send(F32 timeout_sec)
 			// zero-timeout; we don't care too much whether our
 			// heartbeat was digested.
 			result = rawSend();
-			//llinfos << " HEARTSENDb=" << result << llendl;
+			//LL_INFOS() << " HEARTSENDb=" << result << LL_ENDL;
 		}
 	}
 
@@ -146,14 +146,14 @@ LLHeartbeat::send(F32 timeout_sec)
 		// It's been ages since we successfully had a heartbeat
 		// digested by the watchdog.  Sit here and spin a while
 		// in the hope that we can force it through.
-		llwarns << "Unable to deliver heartbeat to launcher for " << mPanicTimer.getElapsedTimeF32() << " seconds.  Going to try very hard for up to " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << llendl;
+		LL_WARNS() << "Unable to deliver heartbeat to launcher for " << mPanicTimer.getElapsedTimeF32() << " seconds.  Going to try very hard for up to " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << LL_ENDL;
 		result = rawSendWithTimeout(mAggressiveHeartbeatMaxBlockingSecs);
 		if (result == 0) {
 			total_success = true;
 		} else {
 			// we couldn't even force it through.  That's bad,
 			// but we'll try again in a while.
-			llwarns << "Could not deliver heartbeat to launcher even after trying very hard for " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << llendl;
+			LL_WARNS() << "Could not deliver heartbeat to launcher even after trying very hard for " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << LL_ENDL;
 		}
 		
 		// in any case, reset the panic timer.
diff --git a/indra/llcommon/llliveappconfig.cpp b/indra/llcommon/llliveappconfig.cpp
index 3a3dfa9f28..7c87c5a1a0 100755
--- a/indra/llcommon/llliveappconfig.cpp
+++ b/indra/llcommon/llliveappconfig.cpp
@@ -47,8 +47,8 @@ LLLiveAppConfig::~LLLiveAppConfig()
 // virtual 
 bool LLLiveAppConfig::loadFile()
 {
-	llinfos << "LLLiveAppConfig::loadFile(): reading from "
-		<< filename() << llendl;
+	LL_INFOS() << "LLLiveAppConfig::loadFile(): reading from "
+		<< filename() << LL_ENDL;
     llifstream file(filename());
 	LLSD config;
     if (file.is_open())
@@ -56,15 +56,15 @@ bool LLLiveAppConfig::loadFile()
         LLSDSerialize::fromXML(config, file);
 		if(!config.isMap())
 		{
-			llwarns << "Live app config not an map in " << filename()
-				<< " Ignoring the data." << llendl;
+			LL_WARNS() << "Live app config not an map in " << filename()
+				<< " Ignoring the data." << LL_ENDL;
 			return false;
 		}
 		file.close();
     }
 	else
 	{
-		llinfos << "Live file " << filename() << " does not exit." << llendl;
+		LL_INFOS() << "Live file " << filename() << " does not exit." << LL_ENDL;
 	}
 	// *NOTE: we do not handle the else case here because we would not
 	// have attempted to load the file unless LLLiveFile had
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index 3fe7470d06..a9256124f2 100755
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -64,7 +64,7 @@ void ll_assert_aligned_func(uintptr_t ptr,U32 alignment)
 	// Redundant, place to set breakpoints.
 	if (ptr%alignment!=0)
 	{
-		llwarns << "alignment check failed" << llendl;
+		LL_WARNS() << "alignment check failed" << LL_ENDL;
 	}
 	llassert(ptr%alignment==0);
 #endif
@@ -109,7 +109,7 @@ void LLMemory::updateMemoryInfo()
 	
 	if (!GetProcessMemoryInfo(self, &counters, sizeof(counters)))
 	{
-		llwarns << "GetProcessMemoryInfo failed" << llendl;
+		LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
 		return ;
 	}
 
@@ -153,7 +153,7 @@ void* LLMemory::tryToAlloc(void* address, U32 size)
 	{
 		if(!VirtualFree(address, 0, MEM_RELEASE))
 		{
-			llerrs << "error happens when free some memory reservation." << llendl ;
+			LL_ERRS() << "error happens when free some memory reservation." << LL_ENDL ;
 		}
 	}
 	return address ;
@@ -171,14 +171,14 @@ void LLMemory::logMemoryInfo(BOOL update)
 		LLPrivateMemoryPoolManager::getInstance()->updateStatistics() ;
 	}
 
-	llinfos << "Current allocated physical memory(KB): " << sAllocatedMemInKB << llendl ;
-	llinfos << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << llendl ;
-	llinfos << "Current availabe physical memory(KB): " << sAvailPhysicalMemInKB << llendl ;
-	llinfos << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << llendl ;
+	LL_INFOS() << "Current allocated physical memory(KB): " << sAllocatedMemInKB << LL_ENDL ;
+	LL_INFOS() << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << LL_ENDL ;
+	LL_INFOS() << "Current availabe physical memory(KB): " << sAvailPhysicalMemInKB << LL_ENDL ;
+	LL_INFOS() << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << LL_ENDL ;
 
-	llinfos << "--- private pool information -- " << llendl ;
-	llinfos << "Total reserved (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalReservedSize / 1024 << llendl ;
-	llinfos << "Total allocated (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalAllocatedSize / 1024 << llendl ;
+	LL_INFOS() << "--- private pool information -- " << LL_ENDL ;
+	LL_INFOS() << "Total reserved (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalReservedSize / 1024 << LL_ENDL ;
+	LL_INFOS() << "Total allocated (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalAllocatedSize / 1024 << LL_ENDL ;
 }
 
 //return 0: everything is normal;
@@ -260,7 +260,7 @@ U64 LLMemory::getCurrentRSS()
 	
 	if (!GetProcessMemoryInfo(self, &counters, sizeof(counters)))
 	{
-		llwarns << "GetProcessMemoryInfo failed" << llendl;
+		LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
 		return 0;
 	}
 
@@ -298,7 +298,7 @@ U32 LLMemory::getWorkingSetSize()
 
 // 	if (sysctl(ctl, 2, &page_size, &size, NULL, 0) == -1)
 // 	{
-// 		llwarns << "Couldn't get page size" << llendl;
+// 		LL_WARNS() << "Couldn't get page size" << LL_ENDL;
 // 		return 0;
 // 	} else {
 // 		return page_size;
@@ -317,11 +317,11 @@ U64 LLMemory::getCurrentRSS()
 		// If we ever wanted it, the process virtual size is also available as:
 		// virtualSize = basicInfo.virtual_size;
 		
-//		llinfos << "resident size is " << residentSize << llendl;
+//		LL_INFOS() << "resident size is " << residentSize << LL_ENDL;
 	}
 	else
 	{
-		llwarns << "task_info failed" << llendl;
+		LL_WARNS() << "task_info failed" << LL_ENDL;
 	}
 
 	return residentSize;
@@ -342,7 +342,7 @@ U64 LLMemory::getCurrentRSS()
 
 	if (fp == NULL)
 	{
-		llwarns << "couldn't open " << statPath << llendl;
+		LL_WARNS() << "couldn't open " << statPath << LL_ENDL;
 		goto bail;
 	}
 
@@ -355,7 +355,7 @@ U64 LLMemory::getCurrentRSS()
 						 &rss);
 		if (ret != 1)
 		{
-			llwarns << "couldn't parse contents of " << statPath << llendl;
+			LL_WARNS() << "couldn't parse contents of " << statPath << LL_ENDL;
 			rss = 0;
 		}
 	}
@@ -385,12 +385,12 @@ U64 LLMemory::getCurrentRSS()
 	sprintf(path, "/proc/%d/psinfo", (int)getpid());
 	int proc_fd = -1;
 	if((proc_fd = open(path, O_RDONLY)) == -1){
-		llwarns << "LLmemory::getCurrentRSS() unable to open " << path << ". Returning 0 RSS!" << llendl;
+		LL_WARNS() << "LLmemory::getCurrentRSS() unable to open " << path << ". Returning 0 RSS!" << LL_ENDL;
 		return 0;
 	}
 	psinfo_t proc_psinfo;
 	if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
-		llwarns << "LLmemory::getCurrentRSS() Unable to read from " << path << ". Returning 0 RSS!" << llendl;
+		LL_WARNS() << "LLmemory::getCurrentRSS() Unable to read from " << path << ". Returning 0 RSS!" << LL_ENDL;
 		close(proc_fd);
 		return 0;
 	}
@@ -823,7 +823,7 @@ void LLPrivateMemoryPool::LLMemoryChunk::dump()
 		total_size += blk_list[i]->getBufferSize() ;
 		if((U32)blk_list[i]->getBuffer() < (U32)blk_list[i-1]->getBuffer() + blk_list[i-1]->getBufferSize())
 		{
-			llerrs << "buffer corrupted." << llendl ;
+			LL_ERRS() << "buffer corrupted." << LL_ENDL ;
 		}
 	}
 
@@ -844,32 +844,32 @@ void LLPrivateMemoryPool::LLMemoryChunk::dump()
 		}
 		else
 		{
-			llerrs << "gap happens" << llendl ;
+			LL_ERRS() << "gap happens" << LL_ENDL ;
 		}
 	}
 #endif
 #if 0
-	llinfos << "---------------------------" << llendl ;
-	llinfos << "Chunk buffer: " << (U32)getBuffer() << " size: " << getBufferSize() << llendl ;
+	LL_INFOS() << "---------------------------" << LL_ENDL ;
+	LL_INFOS() << "Chunk buffer: " << (U32)getBuffer() << " size: " << getBufferSize() << LL_ENDL ;
 
-	llinfos << "available blocks ... " << llendl ;
+	LL_INFOS() << "available blocks ... " << LL_ENDL ;
 	for(S32 i = 0 ; i < mBlockLevels ; i++)
 	{
 		LLMemoryBlock* blk = mAvailBlockList[i] ;
 		while(blk)
 		{
-			llinfos << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << llendl ;
+			LL_INFOS() << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << LL_ENDL ;
 			blk = blk->mNext ;
 		}
 	}
 
-	llinfos << "free blocks ... " << llendl ;
+	LL_INFOS() << "free blocks ... " << LL_ENDL ;
 	for(S32 i = 0 ; i < mPartitionLevels ; i++)
 	{
 		LLMemoryBlock* blk = mFreeSpaceList[i] ;
 		while(blk)
 		{
-			llinfos << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << llendl ;
+			LL_INFOS() << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << LL_ENDL ;
 			blk = blk->mNext ;
 		}
 	}
@@ -1265,7 +1265,7 @@ char* LLPrivateMemoryPool::allocate(U32 size)
 		
 		if(to_log)
 		{
-			llwarns << "The memory pool overflows, now using heap directly!" << llendl ;
+			LL_WARNS() << "The memory pool overflows, now using heap directly!" << LL_ENDL ;
 			to_log = false ;
 		}
 
@@ -1358,7 +1358,7 @@ void  LLPrivateMemoryPool::destroyPool()
 
 	if(mNumOfChunks > 0)
 	{
-		llwarns << "There is some memory not freed when destroy the memory pool!" << llendl ;
+		LL_WARNS() << "There is some memory not freed when destroy the memory pool!" << LL_ENDL ;
 	}
 
 	mNumOfChunks = 0 ;
@@ -1376,11 +1376,11 @@ bool LLPrivateMemoryPool::checkSize(U32 asked_size)
 {
 	if(mReservedPoolSize + asked_size > mMaxPoolSize)
 	{
-		llinfos << "Max pool size: " << mMaxPoolSize << llendl ;
-		llinfos << "Total reserved size: " << mReservedPoolSize + asked_size << llendl ;
-		llinfos << "Total_allocated Size: " << getTotalAllocatedSize() << llendl ;
+		LL_INFOS() << "Max pool size: " << mMaxPoolSize << LL_ENDL ;
+		LL_INFOS() << "Total reserved size: " << mReservedPoolSize + asked_size << LL_ENDL ;
+		LL_INFOS() << "Total_allocated Size: " << getTotalAllocatedSize() << LL_ENDL ;
 
-		//llerrs << "The pool is overflowing..." << llendl ;
+		//LL_ERRS() << "The pool is overflowing..." << LL_ENDL ;
 
 		return false ;
 	}
@@ -1593,7 +1593,7 @@ void LLPrivateMemoryPool::removeFromHashTable(LLMemoryChunk* chunk)
 
 void LLPrivateMemoryPool::rehash()
 {
-	llinfos << "new hash factor: " << mHashFactor << llendl ;
+	LL_INFOS() << "new hash factor: " << mHashFactor << LL_ENDL ;
 
 	mChunkHashList.clear() ;
 	mChunkHashList.resize(mHashFactor) ;
@@ -1673,7 +1673,7 @@ void LLPrivateMemoryPool::LLChunkHashElement::remove(LLPrivateMemoryPool::LLMemo
 	}
 	else
 	{
-		llerrs << "This slot does not contain this chunk!" << llendl ;
+		LL_ERRS() << "This slot does not contain this chunk!" << LL_ENDL ;
 	}
 }
 
@@ -1705,12 +1705,12 @@ LLPrivateMemoryPoolManager::~LLPrivateMemoryPoolManager()
 #if __DEBUG_PRIVATE_MEM__
 	if(!sMemAllocationTracker.empty())
 	{
-		llwarns << "there is potential memory leaking here. The list of not freed memory blocks are from: " <<llendl ;
+		LL_WARNS() << "there is potential memory leaking here. The list of not freed memory blocks are from: " <<LL_ENDL ;
 
 		S32 k = 0 ;
 		for(mem_allocation_info_t::iterator iter = sMemAllocationTracker.begin() ; iter != sMemAllocationTracker.end() ; ++iter)
 		{
-			llinfos << k++ << ", " << (U32)iter->first << " : " << iter->second << llendl ;
+			LL_INFOS() << k++ << ", " << (U32)iter->first << " : " << iter->second << LL_ENDL ;
 		}
 		sMemAllocationTracker.clear() ;
 	}
@@ -1906,7 +1906,7 @@ void  LLPrivateMemoryPoolManager::freeMem(LLPrivateMemoryPool* poolp, void* addr
 		}
 		else
 		{
-			llerrs << "private pool is used before initialized.!" << llendl ;
+			LL_ERRS() << "private pool is used before initialized.!" << LL_ENDL ;
 		}
 	}	
 }
@@ -1980,7 +1980,7 @@ void LLPrivateMemoryPoolTester::test(U32 min_size, U32 max_size, U32 stride, U32
 	//allocate space for p ;
 	if(!(p = ::new char**[times]) || !(*p = ::new char*[times * levels]))
 	{
-		llerrs << "memory initialization for p failed" << llendl ;
+		LL_ERRS() << "memory initialization for p failed" << LL_ENDL ;
 	}
 
 	//init
@@ -2052,8 +2052,8 @@ void LLPrivateMemoryPoolTester::testAndTime(U32 size, U32 times)
 {
 	LLTimer timer ;
 
-	llinfos << " -**********************- " << llendl ;
-	llinfos << "test size: " << size << " test times: " << times << llendl ;
+	LL_INFOS() << " -**********************- " << LL_ENDL ;
+	LL_INFOS() << "test size: " << size << " test times: " << times << LL_ENDL ;
 
 	timer.reset() ;
 	char** p = new char*[times] ;
@@ -2065,7 +2065,7 @@ void LLPrivateMemoryPoolTester::testAndTime(U32 size, U32 times)
 		p[i] = ALLOCATE_MEM(sPool, size) ;
 		if(!p[i])
 		{
-			llerrs << "allocation failed" << llendl ;
+			LL_ERRS() << "allocation failed" << LL_ENDL ;
 		}
 	}
 	//de-allocation
@@ -2074,7 +2074,7 @@ void LLPrivateMemoryPoolTester::testAndTime(U32 size, U32 times)
 		FREE_MEM(sPool, p[i]) ;
 		p[i] = NULL ;
 	}
-	llinfos << "time spent using customized memory pool: " << timer.getElapsedTimeF32() << llendl ;
+	LL_INFOS() << "time spent using customized memory pool: " << timer.getElapsedTimeF32() << LL_ENDL ;
 
 	timer.reset() ;
 
@@ -2085,7 +2085,7 @@ void LLPrivateMemoryPoolTester::testAndTime(U32 size, U32 times)
 		p[i] = ::new char[size] ;
 		if(!p[i])
 		{
-			llerrs << "allocation failed" << llendl ;
+			LL_ERRS() << "allocation failed" << LL_ENDL ;
 		}
 	}
 	//de-allocation
@@ -2094,7 +2094,7 @@ void LLPrivateMemoryPoolTester::testAndTime(U32 size, U32 times)
 		::delete[] p[i] ;
 		p[i] = NULL ;
 	}
-	llinfos << "time spent using standard allocator/de-allocator: " << timer.getElapsedTimeF32() << llendl ;
+	LL_INFOS() << "time spent using standard allocator/de-allocator: " << timer.getElapsedTimeF32() << LL_ENDL ;
 
 	delete[] p;
 }
diff --git a/indra/llcommon/llmemorystream.cpp b/indra/llcommon/llmemorystream.cpp
index 723d94f025..707ac8fd0f 100755
--- a/indra/llcommon/llmemorystream.cpp
+++ b/indra/llcommon/llmemorystream.cpp
@@ -45,7 +45,7 @@ void LLMemoryStreamBuf::reset(const U8* start, S32 length)
 
 int LLMemoryStreamBuf::underflow()
 {
-	//lldebugs << "LLMemoryStreamBuf::underflow()" << llendl;
+	//LL_DEBUGS() << "LLMemoryStreamBuf::underflow()" << LL_ENDL;
 	if(gptr() < egptr())
 	{
 		return *gptr();
diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp
index fd89cb818a..88287e5786 100755
--- a/indra/llcommon/llmetricperformancetester.cpp
+++ b/indra/llcommon/llmetricperformancetester.cpp
@@ -56,7 +56,7 @@ BOOL LLMetricPerformanceTesterBasic::addTester(LLMetricPerformanceTesterBasic* t
 	std::string name = tester->getTesterName() ;
 	if (getTester(name))
 	{
-		llerrs << "Tester name is already used by some other tester : " << name << llendl ;
+		LL_ERRS() << "Tester name is already used by some other tester : " << name << LL_ENDL ;
 		return FALSE;
 	}
 
@@ -136,7 +136,7 @@ void LLMetricPerformanceTesterBasic::doAnalysisMetrics(std::string baseline, std
 	std::ifstream target_is(target.c_str());
 	if (!base_is.is_open() || !target_is.is_open())
 	{
-		llwarns << "'-analyzeperformance' error : baseline or current target file inexistent" << llendl;
+		LL_WARNS() << "'-analyzeperformance' error : baseline or current target file inexistent" << LL_ENDL;
 		base_is.close();
 		target_is.close();
 		return;
@@ -176,7 +176,7 @@ LLMetricPerformanceTesterBasic::LLMetricPerformanceTesterBasic(std::string name)
 {
 	if (mName == std::string())
 	{
-		llerrs << "LLMetricPerformanceTesterBasic construction invalid : Empty name passed to constructor" << llendl ;
+		LL_ERRS() << "LLMetricPerformanceTesterBasic construction invalid : Empty name passed to constructor" << LL_ENDL ;
 	}
 
 	mValidInstance = LLMetricPerformanceTesterBasic::addTester(this) ;
@@ -241,7 +241,7 @@ void LLMetricPerformanceTesterBasic::analyzePerformance(std::ofstream* os, LLSD*
 						(F32)((*base)[label][ mMetricStrings[index] ].asReal()), (F32)((*current)[label][ mMetricStrings[index] ].asReal())) ;
 					break;
 				default:
-					llerrs << "unsupported metric " << mMetricStrings[index] << " LLSD type: " << (S32)(*current)[label][ mMetricStrings[index] ].type() << llendl ;
+					LL_ERRS() << "unsupported metric " << mMetricStrings[index] << " LLSD type: " << (S32)(*current)[label][ mMetricStrings[index] ].type() << LL_ENDL ;
 				}
 			}	
 		}
@@ -305,7 +305,7 @@ void LLMetricPerformanceTesterWithSession::analyzePerformance(std::ofstream* os,
 
 	if (!mBaseSessionp || !mCurrentSessionp)
 	{
-		llerrs << "Error loading test sessions." << llendl ;
+		LL_ERRS() << "Error loading test sessions." << LL_ENDL ;
 	}
 
 	// Compare
diff --git a/indra/llcommon/llmetrics.cpp b/indra/llcommon/llmetrics.cpp
index 3078139f43..d40afe5160 100755
--- a/indra/llcommon/llmetrics.cpp
+++ b/indra/llcommon/llmetrics.cpp
@@ -65,7 +65,7 @@ void LLMetricsImpl::recordEventDetails(const std::string& location,
 	metrics["location"] = location;
 	metrics["stats"]  = stats;
 	
-	llinfos << "LLMETRICS: " << (LLSDNotationStreamer(metrics)) << llendl; 
+	LL_INFOS() << "LLMETRICS: " << (LLSDNotationStreamer(metrics)) << LL_ENDL; 
 }
 
 // Store this:
@@ -128,7 +128,7 @@ void LLMetricsImpl::printTotals(LLSD metadata)
 
 	out_sd["stats"] = stats;
 
-	llinfos << "LLMETRICS: AGGREGATE: " << LLSDOStreamer<LLSDNotationFormatter>(out_sd) << llendl;
+	LL_INFOS() << "LLMETRICS: AGGREGATE: " << LLSDOStreamer<LLSDNotationFormatter>(out_sd) << LL_ENDL;
 }
 
 LLMetrics::LLMetrics()
diff --git a/indra/llcommon/llmetrics.h b/indra/llcommon/llmetrics.h
index 4f0ae56338..85a6986049 100755
--- a/indra/llcommon/llmetrics.h
+++ b/indra/llcommon/llmetrics.h
@@ -38,7 +38,7 @@ public:
 	LLMetrics();
 	virtual ~LLMetrics();
 
-	// Adds this event to aggregate totals and records details to syslog (llinfos)
+	// Adds this event to aggregate totals and records details to syslog (LL_INFOS())
 	virtual void recordEventDetails(const std::string& location, 
 						const std::string& mesg, 
 						bool success, 
diff --git a/indra/llcommon/llmutex.cpp b/indra/llcommon/llmutex.cpp
index ad0287c6d5..252bbd6cd1 100644
--- a/indra/llcommon/llmutex.cpp
+++ b/indra/llcommon/llmutex.cpp
@@ -82,7 +82,7 @@ void LLMutex::lock()
 	// Have to have the lock before we can access the debug info
 	U32 id = LLThread::currentID();
 	if (mIsLocked[id] != FALSE)
-		llerrs << "Already locked in Thread: " << id << llendl;
+		LL_ERRS() << "Already locked in Thread: " << id << LL_ENDL;
 	mIsLocked[id] = TRUE;
 #endif
 
@@ -101,7 +101,7 @@ void LLMutex::unlock()
 	// Access the debug info while we have the lock
 	U32 id = LLThread::currentID();
 	if (mIsLocked[id] != TRUE)
-		llerrs << "Not locked in Thread: " << id << llendl;	
+		LL_ERRS() << "Not locked in Thread: " << id << LL_ENDL;	
 	mIsLocked[id] = FALSE;
 #endif
 
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index e09741b0ec..c9ebc70d19 100755
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -156,7 +156,7 @@ protected:
 			temp->unref();
 			if (mPointer != NULL)
 			{
-				llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
+				LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
 				unref();
 			}
 		}
diff --git a/indra/llcommon/llpriqueuemap.h b/indra/llcommon/llpriqueuemap.h
index da997c7b04..d8d3edd48a 100755
--- a/indra/llcommon/llpriqueuemap.h
+++ b/indra/llcommon/llpriqueuemap.h
@@ -84,7 +84,7 @@ public:
 		pqm_iter iter = mMap.find(LLPQMKey<DATA_TYPE>(priority, data));
 		if (iter != mMap.end())
 		{
-			llerrs << "Pushing already existing data onto queue!" << llendl;
+			LL_ERRS() << "Pushing already existing data onto queue!" << LL_ENDL;
 		}
 #endif
 		mMap.insert(pqm_pair(LLPQMKey<DATA_TYPE>(priority, data), data));
@@ -112,14 +112,14 @@ public:
 		iter = mMap.find(cur_key);
 		if (iter == mMap.end())
 		{
-			llwarns << "Data not on priority queue!" << llendl;
+			LL_WARNS() << "Data not on priority queue!" << LL_ENDL;
 			// OK, try iterating through all of the data and seeing if we just screwed up the priority
 			// somehow.
 			for (iter = mMap.begin(); iter != mMap.end(); iter++)
 			{
 				if ((*(iter)).second == data)
 				{
-					llerrs << "Data on priority queue but priority not matched!" << llendl;
+					LL_ERRS() << "Data on priority queue but priority not matched!" << LL_ENDL;
 				}
 			}
 			return;
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index b80e813d84..80b86153e4 100755
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -700,7 +700,7 @@ private:
 		__cpuid(0x1, eax, ebx, ecx, edx);
 		if(feature_infos[0] != (S32)edx)
 		{
-			llerrs << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << llendl;
+			LL_ERRS() << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << LL_ENDL;
 		} 
 #endif // LL_RELEASE_FOR_DOWNLOAD 	
 
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 3689c4728e..176761c17c 100755
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -81,7 +81,7 @@ void LLQueuedThread::shutdown()
 		}
 		if (timeout == 0)
 		{
-			llwarns << "~LLQueuedThread (" << mName << ") timed out!" << llendl;
+			LL_WARNS() << "~LLQueuedThread (" << mName << ") timed out!" << LL_ENDL;
 		}
 	}
 	else
@@ -102,7 +102,7 @@ void LLQueuedThread::shutdown()
 	}
 	if (active_count)
 	{
-		llwarns << "~LLQueuedThread() called with active requests: " << active_count << llendl;
+		LL_WARNS() << "~LLQueuedThread() called with active requests: " << active_count << LL_ENDL;
 	}
 }
 
@@ -199,11 +199,11 @@ void LLQueuedThread::printQueueStats()
 	if (!mRequestQueue.empty())
 	{
 		QueuedRequest *req = *mRequestQueue.begin();
-		llinfos << llformat("Pending Requests:%d Current status:%d", mRequestQueue.size(), req->getStatus()) << llendl;
+		LL_INFOS() << llformat("Pending Requests:%d Current status:%d", mRequestQueue.size(), req->getStatus()) << LL_ENDL;
 	}
 	else
 	{
-		llinfos << "Queued Thread Idle" << llendl;
+		LL_INFOS() << "Queued Thread Idle" << LL_ENDL;
 	}
 	unlockData();
 }
@@ -234,7 +234,7 @@ bool LLQueuedThread::addRequest(QueuedRequest* req)
 	mRequestQueue.insert(req);
 	mRequestHash.insert(req);
 #if _DEBUG
-// 	llinfos << llformat("LLQueuedThread::Added req [%08d]",handle) << llendl;
+// 	LL_INFOS() << llformat("LLQueuedThread::Added req [%08d]",handle) << LL_ENDL;
 #endif
 	unlockData();
 
@@ -365,7 +365,7 @@ bool LLQueuedThread::completeRequest(handle_t handle)
 		llassert_always(req->getStatus() != STATUS_QUEUED);
 		llassert_always(req->getStatus() != STATUS_INPROGRESS);
 #if _DEBUG
-// 		llinfos << llformat("LLQueuedThread::Completed req [%08d]",handle) << llendl;
+// 		LL_INFOS() << llformat("LLQueuedThread::Completed req [%08d]",handle) << LL_ENDL;
 #endif
 		mRequestHash.erase(handle);
 		req->deleteRequest();
@@ -386,7 +386,7 @@ bool LLQueuedThread::check()
 		{
 			if (entry->getHashKey() > mNextHandle)
 			{
-				llerrs << "Hash Error" << llendl;
+				LL_ERRS() << "Hash Error" << LL_ENDL;
 				return false;
 			}
 			entry = entry->getNextEntry();
@@ -520,7 +520,7 @@ void LLQueuedThread::run()
 		}
 		//LLThread::yield(); // thread should yield after each request		
 	}
-	llinfos << "LLQueuedThread " << mName << " EXITING." << llendl;
+	LL_INFOS() << "LLQueuedThread " << mName << " EXITING." << LL_ENDL;
 }
 
 // virtual
diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp
index e1876599fc..a638df2c7c 100755
--- a/indra/llcommon/llrefcount.cpp
+++ b/indra/llcommon/llrefcount.cpp
@@ -76,7 +76,7 @@ LLRefCount::~LLRefCount()
 { 
 	if (mRef != 0)
 	{
-		llerrs << "deleting non-zero reference" << llendl;
+		LL_ERRS() << "deleting non-zero reference" << LL_ENDL;
 	}
 
 #if LL_REF_COUNT_DEBUG
@@ -95,8 +95,8 @@ void LLRefCount::ref() const
 		if(mMutexp->isLocked()) 
 		{
 			mCrashAtUnlock = TRUE ;
-			llerrs << "the mutex is locked by the thread: " << mLockedThreadID 
-				<< " Current thread: " << LLThread::currentID() << llendl ;
+			LL_ERRS() << "the mutex is locked by the thread: " << mLockedThreadID 
+				<< " Current thread: " << LLThread::currentID() << LL_ENDL ;
 		}
 
 		mMutexp->lock() ;
@@ -123,8 +123,8 @@ S32 LLRefCount::unref() const
 		if(mMutexp->isLocked()) 
 		{
 			mCrashAtUnlock = TRUE ;
-			llerrs << "the mutex is locked by the thread: " << mLockedThreadID 
-				<< " Current thread: " << LLThread::currentID() << llendl ;
+			LL_ERRS() << "the mutex is locked by the thread: " << mLockedThreadID 
+				<< " Current thread: " << LLThread::currentID() << LL_ENDL ;
 		}
 
 		mMutexp->lock() ;
diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h
index c8ec0a0bc0..29950c108d 100755
--- a/indra/llcommon/llregistry.h
+++ b/indra/llcommon/llregistry.h
@@ -62,7 +62,7 @@ public:
 		{
 			if (mMap.insert(std::make_pair(key, value)).second == false)
 			{
-				llwarns << "Tried to register " << key << " but it was already registered!" << llendl;
+				LL_WARNS() << "Tried to register " << key << " but it was already registered!" << LL_ENDL;
 				return false;
 			}
 			return true;
@@ -307,7 +307,7 @@ public:
 		{
 			if (singleton_t::instance().exists(key))
 			{
-				llerrs << "Duplicate registry entry under key \"" << key << "\"" << llendl;
+				LL_ERRS() << "Duplicate registry entry under key \"" << key << "\"" << LL_ENDL;
 			}
 			singleton_t::instance().mStaticScope->add(key, value);
 		}
diff --git a/indra/llcommon/llsafehandle.h b/indra/llcommon/llsafehandle.h
index 8d52d9bb15..4226bf04f0 100755
--- a/indra/llcommon/llsafehandle.h
+++ b/indra/llcommon/llsafehandle.h
@@ -134,7 +134,7 @@ protected:
 			tempp->unref();
 			if (mPointer != NULL)
 			{
-				llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
+				LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
 				unref();
 			}
 		}
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index ad4fce6f35..04d7a6ed56 100755
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -81,7 +81,7 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize
 		break;
 
 	default:
-		llwarns << "serialize request for unknown ELLSD_Serialize" << llendl;
+		LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL;
 	}
 
 	if (f.notNull())
@@ -169,7 +169,7 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
 	}
 	else
 	{
-		llwarns << "deserialize request for unknown ELLSD_Serialize" << llendl;
+		LL_WARNS() << "deserialize request for unknown ELLSD_Serialize" << LL_ENDL;
 	}
 
 	if (p.notNull())
@@ -179,7 +179,7 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
 	}
 
 fail:
-	llwarns << "deserialize LLSD parse failure" << llendl;
+	LL_WARNS() << "deserialize LLSD parse failure" << LL_ENDL;
 	return false;
 }
 
@@ -445,7 +445,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
 		}
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading map." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading map." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -464,7 +464,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
 		}
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading array." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading array." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -500,7 +500,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
 		}
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading boolean." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading boolean." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -526,7 +526,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
 		}
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading boolean." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading boolean." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -539,7 +539,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
 		data = integer;
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading integer." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading integer." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -553,7 +553,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
 		data = real;
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading real." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading real." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -567,7 +567,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
 		data = id;
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading uuid." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading uuid." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -582,7 +582,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
 		}
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading string." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading string." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -604,7 +604,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
 		}
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading link." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading link." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -627,7 +627,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
 		}
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading date." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading date." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -640,15 +640,15 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
 		}
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading data." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading data." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
 
 	default:
 		parse_count = PARSE_FAILURE;
-		llinfos << "Unrecognized character while parsing: int(" << (int)c
-			<< ")" << llendl;
+		LL_INFOS() << "Unrecognized character while parsing: int(" << (int)c
+			<< ")" << LL_ENDL;
 		break;
 	}
 	if(PARSE_FAILURE == parse_count)
@@ -909,7 +909,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 		}
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading binary map." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading binary map." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -928,7 +928,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 		}
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading binary array." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading binary array." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -953,7 +953,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 		data = (S32)ntohl(value_nbo);
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading binary integer." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading binary integer." << LL_ENDL;
 		}
 		break;
 	}
@@ -965,7 +965,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 		data = ll_ntohd(real_nbo);
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading binary real." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading binary real." << LL_ENDL;
 		}
 		break;
 	}
@@ -977,7 +977,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 		data = id;
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading binary uuid." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading binary uuid." << LL_ENDL;
 		}
 		break;
 	}
@@ -998,8 +998,8 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 		}
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading binary (notation-style) string."
-				<< llendl;
+			LL_INFOS() << "STREAM FAILURE reading binary (notation-style) string."
+				<< LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -1018,7 +1018,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 		}
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading binary string." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading binary string." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -1037,7 +1037,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 		}
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading binary link." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading binary link." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -1050,7 +1050,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 		data = LLDate(real);
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading binary date." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading binary date." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -1079,7 +1079,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 		}
 		if(istr.fail())
 		{
-			llinfos << "STREAM FAILURE reading binary." << llendl;
+			LL_INFOS() << "STREAM FAILURE reading binary." << LL_ENDL;
 			parse_count = PARSE_FAILURE;
 		}
 		break;
@@ -1087,8 +1087,8 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 
 	default:
 		parse_count = PARSE_FAILURE;
-		llinfos << "Unrecognized character while parsing: int(" << (int)c
-			<< ")" << llendl;
+		LL_INFOS() << "Unrecognized character while parsing: int(" << (int)c
+			<< ")" << LL_ENDL;
 		break;
 	}
 	if(PARSE_FAILURE == parse_count)
@@ -2017,7 +2017,7 @@ std::string zip_llsd(LLSD& data)
 	S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION);
 	if (ret != Z_OK)
 	{
-		llwarns << "Failed to compress LLSD block." << llendl;
+		LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
 		return std::string();
 	}
 
@@ -2044,7 +2044,7 @@ std::string zip_llsd(LLSD& data)
 			if (strm.avail_out >= CHUNK)
 			{
 				free(output);
-				llwarns << "Failed to compress LLSD block." << llendl;
+				LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
 				return std::string();
 			}
 
@@ -2056,7 +2056,7 @@ std::string zip_llsd(LLSD& data)
 		else 
 		{
 			free(output);
-			llwarns << "Failed to compress LLSD block." << llendl;
+			LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
 			return std::string();
 		}
 	}
@@ -2073,7 +2073,7 @@ std::string zip_llsd(LLSD& data)
 	LLSD test_sd;
 	if (!unzip_llsd(test_sd, test, result.size()))
 	{
-		llerrs << "Invalid compression result!" << llendl;
+		LL_ERRS() << "Invalid compression result!" << LL_ENDL;
 	}
 #endif
 
@@ -2163,7 +2163,7 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
 		
 		if (!LLSDSerialize::fromBinary(data, istr, cur_size))
 		{
-			llwarns << "Failed to unzip LLSD block" << llendl;
+			LL_WARNS() << "Failed to unzip LLSD block" << LL_ENDL;
 			free(result);
 			return false;
 		}		
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index 614a2d5636..4e2af0e589 100755
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -406,7 +406,7 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data)
 		}
 		if (mEmitErrors)
 		{
-		llinfos << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:" << (char*) buffer << llendl;
+		LL_INFOS() << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:" << (char*) buffer << LL_ENDL;
 		}
 		data = LLSD();
 		return LLSDParser::PARSE_FAILURE;
@@ -487,7 +487,7 @@ S32 LLSDXMLParser::Impl::parseLines(std::istream& input, LLSD& data)
 	{
 		if (mEmitErrors)
 		{
-		llinfos << "LLSDXMLParser::Impl::parseLines: XML_STATUS_ERROR" << llendl;
+		LL_INFOS() << "LLSDXMLParser::Impl::parseLines: XML_STATUS_ERROR" << LL_ENDL;
 		}
 		return LLSDParser::PARSE_FAILURE;
 	}
@@ -549,7 +549,7 @@ void LLSDXMLParser::Impl::parsePart(const char* buf, int len)
 		XML_Status status = XML_Parse(mParser, buf, len, false);
 		if (status == XML_STATUS_ERROR)
 		{
-			llinfos << "Unexpected XML parsing error at start" << llendl;
+			LL_INFOS() << "Unexpected XML parsing error at start" << LL_ENDL;
 		}
 	}
 }
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index b9cb8e3d41..6e6291a165 100755
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -143,7 +143,7 @@ public:
 			llassert(false);
 			return NULL;
 		case CONSTRUCTING:
-			llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl;
+			LL_ERRS() << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << LL_ENDL;
 			return NULL;
 		case INITIALIZING:
 			// go ahead and flag ourselves as initialized so we can be reentrant during initialization
@@ -155,7 +155,7 @@ public:
 		case INITIALIZED:
 			return sData.mInstance;
 		case DELETED:
-			llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
+			LL_WARNS() << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << LL_ENDL;
 			SingletonLifetimeManager::construct();
 			// same as first time construction
 			sData.mInitState = INITIALIZED;	
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index 6f92c7d5d4..e6e80fa279 100755
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -110,7 +110,7 @@ bool _read_file_into_string(std::string& str, const std::string& filename)
 	llifstream ifs(filename, llifstream::binary);
 	if (!ifs.is_open())
 	{
-		llinfos << "Unable to open file " << filename << llendl;
+		LL_INFOS() << "Unable to open file " << filename << LL_ENDL;
 		return false;
 	}
 
@@ -188,7 +188,7 @@ S32 wchar_to_utf8chars(llwchar in_char, char* outchars)
 	}
 	else
 	{
-		llwarns << "Invalid Unicode character " << cur_char << "!" << llendl;
+		LL_WARNS() << "Invalid Unicode character " << cur_char << "!" << LL_ENDL;
 		*outchars++ = LL_UNKNOWN_CHAR;
 	}
 	return outchars - base;
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 8d2045dfa0..cad02f491a 100755
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -607,7 +607,7 @@ S32 LLOSInfo::getMaxOpenFiles()
 			}
 			else
 			{
-				llerrs << "LLOSInfo::getMaxOpenFiles: sysconf error for _SC_OPEN_MAX" << llendl;
+				LL_ERRS() << "LLOSInfo::getMaxOpenFiles: sysconf error for _SC_OPEN_MAX" << LL_ENDL;
 			}
 		}
 	}
@@ -666,12 +666,12 @@ U32 LLOSInfo::getProcessVirtualSizeKB()
 	sprintf(proc_ps, "/proc/%d/psinfo", (int)getpid());
 	int proc_fd = -1;
 	if((proc_fd = open(proc_ps, O_RDONLY)) == -1){
-		llwarns << "unable to open " << proc_ps << llendl;
+		LL_WARNS() << "unable to open " << proc_ps << LL_ENDL;
 		return 0;
 	}
 	psinfo_t proc_psinfo;
 	if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
-		llwarns << "Unable to read " << proc_ps << llendl;
+		LL_WARNS() << "Unable to read " << proc_ps << LL_ENDL;
 		close(proc_fd);
 		return 0;
 	}
@@ -712,12 +712,12 @@ U32 LLOSInfo::getProcessResidentSizeKB()
 	sprintf(proc_ps, "/proc/%d/psinfo", (int)getpid());
 	int proc_fd = -1;
 	if((proc_fd = open(proc_ps, O_RDONLY)) == -1){
-		llwarns << "unable to open " << proc_ps << llendl;
+		LL_WARNS() << "unable to open " << proc_ps << LL_ENDL;
 		return 0;
 	}
 	psinfo_t proc_psinfo;
 	if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
-		llwarns << "Unable to read " << proc_ps << llendl;
+		LL_WARNS() << "Unable to read " << proc_ps << LL_ENDL;
 		close(proc_fd);
 		return 0;
 	}
@@ -1449,7 +1449,7 @@ BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile)
 		size_t nwrit = fwrite(buffer, sizeof(U8), bytes, dst);
 		if (nwrit < (size_t) bytes)
 		{
-			llwarns << "Short write on " << tmpfile << ": Wrote " << nwrit << " of " << bytes << " bytes." << llendl;
+			LL_WARNS() << "Short write on " << tmpfile << ": Wrote " << nwrit << " of " << bytes << " bytes." << LL_ENDL;
 			goto err;
 		}
 	} while(gzeof(src) == 0);
@@ -1482,14 +1482,14 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile)
 	{
 		if (gzwrite(dst, buffer, bytes) <= 0)
 		{
-			llwarns << "gzwrite failed: " << gzerror(dst, NULL) << llendl;
+			LL_WARNS() << "gzwrite failed: " << gzerror(dst, NULL) << LL_ENDL;
 			goto err;
 		}
 	}
 
 	if (ferror(src))
 	{
-		llwarns << "Error reading " << srcfile << llendl;
+		LL_WARNS() << "Error reading " << srcfile << LL_ENDL;
 		goto err;
 	}
 
diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h
index cfed0fff17..aa60fc9b2e 100755
--- a/indra/llcommon/llsys.h
+++ b/indra/llcommon/llsys.h
@@ -33,7 +33,7 @@
 // use an LLCPUInfo object:
 //
 //  LLCPUInfo info;
-//  llinfos << info << llendl;
+//  LL_INFOS() << info << LL_ENDL;
 //
 
 #include "llsd.h"
@@ -105,7 +105,7 @@ class LL_COMMON_API LLMemoryInfo
 		Here's how you use an LLMemoryInfo:
 		
 		LLMemoryInfo info;
-<br>	llinfos << info << llendl;
+<br>	LL_INFOS() << info << LL_ENDL;
 */
 {
 public:
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index db7ddbbfd3..bcae57fe22 100755
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -108,7 +108,7 @@ LL_COMMON_API void assert_main_thread()
 	static U32 s_thread_id = LLThread::currentID();
 	if (LLThread::currentID() != s_thread_id)
 	{
-		llerrs << "Illegal execution outside main thread." << llendl;
+		LL_ERRS() << "Illegal execution outside main thread." << LL_ENDL;
 	}
 }
 
@@ -140,7 +140,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 	// Run the user supplied function
 	threadp->run();
 
-	//llinfos << "LLThread::staticRun() Exiting: " << threadp->mName << llendl;
+	//LL_INFOS() << "LLThread::staticRun() Exiting: " << threadp->mName << LL_ENDL;
 	
 	// We're done with the run function, this thread is done executing now.
 	threadp->mStatus = STOPPED;
@@ -197,7 +197,7 @@ void LLThread::shutdown()
 			// First, set the flag that indicates that we're ready to die
 			setQuitting();
 
-			//llinfos << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << llendl;
+			//LL_INFOS() << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << LL_ENDL;
 			// Now wait a bit for the thread to exit
 			// It's unclear whether I should even bother doing this - this destructor
 			// should never get called unless we're already stopped, really...
@@ -219,7 +219,7 @@ void LLThread::shutdown()
 		if (!isStopped())
 		{
 			// This thread just wouldn't stop, even though we gave it time
-			//llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl;
+			//LL_WARNS() << "LLThread::~LLThread() exiting thread before clean exit!" << LL_ENDL;
 			// Put a stake in its heart.
 			apr_thread_exit(mAPRThreadp, -1);
 			return;
@@ -259,7 +259,7 @@ void LLThread::start()
 	else
 	{
 		mStatus = STOPPED;
-		llwarns << "failed to start thread " << mName << llendl;
+		LL_WARNS() << "failed to start thread " << mName << LL_ENDL;
 		ll_apr_warn_status(status);
 	}
 
@@ -416,7 +416,7 @@ LLThreadSafeRefCount::~LLThreadSafeRefCount()
 { 
 	if (mRef != 0)
 	{
-		llerrs << "deleting non-zero reference" << llendl;
+		LL_ERRS() << "deleting non-zero reference" << LL_ENDL;
 	}
 }
 
diff --git a/indra/llcommon/llthreadlocalstorage.cpp b/indra/llcommon/llthreadlocalstorage.cpp
index 03c306cc7f..8cef05caac 100644
--- a/indra/llcommon/llthreadlocalstorage.cpp
+++ b/indra/llcommon/llthreadlocalstorage.cpp
@@ -43,7 +43,7 @@ void LLThreadLocalPointerBase::set( void* value )
 	if (result != APR_SUCCESS)
 	{
 		ll_apr_warn_status(result);
-		llerrs << "Failed to set thread local data" << llendl;
+		LL_ERRS() << "Failed to set thread local data" << LL_ENDL;
 	}
 }
 
@@ -56,7 +56,7 @@ void* LLThreadLocalPointerBase::get() const
 	if (result != APR_SUCCESS)
 	{
 		ll_apr_warn_status(result);
-		llerrs << "Failed to get thread local data" << llendl;
+		LL_ERRS() << "Failed to get thread local data" << LL_ENDL;
 	}
 	return ptr;
 }
@@ -68,7 +68,7 @@ void LLThreadLocalPointerBase::initStorage( )
 	if (result != APR_SUCCESS)
 	{
 		ll_apr_warn_status(result);
-		llerrs << "Failed to allocate thread local data" << llendl;
+		LL_ERRS() << "Failed to allocate thread local data" << LL_ENDL;
 	}
 }
 
@@ -82,7 +82,7 @@ void LLThreadLocalPointerBase::destroyStorage()
 			if (result != APR_SUCCESS)
 			{
 				ll_apr_warn_status(result);
-				llerrs << "Failed to delete thread local data" << llendl;
+				LL_ERRS() << "Failed to delete thread local data" << LL_ENDL;
 			}
 		}
 	}
diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
index 3b2f5f4193..177e822227 100644
--- a/indra/llcommon/llthreadlocalstorage.h
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -157,14 +157,14 @@ private:
 #elif LL_DARWIN
     static void TLSError()
     {
-        llerrs << "Could not create thread local storage" << llendl;
+        LL_ERRS() << "Could not create thread local storage" << LL_ENDL;
     }
     static void createTLSKey()
     {
         static S32 key_created = pthread_key_create(&sInstanceKey, NULL);
         if (key_created != 0)
         {
-            llerrs << "Could not create thread local storage" << llendl;
+            LL_ERRS() << "Could not create thread local storage" << LL_ENDL;
         }
     }
     static pthread_key_t sInstanceKey;
diff --git a/indra/llcommon/llthreadsafequeue.cpp b/indra/llcommon/llthreadsafequeue.cpp
index 8a73e632a9..185f0d63fb 100755
--- a/indra/llcommon/llthreadsafequeue.cpp
+++ b/indra/llcommon/llthreadsafequeue.cpp
@@ -54,7 +54,7 @@ LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * po
 LLThreadSafeQueueImplementation::~LLThreadSafeQueueImplementation()
 {
 	if(mQueue != 0) {
-		if(apr_queue_size(mQueue) != 0) llwarns << 
+		if(apr_queue_size(mQueue) != 0) LL_WARNS() << 
 			"terminating queue which still contains " << apr_queue_size(mQueue) <<
 			" elements;" << "memory will be leaked" << LL_ENDL;
 		apr_queue_term(mQueue);
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index f27c433ee1..a2c5f3d699 100755
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -456,7 +456,7 @@ BOOL LLTimer::knownBadTimer()
 			{
 				if (!wcscmp(pci_id, bad_pci_list[check]))
 				{
-//					llwarns << "unreliable PCI chipset found!! " << pci_id << endl;
+//					LL_WARNS() << "unreliable PCI chipset found!! " << pci_id << endl;
 					failed = TRUE;
 					break;
 				}
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 3dffbe6d4a..eedf1b06f1 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -40,7 +40,7 @@ TraceBase::TraceBase( const char* name, const char* description )
 #ifndef LL_RELEASE_FOR_DOWNLOAD
 	if (LLTrace::get_master_thread_recorder() != NULL)
 	{
-		llerrs << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << llendl;
+		LL_ERRS() << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << LL_ENDL;
 	}
 #endif
 }
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index e20d8b63de..8c32e1568b 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -174,7 +174,7 @@ ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringU
 
 	if (it == end_it)
 	{
-		llwarns << "Recording not active on this thread" << llendl;
+		LL_WARNS() << "Recording not active on this thread" << LL_ENDL;
 	}
 
 	return it;
diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp
index 37f5b3d6a3..9f12d49244 100755
--- a/indra/llcommon/lluri.cpp
+++ b/indra/llcommon/lluri.cpp
@@ -359,7 +359,7 @@ LLURI LLURI::buildHTTP(const std::string& prefix,
 			 it != path.endArray();
 			 ++it)
 		{
-			lldebugs << "PATH: inserting " << it->asString() << llendl;
+			LL_DEBUGS() << "PATH: inserting " << it->asString() << LL_ENDL;
 			result.mEscapedPath += "/" + escapePathComponent(it->asString());
 		}
 	}
@@ -399,8 +399,8 @@ LLURI LLURI::buildHTTP(const std::string& prefix,
 	}
 	else
 	{
-	  llwarns << "Valid path arguments to buildHTTP are array, string, or undef, you passed type" 
-			  << path.type() << llendl;
+	  LL_WARNS() << "Valid path arguments to buildHTTP are array, string, or undef, you passed type" 
+			  << path.type() << LL_ENDL;
 	}
 	result.mEscapedOpaque = "//" + result.mEscapedAuthority +
 		result.mEscapedPath;
@@ -584,7 +584,7 @@ LLSD LLURI::queryMap() const
 // static
 LLSD LLURI::queryMap(std::string escaped_query_string)
 {
-	lldebugs << "LLURI::queryMap query params: " << escaped_query_string << llendl;
+	LL_DEBUGS() << "LLURI::queryMap query params: " << escaped_query_string << LL_ENDL;
 
 	LLSD result = LLSD::emptyArray();
 	while(!escaped_query_string.empty())
@@ -610,12 +610,12 @@ LLSD LLURI::queryMap(std::string escaped_query_string)
 		{
 			std::string key = unescape(tuple.substr(0,key_end));
 			std::string value = unescape(tuple.substr(key_end+1));
-			lldebugs << "inserting key " << key << " value " << value << llendl;
+			LL_DEBUGS() << "inserting key " << key << " value " << value << LL_ENDL;
 			result[key] = value;
 		}
 		else
 		{
-			lldebugs << "inserting key " << unescape(tuple) << " value true" << llendl;
+			LL_DEBUGS() << "inserting key " << unescape(tuple) << " value true" << LL_ENDL;
 		    result[unescape(tuple)] = true;
 		}
 	}
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index ba4b670b9a..e3671047b4 100755
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -232,7 +232,7 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit)
 		{
 			if(emit)
 			{
-				llwarns << "Warning! Using broken UUID string format" << llendl;
+				LL_WARNS() << "Warning! Using broken UUID string format" << LL_ENDL;
 			}
 			broken_format = TRUE;
 		}
@@ -242,7 +242,7 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit)
 			if(emit)
 			{
 				//don't spam the logs because a resident can't spell.
-				llwarns << "Bad UUID string: " << in_string << llendl;
+				LL_WARNS() << "Bad UUID string: " << in_string << LL_ENDL;
 			}
 			setNull();
 			return FALSE;
@@ -281,7 +281,7 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit)
 		{
 			if(emit)
 			{							
-				llwarns << "Invalid UUID string character" << llendl;
+				LL_WARNS() << "Invalid UUID string character" << LL_ENDL;
 			}
 			setNull();
 			return FALSE;
@@ -306,7 +306,7 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit)
 		{
 			if(emit)
 			{
-				llwarns << "Invalid UUID string character" << llendl;
+				LL_WARNS() << "Invalid UUID string character" << LL_ENDL;
 			}
 			setNull();
 			return FALSE;
diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp
index 3d05a30ac2..4c197dc1d6 100755
--- a/indra/llcommon/llworkerthread.cpp
+++ b/indra/llcommon/llworkerthread.cpp
@@ -50,8 +50,8 @@ LLWorkerThread::~LLWorkerThread()
 	// Delete any workers in the delete queue (should be safe - had better be!)
 	if (!mDeleteList.empty())
 	{
-		llwarns << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
-				<< " entries in delete list." << llendl;
+		LL_WARNS() << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
+				<< " entries in delete list." << LL_ENDL;
 	}
 
 	delete mDeleteMutex;
@@ -65,8 +65,8 @@ void LLWorkerThread::clearDeleteList()
 	// Delete any workers in the delete queue (should be safe - had better be!)
 	if (!mDeleteList.empty())
 	{
-		llwarns << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
-				<< " entries in delete list." << llendl;
+		LL_WARNS() << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
+				<< " entries in delete list." << LL_ENDL;
 
 		mDeleteMutex->lock();
 		for (delete_list_t::iterator iter = mDeleteList.begin(); iter != mDeleteList.end(); ++iter)
@@ -142,7 +142,7 @@ LLWorkerThread::handle_t LLWorkerThread::addWorkRequest(LLWorkerClass* workercla
 	bool res = addRequest(req);
 	if (!res)
 	{
-		llerrs << "add called after LLWorkerThread::cleanupClass()" << llendl;
+		LL_ERRS() << "add called after LLWorkerThread::cleanupClass()" << LL_ENDL;
 		req->deleteRequest();
 		handle = nullHandle();
 	}
@@ -209,7 +209,7 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
 {
 	if (!mWorkerThread)
 	{
-		llerrs << "LLWorkerClass() called with NULL workerthread: " << name << llendl;
+		LL_ERRS() << "LLWorkerClass() called with NULL workerthread: " << name << LL_ENDL;
 	}
 }
 
@@ -223,12 +223,12 @@ LLWorkerClass::~LLWorkerClass()
 		LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle);
 		if (!workreq)
 		{
-			llerrs << "LLWorkerClass destroyed with stale work handle" << llendl;
+			LL_ERRS() << "LLWorkerClass destroyed with stale work handle" << LL_ENDL;
 		}
 		if (workreq->getStatus() != LLWorkerThread::STATUS_ABORTED &&
 			workreq->getStatus() != LLWorkerThread::STATUS_COMPLETE)
 		{
-			llerrs << "LLWorkerClass destroyed with active worker! Worker Status: " << workreq->getStatus() << llendl;
+			LL_ERRS() << "LLWorkerClass destroyed with active worker! Worker Status: " << workreq->getStatus() << LL_ENDL;
 		}
 	}
 }
@@ -238,7 +238,7 @@ void LLWorkerClass::setWorkerThread(LLWorkerThread* workerthread)
 	mMutex.lock();
 	if (mRequestHandle != LLWorkerThread::nullHandle())
 	{
-		llerrs << "LLWorkerClass attempt to change WorkerThread with active worker!" << llendl;
+		LL_ERRS() << "LLWorkerClass attempt to change WorkerThread with active worker!" << LL_ENDL;
 	}
 	mWorkerThread = workerthread;
 	mMutex.unlock();
@@ -298,10 +298,10 @@ void LLWorkerClass::addWork(S32 param, U32 priority)
 	llassert_always(!(mWorkFlags & (WCF_WORKING|WCF_HAVE_WORK)));
 	if (mRequestHandle != LLWorkerThread::nullHandle())
 	{
-		llerrs << "LLWorkerClass attempt to add work with active worker!" << llendl;
+		LL_ERRS() << "LLWorkerClass attempt to add work with active worker!" << LL_ENDL;
 	}
 #if _DEBUG
-// 	llinfos << "addWork: " << mWorkerClassName << " Param: " << param << llendl;
+// 	LL_INFOS() << "addWork: " << mWorkerClassName << " Param: " << param << LL_ENDL;
 #endif
 	startWork(param);
 	clearFlags(WCF_WORK_FINISHED|WCF_WORK_ABORTED);
@@ -316,7 +316,7 @@ void LLWorkerClass::abortWork(bool autocomplete)
 #if _DEBUG
 // 	LLWorkerThread::WorkRequest* workreq = mWorkerThread->getRequest(mRequestHandle);
 // 	if (workreq)
-// 		llinfos << "abortWork: " << mWorkerClassName << " Param: " << workreq->getParam() << llendl;
+// 		LL_INFOS() << "abortWork: " << mWorkerClassName << " Param: " << workreq->getParam() << LL_ENDL;
 #endif
 	if (mRequestHandle != LLWorkerThread::nullHandle())
 	{
diff --git a/indra/llcommon/u64.cpp b/indra/llcommon/u64.cpp
index eea16c5036..02c2c15d26 100755
--- a/indra/llcommon/u64.cpp
+++ b/indra/llcommon/u64.cpp
@@ -36,7 +36,7 @@ U64 str_to_U64(const std::string& str)
 
 	if (!aptr)
 	{
-		llwarns << "str_to_U64: Bad string to U64 conversion attempt: format\n" << llendl;
+		LL_WARNS() << "str_to_U64: Bad string to U64 conversion attempt: format\n" << LL_ENDL;
 	}
 	else
 	{
-- 
cgit v1.2.3


From cc31b4ae7934010762b8aaaa7e190c74a1cd7820 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 12 Aug 2013 20:05:16 -0700
Subject: SH-4399 FIX: Interesting: Texture console MB Bound 0/384 and texture
 queue bounces once per second SH-4346 FIX: Interesting: some integer
 Statistics are displayed as floating point after crossing region boundary
 made llerrs/infos/etc properly variadic wrt tags LL_INFOS("A", "B", "C")
 works, for example fixed unit tests remove llsimplestat

---
 indra/llcommon/llerror.cpp                  | 507 ++++++++++++++--------------
 indra/llcommon/llerror.h                    |  79 +++--
 indra/llcommon/llerrorcontrol.h             |  20 +-
 indra/llcommon/lltrace.cpp                  |   2 +-
 indra/llcommon/lltrace.h                    |  10 +-
 indra/llcommon/lltraceaccumulators.h        |  12 +-
 indra/llcommon/lltracerecording.cpp         | 150 +++++---
 indra/llcommon/lltracerecording.h           |  87 +++--
 indra/llcommon/llunit.h                     |  64 ++--
 indra/llcommon/tests/commonmisc_test.cpp    |  10 +-
 indra/llcommon/tests/llerror_test.cpp       |  90 ++---
 indra/llcommon/tests/llsdserialize_test.cpp |   2 +-
 indra/llcommon/tests/llunits_test.cpp       |   6 +
 13 files changed, 557 insertions(+), 482 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 652d0e212a..6f128d0a20 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -51,7 +51,26 @@
 #include "lltimer.h"
 
 namespace {
-#if !LL_WINDOWS
+#if LL_WINDOWS
+	void debugger_print(const std::string& s)
+	{
+		// Be careful when calling OutputDebugString as it throws DBG_PRINTEXCEPTION_C 
+		// which works just fine under the windows debugger, but can cause users who
+		// have enabled SEHOP exception chain validation to crash due to interactions
+		// between the Win 32-bit exception handling and boost coroutine fiber stacks. BUG-2707
+		//
+		if (IsDebuggerPresent())
+		{
+			// Need UTF16 for Unicode OutputDebugString
+			//
+			if (s.size())
+			{
+				OutputDebugString(utf8str_to_utf16str(s).c_str());
+				OutputDebugString(TEXT("\n"));
+			}
+		}
+	}
+#else
 	class RecordToSyslog : public LLError::Recorder
 	{
 	public:
@@ -98,6 +117,7 @@ namespace {
 			{
 				LL_INFOS() << "Error setting log file to " << filename << LL_ENDL;
 			}
+			mWantsTime = true;
 		}
 		
 		~RecordToFile()
@@ -107,8 +127,6 @@ namespace {
 		
 		bool okay() { return mFile; }
 		
-		virtual bool wantsTime() { return true; }
-		
 		virtual void recordMessage(LLError::ELevel level,
 									const std::string& message)
 		{
@@ -123,10 +141,11 @@ namespace {
 	class RecordToStderr : public LLError::Recorder
 	{
 	public:
-		RecordToStderr(bool timestamp) : mTimestamp(timestamp), mUseANSI(ANSI_PROBE) { }
+		RecordToStderr(bool timestamp) : mUseANSI(ANSI_PROBE) 
+		{
+			mWantsTime = timestamp;
+		}
 
-		virtual bool wantsTime() { return mTimestamp; }
-		
 		virtual void recordMessage(LLError::ELevel level,
 					   const std::string& message)
 		{
@@ -156,7 +175,6 @@ namespace {
 		}
 	
 	private:
-		bool				mTimestamp;
 		enum ANSIState 
 		{
 			ANSI_PROBE, 
@@ -202,10 +220,13 @@ namespace {
 	class RecordToWinDebug: public LLError::Recorder
 	{
 	public:
+		RecordToWinDebug()
+		{}
+
 		virtual void recordMessage(LLError::ELevel level,
 								   const std::string& message)
 		{
-			LL_WINDOWS_OUTPUT_DEBUG(message);
+			debugger_print(message);
 		}
 	};
 #endif
@@ -217,7 +238,7 @@ namespace
 	std::string className(const std::type_info& type)
 	{
 #ifdef __GNUC__
-		// GCC: type_info::name() returns a mangled class name, must demangle
+		// GCC: type_info::name() returns a mangled class name,st demangle
 
 		static size_t abi_name_len = 100;
 		static char* abi_name_buf = (char*)malloc(abi_name_len);
@@ -394,25 +415,25 @@ namespace LLError
 	class Settings
 	{
 	public:
-		bool printLocation;
+		bool                                mPrintLocation;
 
-		LLError::ELevel defaultLevel;
-		
-		LevelMap functionLevelMap;
-		LevelMap classLevelMap;
-		LevelMap fileLevelMap;
-		LevelMap tagLevelMap;
-		std::map<std::string, unsigned int> uniqueLogMessages;
-		
-		LLError::FatalFunction crashFunction;
-		LLError::TimeFunction timeFunction;
-		
-		Recorders recorders;
-		Recorder* fileRecorder;
-		Recorder* fixedBufferRecorder;
-		std::string fileRecorderFileName;
-		
-		int shouldLogCallCounter;
+		LLError::ELevel                     mDefaultLevel;
+
+		LevelMap                            mFunctionLevelMap;
+		LevelMap                            mClassLevelMap;
+		LevelMap                            mFileLevelMap;
+		LevelMap                            mTagLevelMap;
+		std::map<std::string, unsigned int> mUniqueLogMessages;
+
+		LLError::FatalFunction              mCrashFunction;
+		LLError::TimeFunction               mTimeFunction;
+
+		Recorders                           mRecorders;
+		Recorder*                           mFileRecorder;
+		Recorder*                           mFixedBufferRecorder;
+		std::string                         mFileRecorderFileName;
+
+		int									mShouldLogCallCounter;
 		
 		static Settings& get();
 	
@@ -422,18 +443,18 @@ namespace LLError
 		
 	private:
 		Settings()
-			:	printLocation(false),
-				defaultLevel(LLError::LEVEL_DEBUG),
-				crashFunction(),
-				timeFunction(NULL),
-				fileRecorder(NULL),
-				fixedBufferRecorder(NULL),
-				shouldLogCallCounter(0)
-			{ }
+		:	mPrintLocation(false),
+			mDefaultLevel(LLError::LEVEL_DEBUG),
+			mCrashFunction(),
+			mTimeFunction(NULL),
+			mFileRecorder(NULL),
+			mFixedBufferRecorder(NULL),
+			mShouldLogCallCounter(NULL)
+		{}
 		
 		~Settings()
 		{
-			for_each(recorders.begin(), recorders.end(),
+			for_each(mRecorders.begin(), mRecorders.end(),
 					 DeletePointer());
 		}
 		
@@ -494,8 +515,8 @@ namespace LLError
 					const std::type_info& class_info, 
 					const char* function, 
 					bool printOnce,
-					const char* broadTag, 
-					const char* narrowTag)
+					const char** tags, 
+					size_t tag_count)
 	:	mLevel(level), 
 		mFile(file), 
 		mLine(line),
@@ -504,37 +525,53 @@ namespace LLError
 		mCached(false), 
 		mShouldLog(false), 
 		mPrintOnce(printOnce),
-		mBroadTag(broadTag), 
-		mNarrowTag(narrowTag)
-	{}
-
-	CallSite::CallSite(ELevel level,
-		const char* file,
-		int line,
-		const std::type_info& class_info, 
-		const char* function, 
-		bool printOnce,
-		const char* broadTag, 
-		const char* narrowTag,
-		const char*,
-		...)
-	:	mLevel(level), 
-		mFile(file), 
-		mLine(line),
-		mClassInfo(class_info), 
-		mFunction(function),
-		mCached(false), 
-		mShouldLog(false), 
-		mPrintOnce(printOnce),
-		mBroadTag(broadTag), 
-		mNarrowTag(narrowTag)
+		mTags(new const char* [tag_count]),
+		mTagCount(tag_count)
 	{
-		LL_ERRS() << "No support for more than 2 logging tags" << LL_ENDL;
+		for (int i = 0; i < tag_count; i++)
+		{
+			mTags[i] = tags[i];
+		}
+
+		switch (mLevel)
+		{
+		case LEVEL_DEBUG:		mLevelString = "DEBUG:";	break;
+		case LEVEL_INFO:		mLevelString = "INFO:";		break;
+		case LEVEL_WARN:		mLevelString = "WARNING:";	break;
+		case LEVEL_ERROR:		mLevelString = "ERROR:";	break;
+		default:				mLevelString = "XXX:";		break;
+		};
+
+		mLocationString = llformat("%s(%d) :", abbreviateFile(mFile).c_str(), mLine);
+#if LL_WINDOWS
+		// DevStudio: __FUNCTION__ already includes the full class name
+#else
+#if LL_LINUX
+		// gross, but typeid comparison seems to always fail here with gcc4.1
+		if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name()))
+#else
+		if (site.mClassInfo != typeid(NoClassInfo))
+#endif // LL_LINUX
+		{
+			mFunctionString = className(site.mClassInfo) + "::";
+		}
+#endif
+		mFunctionString += std::string(mFunction) + ":";
+		for (size_t i = 0; i < mTagCount; i++)
+		{
+			mTagString += std::string("#") + mTags[i] + ((i == mTagCount - 1) ? "" : " ");
+		}
 	}
 
+	CallSite::~CallSite()
+	{
+		delete []mTags;
+	}
 
 	void CallSite::invalidate()
-		{ mCached = false; }
+	{
+		mCached = false; 
+	}
 }
 
 namespace
@@ -620,25 +657,25 @@ namespace LLError
 	void setPrintLocation(bool print)
 	{
 		Settings& s = Settings::get();
-		s.printLocation = print;
+		s.mPrintLocation = print;
 	}
 
 	void setFatalFunction(const FatalFunction& f)
 	{
 		Settings& s = Settings::get();
-		s.crashFunction = f;
+		s.mCrashFunction = f;
 	}
 
     FatalFunction getFatalFunction()
     {
         Settings& s = Settings::get();
-        return s.crashFunction;
+        return s.mCrashFunction;
     }
 
 	void setTimeFunction(TimeFunction f)
 	{
 		Settings& s = Settings::get();
-		s.timeFunction = f;
+		s.mTimeFunction = f;
 	}
 
 	void setDefaultLevel(ELevel level)
@@ -646,13 +683,13 @@ namespace LLError
 		Globals& g = Globals::get();
 		Settings& s = Settings::get();
 		g.invalidateCallSites();
-		s.defaultLevel = level;
+		s.mDefaultLevel = level;
 	}
 
 	ELevel getDefaultLevel()
 	{
 		Settings& s = Settings::get();
-		return s.defaultLevel;
+		return s.mDefaultLevel;
 	}
 
 	void setFunctionLevel(const std::string& function_name, ELevel level)
@@ -660,7 +697,7 @@ namespace LLError
 		Globals& g = Globals::get();
 		Settings& s = Settings::get();
 		g.invalidateCallSites();
-		s.functionLevelMap[function_name] = level;
+		s.mFunctionLevelMap[function_name] = level;
 	}
 
 	void setClassLevel(const std::string& class_name, ELevel level)
@@ -668,7 +705,7 @@ namespace LLError
 		Globals& g = Globals::get();
 		Settings& s = Settings::get();
 		g.invalidateCallSites();
-		s.classLevelMap[class_name] = level;
+		s.mClassLevelMap[class_name] = level;
 	}
 
 	void setFileLevel(const std::string& file_name, ELevel level)
@@ -676,7 +713,7 @@ namespace LLError
 		Globals& g = Globals::get();
 		Settings& s = Settings::get();
 		g.invalidateCallSites();
-		s.fileLevelMap[file_name] = level;
+		s.mFileLevelMap[file_name] = level;
 	}
 
 	void setTagLevel(const std::string& tag_name, ELevel level)
@@ -684,7 +721,7 @@ namespace LLError
 		Globals& g = Globals::get();
 		Settings& s = Settings::get();
 		g.invalidateCallSites();
-		s.tagLevelMap[tag_name] = level;
+		s.mTagLevelMap[tag_name] = level;
 	}
 
 	LLError::ELevel decodeLevel(std::string name)
@@ -732,11 +769,11 @@ namespace LLError
 		Settings& s = Settings::get();
 		
 		g.invalidateCallSites();
-		s.functionLevelMap.clear();
-		s.classLevelMap.clear();
-		s.fileLevelMap.clear();
-		s.tagLevelMap.clear();
-		s.uniqueLogMessages.clear();
+		s.mFunctionLevelMap.clear();
+		s.mClassLevelMap.clear();
+		s.mFileLevelMap.clear();
+		s.mTagLevelMap.clear();
+		s.mUniqueLogMessages.clear();
 		
 		setPrintLocation(config["print-location"]);
 		setDefaultLevel(decodeLevel(config["default-level"]));
@@ -749,10 +786,10 @@ namespace LLError
 			
 			ELevel level = decodeLevel(entry["level"]);
 			
-			setLevels(s.functionLevelMap,	entry["functions"],	level);
-			setLevels(s.classLevelMap,		entry["classes"],	level);
-			setLevels(s.fileLevelMap,		entry["files"],		level);
-			setLevels(s.tagLevelMap,		entry["tags"],		level);
+			setLevels(s.mFunctionLevelMap,	entry["functions"],	level);
+			setLevels(s.mClassLevelMap,		entry["classes"],	level);
+			setLevels(s.mFileLevelMap,		entry["files"],		level);
+			setLevels(s.mTagLevelMap,		entry["tags"],		level);
 		}
 	}
 }
@@ -760,19 +797,44 @@ namespace LLError
 
 namespace LLError
 {
+	Recorder::Recorder()
+	:	mWantsTime(false),
+		mWantsTags(false),
+		mWantsLevel(true),
+		mWantsLocation(false),
+		mWantsFunctionName(true)
+	{}
+
 	Recorder::~Recorder()
 	{}
 
-	// virtual
 	bool Recorder::wantsTime()
 	{ 
-		return false; 
+		return mWantsTime; 
 	}
 
 	// virtual
 	bool Recorder::wantsTags()
 	{
-		return false;
+		return mWantsTags;
+	}
+
+	// virtual 
+	bool Recorder::wantsLevel() 
+	{ 
+		return mWantsLevel;
+	}
+
+	// virtual 
+	bool Recorder::wantsLocation() 
+	{ 
+		return mWantsLocation;
+	}
+
+	// virtual 
+	bool Recorder::wantsFunctionName() 
+	{ 
+		return mWantsFunctionName;
 	}
 
 	void addRecorder(Recorder* recorder)
@@ -782,7 +844,7 @@ namespace LLError
 			return;
 		}
 		Settings& s = Settings::get();
-		s.recorders.push_back(recorder);
+		s.mRecorders.push_back(recorder);
 	}
 
 	void removeRecorder(Recorder* recorder)
@@ -792,8 +854,8 @@ namespace LLError
 			return;
 		}
 		Settings& s = Settings::get();
-		s.recorders.erase(std::remove(s.recorders.begin(), s.recorders.end(), recorder),
-							s.recorders.end());
+		s.mRecorders.erase(std::remove(s.mRecorders.begin(), s.mRecorders.end(), recorder),
+							s.mRecorders.end());
 	}
 }
 
@@ -803,10 +865,10 @@ namespace LLError
 	{
 		LLError::Settings& s = LLError::Settings::get();
 
-		removeRecorder(s.fileRecorder);
-		delete s.fileRecorder;
-		s.fileRecorder = NULL;
-		s.fileRecorderFileName.clear();
+		removeRecorder(s.mFileRecorder);
+		delete s.mFileRecorder;
+		s.mFileRecorder = NULL;
+		s.mFileRecorderFileName.clear();
 		
 		if (file_name.empty())
 		{
@@ -820,8 +882,8 @@ namespace LLError
 			return;
 		}
 
-		s.fileRecorderFileName = file_name;
-		s.fileRecorder = f;
+		s.mFileRecorderFileName = file_name;
+		s.mFileRecorder = f;
 		addRecorder(f);
 	}
 	
@@ -829,132 +891,114 @@ namespace LLError
 	{
 		LLError::Settings& s = LLError::Settings::get();
 
-		removeRecorder(s.fixedBufferRecorder);
-		delete s.fixedBufferRecorder;
-		s.fixedBufferRecorder = NULL;
+		removeRecorder(s.mFixedBufferRecorder);
+		delete s.mFixedBufferRecorder;
+		s.mFixedBufferRecorder = NULL;
 		
 		if (!fixedBuffer)
 		{
 			return;
 		}
 		
-		s.fixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
-		addRecorder(s.fixedBufferRecorder);
+		s.mFixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
+		addRecorder(s.mFixedBufferRecorder);
 	}
 
 	std::string logFileName()
 	{
 		LLError::Settings& s = LLError::Settings::get();
-		return s.fileRecorderFileName;
+		return s.mFileRecorderFileName;
 	}
 }
 
 namespace
 {
-	void writeToRecorders(const LLError::CallSite& site, const std::string& message)
+	void writeToRecorders(const LLError::CallSite& site, const std::string& message, bool show_location = true, bool show_time = true, bool show_tags = true, bool show_level = true, bool show_function = true)
 	{
 		LLError::ELevel level = site.mLevel;
 		LLError::Settings& s = LLError::Settings::get();
 	
-		std::string messageWithTime;
-		std::string messageWithTags;
-		std::string messageWithTagsAndTime;
-		
-		for (Recorders::const_iterator i = s.recorders.begin();
-			i != s.recorders.end();
+		for (Recorders::const_iterator i = s.mRecorders.begin();
+			i != s.mRecorders.end();
 			++i)
 		{
 			LLError::Recorder* r = *i;
-			
-			if (r->wantsTime() && s.timeFunction != NULL)
-			{
-				if (r->wantsTags())
-				{
-					if (messageWithTagsAndTime.empty())
-					{
-						messageWithTagsAndTime = s.timeFunction() + " " 
-												+ (site.mBroadTag ? (std::string("#") + std::string(site.mBroadTag) + " ") : std::string())  
-												+ (site.mNarrowTag ? (std::string("#") + std::string(site.mNarrowTag) + " ") : std::string()) 
-												+ message;
-					}
-
-					r->recordMessage(level, messageWithTagsAndTime);
-				}
-				else
-				{
-					if (messageWithTime.empty())
-					{
-						messageWithTime = s.timeFunction() + " " + message;
-					}
 
-					r->recordMessage(level, messageWithTime);
-				}
-			}
-			else
+			std::ostringstream message_stream;
+
+			if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s.mPrintLocation))
 			{
-				if (r->wantsTags())
-				{
-					if (messageWithTags.empty())
-					{
-						messageWithTags = (site.mBroadTag ? (std::string("#") + std::string(site.mBroadTag) + " ") : std::string())  
-										+ (site.mNarrowTag ? (std::string("#") + std::string(site.mNarrowTag) + " ") : std::string()) 
-										+ message;
-					}
-
-					r->recordMessage(level, messageWithTags);
-				}
-				else
-				{
-					r->recordMessage(level, message);				
-				}
+				message_stream << site.mLocationString << " ";
 			}
-		}
-	}
-}
-
 
-/*
-Recorder formats:
+			if (show_time && r->wantsTime() && s.mTimeFunction != NULL)
+			{
+				message_stream << s.mTimeFunction() << " ";
+			}
 
-$type = "ERROR" | "WARNING" | "ALERT" | "INFO" | "DEBUG"
-$loc = "$file($line)"
-$msg = "$loc : " if FATAL or printing loc
-		"" otherwise
-$msg += "$type: "
-$msg += contents of stringstream
+			if (show_tags && r->wantsTags())
+			{
+				message_stream << site.mTagString << " ";
+			}
 
-$time = "%Y-%m-%dT%H:%M:%SZ" if UTC
-	 or "%Y-%m-%dT%H:%M:%S %Z" if local
+			if (show_level && r->wantsLevel())
+			{
+				message_stream << site.mLevelString << " ";
+			}
+			
+			if (show_function && r->wantsFunctionName())
+			{
+				message_stream << site.mFunctionString << " ";
+			}
 
-syslog:	"$msg"
-file: "$time $msg\n"
-stderr: "$time $msg\n" except on windows, "$msg\n"
-fixedbuf: "$msg"
-winddebug: "$msg\n"
+			message_stream << message;
 
-Note: if FATAL, an additional line gets logged first, with $msg set to
-	"$loc : error"
-	
-You get:
-	llfoo.cpp(42) : error
-	llfoo.cpp(42) : ERROR: something
-	
-*/
+			r->recordMessage(level, message_stream.str());
+		}
+	}
+}
 
 namespace {
 	bool checkLevelMap(const LevelMap& map, const std::string& key,
 						LLError::ELevel& level)
 	{
+		bool stop_checking;
 		LevelMap::const_iterator i = map.find(key);
 		if (i == map.end())
 		{
-			return false;
+			return stop_checking = false;
 		}
 		
-			level = i->second;
-		return true;
+		level = i->second;
+		return stop_checking = true;
 	}
 	
+	bool checkLevelMap(	const LevelMap& map, 
+						const char *const * keys, 
+						size_t count,
+						LLError::ELevel& level)
+	{
+		bool found_level = false;
+
+		LLError::ELevel tag_level = LLError::LEVEL_NONE;
+
+		for (size_t i = 0; i < count; i++)
+		{
+			LevelMap::const_iterator it = map.find(keys[i]);
+			if (it != map.end())
+			{
+				found_level = true;
+				tag_level = llmin(tag_level, it->second);
+			}
+		}
+
+		if (found_level)
+		{
+			level = tag_level;
+		}
+		return found_level;
+	}
+
 	class LogLock
 	{
 	public:
@@ -1019,10 +1063,10 @@ namespace LLError
 		Globals& g = Globals::get();
 		Settings& s = Settings::get();
 		
-		s.shouldLogCallCounter += 1;
-		
-		std::string class_name = className(site.mClassInfo);
-		std::string function_name = functionName(site.mFunction);
+		s.mShouldLogCallCounter++;
+
+		std::string& class_name = className(site.mClassInfo);
+		std::string& function_name = functionName(site.mFunction);
 #if LL_LINUX
 		// gross, but typeid comparison seems to always fail here with gcc4.1
 		if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name()))
@@ -1033,17 +1077,18 @@ namespace LLError
 			function_name = class_name + "::" + function_name;
 		}
 
-		ELevel compareLevel = s.defaultLevel;
+		ELevel compareLevel = s.mDefaultLevel;
 
 		// The most specific match found will be used as the log level,
 		// since the computation short circuits.
 		// So, in increasing order of importance:
-		// Default < Broad Tag < File < Class < Function < Narrow Tag
-		((site.mNarrowTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mNarrowTag, compareLevel) : false)
-		|| checkLevelMap(s.functionLevelMap, function_name, compareLevel)
-		|| checkLevelMap(s.classLevelMap, class_name, compareLevel)
-		|| checkLevelMap(s.fileLevelMap, abbreviateFile(site.mFile), compareLevel)
-		|| ((site.mBroadTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mBroadTag, compareLevel) : false);
+		// Default < Tags < File < Class < Function
+		checkLevelMap(s.mFunctionLevelMap, function_name, compareLevel)
+		|| checkLevelMap(s.mClassLevelMap, class_name, compareLevel)
+		|| checkLevelMap(s.mFileLevelMap, abbreviateFile(site.mFile), compareLevel)
+		|| (site.mTagCount > 0
+			? checkLevelMap(s.mTagLevelMap, site.mTags, site.mTagCount, compareLevel) 
+			: false);
 
 		site.mCached = true;
 		g.addCallSite(site);
@@ -1126,56 +1171,21 @@ namespace LLError
 
 		if (site.mLevel == LEVEL_ERROR)
 		{
-			std::ostringstream fatalMessage;
-			fatalMessage << abbreviateFile(site.mFile)
-						<< "(" << site.mLine << ") : error";
-			
-			writeToRecorders(site, fatalMessage.str());
+			writeToRecorders(site, "error", true, true, true, false, false);
 		}
 		
+		std::ostringstream message_stream;
 		
-		std::ostringstream prefix;
-
-		switch (site.mLevel)
-		{
-			case LEVEL_DEBUG:		prefix << "DEBUG: ";	break;
-			case LEVEL_INFO:		prefix << "INFO: ";		break;
-			case LEVEL_WARN:		prefix << "WARNING: ";	break;
-			case LEVEL_ERROR:		prefix << "ERROR: ";	break;
-			default:				prefix << "XXX: ";		break;
-		};
-		
-		if (s.printLocation)
-		{
-			prefix << abbreviateFile(site.mFile)
-					<< "(" << site.mLine << ") : ";
-		}
-		
-	#if LL_WINDOWS
-		// DevStudio: __FUNCTION__ already includes the full class name
-	#else
-                #if LL_LINUX
-		// gross, but typeid comparison seems to always fail here with gcc4.1
-		if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name()))
-                #else
-		if (site.mClassInfo != typeid(NoClassInfo))
-                #endif // LL_LINUX
-		{
-			prefix << className(site.mClassInfo) << "::";
-		}
-	#endif
-		prefix << site.mFunction << ": ";
-
 		if (site.mPrintOnce)
 		{
-			std::map<std::string, unsigned int>::iterator messageIter = s.uniqueLogMessages.find(message);
-			if (messageIter != s.uniqueLogMessages.end())
+			std::map<std::string, unsigned int>::iterator messageIter = s.mUniqueLogMessages.find(message);
+			if (messageIter != s.mUniqueLogMessages.end())
 			{
 				messageIter->second++;
 				unsigned int num_messages = messageIter->second;
 				if (num_messages == 10 || num_messages == 50 || (num_messages % 100) == 0)
 				{
-					prefix << "ONCE (" << num_messages << "th time seen): ";
+					message_stream << "ONCE (" << num_messages << "th time seen): ";
 				} 
 				else
 				{
@@ -1184,26 +1194,22 @@ namespace LLError
 			}
 			else 
 			{
-				prefix << "ONCE: ";
-				s.uniqueLogMessages[message] = 1;
+				message_stream << "ONCE: ";
+				s.mUniqueLogMessages[message] = 1;
 			}
 		}
 		
-		prefix << message;
-		message = prefix.str();
+		message_stream << message;
 		
-		writeToRecorders(site, message);
+		writeToRecorders(site, message_stream.str());
 		
-		if (site.mLevel == LEVEL_ERROR  &&  s.crashFunction)
+		if (site.mLevel == LEVEL_ERROR  &&  s.mCrashFunction)
 		{
-			s.crashFunction(message);
+			s.mCrashFunction(message_stream.str());
 		}
 	}
 }
 
-
-
-
 namespace LLError
 {
 	Settings* saveAndResetSettings()
@@ -1260,7 +1266,7 @@ namespace LLError
 	int shouldLogCallCount()
 	{
 		Settings& s = Settings::get();
-		return s.shouldLogCallCounter;
+		return s.mShouldLogCallCounter;
 	}
 
 #if LL_WINDOWS
@@ -1471,26 +1477,5 @@ namespace LLError
        sIndex = 0;
    }
 
-#if LL_WINDOWS
-	void LLOutputDebugUTF8(const std::string& s)
-	{
-		// Be careful when calling OutputDebugString as it throws DBG_PRINTEXCEPTION_C 
-		// which works just fine under the windows debugger, but can cause users who
-		// have enabled SEHOP exception chain validation to crash due to interactions
-		// between the Win 32-bit exception handling and boost coroutine fiber stacks. BUG-2707
-		//
-		if (IsDebuggerPresent())
-		{
-			// Need UTF16 for Unicode OutputDebugString
-			//
-			if (s.size())
-			{
-				OutputDebugString(utf8str_to_utf16str(s).c_str());
-				OutputDebugString(TEXT("\n"));
-			}
-		}
-	}
-#endif
-
 }
 
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index ef25a0173c..7810676388 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -194,14 +194,26 @@ namespace LLError
 		// Represents a specific place in the code where a message is logged
 		// This is public because it is used by the macros below.  It is not
 		// intended for public use.
-		CallSite(ELevel, const char* file, int line,
-				const std::type_info& class_info, const char* function, bool printOnce, const char* broadTag = NULL, const char* narrowTag = NULL );
+		CallSite(ELevel level, 
+				const char* file, 
+				int line,
+				const std::type_info& class_info, 
+				const char* function, 
+				bool print_once, 
+				const char** tags, 
+				size_t tag_count);
+
+		~CallSite();
 
 #ifdef LL_LIBRARY_INCLUDE
 		bool shouldLog();
 #else // LL_LIBRARY_INCLUDE
 		bool shouldLog()
-			{ return mCached ? mShouldLog : Log::shouldLog(*this); }
+		{ 
+			return mCached 
+					? mShouldLog 
+					: Log::shouldLog(*this); 
+		}
 			// this member function needs to be in-line for efficiency
 #endif // LL_LIBRARY_INCLUDE
 		
@@ -213,20 +225,17 @@ namespace LLError
 		const int				mLine;
 		const std::type_info&   mClassInfo;
 		const char* const		mFunction;
-		const char* const		mBroadTag;
-		const char* const		mNarrowTag;
+		const char**			mTags;
+		size_t					mTagCount;
 		const bool				mPrintOnce;
-		
-		// these implement a cache of the call to shouldLog()
-		bool mCached;
-		bool mShouldLog;
+		const char*				mLevelString;
+		std::string				mLocationString,
+								mFunctionString,
+								mTagString;
+		bool					mCached,
+								mShouldLog;
 		
 		friend class Log;
-
-	private:
-		// 3 or more tags not currently supported
-		CallSite(ELevel, const char* file, int line,
-			const std::type_info& class_info, const char* function, bool printOnce, const char* broadTag, const char* narrowTag, const char*, ...);
 	};
 	
 	
@@ -258,30 +267,21 @@ namespace LLError
        static void clear() ;
 	   static void end(std::ostringstream* _out) ;
    }; 
-
-#if LL_WINDOWS
-	void LLOutputDebugUTF8(const std::string& s);
-#endif
-
 }
 
-#if LL_WINDOWS
-	// Macro accepting a std::string for display in windows debugging console
-	#define LL_WINDOWS_OUTPUT_DEBUG(a) LLError::LLOutputDebugUTF8(a)
-#else
-	#define LL_WINDOWS_OUTPUT_DEBUG(a)
-#endif
-
 //this is cheaper than llcallstacks if no need to output other variables to call stacks. 
 #define LL_PUSH_CALLSTACKS() LLError::LLCallStacks::push(__FUNCTION__, __LINE__)
-#define llcallstacks \
-	{\
+
+#define llcallstacks                                                                      \
+	{                                                                                     \
        std::ostringstream* _out = LLError::LLCallStacks::insert(__FUNCTION__, __LINE__) ; \
        (*_out)
-#define llcallstacksendl \
-		LLError::End(); \
+
+#define llcallstacksendl                   \
+		LLError::End();                    \
 		LLError::LLCallStacks::end(_out) ; \
 	}
+
 #define LL_CLEAR_CALLSTACKS() LLError::LLCallStacks::clear()
 #define LL_PRINT_CALLSTACKS() LLError::LLCallStacks::print() 
 
@@ -302,13 +302,18 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 // See top of file for common usage.	
 /////////////////////////////////
 
-#define lllog(level, once, ...)																	     \
-	do {                                                                                             \
-		static LLError::CallSite _site(                                                              \
-		    level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, ##__VA_ARGS__ );\
-		if (LL_UNLIKELY(_site.shouldLog()))			                                                 \
-		{                                                                                            \
-			std::ostringstream* _out = LLError::Log::out();                                          \
+// this macro uses a one-shot do statement to avoid parsing errors when writing:
+// if (condition) LL_INFOS() << "True" << LLENDL; else LLINFOS() << "False" << LLENDL
+
+#define lllog(level, once, ...)																	          \
+	do {                                                                                                  \
+		const char* tags[] = {"", ##__VA_ARGS__};													      \
+		size_t tag_count = LL_ARRAY_SIZE(tags) - 1;														  \
+		static LLError::CallSite _site(                                                                   \
+		    level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, &tags[1], tag_count);\
+		if (LL_UNLIKELY(_site.shouldLog()))			                                                      \
+		{                                                                                                 \
+			std::ostringstream* _out = LLError::Log::out();                                               \
 			(*_out)
 
 //Use this construct if you need to do computation in the middle of a
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index 7c9df57115..aab695094c 100755
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -136,18 +136,24 @@ namespace LLError
 	{
 		// An object that handles the actual output or error messages.
 	public:
+		Recorder();
 		virtual ~Recorder();
 
 		virtual void recordMessage(LLError::ELevel, const std::string& message) = 0;
 			// use the level for better display, not for filtering
 
-		virtual bool wantsTime(); // default returns false
-			// override and return true if the recorder wants the time string
-			// included in the text of the message
-
-		virtual bool wantsTags(); // default returns false
-			// override ands return true if the recorder wants the tags included
-			// in the text of the message
+		bool wantsTime();
+		bool wantsTags();
+		bool wantsLevel();
+		bool wantsLocation(); 
+		bool wantsFunctionName();
+
+	protected:
+		bool	mWantsTime,
+				mWantsTags,
+				mWantsLevel,
+				mWantsLocation,
+				mWantsFunctionName;
 	};
 
 	/**
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index eedf1b06f1..436ad9a0a2 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -45,7 +45,7 @@ TraceBase::TraceBase( const char* name, const char* description )
 #endif
 }
 
-const char* TraceBase::getUnitLabel()
+const char* TraceBase::getUnitLabel() const
 {
 	return "";
 }
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 75e913a348..1f86aadaba 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -58,7 +58,7 @@ class TraceBase
 public:
 	TraceBase(const char* name, const char* description);
 	virtual ~TraceBase() {};
-	virtual const char* getUnitLabel();
+	virtual const char* getUnitLabel() const;
 
 	const std::string& getName() const { return mName; }
 	const std::string& getDescription() const { return mDescription; }
@@ -129,7 +129,7 @@ public:
 	:	trace_t(name, description)
 	{}
 
-	/*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); }
+	/*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
 
 };
 
@@ -153,7 +153,7 @@ public:
 	:	trace_t(name, description)
 	{}
 
-	/*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); }
+	/*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
 };
 
 template<typename T, typename VALUE_T>
@@ -176,7 +176,7 @@ public:
 	:	trace_t(name, description)
 	{}
 
-	/*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); }
+	/*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
 };
 
 template<typename T, typename VALUE_T>
@@ -227,7 +227,7 @@ public:
 	:	trace_t(name)
 	{}
 
-	/*virtual*/ const char* getUnitLabel() { return "B"; }
+	/*virtual*/ const char* getUnitLabel() const { return "B"; }
 
 	TraceType<MemStatAccumulator::AllocationCountFacet>& allocationCount() 
 	{ 
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 5871dc4bea..ef73bd3091 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -223,7 +223,6 @@ namespace LLTrace
 	{
 	public:
 		typedef F64 value_t;
-		typedef F64 mean_t;
 
 		EventAccumulator()
 		:	mSum(NaN),
@@ -269,6 +268,7 @@ namespace LLTrace
 		F64	getLastValue() const         { return mLastValue; }
 		F64	getMean() const              { return mMean; }
 		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mNumSamples); }
+		F64 getSumOfSquares() const		 { return mSumOfSquares; }
 		U32 getSampleCount() const       { return mNumSamples; }
 		bool hasValue() const			 { return mNumSamples > 0; }
 
@@ -289,7 +289,6 @@ namespace LLTrace
 	{
 	public:
 		typedef F64 value_t;
-		typedef F64 mean_t;
 
 		SampleAccumulator()
 		:	mSum(0),
@@ -353,6 +352,8 @@ namespace LLTrace
 		F64	getLastValue() const         { return mLastValue; }
 		F64	getMean() const              { return mMean; }
 		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); }
+		F64 getSumOfSquares() const		 { return mSumOfSquares; }
+		LLUnitImplicit<F64, LLUnits::Seconds> getSamplingTime() { return mTotalSamplingTime; }
 		U32 getSampleCount() const       { return mNumSamples; }
 		bool hasValue() const            { return mHasValue; }
 
@@ -378,7 +379,6 @@ namespace LLTrace
 	{
 	public:
 		typedef F64 value_t;
-		typedef F64 mean_t;
 
 		CountAccumulator()
 		:	mSum(0),
@@ -419,20 +419,17 @@ namespace LLTrace
 	{
 	public:
 		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
 		struct CallCountFacet 
 		{
 			typedef U32 value_t;
-			typedef F32 mean_t;
 		};
 
 		struct SelfTimeFacet
 		{
 			typedef LLUnit<F64, LLUnits::Seconds> value_t;
-			typedef LLUnit<F64, LLUnits::Seconds> mean_t;
 		};
 
 		TimeBlockAccumulator();
@@ -486,19 +483,16 @@ namespace LLTrace
 		struct AllocationCountFacet 
 		{
 			typedef U32 value_t;
-			typedef F32 mean_t;
 		};
 
 		struct DeallocationCountFacet 
 		{
 			typedef U32 value_t;
-			typedef F32 mean_t;
 		};
 
 		struct ChildMemFacet
 		{
 			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 a4d58d8ab1..42d97ce314 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -242,9 +242,7 @@ F64 Recording::getSum( const TraceType<EventAccumulator>& stat )
 F64 Recording::getPerSec( const TraceType<CountAccumulator>& stat )
 {
 	F64 sum = mBuffers->mCounts[stat.getIndex()].getSum();
-	return  (sum != 0.0) 
-		? (sum / mElapsedSeconds.value())
-		: 0.0;
+	return  sum / mElapsedSeconds.value();
 }
 
 U32 Recording::getSampleCount( const TraceType<CountAccumulator>& stat )
@@ -522,71 +520,98 @@ void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
 	getCurRecording().splitTo(other.getCurRecording());
 }
 
-
-F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
 {
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-	F64 mean = 0;
-	if (num_periods <= 0) { return mean; }
-
-	S32 total_sample_count = 0;
-
+	bool has_value = false;
+	F64 min_val = std::numeric_limits<F64>::max();
 	for (S32 i = 1; i <= num_periods; i++)
 	{
-		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		Recording& recording = mRecordingPeriods[index];
-
+		Recording& recording = getPrevRecording(i);
 		if (recording.hasValue(stat))
 		{
-			S32 period_sample_count = recording.getSampleCount(stat);
-			mean += recording.getMean(stat) * period_sample_count;
-			total_sample_count += period_sample_count;
+			min_val = llmin(min_val, recording.getMin(stat));
+			has_value = true;
 		}
 	}
 
-	if (total_sample_count)
+	return has_value 
+			? min_val 
+			: NaN;
+}
+
+F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+{
+	size_t total_periods = mRecordingPeriods.size();
+	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+
+	bool has_value = false;
+	F64 max_val = std::numeric_limits<F64>::min();
+	for (S32 i = 1; i <= num_periods; i++)
 	{
-		mean = mean / total_sample_count;
+		Recording& recording = getPrevRecording(i);
+		if (recording.hasValue(stat))
+		{
+			max_val = llmax(max_val, recording.getMax(stat));
+			has_value = true;
+		}
 	}
-	return mean;
+
+	return has_value 
+			? max_val 
+			: NaN;
 }
 
-F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+// calculates means using aggregates per period
+F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
 {
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-	F64 min_val = std::numeric_limits<F64>::max();
+	F64 mean = 0;
+	S32 valid_period_count = 0;
+
 	for (S32 i = 1; i <= num_periods; i++)
 	{
-		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		Recording& recording = mRecordingPeriods[index];
+		Recording& recording = getPrevRecording(i);
 		if (recording.hasValue(stat))
 		{
-			min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat));
+			mean += recording.getMean(stat);
+			valid_period_count++;
 		}
 	}
-	return min_val;
+
+	return valid_period_count 
+			? mean / (F64)valid_period_count
+			: NaN;
 }
 
-F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+
+F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
 {
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-	F64 max_val = std::numeric_limits<F64>::min();
+	F64 period_mean = getPeriodMean(stat, num_periods);
+	F64 sum_of_squares = 0;
+	S32 valid_period_count = 0;
+
 	for (S32 i = 1; i <= num_periods; i++)
 	{
-		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		Recording& recording = mRecordingPeriods[index];
+		Recording& recording = getPrevRecording(i);
 		if (recording.hasValue(stat))
 		{
-			max_val = llmax(max_val, recording.getMax(stat));
+			F64 delta = recording.getMean(stat) - period_mean;
+			sum_of_squares += delta * delta;
+			valid_period_count++;
 		}
 	}
-	return max_val;
+
+	return valid_period_count
+			? sqrt((F64)sum_of_squares / (F64)valid_period_count)
+			: NaN;
 }
 
 F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
@@ -594,17 +619,21 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, s
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
+	bool has_value = false;
 	F64 min_val = std::numeric_limits<F64>::max();
 	for (S32 i = 1; i <= num_periods; i++)
 	{
-		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		Recording& recording = mRecordingPeriods[index];
+		Recording& recording = getPrevRecording(i);
 		if (recording.hasValue(stat))
 		{
 			min_val = llmin(min_val, recording.getMin(stat));
+			has_value = true;
 		}
 	}
-	return min_val;
+
+	return has_value 
+			? min_val 
+			: NaN;
 }
 
 F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/)
@@ -612,17 +641,21 @@ F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, si
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
+	bool has_value = false;
 	F64 max_val = std::numeric_limits<F64>::min();
 	for (S32 i = 1; i <= num_periods; i++)
 	{
-		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		Recording& recording = mRecordingPeriods[index];
+		Recording& recording = getPrevRecording(i);
 		if (recording.hasValue(stat))
 		{
 			max_val = llmax(max_val, recording.getMax(stat));
+			has_value = true;
 		}
 	}
-	return max_val;
+
+	return has_value 
+			? max_val 
+			: NaN;
 }
 
 
@@ -631,31 +664,48 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat,
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-	LLUnit<F64, LLUnits::Seconds> total_duration(0.f);
-
+	S32 valid_period_count = 0;
 	F64 mean = 0;
-	if (num_periods <= 0) { return mean; }
 
 	for (S32 i = 1; i <= num_periods; i++)
 	{
-		S32 index = (mCurPeriod + total_periods - i) % total_periods;
-		Recording& recording = mRecordingPeriods[index];
+		Recording& recording = getPrevRecording(i);
 		if (recording.hasValue(stat))
 		{
-			LLUnit<F64, LLUnits::Seconds> recording_duration = recording.getDuration();
-			mean += recording.getMean(stat) * recording_duration.value();
-			total_duration += recording_duration;
+			mean += recording.getMean(stat);
+			valid_period_count++;
 		}
 	}
 
-	if (total_duration.value())
-	{
-		mean = mean / total_duration;
-	}
-	return mean;
+	return valid_period_count
+			? mean / F64(valid_period_count)
+			: NaN;
 }
 
+F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+{
+	size_t total_periods = mRecordingPeriods.size();
+	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
+	F64 period_mean = getPeriodMean(stat, num_periods);
+	S32 valid_period_count = 0;
+	F64 sum_of_squares = 0;
+
+	for (S32 i = 1; i <= num_periods; i++)
+	{
+		Recording& recording = getPrevRecording(i);
+		if (recording.hasValue(stat))
+		{
+			F64 delta = recording.getMean(stat) - period_mean;
+			sum_of_squares += delta * delta;
+			valid_period_count++;
+		}
+	}
+
+	return valid_period_count
+			? sqrt(sum_of_squares / (F64)valid_period_count)
+			: NaN;
+}
 
 ///////////////////////////////////////////////////////////////////////
 // ExtendableRecording
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 7ee8aba874..3722a61327 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -210,6 +210,7 @@ namespace LLTrace
 
 		// SampleStatHandle accessors
 		bool hasValue(const TraceType<SampleAccumulator>& stat);
+
 		F64 getMin(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
 		T getMin(const SampleStatHandle<T>& stat)
@@ -217,18 +218,18 @@ namespace LLTrace
 			return (T)getMin(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
-		F64 getMean(const TraceType<SampleAccumulator>& stat);
+		F64 getMax(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
-		typename RelatedTypes<T>::fractional_t getMean(SampleStatHandle<T>& stat)
+		T getMax(const SampleStatHandle<T>& stat)
 		{
-			return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const TraceType<SampleAccumulator>&> (stat));
+			return (T)getMax(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
-		F64 getMax(const TraceType<SampleAccumulator>& stat);
+		F64 getMean(const TraceType<SampleAccumulator>& stat);
 		template <typename T>
-		T getMax(const SampleStatHandle<T>& stat)
+		typename RelatedTypes<T>::fractional_t getMean(SampleStatHandle<T>& stat)
 		{
-			return (T)getMax(static_cast<const TraceType<SampleAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
 		F64 getStandardDeviation(const TraceType<SampleAccumulator>& stat);
@@ -345,8 +346,8 @@ namespace LLTrace
             size_t num_samples = 0;
 			for (S32 i = 1; i <= num_periods; i++)
 			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				num_samples += mRecordingPeriods[index].getSampleCount(stat);
+				Recording& recording = getPrevRecording(i);
+				num_samples += Recording.getSampleCount(stat);
 			}
 			return num_samples;
         }
@@ -365,8 +366,8 @@ namespace LLTrace
 			typename T::value_t min_val = std::numeric_limits<typename T::value_t>::max();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				min_val = llmin(min_val, mRecordingPeriods[index].getSum(stat));
+				Recording& recording = getPrevRecording(i)
+				min_val = llmin(min_val, recording.getSum(stat));
 			}
 			return min_val;
 		}
@@ -397,11 +398,11 @@ namespace LLTrace
 			size_t total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-			F64 min_val = std::numeric_limits<F64>::max();
+			RelatedTypes<typename T::value_t>::fractional_t min_val = std::numeric_limits<F64>::max();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				min_val = llmin(min_val, mRecordingPeriods[index].getPerSec(stat));
+				Recording& recording = getPrevRecording(i);
+				min_val = llmin(min_val, recording.getPerSec(stat));
 			}
 			return (typename RelatedTypes<typename T::value_t>::fractional_t) min_val;
 		}
@@ -426,8 +427,8 @@ namespace LLTrace
 			typename T::value_t max_val = std::numeric_limits<typename T::value_t>::min();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				max_val = llmax(max_val, mRecordingPeriods[index].getSum(stat));
+				Recording& recording = getPrevRecording(i);
+				max_val = llmax(max_val, recording.getSum(stat));
 			}
 			return max_val;
 		}
@@ -461,8 +462,8 @@ namespace LLTrace
 			F64 max_val = std::numeric_limits<F64>::min();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				max_val = llmax(max_val, mRecordingPeriods[index].getPerSec(stat));
+				Recording& recording = getPrevRecording(i);
+				max_val = llmax(max_val, recording.getPerSec(stat));
 			}
 			return (typename RelatedTypes<typename T::value_t>::fractional_t)max_val;
 		}
@@ -479,24 +480,24 @@ namespace LLTrace
 
 		// catch all for stats that have a defined sum
 		template <typename T>
-		typename T::mean_t getPeriodMean(const TraceType<T >& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const TraceType<T >& stat, size_t num_periods = U32_MAX)
 		{
 			size_t total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-			typename T::mean_t mean = 0;
-			if (num_periods <= 0) { return mean; }
+			typename RelatedTypes<T::value_t>::fractional_t mean = 0;
 
 			for (S32 i = 1; i <= num_periods; i++)
 			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				if (mRecordingPeriods[index].getDuration() > 0.f)
+				Recording& recording = getPrevRecording(i);
+				if (recording.getDuration() > 0.f)
 				{
-					mean += mRecordingPeriods[index].getSum(stat);
+					mean += recording.getSum(stat);
 				}
 			}
-			mean = mean / num_periods;
-			return mean;
+			return RelatedTypes<T::value_t>::fractional_t(num_periods
+														? mean / num_periods
+														: NaN);
 		}
 
 		template<typename T>
@@ -519,24 +520,25 @@ namespace LLTrace
 		}
 
 		template <typename T>
-		typename RelatedTypes<typename T::mean_t>::fractional_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
 		{
 			size_t total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-			typename T::mean_t mean = 0;
-			if (num_periods <= 0) { return mean; }
+			typename RelatedTypes<T::value_t>::fractional_t mean = 0;
 
 			for (S32 i = 1; i <= num_periods; i++)
 			{
-				S32 index = (mCurPeriod + total_periods - i) % total_periods;
-				if (mRecordingPeriods[index].getDuration() > 0.f)
+				Recording& recording = getPrevRecording(i);
+				if (recording.getDuration() > 0.f)
 				{
-					mean += mRecordingPeriods[index].getPerSec(stat);
+					mean += recording.getPerSec(stat);
 				}
 			}
-			mean = mean / num_periods;
-			return (typename RelatedTypes<typename T::mean_t>::fractional_t)mean;
+
+			return RelatedTypes<T::value_t>::fractional_t(num_periods
+														? mean / num_periods
+														: NaN);
 		}
 
 		template<typename T>
@@ -545,6 +547,25 @@ namespace LLTrace
 			return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
 		}
 
+		//
+		// PERIODIC STANDARD DEVIATION
+		//
+
+		F64 getPeriodStandardDeviation(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX);
+
+		template<typename T> 
+		typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		{
+			return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods));
+		}
+
+		F64 getPeriodStandardDeviation(const TraceType<EventAccumulator>& stat, size_t num_periods = U32_MAX);
+		template<typename T>
+		typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		{
+			return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
+		}
+
 	private:
 		// implementation for LLStopWatchControlsMixin
 		/*virtual*/ void handleStart();
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 2e4c0de28f..b135be48fa 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -517,71 +517,79 @@ struct LLGetUnitLabel<LLUnit<STORAGE_T, T> >
 	static const char* getUnitLabel() { return T::getUnitLabel(); }
 };
 
-template<typename VALUE_TYPE>
+#define LL_UNIT_PROMOTE_VALUE(output_type, value) ((true ? (output_type)(1) : (value/value)) * value)
+
+template<typename INPUT_TYPE, typename OUTPUT_TYPE>
 struct LLUnitLinearOps
 {
-	typedef LLUnitLinearOps<VALUE_TYPE> self_t;
-	LLUnitLinearOps(VALUE_TYPE val) : mResult (val) {}
+	typedef LLUnitLinearOps<OUTPUT_TYPE, OUTPUT_TYPE> output_t;
+
+	LLUnitLinearOps(INPUT_TYPE val) 
+	:	mInput (val)
+	{}
 
-	operator VALUE_TYPE() const { return mResult; }
-	VALUE_TYPE mResult;
+	operator OUTPUT_TYPE() const { return (OUTPUT_TYPE)mInput; }
+	INPUT_TYPE mInput;
 
 	template<typename T>
-	self_t operator * (T other)
+	output_t operator * (T other)
 	{
-		return mResult * other;
+		return mInput * other;
 	}
 
 	template<typename T>
-	self_t operator / (T other)
+	output_t operator / (T other)
 	{
-		return mResult / other;
+		return LL_UNIT_PROMOTE_VALUE(OUTPUT_TYPE, mInput) / other;
 	}
 
 	template<typename T>
-	self_t operator + (T other)
+	output_t operator + (T other)
 	{
-		return mResult + other;
+		return mInput + other;
 	}
 
 	template<typename T>
-	self_t operator - (T other)
+	output_t operator - (T other)
 	{
-		return mResult - other;
+		return mInput - other;
 	}
 };
 
-template<typename VALUE_TYPE>
+template<typename INPUT_TYPE, typename OUTPUT_TYPE>
 struct LLUnitInverseLinearOps
 {
-	typedef LLUnitInverseLinearOps<VALUE_TYPE> self_t;
+	typedef LLUnitInverseLinearOps<OUTPUT_TYPE, OUTPUT_TYPE> output_t;
+
+	LLUnitInverseLinearOps(INPUT_TYPE val) 
+	:	mInput(val)
+	{}
 
-	LLUnitInverseLinearOps(VALUE_TYPE val) : mResult (val) {}
-	operator VALUE_TYPE() const { return mResult; }
-	VALUE_TYPE mResult;
+	operator OUTPUT_TYPE() const { return (OUTPUT_TYPE)mInput; }
+	INPUT_TYPE mInput;
 
 	template<typename T>
-	self_t operator * (T other)
+	output_t operator * (T other)
 	{
-		return mResult / other;
+		return LL_UNIT_PROMOTE_VALUE(OUTPUT_TYPE, mInput) / other;
 	}
 
 	template<typename T>
-	self_t operator / (T other)
+	output_t operator / (T other)
 	{
-		return mResult * other;
+		return mInput * other;
 	}
 
 	template<typename T>
-	self_t operator + (T other)
+	output_t operator + (T other)
 	{
-		return mResult - other;
+		return mInput - other;
 	}
 
 	template<typename T>
-	self_t operator - (T other)
+	output_t operator - (T other)
 	{
-		return mResult + other;
+		return mInput + other;
 	}
 };
 
@@ -613,13 +621,13 @@ struct unit_name
 template<typename S1, typename S2>                                                                      \
 void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)                        \
 {                                                                                                       \
-	out = LLUnit<S2, base_unit_name>((S2)(LLUnitLinearOps<S1>(in.value()) conversion_operation));		\
+	out = LLUnit<S2, base_unit_name>((S2)(LLUnitLinearOps<S1, S2>(in.value()) conversion_operation));		\
 }                                                                                                       \
                                                                                                         \
 template<typename S1, typename S2>                                                                      \
 void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)                        \
 {                                                                                                       \
-	out = LLUnit<S2, unit_name>((S2)(LLUnitInverseLinearOps<S1>(in.value()) conversion_operation));     \
+	out = LLUnit<S2, unit_name>((S2)(LLUnitInverseLinearOps<S1, S2>(in.value()) conversion_operation));     \
 }                                                                                               
 
 //
diff --git a/indra/llcommon/tests/commonmisc_test.cpp b/indra/llcommon/tests/commonmisc_test.cpp
index b115c153c1..4b3e07fa75 100755
--- a/indra/llcommon/tests/commonmisc_test.cpp
+++ b/indra/llcommon/tests/commonmisc_test.cpp
@@ -339,7 +339,7 @@ namespace tut
 /*
 			if(actual != expected)
 			{
-				llwarns << "iteration " << i << llendl;
+				LL_WARNS() << "iteration " << i << LL_ENDL;
 				std::ostringstream e_str;
 				std::string::iterator iter = expected.begin();
 				std::string::iterator end = expected.end();
@@ -349,8 +349,8 @@ namespace tut
 				}
 				e_str << std::endl;
 				llsd_serialize_string(e_str, expected);
-				llwarns << "expected size: " << expected.size() << llendl;
-				llwarns << "expected:      " << e_str.str() << llendl;
+				LL_WARNS() << "expected size: " << expected.size() << LL_ENDL;
+				LL_WARNS() << "expected:      " << e_str.str() << LL_ENDL;
 
 				std::ostringstream a_str;
 				iter = actual.begin();
@@ -361,8 +361,8 @@ namespace tut
 				}
 				a_str << std::endl;
 				llsd_serialize_string(a_str, actual);
-				llwarns << "actual size:   " << actual.size() << llendl;
-				llwarns << "actual:      " << a_str.str() << llendl;
+				LL_WARNS() << "actual size:   " << actual.size() << LL_ENDL;
+				LL_WARNS() << "actual:      " << a_str.str() << LL_ENDL;
 			}
 */
 			ensure_equals("string value", actual, expected);
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index 279a90e51b..b28c5ba4b3 100755
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -40,7 +40,7 @@ namespace
 {
 	void test_that_error_h_includes_enough_things_to_compile_a_message()
 	{
-		llinfos << "!" << llendl;
+		LL_INFOS() << "!" << LL_ENDL;
 	}
 }
 
@@ -55,7 +55,7 @@ namespace tut
 	class TestRecorder : public LLError::Recorder
 	{
 	public:
-		TestRecorder() : mWantsTime(false) { }
+		TestRecorder() { mWantsTime = false; }
 		~TestRecorder() { LLError::removeRecorder(this); }
 
 		void recordMessage(LLError::ELevel level,
@@ -68,7 +68,6 @@ namespace tut
 		void clearMessages()		{ mMessages.clear(); }
 
 		void setWantsTime(bool t)	{ mWantsTime = t; }
-		bool wantsTime()			{ return mWantsTime; }
 
 		std::string message(int n)
 		{
@@ -82,8 +81,6 @@ namespace tut
 	private:
 		typedef std::vector<std::string> MessageVector;
 		MessageVector mMessages;
-
-		bool mWantsTime;
 	};
 
 	struct ErrorTestData
@@ -144,8 +141,8 @@ namespace tut
 	void ErrorTestObject::test<1>()
 		// basic test of output
 	{
-		llinfos << "test" << llendl;
-		llinfos << "bob" << llendl;
+		LL_INFOS() << "test" << LL_ENDL;
+		LL_INFOS() << "bob" << LL_ENDL;
 
 		ensure_message_contains(0, "test");
 		ensure_message_contains(1, "bob");
@@ -156,11 +153,11 @@ namespace
 {
 	void writeSome()
 	{
-		lldebugs << "one" << llendl;
-		llinfos << "two" << llendl;
-		llwarns << "three" << llendl;
-		llerrs << "four" << llendl;
-			// fatal messages write out and addtional "error" message
+		LL_DEBUGS() << "one" << LL_ENDL;
+		LL_INFOS() << "two" << LL_ENDL;
+		LL_WARNS() << "three" << LL_ENDL;
+		// fatal messages write out an additional "error" message
+		LL_ERRS() << "four" << LL_ENDL;
 	}
 };
 
@@ -259,19 +256,20 @@ namespace
 
 	std::string writeReturningLocation()
 	{
-		llinfos << "apple" << llendl;	int this_line = __LINE__;
+		LL_INFOS() << "apple" << LL_ENDL;	int this_line = __LINE__;
 		return locationString(this_line);
 	}
 
-	std::string writeReturningLocationAndFunction()
+	void writeReturningLocationAndFunction(std::string& location, std::string& function)
 	{
-		llinfos << "apple" << llendl;	int this_line = __LINE__;
-		return locationString(this_line) + __FUNCTION__;
+		LL_INFOS() << "apple" << LL_ENDL;	int this_line = __LINE__;
+		location = locationString(this_line);
+		function = __FUNCTION__;
 	}
 
 	std::string errorReturningLocation()
 	{
-		llerrs << "die" << llendl;	int this_line = __LINE__;
+		LL_ERRS() << "die" << LL_ENDL;	int this_line = __LINE__;
 		return locationString(this_line);
 	}
 }
@@ -306,13 +304,13 @@ namespace tut
 
 std::string logFromGlobal(bool id)
 {
-	llinfos << (id ? "logFromGlobal: " : "") << "hi" << llendl;
+	LL_INFOS() << (id ? "logFromGlobal: " : "") << "hi" << LL_ENDL;
 	return "logFromGlobal";
 }
 
 static std::string logFromStatic(bool id)
 {
-	llinfos << (id ? "logFromStatic: " : "") << "hi" << llendl;
+	LL_INFOS() << (id ? "logFromStatic: " : "") << "hi" << LL_ENDL;
 	return "logFromStatic";
 }
 
@@ -320,7 +318,7 @@ namespace
 {
 	std::string logFromAnon(bool id)
 	{
-		llinfos << (id ? "logFromAnon: " : "") << "hi" << llendl;
+		LL_INFOS() << (id ? "logFromAnon: " : "") << "hi" << LL_ENDL;
 		return "logFromAnon";
 	}
 }
@@ -328,7 +326,7 @@ namespace
 namespace Foo {
 	std::string logFromNamespace(bool id)
 	{
-		llinfos << (id ? "Foo::logFromNamespace: " : "") << "hi" << llendl;
+		LL_INFOS() << (id ? "Foo::logFromNamespace: " : "") << "hi" << LL_ENDL;
 		//return "Foo::logFromNamespace";
 			// there is no standard way to get the namespace name, hence
 			// we won't be testing for it
@@ -342,12 +340,12 @@ namespace
 	public:
 		std::string logFromMember(bool id)
 		{
-			llinfos << (id ? "ClassWithNoLogType::logFromMember: " : "") << "hi" << llendl;
+			LL_INFOS() << (id ? "ClassWithNoLogType::logFromMember: " : "") << "hi" << LL_ENDL;
 			return "ClassWithNoLogType::logFromMember";
 		}
 		static std::string logFromStatic(bool id)
 		{
-			llinfos << (id ? "ClassWithNoLogType::logFromStatic: " : "") << "hi" << llendl;
+			LL_INFOS() << (id ? "ClassWithNoLogType::logFromStatic: " : "") << "hi" << LL_ENDL;
 			return "ClassWithNoLogType::logFromStatic";
 		}
 	};
@@ -357,12 +355,12 @@ namespace
 	public:
 		std::string logFromMember(bool id)
 		{
-			llinfos << (id ? "ClassWithLogType::logFromMember: " : "") << "hi" << llendl;
+			LL_INFOS() << (id ? "ClassWithLogType::logFromMember: " : "") << "hi" << LL_ENDL;
 			return "ClassWithLogType::logFromMember";
 		}
 		static std::string logFromStatic(bool id)
 		{
-			llinfos << (id ? "ClassWithLogType::logFromStatic: " : "") << "hi" << llendl;
+			LL_INFOS() << (id ? "ClassWithLogType::logFromStatic: " : "") << "hi" << LL_ENDL;
 			return "ClassWithLogType::logFromStatic";
 		}
 	};
@@ -434,19 +432,19 @@ namespace
 {
 	std::string innerLogger()
 	{
-		llinfos << "inside" << llendl;
+		LL_INFOS() << "inside" << LL_ENDL;
 		return "moo";
 	}
 
 	std::string outerLogger()
 	{
-		llinfos << "outside(" << innerLogger() << ")" << llendl;
+		LL_INFOS() << "outside(" << innerLogger() << ")" << LL_ENDL;
 		return "bar";
 	}
 
 	void uberLogger()
 	{
-		llinfos << "uber(" << outerLogger() << "," << innerLogger() << ")" << llendl;
+		LL_INFOS() << "uber(" << outerLogger() << "," << innerLogger() << ")" << LL_ENDL;
 	}
 
 	class LogWhileLogging
@@ -454,7 +452,7 @@ namespace
 	public:
 		void print(std::ostream& out) const
 		{
-			llinfos << "logging" << llendl;
+			LL_INFOS() << "logging" << LL_ENDL;
 			out << "baz";
 		}
 	};
@@ -465,7 +463,7 @@ namespace
 	void metaLogger()
 	{
 		LogWhileLogging l;
-		llinfos << "meta(" << l << ")" << llendl;
+		LL_INFOS() << "meta(" << l << ")" << LL_ENDL;
 	}
 
 }
@@ -495,7 +493,7 @@ namespace tut
 	}
 
 	template<> template<>
-		// special handling of llerrs calls
+		// special handling of LL_ERRS() calls
 	void ErrorTestObject::test<8>()
 	{
 		LLError::setPrintLocation(false);
@@ -518,7 +516,7 @@ namespace
 
 	void ufoSighting()
 	{
-		llinfos << "ufo" << llendl;
+		LL_INFOS() << "ufo" << LL_ENDL;
 	}
 }
 
@@ -548,11 +546,13 @@ namespace tut
 		LLError::setPrintLocation(true);
 		LLError::setTimeFunction(roswell);
 		mRecorder->setWantsTime(true);
-		std::string locationAndFunction = writeReturningLocationAndFunction();
+		std::string location,
+					function;
+		writeReturningLocationAndFunction(location, function);
 
-		ensure_equals("order is time type location function message",
+		ensure_equals("order is location time type function message",
 			mRecorder->message(0),
-			roswell() + " INFO: " + locationAndFunction + ": apple");
+			location + roswell() + " INFO: " + function + ": apple");
 	}
 
 	template<> template<>
@@ -562,7 +562,7 @@ namespace tut
 		TestRecorder* altRecorder(new TestRecorder);
 		LLError::addRecorder(altRecorder);
 
-		llinfos << "boo" << llendl;
+		LL_INFOS() << "boo" << LL_ENDL;
 
 		ensure_message_contains(0, "boo");
 		ensure_equals("alt recorder count", altRecorder->countMessages(), 1);
@@ -574,7 +574,7 @@ namespace tut
 		anotherRecorder->setWantsTime(true);
 		LLError::addRecorder(anotherRecorder);
 
-		llinfos << "baz" << llendl;
+		LL_INFOS() << "baz" << LL_ENDL;
 
 		std::string when = roswell();
 
@@ -590,10 +590,10 @@ class TestAlpha
 {
 	LOG_CLASS(TestAlpha);
 public:
-	static void doDebug()	{ lldebugs << "add dice" << llendl; }
-	static void doInfo()	{ llinfos  << "any idea" << llendl; }
-	static void doWarn()	{ llwarns  << "aim west" << llendl; }
-	static void doError()	{ llerrs   << "ate eels" << llendl; }
+	static void doDebug()	{ LL_DEBUGS() << "add dice" << LL_ENDL; }
+	static void doInfo()	{ LL_INFOS()  << "any idea" << LL_ENDL; }
+	static void doWarn()	{ LL_WARNS()  << "aim west" << LL_ENDL; }
+	static void doError()	{ LL_ERRS()   << "ate eels" << LL_ENDL; }
 	static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
 };
 
@@ -601,10 +601,10 @@ class TestBeta
 {
 	LOG_CLASS(TestBeta);
 public:
-	static void doDebug()	{ lldebugs << "bed down" << llendl; }
-	static void doInfo()	{ llinfos  << "buy iron" << llendl; }
-	static void doWarn()	{ llwarns  << "bad word" << llendl; }
-	static void doError()	{ llerrs   << "big easy" << llendl; }
+	static void doDebug()	{ LL_DEBUGS() << "bed down" << LL_ENDL; }
+	static void doInfo()	{ LL_INFOS()  << "buy iron" << LL_ENDL; }
+	static void doWarn()	{ LL_WARNS()  << "bad word" << LL_ENDL; }
+	static void doError()	{ LL_ERRS()   << "big easy" << LL_ENDL; }
 	static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
 };
 
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index 4d436e8897..235008a5ae 100755
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -268,7 +268,7 @@ namespace tut
 	{
 		std::stringstream stream;	
 		mFormatter->format(v, stream);
-		//llinfos << "checkRoundTrip: length " << stream.str().length() << llendl;
+		//LL_INFOS() << "checkRoundTrip: length " << stream.str().length() << LL_ENDL;
 		LLSD w;
 		mParser->reset();	// reset() call is needed since test code re-uses mParser
 		mParser->parse(stream, w, stream.str().size());
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index e631f18ad4..ff981ca2ff 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -53,6 +53,7 @@ namespace tut
 	template<> template<>
 	void units_object_t::test<1>()
 	{
+		LL_INFOS("test") << "Test" << LL_ENDL;
 		LLUnit<F32, Quatloos> float_quatloos;
 		ensure(float_quatloos == 0.f);
 
@@ -93,6 +94,11 @@ namespace tut
 
 		LLUnit<F32, Solari> solari(quatloos);
 		ensure(solari == 4096);
+
+		// division of integral unit
+		LLUnit<S32, Quatloos> single_quatloo(1);
+		LLUnit<F32, Latinum> quarter_latinum = single_quatloo;
+		ensure(quarter_latinum == 0.25f);
 	}
 
 	// conversions across non-base units
-- 
cgit v1.2.3


From 9faaa28f4445425e8c5b7b002faffbe0365b905d Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 13 Aug 2013 18:33:07 -0700
Subject: SH-4346 FIX Interesting: some integer Statistics are displayed as
 floating point after crossing region boundary fine-tuned heuristics for
 switching between mean and current values in stat bar display added comments
 to LLUnits unit test

---
 indra/llcommon/tests/llunits_test.cpp | 76 ++++++++++++++---------------------
 1 file changed, 31 insertions(+), 45 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index ff981ca2ff..b0309585aa 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -53,30 +53,29 @@ namespace tut
 	template<> template<>
 	void units_object_t::test<1>()
 	{
-		LL_INFOS("test") << "Test" << LL_ENDL;
 		LLUnit<F32, Quatloos> float_quatloos;
-		ensure(float_quatloos == 0.f);
+		ensure("default float unit is zero", float_quatloos == 0.f);
 
 		LLUnit<F32, Quatloos> float_initialize_quatloos(1);
-		ensure(float_initialize_quatloos == 1.f);
+		ensure("non-zero initialized unit", float_initialize_quatloos == 1.f);
 
 		LLUnit<S32, Quatloos> int_quatloos;
-		ensure(int_quatloos == 0);
+		ensure("default int unit is zero", int_quatloos == 0);
 
 		int_quatloos = 42;
-		ensure(int_quatloos == 42);
+		ensure("int assignment is preserved", int_quatloos == 42);
 		float_quatloos = int_quatloos;
-		ensure(float_quatloos == 42.f);
+		ensure("float assignment from int preserves value", float_quatloos == 42.f);
 
 		int_quatloos = float_quatloos;
-		ensure(int_quatloos == 42);
+		ensure("int assignment from float preserves value", int_quatloos == 42);
 
 		float_quatloos = 42.1f;
-		ensure(float_quatloos == 42.1f);
 		int_quatloos = float_quatloos;
-		ensure(int_quatloos == 42);
+		ensure("int units truncate float units on assignment", int_quatloos == 42);
+
 		LLUnit<U32, Quatloos> unsigned_int_quatloos(float_quatloos);
-		ensure(unsigned_int_quatloos == 42);
+		ensure("unsigned int can be initialized from signed int", unsigned_int_quatloos == 42);
 	}
 
 	// conversions to/from base unit
@@ -84,36 +83,35 @@ namespace tut
 	void units_object_t::test<2>()
 	{
 		LLUnit<F32, Quatloos> quatloos(1.f);
-		ensure(quatloos == 1.f);
 		LLUnit<F32, Latinum> latinum_bars(quatloos);
-		ensure(latinum_bars == 1.f / 4.f);
+		ensure("conversion between units is automatic via initialization", latinum_bars == 1.f / 4.f);
 
 		latinum_bars = 256;
 		quatloos = latinum_bars;
-		ensure(quatloos == 1024);
-
-		LLUnit<F32, Solari> solari(quatloos);
-		ensure(solari == 4096);
+		ensure("conversion between units is automatic via assignment, and bidirectional", quatloos == 1024);
 
-		// division of integral unit
 		LLUnit<S32, Quatloos> single_quatloo(1);
 		LLUnit<F32, Latinum> quarter_latinum = single_quatloo;
-		ensure(quarter_latinum == 0.25f);
+		ensure("division of integer unit preserves fractional values when converted to float unit", quarter_latinum == 0.25f);
 	}
 
 	// conversions across non-base units
 	template<> template<>
 	void units_object_t::test<3>()
 	{
-		LLUnit<F32, Solari> solari = 4.f;
+		LLUnit<F32, Quatloos> quatloos(1024);
+		LLUnit<F32, Solari> solari(quatloos);
+		ensure("conversions can work between indirectly related units: Quatloos -> Latinum -> Solari", solari == 4096);
+
 		LLUnit<F32, Latinum> latinum_bars = solari;
-		ensure(latinum_bars == 0.25f);
+		ensure("Non base units can be converted between each other", latinum_bars == 256);
 	}
 
 	// math operations
 	template<> template<>
 	void units_object_t::test<4>()
 	{
+		// exercise math operations
 		LLUnit<F32, Quatloos> quatloos = 1.f;
 		quatloos *= 4.f;
 		ensure(quatloos == 4);
@@ -142,44 +140,34 @@ namespace tut
 		quatloos -= 4.f;
 		ensure(quatloos == 16);
 
-		quatloos *= 2.f;
-		ensure(quatloos == 32);
-		quatloos = quatloos * 2.f;
-		ensure(quatloos == 64);
-		quatloos = 0.5f * quatloos;
-		ensure(quatloos == 32);
-
 		quatloos /= 2.f;
-		ensure(quatloos == 16);
+		ensure(quatloos == 8);
 		quatloos = quatloos / 4;
-		ensure(quatloos == 4);
+		ensure(quatloos == 2);
 
-		F32 ratio = quatloos / LLUnit<F32, Quatloos>(4.f);
+		F32 ratio = quatloos / LLUnit<F32, Quatloos>(2.f);
 		ensure(ratio == 1);
-		ratio = quatloos / LLUnit<F32, Solari>(16.f);
+		ratio = quatloos / LLUnit<F32, Solari>(8.f);
 		ensure(ratio == 1);
 
-		quatloos += LLUnit<F32, Solari>(4.f);
-		ensure(quatloos == 5);
+		quatloos += LLUnit<F32, Solari>(8.f);
+		ensure(quatloos == 4);
 		quatloos -= LLUnit<F32, Latinum>(1.f);
-		ensure(quatloos == 1);
+		ensure(quatloos == 0);
 	}
 
 	// implicit units
 	template<> template<>
 	void units_object_t::test<5>()
 	{
-		// 0-initialized
 		LLUnit<F32, Quatloos> quatloos;
-		// initialize implicit unit from explicit
 		LLUnitImplicit<F32, Quatloos> quatloos_implicit = quatloos + 1;
-		ensure(quatloos_implicit == 1);
+		ensure("can initialize implicit unit from explicit", quatloos_implicit == 1);
 
-		// assign implicit to explicit, or perform math operations
 		quatloos = quatloos_implicit;
-		ensure(quatloos == 1);
+		ensure("can assign implicit unit to explicit unit", quatloos == 1);
 		quatloos += quatloos_implicit;
-		ensure(quatloos == 2);
+		ensure("can perform math operation using mixture of implicit and explicit units", quatloos == 2);
 
 		// math operations on implicits
 		quatloos_implicit = 1;
@@ -211,15 +199,13 @@ namespace tut
 
 		// implicit conversion to POD
 		F32 float_val = quatloos_implicit;
-		ensure(float_val == 16);
+		ensure("implicit units convert implicitly to regular values", float_val == 16);
 
 		S32 int_val = quatloos_implicit;
-		ensure(int_val == 16);
+		ensure("implicit units convert implicitly to regular values", int_val == 16);
 
 		// conversion of implicits
 		LLUnitImplicit<F32, Latinum> latinum_implicit(2);
-		ensure(latinum_implicit == 2);
-
-		ensure(latinum_implicit * 2 == quatloos_implicit);
+		ensure("implicit units of different types are comparable", latinum_implicit * 2 == quatloos_implicit);
 	}
 }
-- 
cgit v1.2.3


From 26581404e426b00cd0a07c38b5cb858d5d5faa28 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 14 Aug 2013 11:51:49 -0700
Subject: BUILDFIX: added header for numeric_limits support on gcc added
 convenience types for units F32Seconds, etc.

---
 indra/llcommon/llerror.h              |   2 +-
 indra/llcommon/llfasttimer.cpp        |  10 +-
 indra/llcommon/llfasttimer.h          |   2 +-
 indra/llcommon/lltimer.cpp            |   2 +-
 indra/llcommon/lltraceaccumulators.h  |   4 +-
 indra/llcommon/lltracerecording.cpp   |  62 ++++++------
 indra/llcommon/lltracerecording.h     |  28 +++---
 indra/llcommon/llunit.h               | 177 +++++++++++++++++++++++++++++++++-
 indra/llcommon/tests/llunits_test.cpp |   2 +-
 9 files changed, 232 insertions(+), 57 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 7810676388..a3619559eb 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -308,7 +308,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 #define lllog(level, once, ...)																	          \
 	do {                                                                                                  \
 		const char* tags[] = {"", ##__VA_ARGS__};													      \
-		size_t tag_count = LL_ARRAY_SIZE(tags) - 1;														  \
+		::size_t tag_count = LL_ARRAY_SIZE(tags) - 1;														  \
 		static LLError::CallSite _site(                                                                   \
 		    level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, &tags[1], tag_count);\
 		if (LL_UNLIKELY(_site.shouldLog()))			                                                      \
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 8f86a1dfbc..a91e716f19 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -339,7 +339,7 @@ void TimeBlock::logStats()
 		}
 		call_count++;
 
-		LLUnit<F64, LLUnits::Seconds> total_time(0);
+		LLUnits::F64Seconds total_time(0);
 		LLSD sd;
 
 		{
@@ -382,11 +382,11 @@ void TimeBlock::dumpCurTimes()
 		++it)
 	{
 		TimeBlock* timerp = (*it);
-		LLUnit<F64, LLUnits::Seconds> total_time = last_frame_recording.getSum(*timerp);
+		LLUnits::F64Seconds 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 < LLUnits::Milliseconds::fromValue(0.1f)) continue;
+		if (total_time < LLUnits::F32Milliseconds(0.1f)) continue;
 
 		std::ostringstream out_str;
 		TimeBlock* parent_timerp = timerp;
@@ -466,11 +466,11 @@ void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
 	}
 }
 
-LLUnit<F64, LLUnits::Seconds> BlockTimer::getElapsedTime()
+LLUnits::F64Seconds BlockTimer::getElapsedTime()
 {
 	U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
 
-	return LLUnits::Seconds::fromValue((F64)total_time / (F64)TimeBlock::countsPerSecond());
+	return LLUnits::F64Seconds((F64)total_time / (F64)TimeBlock::countsPerSecond());
 }
 
 
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 73c40749ed..589b9bb941 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -48,7 +48,7 @@ public:
 	BlockTimer(TimeBlock& timer);
 	~BlockTimer();
 
-	LLUnit<F64, LLUnits::Seconds> getElapsedTime();
+	LLUnits::F64Seconds getElapsedTime();
 
 private:
 
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index a2c5f3d699..7077ea4b4f 100755
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -262,7 +262,7 @@ LLUnitImplicit<U64, LLUnits::Microseconds> totalTime()
 	}
 
 	// Return the total clock tick count in microseconds.
-	return LLUnits::Microseconds::fromValue(gTotalTimeClockCount*gClocksToMicroseconds);
+	return LLUnits::U64Microseconds(gTotalTimeClockCount*gClocksToMicroseconds);
 }
 
 
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index ef73bd3091..4d79964526 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -418,7 +418,7 @@ namespace LLTrace
 	class TimeBlockAccumulator
 	{
 	public:
-		typedef LLUnit<F64, LLUnits::Seconds> value_t;
+		typedef LLUnits::F64Seconds value_t;
 		typedef TimeBlockAccumulator self_t;
 
 		// fake classes that allows us to view different facets of underlying statistic
@@ -429,7 +429,7 @@ namespace LLTrace
 
 		struct SelfTimeFacet
 		{
-			typedef LLUnit<F64, LLUnits::Seconds> value_t;
+			typedef LLUnits::F64Seconds value_t;
 		};
 
 		TimeBlockAccumulator();
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 42d97ce314..963f0cd174 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -95,7 +95,7 @@ void Recording::handleReset()
 {
 	mBuffers.write()->reset();
 
-	mElapsedSeconds = LLUnits::Seconds::fromValue(0.0);
+	mElapsedSeconds = LLUnits::F64Seconds(0.0);
 	mSamplingTimer.reset();
 }
 
@@ -128,17 +128,17 @@ void Recording::appendRecording( Recording& other )
 	mElapsedSeconds += other.mElapsedSeconds;
 }
 
-LLUnit<F64, LLUnits::Seconds> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat)
+LLUnits::F64Seconds Recording::getSum(const TraceType<TimeBlockAccumulator>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
-	return LLUnits::Seconds::fromValue((F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
+	return LLUnits::F64Seconds((F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
 				/ (F64)LLTrace::TimeBlock::countsPerSecond());
 }
 
-LLUnit<F64, LLUnits::Seconds> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat)
+LLUnits::F64Seconds Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
-	return LLUnits::Seconds::fromValue((F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond());
+	return LLUnits::F64Seconds((F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond());
 }
 
 
@@ -147,19 +147,19 @@ U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& sta
 	return mBuffers->mStackTimers[stat.getIndex()].mCalls;
 }
 
-LLUnit<F64, LLUnits::Seconds> Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat)
+LLUnits::F64Seconds Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
-	return LLUnits::Seconds::fromValue((F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
+	return LLUnits::F64Seconds((F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
 				/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()));
 }
 
-LLUnit<F64, LLUnits::Seconds> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat)
+LLUnits::F64Seconds Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
-	return LLUnits::Seconds::fromValue((F64)(accumulator.mSelfTimeCounter) 
+	return LLUnits::F64Seconds((F64)(accumulator.mSelfTimeCounter) 
 			/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()));
 }
 
@@ -168,54 +168,54 @@ F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>&
 	return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds.value();
 }
 
-LLUnit<F64, LLUnits::Bytes> Recording::getMin(const TraceType<MemStatAccumulator>& stat)
+LLUnits::F64Bytes Recording::getMin(const TraceType<MemStatAccumulator>& stat)
 {
-	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mSize.getMin());
+	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMin());
 }
 
-LLUnit<F64, LLUnits::Bytes> Recording::getMean(const TraceType<MemStatAccumulator>& stat)
+LLUnits::F64Bytes Recording::getMean(const TraceType<MemStatAccumulator>& stat)
 {
-	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mSize.getMean());
+	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMean());
 }
 
-LLUnit<F64, LLUnits::Bytes> Recording::getMax(const TraceType<MemStatAccumulator>& stat)
+LLUnits::F64Bytes Recording::getMax(const TraceType<MemStatAccumulator>& stat)
 {
-	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mSize.getMax());
+	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMax());
 }
 
-LLUnit<F64, LLUnits::Bytes> Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat)
+LLUnits::F64Bytes Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat)
 {
-	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation());
+	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation());
 }
 
-LLUnit<F64, LLUnits::Bytes> Recording::getLastValue(const TraceType<MemStatAccumulator>& stat)
+LLUnits::F64Bytes Recording::getLastValue(const TraceType<MemStatAccumulator>& stat)
 {
-	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue());
+	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue());
 }
 
-LLUnit<F64, LLUnits::Bytes> Recording::getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
+LLUnits::F64Bytes Recording::getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMin());
+	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMin());
 }
 
-LLUnit<F64, LLUnits::Bytes> Recording::getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
+LLUnits::F64Bytes Recording::getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMean());
+	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMean());
 }
 
-LLUnit<F64, LLUnits::Bytes> Recording::getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
+LLUnits::F64Bytes Recording::getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMax());
+	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMax());
 }
 
-LLUnit<F64, LLUnits::Bytes> Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
+LLUnits::F64Bytes Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mChildSize.getStandardDeviation());
+	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getStandardDeviation());
 }
 
-LLUnit<F64, LLUnits::Bytes> Recording::getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
+LLUnits::F64Bytes Recording::getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	return LLUnits::Bytes::fromValue(mBuffers->mMemStats[stat.getIndex()].mChildSize.getLastValue());
+	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getLastValue());
 }
 
 U32 Recording::getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat)
@@ -427,9 +427,9 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 	getCurRecording().setPlayState(getPlayState());
 }
 
-LLUnit<F64, LLUnits::Seconds> PeriodicRecording::getDuration() const
+LLUnits::F64Seconds PeriodicRecording::getDuration() const
 {
-	LLUnit<F64, LLUnits::Seconds> duration;
+	LLUnits::F64Seconds duration;
 	size_t num_periods = mRecordingPeriods.size();
 	for (size_t i = 1; i <= num_periods; i++)
 	{
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 3722a61327..811786fbfa 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -166,12 +166,12 @@ namespace LLTrace
 		void makeUnique() { mBuffers.makeUnique(); }
 
 		// Timer accessors
-		LLUnit<F64, LLUnits::Seconds> getSum(const TraceType<TimeBlockAccumulator>& stat);
-		LLUnit<F64, LLUnits::Seconds> getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat);
+		LLUnits::F64Seconds getSum(const TraceType<TimeBlockAccumulator>& stat);
+		LLUnits::F64Seconds getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat);
 		U32 getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat);
 
-		LLUnit<F64, LLUnits::Seconds> getPerSec(const TraceType<TimeBlockAccumulator>& stat);
-		LLUnit<F64, LLUnits::Seconds> getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat);
+		LLUnits::F64Seconds getPerSec(const TraceType<TimeBlockAccumulator>& stat);
+		LLUnits::F64Seconds getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat);
 		F32 getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat);
 
 		// Memory accessors
@@ -295,7 +295,7 @@ namespace LLTrace
 
 		U32 getSampleCount(const TraceType<EventAccumulator>& stat);
 
-		LLUnit<F64, LLUnits::Seconds> getDuration() const { return mElapsedSeconds; }
+		LLUnits::F64Seconds getDuration() const { return mElapsedSeconds; }
 
 	protected:
 		friend class ThreadRecorder;
@@ -310,7 +310,7 @@ namespace LLTrace
 		class ThreadRecorder* getThreadRecorder(); 
 
 		LLTimer											mSamplingTimer;
-		LLUnit<F64, LLUnits::Seconds>					mElapsedSeconds;
+		LLUnits::F64Seconds					mElapsedSeconds;
 		LLCopyOnWritePointer<AccumulatorBufferGroup>	mBuffers;
 		bool											mInHandOff;
 
@@ -325,7 +325,7 @@ namespace LLTrace
 		void nextPeriod();
 		size_t getNumRecordedPeriods() { return mNumPeriods; }
 
-		LLUnit<F64, LLUnits::Seconds> getDuration() const;
+		LLUnits::F64Seconds getDuration() const;
 
 		void appendPeriodicRecording(PeriodicRecording& other);
 		void appendRecording(Recording& recording);
@@ -485,7 +485,7 @@ namespace LLTrace
 			size_t total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-			typename RelatedTypes<T::value_t>::fractional_t mean = 0;
+			typename RelatedTypes<T::value_t>::fractional_t mean(0);
 
 			for (S32 i = 1; i <= num_periods; i++)
 			{
@@ -495,9 +495,9 @@ namespace LLTrace
 					mean += recording.getSum(stat);
 				}
 			}
-			return RelatedTypes<T::value_t>::fractional_t(num_periods
-														? mean / num_periods
-														: NaN);
+			return (num_periods
+				? RelatedTypes<T::value_t>::fractional_t(mean / num_periods)
+				: RelatedTypes<T::value_t>::fractional_t(NaN));
 		}
 
 		template<typename T>
@@ -536,9 +536,9 @@ namespace LLTrace
 				}
 			}
 
-			return RelatedTypes<T::value_t>::fractional_t(num_periods
-														? mean / num_periods
-														: NaN);
+			return (num_periods
+				? RelatedTypes<T::value_t>::fractional_t(mean / num_periods)
+				: RelatedTypes<T::value_t>::fractional_t(NaN));
 		}
 
 		template<typename T>
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index b135be48fa..9a367d9182 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -39,7 +39,7 @@ struct LLUnit
 	typedef STORAGE_TYPE storage_t;
 
 	// value initialization
-	LLUnit(storage_t value = storage_t())
+	explicit LLUnit(storage_t value = storage_t())
 	:	mValue(value)
 	{}
 
@@ -644,6 +644,54 @@ LL_DECLARE_DERIVED_UNIT(Bytes, * 1024,			Kibibytes, "KiB");
 LL_DECLARE_DERIVED_UNIT(Kibibytes, * 1024,		Mibibytes, "MiB");
 LL_DECLARE_DERIVED_UNIT(Mibibytes, * 1024,		Gibibytes, "GiB");
 
+typedef LLUnit<F32, Bytes>     F32Bytes;
+typedef LLUnit<F32, Kilobytes> F32KiloBytes;
+typedef LLUnit<F32, Megabytes> F32MegaBytes;
+typedef LLUnit<F32, Gigabytes> F32GigaBytes;
+typedef LLUnit<F32, Kibibytes> F32KibiBytes;
+typedef LLUnit<F32, Mibibytes> F32MibiBytes;
+typedef LLUnit<F32, Gibibytes> F32GibiBytes;
+
+typedef LLUnit<F64, Bytes>     F64Bytes;
+typedef LLUnit<F64, Kilobytes> F64KiloBytes;
+typedef LLUnit<F64, Megabytes> F64MegaBytes;
+typedef LLUnit<F64, Gigabytes> F64GigaBytes;
+typedef LLUnit<F64, Kibibytes> F64KibiBytes;
+typedef LLUnit<F64, Mibibytes> F64MibiBytes;
+typedef LLUnit<F64, Gibibytes> F64GibiBytes;
+
+typedef LLUnit<S32, Bytes>     S32Bytes;
+typedef LLUnit<S32, Kilobytes> S32KiloBytes;
+typedef LLUnit<S32, Megabytes> S32MegaBytes;
+typedef LLUnit<S32, Gigabytes> S32GigaBytes;
+typedef LLUnit<S32, Kibibytes> S32KibiBytes;
+typedef LLUnit<S32, Mibibytes> S32MibiBytes;
+typedef LLUnit<S32, Gibibytes> S32GibiBytes;
+
+typedef LLUnit<U32, Bytes>     U32Bytes;
+typedef LLUnit<U32, Kilobytes> U32KiloBytes;
+typedef LLUnit<U32, Megabytes> U32MegaBytes;
+typedef LLUnit<U32, Gigabytes> U32GigaBytes;
+typedef LLUnit<U32, Kibibytes> U32KibiBytes;
+typedef LLUnit<U32, Mibibytes> U32MibiBytes;
+typedef LLUnit<U32, Gibibytes> U32GibiBytes;
+
+typedef LLUnit<S64, Bytes>     S64Bytes;
+typedef LLUnit<S64, Kilobytes> S64KiloBytes;
+typedef LLUnit<S64, Megabytes> S64MegaBytes;
+typedef LLUnit<S64, Gigabytes> S64GigaBytes;
+typedef LLUnit<S64, Kibibytes> S64KibiBytes;
+typedef LLUnit<S64, Mibibytes> S64MibiBytes;
+typedef LLUnit<S64, Gibibytes> S64GibiBytes;
+
+typedef LLUnit<U64, Bytes>     U64Bytes;
+typedef LLUnit<U64, Kilobytes> U64KiloBytes;
+typedef LLUnit<U64, Megabytes> U64MegaBytes;
+typedef LLUnit<U64, Gigabytes> U64GigaBytes;
+typedef LLUnit<U64, Kibibytes> U64KibiBytes;
+typedef LLUnit<U64, Mibibytes> U64MibiBytes;
+typedef LLUnit<U64, Gibibytes> U64GibiBytes;
+
 LL_DECLARE_DERIVED_UNIT(Bytes, / 8,				Bits, "b");
 LL_DECLARE_DERIVED_UNIT(Bits, * 1000,			Kilobits, "Kb");
 LL_DECLARE_DERIVED_UNIT(Kilobits, * 1000,		Megabits, "Mb");
@@ -652,6 +700,54 @@ LL_DECLARE_DERIVED_UNIT(Bits, * 1024,			Kibibits, "Kib");
 LL_DECLARE_DERIVED_UNIT(Kibibits, * 1024,		Mibibits, "Mib");  
 LL_DECLARE_DERIVED_UNIT(Mibibits, * 1024,		Gibibits, "Gib");
 
+typedef LLUnit<F32, Bits>     F32Bits;
+typedef LLUnit<F32, Kilobits> F32KiloBits;
+typedef LLUnit<F32, Megabits> F32MegaBits;
+typedef LLUnit<F32, Gigabits> F32GigaBits;
+typedef LLUnit<F32, Kibibits> F32KibiBits;
+typedef LLUnit<F32, Mibibits> F32MibiBits;
+typedef LLUnit<F32, Gibibits> F32GibiBits;
+
+typedef LLUnit<F64, Bits>     F64Bits;
+typedef LLUnit<F64, Kilobits> F64KiloBits;
+typedef LLUnit<F64, Megabits> F64MegaBits;
+typedef LLUnit<F64, Gigabits> F64GigaBits;
+typedef LLUnit<F64, Kibibits> F64KibiBits;
+typedef LLUnit<F64, Mibibits> F64MibiBits;
+typedef LLUnit<F64, Gibibits> F64GibiBits;
+
+typedef LLUnit<S32, Bits>     S32Bits;
+typedef LLUnit<S32, Kilobits> S32KiloBits;
+typedef LLUnit<S32, Megabits> S32MegaBits;
+typedef LLUnit<S32, Gigabits> S32GigaBits;
+typedef LLUnit<S32, Kibibits> S32KibiBits;
+typedef LLUnit<S32, Mibibits> S32MibiBits;
+typedef LLUnit<S32, Gibibits> S32GibiBits;
+
+typedef LLUnit<U32, Bits>     U32Bits;
+typedef LLUnit<U32, Kilobits> U32KiloBits;
+typedef LLUnit<U32, Megabits> U32MegaBits;
+typedef LLUnit<U32, Gigabits> U32GigaBits;
+typedef LLUnit<U32, Kibibits> U32KibiBits;
+typedef LLUnit<U32, Mibibits> U32MibiBits;
+typedef LLUnit<U32, Gibibits> U32GibiBits;
+
+typedef LLUnit<S64, Bits>     S64Bits;
+typedef LLUnit<S64, Kilobits> S64KiloBits;
+typedef LLUnit<S64, Megabits> S64MegaBits;
+typedef LLUnit<S64, Gigabits> S64GigaBits;
+typedef LLUnit<S64, Kibibits> S64KibiBits;
+typedef LLUnit<S64, Mibibits> S64MibiBits;
+typedef LLUnit<S64, Gibibits> S64GibiBits;
+
+typedef LLUnit<U64, Bits>     U64Bits;
+typedef LLUnit<U64, Kilobits> U64KiloBits;
+typedef LLUnit<U64, Megabits> U64MegaBits;
+typedef LLUnit<U64, Gigabits> U64GigaBits;
+typedef LLUnit<U64, Kibibits> U64KibiBits;
+typedef LLUnit<U64, Mibibits> U64MibiBits;
+typedef LLUnit<U64, Gibibits> U64GibiBits;
+
 LL_DECLARE_BASE_UNIT(Seconds, "s");
 LL_DECLARE_DERIVED_UNIT(Seconds, * 60,			Minutes, "min");
 LL_DECLARE_DERIVED_UNIT(Minutes, * 60,			Hours, "h");
@@ -660,11 +756,90 @@ LL_DECLARE_DERIVED_UNIT(Seconds, / 1000,		Milliseconds, "ms");
 LL_DECLARE_DERIVED_UNIT(Milliseconds, / 1000,	Microseconds, "\x09\x3cs");
 LL_DECLARE_DERIVED_UNIT(Microseconds, / 1000,	Nanoseconds, "ns");
 
+typedef LLUnit<F32, Seconds>      F32Seconds;
+typedef LLUnit<F32, Minutes>      F32Minutes;
+typedef LLUnit<F32, Hours>        F32Hours;
+typedef LLUnit<F32, Days>         F32Days;
+typedef LLUnit<F32, Milliseconds> F32Milliseconds;
+typedef LLUnit<F32, Microseconds> F32Microseconds;
+typedef LLUnit<F32, Nanoseconds>  F32Nanoseconds;
+
+typedef LLUnit<F64, Seconds>      F64Seconds;
+typedef LLUnit<F64, Minutes>      F64Minutes;
+typedef LLUnit<F64, Hours>        F64Hours;
+typedef LLUnit<F64, Days>         F64Days;
+typedef LLUnit<F64, Milliseconds> F64Milliseconds;
+typedef LLUnit<F64, Microseconds> F64Microseconds;
+typedef LLUnit<F64, Nanoseconds>  F64Nanoseconds;
+
+typedef LLUnit<S32, Seconds>      S32Seconds;
+typedef LLUnit<S32, Minutes>      S32Minutes;
+typedef LLUnit<S32, Hours>        S32Hours;
+typedef LLUnit<S32, Days>         S32Days;
+typedef LLUnit<S32, Milliseconds> S32Milliseconds;
+typedef LLUnit<S32, Microseconds> S32Microseconds;
+typedef LLUnit<S32, Nanoseconds>  S32Nanoseconds;
+
+typedef LLUnit<U32, Seconds>      U32Seconds;
+typedef LLUnit<U32, Minutes>      U32Minutes;
+typedef LLUnit<U32, Hours>        U32Hours;
+typedef LLUnit<U32, Days>         U32Days;
+typedef LLUnit<U32, Milliseconds> U32Milliseconds;
+typedef LLUnit<U32, Microseconds> U32Microseconds;
+typedef LLUnit<U32, Nanoseconds>  U32Nanoseconds;
+
+typedef LLUnit<S64, Seconds>      S64Seconds;
+typedef LLUnit<S64, Minutes>      S64Minutes;
+typedef LLUnit<S64, Hours>        S64Hours;
+typedef LLUnit<S64, Days>         S64Days;
+typedef LLUnit<S64, Milliseconds> S64Milliseconds;
+typedef LLUnit<S64, Microseconds> S64Microseconds;
+typedef LLUnit<S64, Nanoseconds>  S64Nanoseconds;
+
+typedef LLUnit<U64, Seconds>      U64Seconds;
+typedef LLUnit<U64, Minutes>      U64Minutes;
+typedef LLUnit<U64, Hours>        U64Hours;
+typedef LLUnit<U64, Days>         U64Days;
+typedef LLUnit<U64, Milliseconds> U64Milliseconds;
+typedef LLUnit<U64, Microseconds> U64Microseconds;
+typedef LLUnit<U64, Nanoseconds>  U64Nanoseconds;
+
 LL_DECLARE_BASE_UNIT(Meters, "m");
 LL_DECLARE_DERIVED_UNIT(Meters, * 1000,			Kilometers, "km");
 LL_DECLARE_DERIVED_UNIT(Meters, / 100,			Centimeters, "cm");
 LL_DECLARE_DERIVED_UNIT(Meters, / 1000,			Millimeters, "mm");
 
+typedef LLUnit<F32, Meters>      F32Meters;
+typedef LLUnit<F32, Kilometers>  F32Kilometers;
+typedef LLUnit<F32, Centimeters> F32Centimeters;
+typedef LLUnit<F32, Millimeters> F32Millimeters;
+
+typedef LLUnit<F64, Meters>      F64Meters;
+typedef LLUnit<F64, Kilometers>  F64Kilometers;
+typedef LLUnit<F64, Centimeters> F64Centimeters;
+typedef LLUnit<F64, Millimeters> F64Millimeters;
+
+typedef LLUnit<S32, Meters>      S32Meters;
+typedef LLUnit<S32, Kilometers>  S32Kilometers;
+typedef LLUnit<S32, Centimeters> S32Centimeters;
+typedef LLUnit<S32, Millimeters> S32Millimeters;
+
+typedef LLUnit<U32, Meters>      U32Meters;
+typedef LLUnit<U32, Kilometers>  U32Kilometers;
+typedef LLUnit<U32, Centimeters> U32Centimeters;
+typedef LLUnit<U32, Millimeters> U32Millimeters;
+
+typedef LLUnit<S64, Meters>      S64Meters;
+typedef LLUnit<S64, Kilometers>  S64Kilometers;
+typedef LLUnit<S64, Centimeters> S64Centimeters;
+typedef LLUnit<S64, Millimeters> S64Millimeters;
+
+typedef LLUnit<U64, Meters>      U64Meters;
+typedef LLUnit<U64, Kilometers>  U64Kilometers;
+typedef LLUnit<U64, Centimeters> U64Centimeters;
+typedef LLUnit<U64, Millimeters> U64Millimeters;
+
+// rare units
 LL_DECLARE_BASE_UNIT(Hertz, "Hz");
 LL_DECLARE_DERIVED_UNIT(Hertz, * 1000,			Kilohertz, "KHz");
 LL_DECLARE_DERIVED_UNIT(Kilohertz, * 1000,		Megahertz, "MHz");
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index b0309585aa..8546bcbc54 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -112,7 +112,7 @@ namespace tut
 	void units_object_t::test<4>()
 	{
 		// exercise math operations
-		LLUnit<F32, Quatloos> quatloos = 1.f;
+		LLUnit<F32, Quatloos> quatloos(1.f);
 		quatloos *= 4.f;
 		ensure(quatloos == 4);
 		quatloos = quatloos * 2;
-- 
cgit v1.2.3


From da030893dd57bdc745330409f28a5982f453a727 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 14 Aug 2013 17:22:29 -0700
Subject: BUILDFIX: gcc fixes

---
 indra/llcommon/llerror.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 6f128d0a20..1b1aada8c1 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -449,7 +449,7 @@ namespace LLError
 			mTimeFunction(NULL),
 			mFileRecorder(NULL),
 			mFixedBufferRecorder(NULL),
-			mShouldLogCallCounter(NULL)
+			mShouldLogCallCounter(0)
 		{}
 		
 		~Settings()
@@ -548,12 +548,12 @@ namespace LLError
 #else
 #if LL_LINUX
 		// gross, but typeid comparison seems to always fail here with gcc4.1
-		if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name()))
+		if (0 != strcmp(mClassInfo.name(), typeid(NoClassInfo).name()))
 #else
-		if (site.mClassInfo != typeid(NoClassInfo))
+		if (mClassInfo != typeid(NoClassInfo))
 #endif // LL_LINUX
 		{
-			mFunctionString = className(site.mClassInfo) + "::";
+			mFunctionString = className(mClassInfo) + "::";
 		}
 #endif
 		mFunctionString += std::string(mFunction) + ":";
@@ -1065,8 +1065,8 @@ namespace LLError
 		
 		s.mShouldLogCallCounter++;
 
-		std::string& class_name = className(site.mClassInfo);
-		std::string& function_name = functionName(site.mFunction);
+		const std::string& class_name = className(site.mClassInfo);
+		std::string function_name = functionName(site.mFunction);
 #if LL_LINUX
 		// gross, but typeid comparison seems to always fail here with gcc4.1
 		if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name()))
-- 
cgit v1.2.3


From a2dc1b7e55b27987f9b20d1e0470a8df77ecc595 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 14 Aug 2013 17:45:15 -0700
Subject: BUILDFIX: more gcc fixes

---
 indra/llcommon/lltracerecording.h | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 811786fbfa..3c23c6a3f6 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -347,7 +347,7 @@ namespace LLTrace
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				Recording& recording = getPrevRecording(i);
-				num_samples += Recording.getSampleCount(stat);
+				num_samples += recording.getSampleCount(stat);
 			}
 			return num_samples;
         }
@@ -366,7 +366,7 @@ namespace LLTrace
 			typename T::value_t min_val = std::numeric_limits<typename T::value_t>::max();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
-				Recording& recording = getPrevRecording(i)
+				Recording& recording = getPrevRecording(i);
 				min_val = llmin(min_val, recording.getSum(stat));
 			}
 			return min_val;
@@ -398,7 +398,7 @@ namespace LLTrace
 			size_t total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-			RelatedTypes<typename T::value_t>::fractional_t min_val = std::numeric_limits<F64>::max();
+			typename RelatedTypes<typename T::value_t>::fractional_t min_val = std::numeric_limits<F64>::max();
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				Recording& recording = getPrevRecording(i);
@@ -485,7 +485,7 @@ namespace LLTrace
 			size_t total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-			typename RelatedTypes<T::value_t>::fractional_t mean(0);
+			typename RelatedTypes<typename T::value_t>::fractional_t mean(0);
 
 			for (S32 i = 1; i <= num_periods; i++)
 			{
@@ -496,8 +496,8 @@ namespace LLTrace
 				}
 			}
 			return (num_periods
-				? RelatedTypes<T::value_t>::fractional_t(mean / num_periods)
-				: RelatedTypes<T::value_t>::fractional_t(NaN));
+				? RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods)
+				: RelatedTypes<typename T::value_t>::fractional_t(NaN));
 		}
 
 		template<typename T>
@@ -525,7 +525,7 @@ namespace LLTrace
 			size_t total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-			typename RelatedTypes<T::value_t>::fractional_t mean = 0;
+			typename RelatedTypes<typename T::value_t>::fractional_t mean = 0;
 
 			for (S32 i = 1; i <= num_periods; i++)
 			{
@@ -537,8 +537,8 @@ namespace LLTrace
 			}
 
 			return (num_periods
-				? RelatedTypes<T::value_t>::fractional_t(mean / num_periods)
-				: RelatedTypes<T::value_t>::fractional_t(NaN));
+				? RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods)
+				: RelatedTypes<typename T::value_t>::fractional_t(NaN));
 		}
 
 		template<typename T>
-- 
cgit v1.2.3


From d83c51a4e1923508e31f25576761f001d731ea93 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 14 Aug 2013 21:58:30 -0700
Subject: BUILDFIX: converted platform-specific files over to new LL_INFOS, etc
 macros

---
 indra/llcommon/llerror.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index a3619559eb..fd7675465c 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -356,10 +356,10 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 
 // DEPRECATED: Use the new macros that allow tags and *look* like macros.
 //#define lldebugs	LL_DEBUGS()
-#define llinfos		LL_INFOS()
+#define LL_INFOS()		LL_INFOS()
 //#define llwarns		LL_WARNS()
 //#define llerrs		LL_ERRS()
 //#define llcont		LL_CONT
-#define llendl		LL_ENDL 
+#define LL_ENDL		LL_ENDL 
 
 #endif // LL_LLERROR_H
-- 
cgit v1.2.3


From 01c1d40b3faa139e9aeacbea7acae3ab65ca9dcd Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 14 Aug 2013 22:01:43 -0700
Subject: BUILDFIX: converted platform-specific files over to new LL_INFOS, etc
 macros fixed bad search and replace

---
 indra/llcommon/llerror.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index fd7675465c..af76a7653a 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -308,7 +308,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 #define lllog(level, once, ...)																	          \
 	do {                                                                                                  \
 		const char* tags[] = {"", ##__VA_ARGS__};													      \
-		::size_t tag_count = LL_ARRAY_SIZE(tags) - 1;														  \
+		::size_t tag_count = LL_ARRAY_SIZE(tags) - 1;													  \
 		static LLError::CallSite _site(                                                                   \
 		    level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, &tags[1], tag_count);\
 		if (LL_UNLIKELY(_site.shouldLog()))			                                                      \
@@ -356,10 +356,10 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 
 // DEPRECATED: Use the new macros that allow tags and *look* like macros.
 //#define lldebugs	LL_DEBUGS()
-#define LL_INFOS()		LL_INFOS()
+#define llinfos		LL_INFOS()
 //#define llwarns		LL_WARNS()
 //#define llerrs		LL_ERRS()
 //#define llcont		LL_CONT
-#define LL_ENDL		LL_ENDL 
+#define llendl		LL_ENDL 
 
 #endif // LL_LLERROR_H
-- 
cgit v1.2.3


From 9f7bfa1c3710856cd2b0a0a8a429d6c45b0fcd09 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 15 Aug 2013 00:02:23 -0700
Subject: moved unit types out of LLUnits namespace, since they are prefixed

---
 indra/llcommon/llfasttimer.cpp       |  10 +-
 indra/llcommon/llfasttimer.h         |   2 +-
 indra/llcommon/lltimer.cpp           |   2 +-
 indra/llcommon/lltraceaccumulators.h |   6 +-
 indra/llcommon/lltracerecording.cpp  |  62 +++----
 indra/llcommon/lltracerecording.h    |  36 ++--
 indra/llcommon/llunit.h              | 342 ++++++++++++++++++-----------------
 7 files changed, 236 insertions(+), 224 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index a91e716f19..5f92c66f47 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -339,7 +339,7 @@ void TimeBlock::logStats()
 		}
 		call_count++;
 
-		LLUnits::F64Seconds total_time(0);
+		F64Seconds total_time(0);
 		LLSD sd;
 
 		{
@@ -382,11 +382,11 @@ void TimeBlock::dumpCurTimes()
 		++it)
 	{
 		TimeBlock* timerp = (*it);
-		LLUnits::F64Seconds total_time = last_frame_recording.getSum(*timerp);
+		F64Seconds 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 < LLUnits::F32Milliseconds(0.1f)) continue;
+		if (total_time < F32Milliseconds(0.1f)) continue;
 
 		std::ostringstream out_str;
 		TimeBlock* parent_timerp = timerp;
@@ -466,11 +466,11 @@ void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
 	}
 }
 
-LLUnits::F64Seconds BlockTimer::getElapsedTime()
+F64Seconds BlockTimer::getElapsedTime()
 {
 	U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
 
-	return LLUnits::F64Seconds((F64)total_time / (F64)TimeBlock::countsPerSecond());
+	return F64Seconds((F64)total_time / (F64)TimeBlock::countsPerSecond());
 }
 
 
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 589b9bb941..ccf71c3f4c 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -48,7 +48,7 @@ public:
 	BlockTimer(TimeBlock& timer);
 	~BlockTimer();
 
-	LLUnits::F64Seconds getElapsedTime();
+	F64Seconds getElapsedTime();
 
 private:
 
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 7077ea4b4f..74f3a7f587 100755
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -262,7 +262,7 @@ LLUnitImplicit<U64, LLUnits::Microseconds> totalTime()
 	}
 
 	// Return the total clock tick count in microseconds.
-	return LLUnits::U64Microseconds(gTotalTimeClockCount*gClocksToMicroseconds);
+	return U64Microseconds(gTotalTimeClockCount*gClocksToMicroseconds);
 }
 
 
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 4d79964526..73da6bd2d8 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -418,7 +418,7 @@ namespace LLTrace
 	class TimeBlockAccumulator
 	{
 	public:
-		typedef LLUnits::F64Seconds value_t;
+		typedef F64Seconds value_t;
 		typedef TimeBlockAccumulator self_t;
 
 		// fake classes that allows us to view different facets of underlying statistic
@@ -429,7 +429,7 @@ namespace LLTrace
 
 		struct SelfTimeFacet
 		{
-			typedef LLUnits::F64Seconds value_t;
+			typedef F64Seconds value_t;
 		};
 
 		TimeBlockAccumulator();
@@ -492,7 +492,7 @@ namespace LLTrace
 
 		struct ChildMemFacet
 		{
-			typedef LLUnit<F64, LLUnits::Bytes> value_t;
+			typedef F64Bytes value_t;
 		};
 
 		MemStatAccumulator()
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 963f0cd174..bc98eebf31 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -95,7 +95,7 @@ void Recording::handleReset()
 {
 	mBuffers.write()->reset();
 
-	mElapsedSeconds = LLUnits::F64Seconds(0.0);
+	mElapsedSeconds = F64Seconds(0.0);
 	mSamplingTimer.reset();
 }
 
@@ -128,17 +128,17 @@ void Recording::appendRecording( Recording& other )
 	mElapsedSeconds += other.mElapsedSeconds;
 }
 
-LLUnits::F64Seconds Recording::getSum(const TraceType<TimeBlockAccumulator>& stat)
+F64Seconds Recording::getSum(const TraceType<TimeBlockAccumulator>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
-	return LLUnits::F64Seconds((F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
+	return F64Seconds((F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
 				/ (F64)LLTrace::TimeBlock::countsPerSecond());
 }
 
-LLUnits::F64Seconds Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat)
+F64Seconds Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
-	return LLUnits::F64Seconds((F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond());
+	return F64Seconds((F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond());
 }
 
 
@@ -147,19 +147,19 @@ U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& sta
 	return mBuffers->mStackTimers[stat.getIndex()].mCalls;
 }
 
-LLUnits::F64Seconds Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat)
+F64Seconds Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
-	return LLUnits::F64Seconds((F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
+	return F64Seconds((F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
 				/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()));
 }
 
-LLUnits::F64Seconds Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat)
+F64Seconds Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
-	return LLUnits::F64Seconds((F64)(accumulator.mSelfTimeCounter) 
+	return F64Seconds((F64)(accumulator.mSelfTimeCounter) 
 			/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()));
 }
 
@@ -168,54 +168,54 @@ F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>&
 	return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds.value();
 }
 
-LLUnits::F64Bytes Recording::getMin(const TraceType<MemStatAccumulator>& stat)
+F64Bytes Recording::getMin(const TraceType<MemStatAccumulator>& stat)
 {
-	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMin());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMin());
 }
 
-LLUnits::F64Bytes Recording::getMean(const TraceType<MemStatAccumulator>& stat)
+F64Bytes Recording::getMean(const TraceType<MemStatAccumulator>& stat)
 {
-	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMean());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMean());
 }
 
-LLUnits::F64Bytes Recording::getMax(const TraceType<MemStatAccumulator>& stat)
+F64Bytes Recording::getMax(const TraceType<MemStatAccumulator>& stat)
 {
-	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMax());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMax());
 }
 
-LLUnits::F64Bytes Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat)
+F64Bytes Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat)
 {
-	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation());
 }
 
-LLUnits::F64Bytes Recording::getLastValue(const TraceType<MemStatAccumulator>& stat)
+F64Bytes Recording::getLastValue(const TraceType<MemStatAccumulator>& stat)
 {
-	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue());
 }
 
-LLUnits::F64Bytes Recording::getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
+F64Bytes Recording::getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMin());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMin());
 }
 
-LLUnits::F64Bytes Recording::getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
+F64Bytes Recording::getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMean());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMean());
 }
 
-LLUnits::F64Bytes Recording::getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
+F64Bytes Recording::getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMax());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMax());
 }
 
-LLUnits::F64Bytes Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
+F64Bytes Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getStandardDeviation());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getStandardDeviation());
 }
 
-LLUnits::F64Bytes Recording::getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
+F64Bytes Recording::getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
 {
-	return LLUnits::F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getLastValue());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getLastValue());
 }
 
 U32 Recording::getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat)
@@ -427,9 +427,9 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 	getCurRecording().setPlayState(getPlayState());
 }
 
-LLUnits::F64Seconds PeriodicRecording::getDuration() const
+F64Seconds PeriodicRecording::getDuration() const
 {
-	LLUnits::F64Seconds duration;
+	F64Seconds duration;
 	size_t num_periods = mRecordingPeriods.size();
 	for (size_t i = 1; i <= num_periods; i++)
 	{
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 3c23c6a3f6..68b95a1003 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -166,26 +166,26 @@ namespace LLTrace
 		void makeUnique() { mBuffers.makeUnique(); }
 
 		// Timer accessors
-		LLUnits::F64Seconds getSum(const TraceType<TimeBlockAccumulator>& stat);
-		LLUnits::F64Seconds getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat);
+		F64Seconds getSum(const TraceType<TimeBlockAccumulator>& stat);
+		F64Seconds getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat);
 		U32 getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat);
 
-		LLUnits::F64Seconds getPerSec(const TraceType<TimeBlockAccumulator>& stat);
-		LLUnits::F64Seconds getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat);
+		F64Seconds getPerSec(const TraceType<TimeBlockAccumulator>& stat);
+		F64Seconds getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat);
 		F32 getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat);
 
 		// Memory accessors
-		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);
+		F64Bytes getMin(const TraceType<MemStatAccumulator>& stat);
+		F64Bytes getMean(const TraceType<MemStatAccumulator>& stat);
+		F64Bytes getMax(const TraceType<MemStatAccumulator>& stat);
+		F64Bytes getStandardDeviation(const TraceType<MemStatAccumulator>& stat);
+		F64Bytes getLastValue(const TraceType<MemStatAccumulator>& stat);
+
+		F64Bytes getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat);
+		F64Bytes getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat);
+		F64Bytes getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat);
+		F64Bytes getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat);
+		F64Bytes getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat);
 
 		U32 getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat);
 		U32 getSum(const TraceType<MemStatAccumulator::DeallocationCountFacet>& stat);
@@ -295,7 +295,7 @@ namespace LLTrace
 
 		U32 getSampleCount(const TraceType<EventAccumulator>& stat);
 
-		LLUnits::F64Seconds getDuration() const { return mElapsedSeconds; }
+		F64Seconds getDuration() const { return mElapsedSeconds; }
 
 	protected:
 		friend class ThreadRecorder;
@@ -310,7 +310,7 @@ namespace LLTrace
 		class ThreadRecorder* getThreadRecorder(); 
 
 		LLTimer											mSamplingTimer;
-		LLUnits::F64Seconds					mElapsedSeconds;
+		F64Seconds					mElapsedSeconds;
 		LLCopyOnWritePointer<AccumulatorBufferGroup>	mBuffers;
 		bool											mInHandOff;
 
@@ -325,7 +325,7 @@ namespace LLTrace
 		void nextPeriod();
 		size_t getNumRecordedPeriods() { return mNumPeriods; }
 
-		LLUnits::F64Seconds getDuration() const;
+		F64Seconds getDuration() const;
 
 		void appendPeriodicRecording(PeriodicRecording& other);
 		void appendRecording(Recording& recording);
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 9a367d9182..b62bebc440 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -643,55 +643,58 @@ LL_DECLARE_DERIVED_UNIT(Megabytes, * 1000,		Gigabytes, "GB");
 LL_DECLARE_DERIVED_UNIT(Bytes, * 1024,			Kibibytes, "KiB");
 LL_DECLARE_DERIVED_UNIT(Kibibytes, * 1024,		Mibibytes, "MiB");
 LL_DECLARE_DERIVED_UNIT(Mibibytes, * 1024,		Gibibytes, "GiB");
+}
 
-typedef LLUnit<F32, Bytes>     F32Bytes;
-typedef LLUnit<F32, Kilobytes> F32KiloBytes;
-typedef LLUnit<F32, Megabytes> F32MegaBytes;
-typedef LLUnit<F32, Gigabytes> F32GigaBytes;
-typedef LLUnit<F32, Kibibytes> F32KibiBytes;
-typedef LLUnit<F32, Mibibytes> F32MibiBytes;
-typedef LLUnit<F32, Gibibytes> F32GibiBytes;
-
-typedef LLUnit<F64, Bytes>     F64Bytes;
-typedef LLUnit<F64, Kilobytes> F64KiloBytes;
-typedef LLUnit<F64, Megabytes> F64MegaBytes;
-typedef LLUnit<F64, Gigabytes> F64GigaBytes;
-typedef LLUnit<F64, Kibibytes> F64KibiBytes;
-typedef LLUnit<F64, Mibibytes> F64MibiBytes;
-typedef LLUnit<F64, Gibibytes> F64GibiBytes;
-
-typedef LLUnit<S32, Bytes>     S32Bytes;
-typedef LLUnit<S32, Kilobytes> S32KiloBytes;
-typedef LLUnit<S32, Megabytes> S32MegaBytes;
-typedef LLUnit<S32, Gigabytes> S32GigaBytes;
-typedef LLUnit<S32, Kibibytes> S32KibiBytes;
-typedef LLUnit<S32, Mibibytes> S32MibiBytes;
-typedef LLUnit<S32, Gibibytes> S32GibiBytes;
-
-typedef LLUnit<U32, Bytes>     U32Bytes;
-typedef LLUnit<U32, Kilobytes> U32KiloBytes;
-typedef LLUnit<U32, Megabytes> U32MegaBytes;
-typedef LLUnit<U32, Gigabytes> U32GigaBytes;
-typedef LLUnit<U32, Kibibytes> U32KibiBytes;
-typedef LLUnit<U32, Mibibytes> U32MibiBytes;
-typedef LLUnit<U32, Gibibytes> U32GibiBytes;
-
-typedef LLUnit<S64, Bytes>     S64Bytes;
-typedef LLUnit<S64, Kilobytes> S64KiloBytes;
-typedef LLUnit<S64, Megabytes> S64MegaBytes;
-typedef LLUnit<S64, Gigabytes> S64GigaBytes;
-typedef LLUnit<S64, Kibibytes> S64KibiBytes;
-typedef LLUnit<S64, Mibibytes> S64MibiBytes;
-typedef LLUnit<S64, Gibibytes> S64GibiBytes;
-
-typedef LLUnit<U64, Bytes>     U64Bytes;
-typedef LLUnit<U64, Kilobytes> U64KiloBytes;
-typedef LLUnit<U64, Megabytes> U64MegaBytes;
-typedef LLUnit<U64, Gigabytes> U64GigaBytes;
-typedef LLUnit<U64, Kibibytes> U64KibiBytes;
-typedef LLUnit<U64, Mibibytes> U64MibiBytes;
-typedef LLUnit<U64, Gibibytes> U64GibiBytes;
+typedef LLUnit<F32, LLUnits::Bytes>     F32Bytes;
+typedef LLUnit<F32, LLUnits::Kilobytes> F32Kilobytes;
+typedef LLUnit<F32, LLUnits::Megabytes> F32Megabytes;
+typedef LLUnit<F32, LLUnits::Gigabytes> F32Gigabytes;
+typedef LLUnit<F32, LLUnits::Kibibytes> F32Kibibytes;
+typedef LLUnit<F32, LLUnits::Mibibytes> F32Mibibytes;
+typedef LLUnit<F32, LLUnits::Gibibytes> F32Gibibytes;
+
+typedef LLUnit<F64, LLUnits::Bytes>     F64Bytes;
+typedef LLUnit<F64, LLUnits::Kilobytes> F64Kilobytes;
+typedef LLUnit<F64, LLUnits::Megabytes> F64Megabytes;
+typedef LLUnit<F64, LLUnits::Gigabytes> F64Gigabytes;
+typedef LLUnit<F64, LLUnits::Kibibytes> F64Kibibytes;
+typedef LLUnit<F64, LLUnits::Mibibytes> F64Mibibytes;
+typedef LLUnit<F64, LLUnits::Gibibytes> F64Gibibytes;
+
+typedef LLUnit<S32, LLUnits::Bytes>     S32Bytes;
+typedef LLUnit<S32, LLUnits::Kilobytes> S32Kilobytes;
+typedef LLUnit<S32, LLUnits::Megabytes> S32Megabytes;
+typedef LLUnit<S32, LLUnits::Gigabytes> S32Gigabytes;
+typedef LLUnit<S32, LLUnits::Kibibytes> S32Kibibytes;
+typedef LLUnit<S32, LLUnits::Mibibytes> S32Mibibytes;
+typedef LLUnit<S32, LLUnits::Gibibytes> S32Gibibytes;
+
+typedef LLUnit<U32, LLUnits::Bytes>     U32Bytes;
+typedef LLUnit<U32, LLUnits::Kilobytes> U32Kilobytes;
+typedef LLUnit<U32, LLUnits::Megabytes> U32Megabytes;
+typedef LLUnit<U32, LLUnits::Gigabytes> U32Gigabytes;
+typedef LLUnit<U32, LLUnits::Kibibytes> U32Kibibytes;
+typedef LLUnit<U32, LLUnits::Mibibytes> U32Mibibytes;
+typedef LLUnit<U32, LLUnits::Gibibytes> U32Gibibytes;
+
+typedef LLUnit<S64, LLUnits::Bytes>     S64Bytes;
+typedef LLUnit<S64, LLUnits::Kilobytes> S64Kilobytes;
+typedef LLUnit<S64, LLUnits::Megabytes> S64Megabytes;
+typedef LLUnit<S64, LLUnits::Gigabytes> S64Gigabytes;
+typedef LLUnit<S64, LLUnits::Kibibytes> S64Kibibytes;
+typedef LLUnit<S64, LLUnits::Mibibytes> S64Mibibytes;
+typedef LLUnit<S64, LLUnits::Gibibytes> S64Gibibytes;
+
+typedef LLUnit<U64, LLUnits::Bytes>     U64Bytes;
+typedef LLUnit<U64, LLUnits::Kilobytes> U64Kilobytes;
+typedef LLUnit<U64, LLUnits::Megabytes> U64Megabytes;
+typedef LLUnit<U64, LLUnits::Gigabytes> U64Gigabytes;
+typedef LLUnit<U64, LLUnits::Kibibytes> U64Kibibytes;
+typedef LLUnit<U64, LLUnits::Mibibytes> U64Mibibytes;
+typedef LLUnit<U64, LLUnits::Gibibytes> U64Gibibytes;
 
+namespace LLUnits
+{
 LL_DECLARE_DERIVED_UNIT(Bytes, / 8,				Bits, "b");
 LL_DECLARE_DERIVED_UNIT(Bits, * 1000,			Kilobits, "Kb");
 LL_DECLARE_DERIVED_UNIT(Kilobits, * 1000,		Megabits, "Mb");
@@ -699,55 +702,58 @@ LL_DECLARE_DERIVED_UNIT(Megabits, * 1000,		Gigabits, "Gb");
 LL_DECLARE_DERIVED_UNIT(Bits, * 1024,			Kibibits, "Kib");
 LL_DECLARE_DERIVED_UNIT(Kibibits, * 1024,		Mibibits, "Mib");  
 LL_DECLARE_DERIVED_UNIT(Mibibits, * 1024,		Gibibits, "Gib");
+}
 
-typedef LLUnit<F32, Bits>     F32Bits;
-typedef LLUnit<F32, Kilobits> F32KiloBits;
-typedef LLUnit<F32, Megabits> F32MegaBits;
-typedef LLUnit<F32, Gigabits> F32GigaBits;
-typedef LLUnit<F32, Kibibits> F32KibiBits;
-typedef LLUnit<F32, Mibibits> F32MibiBits;
-typedef LLUnit<F32, Gibibits> F32GibiBits;
-
-typedef LLUnit<F64, Bits>     F64Bits;
-typedef LLUnit<F64, Kilobits> F64KiloBits;
-typedef LLUnit<F64, Megabits> F64MegaBits;
-typedef LLUnit<F64, Gigabits> F64GigaBits;
-typedef LLUnit<F64, Kibibits> F64KibiBits;
-typedef LLUnit<F64, Mibibits> F64MibiBits;
-typedef LLUnit<F64, Gibibits> F64GibiBits;
-
-typedef LLUnit<S32, Bits>     S32Bits;
-typedef LLUnit<S32, Kilobits> S32KiloBits;
-typedef LLUnit<S32, Megabits> S32MegaBits;
-typedef LLUnit<S32, Gigabits> S32GigaBits;
-typedef LLUnit<S32, Kibibits> S32KibiBits;
-typedef LLUnit<S32, Mibibits> S32MibiBits;
-typedef LLUnit<S32, Gibibits> S32GibiBits;
-
-typedef LLUnit<U32, Bits>     U32Bits;
-typedef LLUnit<U32, Kilobits> U32KiloBits;
-typedef LLUnit<U32, Megabits> U32MegaBits;
-typedef LLUnit<U32, Gigabits> U32GigaBits;
-typedef LLUnit<U32, Kibibits> U32KibiBits;
-typedef LLUnit<U32, Mibibits> U32MibiBits;
-typedef LLUnit<U32, Gibibits> U32GibiBits;
-
-typedef LLUnit<S64, Bits>     S64Bits;
-typedef LLUnit<S64, Kilobits> S64KiloBits;
-typedef LLUnit<S64, Megabits> S64MegaBits;
-typedef LLUnit<S64, Gigabits> S64GigaBits;
-typedef LLUnit<S64, Kibibits> S64KibiBits;
-typedef LLUnit<S64, Mibibits> S64MibiBits;
-typedef LLUnit<S64, Gibibits> S64GibiBits;
-
-typedef LLUnit<U64, Bits>     U64Bits;
-typedef LLUnit<U64, Kilobits> U64KiloBits;
-typedef LLUnit<U64, Megabits> U64MegaBits;
-typedef LLUnit<U64, Gigabits> U64GigaBits;
-typedef LLUnit<U64, Kibibits> U64KibiBits;
-typedef LLUnit<U64, Mibibits> U64MibiBits;
-typedef LLUnit<U64, Gibibits> U64GibiBits;
+typedef LLUnit<F32, LLUnits::Bits>     F32Bits;
+typedef LLUnit<F32, LLUnits::Kilobits> F32Kilobits;
+typedef LLUnit<F32, LLUnits::Megabits> F32Megabits;
+typedef LLUnit<F32, LLUnits::Gigabits> F32Gigabits;
+typedef LLUnit<F32, LLUnits::Kibibits> F32Kibibits;
+typedef LLUnit<F32, LLUnits::Mibibits> F32Mibibits;
+typedef LLUnit<F32, LLUnits::Gibibits> F32Gibibits;
+					
+typedef LLUnit<F64, LLUnits::Bits>     F64Bits;
+typedef LLUnit<F64, LLUnits::Kilobits> F64Kilobits;
+typedef LLUnit<F64, LLUnits::Megabits> F64Megabits;
+typedef LLUnit<F64, LLUnits::Gigabits> F64Gigabits;
+typedef LLUnit<F64, LLUnits::Kibibits> F64Kibibits;
+typedef LLUnit<F64, LLUnits::Mibibits> F64Mibibits;
+typedef LLUnit<F64, LLUnits::Gibibits> F64Gibibits;
+
+typedef LLUnit<S32, LLUnits::Bits>     S32Bits;
+typedef LLUnit<S32, LLUnits::Kilobits> S32Kilobits;
+typedef LLUnit<S32, LLUnits::Megabits> S32Megabits;
+typedef LLUnit<S32, LLUnits::Gigabits> S32Gigabits;
+typedef LLUnit<S32, LLUnits::Kibibits> S32Kibibits;
+typedef LLUnit<S32, LLUnits::Mibibits> S32Mibibits;
+typedef LLUnit<S32, LLUnits::Gibibits> S32Gibibits;
+
+typedef LLUnit<U32, LLUnits::Bits>     U32Bits;
+typedef LLUnit<U32, LLUnits::Kilobits> U32Kilobits;
+typedef LLUnit<U32, LLUnits::Megabits> U32Megabits;
+typedef LLUnit<U32, LLUnits::Gigabits> U32Gigabits;
+typedef LLUnit<U32, LLUnits::Kibibits> U32Kibibits;
+typedef LLUnit<U32, LLUnits::Mibibits> U32Mibibits;
+typedef LLUnit<U32, LLUnits::Gibibits> U32Gibibits;
+
+typedef LLUnit<S64, LLUnits::Bits>     S64Bits;
+typedef LLUnit<S64, LLUnits::Kilobits> S64Kilobits;
+typedef LLUnit<S64, LLUnits::Megabits> S64Megabits;
+typedef LLUnit<S64, LLUnits::Gigabits> S64Gigabits;
+typedef LLUnit<S64, LLUnits::Kibibits> S64Kibibits;
+typedef LLUnit<S64, LLUnits::Mibibits> S64Mibibits;
+typedef LLUnit<S64, LLUnits::Gibibits> S64Gibibits;
+
+typedef LLUnit<U64, LLUnits::Bits>     U64Bits;
+typedef LLUnit<U64, LLUnits::Kilobits> U64Kilobits;
+typedef LLUnit<U64, LLUnits::Megabits> U64Megabits;
+typedef LLUnit<U64, LLUnits::Gigabits> U64Gigabits;
+typedef LLUnit<U64, LLUnits::Kibibits> U64Kibibits;
+typedef LLUnit<U64, LLUnits::Mibibits> U64Mibibits;
+typedef LLUnit<U64, LLUnits::Gibibits> U64Gibibits;
 
+namespace LLUnits
+{
 LL_DECLARE_BASE_UNIT(Seconds, "s");
 LL_DECLARE_DERIVED_UNIT(Seconds, * 60,			Minutes, "min");
 LL_DECLARE_DERIVED_UNIT(Minutes, * 60,			Hours, "h");
@@ -755,90 +761,96 @@ LL_DECLARE_DERIVED_UNIT(Hours, * 24,			Days, "d");
 LL_DECLARE_DERIVED_UNIT(Seconds, / 1000,		Milliseconds, "ms");
 LL_DECLARE_DERIVED_UNIT(Milliseconds, / 1000,	Microseconds, "\x09\x3cs");
 LL_DECLARE_DERIVED_UNIT(Microseconds, / 1000,	Nanoseconds, "ns");
+}
 
-typedef LLUnit<F32, Seconds>      F32Seconds;
-typedef LLUnit<F32, Minutes>      F32Minutes;
-typedef LLUnit<F32, Hours>        F32Hours;
-typedef LLUnit<F32, Days>         F32Days;
-typedef LLUnit<F32, Milliseconds> F32Milliseconds;
-typedef LLUnit<F32, Microseconds> F32Microseconds;
-typedef LLUnit<F32, Nanoseconds>  F32Nanoseconds;
-
-typedef LLUnit<F64, Seconds>      F64Seconds;
-typedef LLUnit<F64, Minutes>      F64Minutes;
-typedef LLUnit<F64, Hours>        F64Hours;
-typedef LLUnit<F64, Days>         F64Days;
-typedef LLUnit<F64, Milliseconds> F64Milliseconds;
-typedef LLUnit<F64, Microseconds> F64Microseconds;
-typedef LLUnit<F64, Nanoseconds>  F64Nanoseconds;
-
-typedef LLUnit<S32, Seconds>      S32Seconds;
-typedef LLUnit<S32, Minutes>      S32Minutes;
-typedef LLUnit<S32, Hours>        S32Hours;
-typedef LLUnit<S32, Days>         S32Days;
-typedef LLUnit<S32, Milliseconds> S32Milliseconds;
-typedef LLUnit<S32, Microseconds> S32Microseconds;
-typedef LLUnit<S32, Nanoseconds>  S32Nanoseconds;
-
-typedef LLUnit<U32, Seconds>      U32Seconds;
-typedef LLUnit<U32, Minutes>      U32Minutes;
-typedef LLUnit<U32, Hours>        U32Hours;
-typedef LLUnit<U32, Days>         U32Days;
-typedef LLUnit<U32, Milliseconds> U32Milliseconds;
-typedef LLUnit<U32, Microseconds> U32Microseconds;
-typedef LLUnit<U32, Nanoseconds>  U32Nanoseconds;
-
-typedef LLUnit<S64, Seconds>      S64Seconds;
-typedef LLUnit<S64, Minutes>      S64Minutes;
-typedef LLUnit<S64, Hours>        S64Hours;
-typedef LLUnit<S64, Days>         S64Days;
-typedef LLUnit<S64, Milliseconds> S64Milliseconds;
-typedef LLUnit<S64, Microseconds> S64Microseconds;
-typedef LLUnit<S64, Nanoseconds>  S64Nanoseconds;
-
-typedef LLUnit<U64, Seconds>      U64Seconds;
-typedef LLUnit<U64, Minutes>      U64Minutes;
-typedef LLUnit<U64, Hours>        U64Hours;
-typedef LLUnit<U64, Days>         U64Days;
-typedef LLUnit<U64, Milliseconds> U64Milliseconds;
-typedef LLUnit<U64, Microseconds> U64Microseconds;
-typedef LLUnit<U64, Nanoseconds>  U64Nanoseconds;
+typedef LLUnit<F32, LLUnits::Seconds>      F32Seconds;
+typedef LLUnit<F32, LLUnits::Minutes>      F32Minutes;
+typedef LLUnit<F32, LLUnits::Hours>        F32Hours;
+typedef LLUnit<F32, LLUnits::Days>         F32Days;
+typedef LLUnit<F32, LLUnits::Milliseconds> F32Milliseconds;
+typedef LLUnit<F32, LLUnits::Microseconds> F32Microseconds;
+typedef LLUnit<F32, LLUnits::Nanoseconds>  F32Nanoseconds;
+
+typedef LLUnit<F64, LLUnits::Seconds>      F64Seconds;
+typedef LLUnit<F64, LLUnits::Minutes>      F64Minutes;
+typedef LLUnit<F64, LLUnits::Hours>        F64Hours;
+typedef LLUnit<F64, LLUnits::Days>         F64Days;
+typedef LLUnit<F64, LLUnits::Milliseconds> F64Milliseconds;
+typedef LLUnit<F64, LLUnits::Microseconds> F64Microseconds;
+typedef LLUnit<F64, LLUnits::Nanoseconds>  F64Nanoseconds;
+
+typedef LLUnit<S32, LLUnits::Seconds>      S32Seconds;
+typedef LLUnit<S32, LLUnits::Minutes>      S32Minutes;
+typedef LLUnit<S32, LLUnits::Hours>        S32Hours;
+typedef LLUnit<S32, LLUnits::Days>         S32Days;
+typedef LLUnit<S32, LLUnits::Milliseconds> S32Milliseconds;
+typedef LLUnit<S32, LLUnits::Microseconds> S32Microseconds;
+typedef LLUnit<S32, LLUnits::Nanoseconds>  S32Nanoseconds;
+
+typedef LLUnit<U32, LLUnits::Seconds>      U32Seconds;
+typedef LLUnit<U32, LLUnits::Minutes>      U32Minutes;
+typedef LLUnit<U32, LLUnits::Hours>        U32Hours;
+typedef LLUnit<U32, LLUnits::Days>         U32Days;
+typedef LLUnit<U32, LLUnits::Milliseconds> U32Milliseconds;
+typedef LLUnit<U32, LLUnits::Microseconds> U32Microseconds;
+typedef LLUnit<U32, LLUnits::Nanoseconds>  U32Nanoseconds;
+
+typedef LLUnit<S64, LLUnits::Seconds>      S64Seconds;
+typedef LLUnit<S64, LLUnits::Minutes>      S64Minutes;
+typedef LLUnit<S64, LLUnits::Hours>        S64Hours;
+typedef LLUnit<S64, LLUnits::Days>         S64Days;
+typedef LLUnit<S64, LLUnits::Milliseconds> S64Milliseconds;
+typedef LLUnit<S64, LLUnits::Microseconds> S64Microseconds;
+typedef LLUnit<S64, LLUnits::Nanoseconds>  S64Nanoseconds;
+					
+typedef LLUnit<U64, LLUnits::Seconds>      U64Seconds;
+typedef LLUnit<U64, LLUnits::Minutes>      U64Minutes;
+typedef LLUnit<U64, LLUnits::Hours>        U64Hours;
+typedef LLUnit<U64, LLUnits::Days>         U64Days;
+typedef LLUnit<U64, LLUnits::Milliseconds> U64Milliseconds;
+typedef LLUnit<U64, LLUnits::Microseconds> U64Microseconds;
+typedef LLUnit<U64, LLUnits::Nanoseconds>  U64Nanoseconds;
 
+namespace LLUnits
+{
 LL_DECLARE_BASE_UNIT(Meters, "m");
 LL_DECLARE_DERIVED_UNIT(Meters, * 1000,			Kilometers, "km");
 LL_DECLARE_DERIVED_UNIT(Meters, / 100,			Centimeters, "cm");
 LL_DECLARE_DERIVED_UNIT(Meters, / 1000,			Millimeters, "mm");
+}
 
-typedef LLUnit<F32, Meters>      F32Meters;
-typedef LLUnit<F32, Kilometers>  F32Kilometers;
-typedef LLUnit<F32, Centimeters> F32Centimeters;
-typedef LLUnit<F32, Millimeters> F32Millimeters;
+typedef LLUnit<F32, LLUnits::Meters>      F32Meters;
+typedef LLUnit<F32, LLUnits::Kilometers>  F32Kilometers;
+typedef LLUnit<F32, LLUnits::Centimeters> F32Centimeters;
+typedef LLUnit<F32, LLUnits::Millimeters> F32Millimeters;
 
-typedef LLUnit<F64, Meters>      F64Meters;
-typedef LLUnit<F64, Kilometers>  F64Kilometers;
-typedef LLUnit<F64, Centimeters> F64Centimeters;
-typedef LLUnit<F64, Millimeters> F64Millimeters;
+typedef LLUnit<F64, LLUnits::Meters>      F64Meters;
+typedef LLUnit<F64, LLUnits::Kilometers>  F64Kilometers;
+typedef LLUnit<F64, LLUnits::Centimeters> F64Centimeters;
+typedef LLUnit<F64, LLUnits::Millimeters> F64Millimeters;
 
-typedef LLUnit<S32, Meters>      S32Meters;
-typedef LLUnit<S32, Kilometers>  S32Kilometers;
-typedef LLUnit<S32, Centimeters> S32Centimeters;
-typedef LLUnit<S32, Millimeters> S32Millimeters;
+typedef LLUnit<S32, LLUnits::Meters>      S32Meters;
+typedef LLUnit<S32, LLUnits::Kilometers>  S32Kilometers;
+typedef LLUnit<S32, LLUnits::Centimeters> S32Centimeters;
+typedef LLUnit<S32, LLUnits::Millimeters> S32Millimeters;
 
-typedef LLUnit<U32, Meters>      U32Meters;
-typedef LLUnit<U32, Kilometers>  U32Kilometers;
-typedef LLUnit<U32, Centimeters> U32Centimeters;
-typedef LLUnit<U32, Millimeters> U32Millimeters;
+typedef LLUnit<U32, LLUnits::Meters>      U32Meters;
+typedef LLUnit<U32, LLUnits::Kilometers>  U32Kilometers;
+typedef LLUnit<U32, LLUnits::Centimeters> U32Centimeters;
+typedef LLUnit<U32, LLUnits::Millimeters> U32Millimeters;
 
-typedef LLUnit<S64, Meters>      S64Meters;
-typedef LLUnit<S64, Kilometers>  S64Kilometers;
-typedef LLUnit<S64, Centimeters> S64Centimeters;
-typedef LLUnit<S64, Millimeters> S64Millimeters;
+typedef LLUnit<S64, LLUnits::Meters>      S64Meters;
+typedef LLUnit<S64, LLUnits::Kilometers>  S64Kilometers;
+typedef LLUnit<S64, LLUnits::Centimeters> S64Centimeters;
+typedef LLUnit<S64, LLUnits::Millimeters> S64Millimeters;
 
-typedef LLUnit<U64, Meters>      U64Meters;
-typedef LLUnit<U64, Kilometers>  U64Kilometers;
-typedef LLUnit<U64, Centimeters> U64Centimeters;
-typedef LLUnit<U64, Millimeters> U64Millimeters;
+typedef LLUnit<U64, LLUnits::Meters>      U64Meters;
+typedef LLUnit<U64, LLUnits::Kilometers>  U64Kilometers;
+typedef LLUnit<U64, LLUnits::Centimeters> U64Centimeters;
+typedef LLUnit<U64, LLUnits::Millimeters> U64Millimeters;
 
+namespace LLUnits
+{
 // rare units
 LL_DECLARE_BASE_UNIT(Hertz, "Hz");
 LL_DECLARE_DERIVED_UNIT(Hertz, * 1000,			Kilohertz, "KHz");
-- 
cgit v1.2.3


From 52640b85c497e8b0a900ff3f1e051021b5485277 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 15 Aug 2013 17:35:17 -0700
Subject: BUILDFIX: mac

---
 indra/llcommon/lltracerecording.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 68b95a1003..f5fb2bf561 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -496,8 +496,8 @@ namespace LLTrace
 				}
 			}
 			return (num_periods
-				? RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods)
-				: RelatedTypes<typename T::value_t>::fractional_t(NaN));
+				? typename RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods)
+				: typename RelatedTypes<typename T::value_t>::fractional_t(NaN));
 		}
 
 		template<typename T>
@@ -537,8 +537,8 @@ namespace LLTrace
 			}
 
 			return (num_periods
-				? RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods)
-				: RelatedTypes<typename T::value_t>::fractional_t(NaN));
+				? typename RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods)
+				: typename RelatedTypes<typename T::value_t>::fractional_t(NaN));
 		}
 
 		template<typename T>
-- 
cgit v1.2.3


From 25937040de9a787c221aae7f178f43827c799028 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 16 Aug 2013 12:38:12 -0700
Subject: SH-4433 WIP: Interesting: Statistics > Ping Sim is always 0 ms
 converted many values over to units system in effort to track down source of
 0 ping

---
 indra/llcommon/llmemory.cpp | 18 +++++++++---------
 indra/llcommon/llmemory.h   | 17 +++++++++--------
 indra/llcommon/llsys.cpp    | 24 ++++++++++++------------
 indra/llcommon/llsys.h      |  6 +++---
 4 files changed, 33 insertions(+), 32 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index a9256124f2..c59b61471a 100755
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -47,11 +47,11 @@
 
 //static
 char* LLMemory::reserveMem = 0;
-U32 LLMemory::sAvailPhysicalMemInKB = U32_MAX ;
-U32 LLMemory::sMaxPhysicalMemInKB = 0;
-U32 LLMemory::sAllocatedMemInKB = 0;
-U32 LLMemory::sAllocatedPageSizeInKB = 0 ;
-U32 LLMemory::sMaxHeapSizeInKB = U32_MAX ;
+U32Kibibytes LLMemory::sAvailPhysicalMemInKB(U32_MAX);
+U32Kibibytes LLMemory::sMaxPhysicalMemInKB(0);
+U32Kibibytes LLMemory::sAllocatedMemInKB(0);
+U32Kibibytes LLMemory::sAllocatedPageSizeInKB(0);
+U32Kibibytes LLMemory::sMaxHeapSizeInKB(U32_MAX);
 BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE;
 
 #if __DEBUG_PRIVATE_MEM__
@@ -116,7 +116,7 @@ void LLMemory::updateMemoryInfo()
 	sAllocatedMemInKB = (U32)(counters.WorkingSetSize / 1024) ;
 	sAllocatedPageSizeInKB = (U32)(counters.PagefileUsage / 1024) ;
 
-	U32 avail_phys, avail_virtual;
+	U32Kibibytes avail_phys, avail_virtual;
 	LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
 	sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
 
@@ -232,19 +232,19 @@ bool LLMemory::isMemoryPoolLow()
 }
 
 //static 
-U32 LLMemory::getAvailableMemKB() 
+U32Kibibytes LLMemory::getAvailableMemKB() 
 {
 	return sAvailPhysicalMemInKB ;
 }
 
 //static 
-U32 LLMemory::getMaxMemKB() 
+U32Kibibytes LLMemory::getMaxMemKB() 
 {
 	return sMaxPhysicalMemInKB ;
 }
 
 //static 
-U32 LLMemory::getAllocatedMemKB() 
+U32Kibibytes LLMemory::getAllocatedMemKB() 
 {
 	return sAllocatedMemInKB ;
 }
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index a24d97576f..c45c7ed213 100755
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -27,6 +27,7 @@
 #define LLMEMORY_H
 
 #include "linden_common.h"
+#include "llunit.h"
 #if !LL_WINDOWS
 #include <stdint.h>
 #endif
@@ -170,17 +171,17 @@ public:
 	static void logMemoryInfo(BOOL update = FALSE);
 	static bool isMemoryPoolLow();
 
-	static U32 getAvailableMemKB() ;
-	static U32 getMaxMemKB() ;
-	static U32 getAllocatedMemKB() ;
+	static U32Kibibytes getAvailableMemKB() ;
+	static U32Kibibytes getMaxMemKB() ;
+	static U32Kibibytes getAllocatedMemKB() ;
 private:
 	static char* reserveMem;
-	static U32 sAvailPhysicalMemInKB ;
-	static U32 sMaxPhysicalMemInKB ;
-	static U32 sAllocatedMemInKB;
-	static U32 sAllocatedPageSizeInKB ;
+	static U32Kibibytes sAvailPhysicalMemInKB ;
+	static U32Kibibytes sMaxPhysicalMemInKB ;
+	static U32Kibibytes sAllocatedMemInKB;
+	static U32Kibibytes sAllocatedPageSizeInKB ;
 
-	static U32 sMaxHeapSizeInKB;
+	static U32Kibibytes sMaxHeapSizeInKB;
 	static BOOL sEnableMemoryFailurePrevention;
 };
 
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index cad02f491a..8f7e60fb68 100755
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -832,7 +832,7 @@ LLMemoryInfo::LLMemoryInfo()
 }
 
 #if LL_WINDOWS
-static U32 LLMemoryAdjustKBResult(U32 inKB)
+static U32Kibibytes LLMemoryAdjustKBResult(U32Kibibytes inKB)
 {
 	// Moved this here from llfloaterabout.cpp
 
@@ -843,16 +843,16 @@ static U32 LLMemoryAdjustKBResult(U32 inKB)
 	// returned from the GetMemoryStatusEx function.  Here we keep the
 	// original adjustment from llfoaterabout.cpp until this can be
 	// fixed somehow.
-	inKB += 1024;
+	inKB += U32Mibibytes(1);
 
 	return inKB;
 }
 #endif
 
-U32 LLMemoryInfo::getPhysicalMemoryKB() const
+U32Kibibytes LLMemoryInfo::getPhysicalMemoryKB() const
 {
 #if LL_WINDOWS
-	return LLMemoryAdjustKBResult(mStatsMap["Total Physical KB"].asInteger());
+	return LLMemoryAdjustKBResult(U32Kibibytes(mStatsMap["Total Physical KB"].asInteger()));
 
 #elif LL_DARWIN
 	// This might work on Linux as well.  Someone check...
@@ -862,17 +862,17 @@ U32 LLMemoryInfo::getPhysicalMemoryKB() const
 	size_t len = sizeof(phys);	
 	sysctl(mib, 2, &phys, &len, NULL, 0);
 	
-	return (U32)(phys >> 10);
+	return U32Bytes(phys);
 
 #elif LL_LINUX
 	U64 phys = 0;
 	phys = (U64)(getpagesize()) * (U64)(get_phys_pages());
-	return (U32)(phys >> 10);
+	return U32Bytes(phys);
 
 #elif LL_SOLARIS
 	U64 phys = 0;
 	phys = (U64)(getpagesize()) * (U64)(sysconf(_SC_PHYS_PAGES));
-	return (U32)(phys >> 10);
+	return U32Bytes(phys);
 
 #else
 	return 0;
@@ -880,24 +880,24 @@ U32 LLMemoryInfo::getPhysicalMemoryKB() const
 #endif
 }
 
-U32 LLMemoryInfo::getPhysicalMemoryClamped() const
+U32Bytes LLMemoryInfo::getPhysicalMemoryClamped() const
 {
 	// Return the total physical memory in bytes, but clamp it
 	// to no more than U32_MAX
 	
-	U32 phys_kb = getPhysicalMemoryKB();
+	U32Bytes phys_kb = getPhysicalMemoryKB();
 	if (phys_kb >= 4194304 /* 4GB in KB */)
 	{
-		return U32_MAX;
+		return U32Bytes(U32_MAX);
 	}
 	else
 	{
-		return phys_kb << 10;
+		return phys_kb;
 	}
 }
 
 //static
-void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb)
+void LLMemoryInfo::getAvailableMemoryKB(U32Kibibytes& avail_physical_mem_kb, U32Kibibytes& avail_virtual_mem_kb)
 {
 #if LL_WINDOWS
 	// Sigh, this shouldn't be a static method, then we wouldn't have to
diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h
index aa60fc9b2e..ad4f243d05 100755
--- a/indra/llcommon/llsys.h
+++ b/indra/llcommon/llsys.h
@@ -112,15 +112,15 @@ public:
 	LLMemoryInfo(); ///< Default constructor
 	void stream(std::ostream& s) const;	///< output text info to s
 
-	U32 getPhysicalMemoryKB() const; ///< Memory size in KiloBytes
+	U32Kibibytes getPhysicalMemoryKB() const; 
 	
 	/*! Memory size in bytes, if total memory is >= 4GB then U32_MAX will
 	**  be returned.
 	*/
-	U32 getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
+	U32Bytes getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
 
 	//get the available memory infomation in KiloBytes.
-	static void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb);
+	static void getAvailableMemoryKB(U32Kibibytes& avail_physical_mem_kb, U32Kibibytes& avail_virtual_mem_kb);
 
 	// Retrieve a map of memory statistics. The keys of the map are platform-
 	// dependent. The values are in kilobytes to try to avoid integer overflow.
-- 
cgit v1.2.3


From 612892b45a3413b16e40c49d3bfde77a4ca927fd Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sun, 18 Aug 2013 22:30:27 -0700
Subject: SH-4433 WIP: Interesting: Statistics > Ping Sim is always 0 ms
 continued conversion to units system made units perform type promotion
 correctly and preserve type in arithmetic e.g. can now do LLVector3 in units
 added typedefs for remaining common unit types, including implicits

---
 indra/llcommon/llcriticaldamp.cpp      |   2 +-
 indra/llcommon/llcriticaldamp.h        |   4 +-
 indra/llcommon/lldate.cpp              |   2 +-
 indra/llcommon/lldate.h                |   2 +-
 indra/llcommon/llframetimer.h          |   4 +-
 indra/llcommon/llmemory.cpp            |  46 +--
 indra/llcommon/llmemory.h              |  18 +-
 indra/llcommon/llprocessor.cpp         |   2 +-
 indra/llcommon/llprocessor.h           |   2 +-
 indra/llcommon/llsys.cpp               |  18 +-
 indra/llcommon/llsys.h                 |   4 +-
 indra/llcommon/lltimer.cpp             |  18 +-
 indra/llcommon/lltimer.h               |  20 +-
 indra/llcommon/lltraceaccumulators.cpp |   2 +-
 indra/llcommon/lltraceaccumulators.h   |  20 +-
 indra/llcommon/lltracerecording.h      |   4 +-
 indra/llcommon/llunit.h                | 727 ++++++++++++++++++++++-----------
 indra/llcommon/tests/llunits_test.cpp  | 126 ++++--
 18 files changed, 659 insertions(+), 362 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llcriticaldamp.cpp b/indra/llcommon/llcriticaldamp.cpp
index 5ffad88973..9f4cb09000 100755
--- a/indra/llcommon/llcriticaldamp.cpp
+++ b/indra/llcommon/llcriticaldamp.cpp
@@ -81,7 +81,7 @@ void LLSmoothInterpolation::updateInterpolants()
 //-----------------------------------------------------------------------------
 // getInterpolant()
 //-----------------------------------------------------------------------------
-F32 LLSmoothInterpolation::getInterpolant(LLUnitImplicit<F32, LLUnits::Seconds> time_constant, bool use_cache)
+F32 LLSmoothInterpolation::getInterpolant(F32SecondsImplicit time_constant, bool use_cache)
 {
 	if (time_constant == 0.f)
 	{
diff --git a/indra/llcommon/llcriticaldamp.h b/indra/llcommon/llcriticaldamp.h
index 7b2a414459..a02a2a0dcf 100755
--- a/indra/llcommon/llcriticaldamp.h
+++ b/indra/llcommon/llcriticaldamp.h
@@ -42,10 +42,10 @@ public:
 	static void updateInterpolants();
 
 	// ACCESSORS
-	static F32 getInterpolant(LLUnitImplicit<F32, LLUnits::Seconds> time_constant, bool use_cache = true);
+	static F32 getInterpolant(F32SecondsImplicit time_constant, bool use_cache = true);
 
 	template<typename T> 
-	static T lerp(T a, T b, LLUnitImplicit<F32, LLUnits::Seconds> time_constant, bool use_cache = true)
+	static T lerp(T a, T b, F32SecondsImplicit 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 cb6f239396..4f2e1304b2 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(LLUnitImplicit<F64, LLUnits::Seconds> seconds_since_epoch) :
+LLDate::LLDate(F64SecondsImplicit seconds_since_epoch) :
 	mSecondsSinceEpoch(seconds_since_epoch.value())
 {}
 
diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h
index 816bc62b14..aecf3b765e 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(LLUnitImplicit<F64, LLUnits::Seconds> seconds_since_epoch);
+	LLDate(F64SecondsImplicit seconds_since_epoch);
 
 	/** 
 	 * @brief Construct a date from a string representation
diff --git a/indra/llcommon/llframetimer.h b/indra/llcommon/llframetimer.h
index d64009440c..81bd5da8a3 100755
--- a/indra/llcommon/llframetimer.h
+++ b/indra/llcommon/llframetimer.h
@@ -43,7 +43,7 @@ public:
 
 	// Return the number of seconds since the start of this
 	// application instance.
-	static F64 getElapsedSeconds()
+	static F64SecondsImplicit getElapsedSeconds()
 	{
 		// Loses msec precision after ~4.5 hours...
 		return sFrameTime;
@@ -52,7 +52,7 @@ public:
 	// Return a low precision usec since epoch
 	static U64 getTotalTime()
 	{
-		return sTotalTime ? LLUnitImplicit<U64, LLUnits::Microseconds>(sTotalTime) : totalTime();
+		return sTotalTime ? U64MicrosecondsImplicit(sTotalTime) : totalTime();
 	}
 
 	// Return a low precision seconds since epoch
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index c59b61471a..d46e205500 100755
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -47,11 +47,11 @@
 
 //static
 char* LLMemory::reserveMem = 0;
-U32Kibibytes LLMemory::sAvailPhysicalMemInKB(U32_MAX);
-U32Kibibytes LLMemory::sMaxPhysicalMemInKB(0);
-U32Kibibytes LLMemory::sAllocatedMemInKB(0);
-U32Kibibytes LLMemory::sAllocatedPageSizeInKB(0);
-U32Kibibytes LLMemory::sMaxHeapSizeInKB(U32_MAX);
+U32Kilobytes LLMemory::sAvailPhysicalMemInKB(U32_MAX);
+U32Kilobytes LLMemory::sMaxPhysicalMemInKB(0);
+U32Kilobytes LLMemory::sAllocatedMemInKB(0);
+U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0);
+U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX);
 BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE;
 
 #if __DEBUG_PRIVATE_MEM__
@@ -94,9 +94,9 @@ void LLMemory::freeReserve()
 }
 
 //static 
-void LLMemory::initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure)
+void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure)
 {
-	sMaxHeapSizeInKB = (U32)(max_heap_size_gb * 1024 * 1024) ;
+	sMaxHeapSizeInKB = max_heap_size;
 	sEnableMemoryFailurePrevention = prevent_heap_failure ;
 }
 
@@ -113,10 +113,10 @@ void LLMemory::updateMemoryInfo()
 		return ;
 	}
 
-	sAllocatedMemInKB = (U32)(counters.WorkingSetSize / 1024) ;
-	sAllocatedPageSizeInKB = (U32)(counters.PagefileUsage / 1024) ;
+	sAllocatedMemInKB = (U32Bytes)(counters.WorkingSetSize) ;
+	sAllocatedPageSizeInKB = (U32Bytes)(counters.PagefileUsage) ;
 
-	U32Kibibytes avail_phys, avail_virtual;
+	U32Kilobytes avail_phys, avail_virtual;
 	LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
 	sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
 
@@ -126,7 +126,7 @@ void LLMemory::updateMemoryInfo()
 	}
 	else
 	{
-		sAvailPhysicalMemInKB = 0 ;
+		sAvailPhysicalMemInKB = U32Kilobytes(0);
 	}
 #else
 	//not valid for other systems for now.
@@ -187,8 +187,8 @@ void LLMemory::logMemoryInfo(BOOL update)
 //static 
 bool LLMemory::isMemoryPoolLow()
 {
-	static const U32 LOW_MEMEOY_POOL_THRESHOLD_KB = 64 * 1024 ; //64 MB for emergency use
-	const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB
+	static const U32Megabytes LOW_MEMORY_POOL_THRESHOLD(64);
+	const static U32Megabytes MAX_SIZE_CHECKED_MEMORY_BLOCK(64);
 	static void* last_reserved_address = NULL ;
 
 	if(!sEnableMemoryFailurePrevention)
@@ -196,32 +196,32 @@ bool LLMemory::isMemoryPoolLow()
 		return false ; //no memory failure prevention.
 	}
 
-	if(sAvailPhysicalMemInKB < (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2)) //out of physical memory
+	if(sAvailPhysicalMemInKB < (LOW_MEMORY_POOL_THRESHOLD / 4)) //out of physical memory
 	{
 		return true ;
 	}
 
-	if(sAllocatedPageSizeInKB + (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2) > sMaxHeapSizeInKB) //out of virtual address space.
+	if(sAllocatedPageSizeInKB + (LOW_MEMORY_POOL_THRESHOLD / 4) > sMaxHeapSizeInKB) //out of virtual address space.
 	{
 		return true ;
 	}
 
-	bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB || 
-		sAllocatedPageSizeInKB + LOW_MEMEOY_POOL_THRESHOLD_KB > sMaxHeapSizeInKB) ;
+	bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMORY_POOL_THRESHOLD || 
+		sAllocatedPageSizeInKB + LOW_MEMORY_POOL_THRESHOLD > sMaxHeapSizeInKB) ;
 
 	//check the virtual address space fragmentation
 	if(!is_low)
 	{
 		if(!last_reserved_address)
 		{
-			last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+			last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
 		}
 		else
 		{
-			last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+			last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
 			if(!last_reserved_address) //failed, try once more
 			{
-				last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+				last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
 			}
 		}
 
@@ -232,19 +232,19 @@ bool LLMemory::isMemoryPoolLow()
 }
 
 //static 
-U32Kibibytes LLMemory::getAvailableMemKB() 
+U32Kilobytes LLMemory::getAvailableMemKB() 
 {
 	return sAvailPhysicalMemInKB ;
 }
 
 //static 
-U32Kibibytes LLMemory::getMaxMemKB() 
+U32Kilobytes LLMemory::getMaxMemKB() 
 {
 	return sMaxPhysicalMemInKB ;
 }
 
 //static 
-U32Kibibytes LLMemory::getAllocatedMemKB() 
+U32Kilobytes LLMemory::getAllocatedMemKB() 
 {
 	return sAllocatedMemInKB ;
 }
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index c45c7ed213..23be1e5b2d 100755
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -166,22 +166,22 @@ public:
 	static U64 getCurrentRSS();
 	static U32 getWorkingSetSize();
 	static void* tryToAlloc(void* address, U32 size);
-	static void initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure);
+	static void initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure);
 	static void updateMemoryInfo() ;
 	static void logMemoryInfo(BOOL update = FALSE);
 	static bool isMemoryPoolLow();
 
-	static U32Kibibytes getAvailableMemKB() ;
-	static U32Kibibytes getMaxMemKB() ;
-	static U32Kibibytes getAllocatedMemKB() ;
+	static U32Kilobytes getAvailableMemKB() ;
+	static U32Kilobytes getMaxMemKB() ;
+	static U32Kilobytes getAllocatedMemKB() ;
 private:
 	static char* reserveMem;
-	static U32Kibibytes sAvailPhysicalMemInKB ;
-	static U32Kibibytes sMaxPhysicalMemInKB ;
-	static U32Kibibytes sAllocatedMemInKB;
-	static U32Kibibytes sAllocatedPageSizeInKB ;
+	static U32Kilobytes sAvailPhysicalMemInKB ;
+	static U32Kilobytes sMaxPhysicalMemInKB ;
+	static U32Kilobytes sAllocatedMemInKB;
+	static U32Kilobytes sAllocatedPageSizeInKB ;
 
-	static U32Kibibytes sMaxHeapSizeInKB;
+	static U32Kilobytes sMaxHeapSizeInKB;
 	static BOOL sEnableMemoryFailurePrevention;
 };
 
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index 80b86153e4..69043dc173 100755
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -875,7 +875,7 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL)
 
 
 LLProcessorInfo::~LLProcessorInfo() {}
-LLUnitImplicit<F64, LLUnits::Megahertz> LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); }
+F64MegahertzImplicit 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 7f220467b0..4956a39700 100755
--- a/indra/llcommon/llprocessor.h
+++ b/indra/llcommon/llprocessor.h
@@ -37,7 +37,7 @@ public:
 	LLProcessorInfo(); 
  	~LLProcessorInfo();
 
-	LLUnitImplicit<F64, LLUnits::Megahertz> getCPUFrequency() const;
+	F64MegahertzImplicit getCPUFrequency() const;
 	bool hasSSE() const;
 	bool hasSSE2() const;
 	bool hasAltivec() const;
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 8f7e60fb68..1ff45d3d90 100755
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -832,7 +832,7 @@ LLMemoryInfo::LLMemoryInfo()
 }
 
 #if LL_WINDOWS
-static U32Kibibytes LLMemoryAdjustKBResult(U32Kibibytes inKB)
+static U32Kilobytes LLMemoryAdjustKBResult(U32Kilobytes inKB)
 {
 	// Moved this here from llfloaterabout.cpp
 
@@ -843,16 +843,16 @@ static U32Kibibytes LLMemoryAdjustKBResult(U32Kibibytes inKB)
 	// returned from the GetMemoryStatusEx function.  Here we keep the
 	// original adjustment from llfoaterabout.cpp until this can be
 	// fixed somehow.
-	inKB += U32Mibibytes(1);
+	inKB += U32Megabytes(1);
 
 	return inKB;
 }
 #endif
 
-U32Kibibytes LLMemoryInfo::getPhysicalMemoryKB() const
+U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
 {
 #if LL_WINDOWS
-	return LLMemoryAdjustKBResult(U32Kibibytes(mStatsMap["Total Physical KB"].asInteger()));
+	return LLMemoryAdjustKBResult(U32Kilobytes(mStatsMap["Total Physical KB"].asInteger()));
 
 #elif LL_DARWIN
 	// This might work on Linux as well.  Someone check...
@@ -885,8 +885,8 @@ U32Bytes LLMemoryInfo::getPhysicalMemoryClamped() const
 	// Return the total physical memory in bytes, but clamp it
 	// to no more than U32_MAX
 	
-	U32Bytes phys_kb = getPhysicalMemoryKB();
-	if (phys_kb >= 4194304 /* 4GB in KB */)
+	U32Kilobytes phys_kb = getPhysicalMemoryKB();
+	if (phys_kb >= U32Gigabytes(4))
 	{
 		return U32Bytes(U32_MAX);
 	}
@@ -897,15 +897,15 @@ U32Bytes LLMemoryInfo::getPhysicalMemoryClamped() const
 }
 
 //static
-void LLMemoryInfo::getAvailableMemoryKB(U32Kibibytes& avail_physical_mem_kb, U32Kibibytes& avail_virtual_mem_kb)
+void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb)
 {
 #if LL_WINDOWS
 	// Sigh, this shouldn't be a static method, then we wouldn't have to
 	// reload this data separately from refresh()
 	LLSD statsMap(loadStatsMap());
 
-	avail_physical_mem_kb = statsMap["Avail Physical KB"].asInteger();
-	avail_virtual_mem_kb  = statsMap["Avail Virtual KB"].asInteger();
+	avail_physical_mem_kb = (U32Kilobytes)statsMap["Avail Physical KB"].asInteger();
+	avail_virtual_mem_kb  = (U32Kilobytes)statsMap["Avail Virtual KB"].asInteger();
 
 #elif LL_DARWIN
 	// mStatsMap is derived from vm_stat, look for (e.g.) "kb free":
diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h
index ad4f243d05..962367f69f 100755
--- a/indra/llcommon/llsys.h
+++ b/indra/llcommon/llsys.h
@@ -112,7 +112,7 @@ public:
 	LLMemoryInfo(); ///< Default constructor
 	void stream(std::ostream& s) const;	///< output text info to s
 
-	U32Kibibytes getPhysicalMemoryKB() const; 
+	U32Kilobytes getPhysicalMemoryKB() const; 
 	
 	/*! Memory size in bytes, if total memory is >= 4GB then U32_MAX will
 	**  be returned.
@@ -120,7 +120,7 @@ public:
 	U32Bytes getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
 
 	//get the available memory infomation in KiloBytes.
-	static void getAvailableMemoryKB(U32Kibibytes& avail_physical_mem_kb, U32Kibibytes& avail_virtual_mem_kb);
+	static void getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb);
 
 	// Retrieve a map of memory statistics. The keys of the map are platform-
 	// dependent. The values are in kilobytes to try to avoid integer overflow.
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 74f3a7f587..da9d2b646c 100755
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -225,7 +225,7 @@ void update_clock_frequencies()
 
 // returns a U64 number that represents the number of 
 // microseconds since the unix epoch - Jan 1, 1970
-LLUnitImplicit<U64, LLUnits::Microseconds> totalTime()
+U64MicrosecondsImplicit totalTime()
 {
 	U64 current_clock_count = get_clock_count();
 	if (!gTotalTimeClockCount)
@@ -295,14 +295,14 @@ void LLTimer::cleanupClass()
 }
 
 // static
-LLUnitImplicit<U64, LLUnits::Microseconds> LLTimer::getTotalTime()
+U64MicrosecondsImplicit LLTimer::getTotalTime()
 {
 	// simply call into the implementation function.
 	return totalTime();
 }	
 
 // static
-LLUnitImplicit<F64, LLUnits::Seconds> LLTimer::getTotalSeconds()
+F64SecondsImplicit LLTimer::getTotalSeconds()
 {
 	return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64;
 }
@@ -351,36 +351,36 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount)
 }
 
 
-LLUnitImplicit<F64, LLUnits::Seconds> LLTimer::getElapsedTimeF64() const
+F64SecondsImplicit LLTimer::getElapsedTimeF64() const
 {
 	U64 last = mLastClockCount;
 	return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv;
 }
 
-LLUnitImplicit<F32, LLUnits::Seconds> LLTimer::getElapsedTimeF32() const
+F32SecondsImplicit LLTimer::getElapsedTimeF32() const
 {
 	return (F32)getElapsedTimeF64();
 }
 
-LLUnitImplicit<F64, LLUnits::Seconds> LLTimer::getElapsedTimeAndResetF64()
+F64SecondsImplicit LLTimer::getElapsedTimeAndResetF64()
 {
 	return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv;
 }
 
-LLUnitImplicit<F32, LLUnits::Seconds> LLTimer::getElapsedTimeAndResetF32()
+F32SecondsImplicit LLTimer::getElapsedTimeAndResetF32()
 {
 	return (F32)getElapsedTimeAndResetF64();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
-void  LLTimer::setTimerExpirySec(LLUnitImplicit<F32, LLUnits::Seconds> expiration)
+void  LLTimer::setTimerExpirySec(F32SecondsImplicit expiration)
 {
 	mExpirationTicks = get_clock_count()
 		+ (U64)((F32)(expiration * gClockFrequency));
 }
 
-LLUnitImplicit<F32, LLUnits::Seconds> LLTimer::getRemainingTimeF32() const
+F32SecondsImplicit 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 1f2c56432b..12a453e897 100755
--- a/indra/llcommon/lltimer.h
+++ b/indra/llcommon/lltimer.h
@@ -67,7 +67,7 @@ public:
 
 	// Return a high precision number of seconds since the start of
 	// this application instance.
-	static LLUnitImplicit<F64, LLUnits::Seconds> getElapsedSeconds()
+	static F64SecondsImplicit getElapsedSeconds()
 	{
 		if (sTimer) 
 		{
@@ -80,10 +80,10 @@ public:
 	}
 
 	// Return a high precision usec since epoch
-	static LLUnitImplicit<U64, LLUnits::Microseconds> getTotalTime();
+	static U64MicrosecondsImplicit getTotalTime();
 
 	// Return a high precision seconds since epoch
-	static LLUnitImplicit<F64, LLUnits::Seconds> getTotalSeconds();
+	static F64SecondsImplicit getTotalSeconds();
 
 
 	// MANIPULATORS
@@ -91,19 +91,19 @@ public:
 	void stop() { mStarted = FALSE; }
 	void reset();								// Resets the timer
 	void setLastClockCount(U64 current_count);		// Sets the timer so that the next elapsed call will be relative to this time
-	void setTimerExpirySec(LLUnitImplicit<F32, LLUnits::Seconds> expiration);
+	void setTimerExpirySec(F32SecondsImplicit expiration);
 	BOOL checkExpirationAndReset(F32 expiration);
 	BOOL hasExpired() const;
-	LLUnitImplicit<F32, LLUnits::Seconds> getElapsedTimeAndResetF32();	// Returns elapsed time in seconds with reset
-	LLUnitImplicit<F64, LLUnits::Seconds> getElapsedTimeAndResetF64();
+	F32SecondsImplicit getElapsedTimeAndResetF32();	// Returns elapsed time in seconds with reset
+	F64SecondsImplicit getElapsedTimeAndResetF64();
 
-	LLUnitImplicit<F32, LLUnits::Seconds> getRemainingTimeF32() const;
+	F32SecondsImplicit getRemainingTimeF32() const;
 
 	static BOOL knownBadTimer();
 
 	// ACCESSORS
-	LLUnitImplicit<F32, LLUnits::Seconds> getElapsedTimeF32() const;			// Returns elapsed time in seconds
-	LLUnitImplicit<F64, LLUnits::Seconds> getElapsedTimeF64() const;			// Returns elapsed time in seconds
+	F32SecondsImplicit getElapsedTimeF32() const;			// Returns elapsed time in seconds
+	F64SecondsImplicit getElapsedTimeF64() const;			// Returns elapsed time in seconds
 
 	bool getStarted() const { return mStarted; }
 
@@ -171,6 +171,6 @@ LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_dayli
 LL_COMMON_API void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);
 LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstring);
 
-LLUnitImplicit<U64, LLUnits::Microseconds> LL_COMMON_API totalTime();					// Returns current system time in microseconds
+U64MicrosecondsImplicit LL_COMMON_API totalTime();					// Returns current system time in microseconds
 
 #endif
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index a632f5634c..1fb68c8158 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -114,7 +114,7 @@ void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other)
 
 void AccumulatorBufferGroup::sync()
 {
-	LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds();
+	F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds();
 
 	mSamples.sync(time_stamp);
 	mMemStats.sync(time_stamp);
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 73da6bd2d8..f9d223066d 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -118,7 +118,7 @@ namespace LLTrace
 			}
 		}
 
-		void sync(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
+		void sync(F64SecondsImplicit time_stamp)
 		{
 			llassert(mStorageSize >= sNextStorageSlot);
 			for (size_t i = 0; i < sNextStorageSlot; i++)
@@ -260,7 +260,7 @@ namespace LLTrace
 
 		void addSamples(const EventAccumulator& other, EBufferAppendType append_type);
 		void reset(const EventAccumulator* other);
-		void sync(LLUnitImplicit<F64, LLUnits::Seconds>) {}
+		void sync(F64SecondsImplicit) {}
 
 		F64	getSum() const               { return mSum; }
 		F64	getMin() const               { return mMin; }
@@ -305,7 +305,7 @@ namespace LLTrace
 
 		void sample(F64 value)
 		{
-			LLUnitImplicit<F64, LLUnits::Seconds> time_stamp = LLTimer::getTotalSeconds();
+			F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds();
 
 			// store effect of last value
 			sync(time_stamp);
@@ -332,11 +332,11 @@ namespace LLTrace
 		void addSamples(const SampleAccumulator& other, EBufferAppendType append_type);
 		void reset(const SampleAccumulator* other);
 
-		void sync(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp)
+		void sync(F64SecondsImplicit time_stamp)
 		{
 			if (mHasValue)
 			{
-				LLUnitImplicit<F64, LLUnits::Seconds> delta_time = time_stamp - mLastSampleTimeStamp;
+				F64SecondsImplicit delta_time = time_stamp - mLastSampleTimeStamp;
 				mSum += mLastValue * delta_time;
 				mTotalSamplingTime += delta_time;
 				F64 old_mean = mMean;
@@ -353,7 +353,7 @@ namespace LLTrace
 		F64	getMean() const              { return mMean; }
 		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); }
 		F64 getSumOfSquares() const		 { return mSumOfSquares; }
-		LLUnitImplicit<F64, LLUnits::Seconds> getSamplingTime() { return mTotalSamplingTime; }
+		F64SecondsImplicit getSamplingTime() { return mTotalSamplingTime; }
 		U32 getSampleCount() const       { return mNumSamples; }
 		bool hasValue() const            { return mHasValue; }
 
@@ -368,7 +368,7 @@ namespace LLTrace
 		F64		mMean,
 				mSumOfSquares;
 
-		LLUnitImplicit<F64, LLUnits::Seconds>	
+		F64SecondsImplicit	
 				mLastSampleTimeStamp,
 				mTotalSamplingTime;
 
@@ -403,7 +403,7 @@ namespace LLTrace
 			mSum = 0;
 		}
 
-		void sync(LLUnitImplicit<F64, LLUnits::Seconds>) {}
+		void sync(F64SecondsImplicit) {}
 
 		F64	getSum() const { return mSum; }
 
@@ -435,7 +435,7 @@ namespace LLTrace
 		TimeBlockAccumulator();
 		void addSamples(const self_t& other, EBufferAppendType append_type);
 		void reset(const self_t* other);
-		void sync(LLUnitImplicit<F64, LLUnits::Seconds>) {}
+		void sync(F64SecondsImplicit) {}
 
 		//
 		// members
@@ -516,7 +516,7 @@ namespace LLTrace
 			mDeallocatedCount = 0;
 		}
 
-		void sync(LLUnitImplicit<F64, LLUnits::Seconds> time_stamp) 
+		void sync(F64SecondsImplicit time_stamp) 
 		{
 			mSize.sync(time_stamp);
 			mChildSize.sync(time_stamp);
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index f5fb2bf561..ea090e6ee1 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -490,7 +490,7 @@ namespace LLTrace
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				Recording& recording = getPrevRecording(i);
-				if (recording.getDuration() > 0.f)
+				if (recording.getDuration() > (F32Seconds)0.f)
 				{
 					mean += recording.getSum(stat);
 				}
@@ -530,7 +530,7 @@ namespace LLTrace
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				Recording& recording = getPrevRecording(i);
-				if (recording.getDuration() > 0.f)
+				if (recording.getDuration() > (F32Seconds)0.f)
 				{
 					mean += recording.getPerSec(stat);
 				}
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index b62bebc440..c49c882f23 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -31,11 +31,29 @@
 #include "llpreprocessor.h"
 #include "llerror.h"
 
+//lightweight replacement of type traits for simple type equality check
+template<typename S, typename T> 
+struct LLIsSameType
+{
+	static const bool value = false;
+};
+
+template<typename T>
+struct LLIsSameType<T, T>
+{
+	static const bool value = true;
+};
+
+template<typename S, typename T>
+struct LLPromotedType
+{
+	typedef decltype(S() + T()) type_t;
+};
+
 template<typename STORAGE_TYPE, typename UNIT_TYPE>
 struct LLUnit
 {
 	typedef LLUnit<STORAGE_TYPE, UNIT_TYPE> self_t;
-
 	typedef STORAGE_TYPE storage_t;
 
 	// value initialization
@@ -49,18 +67,6 @@ struct LLUnit
 	:	mValue(convert(other).mValue)
 	{}
 	
-	bool operator == (const self_t& other)
-	{
-		return mValue = other.mValue;
-	}
-
-	// value assignment
-	self_t& operator = (storage_t value)
-	{
-		mValue = value;
-		return *this;
-	}
-
 	// unit assignment
 	template<typename OTHER_STORAGE, typename OTHER_UNIT>
 	self_t& operator = (LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
@@ -91,22 +97,12 @@ struct LLUnit
 		*this = LLUnit<storage_t, NEW_UNIT_TYPE>(value);
 	}
 
-	void operator += (storage_t value)
-	{
-		mValue += value;
-	}
-
 	template<typename OTHER_STORAGE, typename OTHER_UNIT>
 	void operator += (LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
 	{
 		mValue += convert(other).mValue;
 	}
 
-	void operator -= (storage_t value)
-	{
-		mValue -= value;
-	}
-
 	template<typename OTHER_STORAGE, typename OTHER_UNIT>
 	void operator -= (LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
 	{
@@ -161,7 +157,7 @@ std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit
 {
         STORAGE_TYPE val;
         s >> val;
-        unit = val;
+        unit.value(val);
         return s;
 }
 
@@ -181,12 +177,37 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
 	:	base_t(convert(other))
 	{}
 
-	// unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD scalar (F32, S32, etc)
+	// unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc)
 	// this allows for interoperability with legacy code
 	operator storage_t() const
 	{
 		return base_t::value();
 	}
+
+	using base_t::operator +=;
+	void operator += (storage_t value)
+	{
+		mValue += value;
+	}
+
+	template<typename OTHER_STORAGE, typename OTHER_UNIT>
+	void operator += (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
+	{
+		mValue += convert(other).value();
+	}
+
+	using base_t::operator -=;
+	void operator -= (storage_t value)
+	{
+		mValue -= value;
+	}
+
+	template<typename OTHER_STORAGE, typename OTHER_UNIT>
+	void operator -= (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
+	{
+		mValue -= convert(other).value();
+	}
+
 };
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE>
@@ -205,24 +226,12 @@ std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNIT_TYP
         return s;
 }
 
-template<typename S, typename T> 
-struct LLIsSameType
-{
-	static const bool value = false;
-};
-
-template<typename T>
-struct LLIsSameType<T, T>
-{
-	static const bool value = true;
-};
-
 template<typename S1, typename T1, typename S2, typename T2>
 LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ...)
 {
 	LL_STATIC_ASSERT((LLIsSameType<T1, T2>::value 
 		|| !LLIsSameType<T1, typename T1::base_unit_t>::value 
-		|| !LLIsSameType<T2, typename T2::base_unit_t>::value), "invalid conversion");
+		|| !LLIsSameType<T2, typename T2::base_unit_t>::value), "invalid conversion: incompatible units");
 
 	if (LLIsSameType<T1, typename T1::base_unit_t>::value)
 	{
@@ -253,65 +262,63 @@ LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ..
 // operator +
 //
 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<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnit<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	LLUnit<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result += second;
 	return result;
 }
 
-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)
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS second)
 {
-	LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first);
-	result += second;
-	return result;
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "operator + requires compatible unit types");
+	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
 }
 
-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)
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (UNITLESS first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first);
-	result += second;
-	return result;
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "operator + requires compatible unit types");
+	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
 }
 
 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<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	LLUnitImplicit<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result += second;
 	return result;
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	LLUnitImplicit<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result += second;
 	return result;
 }
 
 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<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	LLUnitImplicit<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result += LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
 	return result;
 }
 
-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)
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnitImplicit<decltype(STORAGE_TYPE() + UNITLESS_TYPE()), UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> result(first);
+	LLUnitImplicit<decltype(STORAGE_TYPE() + UNITLESS_TYPE()), UNIT_TYPE> result(first);
 	result += second;
 	return result;
 }
 
-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)
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnitImplicit<decltype(UNITLESS_TYPE() + STORAGE_TYPE()), UNIT_TYPE> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> result(first);
+	LLUnitImplicit<decltype(UNITLESS_TYPE() + STORAGE_TYPE()), UNIT_TYPE> result(first);
 	result += second;
 	return result;
 }
@@ -320,65 +327,63 @@ LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> operator + (SCALAR_TYPE first, LLUnitImp
 // operator -
 //
 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<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnit<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	LLUnit<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result -= second;
 	return result;
 }
 
-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)
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS second)
 {
-	LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first);
-	result -= second;
-	return result;
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "operator - requires compatible unit types");
+	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
 }
 
-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)
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (UNITLESS first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	LLUnit<STORAGE_TYPE, UNIT_TYPE> result(first);
-	result -= second;
-	return result;
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "operator - requires compatible unit types");
+	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
 }
 
 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<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	LLUnitImplicit<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result -= second;
 	return result;
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	LLUnitImplicit<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result -= second;
 	return result;
 }
 
 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<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> result(first);
+	LLUnitImplicit<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result -= LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
 	return result;
 }
 
-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)
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnitImplicit<decltype(STORAGE_TYPE() - UNITLESS_TYPE()), UNIT_TYPE> operator - (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> result(first);
+	LLUnitImplicit<decltype(STORAGE_TYPE() - UNITLESS_TYPE()), UNIT_TYPE> result(first);
 	result -= second;
 	return result;
 }
 
-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)
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnitImplicit<decltype(UNITLESS_TYPE() - STORAGE_TYPE()), UNIT_TYPE> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> result(first);
+	LLUnitImplicit<decltype(UNITLESS_TYPE() - STORAGE_TYPE()), UNIT_TYPE> result(first);
 	result -= second;
 	return result;
 }
@@ -390,119 +395,144 @@ template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, ty
 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
-	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "Multiplication of unit types results in new unit type - not supported.");
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
 	return LLUnit<STORAGE_TYPE1, UNIT_TYPE1>();
 }
 
-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)
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnit<decltype(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first.value() * second));
+	return LLUnit<decltype(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE>(first.value() * 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)
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnit<decltype(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first * second.value()));
+	return LLUnit<decltype(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE>(first * second.value());
 }
 
 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
-	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "Multiplication of unit types results in new unit type - not supported.");
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
 	return LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>();
 }
 
-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)
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnitImplicit<decltype(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE> operator * (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>(first.value() * second);
+	return LLUnitImplicit<decltype(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE>(first.value() * 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)
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnitImplicit<decltype(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	return LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>(first * second.value());
+	return LLUnitImplicit<decltype(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE>(first * second.value());
 }
 
 
 //
 // operator /
 //
-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 STORAGE_TYPE, typename UNIT_TYPE, typename SCALAR_TYPE>
-LLUnit<STORAGE_TYPE, UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, SCALAR_TYPE second)
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnit<decltype(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first.value() / second));
+	return LLUnit<decltype(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE>(first.value() / 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)
+decltype(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	return STORAGE_TYPE1(first.value() / first.convert(second));
+	return first.value() / first.convert(second).value();
 }
 
-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)
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnitImplicit<decltype(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE> operator / (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>((STORAGE_TYPE)(first.value() / second));
+	return LLUnitImplicit<decltype(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE>(first.value() / 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)
+decltype(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	return STORAGE_TYPE1(first.value() / first.convert(second));
+	return (decltype(STORAGE_TYPE1() / STORAGE_TYPE2()))(first.value() / first.convert(second).value());
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-STORAGE_TYPE1 operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+decltype(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	return STORAGE_TYPE1(first.value() / first.convert(second));
+	return (decltype(STORAGE_TYPE1() / STORAGE_TYPE2()))(first.value() / first.convert(second).value());
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-STORAGE_TYPE1 operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
-{
-	return STORAGE_TYPE1(first.value() / first.convert(second));
-}
-
-#define COMPARISON_OPERATORS(op)                                                                                     \
-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 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 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 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);                                                                   \
-}
-
-COMPARISON_OPERATORS(<)
-COMPARISON_OPERATORS(<=)
-COMPARISON_OPERATORS(>)
-COMPARISON_OPERATORS(>=)
-COMPARISON_OPERATORS(==)
-COMPARISON_OPERATORS(!=)
+decltype(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	return (decltype(STORAGE_TYPE1() / STORAGE_TYPE2()))(first.value() / first.convert(second).value());
+}
+
+//
+// comparison operators
+//
+
+#define LL_UNIT_DECLARE_COMPARISON_OPERATOR(op)                                                                            \
+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).value();                                                                 \
+}                                                                                                                          \
+	                                                                                                                       \
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
+bool operator op (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)                                     \
+{                                                                                                                          \
+	return first.value() op second;                                                                                        \
+}                                                                                                                          \
+                                                                                                                           \
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
+bool operator op (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)                                     \
+{                                                                                                                          \
+	return first op second.value();                                                                                        \
+}                                                                                                                          \
+                                                                                                                           \
+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).value();                                                                 \
+}                                                                                                                          \
+                                                                                                                           \
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
+bool operator op (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)                                             \
+{                                                                                                                          \
+	LL_BAD_TEMPLATE_INSTANTIATION(UNITLESS_TYPE, "operator " #op " requires compatible unit types");                       \
+	return false;                                                                                                          \
+}                                                                                                                          \
+                                                                                                                           \
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
+bool operator op (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)                                             \
+{                                                                                                                          \
+	LL_BAD_TEMPLATE_INSTANTIATION(UNITLESS_TYPE, "operator " #op " requires compatible unit types");                       \
+	return false;                                                                                                          \
+}                                                                                                                          \
+	                                                                                                                       \
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \
+bool operator op (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)               \
+{                                                                                                                          \
+	return first.value() op first.convert(second).value();                                                                 \
+}                                                                                                                          \
+                                                                                                                           \
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \
+bool operator op (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)               \
+{                                                                                                                          \
+	return first.value() op first.convert(second).value();                                                                 \
+}
+
+LL_UNIT_DECLARE_COMPARISON_OPERATOR(<);
+LL_UNIT_DECLARE_COMPARISON_OPERATOR(<=);
+LL_UNIT_DECLARE_COMPARISON_OPERATOR(>);
+LL_UNIT_DECLARE_COMPARISON_OPERATOR(>=);
+LL_UNIT_DECLARE_COMPARISON_OPERATOR(==);
+LL_UNIT_DECLARE_COMPARISON_OPERATOR(!=);
 
 
 template<typename T> 
@@ -517,8 +547,6 @@ struct LLGetUnitLabel<LLUnit<STORAGE_T, T> >
 	static const char* getUnitLabel() { return T::getUnitLabel(); }
 };
 
-#define LL_UNIT_PROMOTE_VALUE(output_type, value) ((true ? (output_type)(1) : (value/value)) * value)
-
 template<typename INPUT_TYPE, typename OUTPUT_TYPE>
 struct LLUnitLinearOps
 {
@@ -534,25 +562,25 @@ struct LLUnitLinearOps
 	template<typename T>
 	output_t operator * (T other)
 	{
-		return mInput * other;
+		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) * other;
 	}
 
 	template<typename T>
 	output_t operator / (T other)
 	{
-		return LL_UNIT_PROMOTE_VALUE(OUTPUT_TYPE, mInput) / other;
+		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) / other;
 	}
 
 	template<typename T>
 	output_t operator + (T other)
 	{
-		return mInput + other;
+		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) + other;
 	}
 
 	template<typename T>
 	output_t operator - (T other)
 	{
-		return mInput - other;
+		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) - other;
 	}
 };
 
@@ -571,25 +599,25 @@ struct LLUnitInverseLinearOps
 	template<typename T>
 	output_t operator * (T other)
 	{
-		return LL_UNIT_PROMOTE_VALUE(OUTPUT_TYPE, mInput) / other;
+		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) / other;
 	}
 
 	template<typename T>
 	output_t operator / (T other)
 	{
-		return mInput * other;
+		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) * other;
 	}
 
 	template<typename T>
 	output_t operator + (T other)
 	{
-		return mInput - other;
+		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) - other;
 	}
 
 	template<typename T>
 	output_t operator - (T other)
 	{
-		return mInput + other;
+		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) + other;
 	}
 };
 
@@ -621,13 +649,13 @@ struct unit_name
 template<typename S1, typename S2>                                                                      \
 void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)                        \
 {                                                                                                       \
-	out = LLUnit<S2, base_unit_name>((S2)(LLUnitLinearOps<S1, S2>(in.value()) conversion_operation));		\
+	out = LLUnit<S2, base_unit_name>((S2)(LLUnitLinearOps<S1, S2>(in.value()) conversion_operation));	\
 }                                                                                                       \
                                                                                                         \
 template<typename S1, typename S2>                                                                      \
 void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)                        \
 {                                                                                                       \
-	out = LLUnit<S2, unit_name>((S2)(LLUnitInverseLinearOps<S1, S2>(in.value()) conversion_operation));     \
+	out = LLUnit<S2, unit_name>((S2)(LLUnitInverseLinearOps<S1, S2>(in.value()) conversion_operation)); \
 }                                                                                               
 
 //
@@ -637,120 +665,140 @@ void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)
 namespace LLUnits
 {
 LL_DECLARE_BASE_UNIT(Bytes, "B");
-LL_DECLARE_DERIVED_UNIT(Bytes, * 1000,			Kilobytes, "KB");
-LL_DECLARE_DERIVED_UNIT(Kilobytes, * 1000,		Megabytes, "MB");
-LL_DECLARE_DERIVED_UNIT(Megabytes, * 1000,		Gigabytes, "GB");
-LL_DECLARE_DERIVED_UNIT(Bytes, * 1024,			Kibibytes, "KiB");
-LL_DECLARE_DERIVED_UNIT(Kibibytes, * 1024,		Mibibytes, "MiB");
-LL_DECLARE_DERIVED_UNIT(Mibibytes, * 1024,		Gibibytes, "GiB");
+// technically, these are kibibytes, mibibytes, etc. but we should stick with commonly accepted terminology
+LL_DECLARE_DERIVED_UNIT(Bytes, * 1024,			Kilobytes, "KB");
+LL_DECLARE_DERIVED_UNIT(Kilobytes, * 1024,		Megabytes, "MB");
+LL_DECLARE_DERIVED_UNIT(Megabytes, * 1024,		Gigabytes, "GB");
 }
 
 typedef LLUnit<F32, LLUnits::Bytes>     F32Bytes;
 typedef LLUnit<F32, LLUnits::Kilobytes> F32Kilobytes;
 typedef LLUnit<F32, LLUnits::Megabytes> F32Megabytes;
 typedef LLUnit<F32, LLUnits::Gigabytes> F32Gigabytes;
-typedef LLUnit<F32, LLUnits::Kibibytes> F32Kibibytes;
-typedef LLUnit<F32, LLUnits::Mibibytes> F32Mibibytes;
-typedef LLUnit<F32, LLUnits::Gibibytes> F32Gibibytes;
+
+typedef LLUnitImplicit<F32, LLUnits::Bytes>     F32BytesImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Kilobytes> F32KilobytesImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Megabytes> F32MegabytesImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Gigabytes> F32GigabytesImplicit;
 
 typedef LLUnit<F64, LLUnits::Bytes>     F64Bytes;
 typedef LLUnit<F64, LLUnits::Kilobytes> F64Kilobytes;
 typedef LLUnit<F64, LLUnits::Megabytes> F64Megabytes;
 typedef LLUnit<F64, LLUnits::Gigabytes> F64Gigabytes;
-typedef LLUnit<F64, LLUnits::Kibibytes> F64Kibibytes;
-typedef LLUnit<F64, LLUnits::Mibibytes> F64Mibibytes;
-typedef LLUnit<F64, LLUnits::Gibibytes> F64Gibibytes;
+
+typedef LLUnitImplicit<F64, LLUnits::Bytes>     F64BytesImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Kilobytes> F64KilobytesImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Megabytes> F64MegabytesImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Gigabytes> F64GigabytesImplicit;
 
 typedef LLUnit<S32, LLUnits::Bytes>     S32Bytes;
 typedef LLUnit<S32, LLUnits::Kilobytes> S32Kilobytes;
 typedef LLUnit<S32, LLUnits::Megabytes> S32Megabytes;
 typedef LLUnit<S32, LLUnits::Gigabytes> S32Gigabytes;
-typedef LLUnit<S32, LLUnits::Kibibytes> S32Kibibytes;
-typedef LLUnit<S32, LLUnits::Mibibytes> S32Mibibytes;
-typedef LLUnit<S32, LLUnits::Gibibytes> S32Gibibytes;
 
-typedef LLUnit<U32, LLUnits::Bytes>     U32Bytes;
-typedef LLUnit<U32, LLUnits::Kilobytes> U32Kilobytes;
-typedef LLUnit<U32, LLUnits::Megabytes> U32Megabytes;
-typedef LLUnit<U32, LLUnits::Gigabytes> U32Gigabytes;
-typedef LLUnit<U32, LLUnits::Kibibytes> U32Kibibytes;
-typedef LLUnit<U32, LLUnits::Mibibytes> U32Mibibytes;
-typedef LLUnit<U32, LLUnits::Gibibytes> U32Gibibytes;
+typedef LLUnitImplicit<S32, LLUnits::Bytes>     S32BytesImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Kilobytes> S32KilobytesImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Megabytes> S32MegabytesImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Gigabytes> S32GigabytesImplicit;
 
 typedef LLUnit<S64, LLUnits::Bytes>     S64Bytes;
 typedef LLUnit<S64, LLUnits::Kilobytes> S64Kilobytes;
 typedef LLUnit<S64, LLUnits::Megabytes> S64Megabytes;
 typedef LLUnit<S64, LLUnits::Gigabytes> S64Gigabytes;
-typedef LLUnit<S64, LLUnits::Kibibytes> S64Kibibytes;
-typedef LLUnit<S64, LLUnits::Mibibytes> S64Mibibytes;
-typedef LLUnit<S64, LLUnits::Gibibytes> S64Gibibytes;
+
+typedef LLUnitImplicit<S64, LLUnits::Bytes>     S64BytesImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Kilobytes> S64KilobytesImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Megabytes> S64MegabytesImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Gigabytes> S64GigabytesImplicit;
+
+typedef LLUnit<U32, LLUnits::Bytes>     U32Bytes;
+typedef LLUnit<U32, LLUnits::Kilobytes> U32Kilobytes;
+typedef LLUnit<U32, LLUnits::Megabytes> U32Megabytes;
+typedef LLUnit<U32, LLUnits::Gigabytes> U32Gigabytes;
+
+typedef LLUnitImplicit<U32, LLUnits::Bytes>     U32BytesImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Kilobytes> U32KilobytesImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Megabytes> U32MegabytesImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Gigabytes> U32GigabytesImplicit;
 
 typedef LLUnit<U64, LLUnits::Bytes>     U64Bytes;
 typedef LLUnit<U64, LLUnits::Kilobytes> U64Kilobytes;
 typedef LLUnit<U64, LLUnits::Megabytes> U64Megabytes;
 typedef LLUnit<U64, LLUnits::Gigabytes> U64Gigabytes;
-typedef LLUnit<U64, LLUnits::Kibibytes> U64Kibibytes;
-typedef LLUnit<U64, LLUnits::Mibibytes> U64Mibibytes;
-typedef LLUnit<U64, LLUnits::Gibibytes> U64Gibibytes;
+
+typedef LLUnitImplicit<U64, LLUnits::Bytes>     U64BytesImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Kilobytes> U64KilobytesImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Megabytes> U64MegabytesImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Gigabytes> U64GigabytesImplicit;
 
 namespace LLUnits
 {
+// technically, these are kibibits, mibibits, etc. but we should stick with commonly accepted terminology
 LL_DECLARE_DERIVED_UNIT(Bytes, / 8,				Bits, "b");
-LL_DECLARE_DERIVED_UNIT(Bits, * 1000,			Kilobits, "Kb");
-LL_DECLARE_DERIVED_UNIT(Kilobits, * 1000,		Megabits, "Mb");
-LL_DECLARE_DERIVED_UNIT(Megabits, * 1000,		Gigabits, "Gb");
-LL_DECLARE_DERIVED_UNIT(Bits, * 1024,			Kibibits, "Kib");
-LL_DECLARE_DERIVED_UNIT(Kibibits, * 1024,		Mibibits, "Mib");  
-LL_DECLARE_DERIVED_UNIT(Mibibits, * 1024,		Gibibits, "Gib");
+LL_DECLARE_DERIVED_UNIT(Bits, * 1024,			Kilobits, "Kb");
+LL_DECLARE_DERIVED_UNIT(Kilobits, * 1024,		Megabits, "Mb");  
+LL_DECLARE_DERIVED_UNIT(Megabits, * 1024,		Gigabits, "Gb");
 }
 
 typedef LLUnit<F32, LLUnits::Bits>     F32Bits;
 typedef LLUnit<F32, LLUnits::Kilobits> F32Kilobits;
 typedef LLUnit<F32, LLUnits::Megabits> F32Megabits;
 typedef LLUnit<F32, LLUnits::Gigabits> F32Gigabits;
-typedef LLUnit<F32, LLUnits::Kibibits> F32Kibibits;
-typedef LLUnit<F32, LLUnits::Mibibits> F32Mibibits;
-typedef LLUnit<F32, LLUnits::Gibibits> F32Gibibits;
-					
+
+typedef LLUnitImplicit<F32, LLUnits::Bits>     F32BitsImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Kilobits> F32KilobitsImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Megabits> F32MegabitsImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Gigabits> F32GigabitsImplicit;
+
 typedef LLUnit<F64, LLUnits::Bits>     F64Bits;
 typedef LLUnit<F64, LLUnits::Kilobits> F64Kilobits;
 typedef LLUnit<F64, LLUnits::Megabits> F64Megabits;
 typedef LLUnit<F64, LLUnits::Gigabits> F64Gigabits;
-typedef LLUnit<F64, LLUnits::Kibibits> F64Kibibits;
-typedef LLUnit<F64, LLUnits::Mibibits> F64Mibibits;
-typedef LLUnit<F64, LLUnits::Gibibits> F64Gibibits;
+
+typedef LLUnitImplicit<F64, LLUnits::Bits>     F64BitsImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Kilobits> F64KilobitsImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Megabits> F64MegabitsImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Gigabits> F64GigabitsImplicit;
 
 typedef LLUnit<S32, LLUnits::Bits>     S32Bits;
 typedef LLUnit<S32, LLUnits::Kilobits> S32Kilobits;
 typedef LLUnit<S32, LLUnits::Megabits> S32Megabits;
 typedef LLUnit<S32, LLUnits::Gigabits> S32Gigabits;
-typedef LLUnit<S32, LLUnits::Kibibits> S32Kibibits;
-typedef LLUnit<S32, LLUnits::Mibibits> S32Mibibits;
-typedef LLUnit<S32, LLUnits::Gibibits> S32Gibibits;
 
-typedef LLUnit<U32, LLUnits::Bits>     U32Bits;
-typedef LLUnit<U32, LLUnits::Kilobits> U32Kilobits;
-typedef LLUnit<U32, LLUnits::Megabits> U32Megabits;
-typedef LLUnit<U32, LLUnits::Gigabits> U32Gigabits;
-typedef LLUnit<U32, LLUnits::Kibibits> U32Kibibits;
-typedef LLUnit<U32, LLUnits::Mibibits> U32Mibibits;
-typedef LLUnit<U32, LLUnits::Gibibits> U32Gibibits;
+typedef LLUnitImplicit<S32, LLUnits::Bits>     S32BitsImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Kilobits> S32KilobitsImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Megabits> S32MegabitsImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Gigabits> S32GigabitsImplicit;
 
 typedef LLUnit<S64, LLUnits::Bits>     S64Bits;
 typedef LLUnit<S64, LLUnits::Kilobits> S64Kilobits;
 typedef LLUnit<S64, LLUnits::Megabits> S64Megabits;
 typedef LLUnit<S64, LLUnits::Gigabits> S64Gigabits;
-typedef LLUnit<S64, LLUnits::Kibibits> S64Kibibits;
-typedef LLUnit<S64, LLUnits::Mibibits> S64Mibibits;
-typedef LLUnit<S64, LLUnits::Gibibits> S64Gibibits;
+
+typedef LLUnitImplicit<S64, LLUnits::Bits>     S64BitsImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Kilobits> S64KilobitsImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Megabits> S64MegabitsImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Gigabits> S64GigabitsImplicit;
+
+typedef LLUnit<U32, LLUnits::Bits>     U32Bits;
+typedef LLUnit<U32, LLUnits::Kilobits> U32Kilobits;
+typedef LLUnit<U32, LLUnits::Megabits> U32Megabits;
+typedef LLUnit<U32, LLUnits::Gigabits> U32Gigabits;
+
+typedef LLUnitImplicit<U32, LLUnits::Bits>     U32BitsImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Kilobits> U32KilobitsImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Megabits> U32MegabitsImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Gigabits> U32GigabitsImplicit;
 
 typedef LLUnit<U64, LLUnits::Bits>     U64Bits;
 typedef LLUnit<U64, LLUnits::Kilobits> U64Kilobits;
 typedef LLUnit<U64, LLUnits::Megabits> U64Megabits;
 typedef LLUnit<U64, LLUnits::Gigabits> U64Gigabits;
-typedef LLUnit<U64, LLUnits::Kibibits> U64Kibibits;
-typedef LLUnit<U64, LLUnits::Mibibits> U64Mibibits;
-typedef LLUnit<U64, LLUnits::Gibibits> U64Gibibits;
+
+typedef LLUnitImplicit<U64, LLUnits::Bits>     U64BitsImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Kilobits> U64KilobitsImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Megabits> U64MegabitsImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Gigabits> U64GigabitsImplicit;
 
 namespace LLUnits
 {
@@ -771,6 +819,14 @@ typedef LLUnit<F32, LLUnits::Milliseconds> F32Milliseconds;
 typedef LLUnit<F32, LLUnits::Microseconds> F32Microseconds;
 typedef LLUnit<F32, LLUnits::Nanoseconds>  F32Nanoseconds;
 
+typedef LLUnitImplicit<F32, LLUnits::Seconds>      F32SecondsImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Minutes>      F32MinutesImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Hours>        F32HoursImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Days>         F32DaysImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Milliseconds> F32MillisecondsImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Microseconds> F32MicrosecondsImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Nanoseconds>  F32NanosecondsImplicit;
+
 typedef LLUnit<F64, LLUnits::Seconds>      F64Seconds;
 typedef LLUnit<F64, LLUnits::Minutes>      F64Minutes;
 typedef LLUnit<F64, LLUnits::Hours>        F64Hours;
@@ -779,6 +835,14 @@ typedef LLUnit<F64, LLUnits::Milliseconds> F64Milliseconds;
 typedef LLUnit<F64, LLUnits::Microseconds> F64Microseconds;
 typedef LLUnit<F64, LLUnits::Nanoseconds>  F64Nanoseconds;
 
+typedef LLUnitImplicit<F64, LLUnits::Seconds>      F64SecondsImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Minutes>      F64MinutesImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Hours>        F64HoursImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Days>         F64DaysImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Milliseconds> F64MillisecondsImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Microseconds> F64MicrosecondsImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Nanoseconds>  F64NanosecondsImplicit;
+
 typedef LLUnit<S32, LLUnits::Seconds>      S32Seconds;
 typedef LLUnit<S32, LLUnits::Minutes>      S32Minutes;
 typedef LLUnit<S32, LLUnits::Hours>        S32Hours;
@@ -787,13 +851,13 @@ typedef LLUnit<S32, LLUnits::Milliseconds> S32Milliseconds;
 typedef LLUnit<S32, LLUnits::Microseconds> S32Microseconds;
 typedef LLUnit<S32, LLUnits::Nanoseconds>  S32Nanoseconds;
 
-typedef LLUnit<U32, LLUnits::Seconds>      U32Seconds;
-typedef LLUnit<U32, LLUnits::Minutes>      U32Minutes;
-typedef LLUnit<U32, LLUnits::Hours>        U32Hours;
-typedef LLUnit<U32, LLUnits::Days>         U32Days;
-typedef LLUnit<U32, LLUnits::Milliseconds> U32Milliseconds;
-typedef LLUnit<U32, LLUnits::Microseconds> U32Microseconds;
-typedef LLUnit<U32, LLUnits::Nanoseconds>  U32Nanoseconds;
+typedef LLUnitImplicit<S32, LLUnits::Seconds>      S32SecondsImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Minutes>      S32MinutesImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Hours>        S32HoursImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Days>         S32DaysImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Milliseconds> S32MillisecondsImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Microseconds> S32MicrosecondsImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Nanoseconds>  S32NanosecondsImplicit;
 
 typedef LLUnit<S64, LLUnits::Seconds>      S64Seconds;
 typedef LLUnit<S64, LLUnits::Minutes>      S64Minutes;
@@ -802,7 +866,31 @@ typedef LLUnit<S64, LLUnits::Days>         S64Days;
 typedef LLUnit<S64, LLUnits::Milliseconds> S64Milliseconds;
 typedef LLUnit<S64, LLUnits::Microseconds> S64Microseconds;
 typedef LLUnit<S64, LLUnits::Nanoseconds>  S64Nanoseconds;
-					
+
+typedef LLUnitImplicit<S64, LLUnits::Seconds>      S64SecondsImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Minutes>      S64MinutesImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Hours>        S64HoursImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Days>         S64DaysImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Milliseconds> S64MillisecondsImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Microseconds> S64MicrosecondsImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Nanoseconds>  S64NanosecondsImplicit;
+
+typedef LLUnit<U32, LLUnits::Seconds>      U32Seconds;
+typedef LLUnit<U32, LLUnits::Minutes>      U32Minutes;
+typedef LLUnit<U32, LLUnits::Hours>        U32Hours;
+typedef LLUnit<U32, LLUnits::Days>         U32Days;
+typedef LLUnit<U32, LLUnits::Milliseconds> U32Milliseconds;
+typedef LLUnit<U32, LLUnits::Microseconds> U32Microseconds;
+typedef LLUnit<U32, LLUnits::Nanoseconds>  U32Nanoseconds;
+
+typedef LLUnitImplicit<U32, LLUnits::Seconds>      U32SecondsImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Minutes>      U32MinutesImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Hours>        U32HoursImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Days>         U32DaysImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Milliseconds> U32MillisecondsImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Microseconds> U32MicrosecondsImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Nanoseconds>  U32NanosecondsImplicit;
+
 typedef LLUnit<U64, LLUnits::Seconds>      U64Seconds;
 typedef LLUnit<U64, LLUnits::Minutes>      U64Minutes;
 typedef LLUnit<U64, LLUnits::Hours>        U64Hours;
@@ -811,6 +899,14 @@ typedef LLUnit<U64, LLUnits::Milliseconds> U64Milliseconds;
 typedef LLUnit<U64, LLUnits::Microseconds> U64Microseconds;
 typedef LLUnit<U64, LLUnits::Nanoseconds>  U64Nanoseconds;
 
+typedef LLUnitImplicit<U64, LLUnits::Seconds>      U64SecondsImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Minutes>      U64MinutesImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Hours>        U64HoursImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Days>         U64DaysImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Milliseconds> U64MillisecondsImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Microseconds> U64MicrosecondsImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Nanoseconds>  U64NanosecondsImplicit;
+
 namespace LLUnits
 {
 LL_DECLARE_BASE_UNIT(Meters, "m");
@@ -824,31 +920,61 @@ typedef LLUnit<F32, LLUnits::Kilometers>  F32Kilometers;
 typedef LLUnit<F32, LLUnits::Centimeters> F32Centimeters;
 typedef LLUnit<F32, LLUnits::Millimeters> F32Millimeters;
 
+typedef LLUnitImplicit<F32, LLUnits::Meters>      F32MetersImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Kilometers>  F32KilometersImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Centimeters> F32CentimetersImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Millimeters> F32MillimetersImplicit;
+
 typedef LLUnit<F64, LLUnits::Meters>      F64Meters;
 typedef LLUnit<F64, LLUnits::Kilometers>  F64Kilometers;
 typedef LLUnit<F64, LLUnits::Centimeters> F64Centimeters;
 typedef LLUnit<F64, LLUnits::Millimeters> F64Millimeters;
 
+typedef LLUnitImplicit<F64, LLUnits::Meters>      F64MetersImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Kilometers>  F64KilometersImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Centimeters> F64CentimetersImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Millimeters> F64MillimetersImplicit;
+
 typedef LLUnit<S32, LLUnits::Meters>      S32Meters;
 typedef LLUnit<S32, LLUnits::Kilometers>  S32Kilometers;
 typedef LLUnit<S32, LLUnits::Centimeters> S32Centimeters;
 typedef LLUnit<S32, LLUnits::Millimeters> S32Millimeters;
 
-typedef LLUnit<U32, LLUnits::Meters>      U32Meters;
-typedef LLUnit<U32, LLUnits::Kilometers>  U32Kilometers;
-typedef LLUnit<U32, LLUnits::Centimeters> U32Centimeters;
-typedef LLUnit<U32, LLUnits::Millimeters> U32Millimeters;
+typedef LLUnitImplicit<S32, LLUnits::Meters>      S32MetersImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Kilometers>  S32KilometersImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Centimeters> S32CentimetersImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Millimeters> S32MillimetersImplicit;
 
 typedef LLUnit<S64, LLUnits::Meters>      S64Meters;
 typedef LLUnit<S64, LLUnits::Kilometers>  S64Kilometers;
 typedef LLUnit<S64, LLUnits::Centimeters> S64Centimeters;
 typedef LLUnit<S64, LLUnits::Millimeters> S64Millimeters;
 
+typedef LLUnitImplicit<S64, LLUnits::Meters>      S64MetersImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Kilometers>  S64KilometersImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Centimeters> S64CentimetersImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Millimeters> S64MillimetersImplicit;
+
+typedef LLUnit<U32, LLUnits::Meters>      U32Meters;
+typedef LLUnit<U32, LLUnits::Kilometers>  U32Kilometers;
+typedef LLUnit<U32, LLUnits::Centimeters> U32Centimeters;
+typedef LLUnit<U32, LLUnits::Millimeters> U32Millimeters;
+
+typedef LLUnitImplicit<U32, LLUnits::Meters>      U32MetersImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Kilometers>  U32KilometersImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Centimeters> U32CentimetersImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Millimeters> U32MillimetersImplicit;
+
 typedef LLUnit<U64, LLUnits::Meters>      U64Meters;
 typedef LLUnit<U64, LLUnits::Kilometers>  U64Kilometers;
 typedef LLUnit<U64, LLUnits::Centimeters> U64Centimeters;
 typedef LLUnit<U64, LLUnits::Millimeters> U64Millimeters;
 
+typedef LLUnitImplicit<U64, LLUnits::Meters>      U64MetersImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Kilometers>  U64KilometersImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Centimeters> U64CentimetersImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Millimeters> U64MillimetersImplicit;
+
 namespace LLUnits
 {
 // rare units
@@ -868,4 +994,137 @@ LL_DECLARE_DERIVED_UNIT(Triangles, * 1000,		Kilotriangles, "ktris");
 
 } // namespace LLUnits
 
+// rare units
+typedef LLUnit<F32, LLUnits::Hertz>			F32Hertz;
+typedef LLUnit<F32, LLUnits::Kilohertz>		F32Kilohertz;
+typedef LLUnit<F32, LLUnits::Megahertz>		F32Megahertz;
+typedef LLUnit<F32, LLUnits::Gigahertz>		F32Gigahertz;
+typedef LLUnit<F32, LLUnits::Radians>		F32Radians;
+typedef LLUnit<F32, LLUnits::Degrees>		F32Degrees;
+typedef LLUnit<F32, LLUnits::Percent>		F32Percent;
+typedef LLUnit<F32, LLUnits::Ratio>			F32Ratio;
+typedef LLUnit<F32, LLUnits::Triangles>		F32Triangles;
+typedef LLUnit<F32, LLUnits::Kilotriangles>	F32KiloTriangles;
+
+typedef LLUnitImplicit<F32, LLUnits::Hertz>			F32HertzImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Kilohertz>		F32KilohertzImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Megahertz>		F32MegahertzImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Gigahertz>		F32GigahertzImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Radians>		F32RadiansImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Degrees>		F32DegreesImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Percent>		F32PercentImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Ratio>			F32RatioImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Triangles>		F32TrianglesImplicit;
+typedef LLUnitImplicit<F32, LLUnits::Kilotriangles>	F32KiloTrianglesImplicit;
+
+typedef LLUnit<F64, LLUnits::Hertz>			F64Hertz;
+typedef LLUnit<F64, LLUnits::Kilohertz>		F64Kilohertz;
+typedef LLUnit<F64, LLUnits::Megahertz>		F64Megahertz;
+typedef LLUnit<F64, LLUnits::Gigahertz>		F64Gigahertz;
+typedef LLUnit<F64, LLUnits::Radians>		F64Radians;
+typedef LLUnit<F64, LLUnits::Degrees>		F64Degrees;
+typedef LLUnit<F64, LLUnits::Percent>		F64Percent;
+typedef LLUnit<F64, LLUnits::Ratio>			F64Ratio;
+typedef LLUnit<F64, LLUnits::Triangles>		F64Triangles;
+typedef LLUnit<F64, LLUnits::Kilotriangles>	F64KiloTriangles;
+
+typedef LLUnitImplicit<F64, LLUnits::Hertz>			F64HertzImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Kilohertz>		F64KilohertzImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Megahertz>		F64MegahertzImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Gigahertz>		F64GigahertzImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Radians>		F64RadiansImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Degrees>		F64DegreesImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Percent>		F64PercentImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Ratio>			F64RatioImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Triangles>		F64TrianglesImplicit;
+typedef LLUnitImplicit<F64, LLUnits::Kilotriangles>	F64KiloTrianglesImplicit;
+
+typedef LLUnit<S32, LLUnits::Hertz>			S32Hertz;
+typedef LLUnit<S32, LLUnits::Kilohertz>		S32Kilohertz;
+typedef LLUnit<S32, LLUnits::Megahertz>		S32Megahertz;
+typedef LLUnit<S32, LLUnits::Gigahertz>		S32Gigahertz;
+typedef LLUnit<S32, LLUnits::Radians>		S32Radians;
+typedef LLUnit<S32, LLUnits::Degrees>		S32Degrees;
+typedef LLUnit<S32, LLUnits::Percent>		S32Percent;
+typedef LLUnit<S32, LLUnits::Ratio>			S32Ratio;
+typedef LLUnit<S32, LLUnits::Triangles>		S32Triangles;
+typedef LLUnit<S32, LLUnits::Kilotriangles>	S32KiloTriangles;
+
+typedef LLUnitImplicit<S32, LLUnits::Hertz>			S32HertzImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Kilohertz>		S32KilohertzImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Megahertz>		S32MegahertzImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Gigahertz>		S32GigahertzImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Radians>		S32RadiansImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Degrees>		S32DegreesImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Percent>		S32PercentImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Ratio>			S32RatioImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Triangles>		S32TrianglesImplicit;
+typedef LLUnitImplicit<S32, LLUnits::Kilotriangles>	S32KiloTrianglesImplicit;
+
+typedef LLUnit<S64, LLUnits::Hertz>			S64Hertz;
+typedef LLUnit<S64, LLUnits::Kilohertz>		S64Kilohertz;
+typedef LLUnit<S64, LLUnits::Megahertz>		S64Megahertz;
+typedef LLUnit<S64, LLUnits::Gigahertz>		S64Gigahertz;
+typedef LLUnit<S64, LLUnits::Radians>		S64Radians;
+typedef LLUnit<S64, LLUnits::Degrees>		S64Degrees;
+typedef LLUnit<S64, LLUnits::Percent>		S64Percent;
+typedef LLUnit<S64, LLUnits::Ratio>			S64Ratio;
+typedef LLUnit<S64, LLUnits::Triangles>		S64Triangles;
+typedef LLUnit<S64, LLUnits::Kilotriangles>	S64KiloTriangles;
+
+typedef LLUnitImplicit<S64, LLUnits::Hertz>			S64HertzImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Kilohertz>		S64KilohertzImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Megahertz>		S64MegahertzImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Gigahertz>		S64GigahertzImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Radians>		S64RadiansImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Degrees>		S64DegreesImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Percent>		S64PercentImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Ratio>			S64RatioImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Triangles>		S64TrianglesImplicit;
+typedef LLUnitImplicit<S64, LLUnits::Kilotriangles>	S64KiloTrianglesImplicit;
+
+typedef LLUnit<U32, LLUnits::Hertz>			U32Hertz;
+typedef LLUnit<U32, LLUnits::Kilohertz>		U32Kilohertz;
+typedef LLUnit<U32, LLUnits::Megahertz>		U32Megahertz;
+typedef LLUnit<U32, LLUnits::Gigahertz>		U32Gigahertz;
+typedef LLUnit<U32, LLUnits::Radians>		U32Radians;
+typedef LLUnit<U32, LLUnits::Degrees>		U32Degrees;
+typedef LLUnit<U32, LLUnits::Percent>		U32Percent;
+typedef LLUnit<U32, LLUnits::Ratio>			U32Ratio;
+typedef LLUnit<U32, LLUnits::Triangles>		U32Triangles;
+typedef LLUnit<U32, LLUnits::Kilotriangles>	U32KiloTriangles;
+
+typedef LLUnitImplicit<U32, LLUnits::Hertz>			U32HertzImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Kilohertz>		U32KilohertzImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Megahertz>		U32MegahertzImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Gigahertz>		U32GigahertzImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Radians>		U32RadiansImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Degrees>		U32DegreesImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Percent>		U32PercentImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Ratio>			U32RatioImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Triangles>		U32TrianglesImplicit;
+typedef LLUnitImplicit<U32, LLUnits::Kilotriangles>	U32KiloTrianglesImplicit;
+
+typedef LLUnit<U64, LLUnits::Hertz>			U64Hertz;
+typedef LLUnit<U64, LLUnits::Kilohertz>		U64Kilohertz;
+typedef LLUnit<U64, LLUnits::Megahertz>		U64Megahertz;
+typedef LLUnit<U64, LLUnits::Gigahertz>		U64Gigahertz;
+typedef LLUnit<U64, LLUnits::Radians>		U64Radians;
+typedef LLUnit<U64, LLUnits::Degrees>		U64Degrees;
+typedef LLUnit<U64, LLUnits::Percent>		U64Percent;
+typedef LLUnit<U64, LLUnits::Ratio>			U64Ratio;
+typedef LLUnit<U64, LLUnits::Triangles>		U64Triangles;
+typedef LLUnit<U64, LLUnits::Kilotriangles>	U64KiloTriangles;
+
+typedef LLUnitImplicit<U64, LLUnits::Hertz>			U64HertzImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Kilohertz>		U64KilohertzImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Megahertz>		U64MegahertzImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Gigahertz>		U64GigahertzImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Radians>		U64RadiansImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Degrees>		U64DegreesImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Percent>		U64PercentImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Ratio>			U64RatioImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Triangles>		U64TrianglesImplicit;
+typedef LLUnitImplicit<U64, LLUnits::Kilotriangles>	U64KiloTrianglesImplicit;
+
 #endif // LL_LLUNIT_H
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index 8546bcbc54..a8e9be86ca 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -38,6 +38,13 @@ namespace LLUnits
 	LL_DECLARE_DERIVED_UNIT(Latinum, / 16, Solari, "Sol");
 }
 
+typedef LLUnit<F32, LLUnits::Quatloos> F32Quatloos;
+typedef LLUnit<S32, LLUnits::Quatloos> S32Quatloos;
+typedef LLUnit<F32, LLUnits::Latinum> F32Latinum;
+typedef LLUnit<S32, LLUnits::Latinum> S32Latinum;
+typedef LLUnit<F32, LLUnits::Solari> F32Solari;
+typedef LLUnit<S32, LLUnits::Solari> S32Solari;
+
 namespace tut
 {
 	using namespace LLUnits;
@@ -54,28 +61,28 @@ namespace tut
 	void units_object_t::test<1>()
 	{
 		LLUnit<F32, Quatloos> float_quatloos;
-		ensure("default float unit is zero", float_quatloos == 0.f);
+		ensure("default float unit is zero", float_quatloos == F32Quatloos(0.f));
 
 		LLUnit<F32, Quatloos> float_initialize_quatloos(1);
-		ensure("non-zero initialized unit", float_initialize_quatloos == 1.f);
+		ensure("non-zero initialized unit", float_initialize_quatloos == F32Quatloos(1.f));
 
 		LLUnit<S32, Quatloos> int_quatloos;
-		ensure("default int unit is zero", int_quatloos == 0);
+		ensure("default int unit is zero", int_quatloos == S32Quatloos(0));
 
-		int_quatloos = 42;
-		ensure("int assignment is preserved", int_quatloos == 42);
+		int_quatloos = S32Quatloos(42);
+		ensure("int assignment is preserved", int_quatloos == S32Quatloos(42));
 		float_quatloos = int_quatloos;
-		ensure("float assignment from int preserves value", float_quatloos == 42.f);
+		ensure("float assignment from int preserves value", float_quatloos == F32Quatloos(42.f));
 
 		int_quatloos = float_quatloos;
-		ensure("int assignment from float preserves value", int_quatloos == 42);
+		ensure("int assignment from float preserves value", int_quatloos == S32Quatloos(42));
 
-		float_quatloos = 42.1f;
+		float_quatloos = F32Quatloos(42.1f);
 		int_quatloos = float_quatloos;
-		ensure("int units truncate float units on assignment", int_quatloos == 42);
+		ensure("int units truncate float units on assignment", int_quatloos == S32Quatloos(42));
 
 		LLUnit<U32, Quatloos> unsigned_int_quatloos(float_quatloos);
-		ensure("unsigned int can be initialized from signed int", unsigned_int_quatloos == 42);
+		ensure("unsigned int can be initialized from signed int", unsigned_int_quatloos == S32Quatloos(42));
 	}
 
 	// conversions to/from base unit
@@ -84,15 +91,15 @@ namespace tut
 	{
 		LLUnit<F32, Quatloos> quatloos(1.f);
 		LLUnit<F32, Latinum> latinum_bars(quatloos);
-		ensure("conversion between units is automatic via initialization", latinum_bars == 1.f / 4.f);
+		ensure("conversion between units is automatic via initialization", latinum_bars == F32Latinum(1.f / 4.f));
 
-		latinum_bars = 256;
+		latinum_bars = S32Latinum(256);
 		quatloos = latinum_bars;
-		ensure("conversion between units is automatic via assignment, and bidirectional", quatloos == 1024);
+		ensure("conversion between units is automatic via assignment, and bidirectional", quatloos == S32Quatloos(1024));
 
 		LLUnit<S32, Quatloos> single_quatloo(1);
 		LLUnit<F32, Latinum> quarter_latinum = single_quatloo;
-		ensure("division of integer unit preserves fractional values when converted to float unit", quarter_latinum == 0.25f);
+		ensure("division of integer unit preserves fractional values when converted to float unit", quarter_latinum == F32Latinum(0.25f));
 	}
 
 	// conversions across non-base units
@@ -101,10 +108,10 @@ namespace tut
 	{
 		LLUnit<F32, Quatloos> quatloos(1024);
 		LLUnit<F32, Solari> solari(quatloos);
-		ensure("conversions can work between indirectly related units: Quatloos -> Latinum -> Solari", solari == 4096);
+		ensure("conversions can work between indirectly related units: Quatloos -> Latinum -> Solari", solari == S32Solari(4096));
 
 		LLUnit<F32, Latinum> latinum_bars = solari;
-		ensure("Non base units can be converted between each other", latinum_bars == 256);
+		ensure("Non base units can be converted between each other", latinum_bars == S32Latinum(256));
 	}
 
 	// math operations
@@ -114,36 +121,36 @@ namespace tut
 		// exercise math operations
 		LLUnit<F32, Quatloos> quatloos(1.f);
 		quatloos *= 4.f;
-		ensure(quatloos == 4);
+		ensure(quatloos == S32Quatloos(4));
 		quatloos = quatloos * 2;
-		ensure(quatloos == 8);
+		ensure(quatloos == S32Quatloos(8));
 		quatloos = 2.f * quatloos;
-		ensure(quatloos == 16);
-
-		quatloos += 4.f;
-		ensure(quatloos == 20);
-		quatloos += 4;
-		ensure(quatloos == 24);
-		quatloos = quatloos + 4;
-		ensure(quatloos == 28);
-		quatloos = 4 + quatloos;
-		ensure(quatloos == 32);
+		ensure(quatloos == S32Quatloos(16));
+
+		quatloos += F32Quatloos(4.f);
+		ensure(quatloos == S32Quatloos(20));
+		quatloos += S32Quatloos(4);
+		ensure(quatloos == S32Quatloos(24));
+		quatloos = quatloos + S32Quatloos(4);
+		ensure(quatloos == S32Quatloos(28));
+		quatloos = S32Quatloos(4) + quatloos;
+		ensure(quatloos == S32Quatloos(32));
 		quatloos += quatloos * 3;
-		ensure(quatloos == 128);
+		ensure(quatloos == S32Quatloos(128));
 
 		quatloos -= quatloos / 4 * 3;
-		ensure(quatloos == 32);
-		quatloos = quatloos - 8;
-		ensure(quatloos == 24);
-		quatloos -= 4;
-		ensure(quatloos == 20);
-		quatloos -= 4.f;
-		ensure(quatloos == 16);
+		ensure(quatloos == S32Quatloos(32));
+		quatloos = quatloos - S32Quatloos(8);
+		ensure(quatloos == S32Quatloos(24));
+		quatloos -= S32Quatloos(4);
+		ensure(quatloos == S32Quatloos(20));
+		quatloos -= F32Quatloos(4.f);
+		ensure(quatloos == S32Quatloos(16));
 
 		quatloos /= 2.f;
-		ensure(quatloos == 8);
+		ensure(quatloos == S32Quatloos(8));
 		quatloos = quatloos / 4;
-		ensure(quatloos == 2);
+		ensure(quatloos == S32Quatloos(2));
 
 		F32 ratio = quatloos / LLUnit<F32, Quatloos>(2.f);
 		ensure(ratio == 1);
@@ -151,23 +158,54 @@ namespace tut
 		ensure(ratio == 1);
 
 		quatloos += LLUnit<F32, Solari>(8.f);
-		ensure(quatloos == 4);
+		ensure(quatloos == S32Quatloos(4));
 		quatloos -= LLUnit<F32, Latinum>(1.f);
-		ensure(quatloos == 0);
+		ensure(quatloos == S32Quatloos(0));
 	}
 
-	// implicit units
+	// comparison operators
 	template<> template<>
 	void units_object_t::test<5>()
+	{
+		LLUnit<S32, Quatloos> quatloos(1);
+		ensure("can perform less than comparison against same type", quatloos < S32Quatloos(2));
+		ensure("can perform less than comparison against different storage type", quatloos < F32Quatloos(2.f));
+		ensure("can perform less than comparison against different units", quatloos < S32Latinum(5));
+		ensure("can perform less than comparison against different storage type and units", quatloos < F32Latinum(5.f));
+
+		ensure("can perform greater than comparison against same type", quatloos > S32Quatloos(0));
+		ensure("can perform greater than comparison against different storage type", quatloos > F32Quatloos(0.f));
+		ensure("can perform greater than comparison against different units", quatloos > S32Latinum(0));
+		ensure("can perform greater than comparison against different storage type and units", quatloos > F32Latinum(0.f));
+
+	}
+
+	bool accept_explicit_quatloos(S32Quatloos q)
+	{
+		return true;
+	}
+
+	// signature compatibility
+	template<> template<>
+	void units_object_t::test<6>()
+	{
+		S32Quatloos quatloos(1);
+		ensure("can pass unit values as argument", accept_explicit_quatloos(S32Quatloos(1)));
+		ensure("can pass unit values as argument", accept_explicit_quatloos(quatloos));
+	}
+
+	// implicit units
+	template<> template<>
+	void units_object_t::test<7>()
 	{
 		LLUnit<F32, Quatloos> quatloos;
-		LLUnitImplicit<F32, Quatloos> quatloos_implicit = quatloos + 1;
+		LLUnitImplicit<F32, Quatloos> quatloos_implicit = quatloos + S32Quatloos(1);
 		ensure("can initialize implicit unit from explicit", quatloos_implicit == 1);
 
 		quatloos = quatloos_implicit;
-		ensure("can assign implicit unit to explicit unit", quatloos == 1);
+		ensure("can assign implicit unit to explicit unit", quatloos == S32Quatloos(1));
 		quatloos += quatloos_implicit;
-		ensure("can perform math operation using mixture of implicit and explicit units", quatloos == 2);
+		ensure("can perform math operation using mixture of implicit and explicit units", quatloos == S32Quatloos(2));
 
 		// math operations on implicits
 		quatloos_implicit = 1;
-- 
cgit v1.2.3


From 3e31cb112daf0a759737ba4ec55a8772361483f2 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 19 Aug 2013 11:50:30 -0700
Subject: BUILDFIX: fixed some units errors

---
 indra/llcommon/llfasttimer.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 5f92c66f47..d99c4c990e 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -335,7 +335,7 @@ 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<F64, LLUnits::Hertz>(LLProcessorInfo().getCPUFrequency())) << LL_ENDL;
+			LL_DEBUGS("FastTimers") << "elapsed sec " << ((F64)getCPUClockCount64() / (F64HertzImplicit)LLProcessorInfo().getCPUFrequency()) << LL_ENDL;
 		}
 		call_count++;
 
-- 
cgit v1.2.3


From 296ec41e1648efe981a30043b4a7f23590d8a828 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 19 Aug 2013 11:57:33 -0700
Subject: BUILDFIX: abstracted decltype into macro LLTYPEOF for temporary gcc
 4.1/4.2 support

---
 indra/llcommon/llpreprocessor.h |  7 ++++
 indra/llcommon/llunit.h         | 88 ++++++++++++++++++++---------------------
 2 files changed, 51 insertions(+), 44 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index 7fdb537ab5..a764a42fca 100755
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -181,4 +181,11 @@
 # define LL_COMMON_API
 #endif // LL_COMMON_LINK_SHARED
 
+#if LL_WINDOWS
+#define LLTYPEOF(exp) decltype(exp)
+#elif LL_LINUX
+#define LLTYPEOF(exp) typeof(exp)
+#elif LL_DARWIN
+#define LLTYPEOF(exp) typeof(exp)
+#endif
 #endif	//	not LL_LINDEN_PREPROCESSOR_H
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index c49c882f23..7a98ce1f45 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -47,7 +47,7 @@ struct LLIsSameType<T, T>
 template<typename S, typename T>
 struct LLPromotedType
 {
-	typedef decltype(S() + T()) type_t;
+	typedef LLTYPEOF(S() + T()) type_t;
 };
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE>
@@ -262,9 +262,9 @@ LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ..
 // operator +
 //
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnit<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnit<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result += second;
 	return result;
 }
@@ -284,41 +284,41 @@ LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (UNITLESS first, LLUnit<STORAGE_TYPE,
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result += second;
 	return result;
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result += second;
 	return result;
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<decltype(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result += LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
 	return result;
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<decltype(STORAGE_TYPE() + UNITLESS_TYPE()), UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() + UNITLESS_TYPE()), UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	LLUnitImplicit<decltype(STORAGE_TYPE() + UNITLESS_TYPE()), UNIT_TYPE> result(first);
+	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() + UNITLESS_TYPE()), UNIT_TYPE> result(first);
 	result += second;
 	return result;
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<decltype(UNITLESS_TYPE() + STORAGE_TYPE()), UNIT_TYPE> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+LLUnitImplicit<LLTYPEOF(UNITLESS_TYPE() + STORAGE_TYPE()), UNIT_TYPE> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	LLUnitImplicit<decltype(UNITLESS_TYPE() + STORAGE_TYPE()), UNIT_TYPE> result(first);
+	LLUnitImplicit<LLTYPEOF(UNITLESS_TYPE() + STORAGE_TYPE()), UNIT_TYPE> result(first);
 	result += second;
 	return result;
 }
@@ -327,9 +327,9 @@ LLUnitImplicit<decltype(UNITLESS_TYPE() + STORAGE_TYPE()), UNIT_TYPE> operator +
 // operator -
 //
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnit<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnit<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result -= second;
 	return result;
 }
@@ -349,41 +349,41 @@ LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (UNITLESS first, LLUnit<STORAGE_TYPE,
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result -= second;
 	return result;
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result -= second;
 	return result;
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<decltype(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
 	result -= LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
 	return result;
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<decltype(STORAGE_TYPE() - UNITLESS_TYPE()), UNIT_TYPE> operator - (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() - UNITLESS_TYPE()), UNIT_TYPE> operator - (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	LLUnitImplicit<decltype(STORAGE_TYPE() - UNITLESS_TYPE()), UNIT_TYPE> result(first);
+	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() - UNITLESS_TYPE()), UNIT_TYPE> result(first);
 	result -= second;
 	return result;
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<decltype(UNITLESS_TYPE() - STORAGE_TYPE()), UNIT_TYPE> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+LLUnitImplicit<LLTYPEOF(UNITLESS_TYPE() - STORAGE_TYPE()), UNIT_TYPE> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	LLUnitImplicit<decltype(UNITLESS_TYPE() - STORAGE_TYPE()), UNIT_TYPE> result(first);
+	LLUnitImplicit<LLTYPEOF(UNITLESS_TYPE() - STORAGE_TYPE()), UNIT_TYPE> result(first);
 	result -= second;
 	return result;
 }
@@ -400,15 +400,15 @@ LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnit<STORAGE_TYPE1, UNIT_TYPE1>,
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<decltype(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnit<LLTYPEOF(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnit<decltype(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE>(first.value() * second);
+	return LLUnit<LLTYPEOF(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE>(first.value() * second);
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<decltype(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
+LLUnit<LLTYPEOF(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	return LLUnit<decltype(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE>(first * second.value());
+	return LLUnit<LLTYPEOF(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE>(first * second.value());
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
@@ -420,15 +420,15 @@ LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnitImplicit<STORAGE_TYP
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<decltype(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE> operator * (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE> operator * (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnitImplicit<decltype(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE>(first.value() * second);
+	return LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE>(first.value() * second);
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<decltype(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+LLUnitImplicit<LLTYPEOF(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	return LLUnitImplicit<decltype(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE>(first * second.value());
+	return LLUnitImplicit<LLTYPEOF(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE>(first * second.value());
 }
 
 
@@ -437,39 +437,39 @@ LLUnitImplicit<decltype(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE> operator *
 //
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<decltype(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnit<LLTYPEOF(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnit<decltype(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE>(first.value() / second);
+	return LLUnit<LLTYPEOF(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE>(first.value() / second);
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-decltype(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
 	return first.value() / first.convert(second).value();
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<decltype(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE> operator / (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE> operator / (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnitImplicit<decltype(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE>(first.value() / second);
+	return LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE>(first.value() / second);
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-decltype(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	return (decltype(STORAGE_TYPE1() / STORAGE_TYPE2()))(first.value() / first.convert(second).value());
+	return (LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()))(first.value() / first.convert(second).value());
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-decltype(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	return (decltype(STORAGE_TYPE1() / STORAGE_TYPE2()))(first.value() / first.convert(second).value());
+	return (LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()))(first.value() / first.convert(second).value());
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-decltype(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	return (decltype(STORAGE_TYPE1() / STORAGE_TYPE2()))(first.value() / first.convert(second).value());
+	return (LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()))(first.value() / first.convert(second).value());
 }
 
 //
-- 
cgit v1.2.3


From b2d4148eecf5a307006453fbdd3ae9d81517523d Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 19 Aug 2013 12:05:09 -0700
Subject: BUILDFIX: fixed several template agument errors

---
 indra/llcommon/llunit.h | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 7a98ce1f45..7afb1089ba 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -187,25 +187,25 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
 	using base_t::operator +=;
 	void operator += (storage_t value)
 	{
-		mValue += value;
+        base_t::mValue += value;
 	}
 
 	template<typename OTHER_STORAGE, typename OTHER_UNIT>
 	void operator += (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
 	{
-		mValue += convert(other).value();
+        base_t::mValue += convert(other).value();
 	}
 
 	using base_t::operator -=;
 	void operator -= (storage_t value)
 	{
-		mValue -= value;
+        base_t::mValue -= value;
 	}
 
 	template<typename OTHER_STORAGE, typename OTHER_UNIT>
 	void operator -= (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
 	{
-		mValue -= convert(other).value();
+        base_t::mValue -= convert(other).value();
 	}
 
 };
@@ -272,14 +272,14 @@ LLUnit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUn
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
 LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS second)
 {
-	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "operator + requires compatible unit types");
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
 	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
 LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (UNITLESS first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "operator + requires compatible unit types");
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
 	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
 }
 
@@ -337,14 +337,14 @@ LLUnit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUn
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
 LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS second)
 {
-	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "operator - requires compatible unit types");
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
 	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
 LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (UNITLESS first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "operator - requires compatible unit types");
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
 	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
 }
 
@@ -443,7 +443,7 @@ LLUnit<LLTYPEOF(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE> operator / (LLUnit
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2(1)) operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
 	return first.value() / first.convert(second).value();
 }
@@ -455,19 +455,19 @@ LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE> operator /
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2(1)) operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	return (LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()))(first.value() / first.convert(second).value());
+	return (LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2(1)))(first.value() / first.convert(second).value());
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2(1)) operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
 	return (LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()))(first.value() / first.convert(second).value());
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()) operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2(1)) operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
 	return (LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()))(first.value() / first.convert(second).value());
 }
-- 
cgit v1.2.3


From ea45b8acd25785bd2789c2c1928e223c9a8e2fbd Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 19 Aug 2013 14:17:17 -0700
Subject: BUILDFIX: refactored decltype out into traits class

---
 indra/llcommon/llpreprocessor.h |   6 +--
 indra/llcommon/llunit.h         | 110 +++++++++++++++++++++-------------------
 2 files changed, 60 insertions(+), 56 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index a764a42fca..e5c8482ed1 100755
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -182,10 +182,10 @@
 #endif // LL_COMMON_LINK_SHARED
 
 #if LL_WINDOWS
-#define LLTYPEOF(exp) decltype(exp)
+#define LL_TYPEOF(exp) decltype(exp)
 #elif LL_LINUX
-#define LLTYPEOF(exp) typeof(exp)
+#define LL_TYPEOF(exp) typeof(exp)
 #elif LL_DARWIN
-#define LLTYPEOF(exp) typeof(exp)
+#define LL_TYPEOF(exp) typeof(exp)
 #endif
 #endif	//	not LL_LINDEN_PREPROCESSOR_H
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 7afb1089ba..67810ffabc 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -44,10 +44,14 @@ struct LLIsSameType<T, T>
 	static const bool value = true;
 };
 
+// workaround for decltype() not existing and typeof() not working inline in gcc 4.2
 template<typename S, typename T>
-struct LLPromotedType
+struct LLResultType
 {
-	typedef LLTYPEOF(S() + T()) type_t;
+	typedef LL_TYPEOF(S() + T()) add_t;
+	typedef LL_TYPEOF(S() - T()) subtract_t;
+	typedef LL_TYPEOF(S() * T()) multiply_t;
+	typedef LL_TYPEOF(S() / T(1)) divide_t;
 };
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE>
@@ -262,9 +266,9 @@ LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ..
 // operator +
 //
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> result(first);
 	result += second;
 	return result;
 }
@@ -284,41 +288,41 @@ LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (UNITLESS first, LLUnit<STORAGE_TYPE,
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> result(first);
 	result += second;
 	return result;
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> result(first);
 	result += second;
 	return result;
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() + STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> result(first);
 	result += LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
 	return result;
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() + UNITLESS_TYPE()), UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::add_t, UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() + UNITLESS_TYPE()), UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::add_t, UNIT_TYPE> result(first);
 	result += second;
 	return result;
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<LLTYPEOF(UNITLESS_TYPE() + STORAGE_TYPE()), UNIT_TYPE> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+LLUnitImplicit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::add_t, UNIT_TYPE> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	LLUnitImplicit<LLTYPEOF(UNITLESS_TYPE() + STORAGE_TYPE()), UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::add_t, UNIT_TYPE> result(first);
 	result += second;
 	return result;
 }
@@ -327,9 +331,9 @@ LLUnitImplicit<LLTYPEOF(UNITLESS_TYPE() + STORAGE_TYPE()), UNIT_TYPE> operator +
 // operator -
 //
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> result(first);
 	result -= second;
 	return result;
 }
@@ -349,41 +353,41 @@ LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (UNITLESS first, LLUnit<STORAGE_TYPE,
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> result(first);
 	result -= second;
 	return result;
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> result(first);
 	result -= second;
 	return result;
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE1() - STORAGE_TYPE2()), UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> result(first);
 	result -= LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
 	return result;
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() - UNITLESS_TYPE()), UNIT_TYPE> operator - (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::subtract_t, UNIT_TYPE> operator - (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() - UNITLESS_TYPE()), UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::subtract_t, UNIT_TYPE> result(first);
 	result -= second;
 	return result;
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<LLTYPEOF(UNITLESS_TYPE() - STORAGE_TYPE()), UNIT_TYPE> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+LLUnitImplicit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::subtract_t, UNIT_TYPE> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	LLUnitImplicit<LLTYPEOF(UNITLESS_TYPE() - STORAGE_TYPE()), UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::subtract_t, UNIT_TYPE> result(first);
 	result -= second;
 	return result;
 }
@@ -400,15 +404,15 @@ LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnit<STORAGE_TYPE1, UNIT_TYPE1>,
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<LLTYPEOF(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::multiply_t, UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnit<LLTYPEOF(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE>(first.value() * second);
+	return LLUnit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::multiply_t, UNIT_TYPE>(first.value() * second);
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<LLTYPEOF(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
+LLUnit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::multiply_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	return LLUnit<LLTYPEOF(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE>(first * second.value());
+	return LLUnit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::multiply_t, UNIT_TYPE>(first * second.value());
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
@@ -420,15 +424,15 @@ LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnitImplicit<STORAGE_TYP
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE> operator * (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::multiply_t, UNIT_TYPE> operator * (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() * UNITLESS_TYPE()), UNIT_TYPE>(first.value() * second);
+	return LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::multiply_t, UNIT_TYPE>(first.value() * second);
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<LLTYPEOF(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+LLUnitImplicit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::multiply_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	return LLUnitImplicit<LLTYPEOF(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE>(first * second.value());
+	return LLUnitImplicit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::multiply_t, UNIT_TYPE>(first * second.value());
 }
 
 
@@ -437,39 +441,39 @@ LLUnitImplicit<LLTYPEOF(UNITLESS_TYPE() * STORAGE_TYPE()), UNIT_TYPE> operator *
 //
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<LLTYPEOF(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::divide_t, UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnit<LLTYPEOF(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE>(first.value() / second);
+	return LLUnit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::divide_t, UNIT_TYPE>(first.value() / second);
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2(1)) operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::divide_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
 	return first.value() / first.convert(second).value();
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE> operator / (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::divide_t, UNIT_TYPE> operator / (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnitImplicit<LLTYPEOF(STORAGE_TYPE() / UNITLESS_TYPE()), UNIT_TYPE>(first.value() / second);
+	return LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::divide_t, UNIT_TYPE>(first.value() / second);
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2(1)) operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::divide_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	return (LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2(1)))(first.value() / first.convert(second).value());
+	return (typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::divide_t)(first.value() / first.convert(second).value());
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2(1)) operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::divide_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	return (LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()))(first.value() / first.convert(second).value());
+	return (typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::divide_t)(first.value() / first.convert(second).value());
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2(1)) operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::divide_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	return (LLTYPEOF(STORAGE_TYPE1() / STORAGE_TYPE2()))(first.value() / first.convert(second).value());
+	return (typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::divide_t)(first.value() / first.convert(second).value());
 }
 
 //
@@ -562,25 +566,25 @@ struct LLUnitLinearOps
 	template<typename T>
 	output_t operator * (T other)
 	{
-		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) * other;
+		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::multiply_t(mInput) * other;
 	}
 
 	template<typename T>
 	output_t operator / (T other)
 	{
-		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) / other;
+		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::divide_t(mInput) / other;
 	}
 
 	template<typename T>
 	output_t operator + (T other)
 	{
-		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) + other;
+		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::add_t(mInput) + other;
 	}
 
 	template<typename T>
 	output_t operator - (T other)
 	{
-		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) - other;
+		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::subtract_t(mInput) - other;
 	}
 };
 
@@ -599,25 +603,25 @@ struct LLUnitInverseLinearOps
 	template<typename T>
 	output_t operator * (T other)
 	{
-		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) / other;
+		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::divide_t(mInput) / other;
 	}
 
 	template<typename T>
 	output_t operator / (T other)
 	{
-		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) * other;
+		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::multiply_t(mInput) * other;
 	}
 
 	template<typename T>
 	output_t operator + (T other)
 	{
-		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) - other;
+		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::subtract_t(mInput) - other;
 	}
 
 	template<typename T>
 	output_t operator - (T other)
 	{
-		return typename LLPromotedType<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) + other;
+		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::add_t(mInput) + other;
 	}
 };
 
-- 
cgit v1.2.3


From 9c256611f1814b843e1adc29f8a9185a3519eeaf Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 19 Aug 2013 16:05:03 -0700
Subject: BUILDFIX: removed consideration of some bad overloads in return type
 evaluation of unit operators

---
 indra/llcommon/llunit.h | 587 +++++++++++-------------------------------------
 1 file changed, 128 insertions(+), 459 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 67810ffabc..8fb53dd94d 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -46,12 +46,27 @@ struct LLIsSameType<T, T>
 
 // workaround for decltype() not existing and typeof() not working inline in gcc 4.2
 template<typename S, typename T>
-struct LLResultType
+struct LLResultTypeAdd
 {
-	typedef LL_TYPEOF(S() + T()) add_t;
-	typedef LL_TYPEOF(S() - T()) subtract_t;
-	typedef LL_TYPEOF(S() * T()) multiply_t;
-	typedef LL_TYPEOF(S() / T(1)) divide_t;
+	typedef LL_TYPEOF(S() + T()) type_t;
+};
+
+template<typename S, typename T>
+struct LLResultTypeSubtract
+{
+	typedef LL_TYPEOF(S() - T()) type_t;
+};
+
+template<typename S, typename T>
+struct LLResultTypeMultiply
+{
+	typedef LL_TYPEOF(S() * T()) type_t;
+};
+
+template<typename S, typename T>
+struct LLResultTypeDivide
+{
+	typedef LL_TYPEOF(S() / T(1)) type_t;
 };
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE>
@@ -262,13 +277,25 @@ LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ..
 	}
 }
 
+template<typename T>
+struct LLStorageType
+{
+	typedef T type_t;
+};
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE>
+struct LLStorageType<LLUnit<STORAGE_TYPE, UNIT_TYPE> >
+{
+	typedef STORAGE_TYPE type_t;
+};
+
 //
 // operator +
 //
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> result(first);
+	LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
 	result += second;
 	return result;
 }
@@ -288,41 +315,42 @@ LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (UNITLESS first, LLUnit<STORAGE_TYPE,
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
 	result += second;
 	return result;
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
 	result += second;
 	return result;
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::add_t, UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
 	result += LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
 	return result;
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::add_t, UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::add_t, UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> result(first);
 	result += second;
 	return result;
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::add_t, UNIT_TYPE> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::
+	type_t, UNIT_TYPE> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	LLUnitImplicit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::add_t, UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> result(first);
 	result += second;
 	return result;
 }
@@ -331,9 +359,9 @@ LLUnitImplicit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::add_t, UNIT_T
 // operator -
 //
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> result(first);
+	LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
 	result -= second;
 	return result;
 }
@@ -353,41 +381,41 @@ LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (UNITLESS first, LLUnit<STORAGE_TYPE,
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
 	result -= second;
 	return result;
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
 	result -= second;
 	return result;
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	LLUnitImplicit<typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::subtract_t, UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
 	result -= LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
 	return result;
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::subtract_t, UNIT_TYPE> operator - (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator - (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::subtract_t, UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> result(first);
 	result -= second;
 	return result;
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::subtract_t, UNIT_TYPE> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	LLUnitImplicit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::subtract_t, UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> result(first);
 	result -= second;
 	return result;
 }
@@ -404,15 +432,15 @@ LLUnit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnit<STORAGE_TYPE1, UNIT_TYPE1>,
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::multiply_t, UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::multiply_t, UNIT_TYPE>(first.value() * second);
+	return LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() * second);
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::multiply_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
+LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	return LLUnit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::multiply_t, UNIT_TYPE>(first * second.value());
+	return LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE>(first * second.value());
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
@@ -424,15 +452,15 @@ LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> operator * (LLUnitImplicit<STORAGE_TYP
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::multiply_t, UNIT_TYPE> operator * (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator * (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::multiply_t, UNIT_TYPE>(first.value() * second);
+	return LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, UNITLESS_TYPE>::type_t, UNIT_TYPE>(first.value() * second);
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::multiply_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
 {
-	return LLUnitImplicit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::multiply_t, UNIT_TYPE>(first * second.value());
+	return LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE>(first * second.value());
 }
 
 
@@ -441,39 +469,39 @@ LLUnitImplicit<typename LLResultType<UNITLESS_TYPE, STORAGE_TYPE>::multiply_t, U
 //
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::divide_t, UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::divide_t, UNIT_TYPE>(first.value() / second);
+	return LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() / second);
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::divide_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
 	return first.value() / first.convert(second).value();
 }
 
 template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::divide_t, UNIT_TYPE> operator / (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator / (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
 {
-	return LLUnitImplicit<typename LLResultType<STORAGE_TYPE, UNITLESS_TYPE>::divide_t, UNIT_TYPE>(first.value() / second);
+	return LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() / second);
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::divide_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	return (typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::divide_t)(first.value() / first.convert(second).value());
+	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::divide_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	return (typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::divide_t)(first.value() / first.convert(second).value());
+	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
 }
 
 template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::divide_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
 {
-	return (typename LLResultType<STORAGE_TYPE1, STORAGE_TYPE2>::divide_t)(first.value() / first.convert(second).value());
+	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
 }
 
 //
@@ -566,25 +594,25 @@ struct LLUnitLinearOps
 	template<typename T>
 	output_t operator * (T other)
 	{
-		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::multiply_t(mInput) * other;
+		return typename LLResultTypeMultiply<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) * other;
 	}
 
 	template<typename T>
 	output_t operator / (T other)
 	{
-		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::divide_t(mInput) / other;
+		return typename LLResultTypeDivide<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) / other;
 	}
 
 	template<typename T>
 	output_t operator + (T other)
 	{
-		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::add_t(mInput) + other;
+		return typename LLResultTypeAdd<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) + other;
 	}
 
 	template<typename T>
 	output_t operator - (T other)
 	{
-		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::subtract_t(mInput) - other;
+		return typename LLResultTypeSubtract<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) - other;
 	}
 };
 
@@ -603,25 +631,25 @@ struct LLUnitInverseLinearOps
 	template<typename T>
 	output_t operator * (T other)
 	{
-		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::divide_t(mInput) / other;
+		return typename LLResultTypeDivide<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) / other;
 	}
 
 	template<typename T>
 	output_t operator / (T other)
 	{
-		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::multiply_t(mInput) * other;
+		return typename LLResultTypeMultiply<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) * other;
 	}
 
 	template<typename T>
 	output_t operator + (T other)
 	{
-		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::subtract_t(mInput) - other;
+		return typename LLResultTypeAdd<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) - other;
 	}
 
 	template<typename T>
 	output_t operator - (T other)
 	{
-		return typename LLResultType<INPUT_TYPE, OUTPUT_TYPE>::add_t(mInput) + other;
+		return typename LLResultTypeSubtract<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) + other;
 	}
 };
 
@@ -662,6 +690,20 @@ void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)
 	out = LLUnit<S2, unit_name>((S2)(LLUnitInverseLinearOps<S1, S2>(in.value()) conversion_operation)); \
 }                                                                                               
 
+#define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name)                         \
+	typedef LLUnit<F32, ns::unit_name> F32##unit_name;                  \
+	typedef LLUnitImplicit<F32, ns::unit_name> F32##unit_name##Implicit;\
+	typedef LLUnit<F64, ns::unit_name> F64##unit_name;                  \
+	typedef LLUnitImplicit<F64, ns::unit_name> F64##unit_name##Implicit;\
+	typedef LLUnit<S32, ns::unit_name> S32##unit_name;                  \
+	typedef LLUnitImplicit<S32, ns::unit_name> S32##unit_name##Implicit;\
+	typedef LLUnit<S64, ns::unit_name> S64##unit_name;                  \
+	typedef LLUnitImplicit<S64, ns::unit_name> S64##unit_name##Implicit;\
+	typedef LLUnit<U32, ns::unit_name> U32##unit_name;                  \
+	typedef LLUnitImplicit<U32, ns::unit_name> U32##unit_name##Implicit;\
+	typedef LLUnit<U64, ns::unit_name> U64##unit_name;                  \
+	typedef LLUnitImplicit<U64, ns::unit_name> U64##unit_name##Implicit
+
 //
 // Unit declarations
 //
@@ -675,65 +717,10 @@ LL_DECLARE_DERIVED_UNIT(Kilobytes, * 1024,		Megabytes, "MB");
 LL_DECLARE_DERIVED_UNIT(Megabytes, * 1024,		Gigabytes, "GB");
 }
 
-typedef LLUnit<F32, LLUnits::Bytes>     F32Bytes;
-typedef LLUnit<F32, LLUnits::Kilobytes> F32Kilobytes;
-typedef LLUnit<F32, LLUnits::Megabytes> F32Megabytes;
-typedef LLUnit<F32, LLUnits::Gigabytes> F32Gigabytes;
-
-typedef LLUnitImplicit<F32, LLUnits::Bytes>     F32BytesImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Kilobytes> F32KilobytesImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Megabytes> F32MegabytesImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Gigabytes> F32GigabytesImplicit;
-
-typedef LLUnit<F64, LLUnits::Bytes>     F64Bytes;
-typedef LLUnit<F64, LLUnits::Kilobytes> F64Kilobytes;
-typedef LLUnit<F64, LLUnits::Megabytes> F64Megabytes;
-typedef LLUnit<F64, LLUnits::Gigabytes> F64Gigabytes;
-
-typedef LLUnitImplicit<F64, LLUnits::Bytes>     F64BytesImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Kilobytes> F64KilobytesImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Megabytes> F64MegabytesImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Gigabytes> F64GigabytesImplicit;
-
-typedef LLUnit<S32, LLUnits::Bytes>     S32Bytes;
-typedef LLUnit<S32, LLUnits::Kilobytes> S32Kilobytes;
-typedef LLUnit<S32, LLUnits::Megabytes> S32Megabytes;
-typedef LLUnit<S32, LLUnits::Gigabytes> S32Gigabytes;
-
-typedef LLUnitImplicit<S32, LLUnits::Bytes>     S32BytesImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Kilobytes> S32KilobytesImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Megabytes> S32MegabytesImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Gigabytes> S32GigabytesImplicit;
-
-typedef LLUnit<S64, LLUnits::Bytes>     S64Bytes;
-typedef LLUnit<S64, LLUnits::Kilobytes> S64Kilobytes;
-typedef LLUnit<S64, LLUnits::Megabytes> S64Megabytes;
-typedef LLUnit<S64, LLUnits::Gigabytes> S64Gigabytes;
-
-typedef LLUnitImplicit<S64, LLUnits::Bytes>     S64BytesImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Kilobytes> S64KilobytesImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Megabytes> S64MegabytesImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Gigabytes> S64GigabytesImplicit;
-
-typedef LLUnit<U32, LLUnits::Bytes>     U32Bytes;
-typedef LLUnit<U32, LLUnits::Kilobytes> U32Kilobytes;
-typedef LLUnit<U32, LLUnits::Megabytes> U32Megabytes;
-typedef LLUnit<U32, LLUnits::Gigabytes> U32Gigabytes;
-
-typedef LLUnitImplicit<U32, LLUnits::Bytes>     U32BytesImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Kilobytes> U32KilobytesImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Megabytes> U32MegabytesImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Gigabytes> U32GigabytesImplicit;
-
-typedef LLUnit<U64, LLUnits::Bytes>     U64Bytes;
-typedef LLUnit<U64, LLUnits::Kilobytes> U64Kilobytes;
-typedef LLUnit<U64, LLUnits::Megabytes> U64Megabytes;
-typedef LLUnit<U64, LLUnits::Gigabytes> U64Gigabytes;
-
-typedef LLUnitImplicit<U64, LLUnits::Bytes>     U64BytesImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Kilobytes> U64KilobytesImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Megabytes> U64MegabytesImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Gigabytes> U64GigabytesImplicit;
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bytes);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobytes);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabytes);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabytes);
 
 namespace LLUnits
 {
@@ -744,65 +731,10 @@ LL_DECLARE_DERIVED_UNIT(Kilobits, * 1024,		Megabits, "Mb");
 LL_DECLARE_DERIVED_UNIT(Megabits, * 1024,		Gigabits, "Gb");
 }
 
-typedef LLUnit<F32, LLUnits::Bits>     F32Bits;
-typedef LLUnit<F32, LLUnits::Kilobits> F32Kilobits;
-typedef LLUnit<F32, LLUnits::Megabits> F32Megabits;
-typedef LLUnit<F32, LLUnits::Gigabits> F32Gigabits;
-
-typedef LLUnitImplicit<F32, LLUnits::Bits>     F32BitsImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Kilobits> F32KilobitsImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Megabits> F32MegabitsImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Gigabits> F32GigabitsImplicit;
-
-typedef LLUnit<F64, LLUnits::Bits>     F64Bits;
-typedef LLUnit<F64, LLUnits::Kilobits> F64Kilobits;
-typedef LLUnit<F64, LLUnits::Megabits> F64Megabits;
-typedef LLUnit<F64, LLUnits::Gigabits> F64Gigabits;
-
-typedef LLUnitImplicit<F64, LLUnits::Bits>     F64BitsImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Kilobits> F64KilobitsImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Megabits> F64MegabitsImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Gigabits> F64GigabitsImplicit;
-
-typedef LLUnit<S32, LLUnits::Bits>     S32Bits;
-typedef LLUnit<S32, LLUnits::Kilobits> S32Kilobits;
-typedef LLUnit<S32, LLUnits::Megabits> S32Megabits;
-typedef LLUnit<S32, LLUnits::Gigabits> S32Gigabits;
-
-typedef LLUnitImplicit<S32, LLUnits::Bits>     S32BitsImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Kilobits> S32KilobitsImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Megabits> S32MegabitsImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Gigabits> S32GigabitsImplicit;
-
-typedef LLUnit<S64, LLUnits::Bits>     S64Bits;
-typedef LLUnit<S64, LLUnits::Kilobits> S64Kilobits;
-typedef LLUnit<S64, LLUnits::Megabits> S64Megabits;
-typedef LLUnit<S64, LLUnits::Gigabits> S64Gigabits;
-
-typedef LLUnitImplicit<S64, LLUnits::Bits>     S64BitsImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Kilobits> S64KilobitsImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Megabits> S64MegabitsImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Gigabits> S64GigabitsImplicit;
-
-typedef LLUnit<U32, LLUnits::Bits>     U32Bits;
-typedef LLUnit<U32, LLUnits::Kilobits> U32Kilobits;
-typedef LLUnit<U32, LLUnits::Megabits> U32Megabits;
-typedef LLUnit<U32, LLUnits::Gigabits> U32Gigabits;
-
-typedef LLUnitImplicit<U32, LLUnits::Bits>     U32BitsImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Kilobits> U32KilobitsImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Megabits> U32MegabitsImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Gigabits> U32GigabitsImplicit;
-
-typedef LLUnit<U64, LLUnits::Bits>     U64Bits;
-typedef LLUnit<U64, LLUnits::Kilobits> U64Kilobits;
-typedef LLUnit<U64, LLUnits::Megabits> U64Megabits;
-typedef LLUnit<U64, LLUnits::Gigabits> U64Gigabits;
-
-typedef LLUnitImplicit<U64, LLUnits::Bits>     U64BitsImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Kilobits> U64KilobitsImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Megabits> U64MegabitsImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Gigabits> U64GigabitsImplicit;
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bits);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobits);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabits);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabits);
 
 namespace LLUnits
 {
@@ -815,101 +747,13 @@ LL_DECLARE_DERIVED_UNIT(Milliseconds, / 1000,	Microseconds, "\x09\x3cs");
 LL_DECLARE_DERIVED_UNIT(Microseconds, / 1000,	Nanoseconds, "ns");
 }
 
-typedef LLUnit<F32, LLUnits::Seconds>      F32Seconds;
-typedef LLUnit<F32, LLUnits::Minutes>      F32Minutes;
-typedef LLUnit<F32, LLUnits::Hours>        F32Hours;
-typedef LLUnit<F32, LLUnits::Days>         F32Days;
-typedef LLUnit<F32, LLUnits::Milliseconds> F32Milliseconds;
-typedef LLUnit<F32, LLUnits::Microseconds> F32Microseconds;
-typedef LLUnit<F32, LLUnits::Nanoseconds>  F32Nanoseconds;
-
-typedef LLUnitImplicit<F32, LLUnits::Seconds>      F32SecondsImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Minutes>      F32MinutesImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Hours>        F32HoursImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Days>         F32DaysImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Milliseconds> F32MillisecondsImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Microseconds> F32MicrosecondsImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Nanoseconds>  F32NanosecondsImplicit;
-
-typedef LLUnit<F64, LLUnits::Seconds>      F64Seconds;
-typedef LLUnit<F64, LLUnits::Minutes>      F64Minutes;
-typedef LLUnit<F64, LLUnits::Hours>        F64Hours;
-typedef LLUnit<F64, LLUnits::Days>         F64Days;
-typedef LLUnit<F64, LLUnits::Milliseconds> F64Milliseconds;
-typedef LLUnit<F64, LLUnits::Microseconds> F64Microseconds;
-typedef LLUnit<F64, LLUnits::Nanoseconds>  F64Nanoseconds;
-
-typedef LLUnitImplicit<F64, LLUnits::Seconds>      F64SecondsImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Minutes>      F64MinutesImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Hours>        F64HoursImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Days>         F64DaysImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Milliseconds> F64MillisecondsImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Microseconds> F64MicrosecondsImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Nanoseconds>  F64NanosecondsImplicit;
-
-typedef LLUnit<S32, LLUnits::Seconds>      S32Seconds;
-typedef LLUnit<S32, LLUnits::Minutes>      S32Minutes;
-typedef LLUnit<S32, LLUnits::Hours>        S32Hours;
-typedef LLUnit<S32, LLUnits::Days>         S32Days;
-typedef LLUnit<S32, LLUnits::Milliseconds> S32Milliseconds;
-typedef LLUnit<S32, LLUnits::Microseconds> S32Microseconds;
-typedef LLUnit<S32, LLUnits::Nanoseconds>  S32Nanoseconds;
-
-typedef LLUnitImplicit<S32, LLUnits::Seconds>      S32SecondsImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Minutes>      S32MinutesImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Hours>        S32HoursImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Days>         S32DaysImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Milliseconds> S32MillisecondsImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Microseconds> S32MicrosecondsImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Nanoseconds>  S32NanosecondsImplicit;
-
-typedef LLUnit<S64, LLUnits::Seconds>      S64Seconds;
-typedef LLUnit<S64, LLUnits::Minutes>      S64Minutes;
-typedef LLUnit<S64, LLUnits::Hours>        S64Hours;
-typedef LLUnit<S64, LLUnits::Days>         S64Days;
-typedef LLUnit<S64, LLUnits::Milliseconds> S64Milliseconds;
-typedef LLUnit<S64, LLUnits::Microseconds> S64Microseconds;
-typedef LLUnit<S64, LLUnits::Nanoseconds>  S64Nanoseconds;
-
-typedef LLUnitImplicit<S64, LLUnits::Seconds>      S64SecondsImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Minutes>      S64MinutesImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Hours>        S64HoursImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Days>         S64DaysImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Milliseconds> S64MillisecondsImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Microseconds> S64MicrosecondsImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Nanoseconds>  S64NanosecondsImplicit;
-
-typedef LLUnit<U32, LLUnits::Seconds>      U32Seconds;
-typedef LLUnit<U32, LLUnits::Minutes>      U32Minutes;
-typedef LLUnit<U32, LLUnits::Hours>        U32Hours;
-typedef LLUnit<U32, LLUnits::Days>         U32Days;
-typedef LLUnit<U32, LLUnits::Milliseconds> U32Milliseconds;
-typedef LLUnit<U32, LLUnits::Microseconds> U32Microseconds;
-typedef LLUnit<U32, LLUnits::Nanoseconds>  U32Nanoseconds;
-
-typedef LLUnitImplicit<U32, LLUnits::Seconds>      U32SecondsImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Minutes>      U32MinutesImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Hours>        U32HoursImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Days>         U32DaysImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Milliseconds> U32MillisecondsImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Microseconds> U32MicrosecondsImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Nanoseconds>  U32NanosecondsImplicit;
-
-typedef LLUnit<U64, LLUnits::Seconds>      U64Seconds;
-typedef LLUnit<U64, LLUnits::Minutes>      U64Minutes;
-typedef LLUnit<U64, LLUnits::Hours>        U64Hours;
-typedef LLUnit<U64, LLUnits::Days>         U64Days;
-typedef LLUnit<U64, LLUnits::Milliseconds> U64Milliseconds;
-typedef LLUnit<U64, LLUnits::Microseconds> U64Microseconds;
-typedef LLUnit<U64, LLUnits::Nanoseconds>  U64Nanoseconds;
-
-typedef LLUnitImplicit<U64, LLUnits::Seconds>      U64SecondsImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Minutes>      U64MinutesImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Hours>        U64HoursImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Days>         U64DaysImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Milliseconds> U64MillisecondsImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Microseconds> U64MicrosecondsImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Nanoseconds>  U64NanosecondsImplicit;
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Seconds);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Minutes);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hours);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Days);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Milliseconds);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Microseconds);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Nanoseconds);
 
 namespace LLUnits
 {
@@ -919,65 +763,10 @@ LL_DECLARE_DERIVED_UNIT(Meters, / 100,			Centimeters, "cm");
 LL_DECLARE_DERIVED_UNIT(Meters, / 1000,			Millimeters, "mm");
 }
 
-typedef LLUnit<F32, LLUnits::Meters>      F32Meters;
-typedef LLUnit<F32, LLUnits::Kilometers>  F32Kilometers;
-typedef LLUnit<F32, LLUnits::Centimeters> F32Centimeters;
-typedef LLUnit<F32, LLUnits::Millimeters> F32Millimeters;
-
-typedef LLUnitImplicit<F32, LLUnits::Meters>      F32MetersImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Kilometers>  F32KilometersImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Centimeters> F32CentimetersImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Millimeters> F32MillimetersImplicit;
-
-typedef LLUnit<F64, LLUnits::Meters>      F64Meters;
-typedef LLUnit<F64, LLUnits::Kilometers>  F64Kilometers;
-typedef LLUnit<F64, LLUnits::Centimeters> F64Centimeters;
-typedef LLUnit<F64, LLUnits::Millimeters> F64Millimeters;
-
-typedef LLUnitImplicit<F64, LLUnits::Meters>      F64MetersImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Kilometers>  F64KilometersImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Centimeters> F64CentimetersImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Millimeters> F64MillimetersImplicit;
-
-typedef LLUnit<S32, LLUnits::Meters>      S32Meters;
-typedef LLUnit<S32, LLUnits::Kilometers>  S32Kilometers;
-typedef LLUnit<S32, LLUnits::Centimeters> S32Centimeters;
-typedef LLUnit<S32, LLUnits::Millimeters> S32Millimeters;
-
-typedef LLUnitImplicit<S32, LLUnits::Meters>      S32MetersImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Kilometers>  S32KilometersImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Centimeters> S32CentimetersImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Millimeters> S32MillimetersImplicit;
-
-typedef LLUnit<S64, LLUnits::Meters>      S64Meters;
-typedef LLUnit<S64, LLUnits::Kilometers>  S64Kilometers;
-typedef LLUnit<S64, LLUnits::Centimeters> S64Centimeters;
-typedef LLUnit<S64, LLUnits::Millimeters> S64Millimeters;
-
-typedef LLUnitImplicit<S64, LLUnits::Meters>      S64MetersImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Kilometers>  S64KilometersImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Centimeters> S64CentimetersImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Millimeters> S64MillimetersImplicit;
-
-typedef LLUnit<U32, LLUnits::Meters>      U32Meters;
-typedef LLUnit<U32, LLUnits::Kilometers>  U32Kilometers;
-typedef LLUnit<U32, LLUnits::Centimeters> U32Centimeters;
-typedef LLUnit<U32, LLUnits::Millimeters> U32Millimeters;
-
-typedef LLUnitImplicit<U32, LLUnits::Meters>      U32MetersImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Kilometers>  U32KilometersImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Centimeters> U32CentimetersImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Millimeters> U32MillimetersImplicit;
-
-typedef LLUnit<U64, LLUnits::Meters>      U64Meters;
-typedef LLUnit<U64, LLUnits::Kilometers>  U64Kilometers;
-typedef LLUnit<U64, LLUnits::Centimeters> U64Centimeters;
-typedef LLUnit<U64, LLUnits::Millimeters> U64Millimeters;
-
-typedef LLUnitImplicit<U64, LLUnits::Meters>      U64MetersImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Kilometers>  U64KilometersImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Centimeters> U64CentimetersImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Millimeters> U64MillimetersImplicit;
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Meters);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilometers);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Centimeters);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Millimeters);
 
 namespace LLUnits
 {
@@ -999,136 +788,16 @@ LL_DECLARE_DERIVED_UNIT(Triangles, * 1000,		Kilotriangles, "ktris");
 } // namespace LLUnits
 
 // rare units
-typedef LLUnit<F32, LLUnits::Hertz>			F32Hertz;
-typedef LLUnit<F32, LLUnits::Kilohertz>		F32Kilohertz;
-typedef LLUnit<F32, LLUnits::Megahertz>		F32Megahertz;
-typedef LLUnit<F32, LLUnits::Gigahertz>		F32Gigahertz;
-typedef LLUnit<F32, LLUnits::Radians>		F32Radians;
-typedef LLUnit<F32, LLUnits::Degrees>		F32Degrees;
-typedef LLUnit<F32, LLUnits::Percent>		F32Percent;
-typedef LLUnit<F32, LLUnits::Ratio>			F32Ratio;
-typedef LLUnit<F32, LLUnits::Triangles>		F32Triangles;
-typedef LLUnit<F32, LLUnits::Kilotriangles>	F32KiloTriangles;
-
-typedef LLUnitImplicit<F32, LLUnits::Hertz>			F32HertzImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Kilohertz>		F32KilohertzImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Megahertz>		F32MegahertzImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Gigahertz>		F32GigahertzImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Radians>		F32RadiansImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Degrees>		F32DegreesImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Percent>		F32PercentImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Ratio>			F32RatioImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Triangles>		F32TrianglesImplicit;
-typedef LLUnitImplicit<F32, LLUnits::Kilotriangles>	F32KiloTrianglesImplicit;
-
-typedef LLUnit<F64, LLUnits::Hertz>			F64Hertz;
-typedef LLUnit<F64, LLUnits::Kilohertz>		F64Kilohertz;
-typedef LLUnit<F64, LLUnits::Megahertz>		F64Megahertz;
-typedef LLUnit<F64, LLUnits::Gigahertz>		F64Gigahertz;
-typedef LLUnit<F64, LLUnits::Radians>		F64Radians;
-typedef LLUnit<F64, LLUnits::Degrees>		F64Degrees;
-typedef LLUnit<F64, LLUnits::Percent>		F64Percent;
-typedef LLUnit<F64, LLUnits::Ratio>			F64Ratio;
-typedef LLUnit<F64, LLUnits::Triangles>		F64Triangles;
-typedef LLUnit<F64, LLUnits::Kilotriangles>	F64KiloTriangles;
-
-typedef LLUnitImplicit<F64, LLUnits::Hertz>			F64HertzImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Kilohertz>		F64KilohertzImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Megahertz>		F64MegahertzImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Gigahertz>		F64GigahertzImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Radians>		F64RadiansImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Degrees>		F64DegreesImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Percent>		F64PercentImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Ratio>			F64RatioImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Triangles>		F64TrianglesImplicit;
-typedef LLUnitImplicit<F64, LLUnits::Kilotriangles>	F64KiloTrianglesImplicit;
-
-typedef LLUnit<S32, LLUnits::Hertz>			S32Hertz;
-typedef LLUnit<S32, LLUnits::Kilohertz>		S32Kilohertz;
-typedef LLUnit<S32, LLUnits::Megahertz>		S32Megahertz;
-typedef LLUnit<S32, LLUnits::Gigahertz>		S32Gigahertz;
-typedef LLUnit<S32, LLUnits::Radians>		S32Radians;
-typedef LLUnit<S32, LLUnits::Degrees>		S32Degrees;
-typedef LLUnit<S32, LLUnits::Percent>		S32Percent;
-typedef LLUnit<S32, LLUnits::Ratio>			S32Ratio;
-typedef LLUnit<S32, LLUnits::Triangles>		S32Triangles;
-typedef LLUnit<S32, LLUnits::Kilotriangles>	S32KiloTriangles;
-
-typedef LLUnitImplicit<S32, LLUnits::Hertz>			S32HertzImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Kilohertz>		S32KilohertzImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Megahertz>		S32MegahertzImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Gigahertz>		S32GigahertzImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Radians>		S32RadiansImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Degrees>		S32DegreesImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Percent>		S32PercentImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Ratio>			S32RatioImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Triangles>		S32TrianglesImplicit;
-typedef LLUnitImplicit<S32, LLUnits::Kilotriangles>	S32KiloTrianglesImplicit;
-
-typedef LLUnit<S64, LLUnits::Hertz>			S64Hertz;
-typedef LLUnit<S64, LLUnits::Kilohertz>		S64Kilohertz;
-typedef LLUnit<S64, LLUnits::Megahertz>		S64Megahertz;
-typedef LLUnit<S64, LLUnits::Gigahertz>		S64Gigahertz;
-typedef LLUnit<S64, LLUnits::Radians>		S64Radians;
-typedef LLUnit<S64, LLUnits::Degrees>		S64Degrees;
-typedef LLUnit<S64, LLUnits::Percent>		S64Percent;
-typedef LLUnit<S64, LLUnits::Ratio>			S64Ratio;
-typedef LLUnit<S64, LLUnits::Triangles>		S64Triangles;
-typedef LLUnit<S64, LLUnits::Kilotriangles>	S64KiloTriangles;
-
-typedef LLUnitImplicit<S64, LLUnits::Hertz>			S64HertzImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Kilohertz>		S64KilohertzImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Megahertz>		S64MegahertzImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Gigahertz>		S64GigahertzImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Radians>		S64RadiansImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Degrees>		S64DegreesImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Percent>		S64PercentImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Ratio>			S64RatioImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Triangles>		S64TrianglesImplicit;
-typedef LLUnitImplicit<S64, LLUnits::Kilotriangles>	S64KiloTrianglesImplicit;
-
-typedef LLUnit<U32, LLUnits::Hertz>			U32Hertz;
-typedef LLUnit<U32, LLUnits::Kilohertz>		U32Kilohertz;
-typedef LLUnit<U32, LLUnits::Megahertz>		U32Megahertz;
-typedef LLUnit<U32, LLUnits::Gigahertz>		U32Gigahertz;
-typedef LLUnit<U32, LLUnits::Radians>		U32Radians;
-typedef LLUnit<U32, LLUnits::Degrees>		U32Degrees;
-typedef LLUnit<U32, LLUnits::Percent>		U32Percent;
-typedef LLUnit<U32, LLUnits::Ratio>			U32Ratio;
-typedef LLUnit<U32, LLUnits::Triangles>		U32Triangles;
-typedef LLUnit<U32, LLUnits::Kilotriangles>	U32KiloTriangles;
-
-typedef LLUnitImplicit<U32, LLUnits::Hertz>			U32HertzImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Kilohertz>		U32KilohertzImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Megahertz>		U32MegahertzImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Gigahertz>		U32GigahertzImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Radians>		U32RadiansImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Degrees>		U32DegreesImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Percent>		U32PercentImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Ratio>			U32RatioImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Triangles>		U32TrianglesImplicit;
-typedef LLUnitImplicit<U32, LLUnits::Kilotriangles>	U32KiloTrianglesImplicit;
-
-typedef LLUnit<U64, LLUnits::Hertz>			U64Hertz;
-typedef LLUnit<U64, LLUnits::Kilohertz>		U64Kilohertz;
-typedef LLUnit<U64, LLUnits::Megahertz>		U64Megahertz;
-typedef LLUnit<U64, LLUnits::Gigahertz>		U64Gigahertz;
-typedef LLUnit<U64, LLUnits::Radians>		U64Radians;
-typedef LLUnit<U64, LLUnits::Degrees>		U64Degrees;
-typedef LLUnit<U64, LLUnits::Percent>		U64Percent;
-typedef LLUnit<U64, LLUnits::Ratio>			U64Ratio;
-typedef LLUnit<U64, LLUnits::Triangles>		U64Triangles;
-typedef LLUnit<U64, LLUnits::Kilotriangles>	U64KiloTriangles;
-
-typedef LLUnitImplicit<U64, LLUnits::Hertz>			U64HertzImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Kilohertz>		U64KilohertzImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Megahertz>		U64MegahertzImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Gigahertz>		U64GigahertzImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Radians>		U64RadiansImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Degrees>		U64DegreesImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Percent>		U64PercentImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Ratio>			U64RatioImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Triangles>		U64TrianglesImplicit;
-typedef LLUnitImplicit<U64, LLUnits::Kilotriangles>	U64KiloTrianglesImplicit;
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hertz);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilohertz);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megahertz);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigahertz);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Radians);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Degrees);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Percent);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Ratio);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Triangles);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilotriangles);
+
 
 #endif // LL_LLUNIT_H
-- 
cgit v1.2.3


From 6d9af374066421a1d8465a57795250a1614adcbb Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 20 Aug 2013 12:10:05 -0700
Subject: BUILDFIX: unit assignment error

---
 indra/llcommon/llmemory.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index d46e205500..4b21fa3bda 100755
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -131,8 +131,8 @@ void LLMemory::updateMemoryInfo()
 #else
 	//not valid for other systems for now.
 	sAllocatedMemInKB = (U32)(LLMemory::getCurrentRSS() / 1024) ;
-	sMaxPhysicalMemInKB = U32_MAX ;
-	sAvailPhysicalMemInKB = U32_MAX ;
+	sMaxPhysicalMemInKB = (U32Bytes)U32_MAX ;
+	sAvailPhysicalMemInKB = (U32Bytes)U32_MAX ;
 #endif
 
 	return ;
-- 
cgit v1.2.3


From 2c6bc5afa59a88136fd6de4ebf0cb99ea7cdef3f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 21 Aug 2013 14:06:57 -0700
Subject: SH-4433 WIP Interesting: Statistics > Ping Sim is always 0 ms made
 getPrimaryAccumulator return a reference since it was an always non-null
 pointer changed unit conversion to perform lazy division in order to avoid
 truncation of timer values

---
 indra/llcommon/llerror.h                 |   2 +
 indra/llcommon/llfasttimer.cpp           |  28 ++---
 indra/llcommon/llfasttimer.h             |  20 ++--
 indra/llcommon/llmemory.cpp              |   2 +-
 indra/llcommon/lltimer.cpp               |  92 +++++++++-------
 indra/llcommon/lltimer.h                 |   4 +-
 indra/llcommon/lltrace.cpp               |   2 +-
 indra/llcommon/lltrace.h                 | 100 ++++++-----------
 indra/llcommon/lltraceaccumulators.cpp   |  14 ++-
 indra/llcommon/lltraceaccumulators.h     |   3 +
 indra/llcommon/lltracethreadrecorder.cpp |   6 +-
 indra/llcommon/llunit.h                  | 180 +++++++++++++++++--------------
 indra/llcommon/tests/llunits_test.cpp    |  23 ++--
 13 files changed, 249 insertions(+), 227 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index af76a7653a..6eaab450ed 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -346,6 +346,8 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 #define LL_INFOS(...)	lllog(LLError::LEVEL_INFO, false, ##__VA_ARGS__)
 #define LL_WARNS(...)	lllog(LLError::LEVEL_WARN, false, ##__VA_ARGS__)
 #define LL_ERRS(...)	lllog(LLError::LEVEL_ERROR, false, ##__VA_ARGS__)
+// alternative to llassert_always that prints explanatory message
+#define LL_ERRS_IF(exp, ...)	if (exp) LL_ERRS(##__VA_ARGS__) << "(" #exp ")"
 
 // Only print the log message once (good for warnings or infos that would otherwise
 // spam the log file over and over, such as tighter loops).
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index d99c4c990e..ae3234a87a 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -189,15 +189,15 @@ void TimeBlock::bootstrapTimerTree()
 		// when this timer was called
 		if (timer.getParent() == &TimeBlock::getRootTimeBlock())
 		{
-			TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
+			TimeBlockAccumulator& accumulator = timer.getPrimaryAccumulator();
 
-			if (accumulator->mLastCaller)
+			if (accumulator.mLastCaller)
 			{
-				timer.setParent(accumulator->mLastCaller);
-				accumulator->mParent = accumulator->mLastCaller;
+				timer.setParent(accumulator.mLastCaller);
+				accumulator.mParent = accumulator.mLastCaller;
 			}
 			// no need to push up tree on first use, flag can be set spuriously
-			accumulator->mMoveUpTree = false;
+			accumulator.mMoveUpTree = false;
 		}
 	}
 }
@@ -223,17 +223,17 @@ void TimeBlock::incrementalUpdateTimerTree()
 		// skip root timer
 		if (timerp != &TimeBlock::getRootTimeBlock())
 		{
-			TimeBlockAccumulator* accumulator = timerp->getPrimaryAccumulator();
+			TimeBlockAccumulator& accumulator = timerp->getPrimaryAccumulator();
 
-			if (accumulator->mMoveUpTree)
+			if (accumulator.mMoveUpTree)
 			{
 				// since ancestors have already been visited, re-parenting 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());
-				accumulator->mParent = timerp->getParent();
-				accumulator->mMoveUpTree = false;
+				accumulator.mParent = timerp->getParent();
+				accumulator.mMoveUpTree = false;
 
 				// don't bubble up any ancestors until descendants are done bubbling up
 				// as ancestors may call this timer only on certain paths, so we want to resolve
@@ -253,7 +253,7 @@ void TimeBlock::updateTimes()
 
 	U64 cur_time = getCPUClockCount64();
 	BlockTimer* cur_timer				= stack_record->mActiveTimer;
-	TimeBlockAccumulator* accumulator	= stack_record->mTimeBlock->getPrimaryAccumulator();
+	TimeBlockAccumulator* accumulator	= &stack_record->mTimeBlock->getPrimaryAccumulator();
 
 	while(cur_timer 
 		&& cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self
@@ -269,7 +269,7 @@ void TimeBlock::updateTimes()
 		cur_timer->mBlockStartTotalTimeCounter = accumulator->mTotalTimeCounter;
 
 		stack_record = &cur_timer->mParentTimerData;
-		accumulator  = stack_record->mTimeBlock->getPrimaryAccumulator();
+		accumulator  = &stack_record->mTimeBlock->getPrimaryAccumulator();
 		cur_timer    = stack_record->mActiveTimer;
 
 		stack_record->mChildTime += cumulative_time_delta;
@@ -299,10 +299,10 @@ void TimeBlock::processTimes()
 		++it)
 	{
 		TimeBlock& timer = *it;
-		TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
+		TimeBlockAccumulator& accumulator = timer.getPrimaryAccumulator();
 
-		accumulator->mLastCaller = NULL;
-		accumulator->mMoveUpTree = false;
+		accumulator.mLastCaller = NULL;
+		accumulator.mMoveUpTree = false;
 	}
 }
 
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index ccf71c3f4c..7bad6134c5 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -257,11 +257,11 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 #if FAST_TIMER_ON
 	BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
 	if (!cur_timer_data) return;
-	TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator();
-	accumulator->mActiveCount++;
-	mBlockStartTotalTimeCounter = accumulator->mTotalTimeCounter;
+	TimeBlockAccumulator& accumulator = timer.getPrimaryAccumulator();
+	accumulator.mActiveCount++;
+	mBlockStartTotalTimeCounter = accumulator.mTotalTimeCounter;
 	// keep current parent as long as it is active when we are
-	accumulator->mMoveUpTree |= (accumulator->mParent->getPrimaryAccumulator()->mActiveCount == 0);
+	accumulator.mMoveUpTree |= (accumulator.mParent->getPrimaryAccumulator().mActiveCount == 0);
 
 	// store top of stack
 	mParentTimerData = *cur_timer_data;
@@ -281,16 +281,16 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 	BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
 	if (!cur_timer_data) return;
 
-	TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
+	TimeBlockAccumulator& accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
 
-	accumulator->mCalls++;
-	accumulator->mTotalTimeCounter += total_time - (accumulator->mTotalTimeCounter - mBlockStartTotalTimeCounter);
-	accumulator->mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
-	accumulator->mActiveCount--;
+	accumulator.mCalls++;
+	accumulator.mTotalTimeCounter += total_time - (accumulator.mTotalTimeCounter - mBlockStartTotalTimeCounter);
+	accumulator.mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
+	accumulator.mActiveCount--;
 
 	// store last caller to bootstrap tree creation
 	// do this in the destructor in case of recursion to get topmost caller
-	accumulator->mLastCaller = mParentTimerData.mTimeBlock;
+	accumulator.mLastCaller = mParentTimerData.mTimeBlock;
 
 	// we are only tracking self time, so subtract our total time delta from parents
 	mParentTimerData.mChildTime += total_time;
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index 4b21fa3bda..06334c012a 100755
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -130,7 +130,7 @@ void LLMemory::updateMemoryInfo()
 	}
 #else
 	//not valid for other systems for now.
-	sAllocatedMemInKB = (U32)(LLMemory::getCurrentRSS() / 1024) ;
+	sAllocatedMemInKB = (U32Bytes)LLMemory::getCurrentRSS();
 	sMaxPhysicalMemInKB = (U32Bytes)U32_MAX ;
 	sAvailPhysicalMemInKB = (U32Bytes)U32_MAX ;
 #endif
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index da9d2b646c..9baac20be9 100755
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -55,11 +55,6 @@ const F64 USEC_TO_SEC_F64 = 0.000001;
 S32 gUTCOffset = 0; // viewer's offset from server UTC, in seconds
 LLTimer* LLTimer::sTimer = NULL;
 
-F64 gClockFrequency = 0.0;
-F64 gClockFrequencyInv = 0.0;
-F64 gClocksToMicroseconds = 0.0;
-U64 gTotalTimeClockCount = 0;
-U64 gLastTotalTimeClockCount = 0;
 
 //
 // Forward declarations
@@ -213,56 +208,76 @@ U64 get_clock_count()
 #endif
 
 
-void update_clock_frequencies()
+struct TimerInfo
 {
-	gClockFrequency = calc_clock_frequency(50U);
-	gClockFrequencyInv = 1.0/gClockFrequency;
-	gClocksToMicroseconds = gClockFrequencyInv * SEC_TO_MICROSEC;
-}
+	TimerInfo()
+	:	mClockFrequency(0.0),
+		mTotalTimeClockCount(0),
+		mLastTotalTimeClockCount(0)
+	{}
+
+	void update()
+	{
+		mClockFrequency = calc_clock_frequency(50U);
+		mClockFrequencyInv = 1.0/mClockFrequency;
+		mClocksToMicroseconds = mClockFrequencyInv;
+	}
+	F64						mClockFrequency;
+	F64SecondsImplicit		mClockFrequencyInv;
+	F64MicrosecondsImplicit	mClocksToMicroseconds;
+	U64						mTotalTimeClockCount;
+	U64						mLastTotalTimeClockCount;
+};
 
+TimerInfo& get_timer_info()
+{
+	static TimerInfo sTimerInfo;
+	return sTimerInfo;
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 
 // returns a U64 number that represents the number of 
-// microseconds since the unix epoch - Jan 1, 1970
+// microseconds since the Unix epoch - Jan 1, 1970
 U64MicrosecondsImplicit totalTime()
 {
 	U64 current_clock_count = get_clock_count();
-	if (!gTotalTimeClockCount)
+	if (!get_timer_info().mTotalTimeClockCount || get_timer_info().mClocksToMicroseconds.value() == 0)
 	{
-		update_clock_frequencies();
-		gTotalTimeClockCount = current_clock_count;
+		get_timer_info().update();
+		get_timer_info().mTotalTimeClockCount = current_clock_count;
 
 #if LL_WINDOWS
-		// Synch us up with local time (even though we PROBABLY don't need to, this is how it was implemented)
+		// Sync us up with local time (even though we PROBABLY don't need to, this is how it was implemented)
 		// Unix platforms use gettimeofday so they are synced, although this probably isn't a good assumption to
 		// make in the future.
 
-		gTotalTimeClockCount = (U64)(time(NULL) * gClockFrequency);
+		get_timer_info().mTotalTimeClockCount = (U64)(time(NULL) * get_timer_info().mClockFrequency);
 #endif
 
 		// Update the last clock count
-		gLastTotalTimeClockCount = current_clock_count;
+		get_timer_info().mLastTotalTimeClockCount = current_clock_count;
 	}
 	else
 	{
-		if (current_clock_count >= gLastTotalTimeClockCount)
+		if (current_clock_count >= get_timer_info().mLastTotalTimeClockCount)
 		{
 			// No wrapping, we're all okay.
-			gTotalTimeClockCount += current_clock_count - gLastTotalTimeClockCount;
+			get_timer_info().mTotalTimeClockCount += current_clock_count - get_timer_info().mLastTotalTimeClockCount;
 		}
 		else
 		{
 			// We've wrapped.  Compensate correctly
-			gTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - gLastTotalTimeClockCount) + current_clock_count;
+			get_timer_info().mTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - get_timer_info().mLastTotalTimeClockCount) + current_clock_count;
 		}
 
 		// Update the last clock count
-		gLastTotalTimeClockCount = current_clock_count;
+		get_timer_info().mLastTotalTimeClockCount = current_clock_count;
 	}
 
 	// Return the total clock tick count in microseconds.
-	return U64Microseconds(gTotalTimeClockCount*gClocksToMicroseconds);
+	U64Microseconds time(get_timer_info().mTotalTimeClockCount*get_timer_info().mClocksToMicroseconds);
+	return time;
 }
 
 
@@ -270,9 +285,9 @@ U64MicrosecondsImplicit totalTime()
 
 LLTimer::LLTimer()
 {
-	if (!gClockFrequency)
+	if (!get_timer_info().mClockFrequency)
 	{
-		update_clock_frequencies();
+		get_timer_info().update();
 	}
 
 	mStarted = TRUE;
@@ -298,13 +313,14 @@ void LLTimer::cleanupClass()
 U64MicrosecondsImplicit LLTimer::getTotalTime()
 {
 	// simply call into the implementation function.
-	return totalTime();
+	U64MicrosecondsImplicit total_time = totalTime();
+	return total_time;
 }	
 
 // static
 F64SecondsImplicit LLTimer::getTotalSeconds()
 {
-	return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64;
+	return F64Microseconds(U64_to_F64(getTotalTime()));
 }
 
 void LLTimer::reset()
@@ -354,7 +370,7 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount)
 F64SecondsImplicit LLTimer::getElapsedTimeF64() const
 {
 	U64 last = mLastClockCount;
-	return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv;
+	return (F64)getElapsedTimeAndUpdate(last) * get_timer_info().mClockFrequencyInv;
 }
 
 F32SecondsImplicit LLTimer::getElapsedTimeF32() const
@@ -364,7 +380,7 @@ F32SecondsImplicit LLTimer::getElapsedTimeF32() const
 
 F64SecondsImplicit LLTimer::getElapsedTimeAndResetF64()
 {
-	return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv;
+	return (F64)getElapsedTimeAndUpdate(mLastClockCount) * get_timer_info().mClockFrequencyInv;
 }
 
 F32SecondsImplicit LLTimer::getElapsedTimeAndResetF32()
@@ -377,7 +393,7 @@ F32SecondsImplicit LLTimer::getElapsedTimeAndResetF32()
 void  LLTimer::setTimerExpirySec(F32SecondsImplicit expiration)
 {
 	mExpirationTicks = get_clock_count()
-		+ (U64)((F32)(expiration * gClockFrequency));
+		+ (U64)((F32)(expiration * get_timer_info().mClockFrequency));
 }
 
 F32SecondsImplicit LLTimer::getRemainingTimeF32() const
@@ -387,7 +403,7 @@ F32SecondsImplicit LLTimer::getRemainingTimeF32() const
 	{
 		return 0.0f;
 	}
-	return F32((mExpirationTicks - cur_ticks) * gClockFrequencyInv);
+	return F32((mExpirationTicks - cur_ticks) * get_timer_info().mClockFrequencyInv);
 }
 
 
@@ -400,7 +416,7 @@ BOOL  LLTimer::checkExpirationAndReset(F32 expiration)
 	}
 
 	mExpirationTicks = cur_ticks
-		+ (U64)((F32)(expiration * gClockFrequency));
+		+ (U64)((F32)(expiration * get_timer_info().mClockFrequency));
 	return TRUE;
 }
 
@@ -499,20 +515,20 @@ BOOL is_daylight_savings()
 
 struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time)
 {
-	S32 pacific_offset_hours;
+	S32Hours pacific_offset_hours;
 	if (pacific_daylight_time)
 	{
-		pacific_offset_hours = 7;
+		pacific_offset_hours = S32Hours(7);
 	}
 	else
 	{
-		pacific_offset_hours = 8;
+		pacific_offset_hours = S32Hours(8);
 	}
 
 	// We subtract off the PST/PDT offset _before_ getting
 	// "UTC" time, because this will handle wrapping around
 	// for 5 AM UTC -> 10 PM PDT of the previous day.
-	utc_time -= pacific_offset_hours * MIN_PER_HOUR * SEC_PER_MIN;
+	utc_time -= S32SecondsImplicit(pacific_offset_hours);
  
 	// Internal buffer to PST/PDT (see above)
 	struct tm* internal_time = gmtime(&utc_time);
@@ -529,7 +545,7 @@ struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time)
 }
 
 
-void microsecondsToTimecodeString(U64 current_time, std::string& tcstring)
+void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring)
 {
 	U64 hours;
 	U64 minutes;
@@ -551,9 +567,9 @@ void microsecondsToTimecodeString(U64 current_time, std::string& tcstring)
 }
 
 
-void secondsToTimecodeString(F32 current_time, std::string& tcstring)
+void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring)
 {
-	microsecondsToTimecodeString((U64)((F64)(SEC_TO_MICROSEC*current_time)), tcstring);
+	microsecondsToTimecodeString(current_time, tcstring);
 }
 
 
diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h
index 12a453e897..8b3930e2fa 100755
--- a/indra/llcommon/lltimer.h
+++ b/indra/llcommon/lltimer.h
@@ -168,8 +168,8 @@ LL_COMMON_API BOOL is_daylight_savings();
 // struct tm* internal_time = utc_to_pacific_time(utc_time, gDaylight);
 LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time);
 
-LL_COMMON_API void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);
-LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstring);
+LL_COMMON_API void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring);
+LL_COMMON_API void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring);
 
 U64MicrosecondsImplicit LL_COMMON_API totalTime();					// Returns current system time in microseconds
 
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 436ad9a0a2..05422f9191 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -76,7 +76,7 @@ void TimeBlockTreeNode::setParent( TimeBlock* parent )
 	}
 
 	mParent = parent;
-	mBlock->getPrimaryAccumulator()->mParent = parent;
+	mBlock->getPrimaryAccumulator().mParent = parent;
 	parent_tree_node->mChildren.push_back(mBlock);
 	parent_tree_node->mNeedsSorting = true;
 }
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 1f86aadaba..bf8e950a8c 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -80,10 +80,10 @@ public:
 		mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot())
 	{}
 
-	LL_FORCE_INLINE ACCUMULATOR* getPrimaryAccumulator() const
+	LL_FORCE_INLINE ACCUMULATOR& getPrimaryAccumulator() const
 	{
 		ACCUMULATOR* accumulator_storage = AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage();
-		return &accumulator_storage[mAccumulatorIndex];
+		return accumulator_storage[mAccumulatorIndex];
 	}
 
 	size_t getIndex() const { return mAccumulatorIndex; }
@@ -137,7 +137,7 @@ template<typename T, typename VALUE_T>
 void record(EventStatHandle<T>& measurement, VALUE_T value)
 {
 	T converted_value(value);
-	measurement.getPrimaryAccumulator()->record(storage_value(converted_value));
+	measurement.getPrimaryAccumulator().record(storage_value(converted_value));
 }
 
 template <typename T = F64>
@@ -160,7 +160,7 @@ template<typename T, typename VALUE_T>
 void sample(SampleStatHandle<T>& measurement, VALUE_T value)
 {
 	T converted_value(value);
-	measurement.getPrimaryAccumulator()->sample(storage_value(converted_value));
+	measurement.getPrimaryAccumulator().sample(storage_value(converted_value));
 }
 
 template <typename T = F64>
@@ -183,7 +183,7 @@ template<typename T, typename VALUE_T>
 void add(CountStatHandle<T>& count, VALUE_T value)
 {
 	T converted_value(value);
-	count.getPrimaryAccumulator()->add(storage_value(converted_value));
+	count.getPrimaryAccumulator().add(storage_value(converted_value));
 }
 
 template<>
@@ -340,49 +340,37 @@ public:
 
 	void* operator new(size_t size) 
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
-		if (accumulator)
-		{
-			accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
-			accumulator->mAllocatedCount++;
-		}
+		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
+		accumulator.mAllocatedCount++;
 
 		return ::operator new(size);
 	}
 
 	void operator delete(void* ptr, size_t size)
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
-		if (accumulator)
-		{
-			accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
-			accumulator->mAllocatedCount--;
-			accumulator->mDeallocatedCount++;
-		}
+		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
+		accumulator.mAllocatedCount--;
+		accumulator.mDeallocatedCount++;
 		::operator delete(ptr);
 	}
 
 	void *operator new [](size_t size)
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
-		if (accumulator)
-		{
-			accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
-			accumulator->mAllocatedCount++;
-		}
+		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
+		accumulator.mAllocatedCount++;
 
 		return ::operator new[](size);
 	}
 
 	void operator delete[](void* ptr, size_t size)
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
-		if (accumulator)
-		{
-			accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
-			accumulator->mAllocatedCount--;
-			accumulator->mDeallocatedCount++;
-		}
+		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
+		accumulator.mAllocatedCount--;
+		accumulator.mDeallocatedCount++;
 		::operator delete[](ptr);
 	}
 
@@ -405,12 +393,9 @@ public:
 	template<typename AMOUNT_T>
 	AMOUNT_T& memClaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
 		mMemFootprint += (size_t)size;
-		if (accumulator)
-		{
-			accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size);
-		}
+		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 		return size;
 	}
 
@@ -432,11 +417,8 @@ public:
 	template<typename AMOUNT_T>
 	AMOUNT_T& memDisclaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
-		if (accumulator)
-		{
-			accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size);
-		}
+		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 		return size;
 	}
 
@@ -448,24 +430,18 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
-			if (accumulator)
-			{
-				size_t footprint = MemFootprint<TRACKED>::measure(tracked);
-				accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)footprint);
-				tracker.mMemFootprint += footprint;
-			}
+			MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
+			accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)footprint : (F64)footprint);
+			tracker.mMemFootprint += footprint;
 		}
 
 		static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
-			if (accumulator)
-			{
-				size_t footprint = MemFootprint<TRACKED>::measure(tracked);
-				accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)footprint);
-				tracker.mMemFootprint -= footprint;
-			}
+			MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
+			accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)footprint : -(F64)footprint);
+			tracker.mMemFootprint -= footprint;
 		}
 	};
 
@@ -474,20 +450,14 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
-			if (accumulator)
-			{
-				accumulator->mChildSize.sample(accumulator->mChildSize.getLastValue() + (F64)MemFootprint<TRACKED>::measure(tracked));
-			}
+			MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() + (F64)MemFootprint<TRACKED>::measure(tracked) : (F64)MemFootprint<TRACKED>::measure(tracked));
 		}
 
 		static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
-			if (accumulator)
-			{
-				accumulator->mChildSize.sample(accumulator->mChildSize.getLastValue() - (F64)MemFootprint<TRACKED>::measure(tracked));
-			}
+			MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() - (F64)MemFootprint<TRACKED>::measure(tracked) : -(F64)MemFootprint<TRACKED>::measure(tracked));
 		}
 	};
 };
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index 1fb68c8158..c79c102afd 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -114,10 +114,13 @@ void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other)
 
 void AccumulatorBufferGroup::sync()
 {
-	F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds();
+	if (isPrimary())
+	{
+		F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds();
 
-	mSamples.sync(time_stamp);
-	mMemStats.sync(time_stamp);
+		mSamples.sync(time_stamp);
+		mMemStats.sync(time_stamp);
+	}
 }
 
 void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppendType append_type )
@@ -144,6 +147,7 @@ void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppen
 
 		if (other.mTotalSamplingTime > epsilon)
 		{
+			llassert(mTotalSamplingTime > 0);
 			// combine variance (and hence standard deviation) of 2 different sized sample groups using
 			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
 			F64 n_1 = mTotalSamplingTime,
@@ -166,17 +170,16 @@ void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppen
 					/ (n_1 + n_2 - epsilon));
 			}
 
-			llassert(other.mTotalSamplingTime > 0);
 			F64 weight = mTotalSamplingTime / (mTotalSamplingTime + other.mTotalSamplingTime);
 			mNumSamples += other.mNumSamples;
 			mTotalSamplingTime += other.mTotalSamplingTime;
 			mMean = (mMean * weight) + (other.mMean * (1.0 - weight));
+			llassert(mMean < 0 || mMean >= 0);
 		}
 		if (append_type == SEQUENTIAL)
 		{
 			mLastValue = other.mLastValue;
 			mLastSampleTimeStamp = other.mLastSampleTimeStamp;
-			mHasValue = true;
 		}
 	}
 }
@@ -190,6 +193,7 @@ void SampleAccumulator::reset( const SampleAccumulator* other )
 	mMin = mLastValue;
 	mMax = mLastValue;
 	mMean = mLastValue;
+	LL_ERRS_IF(mHasValue && !(mMean < 0) && !(mMean >= 0)) << "Invalid mean after capturing value" << LL_ENDL;
 	mSumOfSquares = 0;
 	mLastSampleTimeStamp = LLTimer::getTotalSeconds();
 	mTotalSamplingTime = 0;
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index f9d223066d..d4ff4b8d71 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -1,3 +1,4 @@
+
 /** 
  * @file lltraceaccumulators.h
  * @brief Storage for accumulating statistics
@@ -317,6 +318,7 @@ namespace LLTrace
 				mMin = value;
 				mMax = value;
 				mMean = value;
+				llassert(mMean < 0 || mMean >= 0);
 				mLastSampleTimeStamp = time_stamp;
 			}
 			else
@@ -341,6 +343,7 @@ namespace LLTrace
 				mTotalSamplingTime += delta_time;
 				F64 old_mean = mMean;
 				mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean);
+				llassert(mMean < 0 || mMean >= 0);
 				mSumOfSquares += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
 			}
 			mLastSampleTimeStamp = time_stamp;
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 8c32e1568b..28470fb4c4 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -69,13 +69,13 @@ void ThreadRecorder::init()
 		tree_node.mBlock = &time_block;
 		tree_node.mParent = &root_time_block;
 
-		it->getPrimaryAccumulator()->mParent = &root_time_block;
+		it->getPrimaryAccumulator().mParent = &root_time_block;
 	}
 
 	mRootTimer = new BlockTimer(root_time_block);
 	timer_stack->mActiveTimer = mRootTimer;
 
-	TimeBlock::getRootTimeBlock().getPrimaryAccumulator()->mActiveCount = 1;
+	TimeBlock::getRootTimeBlock().getPrimaryAccumulator().mActiveCount = 1;
 }
 
 
@@ -247,8 +247,6 @@ void ThreadRecorder::pushToParent()
 		mThreadRecordingBuffers.reset();
 	}
 }
-	
-
 
 
 static LLFastTimer::DeclareTimer FTM_PULL_TRACE_DATA_FROM_CHILDREN("Pull child thread trace data");
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 8fb53dd94d..f42456fe72 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -156,7 +156,8 @@ struct LLUnit
 	static self_t convert(LLUnit<SOURCE_STORAGE, SOURCE_UNITS> v) 
 	{ 
 		self_t result;
-		ll_convert_units(v, result);
+		STORAGE_TYPE divisor = ll_convert_units(v, result);
+		result.mValue /= divisor;
 		return result;
 	}
 
@@ -193,7 +194,7 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
 
 	template<typename OTHER_STORAGE, typename OTHER_UNIT>
 	LLUnitImplicit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
-	:	base_t(convert(other))
+	:	base_t(other)
 	{}
 
 	// unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc)
@@ -209,6 +210,8 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
         base_t::mValue += value;
 	}
 
+	// this overload exists to explicitly catch use of another implicit unit
+	// without ambiguity between conversion to storage_t vs conversion to base_t
 	template<typename OTHER_STORAGE, typename OTHER_UNIT>
 	void operator += (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
 	{
@@ -221,6 +224,8 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
         base_t::mValue -= value;
 	}
 
+	// this overload exists to explicitly catch use of another implicit unit
+	// without ambiguity between conversion to storage_t vs conversion to base_t
 	template<typename OTHER_STORAGE, typename OTHER_UNIT>
 	void operator -= (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
 	{
@@ -246,35 +251,35 @@ std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNIT_TYP
 }
 
 template<typename S1, typename T1, typename S2, typename T2>
-LL_FORCE_INLINE void ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ...)
+LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ...)
 {
+	S2 divisor(1);
+
 	LL_STATIC_ASSERT((LLIsSameType<T1, T2>::value 
-		|| !LLIsSameType<T1, typename T1::base_unit_t>::value 
-		|| !LLIsSameType<T2, typename T2::base_unit_t>::value), "invalid conversion: incompatible units");
+						|| !LLIsSameType<T1, typename T1::base_unit_t>::value 
+						|| !LLIsSameType<T2, typename T2::base_unit_t>::value), 
+						"conversion requires compatible units");
 
-	if (LLIsSameType<T1, typename T1::base_unit_t>::value)
+	if (LLIsSameType<T1, T2>::value)
 	{
-		if (LLIsSameType<T2, typename T2::base_unit_t>::value)
-
-		{
-			// T1 and T2 fully reduced and equal...just copy
-			out = LLUnit<S2, T2>((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);
-		}
+		// T1 and T2 same type, just assign
+		out.value((S2)in.value());
 	}
-	else
+	else if (LLIsSameType<T2, typename T2::base_unit_t>::value)
 	{
 		// reduce T1
-		LLUnit<S1, typename T1::base_unit_t> new_in;
-		ll_convert_units(in, new_in);
-		ll_convert_units(new_in, out);
+		LLUnit<S2, typename T1::base_unit_t> new_in;
+		divisor *= (S2)ll_convert_units(in, new_in);
+		divisor *= (S2)ll_convert_units(new_in, out);
 	}
+	else
+	{
+		// reduce T2
+		LLUnit<S2, typename T2::base_unit_t> new_out;
+		divisor *= (S2)ll_convert_units(in, new_out);
+		divisor *= (S2)ll_convert_units(new_out, out);
+	}
+	return divisor;
 }
 
 template<typename T>
@@ -579,77 +584,86 @@ struct LLGetUnitLabel<LLUnit<STORAGE_T, T> >
 	static const char* getUnitLabel() { return T::getUnitLabel(); }
 };
 
-template<typename INPUT_TYPE, typename OUTPUT_TYPE>
+template<typename T>
 struct LLUnitLinearOps
 {
-	typedef LLUnitLinearOps<OUTPUT_TYPE, OUTPUT_TYPE> output_t;
+	typedef LLUnitLinearOps<T> self_t;
 
-	LLUnitLinearOps(INPUT_TYPE val) 
-	:	mInput (val)
+	LLUnitLinearOps(T val) 
+	:	mValue(val),
+		mDivisor(1)
 	{}
 
-	operator OUTPUT_TYPE() const { return (OUTPUT_TYPE)mInput; }
-	INPUT_TYPE mInput;
+	T mValue;
+	T mDivisor;
 
-	template<typename T>
-	output_t operator * (T other)
+	template<typename OTHER_T>
+	self_t operator * (OTHER_T other)
 	{
-		return typename LLResultTypeMultiply<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) * other;
+		return mValue * other;
 	}
 
-	template<typename T>
-	output_t operator / (T other)
+	template<typename OTHER_T>
+	self_t operator / (OTHER_T other)
 	{
-		return typename LLResultTypeDivide<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) / other;
+		mDivisor *= other;
+		return *this;
 	}
 
-	template<typename T>
-	output_t operator + (T other)
+	template<typename OTHER_T>
+	self_t operator + (OTHER_T other)
 	{
-		return typename LLResultTypeAdd<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) + other;
+		mValue += other;
+		return *this;
 	}
 
-	template<typename T>
-	output_t operator - (T other)
+	template<typename OTHER_T>
+	self_t operator - (OTHER_T other)
 	{
-		return typename LLResultTypeSubtract<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) - other;
+		mValue -= other;
+		return *this;
 	}
 };
 
-template<typename INPUT_TYPE, typename OUTPUT_TYPE>
+template<typename T>
 struct LLUnitInverseLinearOps
 {
-	typedef LLUnitInverseLinearOps<OUTPUT_TYPE, OUTPUT_TYPE> output_t;
+	typedef LLUnitInverseLinearOps<T> self_t;
 
-	LLUnitInverseLinearOps(INPUT_TYPE val) 
-	:	mInput(val)
+	LLUnitInverseLinearOps(T val) 
+	:	mValue(val),
+		mDivisor(1)
 	{}
 
-	operator OUTPUT_TYPE() const { return (OUTPUT_TYPE)mInput; }
-	INPUT_TYPE mInput;
+	T mValue;
+	T mDivisor;
 
-	template<typename T>
-	output_t operator * (T other)
+	template<typename OTHER_T>
+	self_t operator * (OTHER_T other)
 	{
-		return typename LLResultTypeDivide<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) / other;
+		mDivisor *= other;
+		return *this;
 	}
 
-	template<typename T>
-	output_t operator / (T other)
+	template<typename OTHER_T>
+	self_t operator / (OTHER_T other)
 	{
-		return typename LLResultTypeMultiply<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) * other;
+		mValue *= other;
+		return *this;
 	}
 
-	template<typename T>
-	output_t operator + (T other)
+	template<typename OTHER_T>
+	self_t operator + (OTHER_T other)
 	{
-		return typename LLResultTypeAdd<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) - other;
+		mValue -= other;
+		return *this;
 	}
 
-	template<typename T>
-	output_t operator - (T other)
+	template<typename OTHER_T>
+	self_t operator - (OTHER_T other)
 	{
-		return typename LLResultTypeSubtract<INPUT_TYPE, OUTPUT_TYPE>::type_t(mInput) + other;
+		mValue += other;
+		return *this;
 	}
 };
 
@@ -666,28 +680,32 @@ struct base_unit_name
 }
 
 
-#define LL_DECLARE_DERIVED_UNIT(base_unit_name, conversion_operation, unit_name, unit_label)	        \
-struct unit_name                                                                                        \
-{                                                                                                       \
-	typedef base_unit_name base_unit_t;                                                                 \
-	static const char* getUnitLabel() { return unit_label; }									        \
-	template<typename T>                                                                                \
-	static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); }		        \
-	template<typename STORAGE_T, typename UNIT_T>                                                       \
-	static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)				        \
-	{ return LLUnit<STORAGE_T, unit_name>(value); }												        \
-};                                                                                                      \
-	                                                                                                    \
-template<typename S1, typename S2>                                                                      \
-void ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)                        \
-{                                                                                                       \
-	out = LLUnit<S2, base_unit_name>((S2)(LLUnitLinearOps<S1, S2>(in.value()) conversion_operation));	\
-}                                                                                                       \
-                                                                                                        \
-template<typename S1, typename S2>                                                                      \
-void ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)                        \
-{                                                                                                       \
-	out = LLUnit<S2, unit_name>((S2)(LLUnitInverseLinearOps<S1, S2>(in.value()) conversion_operation)); \
+#define LL_DECLARE_DERIVED_UNIT(base_unit_name, conversion_operation, unit_name, unit_label)	 \
+struct unit_name                                                                                 \
+{                                                                                                \
+	typedef base_unit_name base_unit_t;                                                          \
+	static const char* getUnitLabel() { return unit_label; }									 \
+	template<typename T>                                                                         \
+	static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); }		 \
+	template<typename STORAGE_T, typename UNIT_T>                                                \
+	static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)				 \
+	{ return LLUnit<STORAGE_T, unit_name>(value); }												 \
+};                                                                                               \
+	                                                                                             \
+template<typename S1, typename S2>                                                               \
+S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)                   \
+{                                                                                                \
+	LLUnitLinearOps<S2> op = LLUnitLinearOps<S2>(in.value()) conversion_operation;               \
+	out = LLUnit<S2, base_unit_name>((S2)op.mValue);	                                         \
+	return op.mDivisor;                                                                          \
+}                                                                                                \
+                                                                                                 \
+template<typename S1, typename S2>                                                               \
+S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)                   \
+{                                                                                                \
+	LLUnitInverseLinearOps<S2> op = LLUnitInverseLinearOps<S2>(in.value()) conversion_operation; \
+	out = LLUnit<S2, unit_name>((S2)op.mValue);                                                  \
+	return op.mDivisor;                                                                          \
 }                                                                                               
 
 #define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name)                         \
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index a8e9be86ca..b8aef9d15e 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -38,12 +38,9 @@ namespace LLUnits
 	LL_DECLARE_DERIVED_UNIT(Latinum, / 16, Solari, "Sol");
 }
 
-typedef LLUnit<F32, LLUnits::Quatloos> F32Quatloos;
-typedef LLUnit<S32, LLUnits::Quatloos> S32Quatloos;
-typedef LLUnit<F32, LLUnits::Latinum> F32Latinum;
-typedef LLUnit<S32, LLUnits::Latinum> S32Latinum;
-typedef LLUnit<F32, LLUnits::Solari> F32Solari;
-typedef LLUnit<S32, LLUnits::Solari> S32Solari;
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Quatloos);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Latinum);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Solari);
 
 namespace tut
 {
@@ -83,6 +80,15 @@ namespace tut
 
 		LLUnit<U32, Quatloos> unsigned_int_quatloos(float_quatloos);
 		ensure("unsigned int can be initialized from signed int", unsigned_int_quatloos == S32Quatloos(42));
+
+		S32Solari int_solari(1);
+
+		float_quatloos = int_solari;
+		ensure("fractional units are preserved in conversion from integer to float type", float_quatloos == F32Quatloos(0.25f));
+
+		int_quatloos = S32Quatloos(1);
+		F32Solari float_solari = int_quatloos;
+		ensure("can convert with fractional intermediates from integer to float type", float_solari == F32Solari(4.f));
 	}
 
 	// conversions to/from base unit
@@ -185,6 +191,11 @@ namespace tut
 		return true;
 	}
 
+	bool accept_implicit_quatloos(S32Quatloos q)
+	{
+		return true;
+	}
+
 	// signature compatibility
 	template<> template<>
 	void units_object_t::test<6>()
-- 
cgit v1.2.3


From 37626bb4a29c39b35fe63971928b76d11faafeb3 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 21 Aug 2013 14:45:04 -0700
Subject: BUILDFIX: gcc build fixes

---
 indra/llcommon/llsys.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 1ff45d3d90..2b0083caff 100755
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -922,8 +922,8 @@ void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32
 	// Pageins:                     2097212.
 	// Pageouts:                      41759.
 	// Object cache: 841598 hits of 7629869 lookups (11% hit rate)
-	avail_physical_mem_kb = -1 ;
-	avail_virtual_mem_kb = -1 ;
+	avail_physical_mem_kb = (U32Kilobytes)-1 ;
+	avail_virtual_mem_kb = (U32Kilobytes)-1 ;
 
 #elif LL_LINUX
 	// mStatsMap is derived from MEMINFO_FILE:
@@ -974,15 +974,15 @@ void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32
 	// DirectMap4k:      434168 kB
 	// DirectMap2M:      477184 kB
 	// (could also run 'free', but easier to read a file than run a program)
-	avail_physical_mem_kb = -1 ;
-	avail_virtual_mem_kb = -1 ;
+	avail_physical_mem_kb = (U32Kilobytes)-1 ;
+	avail_virtual_mem_kb = (U32Kilobytes)-1 ;
 
 #else
 	//do not know how to collect available memory info for other systems.
 	//leave it blank here for now.
 
-	avail_physical_mem_kb = -1 ;
-	avail_virtual_mem_kb = -1 ;
+	avail_physical_mem_kb = (U32Kilobytes)-1 ;
+	avail_virtual_mem_kb = (U32Kilobytes)-1 ;
 #endif
 }
 
-- 
cgit v1.2.3


From 049317fc6442e8b2c2d93309a9d759aa063d2010 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 21 Aug 2013 23:51:46 -0700
Subject: SH-4433 WIP Interesting: Statistics > Ping Sim is always 0 ms added
 unit tests for lltrace

---
 indra/llcommon/CMakeLists.txt          |   1 +
 indra/llcommon/lltraceaccumulators.cpp |   3 +-
 indra/llcommon/lltraceaccumulators.h   |   1 +
 indra/llcommon/tests/lltrace_test.cpp  | 141 +++++++++++++++++++++++++++++++++
 4 files changed, 144 insertions(+), 2 deletions(-)
 create mode 100644 indra/llcommon/tests/lltrace_test.cpp

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 4336550d07..62880b07f6 100755
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -287,6 +287,7 @@ if (LL_TESTS)
   LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")                          
   LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
+  LL_ADD_INTEGRATION_TEST(lltrace "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}")
   LL_ADD_INTEGRATION_TEST(llunits "" "${test_libs}")
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index c79c102afd..42f075a7cb 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -147,7 +147,6 @@ void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppen
 
 		if (other.mTotalSamplingTime > epsilon)
 		{
-			llassert(mTotalSamplingTime > 0);
 			// combine variance (and hence standard deviation) of 2 different sized sample groups using
 			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
 			F64 n_1 = mTotalSamplingTime,
@@ -193,7 +192,7 @@ void SampleAccumulator::reset( const SampleAccumulator* other )
 	mMin = mLastValue;
 	mMax = mLastValue;
 	mMean = mLastValue;
-	LL_ERRS_IF(mHasValue && !(mMean < 0) && !(mMean >= 0)) << "Invalid mean after capturing value" << LL_ENDL;
+	llassert(!mHasValue || mMean < 0 || mMean >= 0);
 	mSumOfSquares = 0;
 	mLastSampleTimeStamp = LLTimer::getTotalSeconds();
 	mTotalSamplingTime = 0;
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index d4ff4b8d71..bf195f72b1 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -342,6 +342,7 @@ namespace LLTrace
 				mSum += mLastValue * delta_time;
 				mTotalSamplingTime += delta_time;
 				F64 old_mean = mMean;
+				llassert(mMean < 0 || mMean >= 0);
 				mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean);
 				llassert(mMean < 0 || mMean >= 0);
 				mSumOfSquares += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
diff --git a/indra/llcommon/tests/lltrace_test.cpp b/indra/llcommon/tests/lltrace_test.cpp
new file mode 100644
index 0000000000..1c2a4528ae
--- /dev/null
+++ b/indra/llcommon/tests/lltrace_test.cpp
@@ -0,0 +1,141 @@
+/** 
+ * @file llsingleton_test.cpp
+ * @date 2011-08-11
+ * @brief Unit test for the LLSingleton class
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltrace.h"
+#include "lltracethreadrecorder.h"
+#include "lltracerecording.h"
+#include "../test/lltut.h"
+
+namespace LLUnits
+{
+	// using powers of 2 to allow strict floating point equality
+	LL_DECLARE_BASE_UNIT(Ounces, "oz");
+	LL_DECLARE_DERIVED_UNIT(Ounces, * 12, TallCup, "");
+	LL_DECLARE_DERIVED_UNIT(Ounces, * 16, GrandeCup, "");
+	LL_DECLARE_DERIVED_UNIT(Ounces, * 20, VentiCup, "");
+
+	LL_DECLARE_BASE_UNIT(Grams, "g");
+	LL_DECLARE_DERIVED_UNIT(Grams, / 1000, Milligrams, "mg");
+}
+
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Ounces);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, TallCup);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, GrandeCup);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, VentiCup);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Grams);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Milligrams);
+
+
+namespace tut
+{
+	using namespace LLTrace;
+	struct trace
+	{
+		ThreadRecorder mRecorder;
+	};
+
+	typedef test_group<trace> trace_t;
+	typedef trace_t::object trace_object_t;
+	tut::trace_t tut_singleton("LLTrace");
+
+	static CountStatHandle<S32> sCupsOfCoffeeConsumed("coffeeconsumed", "Delicious cup of dark roast.");
+	static SampleStatHandle<F32Milligrams> sCaffeineLevelStat("caffeinelevel", "Coffee buzz quotient");
+	static EventStatHandle<S32Ounces> sOuncesPerCup("cupsize", "Large, huge, or ginormous");
+
+	static F32 sCaffeineLevel(0.f);
+	const F32Milligrams sCaffeinePerOz(18.f);
+
+	void drink_coffee(S32 num_cups, S32Ounces cup_size)
+	{
+		add(sCupsOfCoffeeConsumed, num_cups);
+		for (S32 i = 0; i < num_cups; i++)
+		{
+			record(sOuncesPerCup, cup_size);
+		}
+
+		sCaffeineLevel += F32Ounces(num_cups * cup_size).value() * sCaffeinePerOz.value();
+		sample(sCaffeineLevelStat, sCaffeineLevel);
+	}
+
+	// basic data collection
+	template<> template<>
+	void trace_object_t::test<1>()
+	{
+		sample(sCaffeineLevelStat, sCaffeineLevel);
+
+		Recording all_day;
+		Recording at_work;
+		Recording after_3pm;
+
+		all_day.start();
+		{
+			// warm up with one grande cup
+			drink_coffee(1, S32TallCup(1));
+
+			// go to work
+			at_work.start();
+			{
+				// drink 3 tall cups, 1 after 3 pm
+				drink_coffee(2, S32GrandeCup(1));
+				after_3pm.start();
+				drink_coffee(1, S32GrandeCup(1));
+			}
+			at_work.stop();
+			drink_coffee(1, S32VentiCup(1));
+		}
+		after_3pm.stop();
+		all_day.stop();
+
+		ensure("count stats are counted when recording is active", 
+			at_work.getSum(sCupsOfCoffeeConsumed) == 3 
+				&& all_day.getSum(sCupsOfCoffeeConsumed) == 5
+				&& after_3pm.getSum(sCupsOfCoffeeConsumed) == 2);
+		ensure("measurement sums are counted when recording is active", 
+			at_work.getSum(sOuncesPerCup) == S32Ounces(48) 
+				&& all_day.getSum(sOuncesPerCup) == S32Ounces(80)
+				&& after_3pm.getSum(sOuncesPerCup) == S32Ounces(36));
+		ensure("measurement min is specific to when recording is active", 
+			at_work.getMin(sOuncesPerCup) == S32GrandeCup(1) 
+				&& all_day.getMin(sOuncesPerCup) == S32TallCup(1)
+				&& after_3pm.getMin(sOuncesPerCup) == S32GrandeCup(1));
+		ensure("measurement max is specific to when recording is active", 
+			at_work.getMax(sOuncesPerCup) == S32GrandeCup(1) 
+				&& all_day.getMax(sOuncesPerCup) == S32VentiCup(1)
+				&& after_3pm.getMax(sOuncesPerCup) == S32VentiCup(1));
+		ensure("sample min is specific to when recording is active", 
+			at_work.getMin(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1)).value()
+				&& all_day.getMin(sCaffeineLevelStat) == F32Milligrams(0.f)
+				&& after_3pm.getMin(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(2)).value());
+		ensure("sample max is specific to when recording is active", 
+			at_work.getMax(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(3)).value()
+				&& all_day.getMax(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(3) + (S32Ounces)S32VentiCup(1)).value()
+				&& after_3pm.getMax(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(3) + (S32Ounces)S32VentiCup(1)).value());
+	}
+
+}
-- 
cgit v1.2.3


From cf014375b8b408d58bd35deb4e58e4369fb3bf62 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 22 Aug 2013 14:21:16 -0700
Subject: SH-4433 FIX: Interesting: Statistics > Ping Sim is always 0 ms
 removed bad assert fixed precision issues during int->unsigned int
 conversions and vice versa

---
 indra/llcommon/lltraceaccumulators.cpp |  1 -
 indra/llcommon/llunit.h                | 23 +++++++++++++++++------
 indra/llcommon/tests/llunits_test.cpp  | 16 ++++++++++++++++
 3 files changed, 33 insertions(+), 7 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index c79c102afd..5e25ad6b26 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -147,7 +147,6 @@ void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppen
 
 		if (other.mTotalSamplingTime > epsilon)
 		{
-			llassert(mTotalSamplingTime > 0);
 			// combine variance (and hence standard deviation) of 2 different sized sample groups using
 			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
 			F64 n_1 = mTotalSamplingTime,
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index f42456fe72..bfc011bb55 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -69,6 +69,12 @@ struct LLResultTypeDivide
 	typedef LL_TYPEOF(S() / T(1)) type_t;
 };
 
+template<typename S, typename T>
+struct LLResultTypePromote
+{
+	typedef LL_TYPEOF((true) ? S() : T()) type_t;
+};
+
 template<typename STORAGE_TYPE, typename UNIT_TYPE>
 struct LLUnit
 {
@@ -155,10 +161,11 @@ struct LLUnit
 	template<typename SOURCE_STORAGE, typename SOURCE_UNITS>
 	static self_t convert(LLUnit<SOURCE_STORAGE, SOURCE_UNITS> v) 
 	{ 
-		self_t result;
-		STORAGE_TYPE divisor = ll_convert_units(v, result);
-		result.mValue /= divisor;
-		return result;
+		typedef typename LLResultTypePromote<STORAGE_TYPE, SOURCE_STORAGE>::type_t result_storage_t;
+		LLUnit<result_storage_t, UNIT_TYPE> result;
+		result_storage_t divisor = ll_convert_units(v, result);
+		result.value(result.value() / divisor);
+		return self_t(result.value());
 	}
 
 protected:
@@ -695,7 +702,9 @@ struct unit_name
 template<typename S1, typename S2>                                                               \
 S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)                   \
 {                                                                                                \
-	LLUnitLinearOps<S2> op = LLUnitLinearOps<S2>(in.value()) conversion_operation;               \
+	typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t;                       \
+	LLUnitLinearOps<result_storage_t> op =                                                       \
+		LLUnitLinearOps<result_storage_t>(in.value()) conversion_operation;                      \
 	out = LLUnit<S2, base_unit_name>((S2)op.mValue);	                                         \
 	return op.mDivisor;                                                                          \
 }                                                                                                \
@@ -703,7 +712,9 @@ S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)
 template<typename S1, typename S2>                                                               \
 S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)                   \
 {                                                                                                \
-	LLUnitInverseLinearOps<S2> op = LLUnitInverseLinearOps<S2>(in.value()) conversion_operation; \
+	typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t;                       \
+	LLUnitInverseLinearOps<result_storage_t> op =                                                \
+		LLUnitInverseLinearOps<result_storage_t>(in.value()) conversion_operation;               \
 	out = LLUnit<S2, unit_name>((S2)op.mValue);                                                  \
 	return op.mDivisor;                                                                          \
 }                                                                                               
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index b8aef9d15e..292c6122af 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -257,4 +257,20 @@ namespace tut
 		LLUnitImplicit<F32, Latinum> latinum_implicit(2);
 		ensure("implicit units of different types are comparable", latinum_implicit * 2 == quatloos_implicit);
 	}
+
+	// precision tests
+	template<> template<>
+	void units_object_t::test<8>()
+	{
+		U32Bytes max_bytes(U32_MAX);
+		S32Megabytes mega_bytes = max_bytes;
+		ensure("max available precision is used when converting units", mega_bytes == (S32Megabytes)4095);
+
+		mega_bytes = (S32Megabytes)-5 + (U32Megabytes)1;
+		ensure("can mix signed and unsigned in units addition", mega_bytes == (S32Megabytes)-4);
+
+		mega_bytes = (U32Megabytes)5 + (S32Megabytes)-1;
+		ensure("can mix unsigned and signed in units addition", mega_bytes == (S32Megabytes)4);
+
+	}
 }
-- 
cgit v1.2.3


From b1419bfbf090afa8b57d0952d98a529527c82f2d Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 22 Aug 2013 16:56:14 -0700
Subject: BUILDFIX: attempted fix for crash on exit in llsdserialize test

---
 indra/llcommon/llerror.cpp                  | 3 ++-
 indra/llcommon/tests/llsdserialize_test.cpp | 3 +++
 2 files changed, 5 insertions(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 1b1aada8c1..590e236090 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -928,7 +928,8 @@ namespace
 
 			if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s.mPrintLocation))
 			{
-				message_stream << site.mLocationString << " ";
+				message_stream << site.mLocationString;
+                message_stream << " ";
 			}
 
 			if (show_time && r->wantsTime() && s.mTimeFunction != NULL)
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index 235008a5ae..ad89380e36 100755
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -1723,5 +1723,8 @@ namespace tut
                       "This string\n"
                       "has several\n"
                       "lines.");
+        
+        bool loop = true;
+        while(loop) {}
     }
 }
-- 
cgit v1.2.3


From 3413a57a90094b1844fbc837d5ce24921c87e600 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 22 Aug 2013 16:57:51 -0700
Subject: BUILDFIX: accidental checkin of infinite loop in llsdserialize test

---
 indra/llcommon/tests/llsdserialize_test.cpp | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index ad89380e36..235008a5ae 100755
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -1723,8 +1723,5 @@ namespace tut
                       "This string\n"
                       "has several\n"
                       "lines.");
-        
-        bool loop = true;
-        while(loop) {}
     }
 }
-- 
cgit v1.2.3


From a77f42494584537489410a5157179aaadf868935 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 23 Aug 2013 13:41:51 -0700
Subject: BUILDFIX: fix for crashes in unit tests on mac and linux

---
 indra/llcommon/llerror.cpp                  | 12 +++++++++---
 indra/llcommon/llerror.h                    |  3 ++-
 indra/llcommon/tests/llleap_test.cpp        |  3 ---
 indra/llcommon/tests/llprocess_test.cpp     |  3 ---
 indra/llcommon/tests/llsdserialize_test.cpp |  4 +---
 5 files changed, 12 insertions(+), 13 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 590e236090..5bb6f53828 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -926,9 +926,10 @@ namespace
 
 			std::ostringstream message_stream;
 
+            const_cast<LLError::CallSite&>(site).mTagString += " ";
 			if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s.mPrintLocation))
 			{
-				message_stream << site.mLocationString;
+				//message_stream << site.mLocationString;
                 message_stream << " ";
 			}
 
@@ -949,12 +950,13 @@ namespace
 			
 			if (show_function && r->wantsFunctionName())
 			{
-				message_stream << site.mFunctionString << " ";
+				//message_stream << site.mFunctionString << " ";
 			}
 
 			message_stream << message;
 
-			r->recordMessage(level, message_stream.str());
+            std::string final_message = message_stream.str();
+			r->recordMessage(level, final_message);
 		}
 	}
 }
@@ -1158,6 +1160,10 @@ namespace LLError
 		Globals& g = Globals::get();
 		Settings& s = Settings::get();
 
+        //const_cast<CallSite&>(site).mTagString += " ";
+        std::string tag_string = site.mTagString;
+        tag_string += " ";
+        
 		std::string message = out->str();
 		if (out == &g.messageStream)
 		{
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 6eaab450ed..6cac952b7e 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -302,7 +302,8 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 // See top of file for common usage.	
 /////////////////////////////////
 
-// this macro uses a one-shot do statement to avoid parsing errors when writing:
+// this macro uses a one-shot do statement to avoid parsing errors when writing control flow statements
+// without braces:
 // if (condition) LL_INFOS() << "True" << LLENDL; else LLINFOS() << "False" << LLENDL
 
 #define lllog(level, once, ...)																	          \
diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp
index 29060d4ef5..9ea822cb8d 100755
--- a/indra/llcommon/tests/llleap_test.cpp
+++ b/indra/llcommon/tests/llleap_test.cpp
@@ -22,7 +22,6 @@
 // other Linden headers
 #include "../test/lltut.h"
 #include "../test/namedtempfile.h"
-#include "../test/manageapr.h"
 #include "../test/catch_and_store_what_in.h"
 #include "wrapllerrs.h"
 #include "llevents.h"
@@ -33,8 +32,6 @@
 
 using boost::assign::list_of;
 
-static ManageAPR manager;
-
 StringVec sv(const StringVec& listof) { return listof; }
 
 #if defined(LL_WINDOWS)
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index f188865eb0..50b5c79e71 100755
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -29,7 +29,6 @@
 //#include <boost/lambda/bind.hpp>
 // other Linden headers
 #include "../test/lltut.h"
-#include "../test/manageapr.h"
 #include "../test/namedtempfile.h"
 #include "../test/catch_and_store_what_in.h"
 #include "stringize.h"
@@ -47,8 +46,6 @@
 
 //namespace lambda = boost::lambda;
 
-// static instance of this manages APR init/cleanup
-static ManageAPR manager;
 
 /*****************************************************************************
 *   Helpers
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index 235008a5ae..b5893135ea 100755
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -56,12 +56,9 @@ namespace lambda = boost::lambda;
 #include "../llformat.h"
 
 #include "../test/lltut.h"
-#include "../test/manageapr.h"
 #include "../test/namedtempfile.h"
 #include "stringize.h"
 
-static ManageAPR manager;
-
 std::vector<U8> string_to_vector(const std::string& str)
 {
 	return std::vector<U8>(str.begin(), str.end());
@@ -1723,5 +1720,6 @@ namespace tut
                       "This string\n"
                       "has several\n"
                       "lines.");
+        
     }
 }
-- 
cgit v1.2.3


From 235cc392934f1385f05e78f09a079c431a03b4b8 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 23 Aug 2013 14:22:01 -0700
Subject: BUILDFIX: reverted some debugging changes to llerror.cpp

---
 indra/llcommon/llerror.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 5bb6f53828..a51f8f216a 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -929,8 +929,7 @@ namespace
             const_cast<LLError::CallSite&>(site).mTagString += " ";
 			if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s.mPrintLocation))
 			{
-				//message_stream << site.mLocationString;
-                message_stream << " ";
+				message_stream << site.mLocationString << " ";
 			}
 
 			if (show_time && r->wantsTime() && s.mTimeFunction != NULL)
@@ -950,7 +949,7 @@ namespace
 			
 			if (show_function && r->wantsFunctionName())
 			{
-				//message_stream << site.mFunctionString << " ";
+				message_stream << site.mFunctionString << " ";
 			}
 
 			message_stream << message;
-- 
cgit v1.2.3


From 4c7f4896290707c833f5e088963c94ff5e01acde Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 23 Aug 2013 15:02:37 -0700
Subject: BUILDFIX: replaced function that was accidentally removed

---
 indra/llcommon/tests/llprocess_test.cpp | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 50b5c79e71..709a095105 100755
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -45,7 +45,12 @@
 #endif
 
 //namespace lambda = boost::lambda;
-
+ std::string apr_strerror_helper(apr_status_t rv)
+{
+    char errbuf[256];
+    apr_strerror(rv, errbuf, sizeof(errbuf));
+    return errbuf;
+}
 
 /*****************************************************************************
 *   Helpers
@@ -57,7 +62,7 @@
 #define aprchk(expr) aprchk_(#expr, (expr))
 static void aprchk_(const char* call, apr_status_t rv, apr_status_t expected=APR_SUCCESS)
 {
-    tut::ensure_equals(STRINGIZE(call << " => " << rv << ": " << manager.strerror(rv)),
+    tut::ensure_equals(STRINGIZE(call << " => " << rv << ": " << apr_strerror_helper(rv)),
                        rv, expected);
 }
 
-- 
cgit v1.2.3


From b667d20e00e4ea5f1d5a619d2868b502583deb43 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 23 Aug 2013 15:34:41 -0700
Subject: fixed issue with poor framerate after clearing cache

---
 indra/llcommon/llunit.h | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index bfc011bb55..de9cee33fd 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -601,9 +601,6 @@ struct LLUnitLinearOps
 		mDivisor(1)
 	{}
 
-	T mValue;
-	T mDivisor;
-
 	template<typename OTHER_T>
 	self_t operator * (OTHER_T other)
 	{
@@ -620,6 +617,7 @@ struct LLUnitLinearOps
 	template<typename OTHER_T>
 	self_t operator + (OTHER_T other)
 	{
+		mValue /= mDivisor;
 		mValue += other;
 		return *this;
 	}
@@ -627,9 +625,13 @@ struct LLUnitLinearOps
 	template<typename OTHER_T>
 	self_t operator - (OTHER_T other)
 	{
+		mValue /= mDivisor;
 		mValue -= other;
 		return *this;
 	}
+
+	T mValue;
+	T mDivisor;
 };
 
 template<typename T>
@@ -642,9 +644,6 @@ struct LLUnitInverseLinearOps
 		mDivisor(1)
 	{}
 
-	T mValue;
-	T mDivisor;
-
 	template<typename OTHER_T>
 	self_t operator * (OTHER_T other)
 	{
@@ -662,6 +661,7 @@ struct LLUnitInverseLinearOps
 	template<typename OTHER_T>
 	self_t operator + (OTHER_T other)
 	{
+		mValue /= mDivisor;
 		mValue -= other;
 		return *this;
 	}
@@ -669,9 +669,13 @@ struct LLUnitInverseLinearOps
 	template<typename OTHER_T>
 	self_t operator - (OTHER_T other)
 	{
+		mValue /= mDivisor;
 		mValue += other;
 		return *this;
 	}
+
+	T mValue;
+	T mDivisor;
 };
 
 #define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label)                                             \
-- 
cgit v1.2.3


From 662d6a17712fbba5cea0d9cf20f5a2f32e2dd537 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 26 Aug 2013 10:51:08 -0700
Subject: added compile time warnings to use of deprecated llinfos, llwarns,
 etc.

---
 indra/llcommon/llerror.h        | 14 +++++++-------
 indra/llcommon/llpreprocessor.h | 13 +++++++++++++
 2 files changed, 20 insertions(+), 7 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 6eaab450ed..88e5dfdcf1 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -355,13 +355,13 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 #define LL_INFOS_ONCE(...)	lllog(LLError::LEVEL_INFO, true, ##__VA_ARGS__)
 #define LL_WARNS_ONCE(...)	lllog(LLError::LEVEL_WARN, true, ##__VA_ARGS__)
 
-
 // DEPRECATED: Use the new macros that allow tags and *look* like macros.
-//#define lldebugs	LL_DEBUGS()
-#define llinfos		LL_INFOS()
-//#define llwarns		LL_WARNS()
-//#define llerrs		LL_ERRS()
-//#define llcont		LL_CONT
-#define llendl		LL_ENDL 
+#define lldebugs	LL_COMPILE_TIME_WARNING("Warning: lldebugs deprecated, use LL_DEBUGS() instead"); LL_DEBUGS()
+#define llinfos		LL_COMPILE_TIME_WARNING("Warning: llinfos deprecated, use LL_INFOS() instead"); LL_INFOS()
+#define llwarns		LL_COMPILE_TIME_WARNING("Warning: llwarns deprecated, use LL_WARNS() instead"); LL_WARNS()
+#define llerrs		LL_COMPILE_TIME_WARNING("Warning: llerrs deprecated, use LL_ERRS() instead"); LL_ERRS()
+#define llcont		LL_COMPILE_TIME_WARNING("Warning: llcont deprecated, use LL_CONT instead"); LL_CONT
+#define llendl		LL_COMPILE_TIME_WARNING("Warning: llendl deprecated, use LL_ENDL instead"); LL_ENDL
+
 
 #endif // LL_LLERROR_H
diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index e5c8482ed1..eea63d443f 100755
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -188,4 +188,17 @@
 #elif LL_DARWIN
 #define LL_TYPEOF(exp) typeof(exp)
 #endif
+
+#define LL_TO_STRING_HELPER(x) #x
+#define LL_TO_STRING(x) LL_TO_STRING_HELPER(x)
+#define LL_FILE_LINENO(msg) __FILE__ "(" LL_TO_STRING(__LINE__) ") : " msg
+#if LL_WINDOWS
+#define LL_COMPILE_TIME_WARNING(msg) __pragma(message(LL_FILE_LINENO(msg)))
+#define LL_COMPILE_TIME_ERROR(msg) static_assert(false, msg)
+#else
+// no way to get gcc 4.2 to print a user-defined diagnostic message only when a macro is used
+#define LL_COMPILE_TIME_WARNING(msg)
+#define LL_COMPILE_TIME_ERROR(msg)
+#endif
+
 #endif	//	not LL_LINDEN_PREPROCESSOR_H
-- 
cgit v1.2.3


From 8535b87544cc2e71896716a4cd1c3c2445ff4af0 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 26 Aug 2013 18:00:24 -0700
Subject: removed some unecessary template parameters from LLUnit member
 functions forced unit conversion code to inline unit conversion now no longer
 converts all the way to base and back, but tries to find equivalent units as
 early as possible fixed another llinfos instance scene monitor now outputs
 n/a for invalid samples

---
 indra/llcommon/llmemory.cpp           |  4 ++--
 indra/llcommon/llunit.h               | 40 +++++++++++++++--------------------
 indra/llcommon/tests/llunits_test.cpp |  1 -
 3 files changed, 19 insertions(+), 26 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index 06334c012a..cb2f853070 100755
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -206,8 +206,8 @@ bool LLMemory::isMemoryPoolLow()
 		return true ;
 	}
 
-	bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMORY_POOL_THRESHOLD || 
-		sAllocatedPageSizeInKB + LOW_MEMORY_POOL_THRESHOLD > sMaxHeapSizeInKB) ;
+	bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMORY_POOL_THRESHOLD 
+						|| sAllocatedPageSizeInKB + LOW_MEMORY_POOL_THRESHOLD > sMaxHeapSizeInKB) ;
 
 	//check the virtual address space fragmentation
 	if(!is_low)
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index bfc011bb55..1ef4924578 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -82,24 +82,16 @@ struct LLUnit
 	typedef STORAGE_TYPE storage_t;
 
 	// value initialization
-	explicit LLUnit(storage_t value = storage_t())
+	LL_FORCE_INLINE explicit LLUnit(storage_t value = storage_t())
 	:	mValue(value)
 	{}
 
 	// unit initialization and conversion
 	template<typename OTHER_STORAGE, typename OTHER_UNIT>
-	LLUnit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
+	LL_FORCE_INLINE LLUnit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
 	:	mValue(convert(other).mValue)
 	{}
 	
-	// unit assignment
-	template<typename OTHER_STORAGE, typename OTHER_UNIT>
-	self_t& operator = (LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
-	{
-		mValue = convert(other).mValue;
-		return *this;
-	}
-
 	storage_t value() const
 	{
 		return mValue;
@@ -122,14 +114,12 @@ struct LLUnit
 		*this = LLUnit<storage_t, NEW_UNIT_TYPE>(value);
 	}
 
-	template<typename OTHER_STORAGE, typename OTHER_UNIT>
-	void operator += (LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
+	void operator += (self_t other)
 	{
 		mValue += convert(other).mValue;
 	}
 
-	template<typename OTHER_STORAGE, typename OTHER_UNIT>
-	void operator -= (LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
+	void operator -= (self_t other)
 	{
 		mValue -= convert(other).mValue;
 	}
@@ -139,8 +129,7 @@ struct LLUnit
 		mValue *= multiplicand;
 	}
 
-	template<typename OTHER_UNIT, typename OTHER_STORAGE>
-	void operator *= (LLUnit<OTHER_STORAGE, OTHER_UNIT> multiplicand)
+	void operator *= (self_t multiplicand)
 	{
 		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
 		LL_BAD_TEMPLATE_INSTANTIATION(OTHER_UNIT, "Multiplication of unit types not supported.");
@@ -151,15 +140,14 @@ struct LLUnit
 		mValue /= divisor;
 	}
 
-	template<typename OTHER_UNIT, typename OTHER_STORAGE>
-	void operator /= (LLUnit<OTHER_STORAGE, OTHER_UNIT> divisor)
+	void operator /= (self_t divisor)
 	{
 		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
 		LL_BAD_TEMPLATE_INSTANTIATION(OTHER_UNIT, "Illegal in-place division of unit types.");
 	}
 
 	template<typename SOURCE_STORAGE, typename SOURCE_UNITS>
-	static self_t convert(LLUnit<SOURCE_STORAGE, SOURCE_UNITS> v) 
+	LL_FORCE_INLINE static self_t convert(LLUnit<SOURCE_STORAGE, SOURCE_UNITS> v) 
 	{ 
 		typedef typename LLResultTypePromote<STORAGE_TYPE, SOURCE_STORAGE>::type_t result_storage_t;
 		LLUnit<result_storage_t, UNIT_TYPE> result;
@@ -258,7 +246,7 @@ std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNIT_TYP
 }
 
 template<typename S1, typename T1, typename S2, typename T2>
-LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ...)
+LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out)
 {
 	S2 divisor(1);
 
@@ -272,7 +260,7 @@ LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out, ...)
 		// T1 and T2 same type, just assign
 		out.value((S2)in.value());
 	}
-	else if (LLIsSameType<T2, typename T2::base_unit_t>::value)
+	else if (T1::sLevel > T2::sLevel)
 	{
 		// reduce T1
 		LLUnit<S2, typename T1::base_unit_t> new_in;
@@ -301,6 +289,10 @@ struct LLStorageType<LLUnit<STORAGE_TYPE, UNIT_TYPE> >
 	typedef STORAGE_TYPE type_t;
 };
 
+// all of these operators need to perform type promotion on the storage type of the units, so they 
+// cannot be expressed as operations on identical types with implicit unit conversion 
+// e.g. typeof(S32Bytes(x) + F32Megabytes(y)) <==> F32Bytes
+
 //
 // operator +
 //
@@ -677,6 +669,7 @@ struct LLUnitInverseLinearOps
 #define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label)                                             \
 struct base_unit_name                                                                                \
 {                                                                                                    \
+	static const int sLevel = 0;                                                                     \
 	typedef base_unit_name base_unit_t;                                                              \
 	static const char* getUnitLabel() { return unit_label; }                                         \
 	template<typename T>                                                                             \
@@ -690,6 +683,7 @@ struct base_unit_name
 #define LL_DECLARE_DERIVED_UNIT(base_unit_name, conversion_operation, unit_name, unit_label)	 \
 struct unit_name                                                                                 \
 {                                                                                                \
+	static const int sLevel = base_unit_name::sLevel + 1;                                        \
 	typedef base_unit_name base_unit_t;                                                          \
 	static const char* getUnitLabel() { return unit_label; }									 \
 	template<typename T>                                                                         \
@@ -700,7 +694,7 @@ struct unit_name
 };                                                                                               \
 	                                                                                             \
 template<typename S1, typename S2>                                                               \
-S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)                   \
+LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)   \
 {                                                                                                \
 	typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t;                       \
 	LLUnitLinearOps<result_storage_t> op =                                                       \
@@ -710,7 +704,7 @@ S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)
 }                                                                                                \
                                                                                                  \
 template<typename S1, typename S2>                                                               \
-S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)                   \
+LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)   \
 {                                                                                                \
 	typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t;                       \
 	LLUnitInverseLinearOps<result_storage_t> op =                                                \
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index 292c6122af..31d4f86159 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -271,6 +271,5 @@ namespace tut
 
 		mega_bytes = (U32Megabytes)5 + (S32Megabytes)-1;
 		ensure("can mix unsigned and signed in units addition", mega_bytes == (S32Megabytes)4);
-
 	}
 }
-- 
cgit v1.2.3


From e1c09b9b5943cfa2f35eef878643b90d412a41ab Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 26 Aug 2013 18:21:19 -0700
Subject: fixed eol type

---
 indra/llcommon/llpreprocessor.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index eea63d443f..f00885ae2f 100755
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -189,7 +189,7 @@
 #define LL_TYPEOF(exp) typeof(exp)
 #endif
 
-#define LL_TO_STRING_HELPER(x) #x
+#define LL_TO_STRING_HELPER(x) #x
 #define LL_TO_STRING(x) LL_TO_STRING_HELPER(x)
 #define LL_FILE_LINENO(msg) __FILE__ "(" LL_TO_STRING(__LINE__) ") : " msg
 #if LL_WINDOWS
-- 
cgit v1.2.3


From 0b96a0e80c34067056811d100fd5d4e7404e07b5 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 26 Aug 2013 18:37:07 -0700
Subject: BUILDFIX: corrected template parameter for
 LL_BAD_TEMPLATE_INSTANTIATION macro in llunit

---
 indra/llcommon/llunit.h                 | 4 ++--
 indra/llcommon/tests/llprocess_test.cpp | 3 ++-
 2 files changed, 4 insertions(+), 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
index 0081b51f84..798d97a46e 100644
--- a/indra/llcommon/llunit.h
+++ b/indra/llcommon/llunit.h
@@ -132,7 +132,7 @@ struct LLUnit
 	void operator *= (self_t multiplicand)
 	{
 		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
-		LL_BAD_TEMPLATE_INSTANTIATION(OTHER_UNIT, "Multiplication of unit types not supported.");
+		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported.");
 	}
 
 	void operator /= (storage_t divisor)
@@ -143,7 +143,7 @@ struct LLUnit
 	void operator /= (self_t divisor)
 	{
 		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
-		LL_BAD_TEMPLATE_INSTANTIATION(OTHER_UNIT, "Illegal in-place division of unit types.");
+		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types.");
 	}
 
 	template<typename SOURCE_STORAGE, typename SOURCE_UNITS>
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 709a095105..e09692c82d 100755
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -62,7 +62,8 @@
 #define aprchk(expr) aprchk_(#expr, (expr))
 static void aprchk_(const char* call, apr_status_t rv, apr_status_t expected=APR_SUCCESS)
 {
-    tut::ensure_equals(STRINGIZE(call << " => " << rv << ": " << apr_strerror_helper(rv)),
+    tut::ensure_equals(STRINGIZE(call << " => " << rv << ": " << apr_strerror_helper
+                                 (rv)),
                        rv, expected);
 }
 
-- 
cgit v1.2.3


From 7ab616c18786afcb40ab0092fe6f8c6a3a799375 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 26 Aug 2013 19:58:29 -0700
Subject: BUILDFIX: fix for windows unit test failures...don't do unnecessary
 manipulation of callsite strings in llerror

---
 indra/llcommon/llerror.cpp | 18 ++++++------------
 1 file changed, 6 insertions(+), 12 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index a51f8f216a..96dbaa572a 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -926,7 +926,6 @@ namespace
 
 			std::ostringstream message_stream;
 
-            const_cast<LLError::CallSite&>(site).mTagString += " ";
 			if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s.mPrintLocation))
 			{
 				message_stream << site.mLocationString << " ";
@@ -937,16 +936,16 @@ namespace
 				message_stream << s.mTimeFunction() << " ";
 			}
 
-			if (show_tags && r->wantsTags())
+			if (show_level && r->wantsLevel())
 			{
-				message_stream << site.mTagString << " ";
+				message_stream << site.mLevelString << " ";
 			}
 
-			if (show_level && r->wantsLevel())
+			if (show_tags && r->wantsTags())
 			{
-				message_stream << site.mLevelString << " ";
+				message_stream << site.mTagString << " ";
 			}
-			
+
 			if (show_function && r->wantsFunctionName())
 			{
 				message_stream << site.mFunctionString << " ";
@@ -954,8 +953,7 @@ namespace
 
 			message_stream << message;
 
-            std::string final_message = message_stream.str();
-			r->recordMessage(level, final_message);
+			r->recordMessage(level, message_stream.str());
 		}
 	}
 }
@@ -1159,10 +1157,6 @@ namespace LLError
 		Globals& g = Globals::get();
 		Settings& s = Settings::get();
 
-        //const_cast<CallSite&>(site).mTagString += " ";
-        std::string tag_string = site.mTagString;
-        tag_string += " ";
-        
 		std::string message = out->str();
 		if (out == &g.messageStream)
 		{
-- 
cgit v1.2.3


From a7aed07a5b620977fb74e4070e432eef01d11d3c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 27 Aug 2013 13:41:19 -0700
Subject: broke out llunit.h into llunittype.h and llunits.h for unit
 declarations changed unit declarations macros to make a lot more sense

---
 indra/llcommon/CMakeLists.txt         |   3 +-
 indra/llcommon/llcriticaldamp.h       |   2 +-
 indra/llcommon/lldate.h               |   2 +-
 indra/llcommon/llerror.h              |  12 +-
 indra/llcommon/llfasttimer.cpp        |   2 +-
 indra/llcommon/llmemory.h             |   2 +-
 indra/llcommon/llpreprocessor.h       |   6 +-
 indra/llcommon/llprocessor.h          |   2 +-
 indra/llcommon/lltimer.h              |   2 +-
 indra/llcommon/lltraceaccumulators.h  |   2 +-
 indra/llcommon/llunit.h               | 830 ----------------------------------
 indra/llcommon/llunittype.h           | 734 ++++++++++++++++++++++++++++++
 indra/llcommon/tests/lltrace_test.cpp |   8 +-
 indra/llcommon/tests/llunits_test.cpp |  73 ++-
 14 files changed, 825 insertions(+), 855 deletions(-)
 delete mode 100644 indra/llcommon/llunit.h
 create mode 100644 indra/llcommon/llunittype.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 62880b07f6..e138a54d29 100755
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -209,7 +209,8 @@ set(llcommon_HEADER_FILES
     lltracerecording.h
     lltracethreadrecorder.h
     lltreeiterators.h
-    llunit.h
+    llunits.h
+    llunittype.h
     lluri.h
     lluuid.h
 	llwin32headers.h
diff --git a/indra/llcommon/llcriticaldamp.h b/indra/llcommon/llcriticaldamp.h
index a02a2a0dcf..1fb6a1af29 100755
--- a/indra/llcommon/llcriticaldamp.h
+++ b/indra/llcommon/llcriticaldamp.h
@@ -31,7 +31,7 @@
 #include <vector>
 
 #include "llframetimer.h"
-#include "llunit.h"
+#include "llunits.h"
 
 class LL_COMMON_API LLSmoothInterpolation 
 {
diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h
index aecf3b765e..be2cd2d051 100755
--- a/indra/llcommon/lldate.h
+++ b/indra/llcommon/lldate.h
@@ -33,7 +33,7 @@
 #include <string>
 
 #include "stdtypes.h"
-#include "llunit.h"
+#include "llunits.h"
 
 /** 
  * @class LLDate
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 0d6f1810d2..1ddb4874a0 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -357,12 +357,12 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
 #define LL_WARNS_ONCE(...)	lllog(LLError::LEVEL_WARN, true, ##__VA_ARGS__)
 
 // DEPRECATED: Use the new macros that allow tags and *look* like macros.
-#define lldebugs	LL_COMPILE_TIME_WARNING("Warning: lldebugs deprecated, use LL_DEBUGS() instead"); LL_DEBUGS()
-#define llinfos		LL_COMPILE_TIME_WARNING("Warning: llinfos deprecated, use LL_INFOS() instead"); LL_INFOS()
-#define llwarns		LL_COMPILE_TIME_WARNING("Warning: llwarns deprecated, use LL_WARNS() instead"); LL_WARNS()
-#define llerrs		LL_COMPILE_TIME_WARNING("Warning: llerrs deprecated, use LL_ERRS() instead"); LL_ERRS()
-#define llcont		LL_COMPILE_TIME_WARNING("Warning: llcont deprecated, use LL_CONT instead"); LL_CONT
-#define llendl		LL_COMPILE_TIME_WARNING("Warning: llendl deprecated, use LL_ENDL instead"); LL_ENDL
+#define lldebugs	LL_COMPILE_TIME_MESSAGE("Warning: lldebugs deprecated, use LL_DEBUGS() instead"); LL_DEBUGS()
+#define llinfos		LL_COMPILE_TIME_MESSAGE("Warning: llinfos deprecated, use LL_INFOS() instead"); LL_INFOS()
+#define llwarns		LL_COMPILE_TIME_MESSAGE("Warning: llwarns deprecated, use LL_WARNS() instead"); LL_WARNS()
+#define llerrs		LL_COMPILE_TIME_MESSAGE("Warning: llerrs deprecated, use LL_ERRS() instead"); LL_ERRS()
+#define llcont		LL_COMPILE_TIME_MESSAGE("Warning: llcont deprecated, use LL_CONT instead"); LL_CONT
+#define llendl		LL_COMPILE_TIME_MESSAGE("Warning: llendl deprecated, use LL_ENDL instead"); LL_ENDL
 
 
 #endif // LL_LLERROR_H
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index ae3234a87a..2235eb1a08 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -32,7 +32,7 @@
 #include "llsingleton.h"
 #include "lltreeiterators.h"
 #include "llsdserialize.h"
-#include "llunit.h"
+#include "llunits.h"
 #include "llsd.h"
 #include "lltracerecording.h"
 #include "lltracethreadrecorder.h"
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 23be1e5b2d..d3c5e5235d 100755
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -27,7 +27,7 @@
 #define LLMEMORY_H
 
 #include "linden_common.h"
-#include "llunit.h"
+#include "llunits.h"
 #if !LL_WINDOWS
 #include <stdint.h>
 #endif
diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index f00885ae2f..0fcc872690 100755
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -193,12 +193,10 @@
 #define LL_TO_STRING(x) LL_TO_STRING_HELPER(x)
 #define LL_FILE_LINENO(msg) __FILE__ "(" LL_TO_STRING(__LINE__) ") : " msg
 #if LL_WINDOWS
-#define LL_COMPILE_TIME_WARNING(msg) __pragma(message(LL_FILE_LINENO(msg)))
-#define LL_COMPILE_TIME_ERROR(msg) static_assert(false, msg)
+#define LL_COMPILE_TIME_MESSAGE(msg) __pragma(message(LL_FILE_LINENO(msg)))
 #else
 // no way to get gcc 4.2 to print a user-defined diagnostic message only when a macro is used
-#define LL_COMPILE_TIME_WARNING(msg)
-#define LL_COMPILE_TIME_ERROR(msg)
+#define LL_COMPILE_TIME_MESSAGE(msg)
 #endif
 
 #endif	//	not LL_LINDEN_PREPROCESSOR_H
diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h
index 4956a39700..90e5bc59ee 100755
--- a/indra/llcommon/llprocessor.h
+++ b/indra/llcommon/llprocessor.h
@@ -27,7 +27,7 @@
 
 #ifndef LLPROCESSOR_H
 #define LLPROCESSOR_H
-#include "llunit.h"
+#include "llunits.h"
 
 class LLProcessorInfoImpl;
 
diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h
index 8b3930e2fa..4e58102094 100755
--- a/indra/llcommon/lltimer.h
+++ b/indra/llcommon/lltimer.h
@@ -37,7 +37,7 @@
 #include <string>
 #include <list>
 // units conversions
-#include "llunit.h"
+#include "llunits.h"
 #ifndef USEC_PER_SEC
     const U32	USEC_PER_SEC	= 1000000;
 #endif
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index bf195f72b1..e0f60800e3 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -31,7 +31,7 @@
 
 #include "stdtypes.h"
 #include "llpreprocessor.h"
-#include "llunit.h"
+#include "llunits.h"
 #include "lltimer.h"
 #include "llrefcount.h"
 #include "llthreadlocalstorage.h"
diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h
deleted file mode 100644
index 798d97a46e..0000000000
--- a/indra/llcommon/llunit.h
+++ /dev/null
@@ -1,830 +0,0 @@
-/** 
- * @file llunit.h
- * @brief Unit conversion classes
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2012, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLUNIT_H
-#define LL_LLUNIT_H
-
-#include "stdtypes.h"
-#include "llpreprocessor.h"
-#include "llerror.h"
-
-//lightweight replacement of type traits for simple type equality check
-template<typename S, typename T> 
-struct LLIsSameType
-{
-	static const bool value = false;
-};
-
-template<typename T>
-struct LLIsSameType<T, T>
-{
-	static const bool value = true;
-};
-
-// workaround for decltype() not existing and typeof() not working inline in gcc 4.2
-template<typename S, typename T>
-struct LLResultTypeAdd
-{
-	typedef LL_TYPEOF(S() + T()) type_t;
-};
-
-template<typename S, typename T>
-struct LLResultTypeSubtract
-{
-	typedef LL_TYPEOF(S() - T()) type_t;
-};
-
-template<typename S, typename T>
-struct LLResultTypeMultiply
-{
-	typedef LL_TYPEOF(S() * T()) type_t;
-};
-
-template<typename S, typename T>
-struct LLResultTypeDivide
-{
-	typedef LL_TYPEOF(S() / T(1)) type_t;
-};
-
-template<typename S, typename T>
-struct LLResultTypePromote
-{
-	typedef LL_TYPEOF((true) ? S() : T()) type_t;
-};
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-struct LLUnit
-{
-	typedef LLUnit<STORAGE_TYPE, UNIT_TYPE> self_t;
-	typedef STORAGE_TYPE storage_t;
-
-	// value initialization
-	LL_FORCE_INLINE explicit LLUnit(storage_t value = storage_t())
-	:	mValue(value)
-	{}
-
-	// unit initialization and conversion
-	template<typename OTHER_STORAGE, typename OTHER_UNIT>
-	LL_FORCE_INLINE LLUnit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
-	:	mValue(convert(other).mValue)
-	{}
-	
-	storage_t value() const
-	{
-		return mValue;
-	}
-
-	void value(storage_t value)
-	{
-		mValue = value;
-	}
-
-	template<typename NEW_UNIT_TYPE> 
-	storage_t valueInUnits()
-	{
-		return LLUnit<storage_t, NEW_UNIT_TYPE>(*this).value();
-	}
-
-	template<typename NEW_UNIT_TYPE> 
-	void valueInUnits(storage_t value)
-	{
-		*this = LLUnit<storage_t, NEW_UNIT_TYPE>(value);
-	}
-
-	void operator += (self_t other)
-	{
-		mValue += convert(other).mValue;
-	}
-
-	void operator -= (self_t other)
-	{
-		mValue -= convert(other).mValue;
-	}
-
-	void operator *= (storage_t multiplicand)
-	{
-		mValue *= multiplicand;
-	}
-
-	void operator *= (self_t multiplicand)
-	{
-		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
-		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported.");
-	}
-
-	void operator /= (storage_t divisor)
-	{
-		mValue /= divisor;
-	}
-
-	void operator /= (self_t divisor)
-	{
-		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
-		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types.");
-	}
-
-	template<typename SOURCE_STORAGE, typename SOURCE_UNITS>
-	LL_FORCE_INLINE static self_t convert(LLUnit<SOURCE_STORAGE, SOURCE_UNITS> v) 
-	{ 
-		typedef typename LLResultTypePromote<STORAGE_TYPE, SOURCE_STORAGE>::type_t result_storage_t;
-		LLUnit<result_storage_t, UNIT_TYPE> result;
-		result_storage_t divisor = ll_convert_units(v, result);
-		result.value(result.value() / divisor);
-		return self_t(result.value());
-	}
-
-protected:
-	storage_t mValue;
-};
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-std::ostream& operator <<(std::ostream& s, const LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit)
-{
-        s << unit.value() << UNIT_TYPE::getUnitLabel();
-        return s;
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit)
-{
-        STORAGE_TYPE val;
-        s >> val;
-        unit.value(val);
-        return s;
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
-{
-	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_STORAGE, typename OTHER_UNIT>
-	LLUnitImplicit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
-	:	base_t(other)
-	{}
-
-	// unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc)
-	// this allows for interoperability with legacy code
-	operator storage_t() const
-	{
-		return base_t::value();
-	}
-
-	using base_t::operator +=;
-	void operator += (storage_t value)
-	{
-        base_t::mValue += value;
-	}
-
-	// this overload exists to explicitly catch use of another implicit unit
-	// without ambiguity between conversion to storage_t vs conversion to base_t
-	template<typename OTHER_STORAGE, typename OTHER_UNIT>
-	void operator += (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
-	{
-        base_t::mValue += convert(other).value();
-	}
-
-	using base_t::operator -=;
-	void operator -= (storage_t value)
-	{
-        base_t::mValue -= value;
-	}
-
-	// this overload exists to explicitly catch use of another implicit unit
-	// without ambiguity between conversion to storage_t vs conversion to base_t
-	template<typename OTHER_STORAGE, typename OTHER_UNIT>
-	void operator -= (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
-	{
-        base_t::mValue -= convert(other).value();
-	}
-
-};
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-std::ostream& operator <<(std::ostream& s, const LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>& unit)
-{
-        s << unit.value() << UNIT_TYPE::getUnitLabel();
-        return s;
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>& unit)
-{
-        STORAGE_TYPE val;
-        s >> val;
-        unit = val;
-        return s;
-}
-
-template<typename S1, typename T1, typename S2, typename T2>
-LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out)
-{
-	S2 divisor(1);
-
-	LL_STATIC_ASSERT((LLIsSameType<T1, T2>::value 
-						|| !LLIsSameType<T1, typename T1::base_unit_t>::value 
-						|| !LLIsSameType<T2, typename T2::base_unit_t>::value), 
-						"conversion requires compatible units");
-
-	if (LLIsSameType<T1, T2>::value)
-	{
-		// T1 and T2 same type, just assign
-		out.value((S2)in.value());
-	}
-	else if (T1::sLevel > T2::sLevel)
-	{
-		// reduce T1
-		LLUnit<S2, typename T1::base_unit_t> new_in;
-		divisor *= (S2)ll_convert_units(in, new_in);
-		divisor *= (S2)ll_convert_units(new_in, out);
-	}
-	else
-	{
-		// reduce T2
-		LLUnit<S2, typename T2::base_unit_t> new_out;
-		divisor *= (S2)ll_convert_units(in, new_out);
-		divisor *= (S2)ll_convert_units(new_out, out);
-	}
-	return divisor;
-}
-
-template<typename T>
-struct LLStorageType
-{
-	typedef T type_t;
-};
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-struct LLStorageType<LLUnit<STORAGE_TYPE, UNIT_TYPE> >
-{
-	typedef STORAGE_TYPE type_t;
-};
-
-// all of these operators need to perform type promotion on the storage type of the units, so they 
-// cannot be expressed as operations on identical types with implicit unit conversion 
-// e.g. typeof(S32Bytes(x) + F32Megabytes(y)) <==> F32Bytes
-
-//
-// operator +
-//
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
-{
-	LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
-	result += second;
-	return result;
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
-LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS second)
-{
-	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
-LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (UNITLESS first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
-{
-	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
-}
-
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
-{
-	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
-	result += second;
-	return result;
-}
-
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
-{
-	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
-	result += second;
-	return result;
-}
-
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
-{
-	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
-	result += LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
-	return result;
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
-{
-	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> result(first);
-	result += second;
-	return result;
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::
-	type_t, UNIT_TYPE> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
-{
-	LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> result(first);
-	result += second;
-	return result;
-}
-
-//
-// operator -
-//
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
-{
-	LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
-	result -= second;
-	return result;
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
-LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS second)
-{
-	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
-LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (UNITLESS first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
-{
-	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
-}
-
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
-{
-	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
-	result -= second;
-	return result;
-}
-
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
-{
-	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
-	result -= second;
-	return result;
-}
-
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
-{
-	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
-	result -= LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
-	return result;
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator - (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
-{
-	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> result(first);
-	result -= second;
-	return result;
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
-{
-	LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> result(first);
-	result -= second;
-	return result;
-}
-
-//
-// operator *
-//
-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
-	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
-	return LLUnit<STORAGE_TYPE1, UNIT_TYPE1>();
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
-{
-	return LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() * second);
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
-{
-	return LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE>(first * second.value());
-}
-
-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
-	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
-	return LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>();
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator * (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
-{
-	return LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, UNITLESS_TYPE>::type_t, UNIT_TYPE>(first.value() * second);
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
-{
-	return LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE>(first * second.value());
-}
-
-
-//
-// operator /
-//
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
-{
-	return LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() / second);
-}
-
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
-{
-	return first.value() / first.convert(second).value();
-}
-
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator / (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
-{
-	return LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() / second);
-}
-
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
-{
-	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
-}
-
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
-{
-	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
-}
-
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
-{
-	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
-}
-
-//
-// comparison operators
-//
-
-#define LL_UNIT_DECLARE_COMPARISON_OPERATOR(op)                                                                            \
-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).value();                                                                 \
-}                                                                                                                          \
-	                                                                                                                       \
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
-bool operator op (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)                                     \
-{                                                                                                                          \
-	return first.value() op second;                                                                                        \
-}                                                                                                                          \
-                                                                                                                           \
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
-bool operator op (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)                                     \
-{                                                                                                                          \
-	return first op second.value();                                                                                        \
-}                                                                                                                          \
-                                                                                                                           \
-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).value();                                                                 \
-}                                                                                                                          \
-                                                                                                                           \
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
-bool operator op (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)                                             \
-{                                                                                                                          \
-	LL_BAD_TEMPLATE_INSTANTIATION(UNITLESS_TYPE, "operator " #op " requires compatible unit types");                       \
-	return false;                                                                                                          \
-}                                                                                                                          \
-                                                                                                                           \
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
-bool operator op (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)                                             \
-{                                                                                                                          \
-	LL_BAD_TEMPLATE_INSTANTIATION(UNITLESS_TYPE, "operator " #op " requires compatible unit types");                       \
-	return false;                                                                                                          \
-}                                                                                                                          \
-	                                                                                                                       \
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \
-bool operator op (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)               \
-{                                                                                                                          \
-	return first.value() op first.convert(second).value();                                                                 \
-}                                                                                                                          \
-                                                                                                                           \
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \
-bool operator op (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)               \
-{                                                                                                                          \
-	return first.value() op first.convert(second).value();                                                                 \
-}
-
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(<);
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(<=);
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(>);
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(>=);
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(==);
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(!=);
-
-
-template<typename T> 
-struct LLGetUnitLabel
-{
-	static const char* getUnitLabel() { return ""; }
-};
-
-template<typename T, typename STORAGE_T>
-struct LLGetUnitLabel<LLUnit<STORAGE_T, T> >
-{
-	static const char* getUnitLabel() { return T::getUnitLabel(); }
-};
-
-template<typename T>
-struct LLUnitLinearOps
-{
-	typedef LLUnitLinearOps<T> self_t;
-
-	LLUnitLinearOps(T val) 
-	:	mValue(val),
-		mDivisor(1)
-	{}
-
-	template<typename OTHER_T>
-	self_t operator * (OTHER_T other)
-	{
-		return mValue * other;
-	}
-
-	template<typename OTHER_T>
-	self_t operator / (OTHER_T other)
-	{
-		mDivisor *= other;
-		return *this;
-	}
-
-	template<typename OTHER_T>
-	self_t operator + (OTHER_T other)
-	{
-		mValue /= mDivisor;
-		mValue += other;
-		return *this;
-	}
-
-	template<typename OTHER_T>
-	self_t operator - (OTHER_T other)
-	{
-		mValue /= mDivisor;
-		mValue -= other;
-		return *this;
-	}
-
-	T mValue;
-	T mDivisor;
-};
-
-template<typename T>
-struct LLUnitInverseLinearOps
-{
-	typedef LLUnitInverseLinearOps<T> self_t;
-
-	LLUnitInverseLinearOps(T val) 
-	:	mValue(val),
-		mDivisor(1)
-	{}
-
-	template<typename OTHER_T>
-	self_t operator * (OTHER_T other)
-	{
-		mDivisor *= other;
-		return *this;
-	}
-
-	template<typename OTHER_T>
-	self_t operator / (OTHER_T other)
-	{
-		mValue *= other;
-		return *this;
-	}
-
-	template<typename OTHER_T>
-	self_t operator + (OTHER_T other)
-	{
-		mValue /= mDivisor;
-		mValue -= other;
-		return *this;
-	}
-
-	template<typename OTHER_T>
-	self_t operator - (OTHER_T other)
-	{
-		mValue /= mDivisor;
-		mValue += other;
-		return *this;
-	}
-
-	T mValue;
-	T mDivisor;
-};
-
-#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label)                                             \
-struct base_unit_name                                                                                \
-{                                                                                                    \
-	static const int sLevel = 0;                                                                     \
-	typedef base_unit_name base_unit_t;                                                              \
-	static const char* getUnitLabel() { return unit_label; }                                         \
-	template<typename T>                                                                             \
-	static LLUnit<T, base_unit_name> fromValue(T value) { return LLUnit<T, base_unit_name>(value); } \
-	template<typename STORAGE_T, typename UNIT_T>                                                    \
-	static LLUnit<STORAGE_T, base_unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)              \
-	{ return LLUnit<STORAGE_T, base_unit_name>(value); }                                             \
-}
-
-
-#define LL_DECLARE_DERIVED_UNIT(base_unit_name, conversion_operation, unit_name, unit_label)	 \
-struct unit_name                                                                                 \
-{                                                                                                \
-	static const int sLevel = base_unit_name::sLevel + 1;                                        \
-	typedef base_unit_name base_unit_t;                                                          \
-	static const char* getUnitLabel() { return unit_label; }									 \
-	template<typename T>                                                                         \
-	static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); }		 \
-	template<typename STORAGE_T, typename UNIT_T>                                                \
-	static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)				 \
-	{ return LLUnit<STORAGE_T, unit_name>(value); }												 \
-};                                                                                               \
-	                                                                                             \
-template<typename S1, typename S2>                                                               \
-LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)   \
-{                                                                                                \
-	typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t;                       \
-	LLUnitLinearOps<result_storage_t> op =                                                       \
-		LLUnitLinearOps<result_storage_t>(in.value()) conversion_operation;                      \
-	out = LLUnit<S2, base_unit_name>((S2)op.mValue);	                                         \
-	return op.mDivisor;                                                                          \
-}                                                                                                \
-                                                                                                 \
-template<typename S1, typename S2>                                                               \
-LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)   \
-{                                                                                                \
-	typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t;                       \
-	LLUnitInverseLinearOps<result_storage_t> op =                                                \
-		LLUnitInverseLinearOps<result_storage_t>(in.value()) conversion_operation;               \
-	out = LLUnit<S2, unit_name>((S2)op.mValue);                                                  \
-	return op.mDivisor;                                                                          \
-}                                                                                               
-
-#define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name)                         \
-	typedef LLUnit<F32, ns::unit_name> F32##unit_name;                  \
-	typedef LLUnitImplicit<F32, ns::unit_name> F32##unit_name##Implicit;\
-	typedef LLUnit<F64, ns::unit_name> F64##unit_name;                  \
-	typedef LLUnitImplicit<F64, ns::unit_name> F64##unit_name##Implicit;\
-	typedef LLUnit<S32, ns::unit_name> S32##unit_name;                  \
-	typedef LLUnitImplicit<S32, ns::unit_name> S32##unit_name##Implicit;\
-	typedef LLUnit<S64, ns::unit_name> S64##unit_name;                  \
-	typedef LLUnitImplicit<S64, ns::unit_name> S64##unit_name##Implicit;\
-	typedef LLUnit<U32, ns::unit_name> U32##unit_name;                  \
-	typedef LLUnitImplicit<U32, ns::unit_name> U32##unit_name##Implicit;\
-	typedef LLUnit<U64, ns::unit_name> U64##unit_name;                  \
-	typedef LLUnitImplicit<U64, ns::unit_name> U64##unit_name##Implicit
-
-//
-// Unit declarations
-//
-
-namespace LLUnits
-{
-LL_DECLARE_BASE_UNIT(Bytes, "B");
-// technically, these are kibibytes, mibibytes, etc. but we should stick with commonly accepted terminology
-LL_DECLARE_DERIVED_UNIT(Bytes, * 1024,			Kilobytes, "KB");
-LL_DECLARE_DERIVED_UNIT(Kilobytes, * 1024,		Megabytes, "MB");
-LL_DECLARE_DERIVED_UNIT(Megabytes, * 1024,		Gigabytes, "GB");
-}
-
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bytes);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobytes);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabytes);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabytes);
-
-namespace LLUnits
-{
-// technically, these are kibibits, mibibits, etc. but we should stick with commonly accepted terminology
-LL_DECLARE_DERIVED_UNIT(Bytes, / 8,				Bits, "b");
-LL_DECLARE_DERIVED_UNIT(Bits, * 1024,			Kilobits, "Kb");
-LL_DECLARE_DERIVED_UNIT(Kilobits, * 1024,		Megabits, "Mb");  
-LL_DECLARE_DERIVED_UNIT(Megabits, * 1024,		Gigabits, "Gb");
-}
-
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bits);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobits);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabits);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabits);
-
-namespace LLUnits
-{
-LL_DECLARE_BASE_UNIT(Seconds, "s");
-LL_DECLARE_DERIVED_UNIT(Seconds, * 60,			Minutes, "min");
-LL_DECLARE_DERIVED_UNIT(Minutes, * 60,			Hours, "h");
-LL_DECLARE_DERIVED_UNIT(Hours, * 24,			Days, "d");
-LL_DECLARE_DERIVED_UNIT(Seconds, / 1000,		Milliseconds, "ms");
-LL_DECLARE_DERIVED_UNIT(Milliseconds, / 1000,	Microseconds, "\x09\x3cs");
-LL_DECLARE_DERIVED_UNIT(Microseconds, / 1000,	Nanoseconds, "ns");
-}
-
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Seconds);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Minutes);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hours);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Days);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Milliseconds);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Microseconds);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Nanoseconds);
-
-namespace LLUnits
-{
-LL_DECLARE_BASE_UNIT(Meters, "m");
-LL_DECLARE_DERIVED_UNIT(Meters, * 1000,			Kilometers, "km");
-LL_DECLARE_DERIVED_UNIT(Meters, / 100,			Centimeters, "cm");
-LL_DECLARE_DERIVED_UNIT(Meters, / 1000,			Millimeters, "mm");
-}
-
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Meters);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilometers);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Centimeters);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Millimeters);
-
-namespace LLUnits
-{
-// rare units
-LL_DECLARE_BASE_UNIT(Hertz, "Hz");
-LL_DECLARE_DERIVED_UNIT(Hertz, * 1000,			Kilohertz, "KHz");
-LL_DECLARE_DERIVED_UNIT(Kilohertz, * 1000,		Megahertz, "MHz");
-LL_DECLARE_DERIVED_UNIT(Megahertz, * 1000,		Gigahertz, "GHz");
-
-LL_DECLARE_BASE_UNIT(Radians, "rad");
-LL_DECLARE_DERIVED_UNIT(Radians, / 57.29578f,	Degrees, "deg");
-
-LL_DECLARE_BASE_UNIT(Percent, "%");
-LL_DECLARE_DERIVED_UNIT(Percent, * 100,			Ratio, "x");
-
-LL_DECLARE_BASE_UNIT(Triangles, "tris");
-LL_DECLARE_DERIVED_UNIT(Triangles, * 1000,		Kilotriangles, "ktris");
-
-} // namespace LLUnits
-
-// rare units
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hertz);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilohertz);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megahertz);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigahertz);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Radians);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Degrees);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Percent);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Ratio);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Triangles);
-LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilotriangles);
-
-
-#endif // LL_LLUNIT_H
diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h
new file mode 100644
index 0000000000..949e4492c7
--- /dev/null
+++ b/indra/llcommon/llunittype.h
@@ -0,0 +1,734 @@
+/** 
+ * @file llunit.h
+ * @brief Unit conversion classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_UNITTYPE_H
+#define LL_UNITTYPE_H
+
+#include "stdtypes.h"
+#include "llpreprocessor.h"
+#include "llerror.h"
+
+//lightweight replacement of type traits for simple type equality check
+template<typename S, typename T> 
+struct LLIsSameType
+{
+	static const bool value = false;
+};
+
+template<typename T>
+struct LLIsSameType<T, T>
+{
+	static const bool value = true;
+};
+
+// workaround for decltype() not existing and typeof() not working inline in gcc 4.2
+template<typename S, typename T>
+struct LLResultTypeAdd
+{
+	typedef LL_TYPEOF(S() + T()) type_t;
+};
+
+template<typename S, typename T>
+struct LLResultTypeSubtract
+{
+	typedef LL_TYPEOF(S() - T()) type_t;
+};
+
+template<typename S, typename T>
+struct LLResultTypeMultiply
+{
+	typedef LL_TYPEOF(S() * T()) type_t;
+};
+
+template<typename S, typename T>
+struct LLResultTypeDivide
+{
+	typedef LL_TYPEOF(S() / T(1)) type_t;
+};
+
+template<typename S, typename T>
+struct LLResultTypePromote
+{
+	typedef LL_TYPEOF((true) ? S() : T()) type_t;
+};
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE>
+struct LLUnit
+{
+	typedef LLUnit<STORAGE_TYPE, UNIT_TYPE> self_t;
+	typedef STORAGE_TYPE storage_t;
+
+	// value initialization
+	LL_FORCE_INLINE explicit LLUnit(storage_t value = storage_t())
+	:	mValue(value)
+	{}
+
+	// unit initialization and conversion
+	template<typename OTHER_STORAGE, typename OTHER_UNIT>
+	LL_FORCE_INLINE LLUnit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
+	:	mValue(convert(other).mValue)
+	{}
+	
+	storage_t value() const
+	{
+		return mValue;
+	}
+
+	void value(storage_t value)
+	{
+		mValue = value;
+	}
+
+	template<typename NEW_UNIT_TYPE> 
+	storage_t valueInUnits()
+	{
+		return LLUnit<storage_t, NEW_UNIT_TYPE>(*this).value();
+	}
+
+	template<typename NEW_UNIT_TYPE> 
+	void valueInUnits(storage_t value)
+	{
+		*this = LLUnit<storage_t, NEW_UNIT_TYPE>(value);
+	}
+
+	void operator += (self_t other)
+	{
+		mValue += convert(other).mValue;
+	}
+
+	void operator -= (self_t other)
+	{
+		mValue -= convert(other).mValue;
+	}
+
+	void operator *= (storage_t multiplicand)
+	{
+		mValue *= multiplicand;
+	}
+
+	void operator *= (self_t multiplicand)
+	{
+		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported.");
+	}
+
+	void operator /= (storage_t divisor)
+	{
+		mValue /= divisor;
+	}
+
+	void operator /= (self_t divisor)
+	{
+		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types.");
+	}
+
+	template<typename SOURCE_STORAGE, typename SOURCE_UNITS>
+	LL_FORCE_INLINE static self_t convert(LLUnit<SOURCE_STORAGE, SOURCE_UNITS> v) 
+	{ 
+		typedef typename LLResultTypePromote<STORAGE_TYPE, SOURCE_STORAGE>::type_t result_storage_t;
+		LLUnit<result_storage_t, UNIT_TYPE> result;
+		result_storage_t divisor = ll_convert_units(v, result);
+		result.value(result.value() / divisor);
+		return self_t(result.value());
+	}
+
+protected:
+	storage_t mValue;
+};
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE>
+std::ostream& operator <<(std::ostream& s, const LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit)
+{
+        s << unit.value() << UNIT_TYPE::getUnitLabel();
+        return s;
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE>
+std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit)
+{
+        STORAGE_TYPE val;
+        s >> val;
+        unit.value(val);
+        return s;
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE>
+struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
+{
+	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_STORAGE, typename OTHER_UNIT>
+	LLUnitImplicit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
+	:	base_t(other)
+	{}
+
+	// unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc)
+	// this allows for interoperability with legacy code
+	operator storage_t() const
+	{
+		return base_t::value();
+	}
+
+	using base_t::operator +=;
+	void operator += (storage_t value)
+	{
+        base_t::mValue += value;
+	}
+
+	// this overload exists to explicitly catch use of another implicit unit
+	// without ambiguity between conversion to storage_t vs conversion to base_t
+	template<typename OTHER_STORAGE, typename OTHER_UNIT>
+	void operator += (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
+	{
+        base_t::mValue += convert(other).value();
+	}
+
+	using base_t::operator -=;
+	void operator -= (storage_t value)
+	{
+        base_t::mValue -= value;
+	}
+
+	// this overload exists to explicitly catch use of another implicit unit
+	// without ambiguity between conversion to storage_t vs conversion to base_t
+	template<typename OTHER_STORAGE, typename OTHER_UNIT>
+	void operator -= (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
+	{
+        base_t::mValue -= convert(other).value();
+	}
+
+};
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE>
+std::ostream& operator <<(std::ostream& s, const LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>& unit)
+{
+        s << unit.value() << UNIT_TYPE::getUnitLabel();
+        return s;
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE>
+std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>& unit)
+{
+        STORAGE_TYPE val;
+        s >> val;
+        unit = val;
+        return s;
+}
+
+template<typename S1, typename T1, typename S2, typename T2>
+LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out)
+{
+	S2 divisor(1);
+
+	LL_STATIC_ASSERT((LLIsSameType<T1, T2>::value 
+						|| !LLIsSameType<T1, typename T1::base_unit_t>::value 
+						|| !LLIsSameType<T2, typename T2::base_unit_t>::value), 
+						"conversion requires compatible units");
+
+	if (LLIsSameType<T1, T2>::value)
+	{
+		// T1 and T2 same type, just assign
+		out.value((S2)in.value());
+	}
+	else if (T1::sLevel > T2::sLevel)
+	{
+		// reduce T1
+		LLUnit<S2, typename T1::base_unit_t> new_in;
+		divisor *= (S2)ll_convert_units(in, new_in);
+		divisor *= (S2)ll_convert_units(new_in, out);
+	}
+	else
+	{
+		// reduce T2
+		LLUnit<S2, typename T2::base_unit_t> new_out;
+		divisor *= (S2)ll_convert_units(in, new_out);
+		divisor *= (S2)ll_convert_units(new_out, out);
+	}
+	return divisor;
+}
+
+template<typename T>
+struct LLStorageType
+{
+	typedef T type_t;
+};
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE>
+struct LLStorageType<LLUnit<STORAGE_TYPE, UNIT_TYPE> >
+{
+	typedef STORAGE_TYPE type_t;
+};
+
+// all of these operators need to perform type promotion on the storage type of the units, so they 
+// cannot be expressed as operations on identical types with implicit unit conversion 
+// e.g. typeof(S32Bytes(x) + F32Megabytes(y)) <==> F32Bytes
+
+//
+// operator +
+//
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	result += second;
+	return result;
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS second)
+{
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
+	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (UNITLESS first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
+{
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
+	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
+}
+
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	result += second;
+	return result;
+}
+
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	result += second;
+	return result;
+}
+
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	result += LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
+	return result;
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+{
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> result(first);
+	result += second;
+	return result;
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::
+	type_t, UNIT_TYPE> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+{
+	LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> result(first);
+	result += second;
+	return result;
+}
+
+//
+// operator -
+//
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	result -= second;
+	return result;
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS second)
+{
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
+	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (UNITLESS first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
+{
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
+	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
+}
+
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	result -= second;
+	return result;
+}
+
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	result -= second;
+	return result;
+}
+
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	result -= LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
+	return result;
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator - (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+{
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> result(first);
+	result -= second;
+	return result;
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+{
+	LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> result(first);
+	result -= second;
+	return result;
+}
+
+//
+// operator *
+//
+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
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
+	return LLUnit<STORAGE_TYPE1, UNIT_TYPE1>();
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+{
+	return LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() * second);
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
+{
+	return LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE>(first * second.value());
+}
+
+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
+	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
+	return LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>();
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator * (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+{
+	return LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, UNITLESS_TYPE>::type_t, UNIT_TYPE>(first.value() * second);
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+{
+	return LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE>(first * second.value());
+}
+
+
+//
+// operator /
+//
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+{
+	return LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() / second);
+}
+
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	return first.value() / first.convert(second).value();
+}
+
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
+LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator / (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+{
+	return LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() / second);
+}
+
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
+}
+
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
+}
+
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
+typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+{
+	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
+}
+
+//
+// comparison operators
+//
+
+#define LL_UNIT_DECLARE_COMPARISON_OPERATOR(op)                                                                            \
+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).value();                                                                 \
+}                                                                                                                          \
+	                                                                                                                       \
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
+bool operator op (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)                                     \
+{                                                                                                                          \
+	return first.value() op second;                                                                                        \
+}                                                                                                                          \
+                                                                                                                           \
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
+bool operator op (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)                                     \
+{                                                                                                                          \
+	return first op second.value();                                                                                        \
+}                                                                                                                          \
+                                                                                                                           \
+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).value();                                                                 \
+}                                                                                                                          \
+                                                                                                                           \
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
+bool operator op (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)                                             \
+{                                                                                                                          \
+	LL_BAD_TEMPLATE_INSTANTIATION(UNITLESS_TYPE, "operator " #op " requires compatible unit types");                       \
+	return false;                                                                                                          \
+}                                                                                                                          \
+                                                                                                                           \
+template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
+bool operator op (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)                                             \
+{                                                                                                                          \
+	LL_BAD_TEMPLATE_INSTANTIATION(UNITLESS_TYPE, "operator " #op " requires compatible unit types");                       \
+	return false;                                                                                                          \
+}                                                                                                                          \
+	                                                                                                                       \
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \
+bool operator op (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)               \
+{                                                                                                                          \
+	return first.value() op first.convert(second).value();                                                                 \
+}                                                                                                                          \
+                                                                                                                           \
+template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \
+bool operator op (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)               \
+{                                                                                                                          \
+	return first.value() op first.convert(second).value();                                                                 \
+}
+
+LL_UNIT_DECLARE_COMPARISON_OPERATOR(<);
+LL_UNIT_DECLARE_COMPARISON_OPERATOR(<=);
+LL_UNIT_DECLARE_COMPARISON_OPERATOR(>);
+LL_UNIT_DECLARE_COMPARISON_OPERATOR(>=);
+LL_UNIT_DECLARE_COMPARISON_OPERATOR(==);
+LL_UNIT_DECLARE_COMPARISON_OPERATOR(!=);
+
+
+template<typename T> 
+struct LLGetUnitLabel
+{
+	static const char* getUnitLabel() { return ""; }
+};
+
+template<typename T, typename STORAGE_T>
+struct LLGetUnitLabel<LLUnit<STORAGE_T, T> >
+{
+	static const char* getUnitLabel() { return T::getUnitLabel(); }
+};
+
+template<typename T>
+struct LLUnitLinearOps
+{
+	typedef LLUnitLinearOps<T> self_t;
+
+	LLUnitLinearOps(T val) 
+	:	mValue(val),
+		mDivisor(1)
+	{}
+
+	template<typename OTHER_T>
+	self_t operator * (OTHER_T other)
+	{
+		return mValue * other;
+	}
+
+	template<typename OTHER_T>
+	self_t operator / (OTHER_T other)
+	{
+		mDivisor *= other;
+		return *this;
+	}
+
+	template<typename OTHER_T>
+	self_t operator + (OTHER_T other)
+	{
+		mValue /= mDivisor;
+		mValue += other;
+		return *this;
+	}
+
+	template<typename OTHER_T>
+	self_t operator - (OTHER_T other)
+	{
+		mValue /= mDivisor;
+		mValue -= other;
+		return *this;
+	}
+
+	T mValue;
+	T mDivisor;
+};
+
+template<typename T>
+struct LLUnitInverseLinearOps
+{
+	typedef LLUnitInverseLinearOps<T> self_t;
+
+	LLUnitInverseLinearOps(T val) 
+	:	mValue(val),
+		mDivisor(1)
+	{}
+
+	template<typename OTHER_T>
+	self_t operator * (OTHER_T other)
+	{
+		mDivisor *= other;
+		return *this;
+	}
+
+	template<typename OTHER_T>
+	self_t operator / (OTHER_T other)
+	{
+		mValue *= other;
+		return *this;
+	}
+
+	template<typename OTHER_T>
+	self_t operator + (OTHER_T other)
+	{
+		mValue /= mDivisor;
+		mValue -= other;
+		return *this;
+	}
+
+	template<typename OTHER_T>
+	self_t operator - (OTHER_T other)
+	{
+		mValue /= mDivisor;
+		mValue += other;
+		return *this;
+	}
+
+	T mValue;
+	T mDivisor;
+};
+
+#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label)                                             \
+struct base_unit_name                                                                                \
+{                                                                                                    \
+	static const int sLevel = 0;                                                                     \
+	typedef base_unit_name base_unit_t;                                                              \
+	static const char* getUnitLabel() { return unit_label; }                                         \
+	template<typename T>                                                                             \
+	static LLUnit<T, base_unit_name> fromValue(T value) { return LLUnit<T, base_unit_name>(value); } \
+	template<typename STORAGE_T, typename UNIT_T>                                                    \
+	static LLUnit<STORAGE_T, base_unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)              \
+	{ return LLUnit<STORAGE_T, base_unit_name>(value); }                                             \
+}
+
+
+#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation)	 \
+struct unit_name                                                                                 \
+{                                                                                                \
+	static const int sLevel = base_unit_name::sLevel + 1;                                        \
+	typedef base_unit_name base_unit_t;                                                          \
+	static const char* getUnitLabel() { return unit_label; }									 \
+	template<typename T>                                                                         \
+	static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); }		 \
+	template<typename STORAGE_T, typename UNIT_T>                                                \
+	static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value)				 \
+	{ return LLUnit<STORAGE_T, unit_name>(value); }												 \
+};                                                                                               \
+	                                                                                             \
+template<typename S1, typename S2>                                                               \
+LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)   \
+{                                                                                                \
+	typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t;                       \
+	LLUnitInverseLinearOps<result_storage_t> op =                                                \
+		LLUnitInverseLinearOps<result_storage_t>(in.value()) conversion_operation;               \
+	out = LLUnit<S2, base_unit_name>((S2)op.mValue);	                                         \
+	return op.mDivisor;                                                                          \
+}                                                                                                \
+                                                                                                 \
+template<typename S1, typename S2>                                                               \
+LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)   \
+{                                                                                                \
+	typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t;                       \
+	LLUnitLinearOps<result_storage_t> op =                                                       \
+		LLUnitLinearOps<result_storage_t>(in.value()) conversion_operation;				         \
+	out = LLUnit<S2, unit_name>((S2)op.mValue);                                                  \
+	return op.mDivisor;                                                                          \
+}                                                                                               
+
+#define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name)                         \
+	typedef LLUnit<F32, ns::unit_name> F32##unit_name;                  \
+	typedef LLUnitImplicit<F32, ns::unit_name> F32##unit_name##Implicit;\
+	typedef LLUnit<F64, ns::unit_name> F64##unit_name;                  \
+	typedef LLUnitImplicit<F64, ns::unit_name> F64##unit_name##Implicit;\
+	typedef LLUnit<S32, ns::unit_name> S32##unit_name;                  \
+	typedef LLUnitImplicit<S32, ns::unit_name> S32##unit_name##Implicit;\
+	typedef LLUnit<S64, ns::unit_name> S64##unit_name;                  \
+	typedef LLUnitImplicit<S64, ns::unit_name> S64##unit_name##Implicit;\
+	typedef LLUnit<U32, ns::unit_name> U32##unit_name;                  \
+	typedef LLUnitImplicit<U32, ns::unit_name> U32##unit_name##Implicit;\
+	typedef LLUnit<U64, ns::unit_name> U64##unit_name;                  \
+	typedef LLUnitImplicit<U64, ns::unit_name> U64##unit_name##Implicit
+
+#endif //LL_UNITTYPE_H
diff --git a/indra/llcommon/tests/lltrace_test.cpp b/indra/llcommon/tests/lltrace_test.cpp
index 1c2a4528ae..8ce509699d 100644
--- a/indra/llcommon/tests/lltrace_test.cpp
+++ b/indra/llcommon/tests/lltrace_test.cpp
@@ -36,12 +36,12 @@ namespace LLUnits
 {
 	// using powers of 2 to allow strict floating point equality
 	LL_DECLARE_BASE_UNIT(Ounces, "oz");
-	LL_DECLARE_DERIVED_UNIT(Ounces, * 12, TallCup, "");
-	LL_DECLARE_DERIVED_UNIT(Ounces, * 16, GrandeCup, "");
-	LL_DECLARE_DERIVED_UNIT(Ounces, * 20, VentiCup, "");
+	LL_DECLARE_DERIVED_UNIT(TallCup, "", Ounces, / 12);
+	LL_DECLARE_DERIVED_UNIT(GrandeCup, "", Ounces, / 16);
+	LL_DECLARE_DERIVED_UNIT(VentiCup, "", Ounces, / 20);
 
 	LL_DECLARE_BASE_UNIT(Grams, "g");
-	LL_DECLARE_DERIVED_UNIT(Grams, / 1000, Milligrams, "mg");
+	LL_DECLARE_DERIVED_UNIT(Milligrams, "mg", Grams, * 1000);
 }
 
 LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Ounces);
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index 31d4f86159..5a18603e4e 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -27,15 +27,15 @@
 
 #include "linden_common.h"
 
-#include "llunit.h"
+#include "llunits.h"
 #include "../test/lltut.h"
 
 namespace LLUnits
 {
 	// using powers of 2 to allow strict floating point equality
 	LL_DECLARE_BASE_UNIT(Quatloos, "Quat");
-	LL_DECLARE_DERIVED_UNIT(Quatloos, * 4, Latinum, "Lat");
-	LL_DECLARE_DERIVED_UNIT(Latinum, / 16, Solari, "Sol");
+	LL_DECLARE_DERIVED_UNIT(Latinum, "Lat", Quatloos, / 4);
+	LL_DECLARE_DERIVED_UNIT(Solari, "Sol", Latinum, * 16);
 }
 
 LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Quatloos);
@@ -256,6 +256,12 @@ namespace tut
 		// conversion of implicits
 		LLUnitImplicit<F32, Latinum> latinum_implicit(2);
 		ensure("implicit units of different types are comparable", latinum_implicit * 2 == quatloos_implicit);
+
+		quatloos_implicit += F32Quatloos(10);
+		ensure("can add-assign explicit units", quatloos_implicit == 26);
+
+		quatloos_implicit -= F32Quatloos(10);
+		ensure("can subtract-assign explicit units", quatloos_implicit == 16);
 	}
 
 	// precision tests
@@ -272,4 +278,65 @@ namespace tut
 		mega_bytes = (U32Megabytes)5 + (S32Megabytes)-1;
 		ensure("can mix unsigned and signed in units addition", mega_bytes == (S32Megabytes)4);
 	}
+
+	// default units
+	template<> template<>
+	void units_object_t::test<9>()
+	{
+		U32Gigabytes GB(1);
+		U32Megabytes MB(GB);
+		U32Kilobytes KB(GB);
+		U32Bytes B(GB);
+
+		ensure("GB -> MB conversion", MB.value() == 1024);
+		ensure("GB -> KB conversion", KB.value() == 1024 * 1024);
+		ensure("GB -> B conversion", B.value() == 1024 * 1024 * 1024);
+
+		KB = U32Kilobytes(1);
+		U32Kilobits Kb(KB);
+		U32Bits b(KB);
+		ensure("KB -> Kb conversion", Kb.value() == 8);
+		ensure("KB -> b conversion", b.value() == 8 * 1024);
+
+		U32Days days(1);
+		U32Hours hours(days);
+		U32Minutes minutes(days);
+		U32Seconds seconds(days);
+		U32Milliseconds ms(days);
+		
+		ensure("days -> hours conversion", hours.value() == 24);
+		ensure("days -> minutes conversion", minutes.value() == 24 * 60);
+		ensure("days -> seconds conversion", seconds.value() == 24 * 60 * 60);
+		ensure("days -> ms conversion", ms.value() == 24 * 60 * 60 * 1000);
+
+		U32Kilometers km(1);
+		U32Meters m(km);
+		U32Centimeters cm(km);
+		U32Millimeters mm(km);
+
+		ensure("km -> m conversion", m.value() == 1000);
+		ensure("km -> cm conversion", cm.value() == 1000 * 100);
+		ensure("km -> mm conversion", mm.value() == 1000 * 1000);
+		
+		U32Gigahertz GHz(1);
+		U32Megahertz MHz(GHz);
+		U32Kilohertz KHz(GHz);
+		U32Hertz	 Hz(GHz);
+
+		ensure("GHz -> MHz conversion", MHz.value() == 1000);
+		ensure("GHz -> KHz conversion", KHz.value() == 1000 * 1000);
+		ensure("GHz -> Hz conversion", Hz.value() == 1000 * 1000 * 1000);
+
+		F32Radians rad(6.2831853071795f);
+		F32Degrees deg(rad);
+		ensure("radians -> degrees conversion", deg.value() > 359 && deg.value() < 361);
+
+		F32Percent percent(50);
+		F32Ratio ratio(percent);
+		ensure("percent -> ratio conversion", ratio.value() == 0.5f);
+
+		U32Kilotriangles ktris(1);
+		U32Triangles tris(ktris);
+		ensure("kilotriangles -> triangles conversion", tris.value() == 1000);
+	}
 }
-- 
cgit v1.2.3


From 9dbc3b50a4fe0e5196855ab5b16ec6af7cafa337 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 27 Aug 2013 14:44:49 -0700
Subject: forgot a file

---
 indra/llcommon/llunits.h | 129 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 129 insertions(+)
 create mode 100644 indra/llcommon/llunits.h

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llunits.h b/indra/llcommon/llunits.h
new file mode 100644
index 0000000000..0fcb8281a0
--- /dev/null
+++ b/indra/llcommon/llunits.h
@@ -0,0 +1,129 @@
+/** 
+ * @file llunits.h
+ * @brief Unit definitions
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ * 
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLUNITTYPE_H
+#define LL_LLUNITTYPE_H
+
+#include "stdtypes.h"
+#include "llunittype.h"
+
+//
+// Unit declarations
+//
+
+namespace LLUnits
+{
+LL_DECLARE_BASE_UNIT(Bytes, "B");
+// technically, these are kibibytes, mibibytes, etc. but we should stick with commonly accepted terminology
+LL_DECLARE_DERIVED_UNIT(Kilobytes, "KB", Bytes, / 1024);
+LL_DECLARE_DERIVED_UNIT(Megabytes, "MB", Kilobytes, / 1024);
+LL_DECLARE_DERIVED_UNIT(Gigabytes, "GB", Megabytes, / 1024);
+}
+
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bytes);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobytes);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabytes);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabytes);
+
+namespace LLUnits
+{
+// technically, these are kibibits, mibibits, etc. but we should stick with commonly accepted terminology
+LL_DECLARE_DERIVED_UNIT(Bits,		"b", 	Bytes, * 8	);
+LL_DECLARE_DERIVED_UNIT(Kilobits,	"Kb",	Bits, / 1024);
+LL_DECLARE_DERIVED_UNIT(Megabits,	"Mb",	Kilobits, / 1024);  
+LL_DECLARE_DERIVED_UNIT(Gigabits,	"Gb",	Megabits, / 1024);
+}
+
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bits);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobits);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabits);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabits);
+
+namespace LLUnits
+{
+LL_DECLARE_BASE_UNIT(Seconds, "s");
+LL_DECLARE_DERIVED_UNIT(Minutes,		"min",			Seconds, / 60);
+LL_DECLARE_DERIVED_UNIT(Hours,			"h",			Minutes, / 60);
+LL_DECLARE_DERIVED_UNIT(Days,			"d",			Hours, / 24);
+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_UNIT_TYPEDEFS(LLUnits, Seconds);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Minutes);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hours);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Days);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Milliseconds);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Microseconds);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Nanoseconds);
+
+namespace LLUnits
+{
+LL_DECLARE_BASE_UNIT(Meters, "m");
+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_UNIT_TYPEDEFS(LLUnits, Meters);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilometers);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Centimeters);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Millimeters);
+
+namespace LLUnits
+{
+// rare units
+LL_DECLARE_BASE_UNIT(Hertz, "Hz");
+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(Degrees, "deg", Radians, * 57.29578f);
+
+LL_DECLARE_BASE_UNIT(Percent, "%");
+LL_DECLARE_DERIVED_UNIT(Ratio, "x", Percent, / 100);
+
+LL_DECLARE_BASE_UNIT(Triangles, "tris");
+LL_DECLARE_DERIVED_UNIT(Kilotriangles, "ktris", Triangles, / 1000);
+
+} // namespace LLUnits
+
+// rare units
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hertz);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilohertz);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megahertz);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigahertz);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Radians);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Degrees);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Percent);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Ratio);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Triangles);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilotriangles);
+
+
+#endif // LL_LLUNITTYPE_H
-- 
cgit v1.2.3


From 014969690bed06d77cc2e08efbd2dc9b71fb0cd2 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 27 Aug 2013 16:04:15 -0700
Subject: shuffled things around to get MSVC optimizer to generate optimal code
 in particular, created shortcut overloads for conversions and moved
 comparison operators into member functions

---
 indra/llcommon/llunittype.h | 445 +++++++++++++++++++++++++-------------------
 1 file changed, 253 insertions(+), 192 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h
index 949e4492c7..a5e99070b6 100644
--- a/indra/llcommon/llunittype.h
+++ b/indra/llcommon/llunittype.h
@@ -75,10 +75,10 @@ struct LLResultTypePromote
 	typedef LL_TYPEOF((true) ? S() : T()) type_t;
 };
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
+template<typename STORAGE_TYPE, typename UNITS>
 struct LLUnit
 {
-	typedef LLUnit<STORAGE_TYPE, UNIT_TYPE> self_t;
+	typedef LLUnit<STORAGE_TYPE, UNITS> self_t;
 	typedef STORAGE_TYPE storage_t;
 
 	// value initialization
@@ -87,55 +87,55 @@ struct LLUnit
 	{}
 
 	// unit initialization and conversion
-	template<typename OTHER_STORAGE, typename OTHER_UNIT>
-	LL_FORCE_INLINE LLUnit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE LLUnit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
 	:	mValue(convert(other).mValue)
 	{}
 	
-	storage_t value() const
+	LL_FORCE_INLINE storage_t value() const
 	{
 		return mValue;
 	}
 
-	void value(storage_t value)
+	LL_FORCE_INLINE void value(storage_t value)
 	{
 		mValue = value;
 	}
 
-	template<typename NEW_UNIT_TYPE> 
+	template<typename NEW_UNITS> 
 	storage_t valueInUnits()
 	{
-		return LLUnit<storage_t, NEW_UNIT_TYPE>(*this).value();
+		return LLUnit<storage_t, NEW_UNITS>(*this).value();
 	}
 
-	template<typename NEW_UNIT_TYPE> 
+	template<typename NEW_UNITS> 
 	void valueInUnits(storage_t value)
 	{
-		*this = LLUnit<storage_t, NEW_UNIT_TYPE>(value);
+		*this = LLUnit<storage_t, NEW_UNITS>(value);
 	}
 
-	void operator += (self_t other)
+	LL_FORCE_INLINE void operator += (self_t other)
 	{
 		mValue += convert(other).mValue;
 	}
 
-	void operator -= (self_t other)
+	LL_FORCE_INLINE void operator -= (self_t other)
 	{
 		mValue -= convert(other).mValue;
 	}
 
-	void operator *= (storage_t multiplicand)
+	LL_FORCE_INLINE void operator *= (storage_t multiplicand)
 	{
 		mValue *= multiplicand;
 	}
 
-	void operator *= (self_t multiplicand)
+	LL_FORCE_INLINE void operator *= (self_t multiplicand)
 	{
 		// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
 		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported.");
 	}
 
-	void operator /= (storage_t divisor)
+	LL_FORCE_INLINE void operator /= (storage_t divisor)
 	{
 		mValue /= divisor;
 	}
@@ -146,11 +146,58 @@ struct LLUnit
 		LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types.");
 	}
 
-	template<typename SOURCE_STORAGE, typename SOURCE_UNITS>
-	LL_FORCE_INLINE static self_t convert(LLUnit<SOURCE_STORAGE, SOURCE_UNITS> v) 
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue == convert(other).value();
+	}
+
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue != convert(other).value();
+	}
+
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue < convert(other).value();
+	}
+
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue <= convert(other).value();
+	}
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue > convert(other).value();
+	}
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue >= convert(other).value();
+	}
+
+	LL_FORCE_INLINE static self_t convert(self_t v) 
 	{ 
-		typedef typename LLResultTypePromote<STORAGE_TYPE, SOURCE_STORAGE>::type_t result_storage_t;
-		LLUnit<result_storage_t, UNIT_TYPE> result;
+		return v;
+	}
+
+	template<typename FROM_STORAGE_TYPE>
+	LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, UNITS> v) 
+	{
+		self_t result;
+		result.mValue = (STORAGE_TYPE)v.value();
+		return result;
+	}
+
+	template<typename FROM_STORAGE_TYPE, typename FROM_UNITS>
+	LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, FROM_UNITS> v) 
+	{ 
+		typedef typename LLResultTypePromote<FROM_STORAGE_TYPE, STORAGE_TYPE>::type_t result_storage_t;
+		LLUnit<result_storage_t, UNITS> result;
 		result_storage_t divisor = ll_convert_units(v, result);
 		result.value(result.value() / divisor);
 		return self_t(result.value());
@@ -160,15 +207,15 @@ protected:
 	storage_t mValue;
 };
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-std::ostream& operator <<(std::ostream& s, const LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit)
+template<typename STORAGE_TYPE, typename UNITS>
+std::ostream& operator <<(std::ostream& s, const LLUnit<STORAGE_TYPE, UNITS>& unit)
 {
-        s << unit.value() << UNIT_TYPE::getUnitLabel();
+        s << unit.value() << UNITS::getUnitLabel();
         return s;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit)
+template<typename STORAGE_TYPE, typename UNITS>
+std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNITS>& unit)
 {
         STORAGE_TYPE val;
         s >> val;
@@ -176,68 +223,145 @@ std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNIT_TYPE>& unit
         return s;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNIT_TYPE>
+template<typename STORAGE_TYPE, typename UNITS>
+struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
 {
-	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;
+	typedef LLUnitImplicit<STORAGE_TYPE, UNITS> self_t;
+	typedef typename LLUnit<STORAGE_TYPE, UNITS>::storage_t storage_t;
+	typedef LLUnit<STORAGE_TYPE, UNITS> base_t;
 
-	LLUnitImplicit(storage_t value = storage_t())
+	LL_FORCE_INLINE LLUnitImplicit(storage_t value = storage_t())
 	:	base_t(value)
 	{}
 
-	template<typename OTHER_STORAGE, typename OTHER_UNIT>
-	LLUnitImplicit(LLUnit<OTHER_STORAGE, OTHER_UNIT> other)
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE LLUnitImplicit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
 	:	base_t(other)
 	{}
 
 	// unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc)
 	// this allows for interoperability with legacy code
-	operator storage_t() const
+	LL_FORCE_INLINE operator storage_t() const
 	{
 		return base_t::value();
 	}
 
 	using base_t::operator +=;
-	void operator += (storage_t value)
+	LL_FORCE_INLINE void operator += (storage_t value)
 	{
         base_t::mValue += value;
 	}
 
 	// this overload exists to explicitly catch use of another implicit unit
 	// without ambiguity between conversion to storage_t vs conversion to base_t
-	template<typename OTHER_STORAGE, typename OTHER_UNIT>
-	void operator += (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE void operator += (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
 	{
         base_t::mValue += convert(other).value();
 	}
 
 	using base_t::operator -=;
-	void operator -= (storage_t value)
+	LL_FORCE_INLINE void operator -= (storage_t value)
 	{
         base_t::mValue -= value;
 	}
 
 	// this overload exists to explicitly catch use of another implicit unit
 	// without ambiguity between conversion to storage_t vs conversion to base_t
-	template<typename OTHER_STORAGE, typename OTHER_UNIT>
-	void operator -= (LLUnitImplicit<OTHER_STORAGE, OTHER_UNIT> other)
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE void operator -= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
 	{
         base_t::mValue -= convert(other).value();
 	}
 
+	using base_t::operator ==;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator == (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue == convert(other).value();
+	}
+
+	template<typename STORAGE_T>
+	LL_FORCE_INLINE bool operator == (STORAGE_T other)
+	{
+		return mValue == other;
+	}
+
+	using base_t::operator !=;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator != (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue != convert(other).value();
+	}
+
+	template<typename STORAGE_T>
+	LL_FORCE_INLINE bool operator != (STORAGE_T other)
+	{
+		return mValue != other;
+	}
+	
+	using base_t::operator <;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator < (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue < convert(other).value();
+	}
+
+	template<typename STORAGE_T>
+	LL_FORCE_INLINE bool operator < (STORAGE_T other)
+	{
+		return mValue < other;
+	}
+
+	using base_t::operator <=;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator <= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue <= convert(other).value();
+	}
+
+	template<typename STORAGE_T>
+	LL_FORCE_INLINE bool operator <= (STORAGE_T other)
+	{
+		return mValue <= other;
+	}
+
+	using base_t::operator >;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator > (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue > convert(other).value();
+	}
+
+	template<typename STORAGE_T>
+	LL_FORCE_INLINE bool operator > (STORAGE_T other)
+	{
+		return mValue > other;
+	}
+
+	using base_t::operator >=;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator >= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	{
+		return mValue >= convert(other).value();
+	}
+
+	template<typename STORAGE_T>
+	LL_FORCE_INLINE bool operator >= (STORAGE_T other)
+	{
+		return mValue >= other;
+	}
 };
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-std::ostream& operator <<(std::ostream& s, const LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>& unit)
+template<typename STORAGE_TYPE, typename UNITS>
+std::ostream& operator <<(std::ostream& s, const LLUnitImplicit<STORAGE_TYPE, UNITS>& unit)
 {
-        s << unit.value() << UNIT_TYPE::getUnitLabel();
+        s << unit.value() << UNITS::getUnitLabel();
         return s;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE>& unit)
+template<typename STORAGE_TYPE, typename UNITS>
+std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNITS>& unit)
 {
         STORAGE_TYPE val;
         s >> val;
@@ -283,8 +407,8 @@ struct LLStorageType
 	typedef T type_t;
 };
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE>
-struct LLStorageType<LLUnit<STORAGE_TYPE, UNIT_TYPE> >
+template<typename STORAGE_TYPE, typename UNITS>
+struct LLStorageType<LLUnit<STORAGE_TYPE, UNITS> >
 {
 	typedef STORAGE_TYPE type_t;
 };
@@ -296,65 +420,65 @@ struct LLStorageType<LLUnit<STORAGE_TYPE, UNIT_TYPE> >
 //
 // operator +
 //
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
 	result += second;
 	return result;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
-LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNITS> operator + (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second)
 {
 	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
+	return LLUnit<STORAGE_TYPE, UNITS>(0);
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
-LLUnit<STORAGE_TYPE, UNIT_TYPE> operator + (UNITLESS first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNITS> operator + (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second)
 {
 	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
+	return LLUnit<STORAGE_TYPE, UNITS>(0);
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
 	result += second;
 	return result;
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
 	result += second;
 	return result;
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
-	result += LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+	result += LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
 	return result;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator + (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator + (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
 {
-	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
 	result += second;
 	return result;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::
-	type_t, UNIT_TYPE> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::
+	type_t, UNITS> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
 {
-	LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
 	result += second;
 	return result;
 }
@@ -362,64 +486,64 @@ LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::t
 //
 // operator -
 //
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
 	result -= second;
 	return result;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
-LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNITS> operator - (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second)
 {
 	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
+	return LLUnit<STORAGE_TYPE, UNITS>(0);
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS>
-LLUnit<STORAGE_TYPE, UNIT_TYPE> operator - (UNITLESS first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNITS> operator - (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second)
 {
 	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
-	return LLUnit<STORAGE_TYPE, UNIT_TYPE>(0);
+	return LLUnit<STORAGE_TYPE, UNITS>(0);
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
 	result -= second;
 	return result;
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
 	result -= second;
 	return result;
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
 {
-	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNIT_TYPE1> result(first);
-	result -= LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>(second);
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+	result -= LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
 	return result;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator - (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator - (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
 {
-	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
 	result -= second;
 	return result;
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
 {
-	LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> result(first);
+	LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
 	result -= second;
 	return result;
 }
@@ -427,44 +551,44 @@ LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYP
 //
 // operator *
 //
-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>)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LLUnit<STORAGE_TYPE1, UNITS1> operator * (LLUnit<STORAGE_TYPE1, UNITS1>, LLUnit<STORAGE_TYPE2, UNITS2>)
 {
 	// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
 	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
-	return LLUnit<STORAGE_TYPE1, UNIT_TYPE1>();
+	return LLUnit<STORAGE_TYPE1, UNITS1>();
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator * (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
 {
-	return LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() * second);
+	return LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() * second);
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNITS> second)
 {
-	return LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE>(first * second.value());
+	return LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
 }
 
-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>)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LLUnitImplicit<STORAGE_TYPE1, UNITS1> operator * (LLUnitImplicit<STORAGE_TYPE1, UNITS1>, LLUnitImplicit<STORAGE_TYPE2, UNITS2>)
 {
 	// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
 	LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
-	return LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1>();
+	return LLUnitImplicit<STORAGE_TYPE1, UNITS1>();
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator * (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
 {
-	return LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, UNITLESS_TYPE>::type_t, UNIT_TYPE>(first.value() * second);
+	return LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, UNITLESS_TYPE>::type_t, UNITS>(first.value() * second);
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
 {
-	return LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNIT_TYPE>(first * second.value());
+	return LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
 }
 
 
@@ -472,105 +596,42 @@ LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYP
 // operator /
 //
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator / (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
 {
-	return LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() / second);
+	return LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
 {
 	return first.value() / first.convert(second).value();
 }
 
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>
-LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE> operator / (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
 {
-	return LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNIT_TYPE>(first.value() / second);
+	return LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
 {
 	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
 {
 	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
 }
 
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>
-typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
 {
 	return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
 }
 
-//
-// comparison operators
-//
-
-#define LL_UNIT_DECLARE_COMPARISON_OPERATOR(op)                                                                            \
-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).value();                                                                 \
-}                                                                                                                          \
-	                                                                                                                       \
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
-bool operator op (LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)                                     \
-{                                                                                                                          \
-	return first.value() op second;                                                                                        \
-}                                                                                                                          \
-                                                                                                                           \
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
-bool operator op (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> second)                                     \
-{                                                                                                                          \
-	return first op second.value();                                                                                        \
-}                                                                                                                          \
-                                                                                                                           \
-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).value();                                                                 \
-}                                                                                                                          \
-                                                                                                                           \
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
-bool operator op (LLUnit<STORAGE_TYPE, UNIT_TYPE> first, UNITLESS_TYPE second)                                             \
-{                                                                                                                          \
-	LL_BAD_TEMPLATE_INSTANTIATION(UNITLESS_TYPE, "operator " #op " requires compatible unit types");                       \
-	return false;                                                                                                          \
-}                                                                                                                          \
-                                                                                                                           \
-template<typename STORAGE_TYPE, typename UNIT_TYPE, typename UNITLESS_TYPE>                                                \
-bool operator op (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNIT_TYPE> second)                                             \
-{                                                                                                                          \
-	LL_BAD_TEMPLATE_INSTANTIATION(UNITLESS_TYPE, "operator " #op " requires compatible unit types");                       \
-	return false;                                                                                                          \
-}                                                                                                                          \
-	                                                                                                                       \
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \
-bool operator op (LLUnit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnitImplicit<STORAGE_TYPE2, UNIT_TYPE2> second)               \
-{                                                                                                                          \
-	return first.value() op first.convert(second).value();                                                                 \
-}                                                                                                                          \
-                                                                                                                           \
-template<typename STORAGE_TYPE1, typename UNIT_TYPE1, typename STORAGE_TYPE2, typename UNIT_TYPE2>                         \
-bool operator op (LLUnitImplicit<STORAGE_TYPE1, UNIT_TYPE1> first, LLUnit<STORAGE_TYPE2, UNIT_TYPE2> second)               \
-{                                                                                                                          \
-	return first.value() op first.convert(second).value();                                                                 \
-}
-
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(<);
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(<=);
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(>);
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(>=);
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(==);
-LL_UNIT_DECLARE_COMPARISON_OPERATOR(!=);
-
-
 template<typename T> 
 struct LLGetUnitLabel
 {
-- 
cgit v1.2.3


From 00bd492b30f0dcb49d354be74e6e9a312a84863f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 27 Aug 2013 16:36:36 -0700
Subject: got linear unit conversions (like fahrenheit <-> celsius) working
 correctly further optimizations for codegen

---
 indra/llcommon/llunittype.h           | 74 +++++++++++++++++++----------------
 indra/llcommon/tests/llunits_test.cpp | 40 ++++++++++++++++++-
 2 files changed, 79 insertions(+), 35 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h
index a5e99070b6..50037ccade 100644
--- a/indra/llcommon/llunittype.h
+++ b/indra/llcommon/llunittype.h
@@ -147,35 +147,35 @@ struct LLUnit
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
 		return mValue == convert(other).value();
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
 		return mValue != convert(other).value();
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
 		return mValue < convert(other).value();
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
 		return mValue <= convert(other).value();
 	}
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
 		return mValue > convert(other).value();
 	}
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
 		return mValue >= convert(other).value();
 	}
@@ -193,6 +193,15 @@ struct LLUnit
 		return result;
 	}
 
+	template<typename FROM_UNITS>
+	LL_FORCE_INLINE static self_t convert(LLUnit<STORAGE_TYPE, FROM_UNITS> v) 
+	{
+		self_t result;
+		STORAGE_TYPE divisor = ll_convert_units(v, result);
+		result.mValue /= divisor;
+		return result;
+	}
+
 	template<typename FROM_STORAGE_TYPE, typename FROM_UNITS>
 	LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, FROM_UNITS> v) 
 	{ 
@@ -276,78 +285,78 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
 
 	using base_t::operator ==;
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator == (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	LL_FORCE_INLINE bool operator == (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
 		return mValue == convert(other).value();
 	}
 
 	template<typename STORAGE_T>
-	LL_FORCE_INLINE bool operator == (STORAGE_T other)
+	LL_FORCE_INLINE bool operator == (STORAGE_T other) const
 	{
 		return mValue == other;
 	}
 
 	using base_t::operator !=;
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator != (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	LL_FORCE_INLINE bool operator != (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
 		return mValue != convert(other).value();
 	}
 
 	template<typename STORAGE_T>
-	LL_FORCE_INLINE bool operator != (STORAGE_T other)
+	LL_FORCE_INLINE bool operator != (STORAGE_T other) const
 	{
 		return mValue != other;
 	}
 	
 	using base_t::operator <;
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator < (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	LL_FORCE_INLINE bool operator < (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
 		return mValue < convert(other).value();
 	}
 
 	template<typename STORAGE_T>
-	LL_FORCE_INLINE bool operator < (STORAGE_T other)
+	LL_FORCE_INLINE bool operator < (STORAGE_T other) const
 	{
 		return mValue < other;
 	}
 
 	using base_t::operator <=;
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator <= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	LL_FORCE_INLINE bool operator <= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
 		return mValue <= convert(other).value();
 	}
 
 	template<typename STORAGE_T>
-	LL_FORCE_INLINE bool operator <= (STORAGE_T other)
+	LL_FORCE_INLINE bool operator <= (STORAGE_T other) const
 	{
 		return mValue <= other;
 	}
 
 	using base_t::operator >;
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator > (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	LL_FORCE_INLINE bool operator > (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
 		return mValue > convert(other).value();
 	}
 
 	template<typename STORAGE_T>
-	LL_FORCE_INLINE bool operator > (STORAGE_T other)
+	LL_FORCE_INLINE bool operator > (STORAGE_T other) const
 	{
 		return mValue > other;
 	}
 
 	using base_t::operator >=;
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-	LL_FORCE_INLINE bool operator >= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+	LL_FORCE_INLINE bool operator >= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
 		return mValue >= convert(other).value();
 	}
 
 	template<typename STORAGE_T>
-	LL_FORCE_INLINE bool operator >= (STORAGE_T other)
+	LL_FORCE_INLINE bool operator >= (STORAGE_T other) const
 	{
 		return mValue >= other;
 	}
@@ -670,16 +679,14 @@ struct LLUnitLinearOps
 	template<typename OTHER_T>
 	self_t operator + (OTHER_T other)
 	{
-		mValue /= mDivisor;
-		mValue += other;
+		mValue += other * mDivisor;
 		return *this;
 	}
 
 	template<typename OTHER_T>
 	self_t operator - (OTHER_T other)
 	{
-		mValue /= mDivisor;
-		mValue -= other;
+		mValue -= other * mDivisor;
 		return *this;
 	}
 
@@ -694,7 +701,8 @@ struct LLUnitInverseLinearOps
 
 	LLUnitInverseLinearOps(T val) 
 	:	mValue(val),
-		mDivisor(1)
+		mDivisor(1),
+		mMultiplicand(1)
 	{}
 
 	template<typename OTHER_T>
@@ -708,27 +716,27 @@ struct LLUnitInverseLinearOps
 	self_t operator / (OTHER_T other)
 	{
 		mValue *= other;
+		mMultiplicand *= other;
 		return *this;
 	}
 
 	template<typename OTHER_T>
 	self_t operator + (OTHER_T other)
 	{
-		mValue /= mDivisor;
-		mValue -= other;
+		mValue -= other * mMultiplicand;
 		return *this;
 	}
 
 	template<typename OTHER_T>
 	self_t operator - (OTHER_T other)
 	{
-		mValue /= mDivisor;
-		mValue += other;
+		mValue += other * mMultiplicand;
 		return *this;
 	}
 
 	T mValue;
 	T mDivisor;
+	T mMultiplicand;
 };
 
 #define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label)                                             \
@@ -762,20 +770,20 @@ template<typename S1, typename S2>
 LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out)   \
 {                                                                                                \
 	typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t;                       \
-	LLUnitInverseLinearOps<result_storage_t> op =                                                \
+	LLUnitInverseLinearOps<result_storage_t> result =                                            \
 		LLUnitInverseLinearOps<result_storage_t>(in.value()) conversion_operation;               \
-	out = LLUnit<S2, base_unit_name>((S2)op.mValue);	                                         \
-	return op.mDivisor;                                                                          \
+	out = LLUnit<S2, base_unit_name>((S2)result.mValue);	                                     \
+	return result.mDivisor;                                                                      \
 }                                                                                                \
                                                                                                  \
 template<typename S1, typename S2>                                                               \
 LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out)   \
 {                                                                                                \
 	typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t;                       \
-	LLUnitLinearOps<result_storage_t> op =                                                       \
+	LLUnitLinearOps<result_storage_t> result =                                                   \
 		LLUnitLinearOps<result_storage_t>(in.value()) conversion_operation;				         \
-	out = LLUnit<S2, unit_name>((S2)op.mValue);                                                  \
-	return op.mDivisor;                                                                          \
+	out = LLUnit<S2, unit_name>((S2)result.mValue);                                              \
+	return result.mDivisor;                                                                      \
 }                                                                                               
 
 #define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name)                         \
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index 5a18603e4e..59876ce3b4 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -42,6 +42,18 @@ LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Quatloos);
 LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Latinum);
 LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Solari);
 
+namespace LLUnits
+{
+	LL_DECLARE_BASE_UNIT(Celcius, "c");
+	LL_DECLARE_DERIVED_UNIT(Fahrenheit, "f", Celcius, * 9 / 5 + 32);
+	LL_DECLARE_DERIVED_UNIT(Kelvin, "k", Celcius, + 273.15f);
+}
+
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Celcius);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Fahrenheit);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kelvin);
+
+
 namespace tut
 {
 	using namespace LLUnits;
@@ -328,8 +340,8 @@ namespace tut
 		ensure("GHz -> Hz conversion", Hz.value() == 1000 * 1000 * 1000);
 
 		F32Radians rad(6.2831853071795f);
-		F32Degrees deg(rad);
-		ensure("radians -> degrees conversion", deg.value() > 359 && deg.value() < 361);
+		S32Degrees deg(rad);
+		ensure("radians -> degrees conversion", deg.value() == 360);
 
 		F32Percent percent(50);
 		F32Ratio ratio(percent);
@@ -339,4 +351,28 @@ namespace tut
 		U32Triangles tris(ktris);
 		ensure("kilotriangles -> triangles conversion", tris.value() == 1000);
 	}
+
+	bool value_near(F32 value, F32 target, F32 threshold)
+	{
+		return fabsf(value - target) < threshold;
+	}
+
+	// linear transforms
+	template<> template<>
+	void units_object_t::test<10>()
+	{
+		F32Celcius float_celcius(100);
+		F32Fahrenheit float_fahrenheit(float_celcius);
+		ensure("floating point celcius -> fahrenheit conversion using linear transform", value_near(float_fahrenheit.value(), 212, 0.1f) );
+
+		float_celcius = float_fahrenheit;
+		ensure("floating point fahrenheit -> celcius conversion using linear transform (round trip)", value_near(float_celcius.value(), 100.f, 0.1f) );
+
+		S32Celcius int_celcius(100);
+		S32Fahrenheit int_fahrenheit(int_celcius);
+		ensure("integer celcius -> fahrenheit conversion using linear transform", int_fahrenheit.value() == 212);
+
+		int_celcius = int_fahrenheit;
+		ensure("integer fahrenheit -> celcius conversion using linear transform (round trip)", int_celcius.value() == 100);
+	}
 }
-- 
cgit v1.2.3


From 35e8c81dd8afd05b6298a1849c63bc9238ab3271 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 27 Aug 2013 16:48:57 -0700
Subject: gcc build fix

---
 indra/llcommon/llunittype.h | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h
index 50037ccade..5cf41343fc 100644
--- a/indra/llcommon/llunittype.h
+++ b/indra/llcommon/llunittype.h
@@ -287,78 +287,78 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator == (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
-		return mValue == convert(other).value();
+		return base_t::mValue == convert(other).value();
 	}
 
 	template<typename STORAGE_T>
 	LL_FORCE_INLINE bool operator == (STORAGE_T other) const
 	{
-		return mValue == other;
+		return base_t::mValue == other;
 	}
 
 	using base_t::operator !=;
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator != (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
-		return mValue != convert(other).value();
+		return base_t::mValue != convert(other).value();
 	}
 
 	template<typename STORAGE_T>
 	LL_FORCE_INLINE bool operator != (STORAGE_T other) const
 	{
-		return mValue != other;
+		return base_t::mValue != other;
 	}
 	
 	using base_t::operator <;
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator < (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
-		return mValue < convert(other).value();
+		return base_t::mValue < convert(other).value();
 	}
 
 	template<typename STORAGE_T>
 	LL_FORCE_INLINE bool operator < (STORAGE_T other) const
 	{
-		return mValue < other;
+		return base_t::mValue < other;
 	}
 
 	using base_t::operator <=;
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator <= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
-		return mValue <= convert(other).value();
+		return base_t::mValue <= convert(other).value();
 	}
 
 	template<typename STORAGE_T>
 	LL_FORCE_INLINE bool operator <= (STORAGE_T other) const
 	{
-		return mValue <= other;
+		return base_t::mValue <= other;
 	}
 
 	using base_t::operator >;
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator > (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
-		return mValue > convert(other).value();
+		return base_t::mValue > convert(other).value();
 	}
 
 	template<typename STORAGE_T>
 	LL_FORCE_INLINE bool operator > (STORAGE_T other) const
 	{
-		return mValue > other;
+		return base_t::mValue > other;
 	}
 
 	using base_t::operator >=;
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator >= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
-		return mValue >= convert(other).value();
+		return base_t::mValue >= convert(other).value();
 	}
 
 	template<typename STORAGE_T>
 	LL_FORCE_INLINE bool operator >= (STORAGE_T other) const
 	{
-		return mValue >= other;
+		return base_t::mValue >= other;
 	}
 };
 
-- 
cgit v1.2.3


From 25e2fbe419655b2f8ce22dbafa1de6bc655b1567 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 27 Aug 2013 18:08:32 -0700
Subject: got comparisons between implicit and explicit units working right

---
 indra/llcommon/llunittype.h           | 44 ++++++++++++++++++++++++++++++-----
 indra/llcommon/tests/llunits_test.cpp | 10 ++++++++
 2 files changed, 48 insertions(+), 6 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h
index 50037ccade..663641d6b1 100644
--- a/indra/llcommon/llunittype.h
+++ b/indra/llcommon/llunittype.h
@@ -169,11 +169,13 @@ struct LLUnit
 	{
 		return mValue <= convert(other).value();
 	}
+
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
 		return mValue > convert(other).value();
 	}
+
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
@@ -283,7 +285,12 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
         base_t::mValue -= convert(other).value();
 	}
 
-	using base_t::operator ==;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+	{
+		return mValue == convert(other).value();
+	}
+
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator == (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
@@ -296,7 +303,12 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
 		return mValue == other;
 	}
 
-	using base_t::operator !=;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+	{
+		return mValue != convert(other).value();
+	}
+
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator != (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
@@ -309,7 +321,12 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
 		return mValue != other;
 	}
 	
-	using base_t::operator <;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+	{
+		return mValue < convert(other).value();
+	}
+
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator < (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
@@ -322,7 +339,12 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
 		return mValue < other;
 	}
 
-	using base_t::operator <=;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+	{
+		return mValue <= convert(other).value();
+	}
+
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator <= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
@@ -335,7 +357,12 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
 		return mValue <= other;
 	}
 
-	using base_t::operator >;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+	{
+		return mValue > convert(other).value();
+	}
+
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator > (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
@@ -348,7 +375,12 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
 		return mValue > other;
 	}
 
-	using base_t::operator >=;
+	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+	LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+	{
+		return mValue >= convert(other).value();
+	}
+
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator >= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index 59876ce3b4..d5b7c08672 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -274,6 +274,16 @@ namespace tut
 
 		quatloos_implicit -= F32Quatloos(10);
 		ensure("can subtract-assign explicit units", quatloos_implicit == 16);
+
+		// comparisons
+		ensure("can compare greater than implicit unit", quatloos_implicit > F32QuatloosImplicit(0.f));
+		ensure("can compare greater than non-implicit unit", quatloos_implicit > F32Quatloos(0.f));
+		ensure("can compare greater than or equal to implicit unit", quatloos_implicit >= F32QuatloosImplicit(0.f));
+		ensure("can compare greater than or equal to non-implicit unit", quatloos_implicit >= F32Quatloos(0.f));
+		ensure("can compare less than implicit unit", quatloos_implicit < F32QuatloosImplicit(0.f));
+		ensure("can compare less than non-implicit unit", quatloos_implicit < F32Quatloos(0.f));
+		ensure("can compare less than or equal to implicit unit", quatloos_implicit <= F32QuatloosImplicit(0.f));
+		ensure("can compare less than or equal to non-implicit unit", quatloos_implicit <= F32Quatloos(0.f));
 	}
 
 	// precision tests
-- 
cgit v1.2.3


From 5a22ab52618ae588f1303c7b6d0bb7a8c4b4ca93 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 27 Aug 2013 18:10:41 -0700
Subject: more gcc fixes

---
 indra/llcommon/llunittype.h | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h
index fbb8eb2431..fb72d6d8a9 100644
--- a/indra/llcommon/llunittype.h
+++ b/indra/llcommon/llunittype.h
@@ -288,7 +288,7 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
-		return mValue == convert(other).value();
+		return base_t::mValue == convert(other).value();
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
@@ -306,7 +306,7 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
-		return mValue != convert(other).value();
+		return base_t::mValue != convert(other).value();
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
@@ -324,7 +324,7 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
-		return mValue < convert(other).value();
+		return base_t::mValue < convert(other).value();
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
@@ -342,7 +342,7 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
-		return mValue <= convert(other).value();
+		return base_t::mValue <= convert(other).value();
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
@@ -360,7 +360,7 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
-		return mValue > convert(other).value();
+		return base_t::mValue > convert(other).value();
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
@@ -378,7 +378,7 @@ struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
 	LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
 	{
-		return mValue >= convert(other).value();
+		return base_t::mValue >= convert(other).value();
 	}
 
 	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
-- 
cgit v1.2.3


From 5ddd5694b54150b50a77627112ea98a4a94d0e46 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 27 Aug 2013 18:59:32 -0700
Subject: fixed bad logic in unit test

---
 indra/llcommon/tests/llunits_test.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
index d5b7c08672..57cf9810af 100644
--- a/indra/llcommon/tests/llunits_test.cpp
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -280,10 +280,10 @@ namespace tut
 		ensure("can compare greater than non-implicit unit", quatloos_implicit > F32Quatloos(0.f));
 		ensure("can compare greater than or equal to implicit unit", quatloos_implicit >= F32QuatloosImplicit(0.f));
 		ensure("can compare greater than or equal to non-implicit unit", quatloos_implicit >= F32Quatloos(0.f));
-		ensure("can compare less than implicit unit", quatloos_implicit < F32QuatloosImplicit(0.f));
-		ensure("can compare less than non-implicit unit", quatloos_implicit < F32Quatloos(0.f));
-		ensure("can compare less than or equal to implicit unit", quatloos_implicit <= F32QuatloosImplicit(0.f));
-		ensure("can compare less than or equal to non-implicit unit", quatloos_implicit <= F32Quatloos(0.f));
+		ensure("can compare less than implicit unit", quatloos_implicit < F32QuatloosImplicit(20.f));
+		ensure("can compare less than non-implicit unit", quatloos_implicit < F32Quatloos(20.f));
+		ensure("can compare less than or equal to implicit unit", quatloos_implicit <= F32QuatloosImplicit(20.f));
+		ensure("can compare less than or equal to non-implicit unit", quatloos_implicit <= F32Quatloos(20.f));
 	}
 
 	// precision tests
-- 
cgit v1.2.3


From f0a642898dad11f6519bad735857a58e1d83422e Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 29 Aug 2013 15:25:48 -0700
Subject: SH-4377 FIX: Interesting: Windows viewer crashes when
 SceneLoadingMonitorEnabled is enabled

---
 indra/llcommon/lltraceaccumulators.cpp | 3 +--
 indra/llcommon/lltraceaccumulators.h   | 5 +----
 2 files changed, 2 insertions(+), 6 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index 42f075a7cb..ae769350b9 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -145,7 +145,7 @@ void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppen
 
 		F64 epsilon = 0.0000001;
 
-		if (other.mTotalSamplingTime > epsilon)
+		if (other.mTotalSamplingTime > epsilon && mTotalSamplingTime > epsilon)
 		{
 			// combine variance (and hence standard deviation) of 2 different sized sample groups using
 			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
@@ -173,7 +173,6 @@ void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppen
 			mNumSamples += other.mNumSamples;
 			mTotalSamplingTime += other.mTotalSamplingTime;
 			mMean = (mMean * weight) + (other.mMean * (1.0 - weight));
-			llassert(mMean < 0 || mMean >= 0);
 		}
 		if (append_type == SEQUENTIAL)
 		{
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index e0f60800e3..02af480b8a 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -318,7 +318,6 @@ namespace LLTrace
 				mMin = value;
 				mMax = value;
 				mMean = value;
-				llassert(mMean < 0 || mMean >= 0);
 				mLastSampleTimeStamp = time_stamp;
 			}
 			else
@@ -336,15 +335,13 @@ namespace LLTrace
 
 		void sync(F64SecondsImplicit time_stamp)
 		{
-			if (mHasValue)
+			if (mHasValue && time_stamp != mLastSampleTimeStamp)
 			{
 				F64SecondsImplicit delta_time = time_stamp - mLastSampleTimeStamp;
 				mSum += mLastValue * delta_time;
 				mTotalSamplingTime += delta_time;
 				F64 old_mean = mMean;
-				llassert(mMean < 0 || mMean >= 0);
 				mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean);
-				llassert(mMean < 0 || mMean >= 0);
 				mSumOfSquares += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
 			}
 			mLastSampleTimeStamp = time_stamp;
-- 
cgit v1.2.3


From cbe397ad13665c7bc993e10d8fe1e4a876253378 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 5 Sep 2013 14:04:13 -0700
Subject: changed fast timer over to using macro another attempt to move mem
 stat into base class

---
 indra/llcommon/lldate.cpp                |   6 +-
 indra/llcommon/lldefs.h                  |   3 -
 indra/llcommon/llfasttimer.cpp           |   6 +-
 indra/llcommon/llfasttimer.h             |  32 +++++++++-
 indra/llcommon/llpreprocessor.h          |   7 ++-
 indra/llcommon/llsdparam.cpp             |   2 +-
 indra/llcommon/llsdparam.h               |   4 +-
 indra/llcommon/llstring.cpp              |   6 +-
 indra/llcommon/lltrace.h                 | 100 +++++++++++++++++++++++++------
 indra/llcommon/lltracethreadrecorder.cpp |   4 +-
 10 files changed, 131 insertions(+), 39 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp
index 4f2e1304b2..b32c3f6830 100755
--- a/indra/llcommon/lldate.cpp
+++ b/indra/llcommon/lldate.cpp
@@ -86,11 +86,11 @@ std::string LLDate::asRFC1123() const
 	return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT"));
 }
 
-LLFastTimer::DeclareTimer FT_DATE_FORMAT("Date Format");
+LLTrace::TimeBlock FT_DATE_FORMAT("Date Format");
 
 std::string LLDate::toHTTPDateString (std::string fmt) const
 {
-	LLFastTimer ft1(FT_DATE_FORMAT);
+	LL_RECORD_BLOCK_TIME(FT_DATE_FORMAT);
 	
 	time_t locSeconds = (time_t) mSecondsSinceEpoch;
 	struct tm * gmt = gmtime (&locSeconds);
@@ -99,7 +99,7 @@ std::string LLDate::toHTTPDateString (std::string fmt) const
 
 std::string LLDate::toHTTPDateString (tm * gmt, std::string fmt)
 {
-	LLFastTimer ft1(FT_DATE_FORMAT);
+	LL_RECORD_BLOCK_TIME(FT_DATE_FORMAT);
 
 	// avoid calling setlocale() unnecessarily - it's expensive.
 	static std::string prev_locale = "";
diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h
index d57b9dccff..5a4b8325f4 100755
--- a/indra/llcommon/lldefs.h
+++ b/indra/llcommon/lldefs.h
@@ -244,8 +244,5 @@ inline void llswap(LLDATATYPE& lhs, LLDATATYPE& rhs)
 	rhs = tmp;
 }
 
-#define LL_GLUE_IMPL(x, y) x##y
-#define LL_GLUE_TOKENS(x, y) LL_GLUE_IMPL(x, y)
-
 #endif // LL_LLDEFS_H
 
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 2235eb1a08..be240c754a 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -276,13 +276,13 @@ void TimeBlock::updateTimes()
 	}
 }
 
-static LLFastTimer::DeclareTimer FTM_PROCESS_TIMES("Process FastTimer Times");
+static LLTrace::TimeBlock FTM_PROCESS_TIMES("Process FastTimer Times");
 
 // not thread safe, so only call on main thread
 //static
 void TimeBlock::processTimes()
 {
-	LLFastTimer _(FTM_PROCESS_TIMES);
+	LL_RECORD_BLOCK_TIME(FTM_PROCESS_TIMES);
 	get_clock_count(); // good place to calculate clock frequency
 
 	// set up initial tree
@@ -413,7 +413,7 @@ void TimeBlock::writeLog(std::ostream& os)
 		LLSDSerialize::toXML(sd, os);
 		LLMutexLock lock(sLogLock);
 		sLogQueue.pop();
-			}
+	}
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 7bad6134c5..e6bf544b51 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -35,28 +35,56 @@
 
 class LLMutex;
 
+#define LL_RECORD_BLOCK_TIME(timer_stat) const LLTrace::BlockTimer& LL_GLUE_TOKENS(block_time_recorder, __LINE__)(LLTrace::timeThisBlock(timer_stat)); (void)LL_GLUE_TOKENS(block_time_recorder, __LINE__);
+
 namespace LLTrace
 {
 
+class BlockTimer timeThisBlock(class TimeBlock& timer);
+
 class BlockTimer
 {
 public:
-	friend class TimeBlock;
 	typedef BlockTimer self_t;
 	typedef class TimeBlock DeclareTimer;
 
-	BlockTimer(TimeBlock& timer);
 	~BlockTimer();
 
 	F64Seconds getElapsedTime();
 
 private:
+	friend class TimeBlock;
+	// FIXME: this friendship exists so that each thread can instantiate a root timer, 
+	// which could be a derived class with a public constructor instead, possibly
+	friend class ThreadRecorder; 
+	friend BlockTimer timeThisBlock(TimeBlock&); 
 
+	BlockTimer(TimeBlock& timer);
+#if !defined(MSC_VER) || MSC_VER < 1700
+	// Visual Studio 2010 has a bug where capturing an object returned by value
+	// into a local reference requires access to the copy constructor at the call site.
+	// This appears to be fixed in 2012.
+public:
+#endif
+	// no-copy
+	BlockTimer(const BlockTimer& other) {};
+
+private:
 	U64						mStartTime;
 	U64						mBlockStartTotalTimeCounter;
 	BlockTimerStackRecord	mParentTimerData;
 };
 
+// this dummy function assists in allocating a block timer with stack-based lifetime.
+// this is done by capturing the return value in a stack-allocated const reference variable.  
+// (This is most easily done using the macro LL_RECORD_BLOCK_TIME)
+// Otherwise, it would be possible to store a BlockTimer on the heap, resulting in non-nested lifetimes, 
+// which would break the invariants of the timing hierarchy logic
+LL_FORCE_INLINE class BlockTimer timeThisBlock(class TimeBlock& timer)
+{
+	return BlockTimer(timer);
+}
+
 // stores a "named" timer instance to be reused via multiple BlockTimer stack instances
 class TimeBlock 
 :	public TraceType<TimeBlockAccumulator>,
diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index 0fcc872690..309165da7f 100755
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -191,9 +191,12 @@
 
 #define LL_TO_STRING_HELPER(x) #x
 #define LL_TO_STRING(x) LL_TO_STRING_HELPER(x)
-#define LL_FILE_LINENO(msg) __FILE__ "(" LL_TO_STRING(__LINE__) ") : " msg
+#define LL_FILE_LINENO_MSG(msg) __FILE__ "(" LL_TO_STRING(__LINE__) ") : " msg
+#define LL_GLUE_IMPL(x, y) x##y
+#define LL_GLUE_TOKENS(x, y) LL_GLUE_IMPL(x, y)
+
 #if LL_WINDOWS
-#define LL_COMPILE_TIME_MESSAGE(msg) __pragma(message(LL_FILE_LINENO(msg)))
+#define LL_COMPILE_TIME_MESSAGE(msg) __pragma(message(LL_FILE_LINENO_MSG(msg)))
 #else
 // no way to get gcc 4.2 to print a user-defined diagnostic message only when a macro is used
 #define LL_COMPILE_TIME_MESSAGE(msg)
diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp
index c1ba777543..371bd49c04 100755
--- a/indra/llcommon/llsdparam.cpp
+++ b/indra/llcommon/llsdparam.cpp
@@ -37,7 +37,7 @@ static 	LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
 static 	LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
 static const LLSD NO_VALUE_MARKER;
 
-LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion");
+LLTrace::TimeBlock FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion");
 
 //
 // LLParamSDParser
diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h
index 7cfc265c62..47ec6414dd 100755
--- a/indra/llcommon/llsdparam.h
+++ b/indra/llcommon/llsdparam.h
@@ -110,7 +110,7 @@ private:
 };
 
 
-extern LL_COMMON_API LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR;
+extern LL_COMMON_API LLTrace::TimeBlock FTM_SD_PARAM_ADAPTOR;
 template<typename T>
 class LLSDParamAdapter : public T
 {
@@ -118,7 +118,7 @@ public:
 	LLSDParamAdapter() {}
 	LLSDParamAdapter(const LLSD& sd)
 	{
-		LLFastTimer _(FTM_SD_PARAM_ADAPTOR);
+		LL_RECORD_BLOCK_TIME(FTM_SD_PARAM_ADAPTOR);
 		LLParamSDParser parser;
 		// don't spam for implicit parsing of LLSD, as we want to allow arbitrary freeform data and ignore most of it
 		bool parse_silently = true;
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index e6e80fa279..a4b1d2ede3 100755
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -36,7 +36,7 @@
 #include <winnls.h> // for WideCharToMultiByte
 #endif
 
-LLFastTimer::DeclareTimer FT_STRING_FORMAT("String Format");
+LLTrace::TimeBlock FT_STRING_FORMAT("String Format");
 
 
 std::string ll_safe_string(const char* in)
@@ -1195,7 +1195,7 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,
 template<> 
 S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions)
 {
-	LLFastTimer ft(FT_STRING_FORMAT);
+	LL_RECORD_BLOCK_TIME(FT_STRING_FORMAT);
 	S32 res = 0;
 
 	std::string output;
@@ -1268,7 +1268,7 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions)
 template<> 
 S32 LLStringUtil::format(std::string& s, const LLSD& substitutions)
 {
-	LLFastTimer ft(FT_STRING_FORMAT);
+	LL_RECORD_BLOCK_TIME(FT_STRING_FORMAT);
 	S32 res = 0;
 
 	if (!substitutions.isMap()) 
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index bf8e950a8c..a465a7f426 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -38,8 +38,6 @@
 
 #include <list>
 
-#define LL_RECORD_BLOCK_TIME(block_timer) LLTrace::TimeBlock::Recorder LL_GLUE_TOKENS(block_time_recorder, __COUNTER__)(block_timer);
-
 namespace LLTrace
 {
 class Recording;
@@ -89,7 +87,7 @@ public:
 	size_t getIndex() const { return mAccumulatorIndex; }
 	static size_t getNumIndices() { return AccumulatorBuffer<ACCUMULATOR>::getNumIndices(); }
 
-private:
+protected:
 	const size_t		mAccumulatorIndex;
 };
 
@@ -329,7 +327,7 @@ class MemTrackable
 	struct TrackMemImpl;
 
 	typedef MemTrackable<DERIVED, ALIGNMENT> mem_trackable_t;
-
+	static	MemStatHandle	sMemStat;
 public:
 	typedef void mem_trackable_tag_t;
 
@@ -340,38 +338,100 @@ public:
 
 	void* operator new(size_t size) 
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 		accumulator.mAllocatedCount++;
 
-		return ::operator new(size);
+		if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
+		{
+			return ::operator new(size);
+		}
+		else if (ALIGNMENT == 16)
+		{
+			return ll_aligned_malloc_16(size);
+		}
+		else if (ALIGNMENT == 32)
+		{
+			return ll_aligned_malloc_32(size);
+		}
+		else
+		{
+			return ll_aligned_malloc(size, ALIGNMENT);
+		}
 	}
 
 	void operator delete(void* ptr, size_t size)
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 		accumulator.mAllocatedCount--;
 		accumulator.mDeallocatedCount++;
-		::operator delete(ptr);
+
+		if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
+		{
+			::operator delete(ptr);
+		}
+		else if (ALIGNMENT == 16)
+		{
+			ll_aligned_free_16(ptr);
+		}
+		else if (ALIGNMENT == 32)
+		{
+			return ll_aligned_free_32(ptr);
+		}
+		else
+		{
+			return ll_aligned_free(ptr);
+		}
 	}
 
 	void *operator new [](size_t size)
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 		accumulator.mAllocatedCount++;
 
-		return ::operator new[](size);
+		if (alignment == LL_DEFAULT_HEAP_ALIGN)
+		{
+			return ::operator new[](size);
+		}
+		else if (ALIGNMENT == 16)
+		{
+			return ll_aligned_malloc_16(size);
+		}
+		else if (ALIGNMENT == 32)
+		{
+			return ll_aligned_malloc_32(size);
+		}
+		else
+		{
+			return ll_aligned_malloc(size, ALIGNMENT);
+		}
 	}
 
 	void operator delete[](void* ptr, size_t size)
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 		accumulator.mAllocatedCount--;
 		accumulator.mDeallocatedCount++;
-		::operator delete[](ptr);
+
+		if (alignment == LL_DEFAULT_HEAP_ALIGN)
+		{
+			::operator delete[](ptr);
+		}
+		else if (ALIGNMENT == 16)
+		{
+			ll_aligned_free_16(ptr);
+		}
+		else if (ALIGNMENT == 32)
+		{
+			return ll_aligned_free_32(ptr);
+		}
+		else
+		{
+			return ll_aligned_free(ptr);
+		}
 	}
 
 	// claim memory associated with other objects/data as our own, adding to our calculated footprint
@@ -393,7 +453,7 @@ public:
 	template<typename AMOUNT_T>
 	AMOUNT_T& memClaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 		mMemFootprint += (size_t)size;
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 		return size;
@@ -417,7 +477,7 @@ public:
 	template<typename AMOUNT_T>
 	AMOUNT_T& memDisclaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 		return size;
 	}
@@ -430,7 +490,7 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
 			accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)footprint : (F64)footprint);
 			tracker.mMemFootprint += footprint;
@@ -438,7 +498,7 @@ private:
 
 		static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
 			accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)footprint : -(F64)footprint);
 			tracker.mMemFootprint -= footprint;
@@ -450,17 +510,21 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 			accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() + (F64)MemFootprint<TRACKED>::measure(tracked) : (F64)MemFootprint<TRACKED>::measure(tracked));
 		}
 
 		static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 			accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() - (F64)MemFootprint<TRACKED>::measure(tracked) : -(F64)MemFootprint<TRACKED>::measure(tracked));
 		}
 	};
 };
 
+// pretty sure typeid of containing class in static object constructor doesn't work in gcc
+template<typename DERIVED, size_t ALIGNMENT>
+MemStatHandle MemTrackable<DERIVED, ALIGNMENT>::sMemStat(typeid(DERIVED).name());
+
 }
 #endif // LL_LLTRACE_H
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 28470fb4c4..4129f1f889 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -249,11 +249,11 @@ void ThreadRecorder::pushToParent()
 }
 
 
-static LLFastTimer::DeclareTimer FTM_PULL_TRACE_DATA_FROM_CHILDREN("Pull child thread trace data");
+static LLTrace::TimeBlock FTM_PULL_TRACE_DATA_FROM_CHILDREN("Pull child thread trace data");
 
 void ThreadRecorder::pullFromChildren()
 {
-	LLFastTimer _(FTM_PULL_TRACE_DATA_FROM_CHILDREN);
+	LL_RECORD_BLOCK_TIME(FTM_PULL_TRACE_DATA_FROM_CHILDREN);
 	if (mActiveRecordings.empty()) return;
 
 	{ LLMutexLock lock(&mChildListMutex);
-- 
cgit v1.2.3


From 4032c518e49348ad0180b47d73bb73036bab5f73 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 5 Sep 2013 15:33:04 -0700
Subject: BUILDFIX: type typo

---
 indra/llcommon/lltrace.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index a465a7f426..d42c8e26fb 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -391,7 +391,7 @@ public:
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 		accumulator.mAllocatedCount++;
 
-		if (alignment == LL_DEFAULT_HEAP_ALIGN)
+		if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
 		{
 			return ::operator new[](size);
 		}
@@ -416,7 +416,7 @@ public:
 		accumulator.mAllocatedCount--;
 		accumulator.mDeallocatedCount++;
 
-		if (alignment == LL_DEFAULT_HEAP_ALIGN)
+		if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
 		{
 			::operator delete[](ptr);
 		}
-- 
cgit v1.2.3


From 3fd68662f267a3fd96d101834b3a9563bde3f61e Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sat, 7 Sep 2013 21:16:39 -0700
Subject: added memory usage and occlusion events to traces renamed "current"
 to "primary" when referring to accumulators

---
 indra/llcommon/llfasttimer.cpp           | 10 +++----
 indra/llcommon/llfasttimer.h             |  6 ++---
 indra/llcommon/llmemory.cpp              |  5 ++++
 indra/llcommon/lltrace.cpp               |  2 +-
 indra/llcommon/lltrace.h                 | 45 +++++++++++++++++++++-----------
 indra/llcommon/lltraceaccumulators.cpp   | 30 ++++++++++-----------
 indra/llcommon/lltraceaccumulators.h     | 16 ++++++------
 indra/llcommon/lltracethreadrecorder.cpp | 14 +++++-----
 8 files changed, 74 insertions(+), 54 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 2235eb1a08..c58fad12e7 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -189,7 +189,7 @@ void TimeBlock::bootstrapTimerTree()
 		// when this timer was called
 		if (timer.getParent() == &TimeBlock::getRootTimeBlock())
 		{
-			TimeBlockAccumulator& accumulator = timer.getPrimaryAccumulator();
+			TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
 
 			if (accumulator.mLastCaller)
 			{
@@ -223,7 +223,7 @@ void TimeBlock::incrementalUpdateTimerTree()
 		// skip root timer
 		if (timerp != &TimeBlock::getRootTimeBlock())
 		{
-			TimeBlockAccumulator& accumulator = timerp->getPrimaryAccumulator();
+			TimeBlockAccumulator& accumulator = timerp->getCurrentAccumulator();
 
 			if (accumulator.mMoveUpTree)
 			{
@@ -253,7 +253,7 @@ void TimeBlock::updateTimes()
 
 	U64 cur_time = getCPUClockCount64();
 	BlockTimer* cur_timer				= stack_record->mActiveTimer;
-	TimeBlockAccumulator* accumulator	= &stack_record->mTimeBlock->getPrimaryAccumulator();
+	TimeBlockAccumulator* accumulator	= &stack_record->mTimeBlock->getCurrentAccumulator();
 
 	while(cur_timer 
 		&& cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self
@@ -269,7 +269,7 @@ void TimeBlock::updateTimes()
 		cur_timer->mBlockStartTotalTimeCounter = accumulator->mTotalTimeCounter;
 
 		stack_record = &cur_timer->mParentTimerData;
-		accumulator  = &stack_record->mTimeBlock->getPrimaryAccumulator();
+		accumulator  = &stack_record->mTimeBlock->getCurrentAccumulator();
 		cur_timer    = stack_record->mActiveTimer;
 
 		stack_record->mChildTime += cumulative_time_delta;
@@ -299,7 +299,7 @@ void TimeBlock::processTimes()
 		++it)
 	{
 		TimeBlock& timer = *it;
-		TimeBlockAccumulator& accumulator = timer.getPrimaryAccumulator();
+		TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
 
 		accumulator.mLastCaller = NULL;
 		accumulator.mMoveUpTree = false;
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 7bad6134c5..1586ea2d04 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -257,11 +257,11 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 #if FAST_TIMER_ON
 	BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
 	if (!cur_timer_data) return;
-	TimeBlockAccumulator& accumulator = timer.getPrimaryAccumulator();
+	TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
 	accumulator.mActiveCount++;
 	mBlockStartTotalTimeCounter = accumulator.mTotalTimeCounter;
 	// keep current parent as long as it is active when we are
-	accumulator.mMoveUpTree |= (accumulator.mParent->getPrimaryAccumulator().mActiveCount == 0);
+	accumulator.mMoveUpTree |= (accumulator.mParent->getCurrentAccumulator().mActiveCount == 0);
 
 	// store top of stack
 	mParentTimerData = *cur_timer_data;
@@ -281,7 +281,7 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 	BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
 	if (!cur_timer_data) return;
 
-	TimeBlockAccumulator& accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator();
+	TimeBlockAccumulator& accumulator = cur_timer_data->mTimeBlock->getCurrentAccumulator();
 
 	accumulator.mCalls++;
 	accumulator.mTotalTimeCounter += total_time - (accumulator.mTotalTimeCounter - mBlockStartTotalTimeCounter);
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index cb2f853070..e0b2aa87c2 100755
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -43,12 +43,15 @@
 
 #include "llsys.h"
 #include "llframetimer.h"
+#include "lltrace.h"
 //----------------------------------------------------------------------------
 
 //static
 char* LLMemory::reserveMem = 0;
 U32Kilobytes LLMemory::sAvailPhysicalMemInKB(U32_MAX);
 U32Kilobytes LLMemory::sMaxPhysicalMemInKB(0);
+static LLTrace::SampleStatHandle<F64Megabytes> sAllocatedMem("allocated_mem", "active memory in use by application");
+static LLTrace::SampleStatHandle<F64Megabytes> sVirtualMem("virtual_mem", "virtual memory assigned to application");
 U32Kilobytes LLMemory::sAllocatedMemInKB(0);
 U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0);
 U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX);
@@ -114,7 +117,9 @@ void LLMemory::updateMemoryInfo()
 	}
 
 	sAllocatedMemInKB = (U32Bytes)(counters.WorkingSetSize) ;
+	sample(sAllocatedMem, sAllocatedMemInKB);
 	sAllocatedPageSizeInKB = (U32Bytes)(counters.PagefileUsage) ;
+	sample(sVirtualMem, sAllocatedPageSizeInKB);
 
 	U32Kilobytes avail_phys, avail_virtual;
 	LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 05422f9191..e4a6f4c902 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -76,7 +76,7 @@ void TimeBlockTreeNode::setParent( TimeBlock* parent )
 	}
 
 	mParent = parent;
-	mBlock->getPrimaryAccumulator().mParent = parent;
+	mBlock->getCurrentAccumulator().mParent = parent;
 	parent_tree_node->mChildren.push_back(mBlock);
 	parent_tree_node->mNeedsSorting = true;
 }
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index bf8e950a8c..cda15c0de5 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -80,9 +80,9 @@ public:
 		mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot())
 	{}
 
-	LL_FORCE_INLINE ACCUMULATOR& getPrimaryAccumulator() const
+	LL_FORCE_INLINE ACCUMULATOR& getCurrentAccumulator() const
 	{
-		ACCUMULATOR* accumulator_storage = AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage();
+		ACCUMULATOR* accumulator_storage = AccumulatorBuffer<ACCUMULATOR>::getCurrentStorage();
 		return accumulator_storage[mAccumulatorIndex];
 	}
 
@@ -137,7 +137,7 @@ template<typename T, typename VALUE_T>
 void record(EventStatHandle<T>& measurement, VALUE_T value)
 {
 	T converted_value(value);
-	measurement.getPrimaryAccumulator().record(storage_value(converted_value));
+	measurement.getCurrentAccumulator().record(storage_value(converted_value));
 }
 
 template <typename T = F64>
@@ -160,7 +160,22 @@ template<typename T, typename VALUE_T>
 void sample(SampleStatHandle<T>& measurement, VALUE_T value)
 {
 	T converted_value(value);
-	measurement.getPrimaryAccumulator().sample(storage_value(converted_value));
+	measurement.getCurrentAccumulator().sample(storage_value(converted_value));
+}
+
+template<typename T, typename VALUE_T>
+void add(SampleStatHandle<T>& measurement, VALUE_T value)
+{
+	T converted_value(value);
+	SampleAccumulator& acc = measurement.getCurrentAccumulator();
+	if (acc.hasValue())
+	{
+		acc.sample(acc.getLastValue() + converted_value);
+	}
+	else
+	{
+		acc.sample(converted_value);
+	}
 }
 
 template <typename T = F64>
@@ -183,7 +198,7 @@ template<typename T, typename VALUE_T>
 void add(CountStatHandle<T>& count, VALUE_T value)
 {
 	T converted_value(value);
-	count.getPrimaryAccumulator().add(storage_value(converted_value));
+	count.getCurrentAccumulator().add(storage_value(converted_value));
 }
 
 template<>
@@ -340,7 +355,7 @@ public:
 
 	void* operator new(size_t size) 
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 		accumulator.mAllocatedCount++;
 
@@ -349,7 +364,7 @@ public:
 
 	void operator delete(void* ptr, size_t size)
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 		accumulator.mAllocatedCount--;
 		accumulator.mDeallocatedCount++;
@@ -358,7 +373,7 @@ public:
 
 	void *operator new [](size_t size)
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 		accumulator.mAllocatedCount++;
 
@@ -367,7 +382,7 @@ public:
 
 	void operator delete[](void* ptr, size_t size)
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 		accumulator.mAllocatedCount--;
 		accumulator.mDeallocatedCount++;
@@ -393,7 +408,7 @@ public:
 	template<typename AMOUNT_T>
 	AMOUNT_T& memClaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
 		mMemFootprint += (size_t)size;
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 		return size;
@@ -417,7 +432,7 @@ public:
 	template<typename AMOUNT_T>
 	AMOUNT_T& memDisclaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 		return size;
 	}
@@ -430,7 +445,7 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
 			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
 			accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)footprint : (F64)footprint);
 			tracker.mMemFootprint += footprint;
@@ -438,7 +453,7 @@ private:
 
 		static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
 			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
 			accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)footprint : -(F64)footprint);
 			tracker.mMemFootprint -= footprint;
@@ -450,13 +465,13 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
 			accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() + (F64)MemFootprint<TRACKED>::measure(tracked) : (F64)MemFootprint<TRACKED>::measure(tracked));
 		}
 
 		static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = DERIVED::sMemStat.getPrimaryAccumulator();
+			MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
 			accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() - (F64)MemFootprint<TRACKED>::measure(tracked) : -(F64)MemFootprint<TRACKED>::measure(tracked));
 		}
 	};
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index ae769350b9..b234f43337 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -48,13 +48,13 @@ void AccumulatorBufferGroup::handOffTo(AccumulatorBufferGroup& other)
 	other.mMemStats.reset(&mMemStats);
 }
 
-void AccumulatorBufferGroup::makePrimary()
+void AccumulatorBufferGroup::makeCurrent()
 {
-	mCounts.makePrimary();
-	mSamples.makePrimary();
-	mEvents.makePrimary();
-	mStackTimers.makePrimary();
-	mMemStats.makePrimary();
+	mCounts.makeCurrent();
+	mSamples.makeCurrent();
+	mEvents.makeCurrent();
+	mStackTimers.makeCurrent();
+	mMemStats.makeCurrent();
 
 	ThreadRecorder* thread_recorder = get_thread_recorder().get();
 	AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers;
@@ -70,18 +70,18 @@ void AccumulatorBufferGroup::makePrimary()
 }
 
 //static
-void AccumulatorBufferGroup::clearPrimary()
+void AccumulatorBufferGroup::resetCurrent()
 {
-	AccumulatorBuffer<CountAccumulator>::clearPrimary();	
-	AccumulatorBuffer<SampleAccumulator>::clearPrimary();
-	AccumulatorBuffer<EventAccumulator>::clearPrimary();
-	AccumulatorBuffer<TimeBlockAccumulator>::clearPrimary();
-	AccumulatorBuffer<MemStatAccumulator>::clearPrimary();
+	AccumulatorBuffer<CountAccumulator>::resetCurrent();	
+	AccumulatorBuffer<SampleAccumulator>::resetCurrent();
+	AccumulatorBuffer<EventAccumulator>::resetCurrent();
+	AccumulatorBuffer<TimeBlockAccumulator>::resetCurrent();
+	AccumulatorBuffer<MemStatAccumulator>::resetCurrent();
 }
 
-bool AccumulatorBufferGroup::isPrimary() const
+bool AccumulatorBufferGroup::isCurrent() const
 {
-	return mCounts.isPrimary();
+	return mCounts.isCurrent();
 }
 
 void AccumulatorBufferGroup::append( const AccumulatorBufferGroup& other )
@@ -114,7 +114,7 @@ void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other)
 
 void AccumulatorBufferGroup::sync()
 {
-	if (isPrimary())
+	if (isCurrent())
 	{
 		F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds();
 
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 02af480b8a..e31058ab4b 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -75,7 +75,7 @@ namespace LLTrace
 
 		~AccumulatorBuffer()
 		{
-			if (isPrimary())
+			if (isCurrent())
 			{
 				LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
 			}
@@ -128,22 +128,22 @@ namespace LLTrace
 			}
 		}
 
-		void makePrimary()
+		void makeCurrent()
 		{
 			LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(mStorage);
 		}
 
-		bool isPrimary() const
+		bool isCurrent() const
 		{
 			return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage;
 		}
 
-		static void clearPrimary()
+		static void resetCurrent()
 		{
 			LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
 		}
 
-		LL_FORCE_INLINE static ACCUMULATOR* getPrimaryStorage() 
+		LL_FORCE_INLINE static ACCUMULATOR* getCurrentStorage() 
 		{ 
 			ACCUMULATOR* accumulator = LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance();
 			return accumulator ? accumulator : getDefaultBuffer()->mStorage;
@@ -534,9 +534,9 @@ namespace LLTrace
 		AccumulatorBufferGroup();
 
 		void handOffTo(AccumulatorBufferGroup& other);
-		void makePrimary();
-		bool isPrimary() const;
-		static void clearPrimary();
+		void makeCurrent();
+		bool isCurrent() const;
+		static void resetCurrent();
 
 		void append(const AccumulatorBufferGroup& other);
 		void merge(const AccumulatorBufferGroup& other);
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 28470fb4c4..df4af89184 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -69,13 +69,13 @@ void ThreadRecorder::init()
 		tree_node.mBlock = &time_block;
 		tree_node.mParent = &root_time_block;
 
-		it->getPrimaryAccumulator().mParent = &root_time_block;
+		it->getCurrentAccumulator().mParent = &root_time_block;
 	}
 
 	mRootTimer = new BlockTimer(root_time_block);
 	timer_stack->mActiveTimer = mRootTimer;
 
-	TimeBlock::getRootTimeBlock().getPrimaryAccumulator().mActiveCount = 1;
+	TimeBlock::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1;
 }
 
 
@@ -135,7 +135,7 @@ void ThreadRecorder::activate( AccumulatorBufferGroup* recording, bool from_hand
 	}
 	mActiveRecordings.push_back(active_recording);
 
-	mActiveRecordings.back()->mPartialRecording.makePrimary();
+	mActiveRecordings.back()->mPartialRecording.makeCurrent();
 }
 
 ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringUpToDate( AccumulatorBufferGroup* recording )
@@ -186,19 +186,19 @@ void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording )
 	if (it != mActiveRecordings.rend())
 	{
 		active_recording_list_t::iterator recording_to_remove = (++it).base();
-		bool was_primary = (*recording_to_remove)->mPartialRecording.isPrimary();
+		bool was_current = (*recording_to_remove)->mPartialRecording.isCurrent();
 		llassert((*recording_to_remove)->mTargetRecording == recording);
 		delete *recording_to_remove;
 		mActiveRecordings.erase(recording_to_remove);
-		if (was_primary)
+		if (was_current)
 		{
 			if (mActiveRecordings.empty())
 			{
-				AccumulatorBufferGroup::clearPrimary();
+				AccumulatorBufferGroup::resetCurrent();
 			}
 			else
 			{
-				mActiveRecordings.back()->mPartialRecording.makePrimary();
+				mActiveRecordings.back()->mPartialRecording.makeCurrent();
 			}
 		}
 	}
-- 
cgit v1.2.3


From ebd62051a5b2cb1ffcfa2fccc6e6d4292039fdda Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sat, 7 Sep 2013 22:15:41 -0700
Subject: memory stat for MemTrackable has name lazily initialized in an
 attempt to get around link time error for unit tests on gcc

---
 indra/llcommon/lltrace.h | 42 ++++++++++++++++++++++++++++--------------
 1 file changed, 28 insertions(+), 14 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 6436570492..9713bd6c04 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -62,8 +62,8 @@ public:
 	const std::string& getDescription() const { return mDescription; }
 
 protected:
-	const std::string	mName;
-	const std::string	mDescription;
+	std::string	mName;
+	std::string	mDescription;
 };
 
 template<typename ACCUMULATOR>
@@ -240,6 +240,11 @@ public:
 	:	trace_t(name)
 	{}
 
+	void setName(const char* name)
+	{
+		mName = name;
+	}
+
 	/*virtual*/ const char* getUnitLabel() const { return "B"; }
 
 	TraceType<MemStatAccumulator::AllocationCountFacet>& allocationCount() 
@@ -346,6 +351,16 @@ class MemTrackable
 public:
 	typedef void mem_trackable_tag_t;
 
+	MemTrackable()
+	{
+		static bool name_initialized = false;
+		if (!name_initialized)
+		{
+			name_initialized = true;
+			sMemStat.setName(typeid(DERIVED).name());
+		}
+	}
+
 	virtual ~MemTrackable()
 	{
 		memDisclaim(mMemFootprint);
@@ -353,7 +368,7 @@ public:
 
 	void* operator new(size_t size) 
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 		accumulator.mAllocatedCount++;
 
@@ -377,7 +392,7 @@ public:
 
 	void operator delete(void* ptr, size_t size)
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 		accumulator.mAllocatedCount--;
 		accumulator.mDeallocatedCount++;
@@ -402,7 +417,7 @@ public:
 
 	void *operator new [](size_t size)
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 		accumulator.mAllocatedCount++;
 
@@ -426,7 +441,7 @@ public:
 
 	void operator delete[](void* ptr, size_t size)
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 		accumulator.mAllocatedCount--;
 		accumulator.mDeallocatedCount++;
@@ -468,7 +483,7 @@ public:
 	template<typename AMOUNT_T>
 	AMOUNT_T& memClaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
 		mMemFootprint += (size_t)size;
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 		return size;
@@ -492,7 +507,7 @@ public:
 	template<typename AMOUNT_T>
 	AMOUNT_T& memDisclaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 		return size;
 	}
@@ -505,7 +520,7 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
+			MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
 			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
 			accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)footprint : (F64)footprint);
 			tracker.mMemFootprint += footprint;
@@ -513,7 +528,7 @@ private:
 
 		static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
+			MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
 			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
 			accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)footprint : -(F64)footprint);
 			tracker.mMemFootprint -= footprint;
@@ -525,21 +540,20 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
+			MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
 			accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() + (F64)MemFootprint<TRACKED>::measure(tracked) : (F64)MemFootprint<TRACKED>::measure(tracked));
 		}
 
 		static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = DERIVED::sMemStat.getCurrentAccumulator();
+			MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
 			accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() - (F64)MemFootprint<TRACKED>::measure(tracked) : -(F64)MemFootprint<TRACKED>::measure(tracked));
 		}
 	};
 };
 
-// pretty sure typeid of containing class in static object constructor doesn't work in gcc
 template<typename DERIVED, size_t ALIGNMENT>
-MemStatHandle MemTrackable<DERIVED, ALIGNMENT>::sMemStat(typeid(DERIVED).name());
+MemStatHandle MemTrackable<DERIVED, ALIGNMENT>::sMemStat("");
 
 }
 #endif // LL_LLTRACE_H
-- 
cgit v1.2.3


From 5f7f84c7acb686659b2bdc9a018b18c2b23db3d0 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Sun, 8 Sep 2013 11:35:53 -0700
Subject: forgot to update instancetracker key when lazily generating name for
 memstat trace

---
 indra/llcommon/lltrace.h | 1 +
 1 file changed, 1 insertion(+)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 9713bd6c04..f7ceaf585d 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -243,6 +243,7 @@ public:
 	void setName(const char* name)
 	{
 		mName = name;
+		setKey(name);
 	}
 
 	/*virtual*/ const char* getUnitLabel() const { return "B"; }
-- 
cgit v1.2.3


From 4f44366731c6fb3bf62c29a5413dc8db86ab4f2e Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 9 Sep 2013 11:43:12 -0700
Subject: BUILDFIX: don't use typeinfo() in static object constructor of
 baseclass

---
 indra/llcommon/lltrace.h | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index d42c8e26fb..afa9933165 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -62,8 +62,8 @@ public:
 	const std::string& getDescription() const { return mDescription; }
 
 protected:
-	const std::string	mName;
-	const std::string	mDescription;
+	std::string	mName;
+	std::string	mDescription;
 };
 
 template<typename ACCUMULATOR>
@@ -225,6 +225,12 @@ public:
 	:	trace_t(name)
 	{}
 
+    void setName(const char* name)
+    {
+        mName = name;
+        setKey(name);
+    }
+    
 	/*virtual*/ const char* getUnitLabel() const { return "B"; }
 
 	TraceType<MemStatAccumulator::AllocationCountFacet>& allocationCount() 
@@ -331,6 +337,17 @@ class MemTrackable
 public:
 	typedef void mem_trackable_tag_t;
 
+    MemTrackable()
+    {
+        static bool name_initialized = false;
+        if (!name_initialized)
+        {
+            name_initialized = true;
+            sMemStat.setName(typeid(DERIVED).name());
+        }
+    }
+    
+    
 	virtual ~MemTrackable()
 	{
 		memDisclaim(mMemFootprint);
@@ -524,7 +541,7 @@ private:
 
 // pretty sure typeid of containing class in static object constructor doesn't work in gcc
 template<typename DERIVED, size_t ALIGNMENT>
-MemStatHandle MemTrackable<DERIVED, ALIGNMENT>::sMemStat(typeid(DERIVED).name());
+MemStatHandle MemTrackable<DERIVED, ALIGNMENT>::sMemStat("");
 
 }
 #endif // LL_LLTRACE_H
-- 
cgit v1.2.3


From 21ab67416d471a90b343052c986478c9dd65ae79 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 9 Sep 2013 20:18:12 -0700
Subject: SH-4774 FIX: textures are blurry on Mac

---
 indra/llcommon/llsys.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 2b0083caff..49cc441b68 100755
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -862,17 +862,17 @@ U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
 	size_t len = sizeof(phys);	
 	sysctl(mib, 2, &phys, &len, NULL, 0);
 	
-	return U32Bytes(phys);
+	return U32Bytes(llmax(phys, (U64)U32_MAX));
 
 #elif LL_LINUX
 	U64 phys = 0;
 	phys = (U64)(getpagesize()) * (U64)(get_phys_pages());
-	return U32Bytes(phys);
+	return U32Bytes(llmax(phys, (U64)U32_MAX));
 
 #elif LL_SOLARIS
 	U64 phys = 0;
 	phys = (U64)(getpagesize()) * (U64)(sysconf(_SC_PHYS_PAGES));
-	return U32Bytes(phys);
+	return U32Bytes(llmax(phys, (U64)U32_MAX));
 
 #else
 	return 0;
-- 
cgit v1.2.3


From 420a1af0c86113a7db291022373b69c2b8810c7c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 11 Sep 2013 16:26:03 -0700
Subject: SH-4774 FIX: textures are blurry on Mac

---
 indra/llcommon/llsys.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 397ef498d2..7267ba333e 100755
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -868,17 +868,17 @@ U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
 	size_t len = sizeof(phys);	
 	sysctl(mib, 2, &phys, &len, NULL, 0);
 	
-	return U32Bytes(llmax(phys, (U64)U32_MAX));
+	return U32Bytes(llmin(phys, (U64)U32_MAX));
 
 #elif LL_LINUX
 	U64 phys = 0;
 	phys = (U64)(getpagesize()) * (U64)(get_phys_pages());
-	return U32Bytes(llmax(phys, (U64)U32_MAX));
+	return U32Bytes(llmin(phys, (U64)U32_MAX));
 
 #elif LL_SOLARIS
 	U64 phys = 0;
 	phys = (U64)(getpagesize()) * (U64)(sysconf(_SC_PHYS_PAGES));
-	return U32Bytes(llmax(phys, (U64)U32_MAX));
+	return U32Bytes(llmin(phys, (U64)U32_MAX));
 
 #else
 	return 0;
-- 
cgit v1.2.3


From 72f979135b3497d16c2635babf057900ddbc42fe Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 18 Sep 2013 14:20:30 -0700
Subject: merge

---
 indra/llcommon/lltrace.h                 | 81 ++++++++++++++++++++++----------
 indra/llcommon/lltraceaccumulators.cpp   | 12 ++---
 indra/llcommon/lltraceaccumulators.h     | 20 +++-----
 indra/llcommon/lltracerecording.cpp      | 20 ++++----
 indra/llcommon/lltracerecording.h        | 10 ++--
 indra/llcommon/lltracethreadrecorder.cpp |  2 +-
 6 files changed, 85 insertions(+), 60 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index f7ceaf585d..472f0b0cf0 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -80,8 +80,8 @@ public:
 
 	LL_FORCE_INLINE ACCUMULATOR& getCurrentAccumulator() const
 	{
-		ACCUMULATOR* accumulator_storage = AccumulatorBuffer<ACCUMULATOR>::getCurrentStorage();
-		return accumulator_storage[mAccumulatorIndex];
+		ACCUMULATOR* accumulator_storage = LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance();
+		return accumulator_storage ? accumulator_storage[mAccumulatorIndex] : (*AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer())[mAccumulatorIndex];
 	}
 
 	size_t getIndex() const { return mAccumulatorIndex; }
@@ -222,7 +222,7 @@ public:
 };
 
 template<>
-class TraceType<MemStatAccumulator::ChildMemFacet>
+class TraceType<MemStatAccumulator::ShadowMemFacet>
 	:	public TraceType<MemStatAccumulator>
 {
 public:
@@ -258,12 +258,51 @@ public:
 		return static_cast<TraceType<MemStatAccumulator::DeallocationCountFacet>&>(*(TraceType<MemStatAccumulator>*)this);
 	}
 
-	TraceType<MemStatAccumulator::ChildMemFacet>& childMem() 
+	TraceType<MemStatAccumulator::ShadowMemFacet>& childMem() 
 	{ 
-		return static_cast<TraceType<MemStatAccumulator::ChildMemFacet>&>(*(TraceType<MemStatAccumulator>*)this);
+		return static_cast<TraceType<MemStatAccumulator::ShadowMemFacet>&>(*(TraceType<MemStatAccumulator>*)this);
 	}
 };
 
+inline void track_alloc(MemStatHandle& measurement, size_t size)
+{
+	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
+	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
+	accumulator.mAllocatedCount++;
+}
+
+inline void track_dealloc(MemStatHandle& measurement, size_t size)
+{
+	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
+	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
+	accumulator.mAllocatedCount--;
+	accumulator.mDeallocatedCount++;
+}
+
+inline void claim_mem(MemStatHandle& measurement, size_t size)
+{
+	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
+	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
+}
+
+inline void disclaim_mem(MemStatHandle& measurement, size_t size)
+{
+	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
+	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
+}
+
+inline void claim_shadow_mem(MemStatHandle& measurement, size_t size)
+{
+	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
+	accumulator.mShadowSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
+}
+
+inline void disclaim_shadow_mem(MemStatHandle& measurement, size_t size)
+{
+	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
+	accumulator.mShadowSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
+}
+
 // measures effective memory footprint of specified type
 // specialize to cover different types
 
@@ -369,9 +408,7 @@ public:
 
 	void* operator new(size_t size) 
 	{
-		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
-		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
-		accumulator.mAllocatedCount++;
+		track_alloc(sMemStat, size);
 
 		if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
 		{
@@ -393,10 +430,7 @@ public:
 
 	void operator delete(void* ptr, size_t size)
 	{
-		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
-		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
-		accumulator.mAllocatedCount--;
-		accumulator.mDeallocatedCount++;
+		track_dealloc(sMemStat, size);
 
 		if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
 		{
@@ -418,9 +452,7 @@ public:
 
 	void *operator new [](size_t size)
 	{
-		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
-		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
-		accumulator.mAllocatedCount++;
+		track_alloc(sMemStat, size);
 
 		if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
 		{
@@ -442,7 +474,7 @@ public:
 
 	void operator delete[](void* ptr, size_t size)
 	{
-		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 		accumulator.mAllocatedCount--;
 		accumulator.mDeallocatedCount++;
@@ -484,9 +516,8 @@ public:
 	template<typename AMOUNT_T>
 	AMOUNT_T& memClaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 		mMemFootprint += (size_t)size;
-		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 		return size;
 	}
 
@@ -508,7 +539,7 @@ public:
 	template<typename AMOUNT_T>
 	AMOUNT_T& memDisclaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 		return size;
 	}
@@ -521,17 +552,17 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
+			MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
-			accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)footprint : (F64)footprint);
+			claim_mem(sMemStat, footprint);
 			tracker.mMemFootprint += footprint;
 		}
 
 		static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
+			MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
-			accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)footprint : -(F64)footprint);
+			disclaim_mem(sMemStat, footprint);
 			tracker.mMemFootprint -= footprint;
 		}
 	};
@@ -541,13 +572,13 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
+			MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 			accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() + (F64)MemFootprint<TRACKED>::measure(tracked) : (F64)MemFootprint<TRACKED>::measure(tracked));
 		}
 
 		static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
+			MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 			accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() - (F64)MemFootprint<TRACKED>::measure(tracked) : -(F64)MemFootprint<TRACKED>::measure(tracked));
 		}
 	};
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index b234f43337..58d0b5b227 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -70,13 +70,13 @@ void AccumulatorBufferGroup::makeCurrent()
 }
 
 //static
-void AccumulatorBufferGroup::resetCurrent()
+void AccumulatorBufferGroup::clearCurrent()
 {
-	AccumulatorBuffer<CountAccumulator>::resetCurrent();	
-	AccumulatorBuffer<SampleAccumulator>::resetCurrent();
-	AccumulatorBuffer<EventAccumulator>::resetCurrent();
-	AccumulatorBuffer<TimeBlockAccumulator>::resetCurrent();
-	AccumulatorBuffer<MemStatAccumulator>::resetCurrent();
+	AccumulatorBuffer<CountAccumulator>::clearCurrent();	
+	AccumulatorBuffer<SampleAccumulator>::clearCurrent();
+	AccumulatorBuffer<EventAccumulator>::clearCurrent();
+	AccumulatorBuffer<TimeBlockAccumulator>::clearCurrent();
+	AccumulatorBuffer<MemStatAccumulator>::clearCurrent();
 }
 
 bool AccumulatorBufferGroup::isCurrent() const
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index e31058ab4b..c5a0693fef 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -138,17 +138,11 @@ namespace LLTrace
 			return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage;
 		}
 
-		static void resetCurrent()
+		static void clearCurrent()
 		{
 			LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
 		}
 
-		LL_FORCE_INLINE static ACCUMULATOR* getCurrentStorage() 
-		{ 
-			ACCUMULATOR* accumulator = LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance();
-			return accumulator ? accumulator : getDefaultBuffer()->mStorage;
-		}
-
 		// NOTE: this is not thread-safe.  We assume that slots are reserved in the main thread before any child threads are spawned
 		size_t reserveSlot()
 		{
@@ -491,7 +485,7 @@ namespace LLTrace
 			typedef U32 value_t;
 		};
 
-		struct ChildMemFacet
+		struct ShadowMemFacet
 		{
 			typedef F64Bytes value_t;
 		};
@@ -504,7 +498,7 @@ namespace LLTrace
 		void addSamples(const MemStatAccumulator& other, EBufferAppendType append_type)
 		{
 			mSize.addSamples(other.mSize, append_type);
-			mChildSize.addSamples(other.mChildSize, append_type);
+			mShadowSize.addSamples(other.mShadowSize, append_type);
 			mAllocatedCount += other.mAllocatedCount;
 			mDeallocatedCount += other.mDeallocatedCount;
 		}
@@ -512,7 +506,7 @@ namespace LLTrace
 		void reset(const MemStatAccumulator* other)
 		{
 			mSize.reset(other ? &other->mSize : NULL);
-			mChildSize.reset(other ? &other->mChildSize : NULL);
+			mShadowSize.reset(other ? &other->mShadowSize : NULL);
 			mAllocatedCount = 0;
 			mDeallocatedCount = 0;
 		}
@@ -520,11 +514,11 @@ namespace LLTrace
 		void sync(F64SecondsImplicit time_stamp) 
 		{
 			mSize.sync(time_stamp);
-			mChildSize.sync(time_stamp);
+			mShadowSize.sync(time_stamp);
 		}
 
 		SampleAccumulator	mSize,
-							mChildSize;
+							mShadowSize;
 		int					mAllocatedCount,
 							mDeallocatedCount;
 	};
@@ -536,7 +530,7 @@ namespace LLTrace
 		void handOffTo(AccumulatorBufferGroup& other);
 		void makeCurrent();
 		bool isCurrent() const;
-		static void resetCurrent();
+		static void clearCurrent();
 
 		void append(const AccumulatorBufferGroup& other);
 		void merge(const AccumulatorBufferGroup& other);
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index bc98eebf31..c278901bc0 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -193,29 +193,29 @@ F64Bytes Recording::getLastValue(const TraceType<MemStatAccumulator>& stat)
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue());
 }
 
-F64Bytes Recording::getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
+F64Bytes Recording::getMin(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMin());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getMin());
 }
 
-F64Bytes Recording::getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
+F64Bytes Recording::getMean(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMean());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getMean());
 }
 
-F64Bytes Recording::getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
+F64Bytes Recording::getMax(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getMax());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getMax());
 }
 
-F64Bytes Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
+F64Bytes Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getStandardDeviation());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getStandardDeviation());
 }
 
-F64Bytes Recording::getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat)
+F64Bytes Recording::getLastValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mChildSize.getLastValue());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getLastValue());
 }
 
 U32 Recording::getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat)
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index ea090e6ee1..9550838798 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -181,11 +181,11 @@ namespace LLTrace
 		F64Bytes getStandardDeviation(const TraceType<MemStatAccumulator>& stat);
 		F64Bytes getLastValue(const TraceType<MemStatAccumulator>& stat);
 
-		F64Bytes getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat);
-		F64Bytes getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat);
-		F64Bytes getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat);
-		F64Bytes getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat);
-		F64Bytes getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat);
+		F64Bytes getMin(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
+		F64Bytes getMean(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
+		F64Bytes getMax(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
+		F64Bytes getStandardDeviation(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
+		F64Bytes getLastValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
 
 		U32 getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat);
 		U32 getSum(const TraceType<MemStatAccumulator::DeallocationCountFacet>& stat);
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 8cddc49e71..d3d9eb5ca7 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -194,7 +194,7 @@ void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording )
 		{
 			if (mActiveRecordings.empty())
 			{
-				AccumulatorBufferGroup::resetCurrent();
+				AccumulatorBufferGroup::clearCurrent();
 			}
 			else
 			{
-- 
cgit v1.2.3


From f5ca3695f22fa52b4d6b2db9c8a9e10a78869518 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 18 Sep 2013 14:45:15 -0700
Subject: BUILDFIX: bad merge

---
 indra/llcommon/lltrace.h | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 472f0b0cf0..3cc0d16b93 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -539,8 +539,7 @@ public:
 	template<typename AMOUNT_T>
 	AMOUNT_T& memDisclaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
-		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
+		disclaim_mem(size);
 		return size;
 	}
 
@@ -552,7 +551,6 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
 			claim_mem(sMemStat, footprint);
 			tracker.mMemFootprint += footprint;
@@ -560,7 +558,6 @@ private:
 
 		static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
 			disclaim_mem(sMemStat, footprint);
 			tracker.mMemFootprint -= footprint;
@@ -572,13 +569,11 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 			accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() + (F64)MemFootprint<TRACKED>::measure(tracked) : (F64)MemFootprint<TRACKED>::measure(tracked));
 		}
 
 		static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
 			accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() - (F64)MemFootprint<TRACKED>::measure(tracked) : -(F64)MemFootprint<TRACKED>::measure(tracked));
 		}
 	};
-- 
cgit v1.2.3


From 02dc270620bab6d3bd8035294af4be5b35894b1c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 18 Sep 2013 17:08:34 -0700
Subject: BUILDFIX: bad merge

---
 indra/llcommon/lltrace.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 3cc0d16b93..3b4370f947 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -474,7 +474,7 @@ public:
 
 	void operator delete[](void* ptr, size_t size)
 	{
-		MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
 		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 		accumulator.mAllocatedCount--;
 		accumulator.mDeallocatedCount++;
@@ -516,7 +516,7 @@ public:
 	template<typename AMOUNT_T>
 	AMOUNT_T& memClaimAmount(AMOUNT_T& size)
 	{
-		MemStatAccumulator& accumulator = sMemStat.getPrimaryAccumulator();
+		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
 		mMemFootprint += (size_t)size;
 		return size;
 	}
@@ -569,12 +569,12 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() + (F64)MemFootprint<TRACKED>::measure(tracked) : (F64)MemFootprint<TRACKED>::measure(tracked));
+			claim_shadow_mem( (F64)MemFootprint<TRACKED>::measure(tracked));
 		}
 
 		static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			accumulator.mChildSize.sample(accumulator.mChildSize.hasValue() ? accumulator.mChildSize.getLastValue() - (F64)MemFootprint<TRACKED>::measure(tracked) : -(F64)MemFootprint<TRACKED>::measure(tracked));
+			disclaim_shadow_mem((F64)MemFootprint<TRACKED>::measure(tracked));
 		}
 	};
 };
-- 
cgit v1.2.3


From 0dfc08d22a21728ec670bd75e6fd0ed60c97bf06 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 19 Sep 2013 15:21:46 -0700
Subject: BUILDFIX: more bad merge stuff also added ability for statbar to show
 memtrackable info

---
 indra/llcommon/lltrace.h            |  26 ++++++---
 indra/llcommon/lltracerecording.cpp | 102 ++++++++++++++++++++++++++++++++++++
 indra/llcommon/lltracerecording.h   |  15 ++++++
 3 files changed, 136 insertions(+), 7 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 3b4370f947..f677e4349e 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -512,12 +512,17 @@ public:
 		return value;
 	}
 
+	const size_t& memClaim(const size_t& size)
+	{
+		claim_mem(sMemStat, size);
+		mMemFootprint += size;
+		return size;
+	}
 
-	template<typename AMOUNT_T>
-	AMOUNT_T& memClaimAmount(AMOUNT_T& size)
+	size_t& memClaim(size_t& size)
 	{
-		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
-		mMemFootprint += (size_t)size;
+		claim_mem(sMemStat, size);
+		mMemFootprint += size;
 		return size;
 	}
 
@@ -536,10 +541,17 @@ public:
 		return value;
 	}
 
-	template<typename AMOUNT_T>
-	AMOUNT_T& memDisclaimAmount(AMOUNT_T& size)
+	const size_t& memDisclaim(const size_t& size)
+	{
+		disclaim_mem(sMemStat, size);
+		mMemFootprint -= size;
+		return size;
+	}
+
+	size_t& memDisclaim(size_t& size)
 	{
-		disclaim_mem(size);
+		disclaim_mem(sMemStat, size);
+		mMemFootprint -= size;
 		return size;
 	}
 
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index c278901bc0..7155cfa40a 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -168,6 +168,16 @@ F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>&
 	return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds.value();
 }
 
+bool Recording::hasValue(const TraceType<MemStatAccumulator>& stat)
+{
+	return mBuffers->mMemStats[stat.getIndex()].mSize.hasValue();
+}
+
+bool Recording::hasValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
+{
+	return mBuffers->mMemStats[stat.getIndex()].mShadowSize.hasValue();
+}
+
 F64Bytes Recording::getMin(const TraceType<MemStatAccumulator>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMin());
@@ -707,6 +717,98 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<SampleAccumul
 			: NaN;
 }
 
+
+F64Bytes PeriodicRecording::getPeriodMin( const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+{
+	size_t total_periods = mRecordingPeriods.size();
+	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+
+	F64Bytes min_val(std::numeric_limits<F64>::max());
+	for (S32 i = 1; i <= num_periods; i++)
+	{
+		Recording& recording = getPrevRecording(i);
+		min_val = llmin(min_val, recording.getMin(stat));
+	}
+
+	return min_val;
+}
+
+F64Bytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, size_t num_periods)
+{
+	return getPeriodMin(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
+}
+
+F64Bytes PeriodicRecording::getPeriodMax(const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/)
+{
+	size_t total_periods = mRecordingPeriods.size();
+	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+
+	F64Bytes max_val(0.0);
+	for (S32 i = 1; i <= num_periods; i++)
+	{
+		Recording& recording = getPrevRecording(i);
+		max_val = llmax(max_val, recording.getMax(stat));
+	}
+
+	return max_val;
+}
+
+F64Bytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, size_t num_periods)
+{
+	return getPeriodMax(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
+}
+
+F64Bytes PeriodicRecording::getPeriodMean( const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+{
+	size_t total_periods = mRecordingPeriods.size();
+	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+
+	F64Bytes mean(0);
+
+	for (S32 i = 1; i <= num_periods; i++)
+	{
+		Recording& recording = getPrevRecording(i);
+		mean += recording.getMean(stat);
+	}
+
+	return mean / F64(num_periods);
+}
+
+F64Bytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, size_t num_periods)
+{
+	return getPeriodMean(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
+}
+
+F64Bytes PeriodicRecording::getPeriodStandardDeviation( const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+{
+	size_t total_periods = mRecordingPeriods.size();
+	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+
+	F64Bytes period_mean = getPeriodMean(stat, num_periods);
+	S32 valid_period_count = 0;
+	F64 sum_of_squares = 0;
+
+	for (S32 i = 1; i <= num_periods; i++)
+	{
+		Recording& recording = getPrevRecording(i);
+		if (recording.hasValue(stat))
+		{
+			F64Bytes delta = recording.getMean(stat) - period_mean;
+			sum_of_squares += delta.value() * delta.value();
+			valid_period_count++;
+		}
+	}
+
+	return F64Bytes(valid_period_count
+			? sqrt(sum_of_squares / (F64)valid_period_count)
+			: NaN);
+}
+
+F64Bytes PeriodicRecording::getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods)
+{
+	return getPeriodStandardDeviation(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
+}
+
 ///////////////////////////////////////////////////////////////////////
 // ExtendableRecording
 ///////////////////////////////////////////////////////////////////////
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 9550838798..edda0f3a8c 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -175,6 +175,9 @@ namespace LLTrace
 		F32 getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat);
 
 		// Memory accessors
+		bool hasValue(const TraceType<MemStatAccumulator>& stat);
+		bool hasValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
+
 		F64Bytes getMin(const TraceType<MemStatAccumulator>& stat);
 		F64Bytes getMean(const TraceType<MemStatAccumulator>& stat);
 		F64Bytes getMax(const TraceType<MemStatAccumulator>& stat);
@@ -392,6 +395,9 @@ namespace LLTrace
 			return T(getPeriodMin(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
+		F64Bytes getPeriodMin(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64Bytes getPeriodMin(const MemStatHandle& stat, size_t num_periods = U32_MAX);
+
 		template <typename T>
 		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
 		{
@@ -453,6 +459,9 @@ namespace LLTrace
 			return T(getPeriodMax(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
+		F64Bytes getPeriodMax(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64Bytes getPeriodMax(const MemStatHandle& stat, size_t num_periods = U32_MAX);
+
 		template <typename T>
 		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
 		{
@@ -519,6 +528,9 @@ namespace LLTrace
 			return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
+		F64Bytes getPeriodMean(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64Bytes getPeriodMean(const MemStatHandle& stat, size_t num_periods = U32_MAX);
+		
 		template <typename T>
 		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
 		{
@@ -566,6 +578,9 @@ namespace LLTrace
 			return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
+		F64Bytes getPeriodStandardDeviation(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64Bytes getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods = U32_MAX);
+
 	private:
 		// implementation for LLStopWatchControlsMixin
 		/*virtual*/ void handleStart();
-- 
cgit v1.2.3


From 448f5b42a071a88d5e3031538bcf60102c99af89 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 19 Sep 2013 16:36:55 -0700
Subject: BUILDFIX: bad calls to claim_shadow_mem and disclaim_shadow_mem

---
 indra/llcommon/lltrace.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index f677e4349e..49ee252014 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -581,12 +581,12 @@ private:
 	{
 		static void claim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			claim_shadow_mem( (F64)MemFootprint<TRACKED>::measure(tracked));
+			claim_shadow_mem( sMemStat, MemFootprint<TRACKED>::measure(tracked));
 		}
 
 		static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
 		{
-			disclaim_shadow_mem((F64)MemFootprint<TRACKED>::measure(tracked));
+			disclaim_shadow_mem(sMemStat, MemFootprint<TRACKED>::measure(tracked));
 		}
 	};
 };
-- 
cgit v1.2.3


From 05ec5ca3d592ed7c730026582a2573d04c6e4c16 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 19 Sep 2013 20:05:53 -0700
Subject: BUILDFIX: forgot forward declaration better overrides for memclaim
 and memdisclaim of sizes added occlusion stats to stats floater stats now
 render range instead of mean

---
 indra/llcommon/lltrace.h          | 8 ++++----
 indra/llcommon/lltracerecording.h | 2 ++
 2 files changed, 6 insertions(+), 4 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 49ee252014..bf1119d694 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -512,14 +512,14 @@ public:
 		return value;
 	}
 
-	const size_t& memClaim(const size_t& size)
+	size_t& memClaim(size_t& size)
 	{
 		claim_mem(sMemStat, size);
 		mMemFootprint += size;
 		return size;
 	}
 
-	size_t& memClaim(size_t& size)
+	int& memClaim(int& size)
 	{
 		claim_mem(sMemStat, size);
 		mMemFootprint += size;
@@ -541,14 +541,14 @@ public:
 		return value;
 	}
 
-	const size_t& memDisclaim(const size_t& size)
+	size_t& memDisclaim(size_t& size)
 	{
 		disclaim_mem(sMemStat, size);
 		mMemFootprint -= size;
 		return size;
 	}
 
-	size_t& memDisclaim(size_t& size)
+	int& memDisclaim(int& size)
 	{
 		disclaim_mem(sMemStat, size);
 		mMemFootprint -= size;
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index edda0f3a8c..2f5cefa8eb 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -124,6 +124,8 @@ namespace LLTrace
 	template<typename T>
 	class EventStatHandle;
 
+	class MemStatHandle;
+
 	template<typename T>
 	struct RelatedTypes
 	{
-- 
cgit v1.2.3


From e25b5a359faaf4bb51186235567fcb1fea15e440 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 23 Sep 2013 16:07:32 -0700
Subject: refactored lltrace mem tracking to store allocation and deallocation
 sizes at the same time and work better with threads

---
 indra/llcommon/lltrace.h             | 76 ++++++++++++++++++++++--------------
 indra/llcommon/lltraceaccumulators.h | 58 +++++++++++++++++++--------
 indra/llcommon/lltracerecording.cpp  | 57 +++++++++++++++++++++++++--
 indra/llcommon/lltracerecording.h    | 19 +++++++--
 4 files changed, 157 insertions(+), 53 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index bf1119d694..9c620ca5e3 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -200,7 +200,7 @@ void add(CountStatHandle<T>& count, VALUE_T value)
 }
 
 template<>
-class TraceType<MemStatAccumulator::AllocationCountFacet>
+class TraceType<MemStatAccumulator::AllocationFacet>
 :	public TraceType<MemStatAccumulator>
 {
 public:
@@ -211,7 +211,7 @@ public:
 };
 
 template<>
-class TraceType<MemStatAccumulator::DeallocationCountFacet>
+class TraceType<MemStatAccumulator::DeallocationFacet>
 :	public TraceType<MemStatAccumulator>
 {
 public:
@@ -221,6 +221,28 @@ public:
 	{}
 };
 
+template<>
+class TraceType<MemStatAccumulator::ShadowAllocationFacet>
+	:	public TraceType<MemStatAccumulator>
+{
+public:
+
+	TraceType(const char* name, const char* description = "")
+		:	TraceType<MemStatAccumulator>(name, description)
+	{}
+};
+
+template<>
+class TraceType<MemStatAccumulator::ShadowDeallocationFacet>
+	:	public TraceType<MemStatAccumulator>
+{
+public:
+
+	TraceType(const char* name, const char* description = "")
+		:	TraceType<MemStatAccumulator>(name, description)
+	{}
+};
+
 template<>
 class TraceType<MemStatAccumulator::ShadowMemFacet>
 	:	public TraceType<MemStatAccumulator>
@@ -248,59 +270,58 @@ public:
 
 	/*virtual*/ const char* getUnitLabel() const { return "B"; }
 
-	TraceType<MemStatAccumulator::AllocationCountFacet>& allocationCount() 
+	TraceType<MemStatAccumulator::AllocationFacet>& allocations() 
 	{ 
-		return static_cast<TraceType<MemStatAccumulator::AllocationCountFacet>&>(*(TraceType<MemStatAccumulator>*)this);
+		return static_cast<TraceType<MemStatAccumulator::AllocationFacet>&>(*(TraceType<MemStatAccumulator>*)this);
 	}
 
-	TraceType<MemStatAccumulator::DeallocationCountFacet>& deallocationCount() 
+	TraceType<MemStatAccumulator::DeallocationFacet>& deallocations() 
 	{ 
-		return static_cast<TraceType<MemStatAccumulator::DeallocationCountFacet>&>(*(TraceType<MemStatAccumulator>*)this);
+		return static_cast<TraceType<MemStatAccumulator::DeallocationFacet>&>(*(TraceType<MemStatAccumulator>*)this);
 	}
 
-	TraceType<MemStatAccumulator::ShadowMemFacet>& childMem() 
+	TraceType<MemStatAccumulator::ShadowAllocationFacet>& shadowAllocations() 
 	{ 
-		return static_cast<TraceType<MemStatAccumulator::ShadowMemFacet>&>(*(TraceType<MemStatAccumulator>*)this);
+		return static_cast<TraceType<MemStatAccumulator::ShadowAllocationFacet>&>(*(TraceType<MemStatAccumulator>*)this);
 	}
-};
 
-inline void track_alloc(MemStatHandle& measurement, size_t size)
-{
-	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
-	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
-	accumulator.mAllocatedCount++;
-}
+	TraceType<MemStatAccumulator::ShadowDeallocationFacet>& shadowDeallocations() 
+	{ 
+		return static_cast<TraceType<MemStatAccumulator::ShadowDeallocationFacet>&>(*(TraceType<MemStatAccumulator>*)this);
+	}
 
-inline void track_dealloc(MemStatHandle& measurement, size_t size)
-{
-	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
-	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
-	accumulator.mAllocatedCount--;
-	accumulator.mDeallocatedCount++;
-}
+	TraceType<MemStatAccumulator::ShadowMemFacet>& shadowMem() 
+	{ 
+		return static_cast<TraceType<MemStatAccumulator::ShadowMemFacet>&>(*(TraceType<MemStatAccumulator>*)this);
+	}
+};
 
 inline void claim_mem(MemStatHandle& measurement, size_t size)
 {
 	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
+	accumulator.mAllocated.add(1);
 }
 
 inline void disclaim_mem(MemStatHandle& measurement, size_t size)
 {
 	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
+	accumulator.mDeallocated.add(1);
 }
 
 inline void claim_shadow_mem(MemStatHandle& measurement, size_t size)
 {
 	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mShadowSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
+	accumulator.mShadowAllocated.add(1);
 }
 
 inline void disclaim_shadow_mem(MemStatHandle& measurement, size_t size)
 {
 	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mShadowSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
+	accumulator.mShadowDeallocated.add(1);
 }
 
 // measures effective memory footprint of specified type
@@ -408,7 +429,7 @@ public:
 
 	void* operator new(size_t size) 
 	{
-		track_alloc(sMemStat, size);
+		claim_mem(sMemStat, size);
 
 		if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
 		{
@@ -430,7 +451,7 @@ public:
 
 	void operator delete(void* ptr, size_t size)
 	{
-		track_dealloc(sMemStat, size);
+		disclaim_mem(sMemStat, size);
 
 		if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
 		{
@@ -452,7 +473,7 @@ public:
 
 	void *operator new [](size_t size)
 	{
-		track_alloc(sMemStat, size);
+		claim_mem(sMemStat, size);
 
 		if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
 		{
@@ -474,10 +495,7 @@ public:
 
 	void operator delete[](void* ptr, size_t size)
 	{
-		MemStatAccumulator& accumulator = sMemStat.getCurrentAccumulator();
-		accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
-		accumulator.mAllocatedCount--;
-		accumulator.mDeallocatedCount++;
+		disclaim_mem(sMemStat, size);
 
 		if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
 		{
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index c5a0693fef..37a35f4e23 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -475,40 +475,62 @@ namespace LLTrace
 		typedef MemStatAccumulator self_t;
 
 		// fake classes that allows us to view different facets of underlying statistic
-		struct AllocationCountFacet 
+		struct AllocationFacet 
 		{
-			typedef U32 value_t;
+			typedef F64Bytes value_t;
 		};
 
-		struct DeallocationCountFacet 
+		struct DeallocationFacet 
 		{
-			typedef U32 value_t;
+			typedef F64Bytes value_t;
 		};
 
-		struct ShadowMemFacet
+		struct ShadowAllocationFacet 
 		{
 			typedef F64Bytes value_t;
 		};
 
-		MemStatAccumulator()
-		:	mAllocatedCount(0),
-			mDeallocatedCount(0)
-		{}
+		struct ShadowDeallocationFacet 
+		{
+			typedef F64Bytes value_t;
+		};
+
+		struct ShadowMemFacet
+		{
+			typedef F64Bytes value_t;
+		};
 
 		void addSamples(const MemStatAccumulator& other, EBufferAppendType append_type)
 		{
-			mSize.addSamples(other.mSize, append_type);
-			mShadowSize.addSamples(other.mShadowSize, append_type);
-			mAllocatedCount += other.mAllocatedCount;
-			mDeallocatedCount += other.mDeallocatedCount;
+			mAllocated.addSamples(other.mAllocated, append_type);
+			mDeallocated.addSamples(other.mDeallocated, append_type);
+			if (append_type == SEQUENTIAL)
+			{
+				mSize.addSamples(other.mSize, SEQUENTIAL);
+				mShadowSize.addSamples(other.mShadowSize, SEQUENTIAL);
+			}
+			else
+			{
+				F64 allocation_delta(other.mAllocated.getSum() - other.mDeallocated.getSum());
+				mSize.sample(mSize.hasValue() 
+					? mSize.getLastValue() + allocation_delta 
+					: allocation_delta);
+
+				F64 shadow_allocation_delta(other.mShadowAllocated.getSum() - other.mShadowDeallocated.getSum());
+				mShadowSize.sample(mShadowSize.hasValue() 
+					? mShadowSize.getLastValue() + shadow_allocation_delta 
+					: shadow_allocation_delta);
+			}
 		}
 
 		void reset(const MemStatAccumulator* other)
 		{
 			mSize.reset(other ? &other->mSize : NULL);
 			mShadowSize.reset(other ? &other->mShadowSize : NULL);
-			mAllocatedCount = 0;
-			mDeallocatedCount = 0;
+			mAllocated.reset(other ? &other->mAllocated : NULL);
+			mDeallocated.reset(other ? &other->mDeallocated : NULL);
+			mShadowAllocated.reset(other ? &other->mShadowAllocated : NULL);
+			mShadowDeallocated.reset(other ? &other->mShadowDeallocated : NULL);
 		}
 
 		void sync(F64SecondsImplicit time_stamp) 
@@ -519,8 +541,10 @@ namespace LLTrace
 
 		SampleAccumulator	mSize,
 							mShadowSize;
-		int					mAllocatedCount,
-							mDeallocatedCount;
+		CountAccumulator	mAllocated,
+							mDeallocated,
+							mShadowAllocated,
+							mShadowDeallocated;
 	};
 
 	struct AccumulatorBufferGroup : public LLRefCount
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 7155cfa40a..5728997676 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -228,16 +228,65 @@ F64Bytes Recording::getLastValue(const TraceType<MemStatAccumulator::ShadowMemFa
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getLastValue());
 }
 
-U32 Recording::getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat)
+F64Bytes Recording::getSum(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mAllocatedCount;
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocated.getSum());
 }
 
-U32 Recording::getSum(const TraceType<MemStatAccumulator::DeallocationCountFacet>& stat)
+F64Bytes Recording::getPerSec(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mAllocatedCount;
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocated.getSum() / mElapsedSeconds.value());
 }
 
+U32 Recording::getSampleCount(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
+{
+	return mBuffers->mMemStats[stat.getIndex()].mAllocated.getSampleCount();
+}
+
+F64Bytes Recording::getSum(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
+{
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocated.getSum());
+}
+
+F64Bytes Recording::getPerSec(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
+{
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocated.getSum() / mElapsedSeconds.value());
+}
+
+U32 Recording::getSampleCount(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
+{
+	return mBuffers->mMemStats[stat.getIndex()].mDeallocated.getSampleCount();
+}
+
+F64Bytes Recording::getSum(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat)
+{
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowAllocated.getSum());
+}
+
+F64Bytes Recording::getPerSec(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat)
+{
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowAllocated.getSum() / mElapsedSeconds.value());
+}
+
+U32 Recording::getSampleCount(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat)
+{
+	return mBuffers->mMemStats[stat.getIndex()].mShadowAllocated.getSampleCount();
+}
+
+F64Bytes Recording::getSum(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat)
+{
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowDeallocated.getSum());
+}
+
+F64Bytes Recording::getPerSec(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat)
+{
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowDeallocated.getSum() / mElapsedSeconds.value());
+}
+
+U32 Recording::getSampleCount(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat)
+{
+	return mBuffers->mMemStats[stat.getIndex()].mShadowDeallocated.getSampleCount();
+}
 
 F64 Recording::getSum( const TraceType<CountAccumulator>& stat )
 {
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 2f5cefa8eb..466efe44ce 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -177,7 +177,7 @@ namespace LLTrace
 		F32 getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat);
 
 		// Memory accessors
-		bool hasValue(const TraceType<MemStatAccumulator>& stat);
+		bool hasValue(const TraceType<MemStatAccumulator>& stat);
 		bool hasValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
 
 		F64Bytes getMin(const TraceType<MemStatAccumulator>& stat);
@@ -192,8 +192,21 @@ namespace LLTrace
 		F64Bytes getStandardDeviation(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
 		F64Bytes getLastValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
 
-		U32 getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat);
-		U32 getSum(const TraceType<MemStatAccumulator::DeallocationCountFacet>& stat);
+		F64Bytes getSum(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
+		F64Bytes getPerSec(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
+		U32 getSampleCount(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
+
+		F64Bytes getSum(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
+		F64Bytes getPerSec(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
+		U32 getSampleCount(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
+
+		F64Bytes getSum(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat);
+		F64Bytes getPerSec(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat);
+		U32 getSampleCount(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat);
+
+		F64Bytes getSum(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat);
+		F64Bytes getPerSec(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat);
+		U32 getSampleCount(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat);
 
 		// CountStatHandle accessors
 		F64 getSum(const TraceType<CountAccumulator>& stat);
-- 
cgit v1.2.3


From ab8f64a96754edaa68dd1ff97b9519eff4496aa6 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 24 Sep 2013 00:05:43 -0700
Subject: converted memory tracking units to KB from B added more memory
 tracking to LLFolderView and kin

---
 indra/llcommon/lltrace.h            |  9 +++++-
 indra/llcommon/lltracerecording.cpp | 64 ++++++++++++++++++-------------------
 indra/llcommon/lltracerecording.h   | 56 ++++++++++++++++----------------
 3 files changed, 68 insertions(+), 61 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 9c620ca5e3..5c833ea287 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -268,7 +268,7 @@ public:
 		setKey(name);
 	}
 
-	/*virtual*/ const char* getUnitLabel() const { return "B"; }
+	/*virtual*/ const char* getUnitLabel() const { return "KB"; }
 
 	TraceType<MemStatAccumulator::AllocationFacet>& allocations() 
 	{ 
@@ -409,10 +409,12 @@ class MemTrackable
 
 	typedef MemTrackable<DERIVED, ALIGNMENT> mem_trackable_t;
 	static	MemStatHandle	sMemStat;
+
 public:
 	typedef void mem_trackable_tag_t;
 
 	MemTrackable()
+	:	mMemFootprint(0)
 	{
 		static bool name_initialized = false;
 		if (!name_initialized)
@@ -427,6 +429,11 @@ public:
 		memDisclaim(mMemFootprint);
 	}
 
+	static MemStatHandle& getMemStatHandle()
+	{
+		return sMemStat;
+	}
+
 	void* operator new(size_t size) 
 	{
 		claim_mem(sMemStat, size);
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 5728997676..c606007d89 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -178,62 +178,62 @@ bool Recording::hasValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& st
 	return mBuffers->mMemStats[stat.getIndex()].mShadowSize.hasValue();
 }
 
-F64Bytes Recording::getMin(const TraceType<MemStatAccumulator>& stat)
+F64Kilobytes Recording::getMin(const TraceType<MemStatAccumulator>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMin());
 }
 
-F64Bytes Recording::getMean(const TraceType<MemStatAccumulator>& stat)
+F64Kilobytes Recording::getMean(const TraceType<MemStatAccumulator>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMean());
 }
 
-F64Bytes Recording::getMax(const TraceType<MemStatAccumulator>& stat)
+F64Kilobytes Recording::getMax(const TraceType<MemStatAccumulator>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMax());
 }
 
-F64Bytes Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat)
+F64Kilobytes Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation());
 }
 
-F64Bytes Recording::getLastValue(const TraceType<MemStatAccumulator>& stat)
+F64Kilobytes Recording::getLastValue(const TraceType<MemStatAccumulator>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue());
 }
 
-F64Bytes Recording::getMin(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
+F64Kilobytes Recording::getMin(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getMin());
 }
 
-F64Bytes Recording::getMean(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
+F64Kilobytes Recording::getMean(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getMean());
 }
 
-F64Bytes Recording::getMax(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
+F64Kilobytes Recording::getMax(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getMax());
 }
 
-F64Bytes Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
+F64Kilobytes Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getStandardDeviation());
 }
 
-F64Bytes Recording::getLastValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
+F64Kilobytes Recording::getLastValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getLastValue());
 }
 
-F64Bytes Recording::getSum(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
+F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocated.getSum());
 }
 
-F64Bytes Recording::getPerSec(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
+F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocated.getSum() / mElapsedSeconds.value());
 }
@@ -243,12 +243,12 @@ U32 Recording::getSampleCount(const TraceType<MemStatAccumulator::AllocationFace
 	return mBuffers->mMemStats[stat.getIndex()].mAllocated.getSampleCount();
 }
 
-F64Bytes Recording::getSum(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
+F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocated.getSum());
 }
 
-F64Bytes Recording::getPerSec(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
+F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocated.getSum() / mElapsedSeconds.value());
 }
@@ -258,12 +258,12 @@ U32 Recording::getSampleCount(const TraceType<MemStatAccumulator::DeallocationFa
 	return mBuffers->mMemStats[stat.getIndex()].mDeallocated.getSampleCount();
 }
 
-F64Bytes Recording::getSum(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat)
+F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowAllocated.getSum());
 }
 
-F64Bytes Recording::getPerSec(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat)
+F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowAllocated.getSum() / mElapsedSeconds.value());
 }
@@ -273,12 +273,12 @@ U32 Recording::getSampleCount(const TraceType<MemStatAccumulator::ShadowAllocati
 	return mBuffers->mMemStats[stat.getIndex()].mShadowAllocated.getSampleCount();
 }
 
-F64Bytes Recording::getSum(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat)
+F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowDeallocated.getSum());
 }
 
-F64Bytes Recording::getPerSec(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat)
+F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowDeallocated.getSum() / mElapsedSeconds.value());
 }
@@ -767,12 +767,12 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<SampleAccumul
 }
 
 
-F64Bytes PeriodicRecording::getPeriodMin( const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+F64Kilobytes PeriodicRecording::getPeriodMin( const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
 {
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-	F64Bytes min_val(std::numeric_limits<F64>::max());
+	F64Kilobytes min_val(std::numeric_limits<F64>::max());
 	for (S32 i = 1; i <= num_periods; i++)
 	{
 		Recording& recording = getPrevRecording(i);
@@ -782,17 +782,17 @@ F64Bytes PeriodicRecording::getPeriodMin( const TraceType<MemStatAccumulator>& s
 	return min_val;
 }
 
-F64Bytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, size_t num_periods)
+F64Kilobytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, size_t num_periods)
 {
 	return getPeriodMin(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
 }
 
-F64Bytes PeriodicRecording::getPeriodMax(const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/)
+F64Kilobytes PeriodicRecording::getPeriodMax(const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/)
 {
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-	F64Bytes max_val(0.0);
+	F64Kilobytes max_val(0.0);
 	for (S32 i = 1; i <= num_periods; i++)
 	{
 		Recording& recording = getPrevRecording(i);
@@ -802,17 +802,17 @@ F64Bytes PeriodicRecording::getPeriodMax(const TraceType<MemStatAccumulator>& st
 	return max_val;
 }
 
-F64Bytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, size_t num_periods)
+F64Kilobytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, size_t num_periods)
 {
 	return getPeriodMax(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
 }
 
-F64Bytes PeriodicRecording::getPeriodMean( const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+F64Kilobytes PeriodicRecording::getPeriodMean( const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
 {
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-	F64Bytes mean(0);
+	F64Kilobytes mean(0);
 
 	for (S32 i = 1; i <= num_periods; i++)
 	{
@@ -823,17 +823,17 @@ F64Bytes PeriodicRecording::getPeriodMean( const TraceType<MemStatAccumulator>&
 	return mean / F64(num_periods);
 }
 
-F64Bytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, size_t num_periods)
+F64Kilobytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, size_t num_periods)
 {
 	return getPeriodMean(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
 }
 
-F64Bytes PeriodicRecording::getPeriodStandardDeviation( const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
 {
 	size_t total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-	F64Bytes period_mean = getPeriodMean(stat, num_periods);
+	F64Kilobytes period_mean = getPeriodMean(stat, num_periods);
 	S32 valid_period_count = 0;
 	F64 sum_of_squares = 0;
 
@@ -842,18 +842,18 @@ F64Bytes PeriodicRecording::getPeriodStandardDeviation( const TraceType<MemStatA
 		Recording& recording = getPrevRecording(i);
 		if (recording.hasValue(stat))
 		{
-			F64Bytes delta = recording.getMean(stat) - period_mean;
+			F64Kilobytes delta = recording.getMean(stat) - period_mean;
 			sum_of_squares += delta.value() * delta.value();
 			valid_period_count++;
 		}
 	}
 
-	return F64Bytes(valid_period_count
+	return F64Kilobytes(valid_period_count
 			? sqrt(sum_of_squares / (F64)valid_period_count)
 			: NaN);
 }
 
-F64Bytes PeriodicRecording::getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods)
+F64Kilobytes PeriodicRecording::getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods)
 {
 	return getPeriodStandardDeviation(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
 }
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 466efe44ce..3f7737b20b 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -180,32 +180,32 @@ namespace LLTrace
 		bool hasValue(const TraceType<MemStatAccumulator>& stat);
 		bool hasValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
 
-		F64Bytes getMin(const TraceType<MemStatAccumulator>& stat);
-		F64Bytes getMean(const TraceType<MemStatAccumulator>& stat);
-		F64Bytes getMax(const TraceType<MemStatAccumulator>& stat);
-		F64Bytes getStandardDeviation(const TraceType<MemStatAccumulator>& stat);
-		F64Bytes getLastValue(const TraceType<MemStatAccumulator>& stat);
-
-		F64Bytes getMin(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
-		F64Bytes getMean(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
-		F64Bytes getMax(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
-		F64Bytes getStandardDeviation(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
-		F64Bytes getLastValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
-
-		F64Bytes getSum(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
-		F64Bytes getPerSec(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
+		F64Kilobytes getMin(const TraceType<MemStatAccumulator>& stat);
+		F64Kilobytes getMean(const TraceType<MemStatAccumulator>& stat);
+		F64Kilobytes getMax(const TraceType<MemStatAccumulator>& stat);
+		F64Kilobytes getStandardDeviation(const TraceType<MemStatAccumulator>& stat);
+		F64Kilobytes getLastValue(const TraceType<MemStatAccumulator>& stat);
+
+		F64Kilobytes getMin(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
+		F64Kilobytes getMean(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
+		F64Kilobytes getMax(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
+		F64Kilobytes getStandardDeviation(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
+		F64Kilobytes getLastValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
+
+		F64Kilobytes getSum(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
+		F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
 		U32 getSampleCount(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
 
-		F64Bytes getSum(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
-		F64Bytes getPerSec(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
+		F64Kilobytes getSum(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
+		F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
 		U32 getSampleCount(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
 
-		F64Bytes getSum(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat);
-		F64Bytes getPerSec(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat);
+		F64Kilobytes getSum(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat);
+		F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat);
 		U32 getSampleCount(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat);
 
-		F64Bytes getSum(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat);
-		F64Bytes getPerSec(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat);
+		F64Kilobytes getSum(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat);
+		F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat);
 		U32 getSampleCount(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat);
 
 		// CountStatHandle accessors
@@ -410,8 +410,8 @@ namespace LLTrace
 			return T(getPeriodMin(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
-		F64Bytes getPeriodMin(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
-		F64Bytes getPeriodMin(const MemStatHandle& stat, size_t num_periods = U32_MAX);
+		F64Kilobytes getPeriodMin(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64Kilobytes getPeriodMin(const MemStatHandle& stat, size_t num_periods = U32_MAX);
 
 		template <typename T>
 		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
@@ -474,8 +474,8 @@ namespace LLTrace
 			return T(getPeriodMax(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
-		F64Bytes getPeriodMax(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
-		F64Bytes getPeriodMax(const MemStatHandle& stat, size_t num_periods = U32_MAX);
+		F64Kilobytes getPeriodMax(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64Kilobytes getPeriodMax(const MemStatHandle& stat, size_t num_periods = U32_MAX);
 
 		template <typename T>
 		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
@@ -543,8 +543,8 @@ namespace LLTrace
 			return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
-		F64Bytes getPeriodMean(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
-		F64Bytes getPeriodMean(const MemStatHandle& stat, size_t num_periods = U32_MAX);
+		F64Kilobytes getPeriodMean(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64Kilobytes getPeriodMean(const MemStatHandle& stat, size_t num_periods = U32_MAX);
 		
 		template <typename T>
 		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
@@ -593,8 +593,8 @@ namespace LLTrace
 			return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
-		F64Bytes getPeriodStandardDeviation(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
-		F64Bytes getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods = U32_MAX);
+		F64Kilobytes getPeriodStandardDeviation(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods = U32_MAX);
 
 	private:
 		// implementation for LLStopWatchControlsMixin
-- 
cgit v1.2.3


From 053d97db1b283ca2548dc1f64756ddfc5166158f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 25 Sep 2013 19:12:35 -0700
Subject: better memory usage for LLTrace (tighter packing of recording arrays)
 removed complicated and unnecessary fast timer gapless handoff logic (it
 should be gapless anyway) improved MemTrackable API, better separation of
 shadow and footprint added memory usage stats to floater_stats.xml

---
 indra/llcommon/llfasttimer.cpp           |  20 +--
 indra/llcommon/llfasttimer.h             |   4 +-
 indra/llcommon/llmemory.h                |  49 ++++-
 indra/llcommon/lltrace.h                 | 299 +++++++++++++------------------
 indra/llcommon/lltraceaccumulators.h     |  23 ++-
 indra/llcommon/lltracerecording.cpp      |   6 +-
 indra/llcommon/lltracethreadrecorder.cpp |   5 +-
 7 files changed, 202 insertions(+), 204 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 52b3bb39b2..32ef01b2b6 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -259,15 +259,12 @@ void TimeBlock::updateTimes()
 		&& cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self
 	{
 		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
-		accumulator->mTotalTimeCounter += cumulative_time_delta 
-			- (accumulator->mTotalTimeCounter 
-			- cur_timer->mBlockStartTotalTimeCounter);
+		cur_timer->mStartTime = cur_time;
+
+		accumulator->mTotalTimeCounter += cumulative_time_delta;
 		accumulator->mSelfTimeCounter += cumulative_time_delta - stack_record->mChildTime;
 		stack_record->mChildTime = 0;
 
-		cur_timer->mStartTime = cur_time;
-		cur_timer->mBlockStartTotalTimeCounter = accumulator->mTotalTimeCounter;
-
 		stack_record = &cur_timer->mParentTimerData;
 		accumulator  = &stack_record->mTimeBlock->getCurrentAccumulator();
 		cur_timer    = stack_record->mActiveTimer;
@@ -423,7 +420,6 @@ void TimeBlock::writeLog(std::ostream& os)
 TimeBlockAccumulator::TimeBlockAccumulator() 
 :	mTotalTimeCounter(0),
 	mSelfTimeCounter(0),
-	mStartTotalTimeCounter(0),
 	mCalls(0),
 	mLastCaller(NULL),
 	mActiveCount(0),
@@ -436,7 +432,7 @@ void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other, EBuffe
 	// we can't merge two unrelated time block samples, as that will screw with the nested timings
 	// due to the call hierarchy of each thread
 	llassert(append_type == SEQUENTIAL);
-	mTotalTimeCounter += other.mTotalTimeCounter - other.mStartTotalTimeCounter;
+	mTotalTimeCounter += other.mTotalTimeCounter;
 	mSelfTimeCounter += other.mSelfTimeCounter;
 	mCalls += other.mCalls;
 	mLastCaller = other.mLastCaller;
@@ -449,21 +445,15 @@ void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
 {
 	mCalls = 0;
 	mSelfTimeCounter = 0;
+	mTotalTimeCounter = 0;
 
 	if (other)
 	{
-		mStartTotalTimeCounter = other->mTotalTimeCounter;
-		mTotalTimeCounter = mStartTotalTimeCounter;
-
 		mLastCaller = other->mLastCaller;
 		mActiveCount = other->mActiveCount;
 		mMoveUpTree = other->mMoveUpTree;
 		mParent = other->mParent;
 	}
-	else
-	{
-		mStartTotalTimeCounter = mTotalTimeCounter;
-	}
 }
 
 F64Seconds BlockTimer::getElapsedTime()
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 53c61734e5..4eb12907dc 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -71,7 +71,6 @@ public:
 
 private:
 	U64						mStartTime;
-	U64						mBlockStartTotalTimeCounter;
 	BlockTimerStackRecord	mParentTimerData;
 };
 
@@ -287,7 +286,6 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 	if (!cur_timer_data) return;
 	TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
 	accumulator.mActiveCount++;
-	mBlockStartTotalTimeCounter = accumulator.mTotalTimeCounter;
 	// keep current parent as long as it is active when we are
 	accumulator.mMoveUpTree |= (accumulator.mParent->getCurrentAccumulator().mActiveCount == 0);
 
@@ -312,7 +310,7 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer()
 	TimeBlockAccumulator& accumulator = cur_timer_data->mTimeBlock->getCurrentAccumulator();
 
 	accumulator.mCalls++;
-	accumulator.mTotalTimeCounter += total_time - (accumulator.mTotalTimeCounter - mBlockStartTotalTimeCounter);
+	accumulator.mTotalTimeCounter += total_time;
 	accumulator.mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
 	accumulator.mActiveCount--;
 
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index d3c5e5235d..2330bfb8ea 100755
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -54,7 +54,7 @@ class LLMutex ;
 #define LL_DEFAULT_HEAP_ALIGN 8
 #endif
 
-inline void* ll_aligned_malloc( size_t size, int align )
+inline void* ll_aligned_malloc_fallback( size_t size, int align )
 {
 	void* mem = malloc( size + (align - 1) + sizeof(void*) );
 	char* aligned = ((char*)mem) + sizeof(void*);
@@ -64,7 +64,7 @@ inline void* ll_aligned_malloc( size_t size, int align )
 	return aligned;
 }
 
-inline void ll_aligned_free( void* ptr )
+inline void ll_aligned_free_fallback( void* ptr )
 {
 	free( ((void**)ptr)[-1] );
 }
@@ -130,7 +130,7 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi
 #if defined(LL_WINDOWS)
 	return _aligned_malloc(size, 32);
 #elif defined(LL_DARWIN)
-	return ll_aligned_malloc( size, 32 );
+	return ll_aligned_malloc_fallback( size, 32 );
 #else
 	void *rtn;
 	if (LL_LIKELY(0 == posix_memalign(&rtn, 32, size)))
@@ -151,6 +151,49 @@ inline void ll_aligned_free_32(void *p)
 #endif
 }
 
+// general purpose dispatch functions that are forced inline so they can compile down to a single call
+LL_FORCE_INLINE void* ll_aligned_malloc(size_t alignment, size_t size)
+{
+	if (LL_DEFAULT_HEAP_ALIGN % alignment == 0)
+	{
+		return malloc(size);
+	}
+	else if (alignment == 16)
+	{
+		return ll_aligned_malloc_16(size);
+	}
+	else if (alignment == 32)
+	{
+		return ll_aligned_malloc_32(size);
+	}
+	else
+	{
+		return ll_aligned_malloc_fallback(size, alignment);
+	}
+}
+
+LL_FORCE_INLINE void ll_aligned_free(size_t alignment, void* ptr)
+{
+	if (alignment == LL_DEFAULT_HEAP_ALIGN)
+	{
+		free(ptr);
+	}
+	else if (alignment == 16)
+	{
+		ll_aligned_free_16(ptr);
+	}
+	else if (alignment == 32)
+	{
+		return ll_aligned_free_32(ptr);
+	}
+	else
+	{
+		return ll_aligned_free_fallback(ptr);
+	}
+}
+
+
+
 #ifndef __DEBUG_PRIVATE_MEM__
 #define __DEBUG_PRIVATE_MEM__  0
 #endif
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 5c833ea287..355617a898 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -161,21 +161,6 @@ void sample(SampleStatHandle<T>& measurement, VALUE_T value)
 	measurement.getCurrentAccumulator().sample(storage_value(converted_value));
 }
 
-template<typename T, typename VALUE_T>
-void add(SampleStatHandle<T>& measurement, VALUE_T value)
-{
-	T converted_value(value);
-	SampleAccumulator& acc = measurement.getCurrentAccumulator();
-	if (acc.hasValue())
-	{
-		acc.sample(acc.getLastValue() + converted_value);
-	}
-	else
-	{
-		acc.sample(converted_value);
-	}
-}
-
 template <typename T = F64>
 class CountStatHandle
 :	public TraceType<CountAccumulator>
@@ -296,28 +281,28 @@ public:
 	}
 };
 
-inline void claim_mem(MemStatHandle& measurement, size_t size)
+inline void claim_footprint(MemStatHandle& measurement, S32 size)
 {
 	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 	accumulator.mAllocated.add(1);
 }
 
-inline void disclaim_mem(MemStatHandle& measurement, size_t size)
+inline void disclaim_footprint(MemStatHandle& measurement, S32 size)
 {
 	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 	accumulator.mDeallocated.add(1);
 }
 
-inline void claim_shadow_mem(MemStatHandle& measurement, size_t size)
+inline void claim_shadow(MemStatHandle& measurement, S32 size)
 {
 	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mShadowSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 	accumulator.mShadowAllocated.add(1);
 }
 
-inline void disclaim_shadow_mem(MemStatHandle& measurement, size_t size)
+inline void disclaim_shadow(MemStatHandle& measurement, S32 size)
 {
 	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mShadowSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
@@ -327,94 +312,122 @@ inline void disclaim_shadow_mem(MemStatHandle& measurement, size_t size)
 // measures effective memory footprint of specified type
 // specialize to cover different types
 
-template<typename T>
-struct MemFootprint
+template<typename T, typename IS_MEM_TRACKABLE = void>
+struct MeasureMem
 {
-	static size_t measure(const T& value)
+	static size_t measureFootprint(const T& value)
 	{
 		return sizeof(T);
 	}
 
-	static size_t measure()
+	static size_t measureFootprint()
 	{
 		return sizeof(T);
 	}
+
+	static size_t measureShadow(const T& value)
+	{
+		return 0;
+	}
+
+	static size_t measureShadow()
+	{
+		return 0;
+	}
 };
 
 template<typename T>
-struct MemFootprint<T*>
+struct MeasureMem<T, typename T::mem_trackable_tag_t>
 {
-	static size_t measure(const T* value)
+	static size_t measureFootprint(const T& value)
+	{
+		return sizeof(T) + value.getMemFootprint();
+	}
+
+	static size_t measureFootprint()
+	{
+		return sizeof(T);
+	}
+
+	static size_t measureShadow(const T& value)
+	{
+		return value.getMemShadow();
+	}
+
+	static size_t measureShadow()
+	{
+		return MeasureMem<T>::measureShadow();
+	}
+};
+
+
+template<typename T, typename IS_MEM_TRACKABLE>
+struct MeasureMem<T*, IS_MEM_TRACKABLE>
+{
+	static size_t measureFootprint(const T* value)
 	{
 		if (!value)
 		{
 			return 0;
 		}
-		return MemFootprint<T>::measure(*value);
+		return MeasureMem<T>::measureFootprint(*value);
 	}
 
-	static size_t measure()
+	static size_t measureFootprint()
 	{
-		return MemFootprint<T>::measure();
+		return MeasureMem<T>::measureFootprint();
 	}
-};
 
-template<typename T>
-struct MemFootprint<std::basic_string<T> >
-{
-	static size_t measure(const std::basic_string<T>& value)
+	static size_t measureShadow(const T* value)
 	{
-		return value.capacity() * sizeof(T);
+		return MeasureMem<T>::measureShadow(*value);
 	}
 
-	static size_t measure()
+	static size_t measureShadow()
 	{
-		return sizeof(std::basic_string<T>);
+		return MeasureMem<T>::measureShadow();
 	}
 };
 
-template<typename T>
-struct MemFootprint<std::vector<T> >
+template<typename T, typename IS_MEM_TRACKABLE>
+struct MeasureMem<std::basic_string<T>, IS_MEM_TRACKABLE>
 {
-	static size_t measure(const std::vector<T>& value)
+	static size_t measureFootprint(const std::basic_string<T>& value)
 	{
-		return value.capacity() * MemFootprint<T>::measure();
+		return value.capacity() * sizeof(T);
 	}
 
-	static size_t measure()
+	static size_t measureFootprint()
 	{
-		return sizeof(std::vector<T>);
+		return sizeof(std::basic_string<T>);
 	}
-};
 
-template<typename T>
-struct MemFootprint<std::list<T> >
-{
-	static size_t measure(const std::list<T>& value)
+	static size_t measureShadow(const std::basic_string<T>& value)
 	{
-		return value.size() * (MemFootprint<T>::measure() + sizeof(void*) * 2);
+		return 0;
 	}
 
-	static size_t measure()
+	static size_t measureShadow()
 	{
-		return sizeof(std::list<T>);
+		return 0;
 	}
 };
 
 template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN>
 class MemTrackable
 {
-	template<typename TRACKED, typename TRACKED_IS_TRACKER>
-	struct TrackMemImpl;
-
-	typedef MemTrackable<DERIVED, ALIGNMENT> mem_trackable_t;
-	static	MemStatHandle	sMemStat;
-
 public:
 	typedef void mem_trackable_tag_t;
 
+	enum EMemType
+	{
+		MEM_FOOTPRINT, 
+		MEM_SHADOW
+	};
+
 	MemTrackable()
-	:	mMemFootprint(0)
+	:	mMemFootprint(0),
+		mMemShadow(0)
 	{
 		static bool name_initialized = false;
 		if (!name_initialized)
@@ -426,7 +439,8 @@ public:
 
 	virtual ~MemTrackable()
 	{
-		memDisclaim(mMemFootprint);
+		disclaimMem(mMemFootprint, MEM_FOOTPRINT);
+		disclaimMem(mMemShadow, MEM_SHADOW);
 	}
 
 	static MemStatHandle& getMemStatHandle()
@@ -434,186 +448,129 @@ public:
 		return sMemStat;
 	}
 
+	S32 getMemFootprint() const	{ return mMemFootprint; }
+	S32 getMemShadow() const	{ return mMemShadow; }
+
 	void* operator new(size_t size) 
 	{
-		claim_mem(sMemStat, size);
-
-		if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
-		{
-			return ::operator new(size);
-		}
-		else if (ALIGNMENT == 16)
-		{
-			return ll_aligned_malloc_16(size);
-		}
-		else if (ALIGNMENT == 32)
-		{
-			return ll_aligned_malloc_32(size);
-		}
-		else
-		{
-			return ll_aligned_malloc(size, ALIGNMENT);
-		}
+		claim_footprint(sMemStat, size);
+		return ll_aligned_malloc(ALIGNMENT, size);
 	}
 
 	void operator delete(void* ptr, size_t size)
 	{
-		disclaim_mem(sMemStat, size);
-
-		if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
-		{
-			::operator delete(ptr);
-		}
-		else if (ALIGNMENT == 16)
-		{
-			ll_aligned_free_16(ptr);
-		}
-		else if (ALIGNMENT == 32)
-		{
-			return ll_aligned_free_32(ptr);
-		}
-		else
-		{
-			return ll_aligned_free(ptr);
-		}
+		disclaim_footprint(sMemStat, size);
+		ll_aligned_free(ALIGNMENT, ptr);
 	}
 
 	void *operator new [](size_t size)
 	{
-		claim_mem(sMemStat, size);
-
-		if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
-		{
-			return ::operator new[](size);
-		}
-		else if (ALIGNMENT == 16)
-		{
-			return ll_aligned_malloc_16(size);
-		}
-		else if (ALIGNMENT == 32)
-		{
-			return ll_aligned_malloc_32(size);
-		}
-		else
-		{
-			return ll_aligned_malloc(size, ALIGNMENT);
-		}
+		claim_footprint(sMemStat, size);
+		return ll_aligned_malloc(ALIGNMENT, size);
 	}
 
 	void operator delete[](void* ptr, size_t size)
 	{
-		disclaim_mem(sMemStat, size);
-
-		if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
-		{
-			::operator delete[](ptr);
-		}
-		else if (ALIGNMENT == 16)
-		{
-			ll_aligned_free_16(ptr);
-		}
-		else if (ALIGNMENT == 32)
-		{
-			return ll_aligned_free_32(ptr);
-		}
-		else
-		{
-			return ll_aligned_free(ptr);
-		}
+		disclaim_footprint(sMemStat, size);
+		ll_aligned_free(ALIGNMENT, ptr);
 	}
 
 	// claim memory associated with other objects/data as our own, adding to our calculated footprint
 	template<typename CLAIM_T>
-	CLAIM_T& memClaim(CLAIM_T& value)
+	CLAIM_T& claimMem(CLAIM_T& value, EMemType mem_type = MEM_FOOTPRINT)
 	{
-		TrackMemImpl<CLAIM_T>::claim(*this, value);
+		trackAlloc(MeasureMem<CLAIM_T>::measureFootprint(value), mem_type);
+		trackAlloc(MeasureMem<CLAIM_T>::measureShadow(value), MEM_SHADOW);
 		return value;
 	}
 
 	template<typename CLAIM_T>
-	const CLAIM_T& memClaim(const CLAIM_T& value)
+	const CLAIM_T& claimMem(const CLAIM_T& value, EMemType mem_type = MEM_FOOTPRINT)
 	{
-		TrackMemImpl<CLAIM_T>::claim(*this, value);
+		trackAlloc(MeasureMem<CLAIM_T>::measureFootprint(value), mem_type);
+		trackAlloc(MeasureMem<CLAIM_T>::measureShadow(value), MEM_SHADOW);
 		return value;
 	}
 
-	size_t& memClaim(size_t& size)
+	size_t& claimMem(size_t& size, EMemType mem_type = MEM_FOOTPRINT)
 	{
-		claim_mem(sMemStat, size);
-		mMemFootprint += size;
+		trackAlloc(size, mem_type);
 		return size;
 	}
 
-	int& memClaim(int& size)
+	S32& claimMem(S32& size, EMemType mem_type = MEM_FOOTPRINT)
 	{
-		claim_mem(sMemStat, size);
-		mMemFootprint += size;
+		trackAlloc(size, mem_type);
 		return size;
 	}
 
 	// remove memory we had claimed from our calculated footprint
 	template<typename CLAIM_T>
-	CLAIM_T& memDisclaim(CLAIM_T& value)
+	CLAIM_T& disclaimMem(CLAIM_T& value, EMemType mem_type = MEM_FOOTPRINT)
 	{
-		TrackMemImpl<CLAIM_T>::disclaim(*this, value);
+		trackDealloc(MeasureMem<CLAIM_T>::measureFootprint(value), mem_type);
+		trackDealloc(MeasureMem<CLAIM_T>::measureShadow(value), MEM_SHADOW);
 		return value;
 	}
 
 	template<typename CLAIM_T>
-	const CLAIM_T& memDisclaim(const CLAIM_T& value)
+	const CLAIM_T& disclaimMem(const CLAIM_T& value, EMemType mem_type = MEM_FOOTPRINT)
 	{
-		TrackMemImpl<CLAIM_T>::disclaim(*this, value);
+		trackDealloc(MeasureMem<CLAIM_T>::measureFootprint(value), mem_type);
+		trackDealloc(MeasureMem<CLAIM_T>::measureShadow(value), MEM_SHADOW);
 		return value;
 	}
 
-	size_t& memDisclaim(size_t& size)
+	size_t& disclaimMem(size_t& size, EMemType mem_type = MEM_FOOTPRINT)
 	{
-		disclaim_mem(sMemStat, size);
-		mMemFootprint -= size;
+		trackDealloc(size, mem_type);
 		return size;
 	}
 
-	int& memDisclaim(int& size)
+	S32& disclaimMem(S32& size, EMemType mem_type = MEM_FOOTPRINT)
 	{
-		disclaim_mem(sMemStat, size);
-		mMemFootprint -= size;
+		trackDealloc(size, mem_type);
 		return size;
 	}
 
 private:
-	size_t mMemFootprint;
 
-	template<typename TRACKED, typename TRACKED_IS_TRACKER = void>
-	struct TrackMemImpl
+	void trackAlloc(S32 size, EMemType mem_type)
 	{
-		static void claim(mem_trackable_t& tracker, const TRACKED& tracked)
+		if (mem_type == MEM_FOOTPRINT)
 		{
-			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
-			claim_mem(sMemStat, footprint);
-			tracker.mMemFootprint += footprint;
+			claim_footprint(sMemStat, size);
+			mMemFootprint += size;
 		}
-
-		static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked)
+		else
 		{
-			size_t footprint = MemFootprint<TRACKED>::measure(tracked);
-			disclaim_mem(sMemStat, footprint);
-			tracker.mMemFootprint -= footprint;
+			claim_shadow(sMemStat, size);
+			mMemShadow += size;
 		}
-	};
+	}
 
-	template<typename TRACKED>
-	struct TrackMemImpl<TRACKED, typename TRACKED::mem_trackable_tag_t>
+	void trackDealloc(S32 size, EMemType mem_type)
 	{
-		static void claim(mem_trackable_t& tracker, TRACKED& tracked)
+		if (mem_type == MEM_FOOTPRINT)
 		{
-			claim_shadow_mem( sMemStat, MemFootprint<TRACKED>::measure(tracked));
+			disclaim_footprint(sMemStat, size);
+			mMemFootprint -= size;
 		}
-
-		static void disclaim(mem_trackable_t& tracker, TRACKED& tracked)
+		else
 		{
-			disclaim_shadow_mem(sMemStat, MemFootprint<TRACKED>::measure(tracked));
+			disclaim_shadow(sMemStat, size);
+			mMemShadow -= size;
 		}
-	};
+	}
+
+private:
+	// use signed values so that we can temporarily go negative
+	// and reconcile in destructor
+	// NB: this assumes that no single class is responsible for > 2GB of allocations
+	S32 mMemFootprint,
+		mMemShadow;
+	
+	static	MemStatHandle	sMemStat;
 };
 
 template<typename DERIVED, size_t ALIGNMENT>
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 37a35f4e23..4fe84455a6 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -35,6 +35,7 @@
 #include "lltimer.h"
 #include "llrefcount.h"
 #include "llthreadlocalstorage.h"
+#include "llmemory.h"
 #include <limits>
 
 namespace LLTrace
@@ -51,7 +52,7 @@ namespace LLTrace
 	class AccumulatorBuffer : public LLRefCount
 	{
 		typedef AccumulatorBuffer<ACCUMULATOR> self_t;
-		static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64;
+		static const U32 ACCUMULATOR_BUFFER_SIZE_INCREMENT = 16;
 	private:
 		struct StaticAllocationMarker { };
 
@@ -149,7 +150,9 @@ namespace LLTrace
 			size_t next_slot = sNextStorageSlot++;
 			if (next_slot >= mStorageSize)
 			{
-				resize(mStorageSize + (mStorageSize >> 2));
+				// don't perform doubling, as this should only happen during startup
+				// want to keep a tight bounds as we will have a lot of these buffers
+				resize(mStorageSize + ACCUMULATOR_BUFFER_SIZE_INCREMENT);
 			}
 			llassert(mStorage && next_slot < mStorageSize);
 			return next_slot;
@@ -199,7 +202,7 @@ namespace LLTrace
 				// so as not to trigger an access violation
 				sDefaultBuffer = new AccumulatorBuffer(StaticAllocationMarker());
 				sInitialized = true;
-				sDefaultBuffer->resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
+				sDefaultBuffer->resize(ACCUMULATOR_BUFFER_SIZE_INCREMENT);
 			}
 			return sDefaultBuffer;
 		}
@@ -427,6 +430,17 @@ namespace LLTrace
 			typedef F64Seconds value_t;
 		};
 
+		// arrays are allocated with 32 byte alignment
+		void *operator new [](size_t size)
+		{
+			return ll_aligned_malloc(32, size);
+		}
+
+		void operator delete[](void* ptr, size_t size)
+		{
+			ll_aligned_free(32, ptr);
+		}
+
 		TimeBlockAccumulator();
 		void addSamples(const self_t& other, EBufferAppendType append_type);
 		void reset(const self_t* other);
@@ -435,8 +449,7 @@ namespace LLTrace
 		//
 		// members
 		//
-		U64					mStartTotalTimeCounter,
-							mTotalTimeCounter,
+		U64					mTotalTimeCounter,
 							mSelfTimeCounter;
 		U32					mCalls;
 		class TimeBlock*	mParent;		// last acknowledged parent of this time block
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index c606007d89..c16d02216d 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -131,7 +131,7 @@ void Recording::appendRecording( Recording& other )
 F64Seconds Recording::getSum(const TraceType<TimeBlockAccumulator>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
-	return F64Seconds((F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
+	return F64Seconds((F64)(accumulator.mTotalTimeCounter) 
 				/ (F64)LLTrace::TimeBlock::countsPerSecond());
 }
 
@@ -151,7 +151,7 @@ F64Seconds Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
-	return F64Seconds((F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) 
+	return F64Seconds((F64)(accumulator.mTotalTimeCounter) 
 				/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()));
 }
 
@@ -935,7 +935,7 @@ void ExtendablePeriodicRecording::handleSplitTo(ExtendablePeriodicRecording& oth
 
 PeriodicRecording& get_frame_recording()
 {
-	static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(1000, PeriodicRecording::STARTED));
+	static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(200, PeriodicRecording::STARTED));
 	return *sRecording;
 }
 
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index d3d9eb5ca7..e131af5f16 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -127,10 +127,7 @@ void ThreadRecorder::activate( AccumulatorBufferGroup* recording, bool from_hand
 	{
 		AccumulatorBufferGroup& prev_active_recording = mActiveRecordings.back()->mPartialRecording;
 		prev_active_recording.sync();
-		if (!from_handoff)
-		{
-			TimeBlock::updateTimes();
-		}
+		TimeBlock::updateTimes();
 		prev_active_recording.handOffTo(active_recording->mPartialRecording);
 	}
 	mActiveRecordings.push_back(active_recording);
-- 
cgit v1.2.3


From e0a443f5a6b76fd1ab5ffaa8e7a1941d47c80f4f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 27 Sep 2013 11:18:39 -0700
Subject: BUILDFIX: fix for mac builds also, fixed alignment of tick labels on
 stat bars

---
 indra/llcommon/llmemory.h            |   2 +-
 indra/llcommon/lltraceaccumulators.h |  18 +++---
 indra/llcommon/lltracerecording.cpp  | 112 ++++++++++++++++----------------
 indra/llcommon/lltracerecording.h    | 120 +++++++++++++++++------------------
 4 files changed, 126 insertions(+), 126 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 2330bfb8ea..8daea255f9 100755
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -145,7 +145,7 @@ inline void ll_aligned_free_32(void *p)
 #if defined(LL_WINDOWS)
 	_aligned_free(p);
 #elif defined(LL_DARWIN)
-	ll_aligned_free( p );
+	ll_aligned_free_fallback( p );
 #else
 	free(p); // posix_memalign() is compatible with heap deallocator
 #endif
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 4fe84455a6..2dcfdf48ad 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -52,7 +52,7 @@ namespace LLTrace
 	class AccumulatorBuffer : public LLRefCount
 	{
 		typedef AccumulatorBuffer<ACCUMULATOR> self_t;
-		static const U32 ACCUMULATOR_BUFFER_SIZE_INCREMENT = 16;
+		static const S32 ACCUMULATOR_BUFFER_SIZE_INCREMENT = 16;
 	private:
 		struct StaticAllocationMarker { };
 
@@ -267,7 +267,7 @@ namespace LLTrace
 		F64	getMean() const              { return mMean; }
 		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mNumSamples); }
 		F64 getSumOfSquares() const		 { return mSumOfSquares; }
-		U32 getSampleCount() const       { return mNumSamples; }
+		S32 getSampleCount() const       { return mNumSamples; }
 		bool hasValue() const			 { return mNumSamples > 0; }
 
 	private:
@@ -279,7 +279,7 @@ namespace LLTrace
 		F64	mMean,
 			mSumOfSquares;
 
-		U32	mNumSamples;
+		S32	mNumSamples;
 	};
 
 
@@ -352,7 +352,7 @@ namespace LLTrace
 		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); }
 		F64 getSumOfSquares() const		 { return mSumOfSquares; }
 		F64SecondsImplicit getSamplingTime() { return mTotalSamplingTime; }
-		U32 getSampleCount() const       { return mNumSamples; }
+		S32 getSampleCount() const       { return mNumSamples; }
 		bool hasValue() const            { return mHasValue; }
 
 	private:
@@ -370,7 +370,7 @@ namespace LLTrace
 				mLastSampleTimeStamp,
 				mTotalSamplingTime;
 
-		U32		mNumSamples;
+		S32		mNumSamples;
 	};
 
 	class CountAccumulator
@@ -405,12 +405,12 @@ namespace LLTrace
 
 		F64	getSum() const { return mSum; }
 
-		U32 getSampleCount() const { return mNumSamples; }
+		S32 getSampleCount() const { return mNumSamples; }
 
 	private:
 		F64	mSum;
 
-		U32	mNumSamples;
+		S32	mNumSamples;
 	};
 
 	class TimeBlockAccumulator
@@ -422,7 +422,7 @@ namespace LLTrace
 		// fake classes that allows us to view different facets of underlying statistic
 		struct CallCountFacet 
 		{
-			typedef U32 value_t;
+			typedef S32 value_t;
 		};
 
 		struct SelfTimeFacet
@@ -451,7 +451,7 @@ namespace LLTrace
 		//
 		U64					mTotalTimeCounter,
 							mSelfTimeCounter;
-		U32					mCalls;
+		S32					mCalls;
 		class TimeBlock*	mParent;		// last acknowledged parent of this time block
 		class TimeBlock*	mLastCaller;	// used to bootstrap tree construction
 		U16					mActiveCount;	// number of timers with this ID active on stack
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index c16d02216d..ddf62845a0 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -142,7 +142,7 @@ F64Seconds Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet
 }
 
 
-U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat)
+S32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat)
 {
 	return mBuffers->mStackTimers[stat.getIndex()].mCalls;
 }
@@ -238,7 +238,7 @@ F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::Allocation
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocated.getSum() / mElapsedSeconds.value());
 }
 
-U32 Recording::getSampleCount(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
+S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
 {
 	return mBuffers->mMemStats[stat.getIndex()].mAllocated.getSampleCount();
 }
@@ -253,7 +253,7 @@ F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::Deallocati
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocated.getSum() / mElapsedSeconds.value());
 }
 
-U32 Recording::getSampleCount(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
+S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
 {
 	return mBuffers->mMemStats[stat.getIndex()].mDeallocated.getSampleCount();
 }
@@ -268,7 +268,7 @@ F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::ShadowAllo
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowAllocated.getSum() / mElapsedSeconds.value());
 }
 
-U32 Recording::getSampleCount(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat)
+S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat)
 {
 	return mBuffers->mMemStats[stat.getIndex()].mShadowAllocated.getSampleCount();
 }
@@ -283,7 +283,7 @@ F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::ShadowDeal
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowDeallocated.getSum() / mElapsedSeconds.value());
 }
 
-U32 Recording::getSampleCount(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat)
+S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat)
 {
 	return mBuffers->mMemStats[stat.getIndex()].mShadowDeallocated.getSampleCount();
 }
@@ -304,7 +304,7 @@ F64 Recording::getPerSec( const TraceType<CountAccumulator>& stat )
 	return  sum / mElapsedSeconds.value();
 }
 
-U32 Recording::getSampleCount( const TraceType<CountAccumulator>& stat )
+S32 Recording::getSampleCount( const TraceType<CountAccumulator>& stat )
 {
 	return mBuffers->mCounts[stat.getIndex()].getSampleCount();
 }
@@ -339,7 +339,7 @@ F64 Recording::getLastValue( const TraceType<SampleAccumulator>& stat )
 	return mBuffers->mSamples[stat.getIndex()].getLastValue();
 }
 
-U32 Recording::getSampleCount( const TraceType<SampleAccumulator>& stat )
+S32 Recording::getSampleCount( const TraceType<SampleAccumulator>& stat )
 {
 	return mBuffers->mSamples[stat.getIndex()].getSampleCount();
 }
@@ -374,7 +374,7 @@ F64 Recording::getLastValue( const TraceType<EventAccumulator>& stat )
 	return mBuffers->mEvents[stat.getIndex()].getLastValue();
 }
 
-U32 Recording::getSampleCount( const TraceType<EventAccumulator>& stat )
+S32 Recording::getSampleCount( const TraceType<EventAccumulator>& stat )
 {
 	return mBuffers->mEvents[stat.getIndex()].getSampleCount();
 }
@@ -383,7 +383,7 @@ U32 Recording::getSampleCount( const TraceType<EventAccumulator>& stat )
 // PeriodicRecording
 ///////////////////////////////////////////////////////////////////////
 
-PeriodicRecording::PeriodicRecording( U32 num_periods, EPlayState state) 
+PeriodicRecording::PeriodicRecording( S32 num_periods, EPlayState state) 
 :	mAutoResize(num_periods == 0),
 	mCurPeriod(0),
 	mNumPeriods(0),
@@ -403,7 +403,7 @@ void PeriodicRecording::nextPeriod()
 	mCurPeriod = (mCurPeriod + 1) % mRecordingPeriods.size();
 	old_recording.splitTo(getCurRecording());
 
-	mNumPeriods = llmin(mRecordingPeriods.size(), mNumPeriods + 1);
+	mNumPeriods = llmin((S32)mRecordingPeriods.size(), mNumPeriods + 1);
 }
 
 void PeriodicRecording::appendRecording(Recording& recording)
@@ -420,21 +420,21 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 	getCurRecording().update();
 	other.getCurRecording().update();
 	
-	const U32 other_recording_slots = other.mRecordingPeriods.size();
-	const U32 other_num_recordings = other.getNumRecordedPeriods();
-	const U32 other_current_recording_index = other.mCurPeriod;
-	const U32 other_oldest_recording_index = (other_current_recording_index + other_recording_slots - other_num_recordings + 1) % other_recording_slots;
+	const S32 other_recording_slots = other.mRecordingPeriods.size();
+	const S32 other_num_recordings = other.getNumRecordedPeriods();
+	const S32 other_current_recording_index = other.mCurPeriod;
+	const S32 other_oldest_recording_index = (other_current_recording_index + other_recording_slots - other_num_recordings + 1) % other_recording_slots;
 
 	// append first recording into our current slot
 	getCurRecording().appendRecording(other.mRecordingPeriods[other_oldest_recording_index]);
 
 	// from now on, add new recordings for everything after the first
-	U32 other_index = (other_oldest_recording_index + 1) % other_recording_slots;
+	S32 other_index = (other_oldest_recording_index + 1) % other_recording_slots;
 
 	if (mAutoResize)
 	{
 		// push back recordings for everything in the middle
-		U32 other_index = (other_oldest_recording_index + 1) % other_recording_slots;
+		S32 other_index = (other_oldest_recording_index + 1) % other_recording_slots;
 		while (other_index != other_current_recording_index)
 		{
 			mRecordingPeriods.push_back(other.mRecordingPeriods[other_index]);
@@ -452,13 +452,13 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 	}
 	else
 	{
-		size_t num_to_copy = llmin(	mRecordingPeriods.size(), (size_t)other_num_recordings);
+		S32 num_to_copy = llmin((S32)mRecordingPeriods.size(), (S32)other_num_recordings);
 
 		std::vector<Recording>::iterator src_it = other.mRecordingPeriods.begin() + other_index ;
 		std::vector<Recording>::iterator dest_it = mRecordingPeriods.begin() + mCurPeriod;
 
 		// already consumed the first recording from other, so start counting at 1
-		for(size_t i = 1; i < num_to_copy; i++)
+		for(S32 i = 1; i < num_to_copy; i++)
 		{
 			*dest_it = *src_it;
 
@@ -477,7 +477,7 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 		llassert(num_to_copy >= 1);
 		// advance to last recording period copied, and make that our current period
 		mCurPeriod = (mCurPeriod + num_to_copy - 1) % mRecordingPeriods.size();
-		mNumPeriods = llmin(mRecordingPeriods.size(), mNumPeriods + num_to_copy - 1);
+		mNumPeriods = llmin((S32)mRecordingPeriods.size(), mNumPeriods + num_to_copy - 1);
 	}
 
 	// end with fresh period, otherwise next appendPeriodicRecording() will merge the first
@@ -489,10 +489,10 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 F64Seconds PeriodicRecording::getDuration() const
 {
 	F64Seconds duration;
-	size_t num_periods = mRecordingPeriods.size();
-	for (size_t i = 1; i <= num_periods; i++)
+	S32 num_periods = mRecordingPeriods.size();
+	for (S32 i = 1; i <= num_periods; i++)
 	{
-		size_t index = (mCurPeriod + num_periods - i) % num_periods;
+		S32 index = (mCurPeriod + num_periods - i) % num_periods;
 		duration += mRecordingPeriods[index].getDuration();
 	}
 	return duration;
@@ -527,17 +527,17 @@ const Recording& PeriodicRecording::getCurRecording() const
 	return mRecordingPeriods[mCurPeriod];
 }
 
-Recording& PeriodicRecording::getPrevRecording( U32 offset )
+Recording& PeriodicRecording::getPrevRecording( S32 offset )
 {
-	U32 num_periods = mRecordingPeriods.size();
-	offset = llclamp(offset, 0u, num_periods - 1);
+	S32 num_periods = mRecordingPeriods.size();
+	offset = llclamp(offset, 0, num_periods - 1);
 	return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
 }
 
-const Recording& PeriodicRecording::getPrevRecording( U32 offset ) const
+const Recording& PeriodicRecording::getPrevRecording( S32 offset ) const
 {
-	U32 num_periods = mRecordingPeriods.size();
-	offset = llclamp(offset, 0u, num_periods - 1);
+	S32 num_periods = mRecordingPeriods.size();
+	offset = llclamp(offset, 0, num_periods - 1);
 	return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
 }
 
@@ -579,9 +579,9 @@ void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
 	getCurRecording().splitTo(other.getCurRecording());
 }
 
-F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	size_t total_periods = mRecordingPeriods.size();
+	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 	bool has_value = false;
@@ -601,9 +601,9 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, si
 			: NaN;
 }
 
-F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	size_t total_periods = mRecordingPeriods.size();
+	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 	bool has_value = false;
@@ -624,9 +624,9 @@ F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, si
 }
 
 // calculates means using aggregates per period
-F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	size_t total_periods = mRecordingPeriods.size();
+	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 	F64 mean = 0;
@@ -648,9 +648,9 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, s
 }
 
 
-F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	size_t total_periods = mRecordingPeriods.size();
+	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 	F64 period_mean = getPeriodMean(stat, num_periods);
@@ -673,9 +673,9 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<EventAccumula
 			: NaN;
 }
 
-F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	size_t total_periods = mRecordingPeriods.size();
+	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 	bool has_value = false;
@@ -695,9 +695,9 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, s
 			: NaN;
 }
 
-F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/)
+F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/)
 {
-	size_t total_periods = mRecordingPeriods.size();
+	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 	bool has_value = false;
@@ -718,9 +718,9 @@ F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, si
 }
 
 
-F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	size_t total_periods = mRecordingPeriods.size();
+	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 	S32 valid_period_count = 0;
@@ -741,9 +741,9 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat,
 			: NaN;
 }
 
-F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	size_t total_periods = mRecordingPeriods.size();
+	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 	F64 period_mean = getPeriodMean(stat, num_periods);
@@ -767,9 +767,9 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<SampleAccumul
 }
 
 
-F64Kilobytes PeriodicRecording::getPeriodMin( const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+F64Kilobytes PeriodicRecording::getPeriodMin( const TraceType<MemStatAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	size_t total_periods = mRecordingPeriods.size();
+	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 	F64Kilobytes min_val(std::numeric_limits<F64>::max());
@@ -782,14 +782,14 @@ F64Kilobytes PeriodicRecording::getPeriodMin( const TraceType<MemStatAccumulator
 	return min_val;
 }
 
-F64Kilobytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, size_t num_periods)
+F64Kilobytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, S32 num_periods)
 {
 	return getPeriodMin(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
 }
 
-F64Kilobytes PeriodicRecording::getPeriodMax(const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/)
+F64Kilobytes PeriodicRecording::getPeriodMax(const TraceType<MemStatAccumulator>& stat, S32 num_periods /*= S32_MAX*/)
 {
-	size_t total_periods = mRecordingPeriods.size();
+	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 	F64Kilobytes max_val(0.0);
@@ -802,14 +802,14 @@ F64Kilobytes PeriodicRecording::getPeriodMax(const TraceType<MemStatAccumulator>
 	return max_val;
 }
 
-F64Kilobytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, size_t num_periods)
+F64Kilobytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, S32 num_periods)
 {
 	return getPeriodMax(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
 }
 
-F64Kilobytes PeriodicRecording::getPeriodMean( const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+F64Kilobytes PeriodicRecording::getPeriodMean( const TraceType<MemStatAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	size_t total_periods = mRecordingPeriods.size();
+	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 	F64Kilobytes mean(0);
@@ -823,14 +823,14 @@ F64Kilobytes PeriodicRecording::getPeriodMean( const TraceType<MemStatAccumulato
 	return mean / F64(num_periods);
 }
 
-F64Kilobytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, size_t num_periods)
+F64Kilobytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, S32 num_periods)
 {
 	return getPeriodMean(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
 }
 
-F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const TraceType<MemStatAccumulator>& stat, size_t num_periods /*= U32_MAX*/ )
+F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const TraceType<MemStatAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	size_t total_periods = mRecordingPeriods.size();
+	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 	F64Kilobytes period_mean = getPeriodMean(stat, num_periods);
@@ -853,7 +853,7 @@ F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const TraceType<MemS
 			: NaN);
 }
 
-F64Kilobytes PeriodicRecording::getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods)
+F64Kilobytes PeriodicRecording::getPeriodStandardDeviation(const MemStatHandle& stat, S32 num_periods)
 {
 	return getPeriodStandardDeviation(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
 }
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 3f7737b20b..13dffdc701 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -144,7 +144,7 @@ namespace LLTrace
 	struct RelatedTypes<bool>
 	{
 		typedef F64 fractional_t;
-		typedef U32 sum_t;
+		typedef S32 sum_t;
 	};
 
 	class Recording 
@@ -170,7 +170,7 @@ namespace LLTrace
 		// Timer accessors
 		F64Seconds getSum(const TraceType<TimeBlockAccumulator>& stat);
 		F64Seconds getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat);
-		U32 getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat);
+		S32 getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat);
 
 		F64Seconds getPerSec(const TraceType<TimeBlockAccumulator>& stat);
 		F64Seconds getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat);
@@ -194,19 +194,19 @@ namespace LLTrace
 
 		F64Kilobytes getSum(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
 		F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
-		U32 getSampleCount(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
+		S32 getSampleCount(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
 
 		F64Kilobytes getSum(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
 		F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
-		U32 getSampleCount(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
+		S32 getSampleCount(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
 
 		F64Kilobytes getSum(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat);
 		F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat);
-		U32 getSampleCount(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat);
+		S32 getSampleCount(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat);
 
 		F64Kilobytes getSum(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat);
 		F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat);
-		U32 getSampleCount(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat);
+		S32 getSampleCount(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat);
 
 		// CountStatHandle accessors
 		F64 getSum(const TraceType<CountAccumulator>& stat);
@@ -223,7 +223,7 @@ namespace LLTrace
 			return (typename RelatedTypes<T>::fractional_t)getPerSec(static_cast<const TraceType<CountAccumulator>&> (stat));
 		}
 
-		U32 getSampleCount(const TraceType<CountAccumulator>& stat);
+		S32 getSampleCount(const TraceType<CountAccumulator>& stat);
 
 
 		// SampleStatHandle accessors
@@ -264,7 +264,7 @@ namespace LLTrace
 			return (T)getLastValue(static_cast<const TraceType<SampleAccumulator>&> (stat));
 		}
 
-		U32 getSampleCount(const TraceType<SampleAccumulator>& stat);
+		S32 getSampleCount(const TraceType<SampleAccumulator>& stat);
 
 		// EventStatHandle accessors
 		bool hasValue(const TraceType<EventAccumulator>& stat);
@@ -311,7 +311,7 @@ namespace LLTrace
 			return (T)getLastValue(static_cast<const TraceType<EventAccumulator>&> (stat));
 		}
 
-		U32 getSampleCount(const TraceType<EventAccumulator>& stat);
+		S32 getSampleCount(const TraceType<EventAccumulator>& stat);
 
 		F64Seconds getDuration() const { return mElapsedSeconds; }
 
@@ -338,10 +338,10 @@ namespace LLTrace
 	:	public LLStopWatchControlsMixin<PeriodicRecording>
 	{
 	public:
-		PeriodicRecording(U32 num_periods, EPlayState state = STOPPED);
+		PeriodicRecording(S32 num_periods, EPlayState state = STOPPED);
 
 		void nextPeriod();
-		size_t getNumRecordedPeriods() { return mNumPeriods; }
+		S32 getNumRecordedPeriods() { return mNumPeriods; }
 
 		F64Seconds getDuration() const;
 
@@ -351,17 +351,17 @@ namespace LLTrace
 		const Recording& getLastRecording() const;
 		Recording& getCurRecording();
 		const Recording& getCurRecording() const;
-		Recording& getPrevRecording(U32 offset);
-		const Recording& getPrevRecording(U32 offset) const;
+		Recording& getPrevRecording(S32 offset);
+		const Recording& getPrevRecording(S32 offset) const;
 		Recording snapshotCurRecording() const;
 
 		template <typename T>
-		size_t getSampleCount(const TraceType<T>& stat, size_t num_periods = U32_MAX)
+		S32 getSampleCount(const TraceType<T>& stat, S32 num_periods = S32_MAX)
         {
-			size_t total_periods = mNumPeriods;
+			S32 total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-            size_t num_samples = 0;
+            S32 num_samples = 0;
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				Recording& recording = getPrevRecording(i);
@@ -376,9 +376,9 @@ namespace LLTrace
 
 		// catch all for stats that have a defined sum
 		template <typename T>
-		typename T::value_t getPeriodMin(const TraceType<T>& stat, size_t num_periods = U32_MAX)
+		typename T::value_t getPeriodMin(const TraceType<T>& stat, S32 num_periods = S32_MAX)
 		{
-			size_t total_periods = mNumPeriods;
+			S32 total_periods = mNumPeriods;
 			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();
@@ -391,32 +391,32 @@ namespace LLTrace
 		}
 
 		template<typename T>
-		T getPeriodMin(const CountStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		T getPeriodMin(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
 			return T(getPeriodMin(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
 		}
 
-		F64 getPeriodMin(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64 getPeriodMin(const TraceType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
 		template<typename T>
-		T getPeriodMin(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		T getPeriodMin(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
 			return T(getPeriodMin(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods));
 		}
 
-		F64 getPeriodMin(const TraceType<EventAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64 getPeriodMin(const TraceType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
 		template<typename T>
-		T getPeriodMin(const EventStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		T getPeriodMin(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
 			return T(getPeriodMin(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
-		F64Kilobytes getPeriodMin(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
-		F64Kilobytes getPeriodMin(const MemStatHandle& stat, size_t num_periods = U32_MAX);
+		F64Kilobytes getPeriodMin(const TraceType<MemStatAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64Kilobytes getPeriodMin(const MemStatHandle& stat, S32 num_periods = S32_MAX);
 
 		template <typename T>
-		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const TraceType<T>& stat, S32 num_periods = S32_MAX)
 		{
-			size_t total_periods = mNumPeriods;
+			S32 total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 			typename RelatedTypes<typename T::value_t>::fractional_t min_val = std::numeric_limits<F64>::max();
@@ -429,7 +429,7 @@ namespace LLTrace
 		}
 
 		template<typename T>
-		typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
 			return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
 		}
@@ -440,9 +440,9 @@ namespace LLTrace
 
 		// catch all for stats that have a defined sum
 		template <typename T>
-		typename T::value_t getPeriodMax(const TraceType<T>& stat, size_t num_periods = U32_MAX)
+		typename T::value_t getPeriodMax(const TraceType<T>& stat, S32 num_periods = S32_MAX)
 		{
-			size_t total_periods = mNumPeriods;
+			S32 total_periods = mNumPeriods;
 			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();
@@ -455,32 +455,32 @@ namespace LLTrace
 		}
 
 		template<typename T>
-		T getPeriodMax(const CountStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		T getPeriodMax(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
 			return T(getPeriodMax(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
 		}
 
-		F64 getPeriodMax(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64 getPeriodMax(const TraceType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
 		template<typename T>
-		T getPeriodMax(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		T getPeriodMax(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
 			return T(getPeriodMax(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods));
 		}
 
-		F64 getPeriodMax(const TraceType<EventAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64 getPeriodMax(const TraceType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
 		template<typename T>
-		T getPeriodMax(const EventStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		T getPeriodMax(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
 			return T(getPeriodMax(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
-		F64Kilobytes getPeriodMax(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
-		F64Kilobytes getPeriodMax(const MemStatHandle& stat, size_t num_periods = U32_MAX);
+		F64Kilobytes getPeriodMax(const TraceType<MemStatAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64Kilobytes getPeriodMax(const MemStatHandle& stat, S32 num_periods = S32_MAX);
 
 		template <typename T>
-		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const TraceType<T>& stat, S32 num_periods = S32_MAX)
 		{
-			size_t total_periods = mNumPeriods;
+			S32 total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 			F64 max_val = std::numeric_limits<F64>::min();
@@ -493,7 +493,7 @@ namespace LLTrace
 		}
 
 		template<typename T>
-		typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
 			return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
 		}
@@ -504,9 +504,9 @@ namespace LLTrace
 
 		// catch all for stats that have a defined sum
 		template <typename T>
-		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const TraceType<T >& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const TraceType<T >& stat, S32 num_periods = S32_MAX)
 		{
-			size_t total_periods = mNumPeriods;
+			S32 total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 			typename RelatedTypes<typename T::value_t>::fractional_t mean(0);
@@ -525,31 +525,31 @@ namespace LLTrace
 		}
 
 		template<typename T>
-		typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
 			return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
 		}
-		F64 getPeriodMean(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64 getPeriodMean(const TraceType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
 		template<typename T> 
-		typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
 			return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods));
 		}
 
-		F64 getPeriodMean(const TraceType<EventAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64 getPeriodMean(const TraceType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
 		template<typename T>
-		typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
 			return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
-		F64Kilobytes getPeriodMean(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
-		F64Kilobytes getPeriodMean(const MemStatHandle& stat, size_t num_periods = U32_MAX);
+		F64Kilobytes getPeriodMean(const TraceType<MemStatAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64Kilobytes getPeriodMean(const MemStatHandle& stat, S32 num_periods = S32_MAX);
 		
 		template <typename T>
-		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const TraceType<T>& stat, S32 num_periods = S32_MAX)
 		{
-			size_t total_periods = mNumPeriods;
+			S32 total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 			typename RelatedTypes<typename T::value_t>::fractional_t mean = 0;
@@ -569,7 +569,7 @@ namespace LLTrace
 		}
 
 		template<typename T>
-		typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
 			return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
 		}
@@ -578,23 +578,23 @@ namespace LLTrace
 		// PERIODIC STANDARD DEVIATION
 		//
 
-		F64 getPeriodStandardDeviation(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64 getPeriodStandardDeviation(const TraceType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
 
 		template<typename T> 
-		typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
 			return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods));
 		}
 
-		F64 getPeriodStandardDeviation(const TraceType<EventAccumulator>& stat, size_t num_periods = U32_MAX);
+		F64 getPeriodStandardDeviation(const TraceType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
 		template<typename T>
-		typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, size_t num_periods = U32_MAX)
+		typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
 			return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
 		}
 
-		F64Kilobytes getPeriodStandardDeviation(const TraceType<MemStatAccumulator>& stat, size_t num_periods = U32_MAX);
-		F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, size_t num_periods = U32_MAX);
+		F64Kilobytes getPeriodStandardDeviation(const TraceType<MemStatAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, S32 num_periods = S32_MAX);
 
 	private:
 		// implementation for LLStopWatchControlsMixin
@@ -606,8 +606,8 @@ namespace LLTrace
 	private:
 		std::vector<Recording>	mRecordingPeriods;
 		const bool				mAutoResize;
-		size_t					mCurPeriod;
-		size_t					mNumPeriods;
+		S32						mCurPeriod;
+		S32						mNumPeriods;
 	};
 
 	PeriodicRecording& get_frame_recording();
-- 
cgit v1.2.3


From 0e29315ec701583455a109e85221f62ee68225ca Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 27 Sep 2013 15:51:40 -0700
Subject: BUILDFIX: fix for bad assert causing unit tests to fail

---
 indra/llcommon/lltraceaccumulators.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 4fe84455a6..07870c5340 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -95,7 +95,7 @@ namespace LLTrace
 
 		void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, EBufferAppendType append_type)
 		{
-			llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot);
+			llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot);
 			for (size_t i = 0; i < sNextStorageSlot; i++)
 			{
 				mStorage[i].addSamples(other.mStorage[i], append_type);
@@ -104,7 +104,7 @@ namespace LLTrace
 
 		void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
 		{
-			llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot);
+			llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot);
 			for (size_t i = 0; i < sNextStorageSlot; i++)
 			{
 				mStorage[i] = other.mStorage[i];
-- 
cgit v1.2.3


From af6b6db264aaa02e9e6a01d88233d129cf960fdf Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 27 Sep 2013 21:24:27 -0700
Subject: fixed lltrace memory tracking image memory utilization now always
 non-negative

---
 indra/llcommon/lltrace.h               | 16 ++++++++++------
 indra/llcommon/lltraceaccumulators.cpp |  2 +-
 indra/llcommon/lltraceaccumulators.h   | 31 +++++++++++++++++--------------
 indra/llcommon/lltracerecording.cpp    | 24 ++++++++++++------------
 4 files changed, 40 insertions(+), 33 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 355617a898..5c68bbbc0b 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -283,30 +283,34 @@ public:
 
 inline void claim_footprint(MemStatHandle& measurement, S32 size)
 {
+	if(size == 0) return;
 	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
-	accumulator.mAllocated.add(1);
+	accumulator.mFootprintAllocations.record(size);
 }
 
 inline void disclaim_footprint(MemStatHandle& measurement, S32 size)
 {
+	if(size == 0) return;
 	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
-	accumulator.mDeallocated.add(1);
+	accumulator.mFootprintDeallocations.add(size);
 }
 
 inline void claim_shadow(MemStatHandle& measurement, S32 size)
 {
+	if(size == 0) return;
 	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mShadowSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
-	accumulator.mShadowAllocated.add(1);
+	accumulator.mShadowAllocations.record(size);
 }
 
 inline void disclaim_shadow(MemStatHandle& measurement, S32 size)
 {
+	if(size == 0) return;
 	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mShadowSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
-	accumulator.mShadowDeallocated.add(1);
+	accumulator.mShadowDeallocations.add(size);
 }
 
 // measures effective memory footprint of specified type
@@ -465,13 +469,13 @@ public:
 
 	void *operator new [](size_t size)
 	{
-		claim_footprint(sMemStat, size);
+		claim_footprint(sMemStat, size, true);
 		return ll_aligned_malloc(ALIGNMENT, size);
 	}
 
 	void operator delete[](void* ptr, size_t size)
 	{
-		disclaim_footprint(sMemStat, size);
+		disclaim_footprint(sMemStat, size, true);
 		ll_aligned_free(ALIGNMENT, ptr);
 	}
 
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index 58d0b5b227..a7bd04415e 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -239,7 +239,7 @@ void EventAccumulator::addSamples( const EventAccumulator& other, EBufferAppendT
 void EventAccumulator::reset( const EventAccumulator* other )
 {
 	mNumSamples = 0;
-	mSum = NaN;
+	mSum = 0;
 	mMin = NaN;
 	mMax = NaN;
 	mMean = NaN;
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 2dcfdf48ad..01f4ef506f 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -223,7 +223,7 @@ namespace LLTrace
 		typedef F64 value_t;
 
 		EventAccumulator()
-		:	mSum(NaN),
+		:	mSum(0),
 			mMin(NaN),
 			mMax(NaN),
 			mMean(NaN),
@@ -389,7 +389,7 @@ namespace LLTrace
 			mSum += value;
 		}
 
-		void addSamples(const CountAccumulator& other, bool /*follows_in_sequence*/)
+		void addSamples(const CountAccumulator& other, EBufferAppendType /*type*/)
 		{
 			mSum += other.mSum;
 			mNumSamples += other.mNumSamples;
@@ -515,8 +515,11 @@ namespace LLTrace
 
 		void addSamples(const MemStatAccumulator& other, EBufferAppendType append_type)
 		{
-			mAllocated.addSamples(other.mAllocated, append_type);
-			mDeallocated.addSamples(other.mDeallocated, append_type);
+			mFootprintAllocations.addSamples(other.mFootprintAllocations, append_type);
+			mFootprintDeallocations.addSamples(other.mFootprintDeallocations, append_type);
+			mShadowAllocations.addSamples(other.mShadowAllocations, append_type);
+			mShadowDeallocations.addSamples(other.mShadowDeallocations, append_type);
+
 			if (append_type == SEQUENTIAL)
 			{
 				mSize.addSamples(other.mSize, SEQUENTIAL);
@@ -524,12 +527,12 @@ namespace LLTrace
 			}
 			else
 			{
-				F64 allocation_delta(other.mAllocated.getSum() - other.mDeallocated.getSum());
+				F64 allocation_delta(other.mFootprintAllocations.getSum() - other.mFootprintDeallocations.getSum());
 				mSize.sample(mSize.hasValue() 
 					? mSize.getLastValue() + allocation_delta 
 					: allocation_delta);
 
-				F64 shadow_allocation_delta(other.mShadowAllocated.getSum() - other.mShadowDeallocated.getSum());
+				F64 shadow_allocation_delta(other.mShadowAllocations.getSum() - other.mShadowDeallocations.getSum());
 				mShadowSize.sample(mShadowSize.hasValue() 
 					? mShadowSize.getLastValue() + shadow_allocation_delta 
 					: shadow_allocation_delta);
@@ -540,10 +543,10 @@ namespace LLTrace
 		{
 			mSize.reset(other ? &other->mSize : NULL);
 			mShadowSize.reset(other ? &other->mShadowSize : NULL);
-			mAllocated.reset(other ? &other->mAllocated : NULL);
-			mDeallocated.reset(other ? &other->mDeallocated : NULL);
-			mShadowAllocated.reset(other ? &other->mShadowAllocated : NULL);
-			mShadowDeallocated.reset(other ? &other->mShadowDeallocated : NULL);
+			mFootprintAllocations.reset(other ? &other->mFootprintAllocations : NULL);
+			mFootprintDeallocations.reset(other ? &other->mFootprintDeallocations : NULL);
+			mShadowAllocations.reset(other ? &other->mShadowAllocations : NULL);
+			mShadowDeallocations.reset(other ? &other->mShadowDeallocations : NULL);
 		}
 
 		void sync(F64SecondsImplicit time_stamp) 
@@ -554,10 +557,10 @@ namespace LLTrace
 
 		SampleAccumulator	mSize,
 							mShadowSize;
-		CountAccumulator	mAllocated,
-							mDeallocated,
-							mShadowAllocated,
-							mShadowDeallocated;
+		EventAccumulator	mFootprintAllocations,
+							mShadowAllocations;
+		CountAccumulator	mFootprintDeallocations,
+							mShadowDeallocations;
 	};
 
 	struct AccumulatorBufferGroup : public LLRefCount
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index ddf62845a0..fb2293844a 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -230,62 +230,62 @@ F64Kilobytes Recording::getLastValue(const TraceType<MemStatAccumulator::ShadowM
 
 F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocated.getSum());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mFootprintAllocations.getSum());
 }
 
 F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocated.getSum() / mElapsedSeconds.value());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mFootprintAllocations.getSum() / mElapsedSeconds.value());
 }
 
 S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mAllocated.getSampleCount();
+	return mBuffers->mMemStats[stat.getIndex()].mFootprintAllocations.getSampleCount();
 }
 
 F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocated.getSum());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mFootprintDeallocations.getSum());
 }
 
 F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocated.getSum() / mElapsedSeconds.value());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mFootprintDeallocations.getSum() / mElapsedSeconds.value());
 }
 
 S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mDeallocated.getSampleCount();
+	return mBuffers->mMemStats[stat.getIndex()].mFootprintDeallocations.getSampleCount();
 }
 
 F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowAllocated.getSum());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowAllocations.getSum());
 }
 
 F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowAllocated.getSum() / mElapsedSeconds.value());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowAllocations.getSum() / mElapsedSeconds.value());
 }
 
 S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mShadowAllocated.getSampleCount();
+	return mBuffers->mMemStats[stat.getIndex()].mShadowAllocations.getSampleCount();
 }
 
 F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowDeallocated.getSum());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowDeallocations.getSum());
 }
 
 F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowDeallocated.getSum() / mElapsedSeconds.value());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowDeallocations.getSum() / mElapsedSeconds.value());
 }
 
 S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mShadowDeallocated.getSampleCount();
+	return mBuffers->mMemStats[stat.getIndex()].mShadowDeallocations.getSampleCount();
 }
 
 F64 Recording::getSum( const TraceType<CountAccumulator>& stat )
-- 
cgit v1.2.3


From a96da325564f4e9769e85ad006f98a4ac08d4a47 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 27 Sep 2013 23:26:12 -0700
Subject: BUILDFIX: too many arguments

---
 indra/llcommon/lltrace.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 5c68bbbc0b..da4bf6e36b 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -469,13 +469,13 @@ public:
 
 	void *operator new [](size_t size)
 	{
-		claim_footprint(sMemStat, size, true);
+		claim_footprint(sMemStat, size);
 		return ll_aligned_malloc(ALIGNMENT, size);
 	}
 
 	void operator delete[](void* ptr, size_t size)
 	{
-		disclaim_footprint(sMemStat, size, true);
+		disclaim_footprint(sMemStat, size);
 		ll_aligned_free(ALIGNMENT, ptr);
 	}
 
-- 
cgit v1.2.3


From 12f0f8cb72f789e21b01b45063dcc5f1f5292087 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 1 Oct 2013 13:46:43 -0700
Subject: changed over to manual naming of MemTrackable stats changed claimMem
 and disclaimMem behavior to not pass through argument added more mem tracking
 stats to floater_stats

---
 indra/llcommon/lltrace.h               | 298 ++++++++-------------------------
 indra/llcommon/lltraceaccumulators.cpp |   5 +
 indra/llcommon/lltraceaccumulators.h   |  36 +---
 indra/llcommon/lltracerecording.cpp    |  60 -------
 indra/llcommon/lltracerecording.h      |  16 --
 indra/llcommon/llunittype.h            |   1 +
 6 files changed, 79 insertions(+), 337 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index da4bf6e36b..226f64d0c7 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -35,6 +35,8 @@
 #include "lltraceaccumulators.h"
 #include "llthreadlocalstorage.h"
 #include "lltimer.h"
+#include "llpointer.h"
+#include "llunits.h"
 
 #include <list>
 
@@ -206,39 +208,6 @@ public:
 	{}
 };
 
-template<>
-class TraceType<MemStatAccumulator::ShadowAllocationFacet>
-	:	public TraceType<MemStatAccumulator>
-{
-public:
-
-	TraceType(const char* name, const char* description = "")
-		:	TraceType<MemStatAccumulator>(name, description)
-	{}
-};
-
-template<>
-class TraceType<MemStatAccumulator::ShadowDeallocationFacet>
-	:	public TraceType<MemStatAccumulator>
-{
-public:
-
-	TraceType(const char* name, const char* description = "")
-		:	TraceType<MemStatAccumulator>(name, description)
-	{}
-};
-
-template<>
-class TraceType<MemStatAccumulator::ShadowMemFacet>
-	:	public TraceType<MemStatAccumulator>
-{
-public:
-
-	TraceType(const char* name, const char* description = "")
-		:	TraceType<MemStatAccumulator>(name, description)
-	{}
-};
-
 class MemStatHandle : public TraceType<MemStatAccumulator>
 {
 public:
@@ -264,109 +233,40 @@ public:
 	{ 
 		return static_cast<TraceType<MemStatAccumulator::DeallocationFacet>&>(*(TraceType<MemStatAccumulator>*)this);
 	}
-
-	TraceType<MemStatAccumulator::ShadowAllocationFacet>& shadowAllocations() 
-	{ 
-		return static_cast<TraceType<MemStatAccumulator::ShadowAllocationFacet>&>(*(TraceType<MemStatAccumulator>*)this);
-	}
-
-	TraceType<MemStatAccumulator::ShadowDeallocationFacet>& shadowDeallocations() 
-	{ 
-		return static_cast<TraceType<MemStatAccumulator::ShadowDeallocationFacet>&>(*(TraceType<MemStatAccumulator>*)this);
-	}
-
-	TraceType<MemStatAccumulator::ShadowMemFacet>& shadowMem() 
-	{ 
-		return static_cast<TraceType<MemStatAccumulator::ShadowMemFacet>&>(*(TraceType<MemStatAccumulator>*)this);
-	}
 };
 
-inline void claim_footprint(MemStatHandle& measurement, S32 size)
-{
-	if(size == 0) return;
-	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
-	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
-	accumulator.mFootprintAllocations.record(size);
-}
-
-inline void disclaim_footprint(MemStatHandle& measurement, S32 size)
-{
-	if(size == 0) return;
-	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
-	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
-	accumulator.mFootprintDeallocations.add(size);
-}
-
-inline void claim_shadow(MemStatHandle& measurement, S32 size)
-{
-	if(size == 0) return;
-	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
-	accumulator.mShadowSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
-	accumulator.mShadowAllocations.record(size);
-}
-
-inline void disclaim_shadow(MemStatHandle& measurement, S32 size)
-{
-	if(size == 0) return;
-	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
-	accumulator.mShadowSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
-	accumulator.mShadowDeallocations.add(size);
-}
 
 // measures effective memory footprint of specified type
 // specialize to cover different types
-
-template<typename T, typename IS_MEM_TRACKABLE = void>
+template<typename T, typename IS_MEM_TRACKABLE = void, typename IS_UNITS = void>
 struct MeasureMem
 {
 	static size_t measureFootprint(const T& value)
 	{
 		return sizeof(T);
 	}
-
-	static size_t measureFootprint()
-	{
-		return sizeof(T);
-	}
-
-	static size_t measureShadow(const T& value)
-	{
-		return 0;
-	}
-
-	static size_t measureShadow()
-	{
-		return 0;
-	}
 };
 
-template<typename T>
-struct MeasureMem<T, typename T::mem_trackable_tag_t>
+template<typename T, typename IS_BYTES>
+struct MeasureMem<T, typename T::mem_trackable_tag_t, IS_BYTES>
 {
 	static size_t measureFootprint(const T& value)
 	{
 		return sizeof(T) + value.getMemFootprint();
 	}
+};
 
-	static size_t measureFootprint()
-	{
-		return sizeof(T);
-	}
-
-	static size_t measureShadow(const T& value)
-	{
-		return value.getMemShadow();
-	}
-
-	static size_t measureShadow()
+template<typename T, typename IS_MEM_TRACKABLE>
+struct MeasureMem<T, IS_MEM_TRACKABLE, typename T::is_unit_t>
+{
+	static size_t measureFootprint(const T& value)
 	{
-		return MeasureMem<T>::measureShadow();
+		return U32Bytes(value).value();
 	}
 };
 
-
-template<typename T, typename IS_MEM_TRACKABLE>
-struct MeasureMem<T*, IS_MEM_TRACKABLE>
+template<typename T, typename IS_MEM_TRACKABLE, typename IS_BYTES>
+struct MeasureMem<T*, IS_MEM_TRACKABLE, IS_BYTES>
 {
 	static size_t measureFootprint(const T* value)
 	{
@@ -376,46 +276,68 @@ struct MeasureMem<T*, IS_MEM_TRACKABLE>
 		}
 		return MeasureMem<T>::measureFootprint(*value);
 	}
+};
 
-	static size_t measureFootprint()
+template<typename T, typename IS_MEM_TRACKABLE, typename IS_BYTES>
+struct MeasureMem<LLPointer<T>, IS_MEM_TRACKABLE, IS_BYTES>
+{
+	static size_t measureFootprint(const LLPointer<T> value)
 	{
-		return MeasureMem<T>::measureFootprint();
+		if (value.isNull())
+		{
+			return 0;
+		}
+		return MeasureMem<T>::measureFootprint(*value);
 	}
+};
 
-	static size_t measureShadow(const T* value)
+template<typename IS_MEM_TRACKABLE, typename IS_BYTES>
+struct MeasureMem<S32, IS_MEM_TRACKABLE, IS_BYTES>
+{
+	static size_t measureFootprint(S32 value)
 	{
-		return MeasureMem<T>::measureShadow(*value);
+		return value;
 	}
+};
 
-	static size_t measureShadow()
+template<typename IS_MEM_TRACKABLE, typename IS_BYTES>
+struct MeasureMem<U32, IS_MEM_TRACKABLE, IS_BYTES>
+{
+	static size_t measureFootprint(U32 value)
 	{
-		return MeasureMem<T>::measureShadow();
+		return value;
 	}
 };
 
-template<typename T, typename IS_MEM_TRACKABLE>
-struct MeasureMem<std::basic_string<T>, IS_MEM_TRACKABLE>
+template<typename T, typename IS_MEM_TRACKABLE, typename IS_BYTES>
+struct MeasureMem<std::basic_string<T>, IS_MEM_TRACKABLE, IS_BYTES>
 {
 	static size_t measureFootprint(const std::basic_string<T>& value)
 	{
 		return value.capacity() * sizeof(T);
 	}
+};
 
-	static size_t measureFootprint()
-	{
-		return sizeof(std::basic_string<T>);
-	}
 
-	static size_t measureShadow(const std::basic_string<T>& value)
-	{
-		return 0;
-	}
+template<typename T>
+inline void claim_footprint(MemStatHandle& measurement, const T& value)
+{
+	S32 size = MeasureMem<T>::measureFootprint(value);
+	if(size == 0) return;
+	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
+	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
+	accumulator.mFootprintAllocations.record(size);
+}
 
-	static size_t measureShadow()
-	{
-		return 0;
-	}
-};
+template<typename T>
+inline void disclaim_footprint(MemStatHandle& measurement, const T& value)
+{
+	S32 size = MeasureMem<T>::measureFootprint(value);
+	if(size == 0) return;
+	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
+	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
+	accumulator.mFootprintDeallocations.add(size);
+}
 
 template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN>
 class MemTrackable
@@ -423,28 +345,20 @@ class MemTrackable
 public:
 	typedef void mem_trackable_tag_t;
 
-	enum EMemType
-	{
-		MEM_FOOTPRINT, 
-		MEM_SHADOW
-	};
-
-	MemTrackable()
-	:	mMemFootprint(0),
-		mMemShadow(0)
+	MemTrackable(const char* name)
+	:	mMemFootprint(0)
 	{
 		static bool name_initialized = false;
 		if (!name_initialized)
 		{
 			name_initialized = true;
-			sMemStat.setName(typeid(DERIVED).name());
+			sMemStat.setName(name);
 		}
 	}
 
 	virtual ~MemTrackable()
 	{
-		disclaimMem(mMemFootprint, MEM_FOOTPRINT);
-		disclaimMem(mMemShadow, MEM_SHADOW);
+		disclaimMem(mMemFootprint);
 	}
 
 	static MemStatHandle& getMemStatHandle()
@@ -453,7 +367,6 @@ public:
 	}
 
 	S32 getMemFootprint() const	{ return mMemFootprint; }
-	S32 getMemShadow() const	{ return mMemShadow; }
 
 	void* operator new(size_t size) 
 	{
@@ -467,7 +380,7 @@ public:
 		ll_aligned_free(ALIGNMENT, ptr);
 	}
 
-	void *operator new [](size_t size)
+	void* operator new [](size_t size)
 	{
 		claim_footprint(sMemStat, size);
 		return ll_aligned_malloc(ALIGNMENT, size);
@@ -481,98 +394,27 @@ public:
 
 	// claim memory associated with other objects/data as our own, adding to our calculated footprint
 	template<typename CLAIM_T>
-	CLAIM_T& claimMem(CLAIM_T& value, EMemType mem_type = MEM_FOOTPRINT)
-	{
-		trackAlloc(MeasureMem<CLAIM_T>::measureFootprint(value), mem_type);
-		trackAlloc(MeasureMem<CLAIM_T>::measureShadow(value), MEM_SHADOW);
-		return value;
-	}
-
-	template<typename CLAIM_T>
-	const CLAIM_T& claimMem(const CLAIM_T& value, EMemType mem_type = MEM_FOOTPRINT)
-	{
-		trackAlloc(MeasureMem<CLAIM_T>::measureFootprint(value), mem_type);
-		trackAlloc(MeasureMem<CLAIM_T>::measureShadow(value), MEM_SHADOW);
-		return value;
-	}
-
-	size_t& claimMem(size_t& size, EMemType mem_type = MEM_FOOTPRINT)
-	{
-		trackAlloc(size, mem_type);
-		return size;
-	}
-
-	S32& claimMem(S32& size, EMemType mem_type = MEM_FOOTPRINT)
+	void claimMem(const CLAIM_T& value) const
 	{
-		trackAlloc(size, mem_type);
-		return size;
+		S32 size = MeasureMem<CLAIM_T>::measureFootprint(value);
+		claim_footprint(sMemStat, size);
+		mMemFootprint += size;
 	}
 
 	// remove memory we had claimed from our calculated footprint
 	template<typename CLAIM_T>
-	CLAIM_T& disclaimMem(CLAIM_T& value, EMemType mem_type = MEM_FOOTPRINT)
-	{
-		trackDealloc(MeasureMem<CLAIM_T>::measureFootprint(value), mem_type);
-		trackDealloc(MeasureMem<CLAIM_T>::measureShadow(value), MEM_SHADOW);
-		return value;
-	}
-
-	template<typename CLAIM_T>
-	const CLAIM_T& disclaimMem(const CLAIM_T& value, EMemType mem_type = MEM_FOOTPRINT)
-	{
-		trackDealloc(MeasureMem<CLAIM_T>::measureFootprint(value), mem_type);
-		trackDealloc(MeasureMem<CLAIM_T>::measureShadow(value), MEM_SHADOW);
-		return value;
-	}
-
-	size_t& disclaimMem(size_t& size, EMemType mem_type = MEM_FOOTPRINT)
+	void disclaimMem(const CLAIM_T& value) const
 	{
-		trackDealloc(size, mem_type);
-		return size;
-	}
-
-	S32& disclaimMem(S32& size, EMemType mem_type = MEM_FOOTPRINT)
-	{
-		trackDealloc(size, mem_type);
-		return size;
-	}
-
-private:
-
-	void trackAlloc(S32 size, EMemType mem_type)
-	{
-		if (mem_type == MEM_FOOTPRINT)
-		{
-			claim_footprint(sMemStat, size);
-			mMemFootprint += size;
-		}
-		else
-		{
-			claim_shadow(sMemStat, size);
-			mMemShadow += size;
-		}
-	}
-
-	void trackDealloc(S32 size, EMemType mem_type)
-	{
-		if (mem_type == MEM_FOOTPRINT)
-		{
-			disclaim_footprint(sMemStat, size);
-			mMemFootprint -= size;
-		}
-		else
-		{
-			disclaim_shadow(sMemStat, size);
-			mMemShadow -= size;
-		}
+		S32 size = MeasureMem<CLAIM_T>::measureFootprint(value);
+		disclaim_footprint(sMemStat, size);
+		mMemFootprint -= size;
 	}
 
 private:
 	// use signed values so that we can temporarily go negative
 	// and reconcile in destructor
 	// NB: this assumes that no single class is responsible for > 2GB of allocations
-	S32 mMemFootprint,
-		mMemShadow;
+	mutable S32 mMemFootprint;
 	
 	static	MemStatHandle	sMemStat;
 };
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index a7bd04415e..f5f2e7df1c 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -125,6 +125,11 @@ void AccumulatorBufferGroup::sync()
 
 void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppendType append_type )
 {
+	if (append_type == NON_SEQUENTIAL)
+	{
+		return;
+	}
+
 	if (!mHasValue)
 	{
 		*this = other;
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 5cba3e5360..ecc569f5d6 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -498,32 +498,14 @@ namespace LLTrace
 			typedef F64Bytes value_t;
 		};
 
-		struct ShadowAllocationFacet 
-		{
-			typedef F64Bytes value_t;
-		};
-
-		struct ShadowDeallocationFacet 
-		{
-			typedef F64Bytes value_t;
-		};
-
-		struct ShadowMemFacet
-		{
-			typedef F64Bytes value_t;
-		};
-
 		void addSamples(const MemStatAccumulator& other, EBufferAppendType append_type)
 		{
 			mFootprintAllocations.addSamples(other.mFootprintAllocations, append_type);
 			mFootprintDeallocations.addSamples(other.mFootprintDeallocations, append_type);
-			mShadowAllocations.addSamples(other.mShadowAllocations, append_type);
-			mShadowDeallocations.addSamples(other.mShadowDeallocations, append_type);
 
 			if (append_type == SEQUENTIAL)
 			{
 				mSize.addSamples(other.mSize, SEQUENTIAL);
-				mShadowSize.addSamples(other.mShadowSize, SEQUENTIAL);
 			}
 			else
 			{
@@ -531,36 +513,24 @@ namespace LLTrace
 				mSize.sample(mSize.hasValue() 
 					? mSize.getLastValue() + allocation_delta 
 					: allocation_delta);
-
-				F64 shadow_allocation_delta(other.mShadowAllocations.getSum() - other.mShadowDeallocations.getSum());
-				mShadowSize.sample(mShadowSize.hasValue() 
-					? mShadowSize.getLastValue() + shadow_allocation_delta 
-					: shadow_allocation_delta);
 			}
 		}
 
 		void reset(const MemStatAccumulator* other)
 		{
 			mSize.reset(other ? &other->mSize : NULL);
-			mShadowSize.reset(other ? &other->mShadowSize : NULL);
 			mFootprintAllocations.reset(other ? &other->mFootprintAllocations : NULL);
 			mFootprintDeallocations.reset(other ? &other->mFootprintDeallocations : NULL);
-			mShadowAllocations.reset(other ? &other->mShadowAllocations : NULL);
-			mShadowDeallocations.reset(other ? &other->mShadowDeallocations : NULL);
 		}
 
 		void sync(F64SecondsImplicit time_stamp) 
 		{
 			mSize.sync(time_stamp);
-			mShadowSize.sync(time_stamp);
 		}
 
-		SampleAccumulator	mSize,
-							mShadowSize;
-		EventAccumulator	mFootprintAllocations,
-							mShadowAllocations;
-		CountAccumulator	mFootprintDeallocations,
-							mShadowDeallocations;
+		SampleAccumulator	mSize;
+		EventAccumulator	mFootprintAllocations;
+		CountAccumulator	mFootprintDeallocations;
 	};
 
 	struct AccumulatorBufferGroup : public LLRefCount
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index fb2293844a..ce4a433cca 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -173,11 +173,6 @@ bool Recording::hasValue(const TraceType<MemStatAccumulator>& stat)
 	return mBuffers->mMemStats[stat.getIndex()].mSize.hasValue();
 }
 
-bool Recording::hasValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
-{
-	return mBuffers->mMemStats[stat.getIndex()].mShadowSize.hasValue();
-}
-
 F64Kilobytes Recording::getMin(const TraceType<MemStatAccumulator>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMin());
@@ -203,31 +198,6 @@ F64Kilobytes Recording::getLastValue(const TraceType<MemStatAccumulator>& stat)
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue());
 }
 
-F64Kilobytes Recording::getMin(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
-{
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getMin());
-}
-
-F64Kilobytes Recording::getMean(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
-{
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getMean());
-}
-
-F64Kilobytes Recording::getMax(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
-{
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getMax());
-}
-
-F64Kilobytes Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
-{
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getStandardDeviation());
-}
-
-F64Kilobytes Recording::getLastValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat)
-{
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getLastValue());
-}
-
 F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mFootprintAllocations.getSum());
@@ -258,36 +228,6 @@ S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::DeallocationFa
 	return mBuffers->mMemStats[stat.getIndex()].mFootprintDeallocations.getSampleCount();
 }
 
-F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat)
-{
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowAllocations.getSum());
-}
-
-F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat)
-{
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowAllocations.getSum() / mElapsedSeconds.value());
-}
-
-S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat)
-{
-	return mBuffers->mMemStats[stat.getIndex()].mShadowAllocations.getSampleCount();
-}
-
-F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat)
-{
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowDeallocations.getSum());
-}
-
-F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat)
-{
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowDeallocations.getSum() / mElapsedSeconds.value());
-}
-
-S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat)
-{
-	return mBuffers->mMemStats[stat.getIndex()].mShadowDeallocations.getSampleCount();
-}
-
 F64 Recording::getSum( const TraceType<CountAccumulator>& stat )
 {
 	return mBuffers->mCounts[stat.getIndex()].getSum();
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 13dffdc701..085780198d 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -30,7 +30,6 @@
 #include "stdtypes.h"
 #include "llpreprocessor.h"
 
-#include "llpointer.h"
 #include "lltimer.h"
 #include "lltraceaccumulators.h"
 
@@ -178,7 +177,6 @@ namespace LLTrace
 
 		// Memory accessors
 		bool hasValue(const TraceType<MemStatAccumulator>& stat);
-		bool hasValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
 
 		F64Kilobytes getMin(const TraceType<MemStatAccumulator>& stat);
 		F64Kilobytes getMean(const TraceType<MemStatAccumulator>& stat);
@@ -186,12 +184,6 @@ namespace LLTrace
 		F64Kilobytes getStandardDeviation(const TraceType<MemStatAccumulator>& stat);
 		F64Kilobytes getLastValue(const TraceType<MemStatAccumulator>& stat);
 
-		F64Kilobytes getMin(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
-		F64Kilobytes getMean(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
-		F64Kilobytes getMax(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
-		F64Kilobytes getStandardDeviation(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
-		F64Kilobytes getLastValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat);
-
 		F64Kilobytes getSum(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
 		F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
 		S32 getSampleCount(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
@@ -200,14 +192,6 @@ namespace LLTrace
 		F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
 		S32 getSampleCount(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
 
-		F64Kilobytes getSum(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat);
-		F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat);
-		S32 getSampleCount(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat);
-
-		F64Kilobytes getSum(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat);
-		F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat);
-		S32 getSampleCount(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat);
-
 		// CountStatHandle accessors
 		F64 getSum(const TraceType<CountAccumulator>& stat);
 		template <typename T>
diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h
index fb72d6d8a9..0e05ecd683 100644
--- a/indra/llcommon/llunittype.h
+++ b/indra/llcommon/llunittype.h
@@ -80,6 +80,7 @@ struct LLUnit
 {
 	typedef LLUnit<STORAGE_TYPE, UNITS> self_t;
 	typedef STORAGE_TYPE storage_t;
+	typedef void is_unit_t;
 
 	// value initialization
 	LL_FORCE_INLINE explicit LLUnit(storage_t value = storage_t())
-- 
cgit v1.2.3


From b3d42e9b99db7e14354338383239122ef4cbeade Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 1 Oct 2013 20:22:20 -0700
Subject: BUILDFIX: missing header

---
 indra/llcommon/lltracerecording.h | 1 +
 1 file changed, 1 insertion(+)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 085780198d..5cf7596966 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -32,6 +32,7 @@
 
 #include "lltimer.h"
 #include "lltraceaccumulators.h"
+#include "llpointer.h"
 
 class LLStopWatchControlsMixinCommon
 {
-- 
cgit v1.2.3


From 754e8752a9b9a2e75d425a10cb8a0a6f85ad4bf5 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 3 Oct 2013 14:30:34 -0700
Subject: added initial memory usage tracking for lltrace

---
 indra/llcommon/lltrace.cpp               |  2 ++
 indra/llcommon/lltrace.h                 | 16 ++++-----
 indra/llcommon/lltraceaccumulators.cpp   | 20 ++++++++++-
 indra/llcommon/lltraceaccumulators.h     |  6 ++++
 indra/llcommon/lltracerecording.cpp      | 19 ++++++++--
 indra/llcommon/lltracerecording.h        |  3 +-
 indra/llcommon/lltracethreadrecorder.cpp | 62 ++++++++++++++++++++------------
 indra/llcommon/lltracethreadrecorder.h   |  2 +-
 8 files changed, 95 insertions(+), 35 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index e4a6f4c902..73846ba900 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -33,6 +33,8 @@
 namespace LLTrace
 {
 
+MemStatHandle gTraceMemStat("LLTrace");
+
 TraceBase::TraceBase( const char* name, const char* description ) 
 :	mName(name),
 	mDescription(description ? description : "")
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 226f64d0c7..421ec3bda5 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -320,7 +320,7 @@ struct MeasureMem<std::basic_string<T>, IS_MEM_TRACKABLE, IS_BYTES>
 
 
 template<typename T>
-inline void claim_footprint(MemStatHandle& measurement, const T& value)
+inline void claim_alloc(MemStatHandle& measurement, const T& value)
 {
 	S32 size = MeasureMem<T>::measureFootprint(value);
 	if(size == 0) return;
@@ -330,7 +330,7 @@ inline void claim_footprint(MemStatHandle& measurement, const T& value)
 }
 
 template<typename T>
-inline void disclaim_footprint(MemStatHandle& measurement, const T& value)
+inline void disclaim_alloc(MemStatHandle& measurement, const T& value)
 {
 	S32 size = MeasureMem<T>::measureFootprint(value);
 	if(size == 0) return;
@@ -370,25 +370,25 @@ public:
 
 	void* operator new(size_t size) 
 	{
-		claim_footprint(sMemStat, size);
+		claim_alloc(sMemStat, size);
 		return ll_aligned_malloc(ALIGNMENT, size);
 	}
 
 	void operator delete(void* ptr, size_t size)
 	{
-		disclaim_footprint(sMemStat, size);
+		disclaim_alloc(sMemStat, size);
 		ll_aligned_free(ALIGNMENT, ptr);
 	}
 
 	void* operator new [](size_t size)
 	{
-		claim_footprint(sMemStat, size);
+		claim_alloc(sMemStat, size);
 		return ll_aligned_malloc(ALIGNMENT, size);
 	}
 
 	void operator delete[](void* ptr, size_t size)
 	{
-		disclaim_footprint(sMemStat, size);
+		disclaim_alloc(sMemStat, size);
 		ll_aligned_free(ALIGNMENT, ptr);
 	}
 
@@ -397,7 +397,7 @@ public:
 	void claimMem(const CLAIM_T& value) const
 	{
 		S32 size = MeasureMem<CLAIM_T>::measureFootprint(value);
-		claim_footprint(sMemStat, size);
+		claim_alloc(sMemStat, size);
 		mMemFootprint += size;
 	}
 
@@ -406,7 +406,7 @@ public:
 	void disclaimMem(const CLAIM_T& value) const
 	{
 		S32 size = MeasureMem<CLAIM_T>::measureFootprint(value);
-		disclaim_footprint(sMemStat, size);
+		disclaim_alloc(sMemStat, size);
 		mMemFootprint -= size;
 	}
 
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index f5f2e7df1c..9f270e60b9 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -26,18 +26,36 @@
 #include "linden_common.h"
 
 #include "lltraceaccumulators.h"
+#include "lltrace.h"
 #include "lltracethreadrecorder.h"
 
 namespace LLTrace
 {
 
+extern MemStatHandle gTraceMemStat;
+
 
 ///////////////////////////////////////////////////////////////////////
 // AccumulatorBufferGroup
 ///////////////////////////////////////////////////////////////////////
 
 AccumulatorBufferGroup::AccumulatorBufferGroup() 
-{}
+{
+	/*claim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator));
+	claim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator));
+	claim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator));
+	claim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator));
+	claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemStatAccumulator));*/
+}
+
+AccumulatorBufferGroup::~AccumulatorBufferGroup()
+{
+	/*disclaim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator));
+	disclaim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator));
+	disclaim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator));
+	disclaim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator));
+	disclaim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemStatAccumulator));*/
+}
 
 void AccumulatorBufferGroup::handOffTo(AccumulatorBufferGroup& other)
 {
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index ecc569f5d6..d03c6ce5c0 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -188,6 +188,11 @@ namespace LLTrace
 			return getNumIndices();
 		}
 
+		size_t capacity() const
+		{
+			return mStorageSize;
+		}
+
 		static size_t getNumIndices() 
 		{
 			return sNextStorageSlot;
@@ -536,6 +541,7 @@ namespace LLTrace
 	struct AccumulatorBufferGroup : public LLRefCount
 	{
 		AccumulatorBufferGroup();
+		~AccumulatorBufferGroup();
 
 		void handOffTo(AccumulatorBufferGroup& other);
 		void makeCurrent();
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index ce4a433cca..c33d9aedcc 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -25,15 +25,18 @@
 
 #include "linden_common.h"
 
+#include "lltracerecording.h"
+
 #include "lltrace.h"
 #include "llfasttimer.h"
-#include "lltracerecording.h"
 #include "lltracethreadrecorder.h"
 #include "llthread.h"
 
 namespace LLTrace
 {
-	
+
+extern MemStatHandle gTraceMemStat;
+
 ///////////////////////////////////////////////////////////////////////
 // Recording
 ///////////////////////////////////////////////////////////////////////
@@ -42,12 +45,15 @@ Recording::Recording(EPlayState state)
 :	mElapsedSeconds(0),
 	mInHandOff(false)
 {
+	claim_alloc(gTraceMemStat, sizeof(*this));
 	mBuffers = new AccumulatorBufferGroup();
+	claim_alloc(gTraceMemStat, mBuffers);
 	setPlayState(state);
 }
 
 Recording::Recording( const Recording& other )
 {
+	claim_alloc(gTraceMemStat, sizeof(*this));
 	*this = other;
 }
 
@@ -73,6 +79,9 @@ Recording& Recording::operator = (const Recording& other)
 
 Recording::~Recording()
 {
+	disclaim_alloc(gTraceMemStat, sizeof(*this));
+	disclaim_alloc(gTraceMemStat, mBuffers);
+
 	if (isStarted() && LLTrace::get_thread_recorder().notNull())
 	{
 		LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
@@ -330,6 +339,12 @@ PeriodicRecording::PeriodicRecording( S32 num_periods, EPlayState state)
 	mRecordingPeriods(num_periods ? num_periods : 1)
 {
 	setPlayState(state);
+	claim_alloc(gTraceMemStat, sizeof(*this));
+}
+
+PeriodicRecording::~PeriodicRecording()
+{
+	disclaim_alloc(gTraceMemStat, sizeof(*this));
 }
 
 void PeriodicRecording::nextPeriod()
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 5cf7596966..8bb0b1892f 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -313,7 +313,7 @@ namespace LLTrace
 		class ThreadRecorder* getThreadRecorder(); 
 
 		LLTimer											mSamplingTimer;
-		F64Seconds					mElapsedSeconds;
+		F64Seconds										mElapsedSeconds;
 		LLCopyOnWritePointer<AccumulatorBufferGroup>	mBuffers;
 		bool											mInHandOff;
 
@@ -324,6 +324,7 @@ namespace LLTrace
 	{
 	public:
 		PeriodicRecording(S32 num_periods, EPlayState state = STOPPED);
+		~PeriodicRecording();
 
 		void nextPeriod();
 		S32 getNumRecordedPeriods() { return mNumPeriods; }
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index e131af5f16..bf6189dd25 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -27,9 +27,11 @@
 
 #include "lltracethreadrecorder.h"
 #include "llfasttimer.h"
+#include "lltrace.h"
 
 namespace LLTrace
 {
+extern MemStatHandle gTraceMemStat;
 
 static ThreadRecorder* sMasterThreadRecorder = NULL;
 
@@ -55,6 +57,7 @@ void ThreadRecorder::init()
 	timer_stack->mActiveTimer = NULL;
 
 	mNumTimeBlockTreeNodes = AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer()->size();
+
 	mTimeBlockTreeNodes = new TimeBlockTreeNode[mNumTimeBlockTreeNodes];
 
 	activate(&mThreadRecordingBuffers);
@@ -76,10 +79,14 @@ void ThreadRecorder::init()
 	timer_stack->mActiveTimer = mRootTimer;
 
 	TimeBlock::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1;
+
+	claim_alloc(gTraceMemStat, sizeof(*this));
+	claim_alloc(gTraceMemStat, sizeof(BlockTimer));
+	claim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes);
 }
 
 
-ThreadRecorder::ThreadRecorder(ThreadRecorder& master)
+ThreadRecorder::ThreadRecorder( ThreadRecorder& master )
 :	mMasterRecorder(&master)
 {
 	init();
@@ -91,6 +98,10 @@ ThreadRecorder::~ThreadRecorder()
 {
 	LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(NULL);
 
+	disclaim_alloc(gTraceMemStat, sizeof(*this));
+	disclaim_alloc(gTraceMemStat, sizeof(BlockTimer));
+	disclaim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes);
+
 	deactivate(&mThreadRecordingBuffers);
 
 	delete mRootTimer;
@@ -135,9 +146,9 @@ void ThreadRecorder::activate( AccumulatorBufferGroup* recording, bool from_hand
 	mActiveRecordings.back()->mPartialRecording.makeCurrent();
 }
 
-ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringUpToDate( AccumulatorBufferGroup* recording )
+ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::bringUpToDate( AccumulatorBufferGroup* recording )
 {
-	if (mActiveRecordings.empty()) return mActiveRecordings.rend();
+	if (mActiveRecordings.empty()) return mActiveRecordings.end();
 
 	mActiveRecordings.back()->mPartialRecording.sync();
 	TimeBlock::updateTimes();
@@ -174,15 +185,14 @@ ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringU
 		LL_WARNS() << "Recording not active on this thread" << LL_ENDL;
 	}
 
-	return it;
+	return (++it).base();
 }
 
 void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording )
 {
-	active_recording_list_t::reverse_iterator it = bringUpToDate(recording);
-	if (it != mActiveRecordings.rend())
+	active_recording_list_t::iterator recording_to_remove = bringUpToDate(recording);
+	if (recording_to_remove != mActiveRecordings.end())
 	{
-		active_recording_list_t::iterator recording_to_remove = (++it).base();
 		bool was_current = (*recording_to_remove)->mPartialRecording.isCurrent();
 		llassert((*recording_to_remove)->mTargetRecording == recording);
 		delete *recording_to_remove;
@@ -216,25 +226,33 @@ void ThreadRecorder::ActiveRecording::movePartialToTarget()
 
 // called by child thread
 void ThreadRecorder::addChildRecorder( class ThreadRecorder* child )
-{ LLMutexLock lock(&mChildListMutex);
-	mChildThreadRecorders.push_back(child);
+{
+	{ LLMutexLock lock(&mChildListMutex);
+		mChildThreadRecorders.push_back(child);
+	}
 }
 
 // called by child thread
 void ThreadRecorder::removeChildRecorder( class ThreadRecorder* child )
-{ LLMutexLock lock(&mChildListMutex);
-
-for (child_thread_recorder_list_t::iterator it = mChildThreadRecorders.begin(), end_it = mChildThreadRecorders.end();
-	it != end_it;
-	++it)
-{
-	if ((*it) == child)
-	{
-		mChildThreadRecorders.erase(it);
-		break;
+{	
+	{ LLMutexLock lock(&mChildListMutex);
+		for (child_thread_recorder_list_t::iterator it = mChildThreadRecorders.begin(), end_it = mChildThreadRecorders.end();
+			it != end_it;
+			++it)
+		{
+			if ((*it) == child)
+			{
+				// FIXME: this won't do any good, as the child stores the "pushed" values internally
+				// and it is in the process of being deleted.
+				// We need a way to finalize the stats from the outgoing thread, but the storage
+				// for those stats needs to be outside the child's thread recorder
+				//(*it)->pushToParent();
+				mChildThreadRecorders.erase(it);
+				break;
+			}
+		}
 	}
 }
-}
 
 void ThreadRecorder::pushToParent()
 {
@@ -269,7 +287,7 @@ void ThreadRecorder::pullFromChildren()
 }
 
 
-void set_master_thread_recorder(ThreadRecorder* recorder)
+void set_master_thread_recorder( ThreadRecorder* recorder )
 {
 	sMasterThreadRecorder = recorder;
 }
@@ -291,7 +309,7 @@ const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
 	return get_thread_recorder_ptr();
 }
 
-void set_thread_recorder(ThreadRecorder* recorder)
+void set_thread_recorder( ThreadRecorder* recorder )
 {
 	get_thread_recorder_ptr() = recorder;
 }
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index c40228785e..c6afcdac80 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -49,7 +49,7 @@ namespace LLTrace
 
 		void activate(AccumulatorBufferGroup* recording, bool from_handoff = false);
 		void deactivate(AccumulatorBufferGroup* recording);
-		active_recording_list_t::reverse_iterator bringUpToDate(AccumulatorBufferGroup* recording);
+		active_recording_list_t::iterator bringUpToDate(AccumulatorBufferGroup* recording);
 
 		void addChildRecorder(class ThreadRecorder* child);
 		void removeChildRecorder(class ThreadRecorder* child);
-- 
cgit v1.2.3


From 3b6004adf7c897d48a60f7a4d9b0e27dc7656932 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 3 Oct 2013 15:14:26 -0700
Subject: BUILDFIX: fixed tabs in cmake file and lack of newline at EOF

---
 indra/llcommon/CMakeLists.txt      | 6 +++---
 indra/llcommon/indra_constants.cpp | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index e138a54d29..e2e2cb436d 100755
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -34,7 +34,7 @@ set(llcommon_SOURCE_FILES
     llassettype.cpp
     llbase32.cpp
     llbase64.cpp
-	llbitpack.cpp
+    llbitpack.cpp
     llcommon.cpp
     llcommonutils.cpp
     llcoros.cpp
@@ -205,7 +205,7 @@ set(llcommon_HEADER_FILES
     llthreadsafequeue.h
     lltimer.h
     lltrace.h
-	lltraceaccumulators.h
+    lltraceaccumulators.h
     lltracerecording.h
     lltracethreadrecorder.h
     lltreeiterators.h
@@ -213,7 +213,7 @@ set(llcommon_HEADER_FILES
     llunittype.h
     lluri.h
     lluuid.h
-	llwin32headers.h
+    llwin32headers.h
     llwin32headerslean.h
     llworkerthread.h
     stdtypes.h
diff --git a/indra/llcommon/indra_constants.cpp b/indra/llcommon/indra_constants.cpp
index b61dca3243..f3989ee1d0 100755
--- a/indra/llcommon/indra_constants.cpp
+++ b/indra/llcommon/indra_constants.cpp
@@ -66,4 +66,4 @@ const LLUUID TERRAIN_GRASS_DETAIL		("63338ede-0037-c4fd-855b-015d77112fc8"); //
 const LLUUID TERRAIN_MOUNTAIN_DETAIL	("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER
 const LLUUID TERRAIN_ROCK_DETAIL		("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER
 
-const LLUUID DEFAULT_WATER_NORMAL		("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER
\ No newline at end of file
+const LLUUID DEFAULT_WATER_NORMAL		("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER
-- 
cgit v1.2.3


From 1821fa12838974c4eb7de2b6e9f79bf8a4cf23f1 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 3 Oct 2013 16:57:15 -0700
Subject: fixed memory tracking of lltrace system

---
 indra/llcommon/lltraceaccumulators.cpp   | 17 +++++++++++++----
 indra/llcommon/lltracethreadrecorder.cpp | 17 +++++++++--------
 2 files changed, 22 insertions(+), 12 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index 9f270e60b9..6381281a56 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -41,20 +41,29 @@ extern MemStatHandle gTraceMemStat;
 
 AccumulatorBufferGroup::AccumulatorBufferGroup() 
 {
-	/*claim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator));
+	claim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator));
 	claim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator));
 	claim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator));
 	claim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator));
-	claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemStatAccumulator));*/
+	claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemStatAccumulator));
+}
+
+AccumulatorBufferGroup::AccumulatorBufferGroup(const AccumulatorBufferGroup&)
+{
+	claim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator));
+	claim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator));
+	claim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator));
+	claim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator));
+	claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemStatAccumulator));
 }
 
 AccumulatorBufferGroup::~AccumulatorBufferGroup()
 {
-	/*disclaim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator));
+	disclaim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator));
 	disclaim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator));
 	disclaim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator));
 	disclaim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator));
-	disclaim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemStatAccumulator));*/
+	disclaim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemStatAccumulator));
 }
 
 void AccumulatorBufferGroup::handOffTo(AccumulatorBufferGroup& other)
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index bf6189dd25..9dac4f6771 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -80,7 +80,7 @@ void ThreadRecorder::init()
 
 	TimeBlock::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1;
 
-	claim_alloc(gTraceMemStat, sizeof(*this));
+	claim_alloc(gTraceMemStat, this);
 	claim_alloc(gTraceMemStat, sizeof(BlockTimer));
 	claim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes);
 }
@@ -98,7 +98,7 @@ ThreadRecorder::~ThreadRecorder()
 {
 	LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(NULL);
 
-	disclaim_alloc(gTraceMemStat, sizeof(*this));
+	disclaim_alloc(gTraceMemStat, this);
 	disclaim_alloc(gTraceMemStat, sizeof(BlockTimer));
 	disclaim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes);
 
@@ -190,13 +190,13 @@ ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::bringUpToDate(
 
 void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording )
 {
-	active_recording_list_t::iterator recording_to_remove = bringUpToDate(recording);
-	if (recording_to_remove != mActiveRecordings.end())
+	active_recording_list_t::iterator recording_it = bringUpToDate(recording);
+	if (recording_it != mActiveRecordings.end())
 	{
-		bool was_current = (*recording_to_remove)->mPartialRecording.isCurrent();
-		llassert((*recording_to_remove)->mTargetRecording == recording);
-		delete *recording_to_remove;
-		mActiveRecordings.erase(recording_to_remove);
+		ActiveRecording* recording_to_remove = *recording_it;
+		bool was_current = recording_to_remove->mPartialRecording.isCurrent();
+		llassert(recording_to_remove->mTargetRecording == recording);
+		mActiveRecordings.erase(recording_it);
 		if (was_current)
 		{
 			if (mActiveRecordings.empty())
@@ -208,6 +208,7 @@ void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording )
 				mActiveRecordings.back()->mPartialRecording.makeCurrent();
 			}
 		}
+		delete recording_to_remove;
 	}
 }
 
-- 
cgit v1.2.3


From f8a85003ddd4bee1ae00fc329c1c1d66d6100cbd Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 3 Oct 2013 19:04:51 -0700
Subject: more memory optimizations of lltrace

---
 indra/llcommon/lltrace.h               |  4 ++--
 indra/llcommon/lltraceaccumulators.cpp |  7 ++++++-
 indra/llcommon/lltraceaccumulators.h   | 38 +++++++++++++++++++---------------
 indra/llcommon/lltracerecording.cpp    | 22 ++++++++++----------
 4 files changed, 40 insertions(+), 31 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 421ec3bda5..3dc2e5248f 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -326,7 +326,7 @@ inline void claim_alloc(MemStatHandle& measurement, const T& value)
 	if(size == 0) return;
 	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
-	accumulator.mFootprintAllocations.record(size);
+	accumulator.mAllocations.record(size);
 }
 
 template<typename T>
@@ -336,7 +336,7 @@ inline void disclaim_alloc(MemStatHandle& measurement, const T& value)
 	if(size == 0) return;
 	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
-	accumulator.mFootprintDeallocations.add(size);
+	accumulator.mDeallocations.add(size);
 }
 
 template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN>
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index 6381281a56..c25bb704f5 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -48,7 +48,12 @@ AccumulatorBufferGroup::AccumulatorBufferGroup()
 	claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemStatAccumulator));
 }
 
-AccumulatorBufferGroup::AccumulatorBufferGroup(const AccumulatorBufferGroup&)
+AccumulatorBufferGroup::AccumulatorBufferGroup(const AccumulatorBufferGroup& other)
+:	mCounts(other.mCounts),
+	mSamples(other.mSamples),
+	mEvents(other.mEvents),
+	mStackTimers(other.mStackTimers),
+	mMemStats(other.mMemStats)
 {
 	claim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator));
 	claim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator));
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index d03c6ce5c0..27c0910665 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -266,8 +266,8 @@ namespace LLTrace
 		void sync(F64SecondsImplicit) {}
 
 		F64	getSum() const               { return mSum; }
-		F64	getMin() const               { return mMin; }
-		F64	getMax() const               { return mMax; }
+		F32	getMin() const               { return mMin; }
+		F32	getMax() const               { return mMax; }
 		F64	getLastValue() const         { return mLastValue; }
 		F64	getMean() const              { return mMean; }
 		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mNumSamples); }
@@ -277,13 +277,14 @@ namespace LLTrace
 
 	private:
 		F64	mSum,
-			mMin,
-			mMax,
 			mLastValue;
 
 		F64	mMean,
 			mSumOfSquares;
 
+		F32 mMin,
+			mMax;
+
 		S32	mNumSamples;
 	};
 
@@ -350,8 +351,8 @@ namespace LLTrace
 		}
 
 		F64	getSum() const               { return mSum; }
-		F64	getMin() const               { return mMin; }
-		F64	getMax() const               { return mMax; }
+		F32	getMin() const               { return mMin; }
+		F32	getMax() const               { return mMax; }
 		F64	getLastValue() const         { return mLastValue; }
 		F64	getMean() const              { return mMean; }
 		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); }
@@ -362,12 +363,8 @@ namespace LLTrace
 
 	private:
 		F64		mSum,
-				mMin,
-				mMax,
 				mLastValue;
 
-		bool	mHasValue;		// distinct from mNumSamples, since we might have inherited an old sample
-
 		F64		mMean,
 				mSumOfSquares;
 
@@ -375,7 +372,13 @@ namespace LLTrace
 				mLastSampleTimeStamp,
 				mTotalSamplingTime;
 
+		F32		mMin,
+				mMax;
+
 		S32		mNumSamples;
+		// distinct from mNumSamples, since we might have inherited a last value from
+		// a previous sampling period
+		bool	mHasValue;		
 	};
 
 	class CountAccumulator
@@ -505,8 +508,8 @@ namespace LLTrace
 
 		void addSamples(const MemStatAccumulator& other, EBufferAppendType append_type)
 		{
-			mFootprintAllocations.addSamples(other.mFootprintAllocations, append_type);
-			mFootprintDeallocations.addSamples(other.mFootprintDeallocations, append_type);
+			mAllocations.addSamples(other.mAllocations, append_type);
+			mDeallocations.addSamples(other.mDeallocations, append_type);
 
 			if (append_type == SEQUENTIAL)
 			{
@@ -514,7 +517,7 @@ namespace LLTrace
 			}
 			else
 			{
-				F64 allocation_delta(other.mFootprintAllocations.getSum() - other.mFootprintDeallocations.getSum());
+				F64 allocation_delta(other.mAllocations.getSum() - other.mDeallocations.getSum());
 				mSize.sample(mSize.hasValue() 
 					? mSize.getLastValue() + allocation_delta 
 					: allocation_delta);
@@ -524,8 +527,8 @@ namespace LLTrace
 		void reset(const MemStatAccumulator* other)
 		{
 			mSize.reset(other ? &other->mSize : NULL);
-			mFootprintAllocations.reset(other ? &other->mFootprintAllocations : NULL);
-			mFootprintDeallocations.reset(other ? &other->mFootprintDeallocations : NULL);
+			mAllocations.reset(other ? &other->mAllocations : NULL);
+			mDeallocations.reset(other ? &other->mDeallocations : NULL);
 		}
 
 		void sync(F64SecondsImplicit time_stamp) 
@@ -534,13 +537,14 @@ namespace LLTrace
 		}
 
 		SampleAccumulator	mSize;
-		EventAccumulator	mFootprintAllocations;
-		CountAccumulator	mFootprintDeallocations;
+		EventAccumulator	mAllocations;
+		CountAccumulator	mDeallocations;
 	};
 
 	struct AccumulatorBufferGroup : public LLRefCount
 	{
 		AccumulatorBufferGroup();
+		AccumulatorBufferGroup(const AccumulatorBufferGroup&);
 		~AccumulatorBufferGroup();
 
 		void handOffTo(AccumulatorBufferGroup& other);
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index c33d9aedcc..06b4351339 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -45,7 +45,7 @@ Recording::Recording(EPlayState state)
 :	mElapsedSeconds(0),
 	mInHandOff(false)
 {
-	claim_alloc(gTraceMemStat, sizeof(*this));
+	claim_alloc(gTraceMemStat, this);
 	mBuffers = new AccumulatorBufferGroup();
 	claim_alloc(gTraceMemStat, mBuffers);
 	setPlayState(state);
@@ -53,7 +53,7 @@ Recording::Recording(EPlayState state)
 
 Recording::Recording( const Recording& other )
 {
-	claim_alloc(gTraceMemStat, sizeof(*this));
+	claim_alloc(gTraceMemStat, this);
 	*this = other;
 }
 
@@ -79,7 +79,7 @@ Recording& Recording::operator = (const Recording& other)
 
 Recording::~Recording()
 {
-	disclaim_alloc(gTraceMemStat, sizeof(*this));
+	disclaim_alloc(gTraceMemStat, this);
 	disclaim_alloc(gTraceMemStat, mBuffers);
 
 	if (isStarted() && LLTrace::get_thread_recorder().notNull())
@@ -209,32 +209,32 @@ F64Kilobytes Recording::getLastValue(const TraceType<MemStatAccumulator>& stat)
 
 F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mFootprintAllocations.getSum());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocations.getSum());
 }
 
 F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mFootprintAllocations.getSum() / mElapsedSeconds.value());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocations.getSum() / mElapsedSeconds.value());
 }
 
 S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mFootprintAllocations.getSampleCount();
+	return mBuffers->mMemStats[stat.getIndex()].mAllocations.getSampleCount();
 }
 
 F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mFootprintDeallocations.getSum());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSum());
 }
 
 F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mFootprintDeallocations.getSum() / mElapsedSeconds.value());
+	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSum() / mElapsedSeconds.value());
 }
 
 S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mFootprintDeallocations.getSampleCount();
+	return mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSampleCount();
 }
 
 F64 Recording::getSum( const TraceType<CountAccumulator>& stat )
@@ -339,12 +339,12 @@ PeriodicRecording::PeriodicRecording( S32 num_periods, EPlayState state)
 	mRecordingPeriods(num_periods ? num_periods : 1)
 {
 	setPlayState(state);
-	claim_alloc(gTraceMemStat, sizeof(*this));
+	claim_alloc(gTraceMemStat, this);
 }
 
 PeriodicRecording::~PeriodicRecording()
 {
-	disclaim_alloc(gTraceMemStat, sizeof(*this));
+	disclaim_alloc(gTraceMemStat, this);
 }
 
 void PeriodicRecording::nextPeriod()
-- 
cgit v1.2.3


From 17df8988fec3f2ba991ca9e34ff8148253a2fc04 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 7 Oct 2013 13:38:03 -0700
Subject: renamed TraceType to StatType added more MemTrackable types optimized
 memory usage of LLTrace some more

---
 indra/llcommon/llfasttimer.cpp         |   2 +-
 indra/llcommon/llfasttimer.h           |  10 +-
 indra/llcommon/lltrace.cpp             |   4 +-
 indra/llcommon/lltrace.h               | 127 +++++++++++++++----------
 indra/llcommon/lltraceaccumulators.cpp |   8 +-
 indra/llcommon/lltraceaccumulators.h   |  18 ++--
 indra/llcommon/lltracerecording.cpp    | 104 ++++++++++-----------
 indra/llcommon/lltracerecording.h      | 166 ++++++++++++++++-----------------
 8 files changed, 233 insertions(+), 206 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 32ef01b2b6..c948e0ac85 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -165,7 +165,7 @@ U64 TimeBlock::countsPerSecond()
 #endif
 
 TimeBlock::TimeBlock(const char* name, TimeBlock* parent)
-:	TraceType<TimeBlockAccumulator>(name)
+:	StatType<TimeBlockAccumulator>(name)
 {}
 
 TimeBlockTreeNode& TimeBlock::getTreeNode() const
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 4eb12907dc..1266d87f08 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -86,7 +86,7 @@ LL_FORCE_INLINE class BlockTimer timeThisBlock(class TimeBlock& timer)
 
 // stores a "named" timer instance to be reused via multiple BlockTimer stack instances
 class TimeBlock 
-:	public TraceType<TimeBlockAccumulator>,
+:	public StatType<TimeBlockAccumulator>,
 	public LLInstanceTracker<TimeBlock>
 {
 public:
@@ -102,14 +102,14 @@ public:
 	child_iter endChildren();
 	std::vector<TimeBlock*>& getChildren();
 
-	TraceType<TimeBlockAccumulator::CallCountFacet>& callCount() 
+	StatType<TimeBlockAccumulator::CallCountFacet>& callCount() 
 	{
-		return static_cast<TraceType<TimeBlockAccumulator::CallCountFacet>&>(*(TraceType<TimeBlockAccumulator>*)this);
+		return static_cast<StatType<TimeBlockAccumulator::CallCountFacet>&>(*(StatType<TimeBlockAccumulator>*)this);
 	}
 
-	TraceType<TimeBlockAccumulator::SelfTimeFacet>& selfTime() 
+	StatType<TimeBlockAccumulator::SelfTimeFacet>& selfTime() 
 	{
-		return static_cast<TraceType<TimeBlockAccumulator::SelfTimeFacet>&>(*(TraceType<TimeBlockAccumulator>*)this);
+		return static_cast<StatType<TimeBlockAccumulator::SelfTimeFacet>&>(*(StatType<TimeBlockAccumulator>*)this);
 	}
 
 	static TimeBlock& getRootTimeBlock();
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 73846ba900..1ad31cacfe 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -35,7 +35,7 @@ namespace LLTrace
 
 MemStatHandle gTraceMemStat("LLTrace");
 
-TraceBase::TraceBase( const char* name, const char* description ) 
+StatBase::StatBase( const char* name, const char* description ) 
 :	mName(name),
 	mDescription(description ? description : "")
 {
@@ -47,7 +47,7 @@ TraceBase::TraceBase( const char* name, const char* description )
 #endif
 }
 
-const char* TraceBase::getUnitLabel() const
+const char* StatBase::getUnitLabel() const
 {
 	return "";
 }
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 3dc2e5248f..325112b9b1 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -38,8 +38,6 @@
 #include "llpointer.h"
 #include "llunits.h"
 
-#include <list>
-
 namespace LLTrace
 {
 class Recording;
@@ -53,11 +51,11 @@ STORAGE_TYPE storage_value(LLUnit<STORAGE_TYPE, UNIT_TYPE> val) { return val.val
 template<typename UNIT_TYPE, typename STORAGE_TYPE> 
 STORAGE_TYPE storage_value(LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); }
 
-class TraceBase
+class StatBase
 {
 public:
-	TraceBase(const char* name, const char* description);
-	virtual ~TraceBase() {};
+	StatBase(const char* name, const char* description);
+	virtual ~StatBase() {};
 	virtual const char* getUnitLabel() const;
 
 	const std::string& getName() const { return mName; }
@@ -69,14 +67,14 @@ protected:
 };
 
 template<typename ACCUMULATOR>
-class TraceType 
-:	public TraceBase,
-	public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>
+class StatType 
+:	public StatBase,
+	public LLInstanceTracker<StatType<ACCUMULATOR>, std::string>
 {
 public:
-	TraceType(const char* name, const char* description = NULL)
-	:	LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>(name),
-		TraceBase(name, description),
+	StatType(const char* name, const char* description = NULL)
+	:	LLInstanceTracker<StatType<ACCUMULATOR>, std::string>(name),
+		StatBase(name, description),
 		mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot())
 	{}
 
@@ -95,38 +93,38 @@ protected:
 
 
 template<>
-class TraceType<TimeBlockAccumulator::CallCountFacet>
-:	public TraceType<TimeBlockAccumulator>
+class StatType<TimeBlockAccumulator::CallCountFacet>
+:	public StatType<TimeBlockAccumulator>
 {
 public:
 
-	TraceType(const char* name, const char* description = "")
-	:	TraceType<TimeBlockAccumulator>(name, description)
+	StatType(const char* name, const char* description = "")
+	:	StatType<TimeBlockAccumulator>(name, description)
 	{}
 };
 
 template<>
-class TraceType<TimeBlockAccumulator::SelfTimeFacet>
-	:	public TraceType<TimeBlockAccumulator>
+class StatType<TimeBlockAccumulator::SelfTimeFacet>
+	:	public StatType<TimeBlockAccumulator>
 {
 public:
 
-	TraceType(const char* name, const char* description = "")
-		:	TraceType<TimeBlockAccumulator>(name, description)
+	StatType(const char* name, const char* description = "")
+		:	StatType<TimeBlockAccumulator>(name, description)
 	{}
 };
 
 template <typename T = F64>
 class EventStatHandle
-:	public TraceType<EventAccumulator>
+:	public StatType<EventAccumulator>
 {
 public:
 	typedef F64 storage_t;
-	typedef TraceType<EventAccumulator> trace_t;
+	typedef StatType<EventAccumulator> stat_t;
 	typedef EventStatHandle<T> self_t;
 
 	EventStatHandle(const char* name, const char* description = NULL)
-	:	trace_t(name, description)
+	:	stat_t(name, description)
 	{}
 
 	/*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
@@ -142,15 +140,15 @@ void record(EventStatHandle<T>& measurement, VALUE_T value)
 
 template <typename T = F64>
 class SampleStatHandle
-:	public TraceType<SampleAccumulator>
+:	public StatType<SampleAccumulator>
 {
 public:
 	typedef F64 storage_t;
-	typedef TraceType<SampleAccumulator> trace_t;
+	typedef StatType<SampleAccumulator> stat_t;
 	typedef SampleStatHandle<T> self_t;
 
 	SampleStatHandle(const char* name, const char* description = NULL)
-	:	trace_t(name, description)
+	:	stat_t(name, description)
 	{}
 
 	/*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
@@ -165,15 +163,15 @@ void sample(SampleStatHandle<T>& measurement, VALUE_T value)
 
 template <typename T = F64>
 class CountStatHandle
-:	public TraceType<CountAccumulator>
+:	public StatType<CountAccumulator>
 {
 public:
 	typedef F64 storage_t;
-	typedef TraceType<CountAccumulator> trace_t;
+	typedef StatType<CountAccumulator> stat_t;
 	typedef CountStatHandle<T> self_t;
 
 	CountStatHandle(const char* name, const char* description = NULL) 
-	:	trace_t(name, description)
+	:	stat_t(name, description)
 	{}
 
 	/*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
@@ -187,34 +185,36 @@ void add(CountStatHandle<T>& count, VALUE_T value)
 }
 
 template<>
-class TraceType<MemStatAccumulator::AllocationFacet>
-:	public TraceType<MemStatAccumulator>
+class StatType<MemAccumulator::AllocationFacet>
+:	public StatType<MemAccumulator>
 {
 public:
 
-	TraceType(const char* name, const char* description = "")
-	:	TraceType<MemStatAccumulator>(name, description)
+	StatType(const char* name, const char* description = "")
+	:	StatType<MemAccumulator>(name, description)
 	{}
 };
 
 template<>
-class TraceType<MemStatAccumulator::DeallocationFacet>
-:	public TraceType<MemStatAccumulator>
+class StatType<MemAccumulator::DeallocationFacet>
+:	public StatType<MemAccumulator>
 {
 public:
 
-	TraceType(const char* name, const char* description = "")
-	:	TraceType<MemStatAccumulator>(name, description)
+	StatType(const char* name, const char* description = "")
+	:	StatType<MemAccumulator>(name, description)
 	{}
 };
 
-class MemStatHandle : public TraceType<MemStatAccumulator>
+class MemStatHandle : public StatType<MemAccumulator>
 {
 public:
-	typedef TraceType<MemStatAccumulator> trace_t;
+	typedef StatType<MemAccumulator> stat_t;
 	MemStatHandle(const char* name)
-	:	trace_t(name)
-	{}
+	:	stat_t(name)
+	{
+		mName = name;
+	}
 
 	void setName(const char* name)
 	{
@@ -224,14 +224,14 @@ public:
 
 	/*virtual*/ const char* getUnitLabel() const { return "KB"; }
 
-	TraceType<MemStatAccumulator::AllocationFacet>& allocations() 
+	StatType<MemAccumulator::AllocationFacet>& allocations() 
 	{ 
-		return static_cast<TraceType<MemStatAccumulator::AllocationFacet>&>(*(TraceType<MemStatAccumulator>*)this);
+		return static_cast<StatType<MemAccumulator::AllocationFacet>&>(*(StatType<MemAccumulator>*)this);
 	}
 
-	TraceType<MemStatAccumulator::DeallocationFacet>& deallocations() 
+	StatType<MemAccumulator::DeallocationFacet>& deallocations() 
 	{ 
-		return static_cast<TraceType<MemStatAccumulator::DeallocationFacet>&>(*(TraceType<MemStatAccumulator>*)this);
+		return static_cast<StatType<MemAccumulator::DeallocationFacet>&>(*(StatType<MemAccumulator>*)this);
 	}
 };
 
@@ -324,7 +324,7 @@ inline void claim_alloc(MemStatHandle& measurement, const T& value)
 {
 	S32 size = MeasureMem<T>::measureFootprint(value);
 	if(size == 0) return;
-	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
+	MemAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 	accumulator.mAllocations.record(size);
 }
@@ -334,18 +334,18 @@ inline void disclaim_alloc(MemStatHandle& measurement, const T& value)
 {
 	S32 size = MeasureMem<T>::measureFootprint(value);
 	if(size == 0) return;
-	MemStatAccumulator& accumulator = measurement.getCurrentAccumulator();
+	MemAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 	accumulator.mDeallocations.add(size);
 }
 
 template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN>
-class MemTrackable
+class MemTrackableNonVirtual
 {
 public:
 	typedef void mem_trackable_tag_t;
 
-	MemTrackable(const char* name)
+	MemTrackableNonVirtual(const char* name)
 	:	mMemFootprint(0)
 	{
 		static bool name_initialized = false;
@@ -356,7 +356,7 @@ public:
 		}
 	}
 
-	virtual ~MemTrackable()
+	~MemTrackableNonVirtual()
 	{
 		disclaimMem(mMemFootprint);
 	}
@@ -374,12 +374,27 @@ public:
 		return ll_aligned_malloc(ALIGNMENT, size);
 	}
 
+	template<int CUSTOM_ALIGNMENT>
+	static void* aligned_new(size_t size)
+	{
+		claim_alloc(sMemStat, size);
+		return ll_aligned_malloc(CUSTOM_ALIGNMENT, size);
+	}
+
 	void operator delete(void* ptr, size_t size)
 	{
 		disclaim_alloc(sMemStat, size);
 		ll_aligned_free(ALIGNMENT, ptr);
 	}
 
+	template<int CUSTOM_ALIGNMENT>
+	static void aligned_delete(void* ptr, size_t size)
+	{
+		disclaim_alloc(sMemStat, size);
+		ll_aligned_free(CUSTOM_ALIGNMENT, ptr);
+	}
+
+
 	void* operator new [](size_t size)
 	{
 		claim_alloc(sMemStat, size);
@@ -420,7 +435,19 @@ private:
 };
 
 template<typename DERIVED, size_t ALIGNMENT>
-MemStatHandle MemTrackable<DERIVED, ALIGNMENT>::sMemStat("");
+MemStatHandle MemTrackableNonVirtual<DERIVED, ALIGNMENT>::sMemStat(typeid(MemTrackableNonVirtual<DERIVED, ALIGNMENT>).name());
 
+template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN>
+class MemTrackable : public MemTrackableNonVirtual<DERIVED, ALIGNMENT>
+{
+public:
+	MemTrackable(const char* name)
+	:	MemTrackableNonVirtual<DERIVED, ALIGNMENT>(name)
+	{}
+
+	virtual ~MemTrackable()
+	{}
+};
 }
+
 #endif // LL_LLTRACE_H
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index c25bb704f5..7d0e63e76a 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -45,7 +45,7 @@ AccumulatorBufferGroup::AccumulatorBufferGroup()
 	claim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator));
 	claim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator));
 	claim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator));
-	claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemStatAccumulator));
+	claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemAccumulator));
 }
 
 AccumulatorBufferGroup::AccumulatorBufferGroup(const AccumulatorBufferGroup& other)
@@ -59,7 +59,7 @@ AccumulatorBufferGroup::AccumulatorBufferGroup(const AccumulatorBufferGroup& oth
 	claim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator));
 	claim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator));
 	claim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator));
-	claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemStatAccumulator));
+	claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemAccumulator));
 }
 
 AccumulatorBufferGroup::~AccumulatorBufferGroup()
@@ -68,7 +68,7 @@ AccumulatorBufferGroup::~AccumulatorBufferGroup()
 	disclaim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator));
 	disclaim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator));
 	disclaim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator));
-	disclaim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemStatAccumulator));
+	disclaim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemAccumulator));
 }
 
 void AccumulatorBufferGroup::handOffTo(AccumulatorBufferGroup& other)
@@ -108,7 +108,7 @@ void AccumulatorBufferGroup::clearCurrent()
 	AccumulatorBuffer<SampleAccumulator>::clearCurrent();
 	AccumulatorBuffer<EventAccumulator>::clearCurrent();
 	AccumulatorBuffer<TimeBlockAccumulator>::clearCurrent();
-	AccumulatorBuffer<MemStatAccumulator>::clearCurrent();
+	AccumulatorBuffer<MemAccumulator>::clearCurrent();
 }
 
 bool AccumulatorBufferGroup::isCurrent() const
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 27c0910665..85873d469a 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -52,7 +52,7 @@ namespace LLTrace
 	class AccumulatorBuffer : public LLRefCount
 	{
 		typedef AccumulatorBuffer<ACCUMULATOR> self_t;
-		static const S32 ACCUMULATOR_BUFFER_SIZE_INCREMENT = 16;
+		static const S32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 32;
 	private:
 		struct StaticAllocationMarker { };
 
@@ -67,7 +67,7 @@ namespace LLTrace
 		:	mStorageSize(0),
 			mStorage(NULL)
 		{
-			resize(other.mStorageSize);
+			resize(sNextStorageSlot);
 			for (S32 i = 0; i < sNextStorageSlot; i++)
 			{
 				mStorage[i] = other.mStorage[i];
@@ -152,7 +152,7 @@ namespace LLTrace
 			{
 				// don't perform doubling, as this should only happen during startup
 				// want to keep a tight bounds as we will have a lot of these buffers
-				resize(mStorageSize + ACCUMULATOR_BUFFER_SIZE_INCREMENT);
+				resize(mStorageSize + mStorageSize / 2);
 			}
 			llassert(mStorage && next_slot < mStorageSize);
 			return next_slot;
@@ -207,7 +207,7 @@ namespace LLTrace
 				// so as not to trigger an access violation
 				sDefaultBuffer = new AccumulatorBuffer(StaticAllocationMarker());
 				sInitialized = true;
-				sDefaultBuffer->resize(ACCUMULATOR_BUFFER_SIZE_INCREMENT);
+				sDefaultBuffer->resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
 			}
 			return sDefaultBuffer;
 		}
@@ -491,9 +491,9 @@ namespace LLTrace
 		U64					mChildTime;
 	};
 
-	struct MemStatAccumulator
+	struct MemAccumulator
 	{
-		typedef MemStatAccumulator self_t;
+		typedef MemAccumulator self_t;
 
 		// fake classes that allows us to view different facets of underlying statistic
 		struct AllocationFacet 
@@ -506,7 +506,7 @@ namespace LLTrace
 			typedef F64Bytes value_t;
 		};
 
-		void addSamples(const MemStatAccumulator& other, EBufferAppendType append_type)
+		void addSamples(const MemAccumulator& other, EBufferAppendType append_type)
 		{
 			mAllocations.addSamples(other.mAllocations, append_type);
 			mDeallocations.addSamples(other.mDeallocations, append_type);
@@ -524,7 +524,7 @@ namespace LLTrace
 			}
 		}
 
-		void reset(const MemStatAccumulator* other)
+		void reset(const MemAccumulator* other)
 		{
 			mSize.reset(other ? &other->mSize : NULL);
 			mAllocations.reset(other ? &other->mAllocations : NULL);
@@ -561,7 +561,7 @@ namespace LLTrace
 		AccumulatorBuffer<SampleAccumulator>	mSamples;
 		AccumulatorBuffer<EventAccumulator>		mEvents;
 		AccumulatorBuffer<TimeBlockAccumulator> mStackTimers;
-		AccumulatorBuffer<MemStatAccumulator> 	mMemStats;
+		AccumulatorBuffer<MemAccumulator> 	mMemStats;
 	};
 }
 
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 06b4351339..87083eee96 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -137,26 +137,26 @@ void Recording::appendRecording( Recording& other )
 	mElapsedSeconds += other.mElapsedSeconds;
 }
 
-F64Seconds Recording::getSum(const TraceType<TimeBlockAccumulator>& stat)
+F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 	return F64Seconds((F64)(accumulator.mTotalTimeCounter) 
 				/ (F64)LLTrace::TimeBlock::countsPerSecond());
 }
 
-F64Seconds Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat)
+F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 	return F64Seconds((F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond());
 }
 
 
-S32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat)
+S32 Recording::getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
 {
 	return mBuffers->mStackTimers[stat.getIndex()].mCalls;
 }
 
-F64Seconds Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat)
+F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
@@ -164,7 +164,7 @@ F64Seconds Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat)
 				/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()));
 }
 
-F64Seconds Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat)
+F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
@@ -172,158 +172,158 @@ F64Seconds Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFa
 			/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()));
 }
 
-F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat)
+F32 Recording::getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
 {
 	return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds.value();
 }
 
-bool Recording::hasValue(const TraceType<MemStatAccumulator>& stat)
+bool Recording::hasValue(const StatType<MemAccumulator>& stat)
 {
 	return mBuffers->mMemStats[stat.getIndex()].mSize.hasValue();
 }
 
-F64Kilobytes Recording::getMin(const TraceType<MemStatAccumulator>& stat)
+F64Kilobytes Recording::getMin(const StatType<MemAccumulator>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMin());
 }
 
-F64Kilobytes Recording::getMean(const TraceType<MemStatAccumulator>& stat)
+F64Kilobytes Recording::getMean(const StatType<MemAccumulator>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMean());
 }
 
-F64Kilobytes Recording::getMax(const TraceType<MemStatAccumulator>& stat)
+F64Kilobytes Recording::getMax(const StatType<MemAccumulator>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMax());
 }
 
-F64Kilobytes Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat)
+F64Kilobytes Recording::getStandardDeviation(const StatType<MemAccumulator>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation());
 }
 
-F64Kilobytes Recording::getLastValue(const TraceType<MemStatAccumulator>& stat)
+F64Kilobytes Recording::getLastValue(const StatType<MemAccumulator>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue());
 }
 
-F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
+F64Kilobytes Recording::getSum(const StatType<MemAccumulator::AllocationFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocations.getSum());
 }
 
-F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
+F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::AllocationFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocations.getSum() / mElapsedSeconds.value());
 }
 
-S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::AllocationFacet>& stat)
+S32 Recording::getSampleCount(const StatType<MemAccumulator::AllocationFacet>& stat)
 {
 	return mBuffers->mMemStats[stat.getIndex()].mAllocations.getSampleCount();
 }
 
-F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
+F64Kilobytes Recording::getSum(const StatType<MemAccumulator::DeallocationFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSum());
 }
 
-F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
+F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::DeallocationFacet>& stat)
 {
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSum() / mElapsedSeconds.value());
 }
 
-S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::DeallocationFacet>& stat)
+S32 Recording::getSampleCount(const StatType<MemAccumulator::DeallocationFacet>& stat)
 {
 	return mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSampleCount();
 }
 
-F64 Recording::getSum( const TraceType<CountAccumulator>& stat )
+F64 Recording::getSum( const StatType<CountAccumulator>& stat )
 {
 	return mBuffers->mCounts[stat.getIndex()].getSum();
 }
 
-F64 Recording::getSum( const TraceType<EventAccumulator>& stat )
+F64 Recording::getSum( const StatType<EventAccumulator>& stat )
 {
 	return (F64)mBuffers->mEvents[stat.getIndex()].getSum();
 }
 
-F64 Recording::getPerSec( const TraceType<CountAccumulator>& stat )
+F64 Recording::getPerSec( const StatType<CountAccumulator>& stat )
 {
 	F64 sum = mBuffers->mCounts[stat.getIndex()].getSum();
 	return  sum / mElapsedSeconds.value();
 }
 
-S32 Recording::getSampleCount( const TraceType<CountAccumulator>& stat )
+S32 Recording::getSampleCount( const StatType<CountAccumulator>& stat )
 {
 	return mBuffers->mCounts[stat.getIndex()].getSampleCount();
 }
 
-bool Recording::hasValue(const TraceType<SampleAccumulator>& stat)
+bool Recording::hasValue(const StatType<SampleAccumulator>& stat)
 {
 	return mBuffers->mSamples[stat.getIndex()].hasValue();
 }
 
-F64 Recording::getMin( const TraceType<SampleAccumulator>& stat )
+F64 Recording::getMin( const StatType<SampleAccumulator>& stat )
 {
 	return mBuffers->mSamples[stat.getIndex()].getMin();
 }
 
-F64 Recording::getMax( const TraceType<SampleAccumulator>& stat )
+F64 Recording::getMax( const StatType<SampleAccumulator>& stat )
 {
 	return mBuffers->mSamples[stat.getIndex()].getMax();
 }
 
-F64 Recording::getMean( const TraceType<SampleAccumulator>& stat )
+F64 Recording::getMean( const StatType<SampleAccumulator>& stat )
 {
 	return mBuffers->mSamples[stat.getIndex()].getMean();
 }
 
-F64 Recording::getStandardDeviation( const TraceType<SampleAccumulator>& stat )
+F64 Recording::getStandardDeviation( const StatType<SampleAccumulator>& stat )
 {
 	return mBuffers->mSamples[stat.getIndex()].getStandardDeviation();
 }
 
-F64 Recording::getLastValue( const TraceType<SampleAccumulator>& stat )
+F64 Recording::getLastValue( const StatType<SampleAccumulator>& stat )
 {
 	return mBuffers->mSamples[stat.getIndex()].getLastValue();
 }
 
-S32 Recording::getSampleCount( const TraceType<SampleAccumulator>& stat )
+S32 Recording::getSampleCount( const StatType<SampleAccumulator>& stat )
 {
 	return mBuffers->mSamples[stat.getIndex()].getSampleCount();
 }
 
-bool Recording::hasValue(const TraceType<EventAccumulator>& stat)
+bool Recording::hasValue(const StatType<EventAccumulator>& stat)
 {
 	return mBuffers->mEvents[stat.getIndex()].hasValue();
 }
 
-F64 Recording::getMin( const TraceType<EventAccumulator>& stat )
+F64 Recording::getMin( const StatType<EventAccumulator>& stat )
 {
 	return mBuffers->mEvents[stat.getIndex()].getMin();
 }
 
-F64 Recording::getMax( const TraceType<EventAccumulator>& stat )
+F64 Recording::getMax( const StatType<EventAccumulator>& stat )
 {
 	return mBuffers->mEvents[stat.getIndex()].getMax();
 }
 
-F64 Recording::getMean( const TraceType<EventAccumulator>& stat )
+F64 Recording::getMean( const StatType<EventAccumulator>& stat )
 {
 	return mBuffers->mEvents[stat.getIndex()].getMean();
 }
 
-F64 Recording::getStandardDeviation( const TraceType<EventAccumulator>& stat )
+F64 Recording::getStandardDeviation( const StatType<EventAccumulator>& stat )
 {
 	return mBuffers->mEvents[stat.getIndex()].getStandardDeviation();
 }
 
-F64 Recording::getLastValue( const TraceType<EventAccumulator>& stat )
+F64 Recording::getLastValue( const StatType<EventAccumulator>& stat )
 {
 	return mBuffers->mEvents[stat.getIndex()].getLastValue();
 }
 
-S32 Recording::getSampleCount( const TraceType<EventAccumulator>& stat )
+S32 Recording::getSampleCount( const StatType<EventAccumulator>& stat )
 {
 	return mBuffers->mEvents[stat.getIndex()].getSampleCount();
 }
@@ -534,7 +534,7 @@ void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
 	getCurRecording().splitTo(other.getCurRecording());
 }
 
-F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
 	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -556,7 +556,7 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, S3
 			: NaN;
 }
 
-F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
 	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -579,7 +579,7 @@ F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, S3
 }
 
 // calculates means using aggregates per period
-F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
 	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -603,7 +603,7 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, S
 }
 
 
-F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
 	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -628,7 +628,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<EventAccumula
 			: NaN;
 }
 
-F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
 	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -650,7 +650,7 @@ F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, S
 			: NaN;
 }
 
-F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/)
+F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/)
 {
 	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -673,7 +673,7 @@ F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, S3
 }
 
 
-F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
 	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -696,7 +696,7 @@ F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat,
 			: NaN;
 }
 
-F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
 	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -722,7 +722,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const TraceType<SampleAccumul
 }
 
 
-F64Kilobytes PeriodicRecording::getPeriodMin( const TraceType<MemStatAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64Kilobytes PeriodicRecording::getPeriodMin( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
 	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -739,10 +739,10 @@ F64Kilobytes PeriodicRecording::getPeriodMin( const TraceType<MemStatAccumulator
 
 F64Kilobytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, S32 num_periods)
 {
-	return getPeriodMin(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
+	return getPeriodMin(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
 }
 
-F64Kilobytes PeriodicRecording::getPeriodMax(const TraceType<MemStatAccumulator>& stat, S32 num_periods /*= S32_MAX*/)
+F64Kilobytes PeriodicRecording::getPeriodMax(const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/)
 {
 	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -759,10 +759,10 @@ F64Kilobytes PeriodicRecording::getPeriodMax(const TraceType<MemStatAccumulator>
 
 F64Kilobytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, S32 num_periods)
 {
-	return getPeriodMax(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
+	return getPeriodMax(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
 }
 
-F64Kilobytes PeriodicRecording::getPeriodMean( const TraceType<MemStatAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64Kilobytes PeriodicRecording::getPeriodMean( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
 	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -780,10 +780,10 @@ F64Kilobytes PeriodicRecording::getPeriodMean( const TraceType<MemStatAccumulato
 
 F64Kilobytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, S32 num_periods)
 {
-	return getPeriodMean(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
+	return getPeriodMean(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
 }
 
-F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const TraceType<MemStatAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
 	S32 total_periods = mRecordingPeriods.size();
 	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -810,7 +810,7 @@ F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const TraceType<MemS
 
 F64Kilobytes PeriodicRecording::getPeriodStandardDeviation(const MemStatHandle& stat, S32 num_periods)
 {
-	return getPeriodStandardDeviation(static_cast<const TraceType<MemStatAccumulator>&>(stat), num_periods);
+	return getPeriodStandardDeviation(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
 }
 
 ///////////////////////////////////////////////////////////////////////
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 8bb0b1892f..810f796666 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -113,7 +113,7 @@ private:
 namespace LLTrace
 {
 	template<typename T>
-	class TraceType;
+	class StatType;
 
 	template<typename T>
 	class CountStatHandle;
@@ -168,135 +168,135 @@ namespace LLTrace
 		void makeUnique() { mBuffers.makeUnique(); }
 
 		// Timer accessors
-		F64Seconds getSum(const TraceType<TimeBlockAccumulator>& stat);
-		F64Seconds getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat);
-		S32 getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat);
+		F64Seconds getSum(const StatType<TimeBlockAccumulator>& stat);
+		F64Seconds getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat);
+		S32 getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat);
 
-		F64Seconds getPerSec(const TraceType<TimeBlockAccumulator>& stat);
-		F64Seconds getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat);
-		F32 getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat);
+		F64Seconds getPerSec(const StatType<TimeBlockAccumulator>& stat);
+		F64Seconds getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat);
+		F32 getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat);
 
 		// Memory accessors
-		bool hasValue(const TraceType<MemStatAccumulator>& stat);
+		bool hasValue(const StatType<MemAccumulator>& stat);
 
-		F64Kilobytes getMin(const TraceType<MemStatAccumulator>& stat);
-		F64Kilobytes getMean(const TraceType<MemStatAccumulator>& stat);
-		F64Kilobytes getMax(const TraceType<MemStatAccumulator>& stat);
-		F64Kilobytes getStandardDeviation(const TraceType<MemStatAccumulator>& stat);
-		F64Kilobytes getLastValue(const TraceType<MemStatAccumulator>& stat);
+		F64Kilobytes getMin(const StatType<MemAccumulator>& stat);
+		F64Kilobytes getMean(const StatType<MemAccumulator>& stat);
+		F64Kilobytes getMax(const StatType<MemAccumulator>& stat);
+		F64Kilobytes getStandardDeviation(const StatType<MemAccumulator>& stat);
+		F64Kilobytes getLastValue(const StatType<MemAccumulator>& stat);
 
-		F64Kilobytes getSum(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
-		F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
-		S32 getSampleCount(const TraceType<MemStatAccumulator::AllocationFacet>& stat);
+		F64Kilobytes getSum(const StatType<MemAccumulator::AllocationFacet>& stat);
+		F64Kilobytes getPerSec(const StatType<MemAccumulator::AllocationFacet>& stat);
+		S32 getSampleCount(const StatType<MemAccumulator::AllocationFacet>& stat);
 
-		F64Kilobytes getSum(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
-		F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
-		S32 getSampleCount(const TraceType<MemStatAccumulator::DeallocationFacet>& stat);
+		F64Kilobytes getSum(const StatType<MemAccumulator::DeallocationFacet>& stat);
+		F64Kilobytes getPerSec(const StatType<MemAccumulator::DeallocationFacet>& stat);
+		S32 getSampleCount(const StatType<MemAccumulator::DeallocationFacet>& stat);
 
 		// CountStatHandle accessors
-		F64 getSum(const TraceType<CountAccumulator>& stat);
+		F64 getSum(const StatType<CountAccumulator>& stat);
 		template <typename T>
 		typename RelatedTypes<T>::sum_t getSum(const CountStatHandle<T>& stat)
 		{
-			return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const TraceType<CountAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const StatType<CountAccumulator>&> (stat));
 		}
 
-		F64 getPerSec(const TraceType<CountAccumulator>& stat);
+		F64 getPerSec(const StatType<CountAccumulator>& stat);
 		template <typename T>
 		typename RelatedTypes<T>::fractional_t getPerSec(const CountStatHandle<T>& stat)
 		{
-			return (typename RelatedTypes<T>::fractional_t)getPerSec(static_cast<const TraceType<CountAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::fractional_t)getPerSec(static_cast<const StatType<CountAccumulator>&> (stat));
 		}
 
-		S32 getSampleCount(const TraceType<CountAccumulator>& stat);
+		S32 getSampleCount(const StatType<CountAccumulator>& stat);
 
 
 		// SampleStatHandle accessors
-		bool hasValue(const TraceType<SampleAccumulator>& stat);
+		bool hasValue(const StatType<SampleAccumulator>& stat);
 
-		F64 getMin(const TraceType<SampleAccumulator>& stat);
+		F64 getMin(const StatType<SampleAccumulator>& stat);
 		template <typename T>
 		T getMin(const SampleStatHandle<T>& stat)
 		{
-			return (T)getMin(static_cast<const TraceType<SampleAccumulator>&> (stat));
+			return (T)getMin(static_cast<const StatType<SampleAccumulator>&> (stat));
 		}
 
-		F64 getMax(const TraceType<SampleAccumulator>& stat);
+		F64 getMax(const StatType<SampleAccumulator>& stat);
 		template <typename T>
 		T getMax(const SampleStatHandle<T>& stat)
 		{
-			return (T)getMax(static_cast<const TraceType<SampleAccumulator>&> (stat));
+			return (T)getMax(static_cast<const StatType<SampleAccumulator>&> (stat));
 		}
 
-		F64 getMean(const TraceType<SampleAccumulator>& stat);
+		F64 getMean(const StatType<SampleAccumulator>& stat);
 		template <typename T>
 		typename RelatedTypes<T>::fractional_t getMean(SampleStatHandle<T>& stat)
 		{
-			return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const TraceType<SampleAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const StatType<SampleAccumulator>&> (stat));
 		}
 
-		F64 getStandardDeviation(const TraceType<SampleAccumulator>& stat);
+		F64 getStandardDeviation(const StatType<SampleAccumulator>& stat);
 		template <typename T>
 		typename RelatedTypes<T>::fractional_t getStandardDeviation(const SampleStatHandle<T>& stat)
 		{
-			return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const TraceType<SampleAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const StatType<SampleAccumulator>&> (stat));
 		}
 
-		F64 getLastValue(const TraceType<SampleAccumulator>& stat);
+		F64 getLastValue(const StatType<SampleAccumulator>& stat);
 		template <typename T>
 		T getLastValue(const SampleStatHandle<T>& stat)
 		{
-			return (T)getLastValue(static_cast<const TraceType<SampleAccumulator>&> (stat));
+			return (T)getLastValue(static_cast<const StatType<SampleAccumulator>&> (stat));
 		}
 
-		S32 getSampleCount(const TraceType<SampleAccumulator>& stat);
+		S32 getSampleCount(const StatType<SampleAccumulator>& stat);
 
 		// EventStatHandle accessors
-		bool hasValue(const TraceType<EventAccumulator>& stat);
+		bool hasValue(const StatType<EventAccumulator>& stat);
 
-		F64 getSum(const TraceType<EventAccumulator>& stat);
+		F64 getSum(const StatType<EventAccumulator>& stat);
 		template <typename T>
 		typename RelatedTypes<T>::sum_t getSum(const EventStatHandle<T>& stat)
 		{
-			return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const TraceType<EventAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const StatType<EventAccumulator>&> (stat));
 		}
 
-		F64 getMin(const TraceType<EventAccumulator>& stat);
+		F64 getMin(const StatType<EventAccumulator>& stat);
 		template <typename T>
 		T getMin(const EventStatHandle<T>& stat)
 		{
-			return (T)getMin(static_cast<const TraceType<EventAccumulator>&> (stat));
+			return (T)getMin(static_cast<const StatType<EventAccumulator>&> (stat));
 		}
 
-		F64 getMax(const TraceType<EventAccumulator>& stat);
+		F64 getMax(const StatType<EventAccumulator>& stat);
 		template <typename T>
 		T getMax(const EventStatHandle<T>& stat)
 		{
-			return (T)getMax(static_cast<const TraceType<EventAccumulator>&> (stat));
+			return (T)getMax(static_cast<const StatType<EventAccumulator>&> (stat));
 		}
 
-		F64 getMean(const TraceType<EventAccumulator>& stat);
+		F64 getMean(const StatType<EventAccumulator>& stat);
 		template <typename T>
 		typename RelatedTypes<T>::fractional_t getMean(EventStatHandle<T>& stat)
 		{
-			return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const TraceType<EventAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const StatType<EventAccumulator>&> (stat));
 		}
 
-		F64 getStandardDeviation(const TraceType<EventAccumulator>& stat);
+		F64 getStandardDeviation(const StatType<EventAccumulator>& stat);
 		template <typename T>
 		typename RelatedTypes<T>::fractional_t getStandardDeviation(const EventStatHandle<T>& stat)
 		{
-			return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const TraceType<EventAccumulator>&> (stat));
+			return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const StatType<EventAccumulator>&> (stat));
 		}
 
-		F64 getLastValue(const TraceType<EventAccumulator>& stat);
+		F64 getLastValue(const StatType<EventAccumulator>& stat);
 		template <typename T>
 		T getLastValue(const EventStatHandle<T>& stat)
 		{
-			return (T)getLastValue(static_cast<const TraceType<EventAccumulator>&> (stat));
+			return (T)getLastValue(static_cast<const StatType<EventAccumulator>&> (stat));
 		}
 
-		S32 getSampleCount(const TraceType<EventAccumulator>& stat);
+		S32 getSampleCount(const StatType<EventAccumulator>& stat);
 
 		F64Seconds getDuration() const { return mElapsedSeconds; }
 
@@ -342,7 +342,7 @@ namespace LLTrace
 		Recording snapshotCurRecording() const;
 
 		template <typename T>
-		S32 getSampleCount(const TraceType<T>& stat, S32 num_periods = S32_MAX)
+		S32 getSampleCount(const StatType<T>& stat, S32 num_periods = S32_MAX)
         {
 			S32 total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -362,7 +362,7 @@ namespace LLTrace
 
 		// catch all for stats that have a defined sum
 		template <typename T>
-		typename T::value_t getPeriodMin(const TraceType<T>& stat, S32 num_periods = S32_MAX)
+		typename T::value_t getPeriodMin(const StatType<T>& stat, S32 num_periods = S32_MAX)
 		{
 			S32 total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -379,28 +379,28 @@ namespace LLTrace
 		template<typename T>
 		T getPeriodMin(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
-			return T(getPeriodMin(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
+			return T(getPeriodMin(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
 		}
 
-		F64 getPeriodMin(const TraceType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64 getPeriodMin(const StatType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
 		template<typename T>
 		T getPeriodMin(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
-			return T(getPeriodMin(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods));
+			return T(getPeriodMin(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
 		}
 
-		F64 getPeriodMin(const TraceType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64 getPeriodMin(const StatType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
 		template<typename T>
 		T getPeriodMin(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
-			return T(getPeriodMin(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
+			return T(getPeriodMin(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
 		}
 
-		F64Kilobytes getPeriodMin(const TraceType<MemStatAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64Kilobytes getPeriodMin(const StatType<MemAccumulator>& stat, S32 num_periods = S32_MAX);
 		F64Kilobytes getPeriodMin(const MemStatHandle& stat, S32 num_periods = S32_MAX);
 
 		template <typename T>
-		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const TraceType<T>& stat, S32 num_periods = S32_MAX)
+		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX)
 		{
 			S32 total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -417,7 +417,7 @@ namespace LLTrace
 		template<typename T>
 		typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
-			return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
+			return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
 		}
 
 		//
@@ -426,7 +426,7 @@ namespace LLTrace
 
 		// catch all for stats that have a defined sum
 		template <typename T>
-		typename T::value_t getPeriodMax(const TraceType<T>& stat, S32 num_periods = S32_MAX)
+		typename T::value_t getPeriodMax(const StatType<T>& stat, S32 num_periods = S32_MAX)
 		{
 			S32 total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -443,28 +443,28 @@ namespace LLTrace
 		template<typename T>
 		T getPeriodMax(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
-			return T(getPeriodMax(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
+			return T(getPeriodMax(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
 		}
 
-		F64 getPeriodMax(const TraceType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64 getPeriodMax(const StatType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
 		template<typename T>
 		T getPeriodMax(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
-			return T(getPeriodMax(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods));
+			return T(getPeriodMax(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
 		}
 
-		F64 getPeriodMax(const TraceType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64 getPeriodMax(const StatType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
 		template<typename T>
 		T getPeriodMax(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
-			return T(getPeriodMax(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
+			return T(getPeriodMax(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
 		}
 
-		F64Kilobytes getPeriodMax(const TraceType<MemStatAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64Kilobytes getPeriodMax(const StatType<MemAccumulator>& stat, S32 num_periods = S32_MAX);
 		F64Kilobytes getPeriodMax(const MemStatHandle& stat, S32 num_periods = S32_MAX);
 
 		template <typename T>
-		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const TraceType<T>& stat, S32 num_periods = S32_MAX)
+		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX)
 		{
 			S32 total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -481,7 +481,7 @@ namespace LLTrace
 		template<typename T>
 		typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
-			return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
+			return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
 		}
 
 		//
@@ -490,7 +490,7 @@ namespace LLTrace
 
 		// catch all for stats that have a defined sum
 		template <typename T>
-		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const TraceType<T >& stat, S32 num_periods = S32_MAX)
+		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, S32 num_periods = S32_MAX)
 		{
 			S32 total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -513,27 +513,27 @@ namespace LLTrace
 		template<typename T>
 		typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
-			return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
+			return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
 		}
-		F64 getPeriodMean(const TraceType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64 getPeriodMean(const StatType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
 		template<typename T> 
 		typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
-			return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods));
+			return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
 		}
 
-		F64 getPeriodMean(const TraceType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64 getPeriodMean(const StatType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
 		template<typename T>
 		typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
-			return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
+			return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
 		}
 
-		F64Kilobytes getPeriodMean(const TraceType<MemStatAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64Kilobytes getPeriodMean(const StatType<MemAccumulator>& stat, S32 num_periods = S32_MAX);
 		F64Kilobytes getPeriodMean(const MemStatHandle& stat, S32 num_periods = S32_MAX);
 		
 		template <typename T>
-		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const TraceType<T>& stat, S32 num_periods = S32_MAX)
+		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX)
 		{
 			S32 total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
@@ -557,29 +557,29 @@ namespace LLTrace
 		template<typename T>
 		typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
-			return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const TraceType<CountAccumulator>&>(stat), num_periods));
+			return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
 		}
 
 		//
 		// PERIODIC STANDARD DEVIATION
 		//
 
-		F64 getPeriodStandardDeviation(const TraceType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64 getPeriodStandardDeviation(const StatType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
 
 		template<typename T> 
 		typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
-			return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods));
+			return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
 		}
 
-		F64 getPeriodStandardDeviation(const TraceType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64 getPeriodStandardDeviation(const StatType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
 		template<typename T>
 		typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
 		{
-			return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods));
+			return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
 		}
 
-		F64Kilobytes getPeriodStandardDeviation(const TraceType<MemStatAccumulator>& stat, S32 num_periods = S32_MAX);
+		F64Kilobytes getPeriodStandardDeviation(const StatType<MemAccumulator>& stat, S32 num_periods = S32_MAX);
 		F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, S32 num_periods = S32_MAX);
 
 	private:
-- 
cgit v1.2.3


From 7f67e1d4a42037a902a547aef845b46c38f33f2a Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 11 Oct 2013 10:42:32 -0700
Subject: fixed legacy usage of llendl

---
 indra/llcommon/llthread.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 3f2127762e..cbf78bb363 100755
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -109,7 +109,7 @@ LL_COMMON_API void assert_main_thread()
 	if (LLThread::currentID() != s_thread_id)
 	{
 		LL_WARNS() << "Illegal execution from thread id " << (S32) LLThread::currentID()
-			<< " outside main thread " << (S32) s_thread_id << llendl;
+			<< " outside main thread " << (S32) s_thread_id << LL_ENDL;
 	}
 }
 
-- 
cgit v1.2.3


From 1acceb3633c0f0c4fdf29b17d77d67c8a9b71986 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 14 Oct 2013 10:18:41 -0700
Subject: changed ll_aligned_(malloc|free) to take alignment size as a template
 argument

---
 indra/llcommon/llalignedarray.h      | 10 +++++-----
 indra/llcommon/llmemory.h            | 20 +++++++++++---------
 indra/llcommon/lltrace.h             | 12 ++++++------
 indra/llcommon/lltraceaccumulators.h |  4 ++--
 4 files changed, 24 insertions(+), 22 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llalignedarray.h b/indra/llcommon/llalignedarray.h
index 6f18bfe25c..b68e9e0f82 100644
--- a/indra/llcommon/llalignedarray.h
+++ b/indra/llcommon/llalignedarray.h
@@ -60,7 +60,7 @@ LLAlignedArray<T, alignment>::LLAlignedArray()
 template <class T, U32 alignment>
 LLAlignedArray<T, alignment>::~LLAlignedArray()
 {
-	ll_aligned_free(alignment, mArray);
+	ll_aligned_free<alignment>(mArray);
 	mArray = NULL;
 	mElementCount = 0;
 	mCapacity = 0;
@@ -74,7 +74,7 @@ void LLAlignedArray<T, alignment>::push_back(const T& elem)
 	{
 		mCapacity++;
 		mCapacity *= 2;
-		T* new_buf = (T*) ll_aligned_malloc(alignment, mCapacity*sizeof(T));
+		T* new_buf = (T*) ll_aligned_malloc<alignment>(mCapacity*sizeof(T));
 		if (mArray)
 		{
 			ll_memcpy_nonaliased_aligned_16((char*)new_buf, (char*)mArray, sizeof(T)*mElementCount);
@@ -86,7 +86,7 @@ void LLAlignedArray<T, alignment>::push_back(const T& elem)
 	mArray[mElementCount++] = elem;
 
 	//delete old array here to prevent error on a.push_back(a[0])
-	ll_aligned_free(alignment, old_buf);
+	ll_aligned_free<alignment>(old_buf);
 }
 
 template <class T, U32 alignment>
@@ -95,11 +95,11 @@ void LLAlignedArray<T, alignment>::resize(U32 size)
 	if (mCapacity < size)
 	{
 		mCapacity = size+mCapacity*2;
-		T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc(alignment, mCapacity*sizeof(T)) : NULL;
+		T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc<alignment>(mCapacity*sizeof(T)) : NULL;
 		if (mArray)
 		{
 			ll_memcpy_nonaliased_aligned_16((char*) new_buf, (char*) mArray, sizeof(T)*mElementCount);
-			ll_aligned_free(alignment, mArray);
+			ll_aligned_free<alignment>(mArray);
 		}
 
 		/*for (U32 i = mElementCount; i < mCapacity; ++i)
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 5ed4ea7d9e..3de59350db 100755
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -204,37 +204,39 @@ inline void ll_aligned_free_32(void *p)
 }
 
 // general purpose dispatch functions that are forced inline so they can compile down to a single call
-LL_FORCE_INLINE void* ll_aligned_malloc(size_t alignment, size_t size)
+template<size_t ALIGNMENT>
+LL_FORCE_INLINE void* ll_aligned_malloc(size_t size)
 {
-	if (LL_DEFAULT_HEAP_ALIGN % alignment == 0)
+	if (LL_DEFAULT_HEAP_ALIGN % ALIGNMENT == 0)
 	{
 		return malloc(size);
 	}
-	else if (alignment == 16)
+	else if (ALIGNMENT == 16)
 	{
 		return ll_aligned_malloc_16(size);
 	}
-	else if (alignment == 32)
+	else if (ALIGNMENT == 32)
 	{
 		return ll_aligned_malloc_32(size);
 	}
 	else
 	{
-		return ll_aligned_malloc_fallback(size, alignment);
+		return ll_aligned_malloc_fallback(size, ALIGNMENT);
 	}
 }
 
-LL_FORCE_INLINE void ll_aligned_free(size_t alignment, void* ptr)
+template<size_t ALIGNMENT>
+LL_FORCE_INLINE void ll_aligned_free(void* ptr)
 {
-	if (alignment == LL_DEFAULT_HEAP_ALIGN)
+	if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
 	{
 		free(ptr);
 	}
-	else if (alignment == 16)
+	else if (ALIGNMENT == 16)
 	{
 		ll_aligned_free_16(ptr);
 	}
-	else if (alignment == 32)
+	else if (ALIGNMENT == 32)
 	{
 		return ll_aligned_free_32(ptr);
 	}
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 325112b9b1..2f4390e4d1 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -371,40 +371,40 @@ public:
 	void* operator new(size_t size) 
 	{
 		claim_alloc(sMemStat, size);
-		return ll_aligned_malloc(ALIGNMENT, size);
+		return ll_aligned_malloc<ALIGNMENT>(size);
 	}
 
 	template<int CUSTOM_ALIGNMENT>
 	static void* aligned_new(size_t size)
 	{
 		claim_alloc(sMemStat, size);
-		return ll_aligned_malloc(CUSTOM_ALIGNMENT, size);
+		return ll_aligned_malloc<CUSTOM_ALIGNMENT>(size);
 	}
 
 	void operator delete(void* ptr, size_t size)
 	{
 		disclaim_alloc(sMemStat, size);
-		ll_aligned_free(ALIGNMENT, ptr);
+		ll_aligned_free<ALIGNMENT>(ptr);
 	}
 
 	template<int CUSTOM_ALIGNMENT>
 	static void aligned_delete(void* ptr, size_t size)
 	{
 		disclaim_alloc(sMemStat, size);
-		ll_aligned_free(CUSTOM_ALIGNMENT, ptr);
+		ll_aligned_free<CUSTOM_ALIGNMENT>(ptr);
 	}
 
 
 	void* operator new [](size_t size)
 	{
 		claim_alloc(sMemStat, size);
-		return ll_aligned_malloc(ALIGNMENT, size);
+		return ll_aligned_malloc<ALIGNMENT>(size);
 	}
 
 	void operator delete[](void* ptr, size_t size)
 	{
 		disclaim_alloc(sMemStat, size);
-		ll_aligned_free(ALIGNMENT, ptr);
+		ll_aligned_free<ALIGNMENT>(ptr);
 	}
 
 	// claim memory associated with other objects/data as our own, adding to our calculated footprint
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 85873d469a..77370629d3 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -441,12 +441,12 @@ namespace LLTrace
 		// arrays are allocated with 32 byte alignment
 		void *operator new [](size_t size)
 		{
-			return ll_aligned_malloc(32, size);
+			return ll_aligned_malloc<32>(size);
 		}
 
 		void operator delete[](void* ptr, size_t size)
 		{
-			ll_aligned_free(32, ptr);
+			ll_aligned_free<32>(ptr);
 		}
 
 		TimeBlockAccumulator();
-- 
cgit v1.2.3


From 697d2e720ba75e142a4d56ae8794bab8d7698dad Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 15 Oct 2013 20:24:42 -0700
Subject: renamed TimeBlock to BlockTimerStatHandle

---
 indra/llcommon/lldate.cpp                    |   2 +-
 indra/llcommon/llfasttimer.cpp               | 104 +++++++++++++--------------
 indra/llcommon/llfasttimer.h                 |  54 +++++++-------
 indra/llcommon/llmetricperformancetester.cpp |   4 +-
 indra/llcommon/llsdparam.cpp                 |   2 +-
 indra/llcommon/llsdparam.h                   |   2 +-
 indra/llcommon/llstring.cpp                  |   2 +-
 indra/llcommon/lltrace.cpp                   |   6 +-
 indra/llcommon/lltrace.h                     |   6 +-
 indra/llcommon/lltraceaccumulators.h         |  18 ++---
 indra/llcommon/lltracerecording.cpp          |  44 ++++++++++--
 indra/llcommon/lltracethreadrecorder.cpp     |  14 ++--
 12 files changed, 146 insertions(+), 112 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp
index b32c3f6830..7a2a0869f4 100755
--- a/indra/llcommon/lldate.cpp
+++ b/indra/llcommon/lldate.cpp
@@ -86,7 +86,7 @@ std::string LLDate::asRFC1123() const
 	return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT"));
 }
 
-LLTrace::TimeBlock FT_DATE_FORMAT("Date Format");
+LLTrace::BlockTimerStatHandle FT_DATE_FORMAT("Date Format");
 
 std::string LLDate::toHTTPDateString (std::string fmt) const
 {
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index c948e0ac85..361d800629 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -60,14 +60,14 @@ namespace LLTrace
 //////////////////////////////////////////////////////////////////////////////
 // statics
 
-bool        TimeBlock::sLog		     = false;
-std::string TimeBlock::sLogName         = "";
-bool        TimeBlock::sMetricLog       = false;
+bool        BlockTimerStatHandle::sLog		     = false;
+std::string BlockTimerStatHandle::sLogName         = "";
+bool        BlockTimerStatHandle::sMetricLog       = false;
 
 #if LL_LINUX || LL_SOLARIS
-U64         TimeBlock::sClockResolution = 1000000000; // Nanosecond resolution
+U64         BlockTimerStatHandle::sClockResolution = 1000000000; // Nanosecond resolution
 #else
-U64         TimeBlock::sClockResolution = 1000000; // Microsecond resolution
+U64         BlockTimerStatHandle::sClockResolution = 1000000; // Microsecond resolution
 #endif
 
 static LLMutex*			sLogLock = NULL;
@@ -77,13 +77,13 @@ static std::queue<LLSD> sLogQueue;
 // FIXME: move these declarations to the relevant modules
 
 // helper functions
-typedef LLTreeDFSPostIter<TimeBlock, TimeBlock::child_const_iter> timer_tree_bottom_up_iterator_t;
+typedef LLTreeDFSPostIter<BlockTimerStatHandle, BlockTimerStatHandle::child_const_iter> timer_tree_bottom_up_iterator_t;
 
-static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(TimeBlock& id) 
+static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(BlockTimerStatHandle& id) 
 { 
 	return timer_tree_bottom_up_iterator_t(&id, 
-							boost::bind(boost::mem_fn(&TimeBlock::beginChildren), _1), 
-							boost::bind(boost::mem_fn(&TimeBlock::endChildren), _1));
+							boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1), 
+							boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
 }
 
 static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up() 
@@ -91,14 +91,14 @@ static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up()
 	return timer_tree_bottom_up_iterator_t(); 
 }
 
-typedef LLTreeDFSIter<TimeBlock, TimeBlock::child_const_iter> timer_tree_dfs_iterator_t;
+typedef LLTreeDFSIter<BlockTimerStatHandle, BlockTimerStatHandle::child_const_iter> timer_tree_dfs_iterator_t;
 
 
-static timer_tree_dfs_iterator_t begin_timer_tree(TimeBlock& id) 
+static timer_tree_dfs_iterator_t begin_timer_tree(BlockTimerStatHandle& id) 
 { 
 	return timer_tree_dfs_iterator_t(&id, 
-		boost::bind(boost::mem_fn(&TimeBlock::beginChildren), _1), 
-							boost::bind(boost::mem_fn(&TimeBlock::endChildren), _1));
+		boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1), 
+							boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
 }
 
 static timer_tree_dfs_iterator_t end_timer_tree() 
@@ -110,26 +110,26 @@ static timer_tree_dfs_iterator_t end_timer_tree()
 // sort child timers by name
 struct SortTimerByName
 {
-	bool operator()(const TimeBlock* i1, const TimeBlock* i2)
+	bool operator()(const BlockTimerStatHandle* i1, const BlockTimerStatHandle* i2)
         {
 		return i1->getName() < i2->getName();
         }
 };
 
-TimeBlock& TimeBlock::getRootTimeBlock()
+BlockTimerStatHandle& BlockTimerStatHandle::getRootTimeBlock()
 {
-	static TimeBlock root_timer("root", NULL);
+	static BlockTimerStatHandle root_timer("root", NULL);
 	return root_timer;
 }
 
-void TimeBlock::pushLog(LLSD log)
+void BlockTimerStatHandle::pushLog(LLSD log)
 {
 	LLMutexLock lock(sLogLock);
 
 	sLogQueue.push(log);
 }
 
-void TimeBlock::setLogLock(LLMutex* lock)
+void BlockTimerStatHandle::setLogLock(LLMutex* lock)
 {
 	sLogLock = lock;
 }
@@ -137,12 +137,12 @@ void TimeBlock::setLogLock(LLMutex* lock)
 
 //static
 #if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
-U64 TimeBlock::countsPerSecond()
+U64 BlockTimerStatHandle::countsPerSecond()
 {
 	return sClockResolution;
 }
 #else // windows or x86-mac or x86-linux or x86-solaris
-U64 TimeBlock::countsPerSecond()
+U64 BlockTimerStatHandle::countsPerSecond()
 {
 #if LL_FASTTIMER_USE_RDTSC || !LL_WINDOWS
 	//getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz
@@ -164,11 +164,11 @@ U64 TimeBlock::countsPerSecond()
 }
 #endif
 
-TimeBlock::TimeBlock(const char* name, TimeBlock* parent)
-:	StatType<TimeBlockAccumulator>(name)
+BlockTimerStatHandle::BlockTimerStatHandle(const char* name, const char* description)
+:	StatType<TimeBlockAccumulator>(name, description)
 {}
 
-TimeBlockTreeNode& TimeBlock::getTreeNode() const
+TimeBlockTreeNode& BlockTimerStatHandle::getTreeNode() const
 {
 	TimeBlockTreeNode* nodep = LLTrace::get_thread_recorder()->getTimeBlockTreeNode(getIndex());
 	llassert(nodep);
@@ -176,18 +176,18 @@ TimeBlockTreeNode& TimeBlock::getTreeNode() const
 }
 
 
-void TimeBlock::bootstrapTimerTree()
+void BlockTimerStatHandle::bootstrapTimerTree()
 {
-	for (LLInstanceTracker<TimeBlock>::instance_iter begin_it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(), it = begin_it; 
+	for (BlockTimerStatHandle::instance_tracker_t::instance_iter begin_it = BlockTimerStatHandle::instance_tracker_t::beginInstances(), end_it = BlockTimerStatHandle::instance_tracker_t::endInstances(), it = begin_it; 
 		it != end_it; 
 		++it)
 	{
-		TimeBlock& timer = *it;
-		if (&timer == &TimeBlock::getRootTimeBlock()) continue;
+		BlockTimerStatHandle& timer = static_cast<BlockTimerStatHandle&>(*it);
+		if (&timer == &BlockTimerStatHandle::getRootTimeBlock()) continue;
 
 		// bootstrap tree construction by attaching to last timer to be on stack
 		// when this timer was called
-		if (timer.getParent() == &TimeBlock::getRootTimeBlock())
+		if (timer.getParent() == &BlockTimerStatHandle::getRootTimeBlock())
 		{
 			TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
 
@@ -205,13 +205,13 @@ void TimeBlock::bootstrapTimerTree()
 // bump timers up tree if they have 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
-void TimeBlock::incrementalUpdateTimerTree()
+void BlockTimerStatHandle::incrementalUpdateTimerTree()
 {
-	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(TimeBlock::getRootTimeBlock());
+	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(BlockTimerStatHandle::getRootTimeBlock());
 		it != end_timer_tree_bottom_up();
 		++it)
 	{
-		TimeBlock* timerp = *it;
+		BlockTimerStatHandle* timerp = *it;
 
 		// sort timers by time last called, so call graph makes sense
 		TimeBlockTreeNode& tree_node = timerp->getTreeNode();
@@ -221,7 +221,7 @@ void TimeBlock::incrementalUpdateTimerTree()
 		}
 
 		// skip root timer
-		if (timerp != &TimeBlock::getRootTimeBlock())
+		if (timerp != &BlockTimerStatHandle::getRootTimeBlock())
 		{
 			TimeBlockAccumulator& accumulator = timerp->getCurrentAccumulator();
 
@@ -245,7 +245,7 @@ void TimeBlock::incrementalUpdateTimerTree()
 }
 
 
-void TimeBlock::updateTimes()
+void BlockTimerStatHandle::updateTimes()
 {
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
 	BlockTimerStackRecord* stack_record	= LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
@@ -273,11 +273,11 @@ void TimeBlock::updateTimes()
 	}
 }
 
-static LLTrace::TimeBlock FTM_PROCESS_TIMES("Process FastTimer Times");
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_TIMES("Process FastTimer Times");
 
 // not thread safe, so only call on main thread
 //static
-void TimeBlock::processTimes()
+void BlockTimerStatHandle::processTimes()
 {
 	LL_RECORD_BLOCK_TIME(FTM_PROCESS_TIMES);
 	get_clock_count(); // good place to calculate clock frequency
@@ -290,12 +290,12 @@ void TimeBlock::processTimes()
 	updateTimes();
 
 	// reset for next frame
-	for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(),
-			end_it = LLInstanceTracker<TimeBlock>::endInstances();
+	for (BlockTimerStatHandle::instance_tracker_t::instance_iter it = BlockTimerStatHandle::instance_tracker_t::beginInstances(),
+			end_it = BlockTimerStatHandle::instance_tracker_t::endInstances();
 		it != end_it;
 		++it)
 	{
-		TimeBlock& timer = *it;
+		BlockTimerStatHandle& timer = static_cast<BlockTimerStatHandle&>(*it);
 		TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
 
 		accumulator.mLastCaller = NULL;
@@ -303,23 +303,23 @@ void TimeBlock::processTimes()
 	}
 }
 
-std::vector<TimeBlock*>::iterator TimeBlock::beginChildren()
+std::vector<BlockTimerStatHandle*>::iterator BlockTimerStatHandle::beginChildren()
 {
 	return getTreeNode().mChildren.begin(); 
 }
 
-std::vector<TimeBlock*>::iterator TimeBlock::endChildren()
+std::vector<BlockTimerStatHandle*>::iterator BlockTimerStatHandle::endChildren()
 {
 	return getTreeNode().mChildren.end();
 }
 
-std::vector<TimeBlock*>& TimeBlock::getChildren()
+std::vector<BlockTimerStatHandle*>& BlockTimerStatHandle::getChildren()
 {
 	return getTreeNode().mChildren;
 }
 
 // static
-void TimeBlock::logStats()
+void BlockTimerStatHandle::logStats()
 {
 	// get ready for next frame
 	if (sLog)
@@ -340,12 +340,12 @@ void TimeBlock::logStats()
 		LLSD sd;
 
 		{
-			for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), 
-				end_it = LLInstanceTracker<TimeBlock>::endInstances(); 
+			for (BlockTimerStatHandle::instance_tracker_t::instance_iter it = BlockTimerStatHandle::instance_tracker_t::beginInstances(), 
+				end_it = BlockTimerStatHandle::instance_tracker_t::endInstances(); 
 				it != end_it; 
 			++it)
 			{
-				TimeBlock& timer = *it;
+				BlockTimerStatHandle& timer = static_cast<BlockTimerStatHandle&>(*it);
 				LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
 				sd[timer.getName()]["Time"] = (LLSD::Real) (frame_recording.getLastRecording().getSum(timer).value());	
 				sd[timer.getName()]["Calls"] = (LLSD::Integer) (frame_recording.getLastRecording().getSum(timer.callCount()));
@@ -368,17 +368,17 @@ void TimeBlock::logStats()
 }
 
 //static
-void TimeBlock::dumpCurTimes()
+void BlockTimerStatHandle::dumpCurTimes()
 {
 	LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
 	LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording();
 
 	// walk over timers in depth order and output timings
-	for(timer_tree_dfs_iterator_t it = begin_timer_tree(TimeBlock::getRootTimeBlock());
+	for(timer_tree_dfs_iterator_t it = begin_timer_tree(BlockTimerStatHandle::getRootTimeBlock());
 		it != end_timer_tree();
 		++it)
 	{
-		TimeBlock* timerp = (*it);
+		BlockTimerStatHandle* timerp = (*it);
 		F64Seconds total_time = last_frame_recording.getSum(*timerp);
 		U32 num_calls = last_frame_recording.getSum(timerp->callCount());
 
@@ -386,7 +386,7 @@ void TimeBlock::dumpCurTimes()
 		if (total_time < F32Milliseconds(0.1f)) continue;
 
 		std::ostringstream out_str;
-		TimeBlock* parent_timerp = timerp;
+		BlockTimerStatHandle* parent_timerp = timerp;
 		while(parent_timerp && parent_timerp != parent_timerp->getParent())
 		{
 			out_str << "\t";
@@ -402,7 +402,7 @@ void TimeBlock::dumpCurTimes()
 }
 
 //static 
-void TimeBlock::writeLog(std::ostream& os)
+void BlockTimerStatHandle::writeLog(std::ostream& os)
 {
 	while (!sLogQueue.empty())
 	{
@@ -458,9 +458,9 @@ void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
 
 F64Seconds BlockTimer::getElapsedTime()
 {
-	U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
+	U64 total_time = BlockTimerStatHandle::getCPUClockCount64() - mStartTime;
 
-	return F64Seconds((F64)total_time / (F64)TimeBlock::countsPerSecond());
+	return F64Seconds((F64)total_time / (F64)BlockTimerStatHandle::countsPerSecond());
 }
 
 
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 1266d87f08..faa622628b 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -30,36 +30,34 @@
 #include "llinstancetracker.h"
 #include "lltrace.h"
 
-#define FAST_TIMER_ON 1
+#define LL_FAST_TIMER_ON 1
 #define LL_FASTTIMER_USE_RDTSC 1
 
-class LLMutex;
-
 #define LL_RECORD_BLOCK_TIME(timer_stat) const LLTrace::BlockTimer& LL_GLUE_TOKENS(block_time_recorder, __LINE__)(LLTrace::timeThisBlock(timer_stat)); (void)LL_GLUE_TOKENS(block_time_recorder, __LINE__);
 
 namespace LLTrace
 {
-
-class BlockTimer timeThisBlock(class TimeBlock& timer);
+// use to create blocktimer rvalue to be captured in a reference so that the BlockTimer lives to the end of the block.
+class BlockTimer timeThisBlock(class BlockTimerStatHandle& timer);
 
 class BlockTimer
 {
 public:
 	typedef BlockTimer self_t;
-	typedef class TimeBlock DeclareTimer;
+	typedef class BlockTimerStatHandle DeclareTimer;
 
 	~BlockTimer();
 
 	F64Seconds getElapsedTime();
 
 private:
-	friend class TimeBlock;
+	friend class BlockTimerStatHandle;
 	// FIXME: this friendship exists so that each thread can instantiate a root timer, 
 	// which could be a derived class with a public constructor instead, possibly
 	friend class ThreadRecorder; 
-	friend BlockTimer timeThisBlock(TimeBlock&); 
+	friend BlockTimer timeThisBlock(BlockTimerStatHandle&); 
 
-	BlockTimer(TimeBlock& timer);
+	BlockTimer(BlockTimerStatHandle& timer);
 #if !defined(MSC_VER) || MSC_VER < 1700
 	// Visual Studio 2010 has a bug where capturing an object returned by value
 	// into a local reference requires access to the copy constructor at the call site.
@@ -79,28 +77,28 @@ private:
 // (This is most easily done using the macro LL_RECORD_BLOCK_TIME)
 // Otherwise, it would be possible to store a BlockTimer on the heap, resulting in non-nested lifetimes, 
 // which would break the invariants of the timing hierarchy logic
-LL_FORCE_INLINE class BlockTimer timeThisBlock(class TimeBlock& timer)
+LL_FORCE_INLINE class BlockTimer timeThisBlock(class BlockTimerStatHandle& timer)
 {
 	return BlockTimer(timer);
 }
 
 // stores a "named" timer instance to be reused via multiple BlockTimer stack instances
-class TimeBlock 
-:	public StatType<TimeBlockAccumulator>,
-	public LLInstanceTracker<TimeBlock>
+class BlockTimerStatHandle 
+:	public StatType<TimeBlockAccumulator>
 {
 public:
-	TimeBlock(const char* name, TimeBlock* parent = &getRootTimeBlock());
+	typedef LLInstanceTracker<StatType<TimeBlockAccumulator>, std::string> instance_tracker_t;
+	BlockTimerStatHandle(const char* name, const char* description = "");
 
 	TimeBlockTreeNode& getTreeNode() const;
-	TimeBlock* getParent() const { return getTreeNode().getParent(); }
-	void setParent(TimeBlock* parent) { getTreeNode().setParent(parent); }
+	BlockTimerStatHandle* getParent() const { return getTreeNode().getParent(); }
+	void setParent(BlockTimerStatHandle* parent) { getTreeNode().setParent(parent); }
 
-	typedef std::vector<TimeBlock*>::iterator child_iter;
-	typedef std::vector<TimeBlock*>::const_iterator child_const_iter;
+	typedef std::vector<BlockTimerStatHandle*>::iterator child_iter;
+	typedef std::vector<BlockTimerStatHandle*>::const_iterator child_const_iter;
 	child_iter beginChildren();
 	child_iter endChildren();
-	std::vector<TimeBlock*>& getChildren();
+	std::vector<BlockTimerStatHandle*>& getChildren();
 
 	StatType<TimeBlockAccumulator::CallCountFacet>& callCount() 
 	{
@@ -112,9 +110,9 @@ public:
 		return static_cast<StatType<TimeBlockAccumulator::SelfTimeFacet>&>(*(StatType<TimeBlockAccumulator>*)this);
 	}
 
-	static TimeBlock& getRootTimeBlock();
+	static BlockTimerStatHandle& getRootTimeBlock();
 	static void pushLog(LLSD sd);
-	static void setLogLock(LLMutex* mutex);
+	static void setLogLock(class LLMutex* mutex);
 	static void writeLog(std::ostream& os);
 	static void updateTimes();
 
@@ -144,14 +142,14 @@ public:
 	//#undef _interlockedbittestandset
 	//#undef _interlockedbittestandreset
 
-	//inline U32 TimeBlock::getCPUClockCount32()
+	//inline U32 BlockTimerStatHandle::getCPUClockCount32()
 	//{
 	//	U64 time_stamp = __rdtsc();
 	//	return (U32)(time_stamp >> 8);
 	//}
 	//
 	//// return full timer value, *not* shifted by 8 bits
-	//inline U64 TimeBlock::getCPUClockCount64()
+	//inline U64 BlockTimerStatHandle::getCPUClockCount64()
 	//{
 	//	return __rdtsc();
 	//}
@@ -279,9 +277,9 @@ public:
 	static U64									sClockResolution;
 };
 
-LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
+LL_FORCE_INLINE BlockTimer::BlockTimer(BlockTimerStatHandle& timer)
 {
-#if FAST_TIMER_ON
+#if LL_FAST_TIMER_ON
 	BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
 	if (!cur_timer_data) return;
 	TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
@@ -296,14 +294,14 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer)
 	cur_timer_data->mTimeBlock = &timer;
 	cur_timer_data->mChildTime = 0;
 
-	mStartTime = TimeBlock::getCPUClockCount64();
+	mStartTime = BlockTimerStatHandle::getCPUClockCount64();
 #endif
 }
 
 LL_FORCE_INLINE BlockTimer::~BlockTimer()
 {
-#if FAST_TIMER_ON
-	U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime;
+#if LL_FAST_TIMER_ON
+	U64 total_time = BlockTimerStatHandle::getCPUClockCount64() - mStartTime;
 	BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
 	if (!cur_timer_data) return;
 
diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp
index 88287e5786..7963485456 100755
--- a/indra/llcommon/llmetricperformancetester.cpp
+++ b/indra/llcommon/llmetricperformancetester.cpp
@@ -91,7 +91,7 @@ LLMetricPerformanceTesterBasic* LLMetricPerformanceTesterBasic::getTester(std::s
 // Return TRUE if this metric is requested or if the general default "catch all" metric is requested
 BOOL LLMetricPerformanceTesterBasic::isMetricLogRequested(std::string name)
 {
-	return (LLTrace::TimeBlock::sMetricLog && ((LLTrace::TimeBlock::sLogName == name) || (LLTrace::TimeBlock::sLogName == DEFAULT_METRIC_NAME)));
+	return (LLTrace::BlockTimerStatHandle::sMetricLog && ((LLTrace::BlockTimerStatHandle::sLogName == name) || (LLTrace::BlockTimerStatHandle::sLogName == DEFAULT_METRIC_NAME)));
 }
 
 /*static*/ 
@@ -194,7 +194,7 @@ void LLMetricPerformanceTesterBasic::preOutputTestResults(LLSD* sd)
 
 void LLMetricPerformanceTesterBasic::postOutputTestResults(LLSD* sd)
 {
-	LLTrace::TimeBlock::pushLog(*sd);
+	LLTrace::BlockTimerStatHandle::pushLog(*sd);
 }
 
 void LLMetricPerformanceTesterBasic::outputTestResults() 
diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp
index 371bd49c04..2e7b46f885 100755
--- a/indra/llcommon/llsdparam.cpp
+++ b/indra/llcommon/llsdparam.cpp
@@ -37,7 +37,7 @@ static 	LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
 static 	LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
 static const LLSD NO_VALUE_MARKER;
 
-LLTrace::TimeBlock FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion");
+LLTrace::BlockTimerStatHandle FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion");
 
 //
 // LLParamSDParser
diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h
index 47ec6414dd..1542f95e68 100755
--- a/indra/llcommon/llsdparam.h
+++ b/indra/llcommon/llsdparam.h
@@ -110,7 +110,7 @@ private:
 };
 
 
-extern LL_COMMON_API LLTrace::TimeBlock FTM_SD_PARAM_ADAPTOR;
+extern LL_COMMON_API LLTrace::BlockTimerStatHandle FTM_SD_PARAM_ADAPTOR;
 template<typename T>
 class LLSDParamAdapter : public T
 {
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index a4b1d2ede3..76979f29f6 100755
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -36,7 +36,7 @@
 #include <winnls.h> // for WideCharToMultiByte
 #endif
 
-LLTrace::TimeBlock FT_STRING_FORMAT("String Format");
+LLTrace::BlockTimerStatHandle FT_STRING_FORMAT("String Format");
 
 
 std::string ll_safe_string(const char* in)
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 1ad31cacfe..5c4b7b5bb4 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -59,7 +59,7 @@ TimeBlockTreeNode::TimeBlockTreeNode()
 	mCollapsed(true)
 {}
 
-void TimeBlockTreeNode::setParent( TimeBlock* parent )
+void TimeBlockTreeNode::setParent( BlockTimerStatHandle* parent )
 {
 	llassert_always(parent != mBlock);
 	llassert_always(parent != NULL);
@@ -69,8 +69,8 @@ void TimeBlockTreeNode::setParent( TimeBlock* parent )
 
 	if (mParent)
 	{
-		std::vector<TimeBlock*>& children = mParent->getChildren();
-		std::vector<TimeBlock*>::iterator found_it = std::find(children.begin(), children.end(), mBlock);
+		std::vector<BlockTimerStatHandle*>& children = mParent->getChildren();
+		std::vector<BlockTimerStatHandle*>::iterator found_it = std::find(children.begin(), children.end(), mBlock);
 		if (found_it != children.end())
 		{
 			children.erase(found_it);
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 2f4390e4d1..cbdf4e4a6f 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -72,7 +72,7 @@ class StatType
 	public LLInstanceTracker<StatType<ACCUMULATOR>, std::string>
 {
 public:
-	StatType(const char* name, const char* description = NULL)
+	StatType(const char* name, const char* description)
 	:	LLInstanceTracker<StatType<ACCUMULATOR>, std::string>(name),
 		StatBase(name, description),
 		mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot())
@@ -210,8 +210,8 @@ class MemStatHandle : public StatType<MemAccumulator>
 {
 public:
 	typedef StatType<MemAccumulator> stat_t;
-	MemStatHandle(const char* name)
-	:	stat_t(name)
+	MemStatHandle(const char* name, const char* description = "")
+	:	stat_t(name, description)
 	{
 		mName = name;
 	}
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 77370629d3..c30cc9a107 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -460,26 +460,26 @@ namespace LLTrace
 		U64					mTotalTimeCounter,
 							mSelfTimeCounter;
 		S32					mCalls;
-		class TimeBlock*	mParent;		// last acknowledged parent of this time block
-		class TimeBlock*	mLastCaller;	// used to bootstrap tree construction
+		class BlockTimerStatHandle*	mParent;		// last acknowledged parent of this time block
+		class BlockTimerStatHandle*	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
 
 	};
 
-	class TimeBlock;
+	class BlockTimerStatHandle;
 
 	class TimeBlockTreeNode
 	{
 	public:
 		TimeBlockTreeNode();
 
-		void setParent(TimeBlock* parent);
-		TimeBlock* getParent() { return mParent; }
+		void setParent(BlockTimerStatHandle* parent);
+		BlockTimerStatHandle* getParent() { return mParent; }
 
-		TimeBlock*					mBlock;
-		TimeBlock*					mParent;	
-		std::vector<TimeBlock*>		mChildren;
+		BlockTimerStatHandle*					mBlock;
+		BlockTimerStatHandle*					mParent;	
+		std::vector<BlockTimerStatHandle*>		mChildren;
 		bool						mCollapsed;
 		bool						mNeedsSorting;
 	};
@@ -487,7 +487,7 @@ namespace LLTrace
 	struct BlockTimerStackRecord
 	{
 		class BlockTimer*	mActiveTimer;
-		class TimeBlock*	mTimeBlock;
+		class BlockTimerStatHandle*	mTimeBlock;
 		U64					mChildTime;
 	};
 
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 87083eee96..2b2b55f614 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -139,192 +139,228 @@ void Recording::appendRecording( Recording& other )
 
 F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator>& stat)
 {
+	llassert(!isStarted());
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 	return F64Seconds((F64)(accumulator.mTotalTimeCounter) 
-				/ (F64)LLTrace::TimeBlock::countsPerSecond());
+				/ (F64)LLTrace::BlockTimerStatHandle::countsPerSecond());
 }
 
 F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
+	llassert(!isStarted());
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
-	return F64Seconds((F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond());
+	return F64Seconds((F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::BlockTimerStatHandle::countsPerSecond());
 }
 
 
 S32 Recording::getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
 {
+	llassert(!isStarted());
 	return mBuffers->mStackTimers[stat.getIndex()].mCalls;
 }
 
 F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator>& stat)
 {
+	llassert(!isStarted());
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
 	return F64Seconds((F64)(accumulator.mTotalTimeCounter) 
-				/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()));
+				/ ((F64)LLTrace::BlockTimerStatHandle::countsPerSecond() * mElapsedSeconds.value()));
 }
 
 F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
+	llassert(!isStarted());
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
 	return F64Seconds((F64)(accumulator.mSelfTimeCounter) 
-			/ ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds.value()));
+			/ ((F64)LLTrace::BlockTimerStatHandle::countsPerSecond() * mElapsedSeconds.value()));
 }
 
 F32 Recording::getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
 {
+	llassert(!isStarted());
 	return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds.value();
 }
 
 bool Recording::hasValue(const StatType<MemAccumulator>& stat)
 {
+	llassert(!isStarted());
 	return mBuffers->mMemStats[stat.getIndex()].mSize.hasValue();
 }
 
 F64Kilobytes Recording::getMin(const StatType<MemAccumulator>& stat)
 {
+	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMin());
 }
 
 F64Kilobytes Recording::getMean(const StatType<MemAccumulator>& stat)
 {
+	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMean());
 }
 
 F64Kilobytes Recording::getMax(const StatType<MemAccumulator>& stat)
 {
+	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMax());
 }
 
 F64Kilobytes Recording::getStandardDeviation(const StatType<MemAccumulator>& stat)
 {
+	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation());
 }
 
 F64Kilobytes Recording::getLastValue(const StatType<MemAccumulator>& stat)
 {
+	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue());
 }
 
 F64Kilobytes Recording::getSum(const StatType<MemAccumulator::AllocationFacet>& stat)
 {
+	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocations.getSum());
 }
 
 F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::AllocationFacet>& stat)
 {
+	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocations.getSum() / mElapsedSeconds.value());
 }
 
 S32 Recording::getSampleCount(const StatType<MemAccumulator::AllocationFacet>& stat)
 {
+	llassert(!isStarted());
 	return mBuffers->mMemStats[stat.getIndex()].mAllocations.getSampleCount();
 }
 
 F64Kilobytes Recording::getSum(const StatType<MemAccumulator::DeallocationFacet>& stat)
 {
+	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSum());
 }
 
 F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::DeallocationFacet>& stat)
 {
+	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSum() / mElapsedSeconds.value());
 }
 
 S32 Recording::getSampleCount(const StatType<MemAccumulator::DeallocationFacet>& stat)
 {
+	llassert(!isStarted());
 	return mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSampleCount();
 }
 
 F64 Recording::getSum( const StatType<CountAccumulator>& stat )
 {
+	llassert(!isStarted());
 	return mBuffers->mCounts[stat.getIndex()].getSum();
 }
 
 F64 Recording::getSum( const StatType<EventAccumulator>& stat )
 {
+	llassert(!isStarted());
 	return (F64)mBuffers->mEvents[stat.getIndex()].getSum();
 }
 
 F64 Recording::getPerSec( const StatType<CountAccumulator>& stat )
 {
+	llassert(!isStarted());
 	F64 sum = mBuffers->mCounts[stat.getIndex()].getSum();
 	return  sum / mElapsedSeconds.value();
 }
 
 S32 Recording::getSampleCount( const StatType<CountAccumulator>& stat )
 {
+	llassert(!isStarted());
 	return mBuffers->mCounts[stat.getIndex()].getSampleCount();
 }
 
 bool Recording::hasValue(const StatType<SampleAccumulator>& stat)
 {
+	llassert(!isStarted());
 	return mBuffers->mSamples[stat.getIndex()].hasValue();
 }
 
 F64 Recording::getMin( const StatType<SampleAccumulator>& stat )
 {
+	llassert(!isStarted());
 	return mBuffers->mSamples[stat.getIndex()].getMin();
 }
 
 F64 Recording::getMax( const StatType<SampleAccumulator>& stat )
 {
+	llassert(!isStarted());
 	return mBuffers->mSamples[stat.getIndex()].getMax();
 }
 
 F64 Recording::getMean( const StatType<SampleAccumulator>& stat )
 {
+	llassert(!isStarted());
 	return mBuffers->mSamples[stat.getIndex()].getMean();
 }
 
 F64 Recording::getStandardDeviation( const StatType<SampleAccumulator>& stat )
 {
+	llassert(!isStarted());
 	return mBuffers->mSamples[stat.getIndex()].getStandardDeviation();
 }
 
 F64 Recording::getLastValue( const StatType<SampleAccumulator>& stat )
 {
+	llassert(!isStarted());
 	return mBuffers->mSamples[stat.getIndex()].getLastValue();
 }
 
 S32 Recording::getSampleCount( const StatType<SampleAccumulator>& stat )
 {
+	llassert(!isStarted());
 	return mBuffers->mSamples[stat.getIndex()].getSampleCount();
 }
 
 bool Recording::hasValue(const StatType<EventAccumulator>& stat)
 {
+	llassert(!isStarted());
 	return mBuffers->mEvents[stat.getIndex()].hasValue();
 }
 
 F64 Recording::getMin( const StatType<EventAccumulator>& stat )
 {
+	llassert(!isStarted());
 	return mBuffers->mEvents[stat.getIndex()].getMin();
 }
 
 F64 Recording::getMax( const StatType<EventAccumulator>& stat )
 {
+	llassert(!isStarted());
 	return mBuffers->mEvents[stat.getIndex()].getMax();
 }
 
 F64 Recording::getMean( const StatType<EventAccumulator>& stat )
 {
+	llassert(!isStarted());
 	return mBuffers->mEvents[stat.getIndex()].getMean();
 }
 
 F64 Recording::getStandardDeviation( const StatType<EventAccumulator>& stat )
 {
+	llassert(!isStarted());
 	return mBuffers->mEvents[stat.getIndex()].getStandardDeviation();
 }
 
 F64 Recording::getLastValue( const StatType<EventAccumulator>& stat )
 {
+	llassert(!isStarted());
 	return mBuffers->mEvents[stat.getIndex()].getLastValue();
 }
 
 S32 Recording::getSampleCount( const StatType<EventAccumulator>& stat )
 {
+	llassert(!isStarted());
 	return mBuffers->mEvents[stat.getIndex()].getSampleCount();
 }
 
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 9dac4f6771..20e8a0bbaa 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -50,7 +50,7 @@ void ThreadRecorder::init()
 	LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(&mBlockTimerStackRecord);
 	//NB: the ordering of initialization in this function is very fragile due to a large number of implicit dependencies
 	set_thread_recorder(this);
-	TimeBlock& root_time_block = TimeBlock::getRootTimeBlock();
+	BlockTimerStatHandle& root_time_block = BlockTimerStatHandle::getRootTimeBlock();
 
 	BlockTimerStackRecord* timer_stack = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
 	timer_stack->mTimeBlock = &root_time_block;
@@ -63,11 +63,11 @@ void ThreadRecorder::init()
 	activate(&mThreadRecordingBuffers);
 
 	// initialize time block parent pointers
-	for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(); 
+	for (BlockTimerStatHandle::instance_tracker_t::instance_iter it = BlockTimerStatHandle::instance_tracker_t::beginInstances(), end_it = BlockTimerStatHandle::instance_tracker_t::endInstances(); 
 		it != end_it; 
 		++it)
 	{
-		TimeBlock& time_block = *it;
+		BlockTimerStatHandle& time_block = static_cast<BlockTimerStatHandle&>(*it);
 		TimeBlockTreeNode& tree_node = mTimeBlockTreeNodes[it->getIndex()];
 		tree_node.mBlock = &time_block;
 		tree_node.mParent = &root_time_block;
@@ -78,7 +78,7 @@ void ThreadRecorder::init()
 	mRootTimer = new BlockTimer(root_time_block);
 	timer_stack->mActiveTimer = mRootTimer;
 
-	TimeBlock::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1;
+	BlockTimerStatHandle::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1;
 
 	claim_alloc(gTraceMemStat, this);
 	claim_alloc(gTraceMemStat, sizeof(BlockTimer));
@@ -138,7 +138,7 @@ void ThreadRecorder::activate( AccumulatorBufferGroup* recording, bool from_hand
 	{
 		AccumulatorBufferGroup& prev_active_recording = mActiveRecordings.back()->mPartialRecording;
 		prev_active_recording.sync();
-		TimeBlock::updateTimes();
+		BlockTimerStatHandle::updateTimes();
 		prev_active_recording.handOffTo(active_recording->mPartialRecording);
 	}
 	mActiveRecordings.push_back(active_recording);
@@ -151,7 +151,7 @@ ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::bringUpToDate(
 	if (mActiveRecordings.empty()) return mActiveRecordings.end();
 
 	mActiveRecordings.back()->mPartialRecording.sync();
-	TimeBlock::updateTimes();
+	BlockTimerStatHandle::updateTimes();
 
 	active_recording_list_t::reverse_iterator it, end_it;
 	for (it = mActiveRecordings.rbegin(), end_it = mActiveRecordings.rend();
@@ -265,7 +265,7 @@ void ThreadRecorder::pushToParent()
 }
 
 
-static LLTrace::TimeBlock FTM_PULL_TRACE_DATA_FROM_CHILDREN("Pull child thread trace data");
+static LLTrace::BlockTimerStatHandle FTM_PULL_TRACE_DATA_FROM_CHILDREN("Pull child thread trace data");
 
 void ThreadRecorder::pullFromChildren()
 {
-- 
cgit v1.2.3


From 1c26d4265666cd232d38724ad6f1e32fd2dc2d34 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 16 Oct 2013 16:42:27 -0700
Subject: moved tree iterators into llfasttimer.h

---
 indra/llcommon/llfasttimer.cpp | 51 +++++++++++++++++++++++++++---------------
 indra/llcommon/llfasttimer.h   | 13 +++++++++++
 2 files changed, 46 insertions(+), 18 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 361d800629..2db44adacf 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -73,37 +73,52 @@ U64         BlockTimerStatHandle::sClockResolution = 1000000; // Microsecond res
 static LLMutex*			sLogLock = NULL;
 static std::queue<LLSD> sLogQueue;
 
+block_timer_tree_df_iterator_t begin_block_timer_tree_df(BlockTimerStatHandle& id) 
+{ 
+	return block_timer_tree_df_iterator_t(&id, 
+		boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1), 
+		boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
+}
 
-// FIXME: move these declarations to the relevant modules
-
-// helper functions
-typedef LLTreeDFSPostIter<BlockTimerStatHandle, BlockTimerStatHandle::child_const_iter> timer_tree_bottom_up_iterator_t;
+block_timer_tree_df_iterator_t end_block_timer_tree_df() 
+{ 
+	return block_timer_tree_df_iterator_t(); 
+}
 
-static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(BlockTimerStatHandle& id) 
+block_timer_tree_df_post_iterator_t begin_block_timer_tree_df_post(BlockTimerStatHandle& id) 
 { 
-	return timer_tree_bottom_up_iterator_t(&id, 
+	return block_timer_tree_df_post_iterator_t(&id, 
 							boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1), 
 							boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
 }
 
-static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up() 
+block_timer_tree_df_post_iterator_t end_block_timer_tree_df_post() 
 { 
-	return timer_tree_bottom_up_iterator_t(); 
+	return block_timer_tree_df_post_iterator_t(); 
 }
 
-typedef LLTreeDFSIter<BlockTimerStatHandle, BlockTimerStatHandle::child_const_iter> timer_tree_dfs_iterator_t;
+block_timer_tree_bf_iterator_t begin_block_timer_tree_bf(BlockTimerStatHandle& id)
+{
+	return block_timer_tree_bf_iterator_t(&id, 
+		boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1), 
+		boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
+}
 
+block_timer_tree_bf_iterator_t end_block_timer_tree_bf()
+{
+	return block_timer_tree_bf_iterator_t(); 
+}
 
-static timer_tree_dfs_iterator_t begin_timer_tree(BlockTimerStatHandle& id) 
+block_timer_tree_df_iterator_t begin_timer_tree(BlockTimerStatHandle& id) 
 { 
-	return timer_tree_dfs_iterator_t(&id, 
+	return block_timer_tree_df_iterator_t(&id, 
 		boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1), 
 							boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
 }
 
-static timer_tree_dfs_iterator_t end_timer_tree() 
+block_timer_tree_df_iterator_t end_timer_tree() 
 { 
-	return timer_tree_dfs_iterator_t(); 
+	return block_timer_tree_df_iterator_t(); 
 }
 
 
@@ -111,9 +126,9 @@ static timer_tree_dfs_iterator_t end_timer_tree()
 struct SortTimerByName
 {
 	bool operator()(const BlockTimerStatHandle* i1, const BlockTimerStatHandle* i2)
-        {
+	{
 		return i1->getName() < i2->getName();
-        }
+    }
 };
 
 BlockTimerStatHandle& BlockTimerStatHandle::getRootTimeBlock()
@@ -207,8 +222,8 @@ void BlockTimerStatHandle::bootstrapTimerTree()
 // this preserves partial order derived from current frame's observations
 void BlockTimerStatHandle::incrementalUpdateTimerTree()
 {
-	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(BlockTimerStatHandle::getRootTimeBlock());
-		it != end_timer_tree_bottom_up();
+	for(block_timer_tree_df_post_iterator_t it = begin_block_timer_tree_df_post(BlockTimerStatHandle::getRootTimeBlock());
+		it != end_block_timer_tree_df_post();
 		++it)
 	{
 		BlockTimerStatHandle* timerp = *it;
@@ -374,7 +389,7 @@ void BlockTimerStatHandle::dumpCurTimes()
 	LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording();
 
 	// walk over timers in depth order and output timings
-	for(timer_tree_dfs_iterator_t it = begin_timer_tree(BlockTimerStatHandle::getRootTimeBlock());
+	for(block_timer_tree_df_iterator_t it = begin_timer_tree(BlockTimerStatHandle::getRootTimeBlock());
 		it != end_timer_tree();
 		++it)
 	{
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index faa622628b..4821d6c386 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -29,6 +29,7 @@
 
 #include "llinstancetracker.h"
 #include "lltrace.h"
+#include "lltreeiterators.h"
 
 #define LL_FAST_TIMER_ON 1
 #define LL_FASTTIMER_USE_RDTSC 1
@@ -277,6 +278,18 @@ public:
 	static U64									sClockResolution;
 };
 
+// iterators and helper functions for walking the call hierarchy of block timers in different ways
+typedef LLTreeDFSIter<BlockTimerStatHandle, BlockTimerStatHandle::child_const_iter> block_timer_tree_df_iterator_t;
+typedef LLTreeDFSPostIter<BlockTimerStatHandle, BlockTimerStatHandle::child_const_iter> block_timer_tree_df_post_iterator_t;
+typedef LLTreeBFSIter<BlockTimerStatHandle, BlockTimerStatHandle::child_const_iter> block_timer_tree_bf_iterator_t;
+
+block_timer_tree_df_iterator_t begin_block_timer_tree_df(BlockTimerStatHandle& id);
+block_timer_tree_df_iterator_t end_block_timer_tree_df();
+block_timer_tree_df_post_iterator_t begin_block_timer_tree_df_post(BlockTimerStatHandle& id);
+block_timer_tree_df_post_iterator_t end_block_timer_tree_df_post();
+block_timer_tree_bf_iterator_t begin_block_timer_tree_bf(BlockTimerStatHandle& id);
+block_timer_tree_bf_iterator_t end_block_timer_tree_bf();
+
 LL_FORCE_INLINE BlockTimer::BlockTimer(BlockTimerStatHandle& timer)
 {
 #if LL_FAST_TIMER_ON
-- 
cgit v1.2.3


From 1beaedacadc8093c9df612992a873f9c89354bce Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 17 Oct 2013 14:23:56 -0700
Subject: moved root timer to global variable added flag to LLInstanceTracker
 to allow multiple values per key made StatType allow multiple values per key
 to eliminate block timer related crash

---
 indra/llcommon/llfasttimer.cpp           |  9 +++++++--
 indra/llcommon/llfasttimer.h             |  2 +-
 indra/llcommon/llinstancetracker.h       | 27 ++++++++++++++++++++++-----
 indra/llcommon/lltrace.h                 |  5 +++--
 indra/llcommon/lltracethreadrecorder.cpp |  2 +-
 5 files changed, 34 insertions(+), 11 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 2db44adacf..d97fa74c24 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -131,10 +131,10 @@ struct SortTimerByName
     }
 };
 
+static BlockTimerStatHandle sRootTimer("root", NULL);
 BlockTimerStatHandle& BlockTimerStatHandle::getRootTimeBlock()
 {
-	static BlockTimerStatHandle root_timer("root", NULL);
-	return root_timer;
+	return sRootTimer;
 }
 
 void BlockTimerStatHandle::pushLog(LLSD log)
@@ -333,6 +333,11 @@ std::vector<BlockTimerStatHandle*>& BlockTimerStatHandle::getChildren()
 	return getTreeNode().mChildren;
 }
 
+bool BlockTimerStatHandle::hasChildren()
+{
+	return ! getTreeNode().mChildren.empty();
+}
+
 // static
 void BlockTimerStatHandle::logStats()
 {
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 4821d6c386..614e7fdb4c 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -88,7 +88,6 @@ class BlockTimerStatHandle
 :	public StatType<TimeBlockAccumulator>
 {
 public:
-	typedef LLInstanceTracker<StatType<TimeBlockAccumulator>, std::string> instance_tracker_t;
 	BlockTimerStatHandle(const char* name, const char* description = "");
 
 	TimeBlockTreeNode& getTreeNode() const;
@@ -99,6 +98,7 @@ public:
 	typedef std::vector<BlockTimerStatHandle*>::const_iterator child_const_iter;
 	child_iter beginChildren();
 	child_iter endChildren();
+	bool hasChildren();
 	std::vector<BlockTimerStatHandle*>& getChildren();
 
 	StatType<TimeBlockAccumulator::CallCountFacet>& callCount() 
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index f2b982c4c3..1385475444 100755
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -62,16 +62,22 @@ protected:
 
 LL_COMMON_API void assert_main_thread();
 
+enum EInstanceTrackerAllowKeyCollisions
+{
+	InstanceTrackerAllowKeyCollisions,
+	InstanceTrackerDisallowKeyCollisions
+};
+
 /// This mix-in class adds support for tracking all instances of the specified class parameter T
 /// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
 /// If KEY is not provided, then instances are stored in a simple set
 /// @NOTE: see explicit specialization below for default KEY==void case
 /// @NOTE: this class is not thread-safe unless used as read-only
-template<typename T, typename KEY = void>
+template<typename T, typename KEY = void, EInstanceTrackerAllowKeyCollisions ALLOW_KEY_COLLISIONS = InstanceTrackerDisallowKeyCollisions>
 class LLInstanceTracker : public LLInstanceTrackerBase
 {
 	typedef LLInstanceTracker<T, KEY> self_t;
-	typedef typename std::map<KEY, T*> InstanceMap;
+	typedef typename std::multimap<KEY, T*> InstanceMap;
 	struct StaticData: public StaticBase
 	{
 		InstanceMap sMap;
@@ -208,7 +214,18 @@ private:
 	void add_(KEY key) 
 	{ 
 		mInstanceKey = key; 
-		getMap_()[key] = static_cast<T*>(this); 
+		InstanceMap& map = getMap_();
+		InstanceMap::iterator insertion_point_it = map.lower_bound(key);
+		if (ALLOW_KEY_COLLISIONS == InstanceTrackerDisallowKeyCollisions
+			&& insertion_point_it != map.end() 
+			&& insertion_point_it->first == key)
+		{
+			LL_ERRS() << "Key " << key << " already exists in instance map for " << typeid(T).name() << LL_ENDL;
+		}
+		else
+		{
+			map.insert(insertion_point_it, std::make_pair(key, static_cast<T*>(this)));
+		}
 	}
 	void remove_()
 	{
@@ -225,8 +242,8 @@ private:
 
 /// explicit specialization for default case where KEY is void
 /// use a simple std::set<T*>
-template<typename T>
-class LLInstanceTracker<T, void> : public LLInstanceTrackerBase
+template<typename T, EInstanceTrackerAllowKeyCollisions ALLOW_KEY_COLLISIONS>
+class LLInstanceTracker<T, void, ALLOW_KEY_COLLISIONS> : public LLInstanceTrackerBase
 {
 	typedef LLInstanceTracker<T, void> self_t;
 	typedef typename std::set<T*> InstanceSet;
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index cbdf4e4a6f..b499036af2 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -69,11 +69,12 @@ protected:
 template<typename ACCUMULATOR>
 class StatType 
 :	public StatBase,
-	public LLInstanceTracker<StatType<ACCUMULATOR>, std::string>
+	public LLInstanceTracker<StatType<ACCUMULATOR>, std::string, InstanceTrackerAllowKeyCollisions>
 {
 public:
+	typedef LLInstanceTracker<StatType<ACCUMULATOR>, std::string, InstanceTrackerAllowKeyCollisions> instance_tracker_t;
 	StatType(const char* name, const char* description)
-	:	LLInstanceTracker<StatType<ACCUMULATOR>, std::string>(name),
+	:	instance_tracker_t(name),
 		StatBase(name, description),
 		mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot())
 	{}
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 20e8a0bbaa..7b7da5343d 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -81,7 +81,7 @@ void ThreadRecorder::init()
 	BlockTimerStatHandle::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1;
 
 	claim_alloc(gTraceMemStat, this);
-	claim_alloc(gTraceMemStat, sizeof(BlockTimer));
+	claim_alloc(gTraceMemStat, mRootTimer);
 	claim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes);
 }
 
-- 
cgit v1.2.3


From 18aedf0241ba893e12140c0a3855f328d2b4eded Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 17 Oct 2013 19:18:53 -0700
Subject: fix for assert at runtime (reading stats from recording while it was
 active) fix for bad values returns from getPeriodMin and getPeriodMax on
 count stats when no counts recorded fix for gcc compile time error (typename
 ftw)

---
 indra/llcommon/llinstancetracker.h   |  2 +-
 indra/llcommon/lltraceaccumulators.h | 15 +++++++++++++++
 indra/llcommon/lltracerecording.cpp  | 29 +++++++++++++++++++++++++++--
 indra/llcommon/lltracerecording.h    | 35 +++++++++++++++++++++++++++--------
 4 files changed, 70 insertions(+), 11 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 1385475444..3fdb84cfd7 100755
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -215,7 +215,7 @@ private:
 	{ 
 		mInstanceKey = key; 
 		InstanceMap& map = getMap_();
-		InstanceMap::iterator insertion_point_it = map.lower_bound(key);
+		typename InstanceMap::iterator insertion_point_it = map.lower_bound(key);
 		if (ALLOW_KEY_COLLISIONS == InstanceTrackerDisallowKeyCollisions
 			&& insertion_point_it != map.end() 
 			&& insertion_point_it->first == key)
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index c30cc9a107..2971907849 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -226,6 +226,7 @@ namespace LLTrace
 	{
 	public:
 		typedef F64 value_t;
+		static F64 getDefaultValue() { return NaN; }
 
 		EventAccumulator()
 		:	mSum(0),
@@ -293,6 +294,7 @@ namespace LLTrace
 	{
 	public:
 		typedef F64 value_t;
+		static F64 getDefaultValue() { return NaN; }
 
 		SampleAccumulator()
 		:	mSum(0),
@@ -385,6 +387,7 @@ namespace LLTrace
 	{
 	public:
 		typedef F64 value_t;
+		static F64 getDefaultValue() { return 0; }
 
 		CountAccumulator()
 		:	mSum(0),
@@ -415,6 +418,8 @@ namespace LLTrace
 
 		S32 getSampleCount() const { return mNumSamples; }
 
+		bool hasValue() const			 { return true; }
+
 	private:
 		F64	mSum;
 
@@ -425,6 +430,8 @@ namespace LLTrace
 	{
 	public:
 		typedef F64Seconds value_t;
+		static F64Seconds getDefaultValue() { return F64Seconds(0); }
+
 		typedef TimeBlockAccumulator self_t;
 
 		// fake classes that allows us to view different facets of underlying statistic
@@ -453,6 +460,7 @@ namespace LLTrace
 		void addSamples(const self_t& other, EBufferAppendType append_type);
 		void reset(const self_t* other);
 		void sync(F64SecondsImplicit) {}
+		bool hasValue() const { return true; }
 
 		//
 		// members
@@ -493,17 +501,22 @@ namespace LLTrace
 
 	struct MemAccumulator
 	{
+		typedef F64Bytes value_t;
+		static F64Bytes getDefaultValue() { return F64Bytes(0); }
+
 		typedef MemAccumulator self_t;
 
 		// fake classes that allows us to view different facets of underlying statistic
 		struct AllocationFacet 
 		{
 			typedef F64Bytes value_t;
+			static F64Bytes getDefaultValue() { return F64Bytes(0); }
 		};
 
 		struct DeallocationFacet 
 		{
 			typedef F64Bytes value_t;
+			static F64Bytes getDefaultValue() { return F64Bytes(0); }
 		};
 
 		void addSamples(const MemAccumulator& other, EBufferAppendType append_type)
@@ -536,6 +549,8 @@ namespace LLTrace
 			mSize.sync(time_stamp);
 		}
 
+		bool hasValue() const			 { return mSize.hasValue(); }
+
 		SampleAccumulator	mSize;
 		EventAccumulator	mAllocations;
 		CountAccumulator	mDeallocations;
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 2b2b55f614..6ad6bbe356 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -137,6 +137,12 @@ void Recording::appendRecording( Recording& other )
 	mElapsedSeconds += other.mElapsedSeconds;
 }
 
+bool Recording::hasValue(const StatType<TimeBlockAccumulator>& stat)
+{
+	llassert(!isStarted());
+	return mBuffers->mStackTimers[stat.getIndex()].hasValue();
+}
+
 F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator>& stat)
 {
 	llassert(!isStarted());
@@ -219,6 +225,12 @@ F64Kilobytes Recording::getLastValue(const StatType<MemAccumulator>& stat)
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue());
 }
 
+bool Recording::hasValue(const StatType<MemAccumulator::AllocationFacet>& stat)
+{
+	llassert(!isStarted());
+	return mBuffers->mMemStats[stat.getIndex()].mAllocations.hasValue();
+}
+
 F64Kilobytes Recording::getSum(const StatType<MemAccumulator::AllocationFacet>& stat)
 {
 	llassert(!isStarted());
@@ -237,6 +249,13 @@ S32 Recording::getSampleCount(const StatType<MemAccumulator::AllocationFacet>& s
 	return mBuffers->mMemStats[stat.getIndex()].mAllocations.getSampleCount();
 }
 
+bool Recording::hasValue(const StatType<MemAccumulator::DeallocationFacet>& stat)
+{
+	llassert(!isStarted());
+	return mBuffers->mMemStats[stat.getIndex()].mDeallocations.hasValue();
+}
+
+
 F64Kilobytes Recording::getSum(const StatType<MemAccumulator::DeallocationFacet>& stat)
 {
 	llassert(!isStarted());
@@ -255,13 +274,19 @@ S32 Recording::getSampleCount(const StatType<MemAccumulator::DeallocationFacet>&
 	return mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSampleCount();
 }
 
-F64 Recording::getSum( const StatType<CountAccumulator>& stat )
+bool Recording::hasValue(const StatType<CountAccumulator>& stat)
+{
+	llassert(!isStarted());
+	return mBuffers->mCounts[stat.getIndex()].hasValue();
+}
+
+F64 Recording::getSum(const StatType<CountAccumulator>& stat)
 {
 	llassert(!isStarted());
 	return mBuffers->mCounts[stat.getIndex()].getSum();
 }
 
-F64 Recording::getSum( const StatType<EventAccumulator>& stat )
+F64 Recording::getSum( const StatType<EventAccumulator>& stat)
 {
 	llassert(!isStarted());
 	return (F64)mBuffers->mEvents[stat.getIndex()].getSum();
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 810f796666..4b7a5ef0da 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -168,6 +168,7 @@ namespace LLTrace
 		void makeUnique() { mBuffers.makeUnique(); }
 
 		// Timer accessors
+		bool hasValue(const StatType<TimeBlockAccumulator>& stat);
 		F64Seconds getSum(const StatType<TimeBlockAccumulator>& stat);
 		F64Seconds getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat);
 		S32 getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat);
@@ -178,22 +179,24 @@ namespace LLTrace
 
 		// Memory accessors
 		bool hasValue(const StatType<MemAccumulator>& stat);
-
 		F64Kilobytes getMin(const StatType<MemAccumulator>& stat);
 		F64Kilobytes getMean(const StatType<MemAccumulator>& stat);
 		F64Kilobytes getMax(const StatType<MemAccumulator>& stat);
 		F64Kilobytes getStandardDeviation(const StatType<MemAccumulator>& stat);
 		F64Kilobytes getLastValue(const StatType<MemAccumulator>& stat);
 
+		bool hasValue(const StatType<MemAccumulator::AllocationFacet>& stat);
 		F64Kilobytes getSum(const StatType<MemAccumulator::AllocationFacet>& stat);
 		F64Kilobytes getPerSec(const StatType<MemAccumulator::AllocationFacet>& stat);
 		S32 getSampleCount(const StatType<MemAccumulator::AllocationFacet>& stat);
 
+		bool hasValue(const StatType<MemAccumulator::DeallocationFacet>& stat);
 		F64Kilobytes getSum(const StatType<MemAccumulator::DeallocationFacet>& stat);
 		F64Kilobytes getPerSec(const StatType<MemAccumulator::DeallocationFacet>& stat);
 		S32 getSampleCount(const StatType<MemAccumulator::DeallocationFacet>& stat);
 
 		// CountStatHandle accessors
+		bool hasValue(const StatType<CountAccumulator>& stat);
 		F64 getSum(const StatType<CountAccumulator>& stat);
 		template <typename T>
 		typename RelatedTypes<T>::sum_t getSum(const CountStatHandle<T>& stat)
@@ -367,13 +370,21 @@ namespace LLTrace
 			S32 total_periods = mNumPeriods;
 			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();
+			bool has_value = false;
+			T::value_t min_val(std::numeric_limits<T::value_t>::max());
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				Recording& recording = getPrevRecording(i);
-				min_val = llmin(min_val, recording.getSum(stat));
+				if (recording.hasValue(stat))
+				{
+					min_val = llmin(min_val, recording.getSum(stat));
+					has_value = true;
+				}
 			}
-			return min_val;
+
+			return has_value 
+				? min_val 
+				: T::getDefaultValue();
 		}
 
 		template<typename T>
@@ -405,7 +416,7 @@ namespace LLTrace
 			S32 total_periods = mNumPeriods;
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
-			typename RelatedTypes<typename T::value_t>::fractional_t min_val = std::numeric_limits<F64>::max();
+			typename RelatedTypes<typename T::value_t>::fractional_t min_val(std::numeric_limits<F64>::max());
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				Recording& recording = getPrevRecording(i);
@@ -431,13 +442,21 @@ namespace LLTrace
 			S32 total_periods = mNumPeriods;
 			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();
+			bool has_value = false;
+			T::value_t max_val(std::numeric_limits<T::value_t>::min());
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				Recording& recording = getPrevRecording(i);
-				max_val = llmax(max_val, recording.getSum(stat));
+				if (recording.hasValue(stat))
+				{
+					max_val = llmax(max_val, recording.getSum(stat));
+					has_value = true;
+				}
 			}
-			return max_val;
+
+			return has_value 
+				? max_val 
+				: T::getDefaultValue();
 		}
 
 		template<typename T>
-- 
cgit v1.2.3


From 9f097380b85a307db472726175c3515fdeb5aed5 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 18 Oct 2013 09:14:53 -0700
Subject: removed asserts in order to get testable builds again added unpause()
 behavior and changed pause() to do nothing when already stopped

---
 indra/llcommon/lltracerecording.cpp | 74 +++++++++++++++----------------------
 indra/llcommon/lltracerecording.h   | 22 ++++++-----
 2 files changed, 42 insertions(+), 54 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 6ad6bbe356..5ec7ce56b9 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -139,13 +139,11 @@ void Recording::appendRecording( Recording& other )
 
 bool Recording::hasValue(const StatType<TimeBlockAccumulator>& stat)
 {
-	llassert(!isStarted());
 	return mBuffers->mStackTimers[stat.getIndex()].hasValue();
 }
 
 F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator>& stat)
 {
-	llassert(!isStarted());
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 	return F64Seconds((F64)(accumulator.mTotalTimeCounter) 
 				/ (F64)LLTrace::BlockTimerStatHandle::countsPerSecond());
@@ -153,7 +151,6 @@ F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator>& stat)
 
 F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
-	llassert(!isStarted());
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 	return F64Seconds((F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::BlockTimerStatHandle::countsPerSecond());
 }
@@ -161,13 +158,11 @@ F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>
 
 S32 Recording::getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
 {
-	llassert(!isStarted());
 	return mBuffers->mStackTimers[stat.getIndex()].mCalls;
 }
 
 F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator>& stat)
 {
-	llassert(!isStarted());
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
 	return F64Seconds((F64)(accumulator.mTotalTimeCounter) 
@@ -176,7 +171,6 @@ F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator>& stat)
 
 F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
-	llassert(!isStarted());
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 
 	return F64Seconds((F64)(accumulator.mSelfTimeCounter) 
@@ -185,207 +179,173 @@ F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFac
 
 F32 Recording::getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
 {
-	llassert(!isStarted());
 	return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds.value();
 }
 
 bool Recording::hasValue(const StatType<MemAccumulator>& stat)
 {
-	llassert(!isStarted());
 	return mBuffers->mMemStats[stat.getIndex()].mSize.hasValue();
 }
 
 F64Kilobytes Recording::getMin(const StatType<MemAccumulator>& stat)
 {
-	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMin());
 }
 
 F64Kilobytes Recording::getMean(const StatType<MemAccumulator>& stat)
 {
-	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMean());
 }
 
 F64Kilobytes Recording::getMax(const StatType<MemAccumulator>& stat)
 {
-	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMax());
 }
 
 F64Kilobytes Recording::getStandardDeviation(const StatType<MemAccumulator>& stat)
 {
-	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation());
 }
 
 F64Kilobytes Recording::getLastValue(const StatType<MemAccumulator>& stat)
 {
-	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue());
 }
 
 bool Recording::hasValue(const StatType<MemAccumulator::AllocationFacet>& stat)
 {
-	llassert(!isStarted());
 	return mBuffers->mMemStats[stat.getIndex()].mAllocations.hasValue();
 }
 
 F64Kilobytes Recording::getSum(const StatType<MemAccumulator::AllocationFacet>& stat)
 {
-	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocations.getSum());
 }
 
 F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::AllocationFacet>& stat)
 {
-	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocations.getSum() / mElapsedSeconds.value());
 }
 
 S32 Recording::getSampleCount(const StatType<MemAccumulator::AllocationFacet>& stat)
 {
-	llassert(!isStarted());
 	return mBuffers->mMemStats[stat.getIndex()].mAllocations.getSampleCount();
 }
 
 bool Recording::hasValue(const StatType<MemAccumulator::DeallocationFacet>& stat)
 {
-	llassert(!isStarted());
 	return mBuffers->mMemStats[stat.getIndex()].mDeallocations.hasValue();
 }
 
 
 F64Kilobytes Recording::getSum(const StatType<MemAccumulator::DeallocationFacet>& stat)
 {
-	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSum());
 }
 
 F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::DeallocationFacet>& stat)
 {
-	llassert(!isStarted());
 	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSum() / mElapsedSeconds.value());
 }
 
 S32 Recording::getSampleCount(const StatType<MemAccumulator::DeallocationFacet>& stat)
 {
-	llassert(!isStarted());
 	return mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSampleCount();
 }
 
 bool Recording::hasValue(const StatType<CountAccumulator>& stat)
 {
-	llassert(!isStarted());
 	return mBuffers->mCounts[stat.getIndex()].hasValue();
 }
 
 F64 Recording::getSum(const StatType<CountAccumulator>& stat)
 {
-	llassert(!isStarted());
 	return mBuffers->mCounts[stat.getIndex()].getSum();
 }
 
 F64 Recording::getSum( const StatType<EventAccumulator>& stat)
 {
-	llassert(!isStarted());
 	return (F64)mBuffers->mEvents[stat.getIndex()].getSum();
 }
 
 F64 Recording::getPerSec( const StatType<CountAccumulator>& stat )
 {
-	llassert(!isStarted());
 	F64 sum = mBuffers->mCounts[stat.getIndex()].getSum();
 	return  sum / mElapsedSeconds.value();
 }
 
 S32 Recording::getSampleCount( const StatType<CountAccumulator>& stat )
 {
-	llassert(!isStarted());
 	return mBuffers->mCounts[stat.getIndex()].getSampleCount();
 }
 
 bool Recording::hasValue(const StatType<SampleAccumulator>& stat)
 {
-	llassert(!isStarted());
 	return mBuffers->mSamples[stat.getIndex()].hasValue();
 }
 
 F64 Recording::getMin( const StatType<SampleAccumulator>& stat )
 {
-	llassert(!isStarted());
 	return mBuffers->mSamples[stat.getIndex()].getMin();
 }
 
 F64 Recording::getMax( const StatType<SampleAccumulator>& stat )
 {
-	llassert(!isStarted());
 	return mBuffers->mSamples[stat.getIndex()].getMax();
 }
 
 F64 Recording::getMean( const StatType<SampleAccumulator>& stat )
 {
-	llassert(!isStarted());
 	return mBuffers->mSamples[stat.getIndex()].getMean();
 }
 
 F64 Recording::getStandardDeviation( const StatType<SampleAccumulator>& stat )
 {
-	llassert(!isStarted());
 	return mBuffers->mSamples[stat.getIndex()].getStandardDeviation();
 }
 
 F64 Recording::getLastValue( const StatType<SampleAccumulator>& stat )
 {
-	llassert(!isStarted());
 	return mBuffers->mSamples[stat.getIndex()].getLastValue();
 }
 
 S32 Recording::getSampleCount( const StatType<SampleAccumulator>& stat )
 {
-	llassert(!isStarted());
 	return mBuffers->mSamples[stat.getIndex()].getSampleCount();
 }
 
 bool Recording::hasValue(const StatType<EventAccumulator>& stat)
 {
-	llassert(!isStarted());
 	return mBuffers->mEvents[stat.getIndex()].hasValue();
 }
 
 F64 Recording::getMin( const StatType<EventAccumulator>& stat )
 {
-	llassert(!isStarted());
 	return mBuffers->mEvents[stat.getIndex()].getMin();
 }
 
 F64 Recording::getMax( const StatType<EventAccumulator>& stat )
 {
-	llassert(!isStarted());
 	return mBuffers->mEvents[stat.getIndex()].getMax();
 }
 
 F64 Recording::getMean( const StatType<EventAccumulator>& stat )
 {
-	llassert(!isStarted());
 	return mBuffers->mEvents[stat.getIndex()].getMean();
 }
 
 F64 Recording::getStandardDeviation( const StatType<EventAccumulator>& stat )
 {
-	llassert(!isStarted());
 	return mBuffers->mEvents[stat.getIndex()].getStandardDeviation();
 }
 
 F64 Recording::getLastValue( const StatType<EventAccumulator>& stat )
 {
-	llassert(!isStarted());
 	return mBuffers->mEvents[stat.getIndex()].getLastValue();
 }
 
 S32 Recording::getSampleCount( const StatType<EventAccumulator>& stat )
 {
-	llassert(!isStarted());
 	return mBuffers->mEvents[stat.getIndex()].getSampleCount();
 }
 
@@ -964,9 +924,11 @@ void LLStopWatchControlsMixinCommon::start()
 	case STOPPED:
 		handleReset();
 		handleStart();
+		mPlayState = STARTED;
 		break;
 	case PAUSED:
 		handleStart();
+		mPlayState = STARTED;
 		break;
 	case STARTED:
 		break;
@@ -974,7 +936,6 @@ void LLStopWatchControlsMixinCommon::start()
 		llassert(false);
 		break;
 	}
-	mPlayState = STARTED;
 }
 
 void LLStopWatchControlsMixinCommon::stop()
@@ -984,15 +945,16 @@ void LLStopWatchControlsMixinCommon::stop()
 	case STOPPED:
 		break;
 	case PAUSED:
+		mPlayState = STOPPED;
 		break;
 	case STARTED:
 		handleStop();
+		mPlayState = STOPPED;
 		break;
 	default:
 		llassert(false);
 		break;
 	}
-	mPlayState = STOPPED;
 }
 
 void LLStopWatchControlsMixinCommon::pause()
@@ -1000,17 +962,37 @@ void LLStopWatchControlsMixinCommon::pause()
 	switch (mPlayState)
 	{
 	case STOPPED:
+		// stay stopped, don't go to pause
 		break;
 	case PAUSED:
 		break;
 	case STARTED:
 		handleStop();
+		mPlayState = PAUSED;
+		break;
+	default:
+		llassert(false);
+		break;
+	}
+}
+
+void LLStopWatchControlsMixinCommon::unpause()
+{
+	switch (mPlayState)
+	{
+	case STOPPED:
+		// stay stopped, don't start
+		break;
+	case PAUSED:
+		handleStart();
+		mPlayState = STARTED;
+		break;
+	case STARTED:
 		break;
 	default:
 		llassert(false);
 		break;
 	}
-	mPlayState = PAUSED;
 }
 
 void LLStopWatchControlsMixinCommon::resume()
@@ -1019,9 +1001,11 @@ void LLStopWatchControlsMixinCommon::resume()
 	{
 	case STOPPED:
 		handleStart();
+		mPlayState = STARTED;
 		break;
 	case PAUSED:
 		handleStart();
+		mPlayState = STARTED;
 		break;
 	case STARTED:
 		break;
@@ -1029,7 +1013,6 @@ void LLStopWatchControlsMixinCommon::resume()
 		llassert(false);
 		break;
 	}
-	mPlayState = STARTED;
 }
 
 void LLStopWatchControlsMixinCommon::restart()
@@ -1039,10 +1022,12 @@ void LLStopWatchControlsMixinCommon::restart()
 	case STOPPED:
 		handleReset();
 		handleStart();
+		mPlayState = STARTED;
 		break;
 	case PAUSED:
 		handleReset();
 		handleStart();
+		mPlayState = STARTED;
 		break;
 	case STARTED:
 		handleReset();
@@ -1051,7 +1036,6 @@ void LLStopWatchControlsMixinCommon::restart()
 		llassert(false);
 		break;
 	}
-	mPlayState = STARTED;
 }
 
 void LLStopWatchControlsMixinCommon::reset()
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 4b7a5ef0da..4e94c2110b 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -46,16 +46,18 @@ public:
 		STARTED
 	};
 
-	void start();
-	void stop();
-	void pause();
-	void resume();
-	void restart();
-	void reset();
+	void start();   // moves to started state, resetting if stopped
+	void stop();    // moves to stopped state
+	void pause();   // moves to paused state, unless stopped
+	void unpause(); // moves to started state if paused
+	void resume();  // moves to started state, without resetting
+	void restart(); // moves to started state, always resetting
+	void reset();   // resets
 
 	bool isStarted() const { return mPlayState == STARTED; }
 	bool isPaused() const  { return mPlayState == PAUSED; }
 	bool isStopped() const { return mPlayState == STOPPED; }
+
 	EPlayState getPlayState() const { return mPlayState; }
 	// force play state to specific value by calling appropriate handle* methods
 	void setPlayState(EPlayState state);
@@ -66,11 +68,13 @@ protected:
 	{}
 
 private:
-	// trigger active behavior (without reset)
+	// override these methods to provide started/stopped semantics
+
+	// activate behavior (without reset)
 	virtual void handleStart() = 0;
-	// stop active behavior
+	// deactivate behavior
 	virtual void handleStop() = 0;
-	// clear accumulated state, can be called while started
+	// clear accumulated state, may be called while started
 	virtual void handleReset() = 0;
 
 	EPlayState mPlayState;
-- 
cgit v1.2.3


From 4170ef8ecc604da38482934fb864adc5b436739f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 18 Oct 2013 09:50:26 -0700
Subject: fixed llinstancetracker unit test

---
 indra/llcommon/tests/llinstancetracker_test.cpp | 17 +++++++++--------
 indra/llcommon/tests/wrapllerrs.h               |  8 ++++----
 2 files changed, 13 insertions(+), 12 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp
index e769c3e22c..601d28ea3e 100755
--- a/indra/llcommon/tests/llinstancetracker_test.cpp
+++ b/indra/llcommon/tests/llinstancetracker_test.cpp
@@ -194,20 +194,21 @@ namespace tut
     {
         set_test_name("delete Keyed with outstanding instance_iter");
         std::string what;
-        Keyed* keyed = new Keyed("one");
+        Keyed* keyed = new Keyed("delete Keyed with outstanding instance_iter");
         {
-            WrapLL_ERRS wrapper;
+            WrapLLErrs wrapper;
             Keyed::instance_iter i(Keyed::beginInstances());
             try
             {
                 delete keyed;
             }
-            catch (const WrapLL_ERRS::FatalException& e)
+            catch (const WrapLLErrs::FatalException& e)
             {
                 what = e.what();
             }
         }
         ensure(! what.empty());
+		delete keyed;
     }
 
     template<> template<>
@@ -215,15 +216,15 @@ namespace tut
     {
         set_test_name("delete Keyed with outstanding key_iter");
         std::string what;
-        Keyed* keyed = new Keyed("one");
+        Keyed* keyed = new Keyed("delete Keyed with outstanding key_it");
         {
-            WrapLL_ERRS wrapper;
+            WrapLLErrs wrapper;
             Keyed::key_iter i(Keyed::beginKeys());
             try
             {
                 delete keyed;
             }
-            catch (const WrapLL_ERRS::FatalException& e)
+            catch (const WrapLLErrs::FatalException& e)
             {
                 what = e.what();
             }
@@ -238,13 +239,13 @@ namespace tut
         std::string what;
         Unkeyed* unkeyed = new Unkeyed;
         {
-            WrapLL_ERRS wrapper;
+            WrapLLErrs wrapper;
             Unkeyed::instance_iter i(Unkeyed::beginInstances());
             try
             {
                 delete unkeyed;
             }
-            catch (const WrapLL_ERRS::FatalException& e)
+            catch (const WrapLLErrs::FatalException& e)
             {
                 what = e.what();
             }
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index a4d3a4e026..3137bd8fea 100755
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -46,9 +46,9 @@
 // replicate, but better to reuse
 extern void wouldHaveCrashed(const std::string& message);
 
-struct WrapLL_ERRS
+struct WrapLLErrs
 {
-    WrapLL_ERRS():
+    WrapLLErrs():
         // Resetting Settings discards the default Recorder that writes to
         // stderr. Otherwise, expected llerrs (LL_ERRS) messages clutter the
         // console output of successful tests, potentially confusing things.
@@ -57,10 +57,10 @@ struct WrapLL_ERRS
         mPriorFatal(LLError::getFatalFunction())
     {
         // Make LL_ERRS call our own operator() method
-        LLError::setFatalFunction(boost::bind(&WrapLL_ERRS::operator(), this, _1));
+        LLError::setFatalFunction(boost::bind(&WrapLLErrs::operator(), this, _1));
     }
 
-    ~WrapLL_ERRS()
+    ~WrapLLErrs()
     {
         LLError::setFatalFunction(mPriorFatal);
         LLError::restoreSettings(mPriorErrorSettings);
-- 
cgit v1.2.3


From 8b93238b42fdd8b2b6d9b944d4ebb3099f119904 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 18 Oct 2013 10:04:29 -0700
Subject: BUILDFIX: forgot typename

---
 indra/llcommon/lltracerecording.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 4e94c2110b..eb94354189 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -375,7 +375,7 @@ namespace LLTrace
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 			bool has_value = false;
-			T::value_t min_val(std::numeric_limits<T::value_t>::max());
+			typename T::value_t min_val(std::numeric_limits<T::value_t>::max());
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				Recording& recording = getPrevRecording(i);
@@ -447,7 +447,7 @@ namespace LLTrace
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 			bool has_value = false;
-			T::value_t max_val(std::numeric_limits<T::value_t>::min());
+			typename T::value_t max_val(std::numeric_limits<T::value_t>::min());
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				Recording& recording = getPrevRecording(i);
-- 
cgit v1.2.3


From 99e29b83401a1d6da9dbca03a64c0bfd7bad6298 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 18 Oct 2013 13:10:40 -0700
Subject: crash fix - bad handling of instancetracker iterators

---
 indra/llcommon/llfasttimer.cpp       | 2 +-
 indra/llcommon/llinstancetracker.cpp | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index d97fa74c24..4744be7236 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -193,7 +193,7 @@ TimeBlockTreeNode& BlockTimerStatHandle::getTreeNode() const
 
 void BlockTimerStatHandle::bootstrapTimerTree()
 {
-	for (BlockTimerStatHandle::instance_tracker_t::instance_iter begin_it = BlockTimerStatHandle::instance_tracker_t::beginInstances(), end_it = BlockTimerStatHandle::instance_tracker_t::endInstances(), it = begin_it; 
+	for (BlockTimerStatHandle::instance_tracker_t::instance_iter it = BlockTimerStatHandle::instance_tracker_t::beginInstances(), end_it = BlockTimerStatHandle::instance_tracker_t::endInstances(); 
 		it != end_it; 
 		++it)
 	{
diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp
index 7ff8324fe3..11fc53f8c8 100755
--- a/indra/llcommon/llinstancetracker.cpp
+++ b/indra/llcommon/llinstancetracker.cpp
@@ -41,6 +41,7 @@ void LLInstanceTrackerBase::StaticBase::incrementDepth()
 
 void LLInstanceTrackerBase::StaticBase::decrementDepth()
 {
+	llassert(sIterationNestDepth);
 	apr_atomic_dec32(&sIterationNestDepth);
 }
 
-- 
cgit v1.2.3


From d2cf7ba42931bb7ecf637fbf4ff25c7837c3296f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 18 Oct 2013 13:34:25 -0700
Subject: more forgotten typenames

---
 indra/llcommon/lltracerecording.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index eb94354189..b045aafa11 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -375,7 +375,7 @@ namespace LLTrace
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 			bool has_value = false;
-			typename T::value_t min_val(std::numeric_limits<T::value_t>::max());
+			typename T::value_t min_val(std::numeric_limits<typename T::value_t>::max());
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				Recording& recording = getPrevRecording(i);
@@ -447,7 +447,7 @@ namespace LLTrace
 			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
 
 			bool has_value = false;
-			typename T::value_t max_val(std::numeric_limits<T::value_t>::min());
+			typename T::value_t max_val(std::numeric_limits<typename T::value_t>::min());
 			for (S32 i = 1; i <= num_periods; i++)
 			{
 				Recording& recording = getPrevRecording(i);
-- 
cgit v1.2.3


From aef2a527e5ff13db9078c980bfa099bc4bde4124 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 21 Oct 2013 10:32:19 -0700
Subject: BUILDFIX: double delete in instancetracker unit test

---
 indra/llcommon/tests/llinstancetracker_test.cpp | 1 -
 1 file changed, 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp
index 601d28ea3e..c7d4b8a06b 100755
--- a/indra/llcommon/tests/llinstancetracker_test.cpp
+++ b/indra/llcommon/tests/llinstancetracker_test.cpp
@@ -208,7 +208,6 @@ namespace tut
             }
         }
         ensure(! what.empty());
-		delete keyed;
     }
 
     template<> template<>
-- 
cgit v1.2.3


From 30863e0af01945c6aad22ea89d64c6f3167b4bd6 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 21 Oct 2013 11:19:38 -0700
Subject: another attempted buildfix

---
 indra/llcommon/tests/lleventdispatcher_test.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/tests/lleventdispatcher_test.cpp b/indra/llcommon/tests/lleventdispatcher_test.cpp
index 263c9b171f..5a4df81bf1 100755
--- a/indra/llcommon/tests/lleventdispatcher_test.cpp
+++ b/indra/llcommon/tests/lleventdispatcher_test.cpp
@@ -312,7 +312,7 @@ namespace tut
 {
     struct lleventdispatcher_data
     {
-        WrapLL_ERRS redirect;
+        WrapLLErrs redirect;
         Dispatcher work;
         Vars v;
         std::string name, desc;
-- 
cgit v1.2.3


From 318a1eca57d2e4ee3a0845c137f48e721cc57b00 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 21 Oct 2013 11:24:35 -0700
Subject: more buildfix stuff

---
 indra/llcommon/tests/lleventfilter_test.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/tests/lleventfilter_test.cpp b/indra/llcommon/tests/lleventfilter_test.cpp
index ca05ef62a9..2cdfb52f2f 100755
--- a/indra/llcommon/tests/lleventfilter_test.cpp
+++ b/indra/llcommon/tests/lleventfilter_test.cpp
@@ -244,7 +244,7 @@ namespace tut
     void filter_object::test<4>()
     {
         set_test_name("LLEventTimeout::errorAfter()");
-        WrapLL_ERRS capture;
+        WrapLLErrs capture;
         LLEventPump& driver(pumps.obtain("driver"));
         TestEventTimeout filter(driver);
         listener0.reset(0);
@@ -274,7 +274,7 @@ namespace tut
         {
             mainloop.post(17);
         }
-        catch (const WrapLL_ERRS::FatalException& e)
+        catch (const WrapLLErrs::FatalException& e)
         {
             threw = e.what();
         }
-- 
cgit v1.2.3


From fcf5602ba82015cc4ab40734b97a7b8c9085d2d6 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 21 Oct 2013 11:56:31 -0700
Subject: more buildfix

---
 indra/llcommon/tests/lleventcoro_test.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/tests/lleventcoro_test.cpp b/indra/llcommon/tests/lleventcoro_test.cpp
index 5ebde1a31d..cb5e15eff2 100755
--- a/indra/llcommon/tests/lleventcoro_test.cpp
+++ b/indra/llcommon/tests/lleventcoro_test.cpp
@@ -346,13 +346,13 @@ namespace tut
                 LLCoroEventPumps waiter;
                 replyName = waiter.getName0();
                 errorName = waiter.getName1();
-                WrapLL_ERRS capture;
+                WrapLLErrs capture;
                 try
                 {
                     result = waiter.waitWithLog(self);
                     debug("no exception");
                 }
-                catch (const WrapLL_ERRS::FatalException& e)
+                catch (const WrapLLErrs::FatalException& e)
                 {
                     debug(STRINGIZE("exception " << e.what()));
                     threw = e.what();
@@ -436,7 +436,7 @@ namespace tut
             BEGIN
             {
                 LLCoroEventPumps waiter;
-                WrapLL_ERRS capture;
+                WrapLLErrs capture;
                 try
                 {
                     result = waiter.postAndWaitWithLog(self,
@@ -444,7 +444,7 @@ namespace tut
                         immediateAPI.getPump(), "reply", "error");
                     debug("no exception");
                 }
-                catch (const WrapLL_ERRS::FatalException& e)
+                catch (const WrapLLErrs::FatalException& e)
                 {
                     debug(STRINGIZE("exception " << e.what()));
                     threw = e.what();
-- 
cgit v1.2.3


From 1dfba44b3dc14564c99333dedb7a380a160aee44 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 21 Oct 2013 14:22:21 -0700
Subject: fixed things so that trace recordings can be read from even while
 active

---
 indra/llcommon/lltraceaccumulators.cpp   | 102 ++++++-----
 indra/llcommon/lltraceaccumulators.h     |   8 +-
 indra/llcommon/lltracerecording.cpp      | 279 +++++++++++++++++++++++++------
 indra/llcommon/lltracerecording.h        |   2 +-
 indra/llcommon/lltracethreadrecorder.cpp |   3 +-
 indra/llcommon/lltracethreadrecorder.h   |   2 +-
 indra/llcommon/tests/lltrace_test.cpp    |   5 +-
 7 files changed, 299 insertions(+), 102 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
index 7d0e63e76a..385d31edd7 100644
--- a/indra/llcommon/lltraceaccumulators.cpp
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -155,6 +155,39 @@ void AccumulatorBufferGroup::sync()
 	}
 }
 
+F64 SampleAccumulator::mergeSumsOfSquares(const SampleAccumulator& a, const SampleAccumulator& b)
+{
+	const F64 epsilon = 0.0000001;
+
+	if (a.getSamplingTime() > epsilon && b.getSamplingTime() > epsilon)
+	{
+		// combine variance (and hence standard deviation) of 2 different sized sample groups using
+		// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+		F64 n_1 = a.getSamplingTime(),
+			n_2 = b.getSamplingTime();
+		F64 m_1 = a.getMean(),
+			m_2 = b.getMean();
+		F64 v_1 = a.getSumOfSquares() / a.getSamplingTime(),
+			v_2 = b.getSumOfSquares() / b.getSamplingTime();
+		if (n_1 < epsilon)
+		{
+			return b.getSumOfSquares();
+		}
+		else
+		{
+			return a.getSamplingTime()
+				* ((((n_1 - epsilon) * v_1)
+				+ ((n_2 - epsilon) * v_2)
+				+ (((n_1 * n_2) / (n_1 + n_2))
+				* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+				/ (n_1 + n_2 - epsilon));
+		}
+	}
+
+	return a.getSumOfSquares();
+}
+
+
 void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppendType append_type )
 {
 	if (append_type == NON_SEQUENTIAL)
@@ -180,37 +213,8 @@ void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppen
 		if (other.mMin < mMin) { mMin = other.mMin; }
 		if (other.mMax > mMax) { mMax = other.mMax; }
 
-		F64 epsilon = 0.0000001;
+		mSumOfSquares = mergeSumsOfSquares(*this, other);
 
-		if (other.mTotalSamplingTime > epsilon && mTotalSamplingTime > epsilon)
-		{
-			// combine variance (and hence standard deviation) of 2 different sized sample groups using
-			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
-			F64 n_1 = mTotalSamplingTime,
-				n_2 = other.mTotalSamplingTime;
-			F64 m_1 = mMean,
-				m_2 = other.mMean;
-			F64 v_1 = mSumOfSquares / mTotalSamplingTime,
-				v_2 = other.mSumOfSquares / other.mTotalSamplingTime;
-			if (n_1 < epsilon)
-			{
-				mSumOfSquares = other.mSumOfSquares;
-			}
-			else
-			{
-				mSumOfSquares =	mTotalSamplingTime
-					* ((((n_1 - epsilon) * v_1)
-					+ ((n_2 - epsilon) * v_2)
-					+ (((n_1 * n_2) / (n_1 + n_2))
-					* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
-					/ (n_1 + n_2 - epsilon));
-			}
-
-			F64 weight = mTotalSamplingTime / (mTotalSamplingTime + other.mTotalSamplingTime);
-			mNumSamples += other.mNumSamples;
-			mTotalSamplingTime += other.mTotalSamplingTime;
-			mMean = (mMean * weight) + (other.mMean * (1.0 - weight));
-		}
 		if (append_type == SEQUENTIAL)
 		{
 			mLastValue = other.mLastValue;
@@ -234,6 +238,29 @@ void SampleAccumulator::reset( const SampleAccumulator* other )
 	mTotalSamplingTime = 0;
 }
 
+F64 EventAccumulator::mergeSumsOfSquares(const EventAccumulator& a, const EventAccumulator& b)
+{
+	if (a.mNumSamples && b.mNumSamples)
+	{
+		// combine variance (and hence standard deviation) of 2 different sized sample groups using
+		// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+		F64 n_1 = a.mNumSamples,
+			n_2 = b.mNumSamples;
+		F64 m_1 = a.mMean,
+			m_2 = b.mMean;
+		F64 v_1 = a.mSumOfSquares / a.mNumSamples,
+			v_2 = b.mSumOfSquares / b.mNumSamples;
+		return (F64)a.mNumSamples
+			* ((((n_1 - 1.f) * v_1)
+			+ ((n_2 - 1.f) * v_2)
+			+ (((n_1 * n_2) / (n_1 + n_2))
+			* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+			/ (n_1 + n_2 - 1.f));
+	}
+
+	return a.mSumOfSquares;
+}
+
 void EventAccumulator::addSamples( const EventAccumulator& other, EBufferAppendType append_type )
 {
 	if (other.mNumSamples)
@@ -250,20 +277,7 @@ void EventAccumulator::addSamples( const EventAccumulator& other, EBufferAppendT
 			if (other.mMin < mMin) { mMin = other.mMin; }
 			if (other.mMax > mMax) { mMax = other.mMax; }
 
-			// combine variance (and hence standard deviation) of 2 different sized sample groups using
-			// the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
-			F64 n_1 = (F64)mNumSamples,
-				n_2 = (F64)other.mNumSamples;
-			F64 m_1 = mMean,
-				m_2 = other.mMean;
-			F64 v_1 = mSumOfSquares / mNumSamples,
-				v_2 = other.mSumOfSquares / other.mNumSamples;
-			mSumOfSquares = (F64)mNumSamples
-				* ((((n_1 - 1.f) * v_1)
-				+ ((n_2 - 1.f) * v_2)
-				+ (((n_1 * n_2) / (n_1 + n_2))
-				* ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
-				/ (n_1 + n_2 - 1.f));
+			mSumOfSquares = mergeSumsOfSquares(*this, other);
 
 			F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
 			mNumSamples += other.mNumSamples;
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index 2971907849..dfa037d7c0 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -276,6 +276,9 @@ namespace LLTrace
 		S32 getSampleCount() const       { return mNumSamples; }
 		bool hasValue() const			 { return mNumSamples > 0; }
 
+		// helper utility to calculate combined sumofsquares total
+		static F64 mergeSumsOfSquares(const EventAccumulator& a, const EventAccumulator& b);
+
 	private:
 		F64	mSum,
 			mLastValue;
@@ -359,10 +362,13 @@ namespace LLTrace
 		F64	getMean() const              { return mMean; }
 		F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); }
 		F64 getSumOfSquares() const		 { return mSumOfSquares; }
-		F64SecondsImplicit getSamplingTime() { return mTotalSamplingTime; }
+		F64SecondsImplicit getSamplingTime() const { return mTotalSamplingTime; }
 		S32 getSampleCount() const       { return mNumSamples; }
 		bool hasValue() const            { return mHasValue; }
 
+		// helper utility to calculate combined sumofsquares total
+		static F64 mergeSumsOfSquares(const SampleAccumulator& a, const SampleAccumulator& b);
+
 	private:
 		F64		mSum,
 				mLastValue;
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 5ec7ce56b9..0fd0053240 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -32,6 +32,11 @@
 #include "lltracethreadrecorder.h"
 #include "llthread.h"
 
+inline F64 lerp(F64 a, F64 b, F64 u) 
+{
+	return a + ((b - a) * u);
+}
+
 namespace LLTrace
 {
 
@@ -43,7 +48,7 @@ extern MemStatHandle gTraceMemStat;
 
 Recording::Recording(EPlayState state) 
 :	mElapsedSeconds(0),
-	mInHandOff(false)
+	mActiveBuffers(NULL)
 {
 	claim_alloc(gTraceMemStat, this);
 	mBuffers = new AccumulatorBufferGroup();
@@ -88,13 +93,20 @@ Recording::~Recording()
 	}
 }
 
+// brings recording to front of recorder stack, with up to date info
 void Recording::update()
 {
 	if (isStarted())
 	{
 		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
-		AccumulatorBufferGroup* buffers = mBuffers.write();
-		LLTrace::get_thread_recorder()->bringUpToDate(buffers);
+
+		llassert(mActiveBuffers);
+		if(!mActiveBuffers->isCurrent())
+		{
+			AccumulatorBufferGroup* buffers = mBuffers.write();
+			LLTrace::get_thread_recorder()->deactivate(buffers);
+			mActiveBuffers = LLTrace::get_thread_recorder()->activate(buffers);
+		}
 
 		mSamplingTimer.reset();
 	}
@@ -112,20 +124,19 @@ void Recording::handleStart()
 {
 	mSamplingTimer.reset();
 	mBuffers.setStayUnique(true);
-	LLTrace::get_thread_recorder()->activate(mBuffers.write(), mInHandOff);
-	mInHandOff = false;
+	mActiveBuffers = LLTrace::get_thread_recorder()->activate(mBuffers.write());
 }
 
 void Recording::handleStop()
 {
 	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
 	LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
+	mActiveBuffers = NULL;
 	mBuffers.setStayUnique(false);
 }
 
 void Recording::handleSplitTo(Recording& other)
 {
-	other.mInHandOff = true;
 	mBuffers.write()->handOffTo(*other.mBuffers.write());
 }
 
@@ -139,214 +150,378 @@ void Recording::appendRecording( Recording& other )
 
 bool Recording::hasValue(const StatType<TimeBlockAccumulator>& stat)
 {
-	return mBuffers->mStackTimers[stat.getIndex()].hasValue();
+	update();
+	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+	const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+	return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
 }
 
 F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator>& stat)
 {
+	update();
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
-	return F64Seconds((F64)(accumulator.mTotalTimeCounter) 
-				/ (F64)LLTrace::BlockTimerStatHandle::countsPerSecond());
+	const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+	return F64Seconds((F64)(accumulator.mTotalTimeCounter) + (F64)(active_accumulator ? active_accumulator->mTotalTimeCounter : 0))
+				/ (F64)LLTrace::BlockTimerStatHandle::countsPerSecond();
 }
 
 F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
+	update();
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
-	return F64Seconds((F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::BlockTimerStatHandle::countsPerSecond());
+	const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+	return F64Seconds((F64)(accumulator.mSelfTimeCounter) + (F64)(active_accumulator ? active_accumulator->mSelfTimeCounter : 0) / (F64)LLTrace::BlockTimerStatHandle::countsPerSecond());
 }
 
 
 S32 Recording::getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
 {
-	return mBuffers->mStackTimers[stat.getIndex()].mCalls;
+	update();
+	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+	const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+	return accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0);
 }
 
 F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator>& stat)
 {
+	update();
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+	const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
 
-	return F64Seconds((F64)(accumulator.mTotalTimeCounter) 
+	return F64Seconds((F64)(accumulator.mTotalTimeCounter + (active_accumulator ? active_accumulator->mTotalTimeCounter : 0)) 
 				/ ((F64)LLTrace::BlockTimerStatHandle::countsPerSecond() * mElapsedSeconds.value()));
 }
 
 F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
 {
+	update();
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+	const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
 
-	return F64Seconds((F64)(accumulator.mSelfTimeCounter) 
+	return F64Seconds((F64)(accumulator.mSelfTimeCounter + (active_accumulator ? active_accumulator->mSelfTimeCounter : 0))
 			/ ((F64)LLTrace::BlockTimerStatHandle::countsPerSecond() * mElapsedSeconds.value()));
 }
 
 F32 Recording::getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
 {
-	return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds.value();
+	update();
+	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+	const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+	return (F32)(accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0)) / mElapsedSeconds.value();
 }
 
 bool Recording::hasValue(const StatType<MemAccumulator>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mSize.hasValue();
+	update();
+	const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+	const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+	return accumulator.mSize.hasValue() || (active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.hasValue() : false);
 }
 
 F64Kilobytes Recording::getMin(const StatType<MemAccumulator>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMin());
+	update();
+	const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+	const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+	return F64Bytes(llmin(accumulator.mSize.getMin(), (active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.getMin() : F32_MAX)));
 }
 
 F64Kilobytes Recording::getMean(const StatType<MemAccumulator>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMean());
+	update();
+	const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+	const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+	
+	if (active_accumulator && active_accumulator->mSize.hasValue())
+	{
+		return F64Bytes(lerp(accumulator.mSize.getMean(), active_accumulator->mSize.getMean(), active_accumulator->mSize.getSampleCount() / (accumulator.mSize.getSampleCount() + active_accumulator->mSize.getSampleCount())));
+	}
+	else
+	{
+		return F64Bytes(accumulator.mSize.getMean());
+	}
 }
 
 F64Kilobytes Recording::getMax(const StatType<MemAccumulator>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMax());
+	update();
+	const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+	const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+	return F64Bytes(llmax(accumulator.mSize.getMax(), active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.getMax() : F32_MIN));
 }
 
 F64Kilobytes Recording::getStandardDeviation(const StatType<MemAccumulator>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation());
+	update();
+	const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+	const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+	if (active_accumulator && active_accumulator->hasValue())
+	{
+		F64 sum_of_squares = SampleAccumulator::mergeSumsOfSquares(accumulator.mSize, active_accumulator->mSize);
+		return F64Bytes(sqrtf(sum_of_squares / (accumulator.mSize.getSamplingTime().value() + active_accumulator->mSize.getSamplingTime().value())));
+	}
+	else
+	{
+		return F64Bytes(accumulator.mSize.getStandardDeviation());
+	}
 }
 
 F64Kilobytes Recording::getLastValue(const StatType<MemAccumulator>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue());
+	update();
+	const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+	const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+	return F64Bytes(active_accumulator ? active_accumulator->mSize.getLastValue() : accumulator.mSize.getLastValue());
 }
 
 bool Recording::hasValue(const StatType<MemAccumulator::AllocationFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mAllocations.hasValue();
+	update();
+	const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+	const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+	return accumulator.mAllocations.hasValue() || (active_accumulator ? active_accumulator->mAllocations.hasValue() : false);
 }
 
 F64Kilobytes Recording::getSum(const StatType<MemAccumulator::AllocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocations.getSum());
+	update();
+	const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+	const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+	return F64Bytes(accumulator.mAllocations.getSum() + (active_accumulator ? active_accumulator->mAllocations.getSum() : 0));
 }
 
 F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::AllocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mAllocations.getSum() / mElapsedSeconds.value());
+	update();
+	const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+	const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+	return F64Bytes((accumulator.mAllocations.getSum() + (active_accumulator ? active_accumulator->mAllocations.getSum() : 0)) / mElapsedSeconds.value());
 }
 
 S32 Recording::getSampleCount(const StatType<MemAccumulator::AllocationFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mAllocations.getSampleCount();
+	update();
+	const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+	const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+	return accumulator.mAllocations.getSampleCount() + (active_accumulator ? active_accumulator->mAllocations.getSampleCount() : 0);
 }
 
 bool Recording::hasValue(const StatType<MemAccumulator::DeallocationFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mDeallocations.hasValue();
+	update();
+	const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+	const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+	return accumulator.mDeallocations.hasValue() || (active_accumulator ? active_accumulator->mDeallocations.hasValue() : false);
 }
 
 
 F64Kilobytes Recording::getSum(const StatType<MemAccumulator::DeallocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSum());
+	update();
+	const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+	const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+	return F64Bytes(accumulator.mDeallocations.getSum() + (active_accumulator ? active_accumulator->mDeallocations.getSum() : 0));
 }
 
 F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::DeallocationFacet>& stat)
 {
-	return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSum() / mElapsedSeconds.value());
+	update();
+	const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+	const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+	return F64Bytes((accumulator.mDeallocations.getSum() + (active_accumulator ? active_accumulator->mDeallocations.getSum() : 0)) / mElapsedSeconds.value());
 }
 
 S32 Recording::getSampleCount(const StatType<MemAccumulator::DeallocationFacet>& stat)
 {
-	return mBuffers->mMemStats[stat.getIndex()].mDeallocations.getSampleCount();
+	update();
+	const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+	const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+	return accumulator.mDeallocations.getSampleCount() + (active_accumulator ? active_accumulator->mDeallocations.getSampleCount() : 0);
 }
 
 bool Recording::hasValue(const StatType<CountAccumulator>& stat)
 {
-	return mBuffers->mCounts[stat.getIndex()].hasValue();
+	update();
+	const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
+	const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
+	return accumulator.hasValue() || (active_accumulator ? active_accumulator->hasValue() : false);
 }
 
 F64 Recording::getSum(const StatType<CountAccumulator>& stat)
 {
-	return mBuffers->mCounts[stat.getIndex()].getSum();
-}
-
-F64 Recording::getSum( const StatType<EventAccumulator>& stat)
-{
-	return (F64)mBuffers->mEvents[stat.getIndex()].getSum();
+	update();
+	const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
+	const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
+	return accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0);
 }
 
 F64 Recording::getPerSec( const StatType<CountAccumulator>& stat )
 {
-	F64 sum = mBuffers->mCounts[stat.getIndex()].getSum();
-	return  sum / mElapsedSeconds.value();
+	update();
+	const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
+	const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
+	F64 sum = accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0);
+	return sum / mElapsedSeconds.value();
 }
 
 S32 Recording::getSampleCount( const StatType<CountAccumulator>& stat )
 {
-	return mBuffers->mCounts[stat.getIndex()].getSampleCount();
+	update();
+	const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
+	const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
+	return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0);
 }
 
 bool Recording::hasValue(const StatType<SampleAccumulator>& stat)
 {
-	return mBuffers->mSamples[stat.getIndex()].hasValue();
+	update();
+	const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+	const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+	return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
 }
 
 F64 Recording::getMin( const StatType<SampleAccumulator>& stat )
 {
-	return mBuffers->mSamples[stat.getIndex()].getMin();
+	update();
+	const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+	const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+	return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX);
 }
 
 F64 Recording::getMax( const StatType<SampleAccumulator>& stat )
 {
-	return mBuffers->mSamples[stat.getIndex()].getMax();
+	update();
+	const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+	const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+	return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN);
 }
 
 F64 Recording::getMean( const StatType<SampleAccumulator>& stat )
 {
-	return mBuffers->mSamples[stat.getIndex()].getMean();
+	update();
+	const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+	const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+	if (active_accumulator && active_accumulator->hasValue())
+	{
+		return lerp(accumulator.getMean(), active_accumulator->getMean(), active_accumulator->getSampleCount() / (accumulator.getSampleCount() + active_accumulator->getSampleCount()));
+	}
+	else
+	{
+		return accumulator.getMean();
+	}
 }
 
 F64 Recording::getStandardDeviation( const StatType<SampleAccumulator>& stat )
 {
-	return mBuffers->mSamples[stat.getIndex()].getStandardDeviation();
+	update();
+	const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+	const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+
+	if (active_accumulator && active_accumulator->hasValue())
+	{
+		F64 sum_of_squares = SampleAccumulator::mergeSumsOfSquares(accumulator, *active_accumulator);
+		return sqrtf(sum_of_squares / (accumulator.getSamplingTime() + active_accumulator->getSamplingTime()));
+	}
+	else
+	{
+		return accumulator.getStandardDeviation();
+	}
 }
 
 F64 Recording::getLastValue( const StatType<SampleAccumulator>& stat )
 {
-	return mBuffers->mSamples[stat.getIndex()].getLastValue();
+	update();
+	const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+	const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+	return (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getLastValue() : accumulator.getLastValue());
 }
 
 S32 Recording::getSampleCount( const StatType<SampleAccumulator>& stat )
 {
-	return mBuffers->mSamples[stat.getIndex()].getSampleCount();
+	update();
+	const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+	const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+	return accumulator.getSampleCount() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSampleCount() : 0);
 }
 
 bool Recording::hasValue(const StatType<EventAccumulator>& stat)
 {
-	return mBuffers->mEvents[stat.getIndex()].hasValue();
+	update();
+	const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+	const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+	return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
+}
+
+F64 Recording::getSum( const StatType<EventAccumulator>& stat)
+{
+	update();
+	const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+	const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+	return (F64)(accumulator.getSum() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSum() : 0));
 }
 
 F64 Recording::getMin( const StatType<EventAccumulator>& stat )
 {
-	return mBuffers->mEvents[stat.getIndex()].getMin();
+	update();
+	const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+	const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+	return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX);
 }
 
 F64 Recording::getMax( const StatType<EventAccumulator>& stat )
 {
-	return mBuffers->mEvents[stat.getIndex()].getMax();
+	update();
+	const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+	const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+	return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN);
 }
 
 F64 Recording::getMean( const StatType<EventAccumulator>& stat )
 {
-	return mBuffers->mEvents[stat.getIndex()].getMean();
+	update();
+	const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+	const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+	if (active_accumulator && active_accumulator->hasValue())
+	{
+		return lerp(accumulator.getMean(), active_accumulator->getMean(), active_accumulator->getSampleCount() / (accumulator.getSampleCount() + active_accumulator->getSampleCount()));
+	}
+	else
+	{
+		return accumulator.getMean();
+	}
 }
 
 F64 Recording::getStandardDeviation( const StatType<EventAccumulator>& stat )
 {
-	return mBuffers->mEvents[stat.getIndex()].getStandardDeviation();
+	update();
+	const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+	const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+
+	if (active_accumulator && active_accumulator->hasValue())
+	{
+		F64 sum_of_squares = EventAccumulator::mergeSumsOfSquares(accumulator, *active_accumulator);
+		return sqrtf(sum_of_squares / (accumulator.getSampleCount() + active_accumulator->getSampleCount()));
+	}
+	else
+	{
+		return accumulator.getStandardDeviation();
+	}
 }
 
 F64 Recording::getLastValue( const StatType<EventAccumulator>& stat )
 {
-	return mBuffers->mEvents[stat.getIndex()].getLastValue();
+	update();
+	const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+	const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+	return active_accumulator ? active_accumulator->getLastValue() : accumulator.getLastValue();
 }
 
 S32 Recording::getSampleCount( const StatType<EventAccumulator>& stat )
 {
-	return mBuffers->mEvents[stat.getIndex()].getSampleCount();
+	update();
+	const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+	const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+	return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0);
 }
 
 ///////////////////////////////////////////////////////////////////////
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index b045aafa11..93ac276e33 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -322,7 +322,7 @@ namespace LLTrace
 		LLTimer											mSamplingTimer;
 		F64Seconds										mElapsedSeconds;
 		LLCopyOnWritePointer<AccumulatorBufferGroup>	mBuffers;
-		bool											mInHandOff;
+		AccumulatorBufferGroup*							mActiveBuffers;
 
 	};
 
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 7b7da5343d..a70e94e4b1 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -131,7 +131,7 @@ TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode( S32 index )
 }
 
 
-void ThreadRecorder::activate( AccumulatorBufferGroup* recording, bool from_handoff )
+AccumulatorBufferGroup* ThreadRecorder::activate( AccumulatorBufferGroup* recording)
 {
 	ActiveRecording* active_recording = new ActiveRecording(recording);
 	if (!mActiveRecordings.empty())
@@ -144,6 +144,7 @@ void ThreadRecorder::activate( AccumulatorBufferGroup* recording, bool from_hand
 	mActiveRecordings.push_back(active_recording);
 
 	mActiveRecordings.back()->mPartialRecording.makeCurrent();
+	return &active_recording->mPartialRecording;
 }
 
 ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::bringUpToDate( AccumulatorBufferGroup* recording )
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index c6afcdac80..d30fa15ea7 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -47,7 +47,7 @@ namespace LLTrace
 
 		~ThreadRecorder();
 
-		void activate(AccumulatorBufferGroup* recording, bool from_handoff = false);
+		AccumulatorBufferGroup* activate(AccumulatorBufferGroup* recording);
 		void deactivate(AccumulatorBufferGroup* recording);
 		active_recording_list_t::iterator bringUpToDate(AccumulatorBufferGroup* recording);
 
diff --git a/indra/llcommon/tests/lltrace_test.cpp b/indra/llcommon/tests/lltrace_test.cpp
index 8ce509699d..0a9d85ad00 100644
--- a/indra/llcommon/tests/lltrace_test.cpp
+++ b/indra/llcommon/tests/lltrace_test.cpp
@@ -109,8 +109,9 @@ namespace tut
 			at_work.stop();
 			drink_coffee(1, S32VentiCup(1));
 		}
-		after_3pm.stop();
-		all_day.stop();
+		// don't need to stop recordings to get accurate values out of them
+		//after_3pm.stop();
+		//all_day.stop();
 
 		ensure("count stats are counted when recording is active", 
 			at_work.getSum(sCupsOfCoffeeConsumed) == 3 
-- 
cgit v1.2.3


From f4283778dd581801459c262d05b9f5d107505a7c Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Mon, 21 Oct 2013 14:50:53 -0700
Subject: fix for crash when copying trace recording

---
 indra/llcommon/lltracerecording.cpp | 1 +
 1 file changed, 1 insertion(+)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 0fd0053240..95d26f96c0 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -57,6 +57,7 @@ Recording::Recording(EPlayState state)
 }
 
 Recording::Recording( const Recording& other )
+:	mActiveBuffers(NULL)
 {
 	claim_alloc(gTraceMemStat, this);
 	*this = other;
-- 
cgit v1.2.3


From ab43be5ddb50198304de1ae0e82b641c7d343449 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 23 Oct 2013 13:24:47 -0700
Subject: moved some common functionality from LLTrace::BlockTimerStatHandle to
 BlockTimer updates appearance utility dependency

---
 indra/llcommon/llfasttimer.cpp               |  48 ++++----
 indra/llcommon/llfasttimer.h                 | 162 ++++++++++++++-------------
 indra/llcommon/llmetricperformancetester.cpp |   4 +-
 indra/llcommon/lltracerecording.cpp          |   8 +-
 indra/llcommon/lltracethreadrecorder.cpp     |   8 +-
 5 files changed, 116 insertions(+), 114 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 4744be7236..9b093e8936 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -60,14 +60,14 @@ namespace LLTrace
 //////////////////////////////////////////////////////////////////////////////
 // statics
 
-bool        BlockTimerStatHandle::sLog		     = false;
-std::string BlockTimerStatHandle::sLogName         = "";
-bool        BlockTimerStatHandle::sMetricLog       = false;
+bool        BlockTimer::sLog		     = false;
+std::string BlockTimer::sLogName         = "";
+bool        BlockTimer::sMetricLog       = false;
 
 #if LL_LINUX || LL_SOLARIS
-U64         BlockTimerStatHandle::sClockResolution = 1000000000; // Nanosecond resolution
+U64         BlockTimer::sClockResolution = 1000000000; // Nanosecond resolution
 #else
-U64         BlockTimerStatHandle::sClockResolution = 1000000; // Microsecond resolution
+U64         BlockTimer::sClockResolution = 1000000; // Microsecond resolution
 #endif
 
 static LLMutex*			sLogLock = NULL;
@@ -132,19 +132,19 @@ struct SortTimerByName
 };
 
 static BlockTimerStatHandle sRootTimer("root", NULL);
-BlockTimerStatHandle& BlockTimerStatHandle::getRootTimeBlock()
+BlockTimerStatHandle& BlockTimer::getRootTimeBlock()
 {
 	return sRootTimer;
 }
 
-void BlockTimerStatHandle::pushLog(LLSD log)
+void BlockTimer::pushLog(LLSD log)
 {
 	LLMutexLock lock(sLogLock);
 
 	sLogQueue.push(log);
 }
 
-void BlockTimerStatHandle::setLogLock(LLMutex* lock)
+void BlockTimer::setLogLock(LLMutex* lock)
 {
 	sLogLock = lock;
 }
@@ -152,12 +152,12 @@ void BlockTimerStatHandle::setLogLock(LLMutex* lock)
 
 //static
 #if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
-U64 BlockTimerStatHandle::countsPerSecond()
+U64 BlockTimer::countsPerSecond()
 {
 	return sClockResolution;
 }
 #else // windows or x86-mac or x86-linux or x86-solaris
-U64 BlockTimerStatHandle::countsPerSecond()
+U64 BlockTimer::countsPerSecond()
 {
 #if LL_FASTTIMER_USE_RDTSC || !LL_WINDOWS
 	//getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz
@@ -191,18 +191,18 @@ TimeBlockTreeNode& BlockTimerStatHandle::getTreeNode() const
 }
 
 
-void BlockTimerStatHandle::bootstrapTimerTree()
+void BlockTimer::bootstrapTimerTree()
 {
 	for (BlockTimerStatHandle::instance_tracker_t::instance_iter it = BlockTimerStatHandle::instance_tracker_t::beginInstances(), end_it = BlockTimerStatHandle::instance_tracker_t::endInstances(); 
 		it != end_it; 
 		++it)
 	{
 		BlockTimerStatHandle& timer = static_cast<BlockTimerStatHandle&>(*it);
-		if (&timer == &BlockTimerStatHandle::getRootTimeBlock()) continue;
+		if (&timer == &BlockTimer::getRootTimeBlock()) continue;
 
 		// bootstrap tree construction by attaching to last timer to be on stack
 		// when this timer was called
-		if (timer.getParent() == &BlockTimerStatHandle::getRootTimeBlock())
+		if (timer.getParent() == &BlockTimer::getRootTimeBlock())
 		{
 			TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
 
@@ -220,9 +220,9 @@ void BlockTimerStatHandle::bootstrapTimerTree()
 // bump timers up tree if they have 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
-void BlockTimerStatHandle::incrementalUpdateTimerTree()
+void BlockTimer::incrementalUpdateTimerTree()
 {
-	for(block_timer_tree_df_post_iterator_t it = begin_block_timer_tree_df_post(BlockTimerStatHandle::getRootTimeBlock());
+	for(block_timer_tree_df_post_iterator_t it = begin_block_timer_tree_df_post(BlockTimer::getRootTimeBlock());
 		it != end_block_timer_tree_df_post();
 		++it)
 	{
@@ -236,7 +236,7 @@ void BlockTimerStatHandle::incrementalUpdateTimerTree()
 		}
 
 		// skip root timer
-		if (timerp != &BlockTimerStatHandle::getRootTimeBlock())
+		if (timerp != &BlockTimer::getRootTimeBlock())
 		{
 			TimeBlockAccumulator& accumulator = timerp->getCurrentAccumulator();
 
@@ -260,7 +260,7 @@ void BlockTimerStatHandle::incrementalUpdateTimerTree()
 }
 
 
-void BlockTimerStatHandle::updateTimes()
+void BlockTimer::updateTimes()
 {
 	// walk up stack of active timers and accumulate current time while leaving timing structures active
 	BlockTimerStackRecord* stack_record	= LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
@@ -292,7 +292,7 @@ static LLTrace::BlockTimerStatHandle FTM_PROCESS_TIMES("Process FastTimer Times"
 
 // not thread safe, so only call on main thread
 //static
-void BlockTimerStatHandle::processTimes()
+void BlockTimer::processTimes()
 {
 	LL_RECORD_BLOCK_TIME(FTM_PROCESS_TIMES);
 	get_clock_count(); // good place to calculate clock frequency
@@ -339,7 +339,7 @@ bool BlockTimerStatHandle::hasChildren()
 }
 
 // static
-void BlockTimerStatHandle::logStats()
+void BlockTimer::logStats()
 {
 	// get ready for next frame
 	if (sLog)
@@ -388,13 +388,13 @@ void BlockTimerStatHandle::logStats()
 }
 
 //static
-void BlockTimerStatHandle::dumpCurTimes()
+void BlockTimer::dumpCurTimes()
 {
 	LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
 	LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording();
 
 	// walk over timers in depth order and output timings
-	for(block_timer_tree_df_iterator_t it = begin_timer_tree(BlockTimerStatHandle::getRootTimeBlock());
+	for(block_timer_tree_df_iterator_t it = begin_timer_tree(BlockTimer::getRootTimeBlock());
 		it != end_timer_tree();
 		++it)
 	{
@@ -422,7 +422,7 @@ void BlockTimerStatHandle::dumpCurTimes()
 }
 
 //static 
-void BlockTimerStatHandle::writeLog(std::ostream& os)
+void BlockTimer::writeLog(std::ostream& os)
 {
 	while (!sLogQueue.empty())
 	{
@@ -478,9 +478,9 @@ void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
 
 F64Seconds BlockTimer::getElapsedTime()
 {
-	U64 total_time = BlockTimerStatHandle::getCPUClockCount64() - mStartTime;
+	U64 total_time = getCPUClockCount64() - mStartTime;
 
-	return F64Seconds((F64)total_time / (F64)BlockTimerStatHandle::countsPerSecond());
+	return F64Seconds((F64)total_time / (F64)BlockTimer::countsPerSecond());
 }
 
 
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 614e7fdb4c..2370253078 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -51,77 +51,7 @@ public:
 
 	F64Seconds getElapsedTime();
 
-private:
-	friend class BlockTimerStatHandle;
-	// FIXME: this friendship exists so that each thread can instantiate a root timer, 
-	// which could be a derived class with a public constructor instead, possibly
-	friend class ThreadRecorder; 
-	friend BlockTimer timeThisBlock(BlockTimerStatHandle&); 
-
-	BlockTimer(BlockTimerStatHandle& timer);
-#if !defined(MSC_VER) || MSC_VER < 1700
-	// Visual Studio 2010 has a bug where capturing an object returned by value
-	// into a local reference requires access to the copy constructor at the call site.
-	// This appears to be fixed in 2012.
-public:
-#endif
-	// no-copy
-	BlockTimer(const BlockTimer& other) {};
-
-private:
-	U64						mStartTime;
-	BlockTimerStackRecord	mParentTimerData;
-};
-
-// this dummy function assists in allocating a block timer with stack-based lifetime.
-// this is done by capturing the return value in a stack-allocated const reference variable.  
-// (This is most easily done using the macro LL_RECORD_BLOCK_TIME)
-// Otherwise, it would be possible to store a BlockTimer on the heap, resulting in non-nested lifetimes, 
-// which would break the invariants of the timing hierarchy logic
-LL_FORCE_INLINE class BlockTimer timeThisBlock(class BlockTimerStatHandle& timer)
-{
-	return BlockTimer(timer);
-}
-
-// stores a "named" timer instance to be reused via multiple BlockTimer stack instances
-class BlockTimerStatHandle 
-:	public StatType<TimeBlockAccumulator>
-{
-public:
-	BlockTimerStatHandle(const char* name, const char* description = "");
-
-	TimeBlockTreeNode& getTreeNode() const;
-	BlockTimerStatHandle* getParent() const { return getTreeNode().getParent(); }
-	void setParent(BlockTimerStatHandle* parent) { getTreeNode().setParent(parent); }
-
-	typedef std::vector<BlockTimerStatHandle*>::iterator child_iter;
-	typedef std::vector<BlockTimerStatHandle*>::const_iterator child_const_iter;
-	child_iter beginChildren();
-	child_iter endChildren();
-	bool hasChildren();
-	std::vector<BlockTimerStatHandle*>& getChildren();
-
-	StatType<TimeBlockAccumulator::CallCountFacet>& callCount() 
-	{
-		return static_cast<StatType<TimeBlockAccumulator::CallCountFacet>&>(*(StatType<TimeBlockAccumulator>*)this);
-	}
-
-	StatType<TimeBlockAccumulator::SelfTimeFacet>& selfTime() 
-	{
-		return static_cast<StatType<TimeBlockAccumulator::SelfTimeFacet>&>(*(StatType<TimeBlockAccumulator>*)this);
-	}
-
-	static BlockTimerStatHandle& getRootTimeBlock();
-	static void pushLog(LLSD sd);
-	static void setLogLock(class LLMutex* mutex);
-	static void writeLog(std::ostream& os);
-	static void updateTimes();
-
-	// dumps current cumulative frame stats to log
-	// call nextFrame() to reset timers
-	static void dumpCurTimes();
-
-	//////////////////////////////////////////////////////////////////////////////
+		//////////////////////////////////////////////////////////////////////////////
 	//
 	// Important note: These implementations must be FAST!
 	//
@@ -143,14 +73,14 @@ public:
 	//#undef _interlockedbittestandset
 	//#undef _interlockedbittestandreset
 
-	//inline U32 BlockTimerStatHandle::getCPUClockCount32()
+	//inline U32 getCPUClockCount32()
 	//{
 	//	U64 time_stamp = __rdtsc();
 	//	return (U32)(time_stamp >> 8);
 	//}
 	//
 	//// return full timer value, *not* shifted by 8 bits
-	//inline U64 BlockTimerStatHandle::getCPUClockCount64()
+	//inline U64 getCPUClockCount64()
 	//{
 	//	return __rdtsc();
 	//}
@@ -257,6 +187,12 @@ public:
 
 #endif
 
+	static BlockTimerStatHandle& getRootTimeBlock();
+	static void pushLog(LLSD sd);
+	static void setLogLock(class LLMutex* mutex);
+	static void writeLog(std::ostream& os);
+	static void updateTimes();
+	
 	static U64 countsPerSecond();
 
 	// updates cumulative times and hierarchy,
@@ -269,13 +205,79 @@ public:
 	// call this once a frame to periodically log timers
 	static void logStats();
 
-	bool						mCollapsed;				// don't show children
+	// dumps current cumulative frame stats to log
+	// call nextFrame() to reset timers
+	static void dumpCurTimes();
+
+private:
+	friend class BlockTimerStatHandle;
+	// FIXME: this friendship exists so that each thread can instantiate a root timer, 
+	// which could be a derived class with a public constructor instead, possibly
+	friend class ThreadRecorder; 
+	friend BlockTimer timeThisBlock(BlockTimerStatHandle&); 
+
+	BlockTimer(BlockTimerStatHandle& timer);
+#if !defined(MSC_VER) || MSC_VER < 1700
+	// Visual Studio 2010 has a bug where capturing an object returned by value
+	// into a local reference requires access to the copy constructor at the call site.
+	// This appears to be fixed in 2012.
+public:
+#endif
+	// no-copy
+	BlockTimer(const BlockTimer& other) {};
+
+private:
+	U64						mStartTime;
+	BlockTimerStackRecord	mParentTimerData;
 
+public:
 	// statics
-	static std::string							sLogName;
-	static bool									sMetricLog,
-												sLog;	
-	static U64									sClockResolution;
+	static std::string		sLogName;
+	static bool				sMetricLog,
+							sLog;	
+	static U64				sClockResolution;
+
+};
+
+// this dummy function assists in allocating a block timer with stack-based lifetime.
+// this is done by capturing the return value in a stack-allocated const reference variable.  
+// (This is most easily done using the macro LL_RECORD_BLOCK_TIME)
+// Otherwise, it would be possible to store a BlockTimer on the heap, resulting in non-nested lifetimes, 
+// which would break the invariants of the timing hierarchy logic
+LL_FORCE_INLINE class BlockTimer timeThisBlock(class BlockTimerStatHandle& timer)
+{
+	return BlockTimer(timer);
+}
+
+// stores a "named" timer instance to be reused via multiple BlockTimer stack instances
+class BlockTimerStatHandle 
+:	public StatType<TimeBlockAccumulator>
+{
+public:
+	BlockTimerStatHandle(const char* name, const char* description = "");
+
+	TimeBlockTreeNode& getTreeNode() const;
+	BlockTimerStatHandle* getParent() const { return getTreeNode().getParent(); }
+	void setParent(BlockTimerStatHandle* parent) { getTreeNode().setParent(parent); }
+
+	typedef std::vector<BlockTimerStatHandle*>::iterator child_iter;
+	typedef std::vector<BlockTimerStatHandle*>::const_iterator child_const_iter;
+	child_iter beginChildren();
+	child_iter endChildren();
+	bool hasChildren();
+	std::vector<BlockTimerStatHandle*>& getChildren();
+
+	StatType<TimeBlockAccumulator::CallCountFacet>& callCount() 
+	{
+		return static_cast<StatType<TimeBlockAccumulator::CallCountFacet>&>(*(StatType<TimeBlockAccumulator>*)this);
+	}
+
+	StatType<TimeBlockAccumulator::SelfTimeFacet>& selfTime() 
+	{
+		return static_cast<StatType<TimeBlockAccumulator::SelfTimeFacet>&>(*(StatType<TimeBlockAccumulator>*)this);
+	}
+
+	bool						mCollapsed;				// don't show children
 };
 
 // iterators and helper functions for walking the call hierarchy of block timers in different ways
@@ -307,14 +309,14 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(BlockTimerStatHandle& timer)
 	cur_timer_data->mTimeBlock = &timer;
 	cur_timer_data->mChildTime = 0;
 
-	mStartTime = BlockTimerStatHandle::getCPUClockCount64();
+	mStartTime = getCPUClockCount64();
 #endif
 }
 
 LL_FORCE_INLINE BlockTimer::~BlockTimer()
 {
 #if LL_FAST_TIMER_ON
-	U64 total_time = BlockTimerStatHandle::getCPUClockCount64() - mStartTime;
+	U64 total_time = getCPUClockCount64() - mStartTime;
 	BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
 	if (!cur_timer_data) return;
 
diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp
index 7963485456..1fc821d9a9 100755
--- a/indra/llcommon/llmetricperformancetester.cpp
+++ b/indra/llcommon/llmetricperformancetester.cpp
@@ -91,7 +91,7 @@ LLMetricPerformanceTesterBasic* LLMetricPerformanceTesterBasic::getTester(std::s
 // Return TRUE if this metric is requested or if the general default "catch all" metric is requested
 BOOL LLMetricPerformanceTesterBasic::isMetricLogRequested(std::string name)
 {
-	return (LLTrace::BlockTimerStatHandle::sMetricLog && ((LLTrace::BlockTimerStatHandle::sLogName == name) || (LLTrace::BlockTimerStatHandle::sLogName == DEFAULT_METRIC_NAME)));
+	return (LLTrace::BlockTimer::sMetricLog && ((LLTrace::BlockTimer::sLogName == name) || (LLTrace::BlockTimer::sLogName == DEFAULT_METRIC_NAME)));
 }
 
 /*static*/ 
@@ -194,7 +194,7 @@ void LLMetricPerformanceTesterBasic::preOutputTestResults(LLSD* sd)
 
 void LLMetricPerformanceTesterBasic::postOutputTestResults(LLSD* sd)
 {
-	LLTrace::BlockTimerStatHandle::pushLog(*sd);
+	LLTrace::BlockTimer::pushLog(*sd);
 }
 
 void LLMetricPerformanceTesterBasic::outputTestResults() 
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index 95d26f96c0..dbf6771e66 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -163,7 +163,7 @@ F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator>& stat)
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 	const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
 	return F64Seconds((F64)(accumulator.mTotalTimeCounter) + (F64)(active_accumulator ? active_accumulator->mTotalTimeCounter : 0))
-				/ (F64)LLTrace::BlockTimerStatHandle::countsPerSecond();
+				/ (F64)LLTrace::BlockTimer::countsPerSecond();
 }
 
 F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
@@ -171,7 +171,7 @@ F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>
 	update();
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 	const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
-	return F64Seconds((F64)(accumulator.mSelfTimeCounter) + (F64)(active_accumulator ? active_accumulator->mSelfTimeCounter : 0) / (F64)LLTrace::BlockTimerStatHandle::countsPerSecond());
+	return F64Seconds((F64)(accumulator.mSelfTimeCounter) + (F64)(active_accumulator ? active_accumulator->mSelfTimeCounter : 0) / (F64)LLTrace::BlockTimer::countsPerSecond());
 }
 
 
@@ -190,7 +190,7 @@ F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator>& stat)
 	const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
 
 	return F64Seconds((F64)(accumulator.mTotalTimeCounter + (active_accumulator ? active_accumulator->mTotalTimeCounter : 0)) 
-				/ ((F64)LLTrace::BlockTimerStatHandle::countsPerSecond() * mElapsedSeconds.value()));
+				/ ((F64)LLTrace::BlockTimer::countsPerSecond() * mElapsedSeconds.value()));
 }
 
 F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
@@ -200,7 +200,7 @@ F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFac
 	const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
 
 	return F64Seconds((F64)(accumulator.mSelfTimeCounter + (active_accumulator ? active_accumulator->mSelfTimeCounter : 0))
-			/ ((F64)LLTrace::BlockTimerStatHandle::countsPerSecond() * mElapsedSeconds.value()));
+			/ ((F64)LLTrace::BlockTimer::countsPerSecond() * mElapsedSeconds.value()));
 }
 
 F32 Recording::getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index a70e94e4b1..aec36ef2c4 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -50,7 +50,7 @@ void ThreadRecorder::init()
 	LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(&mBlockTimerStackRecord);
 	//NB: the ordering of initialization in this function is very fragile due to a large number of implicit dependencies
 	set_thread_recorder(this);
-	BlockTimerStatHandle& root_time_block = BlockTimerStatHandle::getRootTimeBlock();
+	BlockTimerStatHandle& root_time_block = BlockTimer::getRootTimeBlock();
 
 	BlockTimerStackRecord* timer_stack = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
 	timer_stack->mTimeBlock = &root_time_block;
@@ -78,7 +78,7 @@ void ThreadRecorder::init()
 	mRootTimer = new BlockTimer(root_time_block);
 	timer_stack->mActiveTimer = mRootTimer;
 
-	BlockTimerStatHandle::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1;
+	BlockTimer::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1;
 
 	claim_alloc(gTraceMemStat, this);
 	claim_alloc(gTraceMemStat, mRootTimer);
@@ -138,7 +138,7 @@ AccumulatorBufferGroup* ThreadRecorder::activate( AccumulatorBufferGroup* record
 	{
 		AccumulatorBufferGroup& prev_active_recording = mActiveRecordings.back()->mPartialRecording;
 		prev_active_recording.sync();
-		BlockTimerStatHandle::updateTimes();
+		BlockTimer::updateTimes();
 		prev_active_recording.handOffTo(active_recording->mPartialRecording);
 	}
 	mActiveRecordings.push_back(active_recording);
@@ -152,7 +152,7 @@ ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::bringUpToDate(
 	if (mActiveRecordings.empty()) return mActiveRecordings.end();
 
 	mActiveRecordings.back()->mPartialRecording.sync();
-	BlockTimerStatHandle::updateTimes();
+	BlockTimer::updateTimes();
 
 	active_recording_list_t::reverse_iterator it, end_it;
 	for (it = mActiveRecordings.rbegin(), end_it = mActiveRecordings.rend();
-- 
cgit v1.2.3


From dc60a7564abf16cbf269e47cfc33ed00c6bb0870 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 24 Oct 2013 14:37:57 -0700
Subject: SH-4577 WIP Interesting: viewer crashed when clicking a offline
 Conversation containing a shared object potential fix by making instance
 tracker allow key collisions for LLToastNotifyPanel changed assertion macro
 to use original unpreprocessed source code renamed instance tracker behavior
 macros to use LL prefix added RestoreCameraPosOnLogin setting to optionally
 restore old camera positioning behavior

---
 indra/llcommon/llerror.h              | 8 +++++---
 indra/llcommon/llinstancetracker.h    | 8 ++++----
 indra/llcommon/llthreadlocalstorage.h | 2 +-
 indra/llcommon/lltrace.h              | 4 ++--
 4 files changed, 12 insertions(+), 10 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 046cd69543..5268cf9a4d 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -72,11 +72,13 @@ const int LL_ERR_NOERR = 0;
 
 #endif // !_DEBUG
 
-#define llassert_always(func)	if (LL_UNLIKELY(!(func))) LL_ERRS() << "ASSERT (" << #func << ")" << LL_ENDL;
+#define llassert_always_msg(func, msg) if (LL_UNLIKELY(!(func))) LL_ERRS() << "ASSERT (" << msg << ")" << LL_ENDL
+
+#define llassert_always(func)	llassert_always_msg(func, #func)
 
 #ifdef SHOW_ASSERT
-#define llassert(func)			llassert_always(func)
-#define llverify(func)			llassert_always(func)
+#define llassert(func)			llassert_always_msg(func, #func)
+#define llverify(func)			llassert_always_msg(func, #func)
 #else
 #define llassert(func)
 #define llverify(func)			do {if (func) {}} while(0)
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 3fdb84cfd7..3107415ccf 100755
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -64,8 +64,8 @@ LL_COMMON_API void assert_main_thread();
 
 enum EInstanceTrackerAllowKeyCollisions
 {
-	InstanceTrackerAllowKeyCollisions,
-	InstanceTrackerDisallowKeyCollisions
+	LLInstanceTrackerAllowKeyCollisions,
+	LLInstanceTrackerDisallowKeyCollisions
 };
 
 /// This mix-in class adds support for tracking all instances of the specified class parameter T
@@ -73,7 +73,7 @@ enum EInstanceTrackerAllowKeyCollisions
 /// If KEY is not provided, then instances are stored in a simple set
 /// @NOTE: see explicit specialization below for default KEY==void case
 /// @NOTE: this class is not thread-safe unless used as read-only
-template<typename T, typename KEY = void, EInstanceTrackerAllowKeyCollisions ALLOW_KEY_COLLISIONS = InstanceTrackerDisallowKeyCollisions>
+template<typename T, typename KEY = void, EInstanceTrackerAllowKeyCollisions ALLOW_KEY_COLLISIONS = LLInstanceTrackerDisallowKeyCollisions>
 class LLInstanceTracker : public LLInstanceTrackerBase
 {
 	typedef LLInstanceTracker<T, KEY> self_t;
@@ -216,7 +216,7 @@ private:
 		mInstanceKey = key; 
 		InstanceMap& map = getMap_();
 		typename InstanceMap::iterator insertion_point_it = map.lower_bound(key);
-		if (ALLOW_KEY_COLLISIONS == InstanceTrackerDisallowKeyCollisions
+		if (ALLOW_KEY_COLLISIONS == LLInstanceTrackerDisallowKeyCollisions
 			&& insertion_point_it != map.end() 
 			&& insertion_point_it->first == key)
 		{
diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
index 177e822227..ec3b52c8cb 100644
--- a/indra/llcommon/llthreadlocalstorage.h
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -43,7 +43,7 @@ public:
 	}
 
 	LLThreadLocalPointerBase( const LLThreadLocalPointerBase& other)
-		:	mThreadKey(NULL)
+	:	mThreadKey(NULL)
 	{
 		if (sInitialized)
 		{
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index b499036af2..8b67dd8f44 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -69,10 +69,10 @@ protected:
 template<typename ACCUMULATOR>
 class StatType 
 :	public StatBase,
-	public LLInstanceTracker<StatType<ACCUMULATOR>, std::string, InstanceTrackerAllowKeyCollisions>
+	public LLInstanceTracker<StatType<ACCUMULATOR>, std::string, LLInstanceTrackerAllowKeyCollisions>
 {
 public:
-	typedef LLInstanceTracker<StatType<ACCUMULATOR>, std::string, InstanceTrackerAllowKeyCollisions> instance_tracker_t;
+	typedef LLInstanceTracker<StatType<ACCUMULATOR>, std::string, LLInstanceTrackerAllowKeyCollisions> instance_tracker_t;
 	StatType(const char* name, const char* description)
 	:	instance_tracker_t(name),
 		StatBase(name, description),
-- 
cgit v1.2.3


From 555cf227ffed470184b55bc5a87b125da66f0a16 Mon Sep 17 00:00:00 2001
From: Xiaohong Bao <bao@lindenlab.com>
Date: Fri, 25 Oct 2013 10:29:45 -0600
Subject: trivial: fix several weird compiling errors.

---
 indra/llcommon/llqueuedthread.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index 176761c17c..8cef4293cd 100755
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -246,7 +246,7 @@ bool LLQueuedThread::addRequest(QueuedRequest* req)
 // MAIN thread
 bool LLQueuedThread::waitForResult(LLQueuedThread::handle_t handle, bool auto_complete)
 {
-	llassert (handle != nullHandle())
+	llassert (handle != nullHandle());
 	bool res = false;
 	bool waspaused = isPaused();
 	bool done = false;
-- 
cgit v1.2.3


From 155ca2f926afcbfd86b42ce6db68684ed266ef67 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 29 Oct 2013 16:23:53 -0700
Subject: fixed timer bars not appearing in fast timer view fixed "bouncing"
 stat values when a value ended in zeroes

---
 indra/llcommon/lltracerecording.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index dbf6771e66..ce09c32db5 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -171,7 +171,7 @@ F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>
 	update();
 	const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
 	const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
-	return F64Seconds((F64)(accumulator.mSelfTimeCounter) + (F64)(active_accumulator ? active_accumulator->mSelfTimeCounter : 0) / (F64)LLTrace::BlockTimer::countsPerSecond());
+	return F64Seconds(((F64)(accumulator.mSelfTimeCounter) + (F64)(active_accumulator ? active_accumulator->mSelfTimeCounter : 0)) / (F64)LLTrace::BlockTimer::countsPerSecond());
 }
 
 
-- 
cgit v1.2.3


From e6110bb1cc88c7d353caaeb698e4764e846d521f Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 15 Nov 2013 22:06:41 -0800
Subject: fix for fast timer view having runaway time slot wasn't stopping
 recording when merging into fast timer view stream

---
 indra/llcommon/lltracerecording.cpp | 48 ++++++++++++++-----------------------
 indra/llcommon/lltracerecording.h   | 29 ++++++++++------------
 2 files changed, 31 insertions(+), 46 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index ce09c32db5..cd837c0867 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -532,7 +532,7 @@ S32 Recording::getSampleCount( const StatType<EventAccumulator>& stat )
 PeriodicRecording::PeriodicRecording( S32 num_periods, EPlayState state) 
 :	mAutoResize(num_periods == 0),
 	mCurPeriod(0),
-	mNumPeriods(0),
+	mNumRecordedPeriods(0),
 	mRecordingPeriods(num_periods ? num_periods : 1)
 {
 	setPlayState(state);
@@ -555,7 +555,7 @@ void PeriodicRecording::nextPeriod()
 	mCurPeriod = (mCurPeriod + 1) % mRecordingPeriods.size();
 	old_recording.splitTo(getCurRecording());
 
-	mNumPeriods = llmin((S32)mRecordingPeriods.size(), mNumPeriods + 1);
+	mNumRecordedPeriods = llmin((S32)mRecordingPeriods.size() - 1, mNumRecordedPeriods + 1);
 }
 
 void PeriodicRecording::appendRecording(Recording& recording)
@@ -575,7 +575,7 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 	const S32 other_recording_slots = other.mRecordingPeriods.size();
 	const S32 other_num_recordings = other.getNumRecordedPeriods();
 	const S32 other_current_recording_index = other.mCurPeriod;
-	const S32 other_oldest_recording_index = (other_current_recording_index + other_recording_slots - other_num_recordings + 1) % other_recording_slots;
+	const S32 other_oldest_recording_index = (other_current_recording_index + other_recording_slots - other_num_recordings) % other_recording_slots;
 
 	// append first recording into our current slot
 	getCurRecording().appendRecording(other.mRecordingPeriods[other_oldest_recording_index]);
@@ -600,7 +600,7 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 		}
 
 		mCurPeriod = mRecordingPeriods.size() - 1;
-		mNumPeriods = mRecordingPeriods.size();
+		mNumRecordedPeriods = mRecordingPeriods.size() - 1;
 	}
 	else
 	{
@@ -629,7 +629,7 @@ void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
 		llassert(num_to_copy >= 1);
 		// advance to last recording period copied, and make that our current period
 		mCurPeriod = (mCurPeriod + num_to_copy - 1) % mRecordingPeriods.size();
-		mNumPeriods = llmin((S32)mRecordingPeriods.size(), mNumPeriods + num_to_copy - 1);
+		mNumRecordedPeriods = llmin((S32)mRecordingPeriods.size() - 1, mNumRecordedPeriods + num_to_copy - 1);
 	}
 
 	// end with fresh period, otherwise next appendPeriodicRecording() will merge the first
@@ -722,7 +722,7 @@ void PeriodicRecording::handleReset()
 		}
 	}
 	mCurPeriod = 0;
-	mNumPeriods = 0;
+	mNumRecordedPeriods = 0;
 	getCurRecording().setPlayState(getPlayState());
 }
 
@@ -733,8 +733,7 @@ void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
 
 F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	S32 total_periods = mRecordingPeriods.size();
-	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+	num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 	bool has_value = false;
 	F64 min_val = std::numeric_limits<F64>::max();
@@ -755,8 +754,7 @@ F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, S32
 
 F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	S32 total_periods = mRecordingPeriods.size();
-	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+	num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 	bool has_value = false;
 	F64 max_val = std::numeric_limits<F64>::min();
@@ -778,8 +776,7 @@ F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, S32
 // calculates means using aggregates per period
 F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	S32 total_periods = mRecordingPeriods.size();
-	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+	num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 	F64 mean = 0;
 	S32 valid_period_count = 0;
@@ -802,8 +799,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, S3
 
 F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	S32 total_periods = mRecordingPeriods.size();
-	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+	num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 	F64 period_mean = getPeriodMean(stat, num_periods);
 	F64 sum_of_squares = 0;
@@ -827,8 +823,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulat
 
 F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	S32 total_periods = mRecordingPeriods.size();
-	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+	num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 	bool has_value = false;
 	F64 min_val = std::numeric_limits<F64>::max();
@@ -849,8 +844,7 @@ F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, S3
 
 F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/)
 {
-	S32 total_periods = mRecordingPeriods.size();
-	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+	num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 	bool has_value = false;
 	F64 max_val = std::numeric_limits<F64>::min();
@@ -872,8 +866,7 @@ F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, S32
 
 F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	S32 total_periods = mRecordingPeriods.size();
-	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+	num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 	S32 valid_period_count = 0;
 	F64 mean = 0;
@@ -895,8 +888,7 @@ F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, S
 
 F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	S32 total_periods = mRecordingPeriods.size();
-	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+	num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 	F64 period_mean = getPeriodMean(stat, num_periods);
 	S32 valid_period_count = 0;
@@ -921,8 +913,7 @@ F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumula
 
 F64Kilobytes PeriodicRecording::getPeriodMin( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	S32 total_periods = mRecordingPeriods.size();
-	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+	num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 	F64Kilobytes min_val(std::numeric_limits<F64>::max());
 	for (S32 i = 1; i <= num_periods; i++)
@@ -941,8 +932,7 @@ F64Kilobytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, S32 num_
 
 F64Kilobytes PeriodicRecording::getPeriodMax(const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/)
 {
-	S32 total_periods = mRecordingPeriods.size();
-	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+	num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 	F64Kilobytes max_val(0.0);
 	for (S32 i = 1; i <= num_periods; i++)
@@ -961,8 +951,7 @@ F64Kilobytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, S32 num_
 
 F64Kilobytes PeriodicRecording::getPeriodMean( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	S32 total_periods = mRecordingPeriods.size();
-	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+	num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 	F64Kilobytes mean(0);
 
@@ -982,8 +971,7 @@ F64Kilobytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, S32 num
 
 F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
 {
-	S32 total_periods = mRecordingPeriods.size();
-	num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+	num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 	F64Kilobytes period_mean = getPeriodMean(stat, num_periods);
 	S32 valid_period_count = 0;
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
index 93ac276e33..d0b4a842a6 100644
--- a/indra/llcommon/lltracerecording.h
+++ b/indra/llcommon/lltracerecording.h
@@ -334,7 +334,11 @@ namespace LLTrace
 		~PeriodicRecording();
 
 		void nextPeriod();
-		S32 getNumRecordedPeriods() { return mNumPeriods; }
+		S32 getNumRecordedPeriods() 
+		{ 
+			// current period counts if not active
+			return mNumRecordedPeriods + (isStarted() ? 0 : 1); 
+		}
 
 		F64Seconds getDuration() const;
 
@@ -351,8 +355,7 @@ namespace LLTrace
 		template <typename T>
 		S32 getSampleCount(const StatType<T>& stat, S32 num_periods = S32_MAX)
         {
-			S32 total_periods = mNumPeriods;
-			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+			num_periods = llmin(num_periods, getNumRecordedPeriods());
 
             S32 num_samples = 0;
 			for (S32 i = 1; i <= num_periods; i++)
@@ -371,8 +374,7 @@ namespace LLTrace
 		template <typename T>
 		typename T::value_t getPeriodMin(const StatType<T>& stat, S32 num_periods = S32_MAX)
 		{
-			S32 total_periods = mNumPeriods;
-			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+			num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 			bool has_value = false;
 			typename T::value_t min_val(std::numeric_limits<typename T::value_t>::max());
@@ -417,8 +419,7 @@ namespace LLTrace
 		template <typename T>
 		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX)
 		{
-			S32 total_periods = mNumPeriods;
-			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+			num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 			typename RelatedTypes<typename T::value_t>::fractional_t min_val(std::numeric_limits<F64>::max());
 			for (S32 i = 1; i <= num_periods; i++)
@@ -443,8 +444,7 @@ namespace LLTrace
 		template <typename T>
 		typename T::value_t getPeriodMax(const StatType<T>& stat, S32 num_periods = S32_MAX)
 		{
-			S32 total_periods = mNumPeriods;
-			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+			num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 			bool has_value = false;
 			typename T::value_t max_val(std::numeric_limits<typename T::value_t>::min());
@@ -489,8 +489,7 @@ namespace LLTrace
 		template <typename T>
 		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX)
 		{
-			S32 total_periods = mNumPeriods;
-			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+			num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 			F64 max_val = std::numeric_limits<F64>::min();
 			for (S32 i = 1; i <= num_periods; i++)
@@ -515,8 +514,7 @@ namespace LLTrace
 		template <typename T>
 		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, S32 num_periods = S32_MAX)
 		{
-			S32 total_periods = mNumPeriods;
-			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+			num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 			typename RelatedTypes<typename T::value_t>::fractional_t mean(0);
 
@@ -558,8 +556,7 @@ namespace LLTrace
 		template <typename T>
 		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX)
 		{
-			S32 total_periods = mNumPeriods;
-			num_periods = llmin(num_periods, isStarted() ? total_periods - 1 : total_periods);
+			num_periods = llmin(num_periods, getNumRecordedPeriods());
 
 			typename RelatedTypes<typename T::value_t>::fractional_t mean = 0;
 
@@ -616,7 +613,7 @@ namespace LLTrace
 		std::vector<Recording>	mRecordingPeriods;
 		const bool				mAutoResize;
 		S32						mCurPeriod;
-		S32						mNumPeriods;
+		S32						mNumRecordedPeriods;
 	};
 
 	PeriodicRecording& get_frame_recording();
-- 
cgit v1.2.3


From 391ac367d6922f30bf3a186bc15e1fc38366eecf Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 19 Nov 2013 17:40:44 -0800
Subject: SH-4634 FIX Interesting: Viewer crashes when receiving teleport offer
 renamed fast timers to have unique names, changes instance tracker to never
 allow duplicates

---
 indra/llcommon/llinstancetracker.h   | 46 ++++++++++++++++++++++++------------
 indra/llcommon/lltrace.h             |  4 ++--
 indra/llcommon/lltraceaccumulators.h | 10 ++++----
 3 files changed, 38 insertions(+), 22 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 3107415ccf..cfe690b9ec 100755
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -64,8 +64,8 @@ LL_COMMON_API void assert_main_thread();
 
 enum EInstanceTrackerAllowKeyCollisions
 {
-	LLInstanceTrackerAllowKeyCollisions,
-	LLInstanceTrackerDisallowKeyCollisions
+	LLInstanceTrackerErrorOnCollision,
+	LLInstanceTrackerReplaceOnCollision
 };
 
 /// This mix-in class adds support for tracking all instances of the specified class parameter T
@@ -73,7 +73,7 @@ enum EInstanceTrackerAllowKeyCollisions
 /// If KEY is not provided, then instances are stored in a simple set
 /// @NOTE: see explicit specialization below for default KEY==void case
 /// @NOTE: this class is not thread-safe unless used as read-only
-template<typename T, typename KEY = void, EInstanceTrackerAllowKeyCollisions ALLOW_KEY_COLLISIONS = LLInstanceTrackerDisallowKeyCollisions>
+template<typename T, typename KEY = void, EInstanceTrackerAllowKeyCollisions KEY_COLLISION_BEHAVIOR = LLInstanceTrackerErrorOnCollision>
 class LLInstanceTracker : public LLInstanceTrackerBase
 {
 	typedef LLInstanceTracker<T, KEY> self_t;
@@ -192,7 +192,7 @@ public:
 	}
 
 protected:
-	LLInstanceTracker(KEY key) 
+	LLInstanceTracker(const KEY& key) 
 	{ 
 		// make sure static data outlives all instances
 		getStatic();
@@ -211,28 +211,44 @@ private:
 	LLInstanceTracker( const LLInstanceTracker& );
 	const LLInstanceTracker& operator=( const LLInstanceTracker& );
 
-	void add_(KEY key) 
+	void add_(const KEY& key) 
 	{ 
 		mInstanceKey = key; 
 		InstanceMap& map = getMap_();
 		typename InstanceMap::iterator insertion_point_it = map.lower_bound(key);
-		if (ALLOW_KEY_COLLISIONS == LLInstanceTrackerDisallowKeyCollisions
-			&& insertion_point_it != map.end() 
+		if (insertion_point_it != map.end() 
 			&& insertion_point_it->first == key)
-		{
-			LL_ERRS() << "Key " << key << " already exists in instance map for " << typeid(T).name() << LL_ENDL;
+		{ // found existing entry with that key
+			switch(KEY_COLLISION_BEHAVIOR)
+			{
+				case LLInstanceTrackerErrorOnCollision:
+				{
+					// use assert here instead of LL_ERRS(), otherwise the error will be ignored since this call is made during global object initialization
+					llassert_always_msg(false, "ERROR: Instance with this same key already exists!");
+					break;
+				}
+				case LLInstanceTrackerReplaceOnCollision:
+				{
+					// replace pointer, but leave key (should have compared equal anyway)
+					insertion_point_it->second = static_cast<T*>(this);
+					break;
+				}
+				default:
+					break;
+			}
 		}
 		else
-		{
+		{ // new key
 			map.insert(insertion_point_it, std::make_pair(key, static_cast<T*>(this)));
 		}
 	}
 	void remove_()
 	{
-		typename InstanceMap::iterator iter = getMap_().find(mInstanceKey);
-		if (iter != getMap_().end())
+		InstanceMap& map = getMap_();
+		typename InstanceMap::iterator iter = map.find(mInstanceKey);
+		if (iter != map.end())
 		{
-			getMap_().erase(iter);
+			map.erase(iter);
 		}
 	}
 
@@ -242,8 +258,8 @@ private:
 
 /// explicit specialization for default case where KEY is void
 /// use a simple std::set<T*>
-template<typename T, EInstanceTrackerAllowKeyCollisions ALLOW_KEY_COLLISIONS>
-class LLInstanceTracker<T, void, ALLOW_KEY_COLLISIONS> : public LLInstanceTrackerBase
+template<typename T, EInstanceTrackerAllowKeyCollisions KEY_COLLISION_BEHAVIOR>
+class LLInstanceTracker<T, void, KEY_COLLISION_BEHAVIOR> : public LLInstanceTrackerBase
 {
 	typedef LLInstanceTracker<T, void> self_t;
 	typedef typename std::set<T*> InstanceSet;
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 8b67dd8f44..7e811efe71 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -69,10 +69,10 @@ protected:
 template<typename ACCUMULATOR>
 class StatType 
 :	public StatBase,
-	public LLInstanceTracker<StatType<ACCUMULATOR>, std::string, LLInstanceTrackerAllowKeyCollisions>
+	public LLInstanceTracker<StatType<ACCUMULATOR>, std::string>
 {
 public:
-	typedef LLInstanceTracker<StatType<ACCUMULATOR>, std::string, LLInstanceTrackerAllowKeyCollisions> instance_tracker_t;
+	typedef LLInstanceTracker<StatType<ACCUMULATOR>, std::string> instance_tracker_t;
 	StatType(const char* name, const char* description)
 	:	instance_tracker_t(name),
 		StatBase(name, description),
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
index dfa037d7c0..42fad8a793 100644
--- a/indra/llcommon/lltraceaccumulators.h
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -471,13 +471,13 @@ namespace LLTrace
 		//
 		// members
 		//
-		U64					mTotalTimeCounter,
-							mSelfTimeCounter;
-		S32					mCalls;
+		U64							mTotalTimeCounter,
+									mSelfTimeCounter;
+		S32							mCalls;
 		class BlockTimerStatHandle*	mParent;		// last acknowledged parent of this time block
 		class BlockTimerStatHandle*	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
+		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
 
 	};
 
-- 
cgit v1.2.3


From 7a91ec40aae5f2908573cdf02d0394effee2c0e3 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Wed, 20 Nov 2013 16:21:03 -0800
Subject: SH-4626 FIX: [INTERESTING RC] Viewer randomly crashes when I click on
 links in IMs or group IMs

---
 indra/llcommon/llinstancetracker.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index cfe690b9ec..9783644e66 100755
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -224,7 +224,7 @@ private:
 				case LLInstanceTrackerErrorOnCollision:
 				{
 					// use assert here instead of LL_ERRS(), otherwise the error will be ignored since this call is made during global object initialization
-					llassert_always_msg(false, "ERROR: Instance with this same key already exists!");
+					llassert_always_msg(false, "Instance with this same key already exists!");
 					break;
 				}
 				case LLInstanceTrackerReplaceOnCollision:
-- 
cgit v1.2.3


From 3cb64c5038b7cde8bd44ec3a029d477e415085ee Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 3 Dec 2013 15:52:36 -0800
Subject: SH-4606 FIX Interesting: Small objects do not load until they are
 very close. changed culling to use inverse distance to calculate solid angle,
 not distance squared

---
 indra/llcommon/lltracethreadrecorder.cpp | 21 ++-------------------
 1 file changed, 2 insertions(+), 19 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index aec36ef2c4..d62fabe3df 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -130,7 +130,6 @@ TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode( S32 index )
 	return NULL;
 }
 
-
 AccumulatorBufferGroup* ThreadRecorder::activate( AccumulatorBufferGroup* recording)
 {
 	ActiveRecording* active_recording = new ActiveRecording(recording);
@@ -215,8 +214,7 @@ void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording )
 
 ThreadRecorder::ActiveRecording::ActiveRecording( AccumulatorBufferGroup* target ) 
 :	mTargetRecording(target)
-{
-}
+{}
 
 void ThreadRecorder::ActiveRecording::movePartialToTarget()
 {
@@ -238,21 +236,7 @@ void ThreadRecorder::addChildRecorder( class ThreadRecorder* child )
 void ThreadRecorder::removeChildRecorder( class ThreadRecorder* child )
 {	
 	{ LLMutexLock lock(&mChildListMutex);
-		for (child_thread_recorder_list_t::iterator it = mChildThreadRecorders.begin(), end_it = mChildThreadRecorders.end();
-			it != end_it;
-			++it)
-		{
-			if ((*it) == child)
-			{
-				// FIXME: this won't do any good, as the child stores the "pushed" values internally
-				// and it is in the process of being deleted.
-				// We need a way to finalize the stats from the outgoing thread, but the storage
-				// for those stats needs to be outside the child's thread recorder
-				//(*it)->pushToParent();
-				mChildThreadRecorders.erase(it);
-				break;
-			}
-		}
+		mChildThreadRecorders.remove(child);
 	}
 }
 
@@ -316,5 +300,4 @@ void set_thread_recorder( ThreadRecorder* recorder )
 	get_thread_recorder_ptr() = recorder;
 }
 
-
 }
-- 
cgit v1.2.3


From f7dc3937cd7bd0cfed83db5df25ddba20481d98d Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 3 Dec 2013 20:27:41 -0800
Subject: SH-4641 FIX Interesting: Incorrect amount of system memory detected
 on Mac

---
 indra/llcommon/llsys.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index e45f502206..07fe259e47 100755
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -899,17 +899,17 @@ U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
 	size_t len = sizeof(phys);	
 	sysctl(mib, 2, &phys, &len, NULL, 0);
 	
-	return U32Bytes(llmin(phys, (U64)U32_MAX));
+	return U64Bytes(phys);
 
 #elif LL_LINUX
 	U64 phys = 0;
 	phys = (U64)(getpagesize()) * (U64)(get_phys_pages());
-	return U32Bytes(llmin(phys, (U64)U32_MAX));
+	return U64Bytes(phys);
 
 #elif LL_SOLARIS
 	U64 phys = 0;
 	phys = (U64)(getpagesize()) * (U64)(sysconf(_SC_PHYS_PAGES));
-	return U32Bytes(llmin(phys, (U64)U32_MAX));
+	return U64Bytes(phys);
 
 #else
 	return 0;
-- 
cgit v1.2.3


From 6b84d405582e87e0b7e0a3b0cbc5635651af5e3b Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 5 Dec 2013 21:58:45 -0800
Subject: added some comments and changed calls from
 get_master_thread_recorder() over to get_thread_recorder() to be agnostic
 about which thread we're running on

---
 indra/llcommon/llthread.cpp | 2 +-
 indra/llcommon/lltrace.cpp  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index cbf78bb363..cf105098ef 100755
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -131,7 +131,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 	set_thread_name(-1, threadp->mName.c_str());
 #endif
 
-
+	// for now, hard code all LLThreads to report to single master thread recorder, which is known to be running on main thread
 	LLTrace::ThreadRecorder thread_recorder(*LLTrace::get_master_thread_recorder());
 
 #if !LL_DARWIN
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 5c4b7b5bb4..14e830af7d 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -40,7 +40,7 @@ StatBase::StatBase( const char* name, const char* description )
 	mDescription(description ? description : "")
 {
 #ifndef LL_RELEASE_FOR_DOWNLOAD
-	if (LLTrace::get_master_thread_recorder() != NULL)
+	if (LLTrace::get_thread_recorder() != NULL)
 	{
 		LL_ERRS() << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << LL_ENDL;
 	}
-- 
cgit v1.2.3


From d4f3fe3c5691348b72729ba57cef337c1dca0141 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 10 Dec 2013 12:50:23 -0800
Subject: SH-4653 FIX Interesting: Viewer crashes while reading chat history

---
 indra/llcommon/llthread.cpp | 6 +++++-
 indra/llcommon/llthread.h   | 6 ++++++
 indra/llcommon/lltrace.cpp  | 2 +-
 3 files changed, 12 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index cf105098ef..368a059182 100755
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -132,7 +132,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 #endif
 
 	// for now, hard code all LLThreads to report to single master thread recorder, which is known to be running on main thread
-	LLTrace::ThreadRecorder thread_recorder(*LLTrace::get_master_thread_recorder());
+	mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder());
 
 #if !LL_DARWIN
 	sThreadID = threadp->mID;
@@ -222,6 +222,8 @@ void LLThread::shutdown()
 			// This thread just wouldn't stop, even though we gave it time
 			//LL_WARNS() << "LLThread::~LLThread() exiting thread before clean exit!" << LL_ENDL;
 			// Put a stake in its heart.
+			delete mRecorder;
+
 			apr_thread_exit(mAPRThreadp, -1);
 			return;
 		}
@@ -239,6 +241,8 @@ void LLThread::shutdown()
 		apr_pool_destroy(mAPRPoolp);
 		mAPRPoolp = 0;
 	}
+
+	delete mRecorder;
 }
 
 
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index ba64d20936..2f9c779e00 100755
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -36,6 +36,11 @@
 
 LL_COMMON_API void assert_main_thread();
 
+namespace LLTrace
+{
+	class ThreadRecorder;
+}
+
 class LL_COMMON_API LLThread
 {
 private:
@@ -105,6 +110,7 @@ protected:
 	BOOL				mIsLocalPool;
 	EThreadStatus		mStatus;
 	U32					mID;
+	LLTrace::ThreadRecorder* mRecorder;
 
 	//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
 	//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
index 14e830af7d..54079a4689 100644
--- a/indra/llcommon/lltrace.cpp
+++ b/indra/llcommon/lltrace.cpp
@@ -40,7 +40,7 @@ StatBase::StatBase( const char* name, const char* description )
 	mDescription(description ? description : "")
 {
 #ifndef LL_RELEASE_FOR_DOWNLOAD
-	if (LLTrace::get_thread_recorder() != NULL)
+	if (LLTrace::get_thread_recorder().notNull())
 	{
 		LL_ERRS() << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << LL_ENDL;
 	}
-- 
cgit v1.2.3


From 0b40ee53e3d898990826f5d48ec1deecf3c05062 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 10 Dec 2013 14:04:09 -0800
Subject: BUILDFIX: bad use of non static member

---
 indra/llcommon/llthread.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 368a059182..3e3c876a54 100755
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -132,7 +132,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 #endif
 
 	// for now, hard code all LLThreads to report to single master thread recorder, which is known to be running on main thread
-	mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder());
+	threadp->mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder());
 
 #if !LL_DARWIN
 	sThreadID = threadp->mID;
-- 
cgit v1.2.3


From 1522c1b3bdc8eca4acd23f92dfce118121721038 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Tue, 10 Dec 2013 15:48:57 -0800
Subject: SH-4653 FIX Interesting: Viewer crashes while reading chat history
 fix for crash on exit resulting from 8c0e024d0c33

---
 indra/llcommon/llthread.cpp              | 14 ++++++++++++--
 indra/llcommon/lltracethreadrecorder.cpp | 12 ++++++------
 indra/llcommon/lltracethreadrecorder.h   |  4 ++--
 3 files changed, 20 insertions(+), 10 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 3e3c876a54..cf7768c67b 100755
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -146,6 +146,9 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 	// We're done with the run function, this thread is done executing now.
 	threadp->mStatus = STOPPED;
 
+	delete threadp->mRecorder;
+	threadp->mRecorder = NULL;
+
 	return NULL;
 }
 
@@ -153,7 +156,8 @@ LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
 	mPaused(FALSE),
 	mName(name),
 	mAPRThreadp(NULL),
-	mStatus(STOPPED)
+	mStatus(STOPPED),
+	mRecorder(NULL)
 {
 
 	mID = ++sIDIter;
@@ -242,7 +246,13 @@ void LLThread::shutdown()
 		mAPRPoolp = 0;
 	}
 
-	delete mRecorder;
+	if (mRecorder)
+	{
+		// missed chance to properly shut down recorder (needs to be done in thread context)
+		// probably due to abnormal thread termination
+		// so just leak it and remove it from parent
+		LLTrace::get_master_thread_recorder()->removeChildRecorder(mRecorder);
+	}
 }
 
 
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index d62fabe3df..a14a8ff035 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -40,7 +40,7 @@ static ThreadRecorder* sMasterThreadRecorder = NULL;
 ///////////////////////////////////////////////////////////////////////
 
 ThreadRecorder::ThreadRecorder()
-:	mMasterRecorder(NULL)
+:	mParentRecorder(NULL)
 {
 	init();
 }
@@ -86,11 +86,11 @@ void ThreadRecorder::init()
 }
 
 
-ThreadRecorder::ThreadRecorder( ThreadRecorder& master )
-:	mMasterRecorder(&master)
+ThreadRecorder::ThreadRecorder( ThreadRecorder& parent )
+:	mParentRecorder(&parent)
 {
 	init();
-	mMasterRecorder->addChildRecorder(this);
+	mParentRecorder->addChildRecorder(this);
 }
 
 
@@ -115,9 +115,9 @@ ThreadRecorder::~ThreadRecorder()
 	set_thread_recorder(NULL);
 	delete[] mTimeBlockTreeNodes;
 
-	if (mMasterRecorder)
+	if (mParentRecorder)
 	{
-		mMasterRecorder->removeChildRecorder(this);
+		mParentRecorder->removeChildRecorder(this);
 	}
 }
 
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
index d30fa15ea7..a797c6687e 100644
--- a/indra/llcommon/lltracethreadrecorder.h
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -43,7 +43,7 @@ namespace LLTrace
 		typedef std::vector<ActiveRecording*> active_recording_list_t;
 	public:
 		ThreadRecorder();
-		explicit ThreadRecorder(ThreadRecorder& master);
+		explicit ThreadRecorder(ThreadRecorder& parent);
 
 		~ThreadRecorder();
 
@@ -88,7 +88,7 @@ namespace LLTrace
 		LLMutex							mChildListMutex;		// protects access to child list
 		LLMutex							mSharedRecordingMutex;
 		AccumulatorBufferGroup			mSharedRecordingBuffers;
-		ThreadRecorder*					mMasterRecorder;
+		ThreadRecorder*					mParentRecorder;
 
 	};
 
-- 
cgit v1.2.3


From a712aab616b13a9887e00b5d37714f02d7fde6a0 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 10 Jan 2014 13:56:35 -0800
Subject: added some defensive asserts in lltrace to make cases of misuse more
 obvious when it crashes

---
 indra/llcommon/lltracerecording.cpp      | 12 +++++++++++-
 indra/llcommon/lltracethreadrecorder.cpp | 30 +++++++++++++++---------------
 2 files changed, 26 insertions(+), 16 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index cd837c0867..d6232d771d 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -88,6 +88,9 @@ Recording::~Recording()
 	disclaim_alloc(gTraceMemStat, this);
 	disclaim_alloc(gTraceMemStat, mBuffers);
 
+	// allow recording destruction without thread recorder running, 
+	// otherwise thread shutdown could crash if a recording outlives the thread recorder
+	// besides, recording construction and destruction is fine without a recorder...just don't attempt to start one
 	if (isStarted() && LLTrace::get_thread_recorder().notNull())
 	{
 		LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
@@ -101,7 +104,10 @@ void Recording::update()
 	{
 		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
 
-		llassert(mActiveBuffers);
+		// must have 
+		llassert(mActiveBuffers != NULL 
+				&& LLTrace::get_thread_recorder().notNull());
+
 		if(!mActiveBuffers->isCurrent())
 		{
 			AccumulatorBufferGroup* buffers = mBuffers.write();
@@ -125,12 +131,16 @@ void Recording::handleStart()
 {
 	mSamplingTimer.reset();
 	mBuffers.setStayUnique(true);
+	// must have thread recorder running on this thread
+	llassert(LLTrace::get_thread_recorder().notNull());
 	mActiveBuffers = LLTrace::get_thread_recorder()->activate(mBuffers.write());
 }
 
 void Recording::handleStop()
 {
 	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+	// must have thread recorder running on this thread
+	llassert(LLTrace::get_thread_recorder().notNull());
 	LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
 	mActiveBuffers = NULL;
 	mBuffers.setStayUnique(false);
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index a14a8ff035..187d8546d3 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -191,25 +191,25 @@ ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::bringUpToDate(
 void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording )
 {
 	active_recording_list_t::iterator recording_it = bringUpToDate(recording);
-	if (recording_it != mActiveRecordings.end())
+	// this method should only be called on a thread where the recorder is active
+	llassert_always(recording_it != mActiveRecordings.end());
+
+	ActiveRecording* recording_to_remove = *recording_it;
+	bool was_current = recording_to_remove->mPartialRecording.isCurrent();
+	llassert(recording_to_remove->mTargetRecording == recording);
+	mActiveRecordings.erase(recording_it);
+	if (was_current)
 	{
-		ActiveRecording* recording_to_remove = *recording_it;
-		bool was_current = recording_to_remove->mPartialRecording.isCurrent();
-		llassert(recording_to_remove->mTargetRecording == recording);
-		mActiveRecordings.erase(recording_it);
-		if (was_current)
+		if (mActiveRecordings.empty())
 		{
-			if (mActiveRecordings.empty())
-			{
-				AccumulatorBufferGroup::clearCurrent();
-			}
-			else
-			{
-				mActiveRecordings.back()->mPartialRecording.makeCurrent();
-			}
+			AccumulatorBufferGroup::clearCurrent();
+		}
+		else
+		{
+			mActiveRecordings.back()->mPartialRecording.makeCurrent();
 		}
-		delete recording_to_remove;
 	}
+	delete recording_to_remove;
 }
 
 ThreadRecorder::ActiveRecording::ActiveRecording( AccumulatorBufferGroup* target ) 
-- 
cgit v1.2.3


From 5df86c9a6e258221440a775e229a5be25a4b7e51 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 30 Jan 2014 19:35:34 -0800
Subject: fix for heap corruption crash on shutdown don't set stopped flag
 until recorder object has been deleted

---
 indra/llcommon/llthread.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index cf7768c67b..fd1f8ee096 100755
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -143,12 +143,13 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
 
 	//LL_INFOS() << "LLThread::staticRun() Exiting: " << threadp->mName << LL_ENDL;
 	
-	// We're done with the run function, this thread is done executing now.
-	threadp->mStatus = STOPPED;
-
 	delete threadp->mRecorder;
 	threadp->mRecorder = NULL;
 
+	// We're done with the run function, this thread is done executing now.
+	//NB: we are using this flag to sync across threads...we really need memory barriers here
+	threadp->mStatus = STOPPED;
+
 	return NULL;
 }
 
-- 
cgit v1.2.3


From 3040b429a3b136b87ddb0ae88ccfa3a7aa71e232 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 6 Feb 2014 11:27:16 -0800
Subject: added LL_TRACE_ENABLED to allow disabling of lltrace

---
 indra/llcommon/llfasttimer.cpp           |  4 ++++
 indra/llcommon/llmemory.h                |  2 +-
 indra/llcommon/lltrace.h                 | 40 +++++++++++++++++++++++++++++++-
 indra/llcommon/lltracerecording.cpp      | 12 ++++++++++
 indra/llcommon/lltracethreadrecorder.cpp | 26 +++++++++++++++++++++
 5 files changed, 82 insertions(+), 2 deletions(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 9b093e8936..d46e257af7 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -294,6 +294,7 @@ static LLTrace::BlockTimerStatHandle FTM_PROCESS_TIMES("Process FastTimer Times"
 //static
 void BlockTimer::processTimes()
 {
+#if LL_TRACE_ENABLED
 	LL_RECORD_BLOCK_TIME(FTM_PROCESS_TIMES);
 	get_clock_count(); // good place to calculate clock frequency
 
@@ -316,6 +317,7 @@ void BlockTimer::processTimes()
 		accumulator.mLastCaller = NULL;
 		accumulator.mMoveUpTree = false;
 	}
+#endif
 }
 
 std::vector<BlockTimerStatHandle*>::iterator BlockTimerStatHandle::beginChildren()
@@ -449,6 +451,7 @@ TimeBlockAccumulator::TimeBlockAccumulator()
 
 void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other, EBufferAppendType append_type )
 {
+#if LL_TRACE_ENABLED
 	// we can't merge two unrelated time block samples, as that will screw with the nested timings
 	// due to the call hierarchy of each thread
 	llassert(append_type == SEQUENTIAL);
@@ -459,6 +462,7 @@ void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other, EBuffe
 	mActiveCount = other.mActiveCount;
 	mMoveUpTree = other.mMoveUpTree;
 	mParent = other.mParent;
+#endif
 }
 
 void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 3de59350db..1aa095e71c 100755
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -37,7 +37,7 @@ class LLMutex ;
 #if LL_WINDOWS && LL_DEBUG
 #define LL_CHECK_MEMORY llassert(_CrtCheckMemory());
 #else
-#define LL_CHECK_MEMORY
+#define LL_CHECK_MEMORY _CrtCheckMemory();
 #endif
 
 
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
index 7e811efe71..5f1289dad8 100644
--- a/indra/llcommon/lltrace.h
+++ b/indra/llcommon/lltrace.h
@@ -38,6 +38,8 @@
 #include "llpointer.h"
 #include "llunits.h"
 
+#define LL_TRACE_ENABLED 1
+
 namespace LLTrace
 {
 class Recording;
@@ -135,8 +137,10 @@ public:
 template<typename T, typename VALUE_T>
 void record(EventStatHandle<T>& measurement, VALUE_T value)
 {
+#if LL_TRACE_ENABLED
 	T converted_value(value);
 	measurement.getCurrentAccumulator().record(storage_value(converted_value));
+#endif
 }
 
 template <typename T = F64>
@@ -158,8 +162,10 @@ public:
 template<typename T, typename VALUE_T>
 void sample(SampleStatHandle<T>& measurement, VALUE_T value)
 {
+#if LL_TRACE_ENABLED
 	T converted_value(value);
 	measurement.getCurrentAccumulator().sample(storage_value(converted_value));
+#endif
 }
 
 template <typename T = F64>
@@ -181,8 +187,10 @@ public:
 template<typename T, typename VALUE_T>
 void add(CountStatHandle<T>& count, VALUE_T value)
 {
+#if LL_TRACE_ENABLED
 	T converted_value(value);
 	count.getCurrentAccumulator().add(storage_value(converted_value));
+#endif
 }
 
 template<>
@@ -323,21 +331,25 @@ struct MeasureMem<std::basic_string<T>, IS_MEM_TRACKABLE, IS_BYTES>
 template<typename T>
 inline void claim_alloc(MemStatHandle& measurement, const T& value)
 {
+#if LL_TRACE_ENABLED
 	S32 size = MeasureMem<T>::measureFootprint(value);
 	if(size == 0) return;
 	MemAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
 	accumulator.mAllocations.record(size);
+#endif
 }
 
 template<typename T>
 inline void disclaim_alloc(MemStatHandle& measurement, const T& value)
 {
+#if LL_TRACE_ENABLED
 	S32 size = MeasureMem<T>::measureFootprint(value);
 	if(size == 0) return;
 	MemAccumulator& accumulator = measurement.getCurrentAccumulator();
 	accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
 	accumulator.mDeallocations.add(size);
+#endif
 }
 
 template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN>
@@ -347,16 +359,21 @@ public:
 	typedef void mem_trackable_tag_t;
 
 	MemTrackableNonVirtual(const char* name)
+#if LL_TRACE_ENABLED
 	:	mMemFootprint(0)
+#endif
 	{
+#if LL_TRACE_ENABLED
 		static bool name_initialized = false;
 		if (!name_initialized)
 		{
 			name_initialized = true;
 			sMemStat.setName(name);
 		}
+#endif
 	}
 
+#if LL_TRACE_ENABLED
 	~MemTrackableNonVirtual()
 	{
 		disclaimMem(mMemFootprint);
@@ -368,43 +385,55 @@ public:
 	}
 
 	S32 getMemFootprint() const	{ return mMemFootprint; }
+#endif
 
 	void* operator new(size_t size) 
 	{
+#if LL_TRACE_ENABLED
 		claim_alloc(sMemStat, size);
+#endif
 		return ll_aligned_malloc<ALIGNMENT>(size);
 	}
 
 	template<int CUSTOM_ALIGNMENT>
 	static void* aligned_new(size_t size)
 	{
+#if LL_TRACE_ENABLED
 		claim_alloc(sMemStat, size);
+#endif
 		return ll_aligned_malloc<CUSTOM_ALIGNMENT>(size);
 	}
 
 	void operator delete(void* ptr, size_t size)
 	{
+#if LL_TRACE_ENABLED
 		disclaim_alloc(sMemStat, size);
+#endif
 		ll_aligned_free<ALIGNMENT>(ptr);
 	}
 
 	template<int CUSTOM_ALIGNMENT>
 	static void aligned_delete(void* ptr, size_t size)
 	{
+#if LL_TRACE_ENABLED
 		disclaim_alloc(sMemStat, size);
+#endif
 		ll_aligned_free<CUSTOM_ALIGNMENT>(ptr);
 	}
 
-
 	void* operator new [](size_t size)
 	{
+#if LL_TRACE_ENABLED
 		claim_alloc(sMemStat, size);
+#endif
 		return ll_aligned_malloc<ALIGNMENT>(size);
 	}
 
 	void operator delete[](void* ptr, size_t size)
 	{
+#if LL_TRACE_ENABLED
 		disclaim_alloc(sMemStat, size);
+#endif
 		ll_aligned_free<ALIGNMENT>(ptr);
 	}
 
@@ -412,31 +441,40 @@ public:
 	template<typename CLAIM_T>
 	void claimMem(const CLAIM_T& value) const
 	{
+#if LL_TRACE_ENABLED
 		S32 size = MeasureMem<CLAIM_T>::measureFootprint(value);
 		claim_alloc(sMemStat, size);
 		mMemFootprint += size;
+#endif
 	}
 
 	// remove memory we had claimed from our calculated footprint
 	template<typename CLAIM_T>
 	void disclaimMem(const CLAIM_T& value) const
 	{
+#if LL_TRACE_ENABLED
 		S32 size = MeasureMem<CLAIM_T>::measureFootprint(value);
 		disclaim_alloc(sMemStat, size);
 		mMemFootprint -= size;
+#endif
 	}
 
 private:
+#if LL_TRACE_ENABLED
 	// use signed values so that we can temporarily go negative
 	// and reconcile in destructor
 	// NB: this assumes that no single class is responsible for > 2GB of allocations
 	mutable S32 mMemFootprint;
 	
 	static	MemStatHandle	sMemStat;
+#endif
+
 };
 
+#if LL_TRACE_ENABLED
 template<typename DERIVED, size_t ALIGNMENT>
 MemStatHandle MemTrackableNonVirtual<DERIVED, ALIGNMENT>::sMemStat(typeid(MemTrackableNonVirtual<DERIVED, ALIGNMENT>).name());
+#endif
 
 template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN>
 class MemTrackable : public MemTrackableNonVirtual<DERIVED, ALIGNMENT>
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
index d6232d771d..0b10438b9f 100644
--- a/indra/llcommon/lltracerecording.cpp
+++ b/indra/llcommon/lltracerecording.cpp
@@ -100,6 +100,7 @@ Recording::~Recording()
 // brings recording to front of recorder stack, with up to date info
 void Recording::update()
 {
+#if LL_TRACE_ENABLED
 	if (isStarted())
 	{
 		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
@@ -117,46 +118,57 @@ void Recording::update()
 
 		mSamplingTimer.reset();
 	}
+#endif
 }
 
 void Recording::handleReset()
 {
+#if LL_TRACE_ENABLED
 	mBuffers.write()->reset();
 
 	mElapsedSeconds = F64Seconds(0.0);
 	mSamplingTimer.reset();
+#endif
 }
 
 void Recording::handleStart()
 {
+#if LL_TRACE_ENABLED
 	mSamplingTimer.reset();
 	mBuffers.setStayUnique(true);
 	// must have thread recorder running on this thread
 	llassert(LLTrace::get_thread_recorder().notNull());
 	mActiveBuffers = LLTrace::get_thread_recorder()->activate(mBuffers.write());
+#endif
 }
 
 void Recording::handleStop()
 {
+#if LL_TRACE_ENABLED
 	mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
 	// must have thread recorder running on this thread
 	llassert(LLTrace::get_thread_recorder().notNull());
 	LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
 	mActiveBuffers = NULL;
 	mBuffers.setStayUnique(false);
+#endif
 }
 
 void Recording::handleSplitTo(Recording& other)
 {
+#if LL_TRACE_ENABLED
 	mBuffers.write()->handOffTo(*other.mBuffers.write());
+#endif
 }
 
 void Recording::appendRecording( Recording& other )
 {
+#if LL_TRACE_ENABLED
 	update();
 	other.update();
 	mBuffers.write()->append(*other.mBuffers);
 	mElapsedSeconds += other.mElapsedSeconds;
+#endif
 }
 
 bool Recording::hasValue(const StatType<TimeBlockAccumulator>& stat)
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
index 187d8546d3..181fc2f058 100644
--- a/indra/llcommon/lltracethreadrecorder.cpp
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -47,6 +47,7 @@ ThreadRecorder::ThreadRecorder()
 
 void ThreadRecorder::init()
 {
+#if LL_TRACE_ENABLED
 	LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(&mBlockTimerStackRecord);
 	//NB: the ordering of initialization in this function is very fragile due to a large number of implicit dependencies
 	set_thread_recorder(this);
@@ -83,6 +84,7 @@ void ThreadRecorder::init()
 	claim_alloc(gTraceMemStat, this);
 	claim_alloc(gTraceMemStat, mRootTimer);
 	claim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes);
+#endif
 }
 
 
@@ -96,6 +98,7 @@ ThreadRecorder::ThreadRecorder( ThreadRecorder& parent )
 
 ThreadRecorder::~ThreadRecorder()
 {
+#if LL_TRACE_ENABLED
 	LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(NULL);
 
 	disclaim_alloc(gTraceMemStat, this);
@@ -119,19 +122,23 @@ ThreadRecorder::~ThreadRecorder()
 	{
 		mParentRecorder->removeChildRecorder(this);
 	}
+#endif
 }
 
 TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode( S32 index )
 {
+#if LL_TRACE_ENABLED
 	if (0 <= index && index < mNumTimeBlockTreeNodes)
 	{
 		return &mTimeBlockTreeNodes[index];
 	}
+#endif
 	return NULL;
 }
 
 AccumulatorBufferGroup* ThreadRecorder::activate( AccumulatorBufferGroup* recording)
 {
+#if LL_TRACE_ENABLED
 	ActiveRecording* active_recording = new ActiveRecording(recording);
 	if (!mActiveRecordings.empty())
 	{
@@ -144,10 +151,14 @@ AccumulatorBufferGroup* ThreadRecorder::activate( AccumulatorBufferGroup* record
 
 	mActiveRecordings.back()->mPartialRecording.makeCurrent();
 	return &active_recording->mPartialRecording;
+#else
+	return NULL;
+#endif
 }
 
 ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::bringUpToDate( AccumulatorBufferGroup* recording )
 {
+#if LL_TRACE_ENABLED
 	if (mActiveRecordings.empty()) return mActiveRecordings.end();
 
 	mActiveRecordings.back()->mPartialRecording.sync();
@@ -186,10 +197,14 @@ ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::bringUpToDate(
 	}
 
 	return (++it).base();
+#else
+	return ThreadRecorder::active_recording_list_t::iterator();
+#endif
 }
 
 void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording )
 {
+#if LL_TRACE_ENABLED
 	active_recording_list_t::iterator recording_it = bringUpToDate(recording);
 	// this method should only be called on a thread where the recorder is active
 	llassert_always(recording_it != mActiveRecordings.end());
@@ -210,6 +225,7 @@ void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording )
 		}
 	}
 	delete recording_to_remove;
+#endif
 }
 
 ThreadRecorder::ActiveRecording::ActiveRecording( AccumulatorBufferGroup* target ) 
@@ -218,35 +234,43 @@ ThreadRecorder::ActiveRecording::ActiveRecording( AccumulatorBufferGroup* target
 
 void ThreadRecorder::ActiveRecording::movePartialToTarget()
 {
+#if LL_TRACE_ENABLED
 	mTargetRecording->append(mPartialRecording);
 	// reset based on self to keep history
 	mPartialRecording.reset(&mPartialRecording);
+#endif
 }
 
 
 // called by child thread
 void ThreadRecorder::addChildRecorder( class ThreadRecorder* child )
 {
+#if LL_TRACE_ENABLED
 	{ LLMutexLock lock(&mChildListMutex);
 		mChildThreadRecorders.push_back(child);
 	}
+#endif
 }
 
 // called by child thread
 void ThreadRecorder::removeChildRecorder( class ThreadRecorder* child )
 {	
+#if LL_TRACE_ENABLED
 	{ LLMutexLock lock(&mChildListMutex);
 		mChildThreadRecorders.remove(child);
 	}
+#endif
 }
 
 void ThreadRecorder::pushToParent()
 {
+#if LL_TRACE_ENABLED
 	{ LLMutexLock lock(&mSharedRecordingMutex);	
 		LLTrace::get_thread_recorder()->bringUpToDate(&mThreadRecordingBuffers);
 		mSharedRecordingBuffers.append(mThreadRecordingBuffers);
 		mThreadRecordingBuffers.reset();
 	}
+#endif
 }
 
 
@@ -254,6 +278,7 @@ static LLTrace::BlockTimerStatHandle FTM_PULL_TRACE_DATA_FROM_CHILDREN("Pull chi
 
 void ThreadRecorder::pullFromChildren()
 {
+#if LL_TRACE_ENABLED
 	LL_RECORD_BLOCK_TIME(FTM_PULL_TRACE_DATA_FROM_CHILDREN);
 	if (mActiveRecordings.empty()) return;
 
@@ -270,6 +295,7 @@ void ThreadRecorder::pullFromChildren()
 			(*it)->mSharedRecordingBuffers.reset();
 		}
 	}
+#endif
 }
 
 
-- 
cgit v1.2.3


From a8192fbf60540e42dcff5f1efb8bf8cafbfac484 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Thu, 6 Feb 2014 13:14:40 -0800
Subject: accidentally left _CrtCheckMemory defined in non-Windows builds

---
 indra/llcommon/llmemory.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'indra/llcommon')

diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 1aa095e71c..db52f2b1f4 100755
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -37,7 +37,7 @@ class LLMutex ;
 #if LL_WINDOWS && LL_DEBUG
 #define LL_CHECK_MEMORY llassert(_CrtCheckMemory());
 #else
-#define LL_CHECK_MEMORY _CrtCheckMemory();
+#define LL_CHECK_MEMORY 
 #endif
 
 
-- 
cgit v1.2.3