diff options
Diffstat (limited to 'indra/llcommon')
184 files changed, 9036 insertions, 16852 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 8767616a70..cc54524320 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      lldeadmantimer.cpp      lldependencies.cpp @@ -59,7 +57,6 @@ set(llcommon_SOURCE_FILES      llfile.cpp      llfindlocale.cpp      llfixedbuffer.cpp -    llfoldertype.cpp      llformat.cpp      llframetimer.cpp      llheartbeat.cpp @@ -69,15 +66,15 @@ set(llcommon_SOURCE_FILES      llleaplistener.cpp      llliveappconfig.cpp      lllivefile.cpp -    lllog.cpp      llmd5.cpp      llmemory.cpp      llmemorystream.cpp      llmetrics.cpp      llmetricperformancetester.cpp      llmortician.cpp -    lloptioninterface.cpp +    llmutex.cpp      llptrto.cpp  +    llpredicate.cpp      llprocess.cpp      llprocessor.cpp      llprocinfo.cpp @@ -90,9 +87,7 @@ set(llcommon_SOURCE_FILES      llsdserialize.cpp      llsdserialize_xml.cpp      llsdutil.cpp -    llsecondlifeurls.cpp      llsingleton.cpp -    llstat.cpp      llstacktrace.cpp      llstreamqueue.cpp      llstreamtools.cpp @@ -100,14 +95,16 @@ set(llcommon_SOURCE_FILES      llstringtable.cpp      llsys.cpp      llthread.cpp +    llthreadlocalstorage.cpp      llthreadsafequeue.cpp      lltimer.cpp +    lltrace.cpp +    lltraceaccumulators.cpp +    lltracerecording.cpp +    lltracethreadrecorder.cpp      lluri.cpp      lluuid.cpp      llworkerthread.cpp -    metaclass.cpp -    metaproperty.cpp -    reflective.cpp      timing.cpp      u64.cpp      ) @@ -115,53 +112,35 @@ set(llcommon_SOURCE_FILES  set(llcommon_HEADER_FILES      CMakeLists.txt -    bitpack.h      ctype_workaround.h -    doublelinkedlist.h      fix_macros.h -    imageids.h      indra_constants.h      linden_common.h -    linked_lists.h -    llaccountingcost.h      llalignedarray.h      llallocator.h      llallocator_heap_profile.h -    llagentconstants.h -    llavatarname.h      llapp.h      llapr.h      llassettype.h -    llassoclist.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 -    lldarrayptr.h      lldate.h      lldeadmantimer.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      llerrorthread.h      llevent.h      lleventapi.h @@ -170,49 +149,39 @@ 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 -    llindexedqueue.h +    llindexedvector.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      llmd5.h      llmemory.h      llmemorystream.h      llmetrics.h      llmetricperformancetester.h      llmortician.h -    llnametable.h -    lloptioninterface.h +    llmutex.h      llpointer.h +    llpredicate.h      llpreprocessor.h      llpriqueuemap.h      llprocess.h      llprocessor.h      llprocinfo.h -    llptrskiplist.h -    llptrskipmap.h      llptrto.h      llqueuedthread.h      llrand.h @@ -226,16 +195,9 @@ set(llcommon_HEADER_FILES      llsdserialize.h      llsdserialize_xml.h      llsdutil.h -    llsecondlifeurls.h      llsimplehash.h      llsingleton.h -    llskiplist.h -    llskipmap.h -    llsortedvector.h -    llstack.h      llstacktrace.h -    llstat.h -    llstatenums.h      llstl.h      llstreamqueue.h      llstreamtools.h @@ -245,29 +207,24 @@ set(llcommon_HEADER_FILES      llstaticstringtable.h      llsys.h      llthread.h +    llthreadlocalstorage.h      llthreadsafequeue.h      lltimer.h +    lltrace.h +    lltraceaccumulators.h +    lltracerecording.h +    lltracethreadrecorder.h      lltreeiterators.h -    lltypeinfolookup.h +    llunits.h +    llunittype.h      lluri.h      lluuid.h -    lluuidhashmap.h -    llversionserver.h +    llwin32headers.h +    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 -    string_table.h      stringize.h      timer.h -    timing.h      u64.h      ) @@ -333,16 +290,16 @@ 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(llprocinfo "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")    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(reflection "" "${test_libs}") +  LL_ADD_INTEGRATION_TEST(llunits "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(lleventcoro "" "${test_libs};${BOOST_CONTEXT_LIBRARY}") diff --git a/indra/llcommon/doublelinkedlist.h b/indra/llcommon/doublelinkedlist.h deleted file mode 100755 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/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..f3989ee1d0 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 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/llalignedarray.h b/indra/llcommon/llalignedarray.h index ed8fd31205..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(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(mCapacity*sizeof(T), alignment); +		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(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(mCapacity*sizeof(T), alignment) : 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(mArray); +			ll_aligned_free<alignment>(mArray);  		}  		/*for (U32 i = mElementCount; i < mCapacity; ++i) 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/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/llapr.cpp b/indra/llcommon/llapr.cpp index b7815b0e35..a548c96002 100755 --- 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 "llthreadlocalstorage.h"  apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool  LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool. @@ -37,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 @@ -54,11 +58,21 @@ void ll_init_apr()  	{  		LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;  	} + +	LLThreadLocalPointerBase::initAllThreadLocalStorage(); +	gAPRInitialized = true;  } +bool ll_apr_is_initialized() +{ +	return gAPRInitialized; +} +  void ll_cleanup_apr()  { +	gAPRInitialized = false; +  	LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;  	if (gLogMutexp) @@ -77,6 +91,9 @@ void ll_cleanup_apr()  		apr_thread_mutex_destroy(gCallStacksLogMutexp);  		gCallStacksLogMutexp = NULL;  	} + +	LLThreadLocalPointerBase::destroyAllThreadLocalStorage(); +  	if (gAPRPoolp)  	{  		apr_pool_destroy(gAPRPoolp); @@ -429,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;  	} @@ -451,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/llapr.h b/indra/llcommon/llapr.h index 1fe7d98472..b1b0fc4718 100755 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -32,28 +32,34 @@  #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> -#endif  #include <boost/noncopyable.hpp> - +#include "llwin32headerslean.h"  #include "apr_thread_proc.h"  #include "apr_thread_mutex.h"  #include "apr_getopt.h"  #include "apr_signal.h"  #include "apr_atomic.h" +  #include "llstring.h"  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 @@ -66,6 +72,9 @@ void LL_COMMON_API ll_init_apr();   */  void LL_COMMON_API ll_cleanup_apr(); +bool LL_COMMON_API ll_apr_is_initialized(); + +  //  //LL apr_pool  //manage apr_pool_t, destroy allocated apr_pool in the destruction function. @@ -263,18 +272,5 @@ 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/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/llassoclist.h b/indra/llcommon/llassoclist.h deleted file mode 100755 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/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 d12f157910..0000000000 --- a/indra/llcommon/llavatarname.cpp +++ /dev/null @@ -1,254 +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; -bool LLAvatarName::sUseUsernames = 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;  -} - -void LLAvatarName::setUseUsernames(bool use) -{ -	sUseUsernames = use; -} - -bool LLAvatarName::useUsernames() -{ -	return sUseUsernames; -} - -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; -			if(sUseUsernames) -			{ -				name += " (" + 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 1cb3ae421f..0000000000 --- a/indra/llcommon/llavatarname.h +++ /dev/null @@ -1,139 +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(); -	 -	static void setUseUsernames(bool use); -	static bool useUsernames(); - -	// 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; - -	// Flag indicating if username should be shown after display name or not -	static bool sUseUsernames; -}; - -#endif 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/bitpack.cpp b/indra/llcommon/llbitpack.cpp index cdcaba0765..622a099945 100755 --- a/indra/llcommon/bitpack.cpp +++ b/indra/llcommon/llbitpack.cpp @@ -27,4 +27,4 @@  #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" +#include "llbitpack.h" diff --git a/indra/llcommon/bitpack.h b/indra/llcommon/llbitpack.h index 037300dd14..f99a354cd4 100755 --- a/indra/llcommon/bitpack.h +++ b/indra/llcommon/llbitpack.h @@ -1,5 +1,5 @@  /**  - * @file bitpack.h + * @file llbitpack.h   * @brief Convert data to packed bit stream   *   * $LicenseInfo:firstyear=2000&license=viewerlgpl$ @@ -79,7 +79,7 @@ public:  					*(mBuffer + mBufferSize++) = mLoad;  					if (mBufferSize > mMaxSize)  					{ -						llerror("mBufferSize exceeding mMaxSize!", 0); +						LL_ERRS() << "mBufferSize exceeding mMaxSize!" << LL_ENDL;  					}  					mLoadSize = 0;  					mLoad = 0x00; @@ -122,7 +122,7 @@ public:  					*(mBuffer + mBufferSize++) = mLoad;  					if (mBufferSize > mMaxSize)  					{ -						llerror("mBufferSize exceeding mMaxSize!", 0); +						LL_ERRS() << "mBufferSize exceeding mMaxSize!" << LL_ENDL;  					}  					mLoadSize = 0;  					mLoad = 0x00; @@ -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++); @@ -190,7 +190,7 @@ public:  			*(mBuffer + mBufferSize++) = mLoad;  			if (mBufferSize > mMaxSize)  			{ -				llerror("mBufferSize exceeding mMaxSize!", 0); +				LL_ERRS() << "mBufferSize exceeding mMaxSize!" << LL_ENDL;  			}  			mLoadSize = 0;  		} 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 index 1f87d8eec3..2f83113af9 100755..100644 --- a/indra/llcommon/llclickaction.h +++ b/indra/llcommon/llclickaction.h @@ -27,15 +27,4 @@  #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/llcommon.cpp b/indra/llcommon/llcommon.cpp index b938b0e65a..19642b0982 100755 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -29,10 +29,14 @@  #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,15 +49,19 @@ void LLCommon::initClass()  	LLTimer::initClass();  	LLThreadSafeRefCount::initThreadSafeRefCount();  	assert_main_thread();		// Make sure we record the main thread -// 	LLWorkerThread::initClass(); -// 	LLFrameCallbackManager::initClass(); +	if (!sMasterThreadRecorder) +	{ +		sMasterThreadRecorder = new LLTrace::ThreadRecorder(); +		LLTrace::set_master_thread_recorder(sMasterThreadRecorder); +	}  }  //static  void LLCommon::cleanupClass()  { -// 	LLFrameCallbackManager::cleanupClass(); -// 	LLWorkerThread::cleanupClass(); +	delete sMasterThreadRecorder; +	sMasterThreadRecorder = NULL; +	LLTrace::set_master_thread_recorder(NULL);  	LLThreadSafeRefCount::cleanupThreadSafeRefCount();  	LLTimer::cleanupClass();  	if (sAprInitialized) 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/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/llcriticaldamp.cpp b/indra/llcommon/llcriticaldamp.cpp index 49aac9ce75..54be855f67 100755 --- 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,44 +67,55 @@ 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(F32SecondsImplicit 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; +//----------------------------------------------------------------------------- +// calcInterpolant() +//----------------------------------------------------------------------------- +F32 LLSmoothInterpolation::calcInterpolant(F32 time_constant) +{ +	return llclamp(1.f - powf(2.f, -sTimeDelta / time_constant), 0.f, 1.f);  } diff --git a/indra/llcommon/llcriticaldamp.h b/indra/llcommon/llcriticaldamp.h index 52f052ae25..1fb6a1af29 100755 --- 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 "llunits.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(F32SecondsImplicit time_constant, bool use_cache = true); -protected:	 +	template<typename T>  +	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))  +				+ (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/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/lldate.cpp b/indra/llcommon/lldate.cpp index 030ef6a3c7..7a2a0869f4 100755 --- 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; @@ -48,25 +49,22 @@ 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) : -	mSecondsSinceEpoch(seconds_since_epoch) -{ -} +LLDate::LLDate(F64SecondsImplicit seconds_since_epoch) : +	mSecondsSinceEpoch(seconds_since_epoch.value()) +{}  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;  	}  } @@ -88,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::BlockTimerStatHandle 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); @@ -101,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/lldate.h b/indra/llcommon/lldate.h index 7ff8b550ad..be2cd2d051 100755 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -33,6 +33,7 @@  #include <string>  #include "stdtypes.h" +#include "llunits.h"  /**    * @class LLDate @@ -56,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(F64 seconds_since_epoch); +	LLDate(F64SecondsImplicit seconds_since_epoch);  	/**   	 * @brief Construct a date from a string representation diff --git a/indra/llcommon/lldeadmantimer.cpp b/indra/llcommon/lldeadmantimer.cpp index 7d9097e344..830443b956 100644 --- a/indra/llcommon/lldeadmantimer.cpp +++ b/indra/llcommon/lldeadmantimer.cpp @@ -43,7 +43,7 @@  //    true    true   Not allowed  //  LLDeadmanTimer::LLDeadmanTimer(F64 horizon, bool inc_cpu) -	: mHorizon(time_type(llmax(horizon, F64(0.0)) * gClockFrequency)), +	: mHorizon(time_type(llmax(horizon, F64(0.0)) * get_timer_info().mClockFrequency)),  	  mActive(false),			// If true, a timer is running.  	  mDone(false),				// If true, timer has completed and can be read (once)  	  mStarted(U64L(0)), @@ -144,8 +144,8 @@ bool LLDeadmanTimer::isExpired(time_type now, F64 & started, F64 & stopped, U64  		return false;  	} -	started = mStarted * gClockFrequencyInv; -	stopped = mStopped * gClockFrequencyInv; +	started = mStarted * get_timer_info().mClockFrequencyInv; +	stopped = mStopped * get_timer_info().mClockFrequencyInv;  	count = mCount;  	mDone = false; diff --git a/indra/llcommon/lldeleteutils.h b/indra/llcommon/lldeleteutils.h deleted file mode 100755 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..b65840d342 100755 --- a/indra/llcommon/lldepthstack.h +++ b/indra/llcommon/lldepthstack.h @@ -27,18 +27,19 @@  #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()	{} +	LLDepthStack()  +	:	mCurrentDepth(0), mMaxDepth(0)  +	{}  	void setDepth(U32 depth)  	{ @@ -54,24 +55,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 +83,13 @@ public:  	DATA_TYPE *check()  	{  -		DATA_TYPE *tempp = mStack.getFirstData();  -		return tempp;  +		return mStack.empty() ? NULL : mStack.back();  	} -	 -	void deleteAllData() -	{  -		mCurrentDepth = 0; -		mStack.deleteAllData();  -	} -	 +  	void removeAllNodes()  	{   		mCurrentDepth = 0; -		mStack.removeAllNodes();  +		mStack.clear();   	}  }; 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/lldlinked.h b/indra/llcommon/lldlinked.h deleted file mode 100755 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 100755 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 100755 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/llerror.cpp b/indra/llcommon/llerror.cpp index 853f279c95..a7963174ad 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: @@ -96,8 +115,9 @@ 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;  			} +			mWantsTime = true;  		}  		~RecordToFile() @@ -107,14 +127,10 @@ namespace {  		bool okay() { return mFile; } -		virtual bool wantsTime() { return true; } -		  		virtual void recordMessage(LLError::ELevel level,  									const std::string& message)  		{  			mFile << message << std::endl; -			// mFile.flush(); -				// *FIX: should we do this?   		}  	private: @@ -125,9 +141,10 @@ namespace {  	class RecordToStderr : public LLError::Recorder  	{  	public: -		RecordToStderr(bool timestamp) : mTimestamp(timestamp), mUseANSI(ANSI_PROBE) { } - -		virtual bool wantsTime() { return mTimestamp; } +		RecordToStderr(bool timestamp) : mUseANSI(ANSI_PROBE)  +		{ +			mWantsTime = timestamp; +		}  		virtual void recordMessage(LLError::ELevel level,  					   const std::string& message) @@ -158,14 +175,19 @@ namespace {  		}  	private: -		bool mTimestamp; -		enum ANSIState {ANSI_PROBE, ANSI_YES, ANSI_NO}; -		ANSIState mUseANSI; +		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 @@ -198,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 @@ -213,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); @@ -317,15 +342,15 @@ 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;  			}  		}  		LLError::configure(configuration); -		llinfos << "logging reconfigured from " << filename() << llendl; +		LL_INFOS() << "logging reconfigured from " << filename() << LL_ENDL;  		return true;  	} @@ -390,25 +415,25 @@ namespace LLError  	class Settings  	{  	public: -		bool printLocation; +		bool                                mPrintLocation; -		LLError::ELevel defaultLevel; +		LLError::ELevel                     mDefaultLevel; -		LevelMap functionLevelMap; -		LevelMap classLevelMap; -		LevelMap fileLevelMap; -		LevelMap tagLevelMap; -		std::map<std::string, unsigned int> uniqueLogMessages; +		LevelMap                            mFunctionLevelMap; +		LevelMap                            mClassLevelMap; +		LevelMap                            mFileLevelMap; +		LevelMap                            mTagLevelMap; +		std::map<std::string, unsigned int> mUniqueLogMessages; -		LLError::FatalFunction crashFunction; -		LLError::TimeFunction timeFunction; +		LLError::FatalFunction              mCrashFunction; +		LLError::TimeFunction               mTimeFunction; -		Recorders recorders; -		Recorder* fileRecorder; -		Recorder* fixedBufferRecorder; -		std::string fileRecorderFileName; +		Recorders                           mRecorders; +		Recorder*                           mFileRecorder; +		Recorder*                           mFixedBufferRecorder; +		std::string                         mFileRecorderFileName; -		int shouldLogCallCounter; +		int									mShouldLogCallCounter;  		static Settings& get(); @@ -418,19 +443,19 @@ 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(0)  			{ }  		~Settings()  		{ -			for_each(recorders.begin(), recorders.end(), DeletePointer()); -			recorders.clear(); +			for_each(mRecorders.begin(), mRecorders.end(), DeletePointer()); +			mRecorders.clear();  		}  		static Settings*& getPtr(); @@ -489,18 +514,64 @@ namespace LLError  					int line,  					const std::type_info& class_info,   					const char* function,  -					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) -		{ } +					bool printOnce, +					const char** tags,  +					size_t tag_count) +	:	mLevel(level),  +		mFile(file),  +		mLine(line), +		mClassInfo(class_info),  +		mFunction(function), +		mCached(false),  +		mShouldLog(false),  +		mPrintOnce(printOnce), +		mTags(new const char* [tag_count]), +		mTagCount(tag_count) +	{ +		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(mClassInfo.name(), typeid(NoClassInfo).name())) +#else +		if (mClassInfo != typeid(NoClassInfo)) +#endif // LL_LINUX +		{ +			mFunctionString = className(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 @@ -586,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) @@ -612,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) @@ -626,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) @@ -634,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) @@ -642,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) @@ -650,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) @@ -671,7 +742,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;  		} @@ -698,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"])); @@ -715,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);  		}  	}  } @@ -726,14 +797,45 @@ 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 mWantsTags; +	} +	// virtual  +	bool Recorder::wantsLevel()  +	{  +		return mWantsLevel; +	} + +	// virtual  +	bool Recorder::wantsLocation()  +	{  +		return mWantsLocation; +	} + +	// virtual  +	bool Recorder::wantsFunctionName()  +	{  +		return mWantsFunctionName; +	}  	void addRecorder(Recorder* recorder)  	{ @@ -742,7 +844,7 @@ namespace LLError  			return;  		}  		Settings& s = Settings::get(); -		s.recorders.push_back(recorder); +		s.mRecorders.push_back(recorder);  	}  	void removeRecorder(Recorder* recorder) @@ -752,9 +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());  	}  } @@ -764,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())  		{ @@ -781,8 +882,8 @@ namespace LLError  			return;  		} -		s.fileRecorderFileName = file_name; -		s.fileRecorder = f; +		s.mFileRecorderFileName = file_name; +		s.mFileRecorder = f;  		addRecorder(f);  	} @@ -790,98 +891,112 @@ 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(LLError::ELevel level, 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; -		 -		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) +			std::ostringstream message_stream; + +			if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s.mPrintLocation)) +			{ +				message_stream << site.mLocationString << " "; +			} + +			if (show_time && r->wantsTime() && s.mTimeFunction != NULL)  			{ -				if (messageWithTime.empty()) +				message_stream << s.mTimeFunction() << " "; +			} + +			if (show_level && r->wantsLevel())  				{ -					messageWithTime = s.timeFunction() + " " + message; +				message_stream << site.mLevelString << " ";  				} -				r->recordMessage(level, messageWithTime); +			if (show_tags && r->wantsTags()) +			{ +				message_stream << site.mTagString << " ";  			} -			else + +			if (show_function && r->wantsFunctionName())  			{ -				r->recordMessage(level, message); +				message_stream << site.mFunctionString << " ";  			} + +			message_stream << message; + +			r->recordMessage(level, message_stream.str());  		}  	}  } - -/* -Recorder formats: - -$type = "ERROR" | "WARNING" | "ALERT" | "INFO" | "DEBUG" -$loc = "$file($line)" -$msg = "$loc : " if FATAL or printing loc -		"" otherwise -$msg += "$type: " -$msg += contents of stringstream - -$time = "%Y-%m-%dT%H:%M:%SZ" if UTC -	 or "%Y-%m-%dT%H:%M:%S %Z" if local - -syslog:	"$msg" -file: "$time $msg\n" -stderr: "$time $msg\n" except on windows, "$msg\n" -fixedbuf: "$msg" -winddebug: "$msg\n" - -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 -	 -*/ -  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; +		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 @@ -948,9 +1063,9 @@ namespace LLError  		Globals& g = Globals::get();  		Settings& s = Settings::get(); -		s.shouldLogCallCounter += 1; +		s.mShouldLogCallCounter++; -		std::string class_name = className(site.mClassInfo); +		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 @@ -962,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); @@ -1016,6 +1132,7 @@ namespace LLError  	   }  	   Globals& g = Globals::get(); +         if (out == &g.messageStream)         {             g.messageStream.clear(); @@ -1054,56 +1171,21 @@ namespace LLError  		if (site.mLevel == LEVEL_ERROR)  		{ -			std::ostringstream fatalMessage; -			fatalMessage << abbreviateFile(site.mFile) -						<< "(" << site.mLine << ") : error"; -			 -			writeToRecorders(site.mLevel, fatalMessage.str()); -		} -		 -		 -		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 << ") : "; +			writeToRecorders(site, "error", true, true, true, false, false);  		} -	#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 << ": "; +		std::ostringstream message_stream;  		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  				{ @@ -1112,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.mLevel, 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() @@ -1188,7 +1266,7 @@ namespace LLError  	int shouldLogCallCount()  	{  		Settings& s = Settings::get(); -		return s.shouldLogCallCounter; +		return s.mShouldLogCallCounter;  	}  #if LL_WINDOWS @@ -1376,13 +1454,13 @@ 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 ; +               LL_INFOS() << sBuffer[sIndex] << LL_ENDL;             } -           llinfos << " *************** END OF LL CALL STACKS *************** " << llendl ; +           LL_INFOS() << " *************** END OF LL CALL STACKS *************** " << LL_ENDL;         }  	   if(sBuffer) @@ -1399,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 0b723aeb5d..bc80e64423 100755 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -31,9 +31,68 @@  #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_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_msg(func, #func) +#define llverify(func)			llassert_always_msg(func, #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,50 +180,62 @@ 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); -						 +		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  		void invalidate(); -	private:  		// 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; -		 -		// these implement a cache of the call to shouldLog() -		bool mCached; -		bool mShouldLog; +		const char**			mTags; +		size_t					mTagCount; +		const bool				mPrintOnce; +		const char*				mLevelString; +		std::string				mLocationString, +								mFunctionString, +								mTagString; +		bool					mCached, +								mShouldLog;  		friend class Log;  	}; @@ -198,32 +269,23 @@ 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 llpushcallstacks LLError::LLCallStacks::push(__FUNCTION__, __LINE__) -#define llcallstacks \ -	{\ +#define LL_PUSH_CALLSTACKS() LLError::LLCallStacks::push(__FUNCTION__, __LINE__) + +#define llcallstacks                                                                      \ +	{                                                                                     \         std::ostringstream* _out = LLError::LLCallStacks::insert(__FUNCTION__, __LINE__) ; \         (*_out) -#define llcallstacksendl \ -		LLError::End(); \ + +#define llcallstacksendl                   \ +		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 @@ -237,78 +299,72 @@ 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.	 +///////////////////////////////// +// this macro uses a one-shot do statement to avoid parsing errors when writing control flow statements +// without braces: +// if (condition) LL_INFOS() << "True" << LL_ENDL; else LL_INFOS()() << "False" << LL_ENDL +#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 +//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) -/* -	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) +#define LL_NEWLINE '\n' -// 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__) +// 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). -#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_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/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index 480654b1a2..aab695094c 100755 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -136,14 +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 +		bool wantsTime(); +		bool wantsTags(); +		bool wantsLevel(); +		bool wantsLocation();  +		bool wantsFunctionName(); + +	protected: +		bool	mWantsTime, +				mWantsTags, +				mWantsLevel, +				mWantsLocation, +				mWantsFunctionName;  	};  	/** diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h index 37cee579cd..31dd207008 100755 --- a/indra/llcommon/llerrorlegacy.h +++ b/indra/llcommon/llerrorlegacy.h @@ -28,91 +28,5 @@  #ifndef LL_LLERRORLEGACY_H  #define LL_LLERRORLEGACY_H -#include "llpreprocessor.h" - -/* -	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 - -// 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/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/llevent.h b/indra/llcommon/llevent.h index 8cd682b8bf..28ce7de102 100755 --- a/indra/llcommon/llevent.h +++ b/indra/llcommon/llevent.h @@ -29,8 +29,8 @@  #define LL_EVENT_H  #include "llsd.h" +#include "llrefcount.h"  #include "llpointer.h" -#include "llthread.h"  namespace LLOldEvents  { diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 0855180dcd..1c928b3db8 100755 --- 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/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/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index 58db7d0d17..3d28cd15b0 100755 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -32,8 +32,13 @@  #include "llsingleton.h"  #include "lltreeiterators.h"  #include "llsdserialize.h" +#include "llunits.h" +#include "llsd.h" +#include "lltracerecording.h" +#include "lltracethreadrecorder.h"  #include <boost/bind.hpp> +#include <queue>  #if LL_WINDOWS @@ -49,140 +54,115 @@  #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; +bool        BlockTimer::sLog		     = false; +std::string BlockTimer::sLogName         = ""; +bool        BlockTimer::sMetricLog       = false;  #if LL_LINUX || LL_SOLARIS -U64 LLFastTimer::sClockResolution = 1000000000; // Nanosecond resolution +U64         BlockTimer::sClockResolution = 1000000000; // Nanosecond resolution  #else -U64 LLFastTimer::sClockResolution = 1000000; // Microsecond resolution +U64         BlockTimer::sClockResolution = 1000000; // Microsecond resolution  #endif -// 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; +static LLMutex*			sLogLock = NULL; +static std::queue<LLSD> sLogQueue; -static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(LLFastTimer::NamedTimer& id)  +block_timer_tree_df_iterator_t begin_block_timer_tree_df(BlockTimerStatHandle& 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)); +	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_bottom_up_iterator_t end_timer_tree_bottom_up()  +block_timer_tree_df_iterator_t end_block_timer_tree_df()   {  -	return timer_tree_bottom_up_iterator_t();  +	return block_timer_tree_df_iterator_t();   } -typedef LLTreeDFSIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_dfs_iterator_t; - +block_timer_tree_df_post_iterator_t begin_block_timer_tree_df_post(BlockTimerStatHandle& 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_dfs_iterator_t begin_timer_tree(LLFastTimer::NamedTimer& id)  +block_timer_tree_df_post_iterator_t end_block_timer_tree_df_post()   {  -	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)); +	return block_timer_tree_df_post_iterator_t();   } -static timer_tree_dfs_iterator_t end_timer_tree()  +block_timer_tree_bf_iterator_t begin_block_timer_tree_bf(BlockTimerStatHandle& id)  {  -	return timer_tree_dfs_iterator_t();  +	return block_timer_tree_bf_iterator_t(&id,  +		boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1),  +		boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));  } -// factory class that creates NamedTimers via static DeclareTimer objects -class NamedTimerFactory : public LLSingleton<NamedTimerFactory> -{ -public: -	NamedTimerFactory() -	:	mTimerRoot(new LLFastTimer::NamedTimer("root")) +block_timer_tree_bf_iterator_t end_block_timer_tree_bf()  	{ -		mRootFrameState.setNamedTimer(mTimerRoot); -		mTimerRoot->setFrameState(&mRootFrameState); -		mTimerRoot->mParent = mTimerRoot; -		mTimerRoot->setCollapsed(false); -		mRootFrameState.mParent = &mRootFrameState;	 +	return block_timer_tree_bf_iterator_t();   	} -	~NamedTimerFactory() +block_timer_tree_df_iterator_t begin_timer_tree(BlockTimerStatHandle& id)   	{ -		std::for_each(mTimers.begin(), mTimers.end(), DeletePairedPointer()); -		mTimers.clear(); - -		delete mTimerRoot; +	return block_timer_tree_df_iterator_t(&id,  +		boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1),  +							boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));  	} -	LLFastTimer::NamedTimer& createNamedTimer(const std::string& name, LLFastTimer::FrameState* state) +block_timer_tree_df_iterator_t end_timer_tree()   	{ -		LLFastTimer::NamedTimer* timer = new LLFastTimer::NamedTimer(name); -		timer->setFrameState(state); -		timer->setParent(mTimerRoot); -		mTimers.insert(std::make_pair(name, timer)); +	return block_timer_tree_df_iterator_t();  +} -		return *timer; -	} -	LLFastTimer::NamedTimer* getTimerByName(const std::string& name) +// sort child timers by name +struct SortTimerByName  	{ -		timer_map_t::iterator found_it = mTimers.find(name); -		if (found_it != mTimers.end()) +	bool operator()(const BlockTimerStatHandle* i1, const BlockTimerStatHandle* i2)  		{ -			return found_it->second; +		return i1->getName() < i2->getName();  		} -		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)) +static BlockTimerStatHandle sRootTimer("root", NULL); +BlockTimerStatHandle& BlockTimer::getRootTimeBlock()  { -	mTimer.setCollapsed(!open); +	return sRootTimer; +	} + +void BlockTimer::pushLog(LLSD log) +{ +	LLMutexLock lock(sLogLock); + +	sLogQueue.push(log);  } -LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name) -:	mTimer(NamedTimerFactory::instance().createNamedTimer(name, &mFrameState)) +void BlockTimer::setLogLock(LLMutex* lock)  { +	sLogLock = lock;  } +  //static  #if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__)) -U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer +U64 BlockTimer::countsPerSecond()  { -	return sClockResolution >> 8; +	return sClockResolution;  }  #else // windows or x86-mac or x86-linux or x86-solaris -U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer +U64 BlockTimer::countsPerSecond()  {  #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); - -	// we drop the low-order byte in our timers, so report a lower frequency +	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()) @@ -194,270 +174,211 @@ U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer  		QueryPerformanceFrequency((LARGE_INTEGER*)&sCPUClockFrequency);  		firstcall = false;  	} +	return sCPUClockFrequency.value();  #endif -	return sCPUClockFrequency >> 8;  }  #endif -LLFastTimer::FrameState::FrameState() -:	mActiveCount(0), -	mCalls(0), -	mSelfTimeCounter(0), -	mParent(NULL), -	mLastCaller(NULL), -	mMoveUpTree(false) +BlockTimerStatHandle::BlockTimerStatHandle(const char* name, const char* description) +:	StatType<TimeBlockAccumulator>(name, description)  {} - -LLFastTimer::NamedTimer::NamedTimer(const std::string& name) -:	mName(name), -	mCollapsed(true), -	mParent(NULL), -	mTotalTimeCounter(0), -	mCountAverage(0), -	mCallAverage(0), -	mNeedsSorting(false), -	mFrameState(NULL) +TimeBlockTreeNode& BlockTimerStatHandle::getTreeNode() const  { -	mCountHistory = new U32[HISTORY_NUM]; -	memset(mCountHistory, 0, sizeof(U32) * HISTORY_NUM); -	mCallHistory = new U32[HISTORY_NUM]; -	memset(mCallHistory, 0, sizeof(U32) * HISTORY_NUM); +	TimeBlockTreeNode* nodep = LLTrace::get_thread_recorder()->getTimeBlockTreeNode(getIndex()); +	llassert(nodep); +	return *nodep;  } -LLFastTimer::NamedTimer::~NamedTimer() -{ -	delete[] mCountHistory; -	delete[] mCallHistory; -} -std::string LLFastTimer::NamedTimer::getToolTip(S32 history_idx) +void BlockTimer::bootstrapTimerTree()  { -	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 +	for (BlockTimerStatHandle::instance_tracker_t::instance_iter it = BlockTimerStatHandle::instance_tracker_t::beginInstances(), end_it = BlockTimerStatHandle::instance_tracker_t::endInstances();  +		it != end_it;  +		++it)  	{ -		return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getHistoricalCount(history_idx) * ms_multiplier), (S32)getHistoricalCalls(history_idx)); -	} -} +		BlockTimerStatHandle& timer = static_cast<BlockTimerStatHandle&>(*it); +		if (&timer == &BlockTimer::getRootTimeBlock()) continue; -void LLFastTimer::NamedTimer::setParent(NamedTimer* parent) +		// bootstrap tree construction by attaching to last timer to be on stack +		// when this timer was called +		if (timer.getParent() == &BlockTimer::getRootTimeBlock())  { -	llassert_always(parent != this); -	llassert_always(parent != NULL); +			TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator(); -	if (mParent) +			if (accumulator.mLastCaller)  	{ -		// 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<NamedTimer*>& children = mParent->getChildren(); -		std::vector<NamedTimer*>::iterator found_it = std::find(children.begin(), children.end(), this); -		if (found_it != children.end()) -		{ -			children.erase(found_it); +				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;  	} - -	mParent = parent; -	if (parent) -	{ -		getFrameState().mParent = &parent->getFrameState(); -		parent->getChildren().push_back(this); -		parent->mNeedsSorting = true;  	}  } -S32 LLFastTimer::NamedTimer::getDepth() +// 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 BlockTimer::incrementalUpdateTimerTree()  { -	S32 depth = 0; -	NamedTimer* timerp = mParent; -	while(timerp) +	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)  	{ -		depth++; -		if (timerp->getParent() == timerp) break; -		timerp = timerp->mParent; -	} -	return depth; -} +		BlockTimerStatHandle* timerp = *it; -// static -void LLFastTimer::NamedTimer::processTimes() +		// sort timers by time last called, so call graph makes sense +		TimeBlockTreeNode& tree_node = timerp->getTreeNode(); +		if (tree_node.mNeedsSorting)  { -	if (sCurFrameIndex < 0) return; - -	buildHierarchy(); -	accumulateTimings(); +			std::sort(tree_node.mChildren.begin(), tree_node.mChildren.end(), SortTimerByName());  } -// sort child timers by name -struct SortTimerByName +		// skip root timer +		if (timerp != &BlockTimer::getRootTimeBlock())  { -	bool operator()(const LLFastTimer::NamedTimer* i1, const LLFastTimer::NamedTimer* i2) -	{ -		return i1->getName() < i2->getName(); -	} -}; +			TimeBlockAccumulator& accumulator = timerp->getCurrentAccumulator(); -//static -void LLFastTimer::NamedTimer::buildHierarchy() +			if (accumulator.mMoveUpTree)  { -	if (sCurFrameIndex < 0 ) return; - -	// set up initial tree -	{ -		for (instance_iter it = beginInstances(); it != endInstances(); ++it) -		{ -			NamedTimer& timer = *it; -			if (&timer == NamedTimerFactory::instance().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()) -			{ -				timer.setParent(timer.getFrameState().mLastCaller->mTimer); -				// no need to push up tree on first use, flag can be set spuriously -				timer.getFrameState().mMoveUpTree = false; -			} -		} -	} - -	// 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()); -		it != end_timer_tree_bottom_up(); -		++it) -	{ -		NamedTimer* timerp = *it; -		// skip root timer -		if (timerp == NamedTimerFactory::instance().getRootTimer()) continue; - -		if (timerp->getFrameState().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->getFrameState().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  			it.skipAncestors();  		}  	} +	} +} -	// sort timers by time last called, so call graph makes sense -	for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer()); -		it != end_timer_tree(); -		++it) + +void BlockTimer::updateTimes()  	{ -		NamedTimer* timerp = (*it); -		if (timerp->mNeedsSorting) +	// 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; + +	U64 cur_time = getCPUClockCount64(); +	BlockTimer* cur_timer				= stack_record->mActiveTimer; +	TimeBlockAccumulator* accumulator	= &stack_record->mTimeBlock->getCurrentAccumulator(); + +	while(cur_timer  +		&& cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self  		{ -			std::sort(timerp->getChildren().begin(), timerp->getChildren().end(), SortTimerByName()); -		} -		timerp->mNeedsSorting = false; +		U64 cumulative_time_delta = cur_time - cur_timer->mStartTime; +		cur_timer->mStartTime = cur_time; + +		accumulator->mTotalTimeCounter += cumulative_time_delta; +		accumulator->mSelfTimeCounter += cumulative_time_delta - stack_record->mChildTime; +		stack_record->mChildTime = 0; + +		stack_record = &cur_timer->mParentTimerData; +		accumulator  = &stack_record->mTimeBlock->getCurrentAccumulator(); +		cur_timer    = stack_record->mActiveTimer; + +		stack_record->mChildTime += cumulative_time_delta;  	}  } +static LLTrace::BlockTimerStatHandle FTM_PROCESS_TIMES("Process FastTimer Times"); + +// not thread safe, so only call on main thread  //static -void LLFastTimer::NamedTimer::accumulateTimings() +void BlockTimer::processTimes()  { -	U32 cur_time = getCPUClockCount32(); +#if LL_TRACE_ENABLED +	LL_RECORD_BLOCK_TIME(FTM_PROCESS_TIMES); +	get_clock_count(); // good place to calculate clock frequency -	// walk up stack of active timers and accumulate current time while leaving timing structures active -	LLFastTimer* cur_timer = sCurTimerData.mCurTimer; -	// root defined by parent pointing to self -	CurTimerData* cur_data = &sCurTimerData; -	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_timer->mFrameState->mSelfTimeCounter += self_time_delta; -		cur_timer->mStartTime = cur_time; +	// set up initial tree +	bootstrapTimerTree(); -		cur_data = &cur_timer->mLastTimerData; -		cur_data->mChildTime += cumulative_time_delta; +	incrementalUpdateTimerTree(); -		cur_timer = cur_timer->mLastTimerData.mCurTimer; -	} +	updateTimes(); -	// 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()); -		it != end_timer_tree_bottom_up(); +	// reset for next frame +	for (BlockTimerStatHandle::instance_tracker_t::instance_iter it = BlockTimerStatHandle::instance_tracker_t::beginInstances(), +			end_it = BlockTimerStatHandle::instance_tracker_t::endInstances(); +		it != end_it;  		++it)  	{ -		NamedTimer* timerp = (*it); -		timerp->mTotalTimeCounter = timerp->getFrameState().mSelfTimeCounter; -		for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it) +		BlockTimerStatHandle& timer = static_cast<BlockTimerStatHandle&>(*it); +		TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator(); + +		accumulator.mLastCaller = NULL; +		accumulator.mMoveUpTree = false; +	} +#endif +} + +std::vector<BlockTimerStatHandle*>::iterator BlockTimerStatHandle::beginChildren()  		{ -			timerp->mTotalTimeCounter += (*child_it)->mTotalTimeCounter; +	return getTreeNode().mChildren.begin();   		} -		S32 cur_frame = sCurFrameIndex; -		if (cur_frame >= 0) +std::vector<BlockTimerStatHandle*>::iterator BlockTimerStatHandle::endChildren()  		{ -			// update timer history -			int hidx = cur_frame % HISTORY_NUM; +	return getTreeNode().mChildren.end(); +} -			timerp->mCountHistory[hidx] = timerp->mTotalTimeCounter; -			timerp->mCountAverage = ((U64)timerp->mCountAverage * cur_frame + timerp->mTotalTimeCounter) / (cur_frame+1); -			timerp->mCallHistory[hidx] = timerp->getFrameState().mCalls; -			timerp->mCallAverage = ((U64)timerp->mCallAverage * cur_frame + timerp->getFrameState().mCalls) / (cur_frame+1); -		} +std::vector<BlockTimerStatHandle*>& BlockTimerStatHandle::getChildren() +{ +	return getTreeNode().mChildren;  	} + +bool BlockTimerStatHandle::hasChildren() +{ +	return ! getTreeNode().mChildren.empty();  }  // static -void LLFastTimer::NamedTimer::resetFrame() +void BlockTimer::logStats()  { +	// get ready for next frame  	if (sLog)  	{ //output current frame counts to performance log  		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() << llendl; +			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())/((F64)LLProcessorInfo().getCPUFrequency()*1000000.0) << LL_ENDL; +			LL_DEBUGS("FastTimers") << "elapsed sec " << ((F64)getCPUClockCount64() / (F64HertzImplicit)LLProcessorInfo().getCPUFrequency()) << LL_ENDL;  		}  		call_count++; -		F64 iclock_freq = 1000.0 / countsPerSecond(); // good place to calculate clock frequency - -		F64 total_time = 0; +		F64Seconds total_time(0);  		LLSD sd;  		{ -			for (instance_iter it = beginInstances(); it != endInstances(); ++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)  			{ -				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; +				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()));  				// 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 += frame_recording.getLastRecording().getSum(timer);  			}  		} -		sd["Total"]["Time"] = (LLSD::Real) total_time; +		sd["Total"]["Time"] = (LLSD::Real) total_time.value();  		sd["Total"]["Calls"] = (LLSD::Integer) 1;  		{		 @@ -466,168 +387,44 @@ void LLFastTimer::NamedTimer::resetFrame()  		}  	} -	// reset for next frame -	for (instance_iter it = beginInstances(); it != endInstances(); ++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(); -		} -	} -} - -//static -void LLFastTimer::NamedTimer::reset() -{ -	resetFrame(); // reset frame data - -	// walk up stack of active timers and reset start times to current time -	// effectively zeroing out any accumulated time -	U32 cur_time = getCPUClockCount32(); - -	// root defined by parent pointing to self -	CurTimerData* cur_data = &sCurTimerData; -	LLFastTimer* 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 (instance_iter it = beginInstances(); it != endInstances(); ++it) -		{ -			NamedTimer& timer = *it; -			if (&timer != NamedTimerFactory::instance().getRootTimer())  -			{ -				timer.setParent(NamedTimerFactory::instance().getRootTimer()); -			} -			 -			timer.mCountAverage = 0; -			timer.mCallAverage = 0; -			memset(timer.mCountHistory, 0, sizeof(U32) * HISTORY_NUM); -			memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM); -		} -	} - -	sLastFrameIndex = 0; -	sCurFrameIndex = 0; -} - -U32 LLFastTimer::NamedTimer::getHistoricalCount(S32 history_index) const -{ -	S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM; -	return mCountHistory[history_idx]; -} - -U32 LLFastTimer::NamedTimer::getHistoricalCalls(S32 history_index ) const -{ -	S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM; -	return mCallHistory[history_idx]; -} - -LLFastTimer::FrameState& LLFastTimer::NamedTimer::getFrameState() const -{ -	return *mFrameState; -} - -std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::beginChildren() -{  -	return mChildren.begin();  -} - -std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::endChildren() -{ -	return mChildren.end(); -} - -std::vector<LLFastTimer::NamedTimer*>& LLFastTimer::NamedTimer::getChildren() -{ -	return mChildren; -} - -//static -LLFastTimer::NamedTimer& LLFastTimer::NamedTimer::getRootNamedTimer() -{ -        return *NamedTimerFactory::instance().getRootTimer(); -} - -//static -void LLFastTimer::nextFrame() -{ -	countsPerSecond(); // good place to calculate clock frequency -	U64 frame_time = getCPUClockCount64(); -	if ((frame_time - sLastFrameTime) >> 8 > 0xffffffff) -	{ -		llinfos << "Slow frame, fast timers inaccurate" << llendl; -	} - -	if (!sPauseHistory) -	{ -		NamedTimer::processTimes(); -		sLastFrameIndex = sCurFrameIndex++; -	} -	 -	// get ready for next frame -	NamedTimer::resetFrame(); -	sLastFrameTime = frame_time;  }  //static -void LLFastTimer::dumpCurTimes() +void BlockTimer::dumpCurTimes()  { -	// accumulate timings, etc. -	NamedTimer::processTimes(); -	 -	F64 clock_freq = (F64)countsPerSecond(); -	F64 iclock_freq = 1000.0 / clock_freq; // clock_ticks -> milliseconds +	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(*NamedTimerFactory::instance().getRootTimer()); +	for(block_timer_tree_df_iterator_t it = begin_timer_tree(BlockTimer::getRootTimeBlock());  		it != end_timer_tree();  		++it)  	{ -		NamedTimer* timerp = (*it); -		F64 total_time_ms = ((F64)timerp->getHistoricalCount(0) * iclock_freq); +		BlockTimerStatHandle* timerp = (*it); +		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_ms < 0.1) continue; +		if (total_time < F32Milliseconds(0.1f)) continue;  		std::ostringstream out_str; -		for (S32 i = 0; i < timerp->getDepth(); i++) +		BlockTimerStatHandle* parent_timerp = timerp; +		while(parent_timerp && parent_timerp != parent_timerp->getParent())  		{  			out_str << "\t"; +			parent_timerp = parent_timerp->getParent();  		} -  		out_str << timerp->getName() << " "  -			<< std::setprecision(3) << total_time_ms << " ms, " -			<< timerp->getHistoricalCalls(0) << " calls"; +			<< std::setprecision(3) << total_time.valueInUnits<LLUnits::Milliseconds>() << " ms, " +			<< num_calls << " calls"; -		llinfos << out_str.str() << llendl; -	} +		LL_INFOS() << out_str.str() << LL_ENDL;  } - -//static  -void LLFastTimer::reset() -{ -	NamedTimer::reset();  } -  //static -void LLFastTimer::writeLog(std::ostream& os) +void BlockTimer::writeLog(std::ostream& os)  {  	while (!sLogQueue.empty())  	{ @@ -638,22 +435,57 @@ void LLFastTimer::writeLog(std::ostream& os)  	}  } -//static -const LLFastTimer::NamedTimer* LLFastTimer::getTimerByName(const std::string& name) +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// TimeBlockAccumulator +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +TimeBlockAccumulator::TimeBlockAccumulator()  +:	mTotalTimeCounter(0), +	mSelfTimeCounter(0), +	mCalls(0), +	mLastCaller(NULL), +	mActiveCount(0), +	mMoveUpTree(false), +	mParent(NULL) +{} + +void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other, EBufferAppendType append_type )  { -	return NamedTimerFactory::instance().getTimerByName(name); +#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); +	mTotalTimeCounter += other.mTotalTimeCounter; +	mSelfTimeCounter += other.mSelfTimeCounter; +	mCalls += other.mCalls; +	mLastCaller = other.mLastCaller; +	mActiveCount = other.mActiveCount; +	mMoveUpTree = other.mMoveUpTree; +	mParent = other.mParent; +#endif  } -LLFastTimer::LLFastTimer(LLFastTimer::FrameState* state) -:	mFrameState(state) +void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other ) +{ +	mCalls = 0; +	mSelfTimeCounter = 0; +	mTotalTimeCounter = 0; + +	if (other)  { -	U32 start_time = getCPUClockCount32(); -	mStartTime = start_time; -	mFrameState->mActiveCount++; -	LLFastTimer::sCurTimerData.mCurTimer = this; -	LLFastTimer::sCurTimerData.mFrameState = mFrameState; -	LLFastTimer::sCurTimerData.mChildTime = 0; -	mLastTimerData = LLFastTimer::sCurTimerData; +		mLastCaller = other->mLastCaller; +		mActiveCount = other->mActiveCount; +		mMoveUpTree = other->mMoveUpTree; +		mParent = other->mParent; +	} +} + +F64Seconds BlockTimer::getElapsedTime() +{ +	U64 total_time = getCPUClockCount64() - mStartTime; + +	return F64Seconds((F64)total_time / (F64)BlockTimer::countsPerSecond());  } +} // namespace LLTrace diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index a99a1d88af..2370253078 100755 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -28,218 +28,30 @@  #define LL_FASTTIMER_H  #include "llinstancetracker.h" +#include "lltrace.h" +#include "lltreeiterators.h" -#define FAST_TIMER_ON 1 -#define DEBUG_FAST_TIMER_THREADS 1 - -class LLMutex; - -#include <queue> -#include "llsd.h" - +#define LL_FAST_TIMER_ON 1  #define LL_FASTTIMER_USE_RDTSC 1 +#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__); -LL_COMMON_API void assert_main_thread(); - -class LL_COMMON_API LLFastTimer +namespace LLTrace  { -public: -	class NamedTimer; - -	struct LL_COMMON_API FrameState -	{ -		FrameState(); -		void setNamedTimer(NamedTimer* timerp) { mTimer = timerp; } - -		U32 				mSelfTimeCounter; -		U32 				mCalls; -		FrameState*			mParent;		// info for caller timer -		FrameState*			mLastCaller;	// used to bootstrap tree construction -		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 -	}; - -	// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances -	class LL_COMMON_API NamedTimer -	:	public LLInstanceTracker<NamedTimer> -	{ -		friend class DeclareTimer; -	public: -		~NamedTimer(); - -		enum { HISTORY_NUM = 300 }; - -		const std::string& getName() const { return mName; } -		NamedTimer* getParent() const { return mParent; } -		void setParent(NamedTimer* parent); -		S32 getDepth(); -		std::string getToolTip(S32 history_index = -1); - -		typedef std::vector<NamedTimer*>::const_iterator child_const_iter; -		child_const_iter beginChildren(); -		child_const_iter endChildren(); -		std::vector<NamedTimer*>& 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 NamedTimer& getRootNamedTimer(); - -		void setFrameState(FrameState* state) { mFrameState = state; state->setNamedTimer(this); } -		FrameState& getFrameState() const; - -	private: -		friend class LLFastTimer; -		friend class NamedTimerFactory; - -		// -		// methods -		// -		NamedTimer(const std::string& name); -		// 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 -		// -		FrameState*		mFrameState; - -		std::string	mName; - -		U32 		mTotalTimeCounter; - -		U32 		mCountAverage; -		U32			mCallAverage; - -		U32*		mCountHistory; -		U32*		mCallHistory; - -		// tree structure -		NamedTimer*					mParent;				// NamedTimer of caller(parent) -		std::vector<NamedTimer*>	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) -	:	mFrameState(&timer.mFrameState) -	{ -#if FAST_TIMER_ON -		LLFastTimer::FrameState* frame_state = mFrameState; -		mStartTime = getCPUClockCount32(); - -		frame_state->mActiveCount++; -		frame_state->mCalls++; -		// keep current parent as long as it is active when we are -		frame_state->mMoveUpTree |= (frame_state->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->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 = mFrameState; -		U32 total_time = getCPUClockCount32() - mStartTime; - -		frame_state->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime; -		frame_state->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; - -		// we are only tracking self time, so subtract our total time delta from parents -		mLastTimerData.mChildTime += total_time; - -		LLFastTimer::sCurTimerData = mLastTimerData; -#endif -	} +// 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: -	static LLMutex*			sLogLock; -	static std::queue<LLSD> sLogQueue; -	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(); +	typedef BlockTimer self_t; +	typedef class BlockTimerStatHandle DeclareTimer; -	// dumps current cumulative frame stats to log -	// call nextFrame() to reset timers -	static void dumpCurTimes(); +	~BlockTimer(); -	// call this to reset timer hierarchy, averages, etc. -	static void reset(); +	F64Seconds getElapsedTime(); -	static U64 countsPerSecond(); -	static S32 getLastFrameIndex() { return sLastFrameIndex; } -	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; -		U32				mChildTime; -	}; -	static CurTimerData		sCurTimerData; - -private: - - -	////////////////////////////////////////////////////////////////////////////// +		//////////////////////////////////////////////////////////////////////////////  	//  	// Important note: These implementations must be FAST!  	// @@ -261,14 +73,14 @@ private:  	//#undef _interlockedbittestandset  	//#undef _interlockedbittestandreset -	//inline U32 LLFastTimer::getCPUClockCount32() +	//inline U32 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 getCPUClockCount64()  	//{  	//	return __rdtsc();  	//} @@ -308,7 +120,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()  	{ @@ -375,18 +187,160 @@ private:  #endif -	static U64 sClockResolution; +	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, +	// can be called multiple times in a frame, at any point +	static void processTimes(); -	static S32				sCurFrameIndex; -	static S32				sLastFrameIndex; -	static U64				sLastFrameTime; +	static void bootstrapTimerTree(); +	static void incrementalUpdateTimerTree(); -	U32							mStartTime; -	LLFastTimer::FrameState*	mFrameState; -	LLFastTimer::CurTimerData	mLastTimerData; +	// call this once a frame to periodically log timers +	static void logStats(); + +	// 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;  }; -typedef class LLFastTimer LLFastTimer; +// 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 +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 +	BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance(); +	if (!cur_timer_data) return; +	TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator(); +	accumulator.mActiveCount++; +	// keep current parent as long as it is active when we are +	accumulator.mMoveUpTree |= (accumulator.mParent->getCurrentAccumulator().mActiveCount == 0); + +	// store top of stack +	mParentTimerData = *cur_timer_data; +	// push new information +	cur_timer_data->mActiveTimer = this; +	cur_timer_data->mTimeBlock = &timer; +	cur_timer_data->mChildTime = 0; + +	mStartTime = getCPUClockCount64(); +#endif +} + +LL_FORCE_INLINE BlockTimer::~BlockTimer() +{ +#if LL_FAST_TIMER_ON +	U64 total_time = getCPUClockCount64() - mStartTime; +	BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance(); +	if (!cur_timer_data) return; + +	TimeBlockAccumulator& accumulator = cur_timer_data->mTimeBlock->getCurrentAccumulator(); + +	accumulator.mCalls++; +	accumulator.mTotalTimeCounter += total_time; +	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; + +	// we are only tracking self time, so subtract our total time delta from parents +	mParentTimerData.mChildTime += total_time; + +	//pop stack +	*cur_timer_data = mParentTimerData; +#endif +} + +} + +typedef LLTrace::BlockTimer LLFastTimer;   #endif // LL_LLFASTTIMER_H diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index c3a0f0bfe0..06bc931dea 100755 --- 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> @@ -438,7 +438,7 @@ llstdio_filebuf::int_type llstdio_filebuf::overflow(llstdio_filebuf::int_type __  				_M_set_buffer(0);  				__ret = traits_type::not_eof(__c);  			} -	} +		}  		else if (_M_buf_size > 1)  		{  			// Overflow in 'uncommitted' mode: set _M_writing, set @@ -496,11 +496,11 @@ bool llstdio_filebuf::_convert_to_external(char_type* __ibuf,  		if (__r == codecvt_base::ok || __r == codecvt_base::partial)  			__blen = __bend - __buf;  		else if (__r == codecvt_base::noconv) -	{ +		{  			// Same as the always_noconv case above.  			__buf = reinterpret_cast<char*>(__ibuf);  			__blen = __ilen; -	} +		}  		else  			__throw_ios_failure(__N("llstdio_filebuf::_convert_to_external "  									"conversion error")); @@ -643,9 +643,9 @@ llstdio_filebuf::int_type llstdio_filebuf::underflow()  							_M_ext_end, _M_ext_next,  							this->eback(),  							this->eback() + __buflen, __iend); -} +				}  				if (__r == codecvt_base::noconv) -{ +				{  					size_t __avail = _M_ext_end - _M_ext_buf;  					__ilen = std::min(__avail, __buflen);  					traits_type::copy(this->eback(), @@ -806,15 +806,15 @@ std::streamsize llstdio_filebuf::xsputn(char_type* __s, std::streamsize __n)  				__ret = fwrite(__buf, 1, __buffill, _M_file.file());  			}  			if (__ret == __buffill) -	{ +			{  				__ret += fwrite(reinterpret_cast<const char*>(__s), 1,  								__n, _M_file.file()); -	} +			}  			if (__ret == __buffill + __n)  			{  				_M_set_buffer(0);  				_M_writing = true; -} +			}  			if (__ret > __buffill)  				__ret -= __buffill;  			else @@ -848,7 +848,7 @@ llifstream::llifstream() : _M_filebuf(),  #endif  // explicit -llifstream::llifstream(const std::string& _Filename, +llifstream::llifstream(const std::string& _Filename,   		ios_base::openmode _Mode) : _M_filebuf(),  #if LL_WINDOWS  	std::istream(&_M_filebuf) @@ -877,7 +877,7 @@ llifstream::llifstream(const char* _Filename,  	if (_M_filebuf.open(wideName.c_str(), _Mode | ios_base::in) == 0)  	{  		_Myios::setstate(ios_base::failbit); -} +	}  }  #else  	std::istream() @@ -951,8 +951,8 @@ void llifstream::close()  #else  		this->setstate(ios_base::failbit);  #endif -		}  	} +}  /************** output file stream ********************************/ @@ -1042,7 +1042,7 @@ void llofstream::open(const char* _Filename, ios_base::openmode _Mode)  #if LL_WINDOWS  	llutf16string wideName = utf8str_to_utf16str( _Filename );  	if (_M_filebuf.open( wideName.c_str(), _Mode | ios_base::out) == 0) -{ +	{  		_Myios::setstate(ios_base::failbit);  	}  	else diff --git a/indra/llcommon/llfindlocale.cpp b/indra/llcommon/llfindlocale.cpp index cd7c0c7c09..f019bd0c64 100755 --- 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/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 100644 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/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/llframetimer.h b/indra/llcommon/llframetimer.h index 45754f3785..81bd5da8a3 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   { @@ -44,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; @@ -53,7 +52,7 @@ public:  	// Return a low precision usec since epoch  	static U64 getTotalTime()  	{ -		return sTotalTime ? sTotalTime : totalTime(); +		return sTotalTime ? U64MicrosecondsImplicit(sTotalTime) : totalTime();  	}  	// Return a low precision seconds since epoch 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/llindexedqueue.h b/indra/llcommon/llindexedqueue.h deleted file mode 100755 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/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 89c831d296..aa2f4eb289 100755 --- a/indra/llcommon/llinitparam.cpp +++ b/indra/llcommon/llinitparam.cpp @@ -28,10 +28,17 @@  #include "linden_common.h"  #include "llinitparam.h" +#include "llformat.h"  namespace LLInitParam  { + +	predicate_rule_t default_parse_rules()  +	{  +		return ll_make_predicate(PROVIDED) && !ll_make_predicate(EMPTY); +	} +  	//  	// Param  	// @@ -93,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;  	} @@ -124,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()) @@ -196,6 +203,9 @@ namespace LLInitParam  	bool BaseBlock::validateBlock(bool emit_errors) const  	{ +		// only validate block when it hasn't already passed validation with current data +		if (!mValidated) +		{  		const BlockDescriptor& block_data = mostDerivedBlockDescriptor();  		for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it)  		{ @@ -204,16 +214,23 @@ 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;  			}  		} -		return true; +			mValidated = true; +		} +		return mValidated;  	} -	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 predicate_rule_t predicate_rule, const LLInitParam::BaseBlock* diff_block) const  	{ +		bool serialized = false; +		if (!predicate_rule.check(ll_make_predicate(PROVIDED, isProvided()))) +		{ +			return false; +		}  		// named param is one like LLView::Params::follows  		// unnamed param is like LLView::Params::rect - implicit  		const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); @@ -225,10 +242,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 && predicate_rule.check(ll_make_predicate(PROVIDED, 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, predicate_rule, diff_param);  			}  		} @@ -239,7 +256,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. @@ -264,10 +281,17 @@ 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, predicate_rule, diff_param);  				name_stack.pop_back();  			}  		} + +		if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY))) +		{ +			serialized |= parser.writeValue(Flag(), name_stack); +		} +		// 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 @@ -393,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/llinitparam.h b/indra/llcommon/llinitparam.h index 03ab0fb67f..880cd0a370 100755 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -29,14 +29,16 @@  #define LL_LLPARAM_H  #include <vector> +#include <list>  #include <boost/function.hpp>  #include <boost/type_traits/is_convertible.hpp>  #include <boost/type_traits/is_enum.hpp>  #include <boost/unordered_map.hpp> -#include <boost/shared_ptr.hpp>  #include "llerror.h"  #include "llstl.h" +#include "llpredicate.h" +#include "llsd.h"  namespace LLTypeTags  { @@ -195,6 +197,8 @@ namespace LLInitParam  			return mValue;  		} +		bool isValid() const { return true; } +  	protected:  		T mValue;  	}; @@ -209,13 +213,11 @@ namespace LLInitParam  		typedef T	value_t;  		ParamValue()  -		:	T(), -			mValidated(false) +		:	T()  		{}  		ParamValue(const default_value_t& other) -		:	T(other), -			mValidated(false) +		:	T(other)  		{}  		void setValue(const value_t& val) @@ -232,9 +234,6 @@ namespace LLInitParam  		{  			return *this;  		} - -	protected: -		mutable bool 	mValidated; // lazy validation flag  	}; @@ -497,25 +496,25 @@ namespace LLInitParam  		virtual ~Parser();  		template <typename T> bool readValue(T& param, typename boost::disable_if<boost::is_enum<T> >::type* dummy = 0) -			{ +		{  			parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));  			if (found_it != mParserReadFuncs->end()) -				{ +			{  				return found_it->second(*this, (void*)¶m); -				} -			 -				return false;  			} +			return false; +		} +			  		template <typename T> bool readValue(T& param, typename boost::enable_if<boost::is_enum<T> >::type* dummy = 0) -			{ +		{  			parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));  			if (found_it != mParserReadFuncs->end()) -				{ +			{  				return found_it->second(*this, (void*)¶m); -				} +			}  			else -		{ +			{  				found_it = mParserReadFuncs->find(&typeid(S32));  				if (found_it != mParserReadFuncs->end())  				{ @@ -579,6 +578,19 @@ namespace LLInitParam  	class Param; +	enum ESerializePredicates +	{ +		PROVIDED, +		REQUIRED, +		VALID, +		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  	{ @@ -589,7 +601,7 @@ namespace LLInitParam  		typedef bool(*merge_func_t)(Param&, const Param&, bool);  		typedef bool(*deserialize_func_t)(Param&, Parser&, 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 predicate_rule_t rules, 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*); @@ -617,7 +629,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 @@ -829,12 +841,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; @@ -852,10 +880,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; +		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 getBlockDescriptor(); } @@ -893,6 +930,9 @@ namespace LLInitParam  			return mergeBlock(block_data, source, overwrite);  		} +		mutable bool 	mValidated; // lazy validation flag +		bool			mParamProvided; +  	private:  		const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const;  	}; @@ -986,6 +1026,8 @@ namespace LLInitParam  		bool isProvided() const { return Param::anyProvided(); } +		bool isValid() const { return true; } +  		static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)  		{   			self_t& typed_param = static_cast<self_t&>(param); @@ -1014,10 +1056,23 @@ 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 predicate_rule_t predicate_rule, const Param* diff_param)  		{ +			bool serialized = false;  			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(HAS_DEFAULT_VALUE); +			} + +			predicate.set(VALID, typed_param.isValid()); +			predicate.set(PROVIDED, typed_param.anyProvided()); +			predicate.set(EMPTY, false); + +			if (!predicate_rule.check(predicate)) return false;  			if (!name_stack.empty())  			{ @@ -1030,25 +1085,27 @@ 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); +					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())) +			else if (!diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_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 (calculated_key.size()  -						&& (!diff_param  +						&& (!diff_typed_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) @@ -1113,19 +1170,19 @@ namespace LLInitParam  	};  	// parameter that is a block -	template <typename T, typename NAME_VALUE_LOOKUP> -	class TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK>  +	template <typename BLOCK_T, typename NAME_VALUE_LOOKUP> +	class TypedParam<BLOCK_T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK>   	:	public Param,  		public NAME_VALUE_LOOKUP::type_value_t  	{  	protected: -		typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t>	param_value_t; -		typedef typename param_value_t::default_value_t				default_value_t; -		typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK>	self_t; -		typedef typename NAME_VALUE_LOOKUP::type_value_t			named_value_t; +		typedef ParamValue<typename LLTypeTags::Sorted<BLOCK_T>::value_t>	param_value_t; +		typedef typename param_value_t::default_value_t						default_value_t; +		typedef TypedParam<BLOCK_T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK>	self_t; +		typedef typename NAME_VALUE_LOOKUP::type_value_t					named_value_t;  	public:  		using named_value_t::operator(); -		typedef typename param_value_t::value_t						value_t; +		typedef typename param_value_t::value_t								value_t;  		TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  		:	Param(block_descriptor.mCurrentBlockPtr), @@ -1148,11 +1205,11 @@ namespace LLInitParam  				if(named_value_t::valueNamesExist()  					&& parser.readValue(name)				  					&& named_value_t::getValueFromName(name, typed_param.getValue())) -				{ -					typed_param.setValueName(name); -					typed_param.setProvided(); -					return true; -				} +			{ +				typed_param.setValueName(name); +				typed_param.setProvided(); +				return true; +			}  			}  			if(typed_param.deserializeBlock(parser, name_stack_range, new_name)) @@ -1166,10 +1223,16 @@ 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 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; + +			LLPredicate::Value<ESerializePredicates> predicate; + +			predicate.set(VALID, typed_param.isValid()); +			predicate.set(PROVIDED, typed_param.anyProvided()); + +			if (!predicate_rule.check(predicate)) return false;  			if (!name_stack.empty())  			{ @@ -1182,12 +1245,15 @@ namespace LLInitParam  				if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))  				{  					parser.writeValue(key, name_stack); +					return true;  				}  			}  			else  			{ -				typed_param.serializeBlock(parser, name_stack, static_cast<const self_t*>(diff_param)); +				return typed_param.serializeBlock(parser, name_stack, predicate_rule, 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) @@ -1209,13 +1275,12 @@ 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(); +		} + +		bool isValid() const +		{ +			return param_value_t::isValid();  		}  		// assign block contents to this param-that-is-a-block @@ -1223,9 +1288,6 @@ namespace LLInitParam  		{  			setValue(val);  			named_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);  		} @@ -1242,9 +1304,6 @@ namespace LLInitParam  			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();  				named_value_t::clearValueName();  			} @@ -1296,13 +1355,13 @@ namespace LLInitParam  	};  	// list of non-block parameters -	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> -	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK>  +	template <typename MULTI_VALUE_T, typename NAME_VALUE_LOOKUP> +	class TypedParam<MULTI_VALUE_T, NAME_VALUE_LOOKUP, true, NOT_BLOCK>   	:	public Param  	{  	protected: -		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK>		self_t; -		typedef ParamValue<typename LLTypeTags::Sorted<VALUE_TYPE>::value_t>	param_value_t; +		typedef TypedParam<MULTI_VALUE_T, NAME_VALUE_LOOKUP, true, NOT_BLOCK>		self_t; +		typedef ParamValue<typename LLTypeTags::Sorted<MULTI_VALUE_T>::value_t>	param_value_t;  		typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t>	container_t;  		typedef container_t														default_value_t;  		typedef typename NAME_VALUE_LOOKUP::type_value_t						named_value_t; @@ -1311,7 +1370,9 @@ namespace LLInitParam  		typedef typename param_value_t::value_t								value_t;  		TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_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)); @@ -1322,7 +1383,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, Parser::name_stack_range_t& name_stack_range, bool new_name)  		{  @@ -1337,7 +1404,7 @@ namespace LLInitParam  			}  			// 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)  			{	  				std::string name; @@ -1359,10 +1426,19 @@ 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 predicate_rule_t predicate_rule, const Param* diff_param)  		{ +			bool serialized = false;  			const self_t& typed_param = static_cast<const self_t&>(param); -			if (!typed_param.isProvided()) return; + +			LLPredicate::Value<ESerializePredicates> predicate; + +			predicate.set(REQUIRED, typed_param.mMinCount > 0); +			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;  			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();  				it != end_it; @@ -1378,7 +1454,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;  						} @@ -1386,19 +1466,23 @@ namespace LLInitParam  				}  				else   				{ -					if(!parser.writeValue(key, name_stack)) +					if(parser.writeValue(key, name_stack)) +					{ +						serialized = true; +					} +					else  					{  						break;  					}  				} - -				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)  		{ -			parser.inspectValue<VALUE_TYPE>(name_stack, min_count, max_count, NULL); +			parser.inspectValue<MULTI_VALUE_T>(name_stack, min_count, max_count, NULL);  			if (named_value_t::getPossibleValues())  			{  				parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues()); @@ -1453,7 +1537,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();  		} @@ -1483,6 +1567,8 @@ namespace LLInitParam  		}  		container_t		mValues; +		size_t			mMinCount, +						mMaxCount;  	private:  		void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )  @@ -1500,13 +1586,13 @@ namespace LLInitParam  	};  	// list of block parameters -	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> -	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK>  +	template <typename MULTI_BLOCK_T, typename NAME_VALUE_LOOKUP> +	class TypedParam<MULTI_BLOCK_T, NAME_VALUE_LOOKUP, true, IS_A_BLOCK>   	:	public Param  	{  	protected: -		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK>		self_t; -		typedef ParamValue<typename LLTypeTags::Sorted<VALUE_TYPE>::value_t>	param_value_t; +		typedef TypedParam<MULTI_BLOCK_T, NAME_VALUE_LOOKUP, true, IS_A_BLOCK>		self_t; +		typedef ParamValue<typename LLTypeTags::Sorted<MULTI_BLOCK_T>::value_t>	param_value_t;  		typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t>	container_t;  		typedef typename NAME_VALUE_LOOKUP::type_value_t						named_value_t;  		typedef container_t														default_value_t; @@ -1516,7 +1602,9 @@ namespace LLInitParam  		typedef typename param_value_t::value_t							value_t;  		TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_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)); @@ -1526,7 +1614,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, Parser::name_stack_range_t& name_stack_range, bool new_name)   		{  @@ -1549,7 +1644,7 @@ namespace LLInitParam  			}  			param_value_t& value = typed_param.mValues.back(); -			if (name_stack_range.first == name_stack_range.second) +			if (new_name_stack_range.first == new_name_stack_range.second)  			{	// try to parse a known named value  				std::string name; @@ -1559,6 +1654,10 @@ namespace LLInitParam  				{  					typed_param.mValues.back().setValueName(name);  					typed_param.setProvided(); +					if (new_array_value) +					{ +						name_stack_range.first->second = false; +					}  					return true;  				}  			} @@ -1583,10 +1682,18 @@ 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 predicate_rule_t predicate_rule, const Param* diff_param)  		{ +			bool serialized = false;  			const self_t& typed_param = static_cast<const self_t&>(param); -			if (!typed_param.isProvided()) return; +			LLPredicate::Value<ESerializePredicates> predicate; + +			predicate.set(REQUIRED, typed_param.mMinCount > 0); +			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;  			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();  				it != end_it; @@ -1597,17 +1704,24 @@ 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 +				// NOTE: currently we don't do diffing of Multiples  				else   				{ -					it->serializeBlock(parser, name_stack, NULL); +					serialized = it->serializeBlock(parser, name_stack, predicate_rule, NULL);  				}  				name_stack.pop_back();  			} + +			if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY))) +			{ +				serialized |= parser.writeValue(Flag(), name_stack); +			} + +			return serialized;  		}  		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) @@ -1670,14 +1784,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;  		} @@ -1709,6 +1823,8 @@ namespace LLInitParam  		}  		container_t			mValues; +		size_t				mMinCount, +							mMaxCount;  	private:  		void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )  @@ -2015,7 +2131,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;  			}  		}; @@ -2158,13 +2274,11 @@ namespace LLInitParam  		typedef T									default_value_t;  		ParamValue() -		:	mValue(), -			mValidated(false) +		:	mValue()  		{}  		ParamValue(const default_value_t& value) -		:	mValue(value), -			mValidated(false) +		:	mValue(value)  		{}  		void setValue(const value_t& val) @@ -2191,18 +2305,18 @@ namespace LLInitParam  			return mValue.deserializeBlock(p, name_stack_range, new_name);  		} -		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const +		bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const self_t* diff_block = NULL) const  		{  			const BaseBlock* base_block = diff_block  				? &(diff_block->mValue)  				: NULL; -			mValue.serializeBlock(p, name_stack, base_block); +			return mValue.serializeBlock(p, name_stack, predicate_rule, base_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 -			{ +		{  			return mValue.inspectBlock(p, name_stack, min_count, max_count); -			} +		}  		bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)  		{ @@ -2212,9 +2326,7 @@ namespace LLInitParam  				// clear away what is there and take the new stuff as a whole  				resetToDefault();  				return mValue.mergeBlock(block_data, source.getValue(), overwrite); -		} -			 - +			}  			return mValue.mergeBlock(block_data, source.getValue(), overwrite);  		} @@ -2223,14 +2335,17 @@ namespace LLInitParam  			return mValue.validateBlock(emit_errors);  		} +		bool isValid() const +		{ +			return validateBlock(false); +		} +  		static BlockDescriptor& getBlockDescriptor()  		{  			return value_t::getBlockDescriptor();  		} -		mutable bool 	mValidated; // lazy validation flag -  	private:  		void resetToDefault()  		{ @@ -2251,15 +2366,13 @@ namespace LLInitParam  		typedef T									default_value_t;  		ParamValue() -		:	mValue(), -			mValidated(false) +		:	mValue()  		{  			mCurParam = getBlockDescriptor().mAllParams.begin();  		}  		ParamValue(const default_value_t& value) -		:	mValue(value), -			mValidated(false) +		:	mValue(value)  		{  			mCurParam = getBlockDescriptor().mAllParams.begin();  		} @@ -2284,7 +2397,7 @@ namespace LLInitParam  			if (new_name)  			{  				mCurParam = getBlockDescriptor().mAllParams.begin(); -		} +			}  			if (name_stack_range.first == name_stack_range.second   				&& mCurParam != getBlockDescriptor().mAllParams.end())  			{ @@ -2296,7 +2409,7 @@ namespace LLInitParam  				if (deserialize_func   					&& paramp   					&& deserialize_func(*paramp, p, name_stack_range, new_name)) -		{ +				{  					++mCurParam;  					return true;  				} @@ -2304,19 +2417,19 @@ namespace LLInitParam  				{  					return false;  				} -		} +			}  			else  			{  				return mValue.deserializeBlock(p, name_stack_range, new_name);  			}  		} -		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const +		bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const self_t* diff_block = NULL) const  		{  			const BaseBlock* base_block = diff_block  				? &(diff_block->mValue)  				: NULL; -			mValue.serializeBlock(p, name_stack, base_block); +			return mValue.serializeBlock(p, name_stack, predicate_rule, base_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 @@ -2334,13 +2447,16 @@ namespace LLInitParam  			return mValue.validateBlock(emit_errors);  		} +		bool isValid() const +		{ +			return validateBlock(false); +		} +  		static BlockDescriptor& getBlockDescriptor()  		{  			return value_t::getBlockDescriptor();  		} -		mutable bool 	mValidated; // lazy validation flag -  	private:  		BlockDescriptor::all_params_list_t::iterator	mCurParam; @@ -2358,16 +2474,14 @@ namespace LLInitParam  		typedef T									default_value_t;  		ParamValue() -		:	T(), -			mValidated(false) +		:	T()  		{}  		ParamValue(const default_value_t& value) -		:	T(value.getValue()), -			mValidated(false) +		:	T(value.getValue())  		{} -		mutable bool 	mValidated; // lazy validation flag +		bool isValid() const { return true; }  	};  	template<typename T, typename BLOCK_T> @@ -2380,18 +2494,15 @@ namespace LLInitParam  		typedef LazyValue<T>						default_value_t;  		ParamValue() -		:	mValue(), -			mValidated(false) +		:	mValue()  		{}  		ParamValue(const default_value_t& other) -		:	mValue(other), -			mValidated(false) +		:	mValue(other)  		{}  		ParamValue(const T& value) -		:	mValue(value), -			mValidated(false) +		:	mValue(value)  		{}  		void setValue(const value_t& val) @@ -2414,14 +2525,14 @@ namespace LLInitParam  			return mValue.get().deserializeBlock(p, name_stack_range, new_name);  		} -		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const +		bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const self_t* diff_block = NULL) const  		{ -			if (mValue.empty()) return; +			if (mValue.empty()) return false;  			const BaseBlock* base_block = (diff_block && !diff_block->mValue.empty())  											? &(diff_block->mValue.get().getValue())  											: NULL; -			mValue.get().serializeBlock(p, name_stack, base_block); +			return mValue.get().serializeBlock(p, name_stack, predicate_rule, base_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 @@ -2433,26 +2544,29 @@ namespace LLInitParam  		{  			return source.mValue.empty() || mValue.get().mergeBlock(block_data, source.getValue(), overwrite);  		} -			 +  		bool validateBlock(bool emit_errors = true) const  		{  			return mValue.empty() || mValue.get().validateBlock(emit_errors);  		} +		bool isValid() const +		{ +			return validateBlock(false); +		} +  		static BlockDescriptor& getBlockDescriptor()  		{  			return value_t::getBlockDescriptor();  		} -		mutable bool 	mValidated; // lazy validation flag -  	private:  		LazyValue<T>	mValue;  	};  	template<typename T, typename BLOCK_T>  	class ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> -		{ +	{  		typedef ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> self_t;  	public: @@ -2460,18 +2574,15 @@ namespace LLInitParam  		typedef LazyValue<T>						default_value_t;  		ParamValue() -		:	mValue(), -			mValidated(false) +		:	mValue()  		{}  		ParamValue(const default_value_t& other) -		:	mValue(other), -			mValidated(false) +		:	mValue(other)  		{}  		ParamValue(const T& value) -		:	mValue(value), -			mValidated(false) +		:	mValue(value)  		{}  		void setValue(const value_t& val) @@ -2489,7 +2600,10 @@ namespace LLInitParam  			return mValue.get().getValue();  		} -		mutable bool 	mValidated; // lazy validation flag +		bool isValid() const +		{ +			return true; +		}  	private:  		LazyValue<T>	mValue; @@ -2504,12 +2618,10 @@ namespace LLInitParam  		typedef LLSD			default_value_t;  		ParamValue() -		:	mValidated(false)  		{}  		ParamValue(const default_value_t& other) -		:	mValue(other), -			mValidated(false) +		:	mValue(other)  		{}  		void setValue(const value_t& val) { mValue = val; } @@ -2519,16 +2631,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 bool 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); @@ -2547,18 +2656,17 @@ namespace LLInitParam  			BLOCK_AUTHORITATIVE		// mValue is derived from the block parameters, which are authoritative  		} EValueAge; -		typedef ParamValue<T>			derived_t; -		typedef CustomParamValue<T>				self_t; -		typedef Block<derived_t>				block_t; +		typedef TypeValues<T>			derived_t; +		typedef CustomParamValue<T>		self_t; +		typedef Block<ParamValue<T> >	block_t;  		typedef T						default_value_t; -		typedef T								value_t; +		typedef T						value_t;  		typedef void					baseblock_base_class_t;  		CustomParamValue(const default_value_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) @@ -2580,16 +2688,30 @@ 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 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); +			//std::string key = typed_param.getValueName(); + +			//// first try to write out name of name/value pair +			//if (!key.empty()) +			//{ +			//	if (!diff_param || !ParamCompare<std::string>::equals(diff_param->getValueName(), key)) +			//	{ +			//		return parser.writeValue(key, name_stack); +			//	} +			//}  			// then try to serialize value directly  			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 @@ -2606,14 +2728,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, predicate_rule, NULL);  					}  					else  					{ -						block_t::serializeBlock(parser, name_stack, NULL); +						return block_t::serializeBlock(parser, name_stack, predicate_rule, NULL);  					}  				}  			} +			return false;  		}  		bool validateBlock(bool emit_errors = true) const @@ -2705,8 +2828,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/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp index 64a313b5ff..11fc53f8c8 100755 --- a/indra/llcommon/llinstancetracker.cpp +++ b/indra/llcommon/llinstancetracker.cpp @@ -27,8 +27,26 @@  #include "linden_common.h"  // associated header  #include "llinstancetracker.h" +#include "llapr.h" +  // STL headers  // std headers  // external library headers  // other Linden headers +void LLInstanceTrackerBase::StaticBase::incrementDepth() +{ +	apr_atomic_inc32(&sIterationNestDepth); +} + +void LLInstanceTrackerBase::StaticBase::decrementDepth() +{ +	llassert(sIterationNestDepth); +	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 55187d8325..9783644e66 100755 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -31,10 +31,7 @@  #include <map>  #include <typeinfo> -#include "string_table.h" -#include <boost/utility.hpp> -#include <boost/function.hpp> -#include <boost/bind.hpp> +#include "llstringtable.h"  #include <boost/iterator/transform_iterator.hpp>  #include <boost/iterator/indirect_iterator.hpp> @@ -46,8 +43,6 @@  class LL_COMMON_API LLInstanceTrackerBase  {  protected: - -      /// It's not essential to derive your STATICDATA (for use with      /// getStatic()) from StaticBase; it's just that both known      /// implementations do. @@ -56,31 +51,39 @@ protected:          StaticBase():              sIterationNestDepth(0)          {} -        S32 sIterationNestDepth; + +		void incrementDepth(); +		void decrementDepth(); +		U32 getDepth(); +	private: +		U32 sIterationNestDepth;      };  };  LL_COMMON_API void assert_main_thread(); +enum EInstanceTrackerAllowKeyCollisions +{ +	LLInstanceTrackerErrorOnCollision, +	LLInstanceTrackerReplaceOnCollision +}; +  /// 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 +/// @NOTE: this class is not thread-safe unless used as read-only +template<typename T, typename KEY = void, EInstanceTrackerAllowKeyCollisions KEY_COLLISION_BEHAVIOR = LLInstanceTrackerErrorOnCollision>  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;  	};  	static StaticData& getStatic() { static StaticData sData; return sData;} -	static InstanceMap& getMap_()  -	{ -		// assert_main_thread();   fwiw this class is not thread safe, and it used by multiple threads.  Bad things happen. -		return getStatic().sMap;  -	} +	static InstanceMap& getMap_() { return getStatic().sMap; }  public:  	class instance_iter : public boost::iterator_facade<instance_iter, T, boost::forward_traversal_tag> @@ -91,12 +94,12 @@ public:  		instance_iter(const typename InstanceMap::iterator& it)  		:	mIterator(it)  		{ -			++getStatic().sIterationNestDepth; +			getStatic().incrementDepth();  		}  		~instance_iter()  		{ -			--getStatic().sIterationNestDepth; +			getStatic().decrementDepth();  		} @@ -123,20 +126,20 @@ 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().sIterationNestDepth; +			getStatic().incrementDepth();  		}  		key_iter(const key_iter& other) -			:	mIterator(other.mIterator) +		:	mIterator(other.mIterator)  		{ -			++getStatic().sIterationNestDepth; +			getStatic().incrementDepth();  		}  		~key_iter()  		{ -			--getStatic().sIterationNestDepth; +			getStatic().decrementDepth();  		} @@ -174,7 +177,10 @@ public:  		return instance_iter(getMap_().end());  	} -	static S32 instanceCount() { return getMap_().size(); } +	static S32 instanceCount()  +	{  +		return getMap_().size();  +	}  	static key_iter beginKeys()  	{ @@ -186,7 +192,7 @@ public:  	}  protected: -	LLInstanceTracker(KEY key)  +	LLInstanceTracker(const KEY& key)   	{   		// make sure static data outlives all instances  		getStatic(); @@ -195,7 +201,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); } @@ -205,17 +211,44 @@ private:  	LLInstanceTracker( const LLInstanceTracker& );  	const LLInstanceTracker& operator=( const LLInstanceTracker& ); -	void add_(KEY key)  +	void add_(const KEY& key)   	{   		mInstanceKey = key;  -		getMap_()[key] = static_cast<T*>(this);  +		InstanceMap& map = getMap_(); +		typename InstanceMap::iterator insertion_point_it = map.lower_bound(key); +		if (insertion_point_it != map.end()  +			&& insertion_point_it->first == key) +		{ // 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, "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);  		}  	} @@ -223,12 +256,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 +template<typename T, EInstanceTrackerAllowKeyCollisions KEY_COLLISION_BEHAVIOR> +class LLInstanceTracker<T, void, KEY_COLLISION_BEHAVIOR> : public LLInstanceTrackerBase  { -	typedef LLInstanceTracker<T, T*> self_t; +	typedef LLInstanceTracker<T, void> self_t;  	typedef typename std::set<T*> InstanceSet;  	struct StaticData: public StaticBase  	{ @@ -261,18 +294,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: @@ -305,7 +338,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/lllazy.cpp b/indra/llcommon/lllazy.cpp deleted file mode 100755 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 100755 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/llleap.cpp b/indra/llcommon/llleap.cpp index 0a57ef1c48..84d2a12f65 100755 --- 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/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/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/lllocalidhashmap.h b/indra/llcommon/lllocalidhashmap.h deleted file mode 100755 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/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 926ce32d75..0000000000 --- a/indra/llcommon/lllslconstants.h +++ /dev/null @@ -1,242 +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_TEXT			= 26; -const S32 LSL_PRIM_NAME			= 27; -const S32 LSL_PRIM_DESC			= 28; -const S32 LSL_PRIM_ROT_LOCAL	= 29; -const S32 LSL_PRIM_PHYSICS_SHAPE_TYPE	= 30; -const S32 LSL_PRIM_OMEGA		= 32; -const S32 LSL_PRIM_POS_LOCAL	= 33; -const S32 LSL_PRIM_LINK_TARGET	= 34; -const S32 LSL_PRIM_SLICE		= 35; - -const S32 LSL_PRIM_PHYSICS_SHAPE_PRIM	= 0; -const S32 LSL_PRIM_PHYSICS_SHAPE_NONE	= 1; -const S32 LSL_PRIM_PHYSICS_SHAPE_CONVEX	= 2; - -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; -const S32 OBJECT_RUNNING_SCRIPT_COUNT = 9; -const S32 OBJECT_TOTAL_SCRIPT_COUNT = 10; -const S32 OBJECT_SCRIPT_MEMORY = 11; -const S32 OBJECT_SCRIPT_TIME = 12; -const S32 OBJECT_PRIM_EQUIVALENCE = 13; -const S32 OBJECT_SERVER_COST = 14; -const S32 OBJECT_STREAMING_COST = 15; -const S32 OBJECT_PHYSICS_COST = 16; -const S32 OBJECT_CHARACTER_TIME = 17; -const S32 OBJECT_ROOT = 18; -const S32 OBJECT_ATTACHED_POINT = 19; -const S32 OBJECT_PATHFINDING_TYPE = 20; -const S32 OBJECT_PHYSICS = 21; -const S32 OBJECT_PHANTOM = 22; -const S32 OBJECT_TEMP_ON_REZ = 23; -const S32 OBJECT_RENDER_WEIGHT = 24; - -// 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/llmd5.cpp b/indra/llcommon/llmd5.cpp index 1409c55d1c..ed80af36d8 100755 --- 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/llmemory.cpp b/indra/llcommon/llmemory.cpp index 70ad10ad55..e0b2aa87c2 100755 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -27,12 +27,9 @@  #include "linden_common.h" -//#if MEM_TRACK_MEM  #include "llthread.h" -//#endif  #if defined(LL_WINDOWS) -//# include <windows.h>  # include <psapi.h>  #elif defined(LL_DARWIN)  # include <sys/types.h> @@ -46,15 +43,18 @@  #include "llsys.h"  #include "llframetimer.h" +#include "lltrace.h"  //----------------------------------------------------------------------------  //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 ; +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);  BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE;  #if __DEBUG_PRIVATE_MEM__ @@ -67,7 +67,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 @@ -97,9 +97,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 ;  } @@ -112,14 +112,16 @@ void LLMemory::updateMemoryInfo()  	if (!GetProcessMemoryInfo(self, &counters, sizeof(counters)))  	{ -		llwarns << "GetProcessMemoryInfo failed" << llendl; +		LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;  		return ;  	} -	sAllocatedMemInKB = (U32)(counters.WorkingSetSize / 1024) ; -	sAllocatedPageSizeInKB = (U32)(counters.PagefileUsage / 1024) ; +	sAllocatedMemInKB = (U32Bytes)(counters.WorkingSetSize) ; +	sample(sAllocatedMem, sAllocatedMemInKB); +	sAllocatedPageSizeInKB = (U32Bytes)(counters.PagefileUsage) ; +	sample(sVirtualMem, sAllocatedPageSizeInKB); -	U32 avail_phys, avail_virtual; +	U32Kilobytes avail_phys, avail_virtual;  	LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;  	sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB); @@ -129,13 +131,13 @@ void LLMemory::updateMemoryInfo()  	}  	else  	{ -		sAvailPhysicalMemInKB = 0 ; +		sAvailPhysicalMemInKB = U32Kilobytes(0);  	}  #else  	//not valid for other systems for now. -	sAllocatedMemInKB = (U32)(LLMemory::getCurrentRSS() / 1024) ; -	sMaxPhysicalMemInKB = U32_MAX ; -	sAvailPhysicalMemInKB = U32_MAX ; +	sAllocatedMemInKB = (U32Bytes)LLMemory::getCurrentRSS(); +	sMaxPhysicalMemInKB = (U32Bytes)U32_MAX ; +	sAvailPhysicalMemInKB = (U32Bytes)U32_MAX ;  #endif  	return ; @@ -156,7 +158,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 ; @@ -174,14 +176,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; @@ -190,8 +192,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) @@ -199,32 +201,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()) ;  			}  		} @@ -235,19 +237,19 @@ bool LLMemory::isMemoryPoolLow()  }  //static  -U32 LLMemory::getAvailableMemKB()  +U32Kilobytes LLMemory::getAvailableMemKB()   {  	return sAvailPhysicalMemInKB ;  }  //static  -U32 LLMemory::getMaxMemKB()  +U32Kilobytes LLMemory::getMaxMemKB()   {  	return sMaxPhysicalMemInKB ;  }  //static  -U32 LLMemory::getAllocatedMemKB()  +U32Kilobytes LLMemory::getAllocatedMemKB()   {  	return sAllocatedMemInKB ;  } @@ -263,7 +265,7 @@ U64 LLMemory::getCurrentRSS()  	if (!GetProcessMemoryInfo(self, &counters, sizeof(counters)))  	{ -		llwarns << "GetProcessMemoryInfo failed" << llendl; +		LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;  		return 0;  	} @@ -301,7 +303,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; @@ -320,11 +322,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; @@ -345,7 +347,7 @@ U64 LLMemory::getCurrentRSS()  	if (fp == NULL)  	{ -		llwarns << "couldn't open " << statPath << llendl; +		LL_WARNS() << "couldn't open " << statPath << LL_ENDL;  		goto bail;  	} @@ -358,7 +360,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;  		}  	} @@ -388,12 +390,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;  	} @@ -423,141 +425,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  const U32 ATOMIC_MEM_SLOT = 16 ; //bytes @@ -961,7 +828,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 ;  		}  	} @@ -982,32 +849,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 ;  		}  	} @@ -1403,7 +1270,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 ;  		} @@ -1496,7 +1363,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 ; @@ -1514,11 +1381,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 ;  	} @@ -1731,7 +1598,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) ; @@ -1811,7 +1678,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 ;  	}  } @@ -1843,12 +1710,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() ;  	} @@ -2044,7 +1911,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 ;  		}  	}	  } @@ -2118,7 +1985,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 @@ -2190,8 +2057,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] ; @@ -2203,7 +2070,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 @@ -2212,7 +2079,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() ; @@ -2223,7 +2090,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 @@ -2232,7 +2099,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/llmemory.h b/indra/llcommon/llmemory.h index 61e30f11cc..db52f2b1f4 100755 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -27,15 +27,35 @@  #define LLMEMORY_H  #include "linden_common.h" +#include "llunits.h" +#if !LL_WINDOWS +#include <stdint.h> +#endif  class LLMutex ;  #if LL_WINDOWS && LL_DEBUG  #define LL_CHECK_MEMORY llassert(_CrtCheckMemory());  #else -#define LL_CHECK_MEMORY +#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 +  LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment);  #ifdef SHOW_ASSERT @@ -74,7 +94,8 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)  #define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16) -inline void* ll_aligned_malloc( size_t size, int align ) + +inline void* ll_aligned_malloc_fallback( size_t size, int align )  {  #if defined(LL_WINDOWS)  	return _aligned_malloc(size, align); @@ -88,7 +109,7 @@ inline void* ll_aligned_malloc( size_t size, int align )  #endif  } -inline void ll_aligned_free( void* ptr ) +inline void ll_aligned_free_fallback( void* ptr )  {  #if defined(LL_WINDOWS)  	_aligned_free(ptr); @@ -161,7 +182,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))) @@ -176,12 +197,54 @@ 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  } +// general purpose dispatch functions that are forced inline so they can compile down to a single call +template<size_t ALIGNMENT> +LL_FORCE_INLINE void* ll_aligned_malloc(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); +	} +} + +template<size_t ALIGNMENT> +LL_FORCE_INLINE void ll_aligned_free(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); +	} +}  // Copy words 16-byte blocks from src to dst. Source and destination MUST NOT OVERLAP.   // Source and dest must be 16-byte aligned and size must be multiple of 16. @@ -269,70 +332,25 @@ 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 U32 getAvailableMemKB() ; -	static U32 getMaxMemKB() ; -	static U32 getAllocatedMemKB() ; +	static U32Kilobytes getAvailableMemKB() ; +	static U32Kilobytes getMaxMemKB() ; +	static U32Kilobytes getAllocatedMemKB() ;  private:  	static char* reserveMem; -	static U32 sAvailPhysicalMemInKB ; -	static U32 sMaxPhysicalMemInKB ; -	static U32 sAllocatedMemInKB; -	static U32 sAllocatedPageSizeInKB ; +	static U32Kilobytes sAvailPhysicalMemInKB ; +	static U32Kilobytes sMaxPhysicalMemInKB ; +	static U32Kilobytes sAllocatedMemInKB; +	static U32Kilobytes sAllocatedPageSizeInKB ; -	static U32 sMaxHeapSizeInKB; +	static U32Kilobytes sMaxHeapSizeInKB;  	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/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 731e58bd20..1fc821d9a9 100755 --- a/indra/llcommon/llmetricperformancetester.cpp +++ b/indra/llcommon/llmetricperformancetester.cpp @@ -29,9 +29,9 @@  #include "indra_constants.h"  #include "llerror.h"  #include "llsdserialize.h" -#include "llstat.h"  #include "lltreeiterators.h"  #include "llmetricperformancetester.h" +#include "llfasttimer.h"  //----------------------------------------------------------------------------------------------  // LLMetricPerformanceTesterBasic : static methods and testers management @@ -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;  	} @@ -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 (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*/  @@ -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) ; @@ -194,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()  @@ -242,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 ;  				}  			}	  		} @@ -306,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/llmortician.h b/indra/llcommon/llmortician.h index 319955ef93..9517e2db5e 100755 --- 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/llmutex.cpp b/indra/llcommon/llmutex.cpp new file mode 100644 index 0000000000..9c13ef9e30 --- /dev/null +++ b/indra/llcommon/llmutex.cpp @@ -0,0 +1,205 @@ +/**  + * @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 +	if (ll_apr_is_initialized()) +	{ +		apr_thread_mutex_destroy(mAPRMutexp); +		if (mIsLocalPool) +		{ +			apr_pool_destroy(mAPRPoolp); +		} +	} +	mAPRMutexp = NULL; +} + + +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) +		LL_ERRS() << "Already locked in Thread: " << id << LL_ENDL; +	mIsLocked[id] = TRUE; +#endif + +	mLockingThread = LLThread::currentID(); +} + +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) +		LL_ERRS() << "Not locked in Thread: " << id << LL_ENDL;	 +	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() +{ +	return mLockingThread == LLThread::currentID(); +} + +U32 LLMutex::lockingThread() const +{ +	return mLockingThread; +} + +bool LLMutex::trylock() +{ +	if(isSelfLocked()) +	{ //redundant lock +		mCount++; +		return true; +	} +	 +	apr_status_t status(apr_thread_mutex_trylock(mAPRMutexp)); +	if (APR_STATUS_IS_EBUSY(status)) +	{ +		return false; +	} +	 +#if MUTEX_DEBUG +	// Have to have the lock before we can access the debug info +	U32 id = LLThread::currentID(); +	if (mIsLocked[id] != FALSE) +		LL_ERRS() << "Already locked in Thread: " << id << LL_ENDL; +	mIsLocked[id] = TRUE; +#endif + +	mLockingThread = LLThread::currentID(); +	return true; +} + +//============================================================================ + +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); +} + + +//============================================================================ diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h new file mode 100644 index 0000000000..3659a319a2 --- /dev/null +++ b/indra/llcommon/llmutex.h @@ -0,0 +1,141 @@ +/**  + * @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 "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: +	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 +	bool trylock();		// non-blocking, returns true if lock held. +	void unlock();		// undefined behavior when called on mutex not being held +	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; +}; + +//============================================================================ + +// Scoped locking class similar in function to LLMutexLock but uses +// the trylock() method to conditionally acquire lock without +// blocking.  Caller resolves the resulting condition by calling +// the isLocked() method and either punts or continues as indicated. +// +// Mostly of interest to callers needing to avoid stalls who can +// guarantee another attempt at a later time. + +class LLMutexTrylock +{ +public: +	LLMutexTrylock(LLMutex* mutex) +		: mMutex(mutex), +		  mLocked(false) +	{ +		if (mMutex) +			mLocked = mMutex->trylock(); +	} + +	~LLMutexTrylock() +	{ +		if (mMutex && mLocked) +			mMutex->unlock(); +	} + +	bool isLocked() const +	{ +		return mLocked; +	} +	 +private: +	LLMutex*	mMutex; +	bool		mLocked; +}; +#endif // LL_LLTHREAD_H 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/llpointer.h b/indra/llcommon/llpointer.h index 88c09c8dca..c9ebc70d19 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 @@ -97,24 +98,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 +112,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 +129,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,12 +151,12 @@ 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; +				LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;  				unref();  			}  		} @@ -171,4 +166,52 @@ protected:  	Type*	mPointer;  }; +template<typename Type> +class LLCopyOnWritePointer : public LLPointer<Type> +{ +public: +	typedef LLCopyOnWritePointer<Type> self_t; +    typedef LLPointer<Type> pointer_t; +     +	LLCopyOnWritePointer()  +	:	mStayUnique(false) +	{} + +	LLCopyOnWritePointer(Type* ptr)  +	:	LLPointer<Type>(ptr), +		mStayUnique(false) +	{} + +	LLCopyOnWritePointer(LLPointer<Type>& ptr) +	:	LLPointer<Type>(ptr), +		mStayUnique(false) +	{ +		if (ptr.mForceUnique) +		{ +			makeUnique(); +		} +	} + +	Type* write() +	{ +		makeUnique(); +		return pointer_t::mPointer; +	} + +	void makeUnique() +	{ +		if (pointer_t::notNull() && pointer_t::mPointer->getNumRefs() > 1) +		{ +			*(pointer_t* )(this) = new Type(*pointer_t::mPointer); +		} +	} + +	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/lloptioninterface.h b/indra/llcommon/llpredicate.cpp index 93b465db32..1278948e24 100755..100644 --- a/indra/llcommon/lloptioninterface.h +++ b/indra/llcommon/llpredicate.cpp @@ -1,8 +1,8 @@  /**  - * @file lloptioninterface.h - * @brief  + * @file llpredicate.cpp + * @brief abstraction for filtering objects by predicates, with arbitrary boolean expressions   * - * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * $LicenseInfo:firstyear=2008&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc.   *  @@ -23,18 +23,19 @@   * 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 +#include "llpredicate.h" + +namespace LLPredicate  { -public: -    virtual ~LLOptionInterface() = 0; -	virtual LLSD getOption(const std::string& name) const = 0; -}; +	const U32 cPredicateFlagsFromEnum[5] =  +	{ +		0xAAAAaaaa, // 10101010101010101010101010101010 +		0xCCCCcccc, // 11001100110011001100110011001100 +		0xF0F0F0F0, // 11110000111100001111000011110000 +		0xFF00FF00, // 11111111000000001111111100000000 +		0xFFFF0000  // 11111111111111110000000000000000  +	}; +} -#endif diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h new file mode 100644 index 0000000000..a0e970a799 --- /dev/null +++ b/indra/llcommon/llpredicate.h @@ -0,0 +1,210 @@ +/**  + * @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; + +	extern const U32 cPredicateFlagsFromEnum[5]; + +	template<typename ENUM> +	class Value +	{ +	public: +		typedef U32 predicate_flag_t; +		static const S32 cMaxEnum = 5; + +		Value(ENUM e, bool predicate_value = true) +		:	mPredicateFlags(predicate_value ? cPredicateFlagsFromEnum[e] : ~cPredicateFlagsFromEnum[e]) +		{ +			llassert(0 <= e && e < cMaxEnum); +		} + +		Value() +		:	mPredicateFlags(0xFFFFffff) +		{} + +		Value operator!() const +		{ +			Value new_value; +			new_value.mPredicateFlags = ~mPredicateFlags; +			return new_value; +		} + +		Value operator &&(const Value other) const +		{ +			Value new_value; +			new_value.mPredicateFlags = mPredicateFlags & other.mPredicateFlags; +			return new_value; +		} + +		Value operator ||(const Value other) const +		{ +			Value new_value; +			new_value.mPredicateFlags = mPredicateFlags | other.mPredicateFlags; +			return new_value; +		} + +		void set(ENUM e, bool value = true) +		{ +			llassert(0 <= e && e < cMaxEnum); +			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); +			} +		} + +		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; +		} + +		bool allSet() const +		{ +			return mPredicateFlags == ~0; +		} + +		bool noneSet() const +		{ +			return mPredicateFlags == 0; +		} + +		bool someSet() const +		{ +			return mPredicateFlags != 0; +		} + +	private: +		predicate_flag_t mPredicateFlags; +	}; + +	template<typename ENUM> +	class Rule +	{ +	public: +		Rule(ENUM value) +		:	mRule(value) +		{} + +		Rule(const Value<ENUM> other) +		:	mRule(other) +		{} + +		Rule() +		{} + +		void require(ENUM e) +		{ +			mRule.set(e, require); +		} + +		void allow(ENUM e) +		{ +			mRule.forget(e); +		} + +		bool check(const Value<ENUM> value) const +		{ +			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 acceptsAll() const +		{ +			return mRule.allSet(); +		} + +		bool acceptsNone() const +		{ +			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::Value<ENUM> ll_make_predicate(ENUM e, bool predicate_value = true) +{ +	 return LLPredicate::Value<ENUM>(e, predicate_value); +} + + +#endif // LL_LLPREDICATE_H diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index 7fdb537ab5..309165da7f 100755 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -181,4 +181,25 @@  # define LL_COMMON_API  #endif // LL_COMMON_LINK_SHARED +#if LL_WINDOWS +#define LL_TYPEOF(exp) decltype(exp) +#elif LL_LINUX +#define LL_TYPEOF(exp) typeof(exp) +#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(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(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) +#endif +  #endif	//	not LL_LINDEN_PREPROCESSOR_H 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/llprocess.h b/indra/llcommon/llprocess.h index d711ce2f74..43ccadc412 100755 --- a/indra/llcommon/llprocess.h +++ b/indra/llcommon/llprocess.h @@ -29,6 +29,7 @@  #include "llinitparam.h"  #include "llsdparam.h" +#include "llwin32headerslean.h"  #include "apr_thread_proc.h"  #include <boost/shared_ptr.hpp>  #include <boost/ptr_container/ptr_vector.hpp> @@ -38,8 +39,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 fd8f603d21..69043dc173 100755 --- 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> @@ -702,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 	 @@ -877,7 +875,7 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL)  LLProcessorInfo::~LLProcessorInfo() {} -F64 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 6364d3c8bb..90e5bc59ee 100755 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -27,6 +27,8 @@  #ifndef LLPROCESSOR_H  #define LLPROCESSOR_H +#include "llunits.h" +  class LLProcessorInfoImpl;  class LL_COMMON_API LLProcessorInfo @@ -35,7 +37,7 @@ public:  	LLProcessorInfo();    	~LLProcessorInfo(); -	F64 getCPUFrequency() const; +	F64MegahertzImplicit getCPUFrequency() const;  	bool hasSSE() const;  	bool hasSSE2() const;  	bool hasAltivec() const; diff --git a/indra/llcommon/llptrskiplist.h b/indra/llcommon/llptrskiplist.h deleted file mode 100755 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 100755 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/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/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index abf47a0f57..8cef4293cd 100755 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -28,6 +28,7 @@  #include "llstl.h"  #include "lltimer.h"	// ms_sleep() +#include "lltracethreadrecorder.h"  //============================================================================ @@ -80,7 +81,7 @@ void LLQueuedThread::shutdown()  		}  		if (timeout == 0)  		{ -			llwarns << "~LLQueuedThread (" << mName << ") timed out!" << llendl; +			LL_WARNS() << "~LLQueuedThread (" << mName << ") timed out!" << LL_ENDL;  		}  	}  	else @@ -101,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;  	}  } @@ -134,8 +135,8 @@ S32 LLQueuedThread::updateQueue(F32 max_time_ms)  		pending = getPending();  		if(pending > 0)  		{ -			unpause(); -		} +		unpause(); +	}  	}  	else  	{ @@ -198,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();  } @@ -233,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(); @@ -245,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; @@ -364,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(); @@ -385,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(); @@ -403,6 +404,7 @@ S32 LLQueuedThread::processNextRequest()  	QueuedRequest *req;  	// Get next request from pool  	lockData(); +	  	while(1)  	{  		req = NULL; @@ -467,10 +469,11 @@ S32 LLQueuedThread::processNextRequest()  				ms_sleep(1); // sleep the thread a little  			}  		} +		 +		LLTrace::get_thread_recorder()->pushToParent();  	}  	S32 pending = getPending(); -  	return pending;  } @@ -499,6 +502,7 @@ void LLQueuedThread::run()  		if (isQuitting())  		{ +			LLTrace::get_thread_recorder()->pushToParent();  			endThread();  			break;  		} @@ -507,15 +511,16 @@ void LLQueuedThread::run()  		threadedUpdate(); -		int res = processNextRequest(); -		if (res == 0) +		int pending_work = processNextRequest(); + +		if (pending_work == 0)  		{  			mIdleThread = TRUE;  			ms_sleep(1);  		}  		//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/llrefcount.h b/indra/llcommon/llrefcount.h index 32ae15435a..72011d04a0 100755 --- a/indra/llcommon/llrefcount.h +++ b/indra/llcommon/llrefcount.h @@ -28,6 +28,8 @@  #include <boost/noncopyable.hpp>  #include <boost/intrusive_ptr.hpp> +#include "llmutex.h" +#include "llapr.h"  #define LL_REF_COUNT_DEBUG 0  #if LL_REF_COUNT_DEBUG @@ -61,7 +63,7 @@ public:  	inline S32 unref() const  	{  		llassert(mRef >= 1); -		if (0 == --mRef)  +		if (0 == --mRef)  		{  			delete this;   			return 0; @@ -87,22 +89,91 @@ 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)  +	{ +		mRef = 0; +		return *this; +	} + +	void ref() +	{ +		mRef++;  +	}  + +	void unref() +	{ +		llassert(mRef >= 1); +		if ((--mRef) == 0)		// See note in llapr.h on atomic decrement operator return value.   +		{	 +			// If we hit zero, the caller should be the only smart pointer owning the object and we can delete it. +			// It is technically possible for a vanilla pointer to mess this up, or another thread to +			// jump in, find this object, create another smart pointer and end up dangling, but if +			// the code is that bad and not thread-safe, it's trouble already. +			delete this; +		} +	} + +	S32 getNumRefs() const +	{ +		const S32 currentVal = mRef.CurrentValue(); +		return currentVal; +	} + +private:  +	LLAtomic32< 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/llregistry.h b/indra/llcommon/llregistry.h index bb0d60247e..29950c108d 100755 --- 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  	{ @@ -64,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; @@ -309,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/llsdparam.cpp b/indra/llcommon/llsdparam.cpp index 9f4460a988..2e7b46f885 100755 --- a/indra/llcommon/llsdparam.cpp +++ b/indra/llcommon/llsdparam.cpp @@ -30,13 +30,14 @@  // 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;  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::BlockTimerStatHandle FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion");  //  // LLParamSDParser @@ -102,13 +103,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::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); +	block.serializeBlock(*this, name_stack, rules, diff_block);  }  /*virtual*/ std::string LLParamSDParser::getCurrentElementName() @@ -299,6 +300,7 @@ void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd)  	LLInitParam::Parser::name_stack_t stack = LLInitParam::Parser::name_stack_t();  	readSDValues(cb, sd, stack);  } +  namespace LLInitParam  {  	// LLSD specialization @@ -329,13 +331,14 @@ namespace LLInitParam  		p.writeValue<LLSD::String>(sd.asString(), name_stack);  	} -	void ParamValue<LLSD, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const +	bool ParamValue<LLSD, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack_range, const predicate_rule_t predicate_rule, const BaseBlock* diff_block) const  	{  		// attempt to write LLSD out directly -		if (!p.writeValue<LLSD>(mValue, name_stack)) +		if (!p.writeValue<LLSD>(mValue, name_stack_range))  		{  			// 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); +			LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack_range);  		} +		return true;  	}  } diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h index 6ef5debd7b..1542f95e68 100755 --- 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  { @@ -50,11 +51,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); +	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> @@ -92,7 +110,7 @@ private:  }; -extern LL_COMMON_API LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR; +extern LL_COMMON_API LLTrace::BlockTimerStatHandle FTM_SD_PARAM_ADAPTOR;  template<typename T>  class LLSDParamAdapter : public T  { @@ -100,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/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/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/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/llsingleton.h b/indra/llcommon/llsingleton.h index 40002313f1..6e6291a165 100755 --- 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;  		} @@ -138,18 +143,21 @@ 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  			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:  			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;	  			sData.mInstance->initSingleton();   			return sData.mInstance; @@ -190,6 +198,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;  	}; diff --git a/indra/llcommon/llskiplist.h b/indra/llcommon/llskiplist.h deleted file mode 100755 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 100755 index 49ff2928d1..0000000000 --- a/indra/llcommon/llskipmap.h +++ /dev/null @@ -1,1022 +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) -{ -	// Skipmaps must have binary depth of at least 2 -	cassert(BINARY_DEPTH >= 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) -{ -	// Skipmaps must have binary depth of at least 2 -	cassert(BINARY_DEPTH >= 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/llsortedvector.h b/indra/llcommon/llsortedvector.h deleted file mode 100755 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 100755 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/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp index ccd7ef91c2..e0e9056380 100755 --- 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/llstat.cpp b/indra/llcommon/llstat.cpp deleted file mode 100755 index 3678c8e1c1..0000000000 --- a/indra/llcommon/llstat.cpp +++ /dev/null @@ -1,404 +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, S32 num_bins, BOOL use_frame_timer) -:	mUseFrameTimer(use_frame_timer), -	mNumBins(num_bins), -	mName(name), -	mBins(NULL) -{ -	llassert(mNumBins > 0); -	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::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::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; - -	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; -} - -F64 LLStat::getLastTime() const -{ -	return mLastTime; -} diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h deleted file mode 100755 index 38377a010b..0000000000 --- a/indra/llcommon/llstat.h +++ /dev/null @@ -1,116 +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" - -class	LLSD; - -// ---------------------------------------------------------------------------- -class LL_COMMON_API LLStat -{ -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(); - -	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 getMeanDuration() const; -	F32 getMax() const; -	F32 getMaxPerSec() const; - -	U32 getNumValues() const; -	S32 getNumBins() const; - -	F64 getLastTime() 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; -	 -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_ diff --git a/indra/llcommon/llstatenums.h b/indra/llcommon/llstatenums.h index 81c4085d16..6515a3e3cb 100755..100644 --- a/indra/llcommon/llstatenums.h +++ b/indra/llcommon/llstatenums.h @@ -26,50 +26,6 @@  #ifndef LL_LLSTATENUMS_H  #define LL_LLSTATENUMS_H -enum -{ -	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 0a39288f5a..02f10fa2ba 100755 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -31,8 +31,8 @@  #include <algorithm>  #include <map>  #include <vector> +#include <list>  #include <set> -#include <deque>  #include <typeinfo>  // Use to compare the first element only of a pair @@ -125,7 +125,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 +170,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 +272,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 +280,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 +301,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 +563,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/llstring.cpp b/indra/llcommon/llstring.cpp index 22c8681983..76979f29f6 100755 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -28,15 +28,15 @@  #include "llstring.h"  #include "llerror.h" +#include "llfasttimer.h" +#include "llsd.h"  #if LL_WINDOWS -#define WIN32_LEAN_AND_MEAN -#include <winsock2.h> -#include <windows.h> +#include "llwin32headerslean.h"  #include <winnls.h> // for WideCharToMultiByte  #endif -LLFastTimer::DeclareTimer FT_STRING_FORMAT("String Format"); +LLTrace::BlockTimerStatHandle FT_STRING_FORMAT("String Format");  std::string ll_safe_string(const char* in) @@ -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; @@ -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/llstring.h b/indra/llcommon/llstring.h index f9702868c8..fdf9f3ce89 100755 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -29,10 +29,12 @@  #include <string>  #include <cstdio> -#include <locale> +//#include <locale>  #include <iomanip> -#include "llsd.h" -#include "llfasttimer.h" +#include <algorithm> +#include <vector> +#include <map> +#include "llformat.h"  #if LL_LINUX || LL_SOLARIS  #include <wctype.h> @@ -49,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/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/llsys.cpp b/indra/llcommon/llsys.cpp index e63045659e..07fe259e47 100755 --- 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> @@ -645,7 +644,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;  			}  		}  	} @@ -704,12 +703,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;  	} @@ -750,12 +749,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;  	} @@ -870,7 +869,7 @@ LLMemoryInfo::LLMemoryInfo()  }  #if LL_WINDOWS -static U32 LLMemoryAdjustKBResult(U32 inKB) +static U32Kilobytes LLMemoryAdjustKBResult(U32Kilobytes inKB)  {  	// Moved this here from llfloaterabout.cpp @@ -881,16 +880,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 += U32Megabytes(1);  	return inKB;  }  #endif -U32 LLMemoryInfo::getPhysicalMemoryKB() const +U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const  {  #if LL_WINDOWS -	return LLMemoryAdjustKBResult(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... @@ -900,17 +899,17 @@ U32 LLMemoryInfo::getPhysicalMemoryKB() const  	size_t len = sizeof(phys);	  	sysctl(mib, 2, &phys, &len, NULL, 0); -	return (U32)(phys >> 10); +	return U64Bytes(phys);  #elif LL_LINUX  	U64 phys = 0;  	phys = (U64)(getpagesize()) * (U64)(get_phys_pages()); -	return (U32)(phys >> 10); +	return U64Bytes(phys);  #elif LL_SOLARIS  	U64 phys = 0;  	phys = (U64)(getpagesize()) * (U64)(sysconf(_SC_PHYS_PAGES)); -	return (U32)(phys >> 10); +	return U64Bytes(phys);  #else  	return 0; @@ -918,32 +917,32 @@ 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(); -	if (phys_kb >= 4194304 /* 4GB in KB */) +	U32Kilobytes phys_kb = getPhysicalMemoryKB(); +	if (phys_kb >= U32Gigabytes(4))  	{ -		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(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": @@ -960,8 +959,8 @@ void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_v  	// 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: @@ -1012,15 +1011,15 @@ void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_v  	// 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  } @@ -1433,9 +1432,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;      } @@ -1482,7 +1486,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); @@ -1515,14 +1519,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..962367f69f 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,22 +105,22 @@ 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:  	LLMemoryInfo(); ///< Default constructor  	void stream(std::ostream& s) const;	///< output text info to s -	U32 getPhysicalMemoryKB() const; ///< Memory size in KiloBytes +	U32Kilobytes 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(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/llthread.cpp b/indra/llcommon/llthread.cpp index e67d1bc57b..51c89e1eaf 100755 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -29,13 +29,49 @@  #include "apr_portable.h"  #include "llthread.h" +#include "llmutex.h"  #include "lltimer.h" +#include "lltrace.h" +#include "lltracethreadrecorder.h"  #if LL_LINUX || LL_SOLARIS  #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. +	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 set_thread_name( 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) @@ -56,19 +92,24 @@  //   //---------------------------------------------------------------------------- -#if !LL_DARWIN -U32 ll_thread_local sThreadID = 0; +#if LL_DARWIN +// statically allocated thread local storage not supported in Darwin executable formats +#elif LL_WINDOWS +U32 __declspec(thread) sThreadID = 0; +#elif LL_LINUX +U32 __thread sThreadID = 0;  #endif   U32 LLThread::sIDIter = 0; +  LL_COMMON_API void assert_main_thread()  {  	static U32 s_thread_id = LLThread::currentID();  	if (LLThread::currentID() != s_thread_id)  	{ -		llwarns << "Illegal execution from thread id " << (S32) LLThread::currentID() -			<< " outside main thread " << (S32) s_thread_id << llendl; +		LL_WARNS() << "Illegal execution from thread id " << (S32) LLThread::currentID() +			<< " outside main thread " << (S32) s_thread_id << LL_ENDL;  	}  } @@ -86,6 +127,13 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap  {  	LLThread *threadp = (LLThread *)datap; +#ifdef LL_WINDOWS +	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 +	threadp->mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder()); +  #if !LL_DARWIN  	sThreadID = threadp->mID;  #endif @@ -93,21 +141,26 @@ 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; +	 +	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;  } -  LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :  	mPaused(FALSE),  	mName(name),  	mAPRThreadp(NULL), -	mStatus(STOPPED) +	mStatus(STOPPED), +	mRecorder(NULL)  { +  	mID = ++sIDIter;  	// Thread creation probably CAN be paranoid about APR being initialized, if necessary @@ -150,10 +203,10 @@ 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 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) @@ -172,8 +225,10 @@ 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. +			delete mRecorder; +  			apr_thread_exit(mAPRThreadp, -1);  			return;  		} @@ -191,6 +246,14 @@ void LLThread::shutdown()  		apr_pool_destroy(mAPRPoolp);  		mAPRPoolp = 0;  	} + +	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); +	}  } @@ -212,9 +275,10 @@ 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);  	} +  }  //============================================================================ @@ -283,7 +347,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 @@ -316,185 +386,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 -} - -bool LLMutex::trylock() -{ -	if(isSelfLocked()) -	{ //redundant lock -		mCount++; -		return true; -	} -	 -	apr_status_t status(apr_thread_mutex_trylock(mAPRMutexp)); -	if (APR_STATUS_IS_EBUSY(status)) -	{ -		return false; -	} -	 -#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 -	return true; -} - -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 @@ -533,11 +424,10 @@ LLThreadSafeRefCount::~LLThreadSafeRefCount()  {   	if (mRef != 0)  	{ -		llerrs << "deleting non-zero reference" << llendl; +		LL_ERRS() << "deleting non-zero reference" << LL_ENDL;  	}  } -  //============================================================================  LLResponder::~LLResponder() diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index 8c7143304f..6f9ec10fd3 100755 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -31,20 +31,20 @@  #include "llapr.h"  #include "apr_thread_cond.h"  #include "boost/intrusive_ptr.hpp" +#include "llmutex.h" +#include "llrefcount.h" -class LLThread; -class LLMutex; -class LLCondition; +LL_COMMON_API void assert_main_thread(); -#if LL_WINDOWS -#define ll_thread_local __declspec(thread) -#else -#define ll_thread_local __thread -#endif +namespace LLTrace +{ +	class ThreadRecorder; +}  class LL_COMMON_API LLThread  {  private: +	friend class LLMutex;  	static U32 sIDIter;  public: @@ -98,11 +98,11 @@ 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; -	LLCondition*		mRunCondition; +	class LLCondition*	mRunCondition;  	LLMutex*			mDataLock;  	apr_thread_t		*mAPRThreadp; @@ -110,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. @@ -140,117 +141,6 @@ protected:  	// mDataLock->unlock();  }; -//============================================================================ - -#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 -	bool trylock();		// non-blocking, returns true if lock held. -	void unlock();		// undefined behavior when called on mutex not being held -	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; -}; - -//============================================================================ - -// Scoped locking class similar in function to LLMutexLock but uses -// the trylock() method to conditionally acquire lock without -// blocking.  Caller resolves the resulting condition by calling -// the isLocked() method and either punts or continues as indicated. -// -// Mostly of interest to callers needing to avoid stalls who can -// guarantee another attempt at a later time. - -class LLMutexTrylock -{ -public: -	LLMutexTrylock(LLMutex* mutex) -		: mMutex(mutex), -		  mLocked(false) -	{ -		if (mMutex) -			mLocked = mMutex->trylock(); -	} - -	~LLMutexTrylock() -	{ -		if (mMutex && mLocked) -			mMutex->unlock(); -	} - -	bool isLocked() const -	{ -		return mLocked; -	} -	 -private: -	LLMutex*	mMutex; -	bool		mLocked; -}; - -//============================================================================  void LLThread::lockData()  { @@ -265,76 +155,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)  -	{ -		mRef = 0; -		return *this; -	} - -	void ref() -	{ -		mRef++;  -	}  - -	void unref() -	{ -		llassert(mRef >= 1); -		if ((--mRef) == 0)		// See note in llapr.h on atomic decrement operator return value.   -		{	 -			// If we hit zero, the caller should be the only smart pointer owning the object and we can delete it. -			// It is technically possible for a vanilla pointer to mess this up, or another thread to -			// jump in, find this object, create another smart pointer and end up dangling, but if -			// the code is that bad and not thread-safe, it's trouble already. -			delete this; -		} -	} - -	S32 getNumRefs() const -	{ -		const S32 currentVal = mRef.CurrentValue(); -		return currentVal; -	} - -private:  -	LLAtomic32< 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/llthreadlocalstorage.cpp b/indra/llcommon/llthreadlocalstorage.cpp new file mode 100644 index 0000000000..8cef05caac --- /dev/null +++ b/indra/llcommon/llthreadlocalstorage.cpp @@ -0,0 +1,119 @@ +/**  + * @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" +#include "llapr.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); +		LL_ERRS() << "Failed to set thread local data" << LL_ENDL; +	} +} + +void* LLThreadLocalPointerBase::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); +		LL_ERRS() << "Failed to get thread local data" << LL_ENDL; +	} +	return ptr; +} + + +void LLThreadLocalPointerBase::initStorage( ) +{ +	apr_status_t result = apr_threadkey_private_create(&mThreadKey, NULL, gAPRPoolp); +	if (result != APR_SUCCESS) +	{ +		ll_apr_warn_status(result); +		LL_ERRS() << "Failed to allocate thread local data" << LL_ENDL; +	} +} + +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); +				LL_ERRS() << "Failed to delete thread local data" << LL_ENDL; +			} +		} +	} +} + +//static +void LLThreadLocalPointerBase::initAllThreadLocalStorage() +{ +	if (!sInitialized) +	{ +		for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances(); +			it != end_it; +			++it) +		{ +			(*it).initStorage(); +		} +		sInitialized = true; +	} +} + +//static +void LLThreadLocalPointerBase::destroyAllThreadLocalStorage() +{ +	if (sInitialized) +	{ +		//for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances(); +		//	it != end_it; +		//	++it) +		//{ +		//	(*it).destroyStorage(); +		//} +		sInitialized = false; +	} +} diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h new file mode 100644 index 0000000000..ec3b52c8cb --- /dev/null +++ b/indra/llcommon/llthreadlocalstorage.h @@ -0,0 +1,185 @@ +/**  + * @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" + +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); + +	void* get() const; + +	void initStorage(); +	void destroyStorage(); + +protected: +	struct 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; +	} + +	bool isNull() const { return !sInitialized || get() == NULL; } + +	bool notNull() const { return sInitialized && get() != NULL; } +}; + +template<typename DERIVED_TYPE> +class LLThreadLocalSingletonPointer +{ +public: +	LL_FORCE_INLINE static DERIVED_TYPE* getInstance() +	{ +#if LL_DARWIN +        createTLSKey(); +        return (DERIVED_TYPE*)pthread_getspecific(sInstanceKey); +#else +		return sInstance; +#endif +	} + +	static void setInstance(DERIVED_TYPE* instance) +	{ +#if LL_DARWIN +        createTLSKey(); +        pthread_setspecific(sInstanceKey, (void*)instance); +#else +		sInstance = instance; +#endif +	} + +private: + +#if LL_WINDOWS +	static __declspec(thread) DERIVED_TYPE* sInstance; +#elif LL_LINUX +	static __thread DERIVED_TYPE* sInstance; +#elif LL_DARWIN +    static void TLSError() +    { +        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) +        { +            LL_ERRS() << "Could not create thread local storage" << LL_ENDL; +        } +    } +    static pthread_key_t sInstanceKey; +#endif +}; + +#if LL_WINDOWS +template<typename DERIVED_TYPE> +__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> +pthread_key_t LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstanceKey; +#endif + +#endif // LL_LLTHREADLOCALSTORAGE_H 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 9ebc6de7f4..ab105a82e6 100755 --- 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" @@ -45,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; @@ -58,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 @@ -190,7 +182,7 @@ U64 get_clock_count()  	return clock_count.QuadPart - offset;  } -F64 calc_clock_frequency(U32 uiMeasureMSecs) +F64 calc_clock_frequency()  {  	__int64 freq;  	QueryPerformanceFrequency((LARGE_INTEGER *) &freq); @@ -201,7 +193,7 @@ F64 calc_clock_frequency(U32 uiMeasureMSecs)  #if LL_LINUX || LL_DARWIN || LL_SOLARIS  // Both Linux and Mac use gettimeofday for accurate time -F64 calc_clock_frequency(unsigned int uiMeasureMSecs) +F64 calc_clock_frequency()  {  	return 1000000.0; // microseconds, so 1 MHz.  } @@ -216,56 +208,68 @@ U64 get_clock_count()  #endif -void update_clock_frequencies() +TimerInfo::TimerInfo() +:	mClockFrequency(0.0), +	mTotalTimeClockCount(0), +	mLastTotalTimeClockCount(0) +{} + +void TimerInfo::update()  { -	gClockFrequency = calc_clock_frequency(50U); -	gClockFrequencyInv = 1.0/gClockFrequency; -	gClocksToMicroseconds = gClockFrequencyInv * SEC_TO_MICROSEC; +	mClockFrequency = calc_clock_frequency(); +	mClockFrequencyInv = 1.0/mClockFrequency; +	mClocksToMicroseconds = mClockFrequencyInv;  } +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 -U64 totalTime() +// 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 (U64)(gTotalTimeClockCount*gClocksToMicroseconds); +	U64Microseconds time(get_timer_info().mTotalTimeClockCount*get_timer_info().mClocksToMicroseconds); +	return time;  } @@ -273,9 +277,9 @@ U64 totalTime()  LLTimer::LLTimer()  { -	if (!gClockFrequency) +	if (!get_timer_info().mClockFrequency)  	{ -		update_clock_frequencies(); +		get_timer_info().update();  	}  	mStarted = TRUE; @@ -283,20 +287,32 @@ LLTimer::LLTimer()  }  LLTimer::~LLTimer() +{} + +// static +void LLTimer::initClass() +{ +	if (!sTimer) sTimer = new LLTimer; +} + +// static +void LLTimer::cleanupClass()  { +	delete sTimer; sTimer = NULL;  }  // static -U64 LLTimer::getTotalTime() +U64MicrosecondsImplicit LLTimer::getTotalTime()  {  	// simply call into the implementation function. -	return totalTime(); +	U64MicrosecondsImplicit total_time = totalTime(); +	return total_time;  }	  // static -F64 LLTimer::getTotalSeconds() +F64SecondsImplicit LLTimer::getTotalSeconds()  { -	return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64; +	return F64Microseconds(U64_to_F64(getTotalTime()));  }  void LLTimer::reset() @@ -343,43 +359,43 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount)  } -F64 LLTimer::getElapsedTimeF64() const +F64SecondsImplicit LLTimer::getElapsedTimeF64() const  {  	U64 last = mLastClockCount; -	return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv; +	return (F64)getElapsedTimeAndUpdate(last) * get_timer_info().mClockFrequencyInv;  } -F32 LLTimer::getElapsedTimeF32() const +F32SecondsImplicit LLTimer::getElapsedTimeF32() const  {  	return (F32)getElapsedTimeF64();  } -F64 LLTimer::getElapsedTimeAndResetF64() +F64SecondsImplicit LLTimer::getElapsedTimeAndResetF64()  { -	return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv; +	return (F64)getElapsedTimeAndUpdate(mLastClockCount) * get_timer_info().mClockFrequencyInv;  } -F32 LLTimer::getElapsedTimeAndResetF32() +F32SecondsImplicit LLTimer::getElapsedTimeAndResetF32()  {  	return (F32)getElapsedTimeAndResetF64();  }  /////////////////////////////////////////////////////////////////////////////// -void  LLTimer::setTimerExpirySec(F32 expiration) +void  LLTimer::setTimerExpirySec(F32SecondsImplicit expiration)  {  	mExpirationTicks = get_clock_count() -		+ (U64)((F32)(expiration * gClockFrequency)); +		+ (U64)((F32)(expiration * get_timer_info().mClockFrequency.value()));  } -F32 LLTimer::getRemainingTimeF32() const +F32SecondsImplicit LLTimer::getRemainingTimeF32() const  {  	U64 cur_ticks = get_clock_count();  	if (cur_ticks > mExpirationTicks)  	{  		return 0.0f;  	} -	return F32((mExpirationTicks - cur_ticks) * gClockFrequencyInv); +	return F32((mExpirationTicks - cur_ticks) * get_timer_info().mClockFrequencyInv);  } @@ -392,7 +408,7 @@ BOOL  LLTimer::checkExpirationAndReset(F32 expiration)  	}  	mExpirationTicks = cur_ticks -		+ (U64)((F32)(expiration * gClockFrequency)); +		+ (U64)((F32)(expiration * get_timer_info().mClockFrequency));  	return TRUE;  } @@ -448,7 +464,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;  				} @@ -491,20 +507,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); @@ -521,7 +537,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; @@ -543,9 +559,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 e73741217c..ec70213447 100755 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -37,6 +37,7 @@  #include <string>  #include <list>  // units conversions +#include "llunits.h"  #ifndef USEC_PER_SEC      const U32	USEC_PER_SEC	= 1000000;  #endif @@ -55,27 +56,34 @@ public:  protected:	  	U64 mLastClockCount;  	U64 mExpirationTicks; -	BOOL mStarted; +	bool mStarted;  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 F64 getElapsedSeconds() +	static F64SecondsImplicit getElapsedSeconds() +	{ +		if (sTimer)   	{  		return sTimer->getElapsedTimeF64();  	} +		else +		{ +			return 0; +		} +	}  	// Return a high precision usec since epoch -	static U64 getTotalTime(); +	static U64MicrosecondsImplicit getTotalTime();  	// Return a high precision seconds since epoch -	static F64 getTotalSeconds(); +	static F64SecondsImplicit getTotalSeconds();  	// MANIPULATORS @@ -83,21 +91,21 @@ 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(F32SecondsImplicit expiration);  	BOOL checkExpirationAndReset(F32 expiration);  	BOOL hasExpired() const; -	F32 getElapsedTimeAndResetF32();	// Returns elapsed time in seconds with reset -	F64 getElapsedTimeAndResetF64(); +	F32SecondsImplicit getElapsedTimeAndResetF32();	// Returns elapsed time in seconds with reset +	F64SecondsImplicit getElapsedTimeAndResetF64(); -	F32 getRemainingTimeF32() const; +	F32SecondsImplicit getRemainingTimeF32() const;  	static BOOL knownBadTimer();  	// ACCESSORS -	F32 getElapsedTimeF32() const;			// Returns elapsed time in seconds -	F64 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; } +	bool getStarted() const { return mStarted; }  	static U64 getCurrentClockCount();		// Returns the raw clockticks @@ -106,9 +114,21 @@ public:  //  // Various functions for initializing/accessing clock and timing stuff.  Don't use these without REALLY knowing how they work.  // +struct TimerInfo +{ +	TimerInfo(); +	void update(); + +	F64HertzImplicit		mClockFrequency; +	F64SecondsImplicit		mClockFrequencyInv; +	F64MicrosecondsImplicit	mClocksToMicroseconds; +	U64						mTotalTimeClockCount; +	U64						mLastTotalTimeClockCount; +}; + +TimerInfo& get_timer_info(); +  LL_COMMON_API U64 get_clock_count(); -LL_COMMON_API F64 calc_clock_frequency(U32 msecs); -LL_COMMON_API void update_clock_frequencies();  // Sleep for milliseconds  LL_COMMON_API void ms_sleep(U32 ms); @@ -146,13 +166,6 @@ static inline time_t time_max()  	}  } -// These are really statics but they've been global for awhile -// and they're material to other timing classes.  If you are -// not implementing a timer class, do not use these directly. -extern LL_COMMON_API F64 gClockFrequency; -extern LL_COMMON_API F64 gClockFrequencyInv; -extern LL_COMMON_API F64 gClocksToMicroseconds; -  // Correction factor used by time_corrected() above.  extern LL_COMMON_API S32 gUTCOffset; @@ -167,9 +180,9 @@ 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); -U64 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/lltrace.cpp b/indra/llcommon/lltrace.cpp new file mode 100644 index 0000000000..54079a4689 --- /dev/null +++ b/indra/llcommon/lltrace.cpp @@ -0,0 +1,86 @@ +/**  + * @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 "lltracerecording.h" +#include "lltracethreadrecorder.h" +#include "llfasttimer.h" + +namespace LLTrace +{ + +MemStatHandle gTraceMemStat("LLTrace"); + +StatBase::StatBase( const char* name, const char* description )  +:	mName(name), +	mDescription(description ? description : "") +{ +#ifndef LL_RELEASE_FOR_DOWNLOAD +	if (LLTrace::get_thread_recorder().notNull()) +	{ +		LL_ERRS() << "Attempting to declare trace object after program initialization.  Trace objects should be statically initialized." << LL_ENDL; +	} +#endif +} + +const char* StatBase::getUnitLabel() const +{ +	return ""; +} + +TimeBlockTreeNode::TimeBlockTreeNode()  +:	mBlock(NULL), +	mParent(NULL), +	mNeedsSorting(false), +	mCollapsed(true) +{} + +void TimeBlockTreeNode::setParent( BlockTimerStatHandle* 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<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); +		} +	} + +	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 new file mode 100644 index 0000000000..5f1289dad8 --- /dev/null +++ b/indra/llcommon/lltrace.h @@ -0,0 +1,492 @@ +/**  + * @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 + +#include "stdtypes.h" +#include "llpreprocessor.h" + +#include "llmemory.h" +#include "llrefcount.h" +#include "lltraceaccumulators.h" +#include "llthreadlocalstorage.h" +#include "lltimer.h" +#include "llpointer.h" +#include "llunits.h" + +#define LL_TRACE_ENABLED 1 + +namespace LLTrace +{ +class Recording; + +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(); } + +class StatBase +{ +public: +	StatBase(const char* name, const char* description); +	virtual ~StatBase() {}; +	virtual const char* getUnitLabel() const; + +	const std::string& getName() const { return mName; } +	const std::string& getDescription() const { return mDescription; } + +protected: +	std::string	mName; +	std::string	mDescription; +}; + +template<typename ACCUMULATOR> +class StatType  +:	public StatBase, +	public LLInstanceTracker<StatType<ACCUMULATOR>, std::string> +{ +public: +	typedef LLInstanceTracker<StatType<ACCUMULATOR>, std::string> instance_tracker_t; +	StatType(const char* name, const char* description) +	:	instance_tracker_t(name), +		StatBase(name, description), +		mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot()) +	{} + +	LL_FORCE_INLINE ACCUMULATOR& getCurrentAccumulator() const +	{ +		ACCUMULATOR* accumulator_storage = LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance(); +		return accumulator_storage ? accumulator_storage[mAccumulatorIndex] : (*AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer())[mAccumulatorIndex]; +	} + +	size_t getIndex() const { return mAccumulatorIndex; } +	static size_t getNumIndices() { return AccumulatorBuffer<ACCUMULATOR>::getNumIndices(); } + +protected: +	const size_t		mAccumulatorIndex; +}; + + +template<> +class StatType<TimeBlockAccumulator::CallCountFacet> +:	public StatType<TimeBlockAccumulator> +{ +public: + +	StatType(const char* name, const char* description = "") +	:	StatType<TimeBlockAccumulator>(name, description) +	{} +}; + +template<> +class StatType<TimeBlockAccumulator::SelfTimeFacet> +	:	public StatType<TimeBlockAccumulator> +{ +public: + +	StatType(const char* name, const char* description = "") +		:	StatType<TimeBlockAccumulator>(name, description) +	{} +}; + +template <typename T = F64> +class EventStatHandle +:	public StatType<EventAccumulator> +{ +public: +	typedef F64 storage_t; +	typedef StatType<EventAccumulator> stat_t; +	typedef EventStatHandle<T> self_t; + +	EventStatHandle(const char* name, const char* description = NULL) +	:	stat_t(name, description) +	{} + +	/*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); } + +}; + +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> +class SampleStatHandle +:	public StatType<SampleAccumulator> +{ +public: +	typedef F64 storage_t; +	typedef StatType<SampleAccumulator> stat_t; +	typedef SampleStatHandle<T> self_t; + +	SampleStatHandle(const char* name, const char* description = NULL) +	:	stat_t(name, description) +	{} + +	/*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); } +}; + +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> +class CountStatHandle +:	public StatType<CountAccumulator> +{ +public: +	typedef F64 storage_t; +	typedef StatType<CountAccumulator> stat_t; +	typedef CountStatHandle<T> self_t; + +	CountStatHandle(const char* name, const char* description = NULL)  +	:	stat_t(name, description) +	{} + +	/*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); } +}; + +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<> +class StatType<MemAccumulator::AllocationFacet> +:	public StatType<MemAccumulator> +{ +public: + +	StatType(const char* name, const char* description = "") +	:	StatType<MemAccumulator>(name, description) +	{} +}; + +template<> +class StatType<MemAccumulator::DeallocationFacet> +:	public StatType<MemAccumulator> +{ +public: + +	StatType(const char* name, const char* description = "") +	:	StatType<MemAccumulator>(name, description) +	{} +}; + +class MemStatHandle : public StatType<MemAccumulator> +{ +public: +	typedef StatType<MemAccumulator> stat_t; +	MemStatHandle(const char* name, const char* description = "") +	:	stat_t(name, description) +	{ +		mName = name; +	} + +	void setName(const char* name) +	{ +		mName = name; +		setKey(name); +	} + +	/*virtual*/ const char* getUnitLabel() const { return "KB"; } + +	StatType<MemAccumulator::AllocationFacet>& allocations()  +	{  +		return static_cast<StatType<MemAccumulator::AllocationFacet>&>(*(StatType<MemAccumulator>*)this); +	} + +	StatType<MemAccumulator::DeallocationFacet>& deallocations()  +	{  +		return static_cast<StatType<MemAccumulator::DeallocationFacet>&>(*(StatType<MemAccumulator>*)this); +	} +}; + + +// measures effective memory footprint of specified type +// specialize to cover different types +template<typename T, typename IS_MEM_TRACKABLE = void, typename IS_UNITS = void> +struct MeasureMem +{ +	static size_t measureFootprint(const T& value) +	{ +		return sizeof(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(); +	} +}; + +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 U32Bytes(value).value(); +	} +}; + +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) +	{ +		if (!value) +		{ +			return 0; +		} +		return MeasureMem<T>::measureFootprint(*value); +	} +}; + +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) +	{ +		if (value.isNull()) +		{ +			return 0; +		} +		return MeasureMem<T>::measureFootprint(*value); +	} +}; + +template<typename IS_MEM_TRACKABLE, typename IS_BYTES> +struct MeasureMem<S32, IS_MEM_TRACKABLE, IS_BYTES> +{ +	static size_t measureFootprint(S32 value) +	{ +		return value; +	} +}; + +template<typename IS_MEM_TRACKABLE, typename IS_BYTES> +struct MeasureMem<U32, IS_MEM_TRACKABLE, IS_BYTES> +{ +	static size_t measureFootprint(U32 value) +	{ +		return value; +	} +}; + +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); +	} +}; + + +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> +class MemTrackableNonVirtual +{ +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); +	} + +	static MemStatHandle& getMemStatHandle() +	{ +		return sMemStat; +	} + +	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); +	} + +	// claim memory associated with other objects/data as our own, adding to our calculated footprint +	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> +{ +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 new file mode 100644 index 0000000000..385d31edd7 --- /dev/null +++ b/indra/llcommon/lltraceaccumulators.cpp @@ -0,0 +1,302 @@ +/**  + * @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 "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(MemAccumulator)); +} + +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)); +	claim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator)); +	claim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator)); +	claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemAccumulator)); +} + +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(MemAccumulator)); +} + +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::makeCurrent() +{ +	mCounts.makeCurrent(); +	mSamples.makeCurrent(); +	mEvents.makeCurrent(); +	mStackTimers.makeCurrent(); +	mMemStats.makeCurrent(); + +	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; +		} +	} +} + +//static +void AccumulatorBufferGroup::clearCurrent() +{ +	AccumulatorBuffer<CountAccumulator>::clearCurrent();	 +	AccumulatorBuffer<SampleAccumulator>::clearCurrent(); +	AccumulatorBuffer<EventAccumulator>::clearCurrent(); +	AccumulatorBuffer<TimeBlockAccumulator>::clearCurrent(); +	AccumulatorBuffer<MemAccumulator>::clearCurrent(); +} + +bool AccumulatorBufferGroup::isCurrent() const +{ +	return mCounts.isCurrent(); +} + +void AccumulatorBufferGroup::append( const AccumulatorBufferGroup& other ) +{ +	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, 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, NON_SEQUENTIAL); +} + +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::sync() +{ +	if (isCurrent()) +	{ +		F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds(); + +		mSamples.sync(time_stamp); +		mMemStats.sync(time_stamp); +	} +} + +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) +	{ +		return; +	} + +	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; } + +		mSumOfSquares = mergeSumsOfSquares(*this, other); + +		if (append_type == SEQUENTIAL) +		{ +			mLastValue = other.mLastValue; +			mLastSampleTimeStamp = other.mLastSampleTimeStamp; +		} +	} +} + +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; +	llassert(!mHasValue || mMean < 0 || mMean >= 0); +	mSumOfSquares = 0; +	mLastSampleTimeStamp = LLTimer::getTotalSeconds(); +	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) +	{ +		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; } + +			mSumOfSquares = mergeSumsOfSquares(*this, other); + +			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 = 0; +	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 new file mode 100644 index 0000000000..42fad8a793 --- /dev/null +++ b/indra/llcommon/lltraceaccumulators.h @@ -0,0 +1,590 @@ + +/**  + * @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 "llunits.h" +#include "lltimer.h" +#include "llrefcount.h" +#include "llthreadlocalstorage.h" +#include "llmemory.h" +#include <limits> + +namespace LLTrace +{ +	const F64 NaN	= std::numeric_limits<double>::quiet_NaN(); + +	enum EBufferAppendType +	{ +		SEQUENTIAL, +		NON_SEQUENTIAL +	}; + +	template<typename ACCUMULATOR> +	class AccumulatorBuffer : public LLRefCount +	{ +		typedef AccumulatorBuffer<ACCUMULATOR> self_t; +		static const S32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 32; +	private: +		struct StaticAllocationMarker { }; + +		AccumulatorBuffer(StaticAllocationMarker m) +		:	mStorageSize(0), +			mStorage(NULL) +		{} + +	public: + +		AccumulatorBuffer(const AccumulatorBuffer& other = *getDefaultBuffer()) +		:	mStorageSize(0), +			mStorage(NULL) +		{ +			resize(sNextStorageSlot); +			for (S32 i = 0; i < sNextStorageSlot; i++) +			{ +				mStorage[i] = other.mStorage[i]; +			} +		} + +		~AccumulatorBuffer() +		{ +			if (isCurrent()) +			{ +				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, EBufferAppendType append_type) +		{ +			llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot); +			for (size_t i = 0; i < sNextStorageSlot; i++) +			{ +				mStorage[i].addSamples(other.mStorage[i], append_type); +			} +		} + +		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 sync(F64SecondsImplicit time_stamp) +		{ +			llassert(mStorageSize >= sNextStorageSlot); +			for (size_t i = 0; i < sNextStorageSlot; i++) +			{ +				mStorage[i].sync(time_stamp); +			} +		} + +		void makeCurrent() +		{ +			LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(mStorage); +		} + +		bool isCurrent() const +		{ +			return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage; +		} + +		static void clearCurrent() +		{ +			LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL); +		} + +		// 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() +		{ +			size_t next_slot = sNextStorageSlot++; +			if (next_slot >= mStorageSize) +			{ +				// 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 + 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(); +		} + +		size_t capacity() const +		{ +			return mStorageSize; +		} + +		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; +		static F64 getDefaultValue() { return NaN; } + +		EventAccumulator() +		:	mSum(0), +			mMin(NaN), +			mMax(NaN), +			mMean(NaN), +			mSumOfSquares(0), +			mNumSamples(0), +			mLastValue(NaN) +		{} + +		void record(F64 value) +		{ +			if (mNumSamples == 0) +			{ +				mSum = value; +				mMean = value; +				mMin = value; +				mMax = value; +			} +			else +			{ +				mSum += value; +				F64 old_mean = mMean; +				mMean += (value - old_mean) / (F64)mNumSamples; +				mSumOfSquares += (value - old_mean) * (value - mMean); + +				if (value < mMin) { mMin = value; } +				else if (value > mMax) { mMax = value; } +			} + +			mNumSamples++; +			mLastValue = value; +		} + +		void addSamples(const EventAccumulator& other, EBufferAppendType append_type); +		void reset(const EventAccumulator* other); +		void sync(F64SecondsImplicit) {} + +		F64	getSum() const               { return mSum; } +		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); } +		F64 getSumOfSquares() const		 { return mSumOfSquares; } +		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; + +		F64	mMean, +			mSumOfSquares; + +		F32 mMin, +			mMax; + +		S32	mNumSamples; +	}; + + +	class SampleAccumulator +	{ +	public: +		typedef F64 value_t; +		static F64 getDefaultValue() { return NaN; } + +		SampleAccumulator() +		:	mSum(0), +			mMin(NaN), +			mMax(NaN), +			mMean(NaN), +			mSumOfSquares(0), +			mLastSampleTimeStamp(0), +			mTotalSamplingTime(0), +			mNumSamples(0), +			mLastValue(NaN), +			mHasValue(false) +		{} + +		void sample(F64 value) +		{ +			F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds(); + +			// store effect of last value +			sync(time_stamp); + +			if (!mHasValue) +			{ +				mHasValue = true; + +				mMin = value; +				mMax = value; +				mMean = value; +				mLastSampleTimeStamp = time_stamp; +			} +			else +			{ +				if (value < mMin) { mMin = value; } +				else if (value > mMax) { mMax = value; } +			} + +			mLastValue = value; +			mNumSamples++; +		} + +		void addSamples(const SampleAccumulator& other, EBufferAppendType append_type); +		void reset(const SampleAccumulator* other); + +		void sync(F64SecondsImplicit time_stamp) +		{ +			if (mHasValue && time_stamp != mLastSampleTimeStamp) +			{ +				F64SecondsImplicit 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; } +		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); } +		F64 getSumOfSquares() const		 { return mSumOfSquares; } +		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; + +		F64		mMean, +				mSumOfSquares; + +		F64SecondsImplicit	 +				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 +	{ +	public: +		typedef F64 value_t; +		static F64 getDefaultValue() { return 0; } + +		CountAccumulator() +		:	mSum(0), +			mNumSamples(0) +		{} + +		void add(F64 value) +		{ +			mNumSamples++; +			mSum += value; +		} + +		void addSamples(const CountAccumulator& other, EBufferAppendType /*type*/) +		{ +			mSum += other.mSum; +			mNumSamples += other.mNumSamples; +		} + +		void reset(const CountAccumulator* other) +		{ +			mNumSamples = 0; +			mSum = 0; +		} + +		void sync(F64SecondsImplicit) {} + +		F64	getSum() const { return mSum; } + +		S32 getSampleCount() const { return mNumSamples; } + +		bool hasValue() const			 { return true; } + +	private: +		F64	mSum; + +		S32	mNumSamples; +	}; + +	class TimeBlockAccumulator +	{ +	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 +		struct CallCountFacet  +		{ +			typedef S32 value_t; +		}; + +		struct SelfTimeFacet +		{ +			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); +		void sync(F64SecondsImplicit) {} +		bool hasValue() const { return true; } + +		// +		// members +		// +		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 + +	}; + +	class BlockTimerStatHandle; + +	class TimeBlockTreeNode +	{ +	public: +		TimeBlockTreeNode(); + +		void setParent(BlockTimerStatHandle* parent); +		BlockTimerStatHandle* getParent() { return mParent; } + +		BlockTimerStatHandle*					mBlock; +		BlockTimerStatHandle*					mParent;	 +		std::vector<BlockTimerStatHandle*>		mChildren; +		bool						mCollapsed; +		bool						mNeedsSorting; +	}; +	 +	struct BlockTimerStackRecord +	{ +		class BlockTimer*	mActiveTimer; +		class BlockTimerStatHandle*	mTimeBlock; +		U64					mChildTime; +	}; + +	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) +		{ +			mAllocations.addSamples(other.mAllocations, append_type); +			mDeallocations.addSamples(other.mDeallocations, append_type); + +			if (append_type == SEQUENTIAL) +			{ +				mSize.addSamples(other.mSize, SEQUENTIAL); +			} +			else +			{ +				F64 allocation_delta(other.mAllocations.getSum() - other.mDeallocations.getSum()); +				mSize.sample(mSize.hasValue()  +					? mSize.getLastValue() + allocation_delta  +					: allocation_delta); +			} +		} + +		void reset(const MemAccumulator* other) +		{ +			mSize.reset(other ? &other->mSize : NULL); +			mAllocations.reset(other ? &other->mAllocations : NULL); +			mDeallocations.reset(other ? &other->mDeallocations : NULL); +		} + +		void sync(F64SecondsImplicit time_stamp)  +		{ +			mSize.sync(time_stamp); +		} + +		bool hasValue() const			 { return mSize.hasValue(); } + +		SampleAccumulator	mSize; +		EventAccumulator	mAllocations; +		CountAccumulator	mDeallocations; +	}; + +	struct AccumulatorBufferGroup : public LLRefCount +	{ +		AccumulatorBufferGroup(); +		AccumulatorBufferGroup(const AccumulatorBufferGroup&); +		~AccumulatorBufferGroup(); + +		void handOffTo(AccumulatorBufferGroup& other); +		void makeCurrent(); +		bool isCurrent() const; +		static void clearCurrent(); + +		void append(const AccumulatorBufferGroup& other); +		void merge(const AccumulatorBufferGroup& other); +		void reset(AccumulatorBufferGroup* other = NULL); +		void sync(); + +		AccumulatorBuffer<CountAccumulator>	 	mCounts; +		AccumulatorBuffer<SampleAccumulator>	mSamples; +		AccumulatorBuffer<EventAccumulator>		mEvents; +		AccumulatorBuffer<TimeBlockAccumulator> mStackTimers; +		AccumulatorBuffer<MemAccumulator> 	mMemStats; +	}; +} + +#endif // LL_LLTRACEACCUMULATORS_H + diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp new file mode 100644 index 0000000000..0b10438b9f --- /dev/null +++ b/indra/llcommon/lltracerecording.cpp @@ -0,0 +1,1251 @@ +/**  + * @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 "llfasttimer.h" +#include "lltracethreadrecorder.h" +#include "llthread.h" + +inline F64 lerp(F64 a, F64 b, F64 u)  +{ +	return a + ((b - a) * u); +} + +namespace LLTrace +{ + +extern MemStatHandle gTraceMemStat; + +/////////////////////////////////////////////////////////////////////// +// Recording +/////////////////////////////////////////////////////////////////////// + +Recording::Recording(EPlayState state)  +:	mElapsedSeconds(0), +	mActiveBuffers(NULL) +{ +	claim_alloc(gTraceMemStat, this); +	mBuffers = new AccumulatorBufferGroup(); +	claim_alloc(gTraceMemStat, mBuffers); +	setPlayState(state); +} + +Recording::Recording( const Recording& other ) +:	mActiveBuffers(NULL) +{ +	claim_alloc(gTraceMemStat, this); +	*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); + +	const_cast<Recording&>(other).update(); +	EPlayState other_play_state = other.getPlayState(); + +	mBuffers = other.mBuffers; + +	// 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; +} + + +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()); +	} +} + +// brings recording to front of recorder stack, with up to date info +void Recording::update() +{ +#if LL_TRACE_ENABLED +	if (isStarted()) +	{ +		mElapsedSeconds += mSamplingTimer.getElapsedTimeF64(); + +		// must have  +		llassert(mActiveBuffers != NULL  +				&& LLTrace::get_thread_recorder().notNull()); + +		if(!mActiveBuffers->isCurrent()) +		{ +			AccumulatorBufferGroup* buffers = mBuffers.write(); +			LLTrace::get_thread_recorder()->deactivate(buffers); +			mActiveBuffers = LLTrace::get_thread_recorder()->activate(buffers); +		} + +		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) +{ +	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()]; +	const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL; +	return F64Seconds((F64)(accumulator.mTotalTimeCounter) + (F64)(active_accumulator ? active_accumulator->mTotalTimeCounter : 0)) +				/ (F64)LLTrace::BlockTimer::countsPerSecond(); +} + +F64Seconds Recording::getSum(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) + (F64)(active_accumulator ? active_accumulator->mSelfTimeCounter : 0)) / (F64)LLTrace::BlockTimer::countsPerSecond()); +} + + +S32 Recording::getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat) +{ +	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 + (active_accumulator ? active_accumulator->mTotalTimeCounter : 0))  +				/ ((F64)LLTrace::BlockTimer::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 + (active_accumulator ? active_accumulator->mSelfTimeCounter : 0)) +			/ ((F64)LLTrace::BlockTimer::countsPerSecond() * mElapsedSeconds.value())); +} + +F32 Recording::getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat) +{ +	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) +{ +	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) +{ +	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) +{ +	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) +{ +	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) +{ +	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) +{ +	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) +{ +	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) +{ +	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) +{ +	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) +{ +	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) +{ +	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) +{ +	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) +{ +	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) +{ +	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) +{ +	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) +{ +	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 ) +{ +	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 ) +{ +	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) +{ +	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 ) +{ +	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 ) +{ +	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 ) +{ +	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 ) +{ +	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 ) +{ +	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 ) +{ +	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) +{ +	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 ) +{ +	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 ) +{ +	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 ) +{ +	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 ) +{ +	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 ) +{ +	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 ) +{ +	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); +} + +/////////////////////////////////////////////////////////////////////// +// PeriodicRecording +/////////////////////////////////////////////////////////////////////// + +PeriodicRecording::PeriodicRecording( S32 num_periods, EPlayState state)  +:	mAutoResize(num_periods == 0), +	mCurPeriod(0), +	mNumRecordedPeriods(0), +	mRecordingPeriods(num_periods ? num_periods : 1) +{ +	setPlayState(state); +	claim_alloc(gTraceMemStat, this); +} + +PeriodicRecording::~PeriodicRecording() +{ +	disclaim_alloc(gTraceMemStat, this); +} + +void PeriodicRecording::nextPeriod() +{ +	if (mAutoResize) +	{ +		mRecordingPeriods.push_back(Recording()); +	} + +	Recording& old_recording = getCurRecording(); +	mCurPeriod = (mCurPeriod + 1) % mRecordingPeriods.size(); +	old_recording.splitTo(getCurRecording()); + +	mNumRecordedPeriods = llmin((S32)mRecordingPeriods.size() - 1, mNumRecordedPeriods + 1); +} + +void PeriodicRecording::appendRecording(Recording& recording) +{ +	getCurRecording().appendRecording(recording); +	nextPeriod(); +} + + +void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other ) +{ +	if (other.mRecordingPeriods.empty()) return; + +	getCurRecording().update(); +	other.getCurRecording().update(); +	 +	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) % 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 +	S32 other_index = (other_oldest_recording_index + 1) % other_recording_slots; + +	if (mAutoResize) +	{ +		// push back recordings for everything in the middle +		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]); +			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]); +		} + +		mCurPeriod = mRecordingPeriods.size() - 1; +		mNumRecordedPeriods = mRecordingPeriods.size() - 1; +	} +	else +	{ +		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(S32 i = 1; 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(); +			} +		} +		 +		// 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, and make that our current period +		mCurPeriod = (mCurPeriod + num_to_copy - 1) % mRecordingPeriods.size(); +		mNumRecordedPeriods = llmin((S32)mRecordingPeriods.size() - 1, mNumRecordedPeriods + num_to_copy - 1); +	} + +	// end with fresh period, otherwise next appendPeriodicRecording() will merge the first +	// recording period with the last one appended here +	nextPeriod(); +	getCurRecording().setPlayState(getPlayState()); +} + +F64Seconds PeriodicRecording::getDuration() const +{ +	F64Seconds duration; +	S32 num_periods = mRecordingPeriods.size(); +	for (S32 i = 1; i <= num_periods; i++) +	{ +		S32 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() +{ +	return getPrevRecording(1); +} + +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( S32 offset ) +{ +	S32 num_periods = mRecordingPeriods.size(); +	offset = llclamp(offset, 0, num_periods - 1); +	return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods]; +} + +const Recording& PeriodicRecording::getPrevRecording( S32 offset ) const +{ +	S32 num_periods = mRecordingPeriods.size(); +	offset = llclamp(offset, 0, num_periods - 1); +	return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods]; +} + +void PeriodicRecording::handleStart() +{ +	getCurRecording().start(); +} + +void PeriodicRecording::handleStop() +{ +	getCurRecording().pause(); +} + +void PeriodicRecording::handleReset() +{ +	getCurRecording().stop(); + +	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; +	mNumRecordedPeriods = 0; +	getCurRecording().setPlayState(getPlayState()); +} + +void PeriodicRecording::handleSplitTo(PeriodicRecording& other) +{ +	getCurRecording().splitTo(other.getCurRecording()); +} + +F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) +{ +	num_periods = llmin(num_periods, getNumRecordedPeriods()); + +	bool has_value = false; +	F64 min_val = std::numeric_limits<F64>::max(); +	for (S32 i = 1; i <= num_periods; i++) +	{ +		Recording& recording = getPrevRecording(i); +		if (recording.hasValue(stat)) +		{ +			min_val = llmin(min_val, recording.getMin(stat)); +			has_value = true; +		} +	} + +	return has_value  +			? min_val  +			: NaN; +} + +F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) +{ +	num_periods = llmin(num_periods, getNumRecordedPeriods()); + +	bool has_value = false; +	F64 max_val = std::numeric_limits<F64>::min(); +	for (S32 i = 1; i <= num_periods; i++) +	{ +		Recording& recording = getPrevRecording(i); +		if (recording.hasValue(stat)) +		{ +			max_val = llmax(max_val, recording.getMax(stat)); +			has_value = true; +		} +	} + +	return has_value  +			? max_val  +			: NaN; +} + +// calculates means using aggregates per period +F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) +{ +	num_periods = llmin(num_periods, getNumRecordedPeriods()); + +	F64 mean = 0; +	S32 valid_period_count = 0; + +	for (S32 i = 1; i <= num_periods; i++) +	{ +		Recording& recording = getPrevRecording(i); +		if (recording.hasValue(stat)) +		{ +			mean += recording.getMean(stat); +			valid_period_count++; +		} +	} + +	return valid_period_count  +			? mean / (F64)valid_period_count +			: NaN; +} + + +F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) +{ +	num_periods = llmin(num_periods, getNumRecordedPeriods()); + +	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++) +	{ +		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((F64)sum_of_squares / (F64)valid_period_count) +			: NaN; +} + +F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) +{ +	num_periods = llmin(num_periods, getNumRecordedPeriods()); + +	bool has_value = false; +	F64 min_val = std::numeric_limits<F64>::max(); +	for (S32 i = 1; i <= num_periods; i++) +	{ +		Recording& recording = getPrevRecording(i); +		if (recording.hasValue(stat)) +		{ +			min_val = llmin(min_val, recording.getMin(stat)); +			has_value = true; +		} +	} + +	return has_value  +			? min_val  +			: NaN; +} + +F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/) +{ +	num_periods = llmin(num_periods, getNumRecordedPeriods()); + +	bool has_value = false; +	F64 max_val = std::numeric_limits<F64>::min(); +	for (S32 i = 1; i <= num_periods; i++) +	{ +		Recording& recording = getPrevRecording(i); +		if (recording.hasValue(stat)) +		{ +			max_val = llmax(max_val, recording.getMax(stat)); +			has_value = true; +		} +	} + +	return has_value  +			? max_val  +			: NaN; +} + + +F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) +{ +	num_periods = llmin(num_periods, getNumRecordedPeriods()); + +	S32 valid_period_count = 0; +	F64 mean = 0; + +	for (S32 i = 1; i <= num_periods; i++) +	{ +		Recording& recording = getPrevRecording(i); +		if (recording.hasValue(stat)) +		{ +			mean += recording.getMean(stat); +			valid_period_count++; +		} +	} + +	return valid_period_count +			? mean / F64(valid_period_count) +			: NaN; +} + +F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) +{ +	num_periods = llmin(num_periods, getNumRecordedPeriods()); + +	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; +} + + +F64Kilobytes PeriodicRecording::getPeriodMin( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) +{ +	num_periods = llmin(num_periods, getNumRecordedPeriods()); + +	F64Kilobytes 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; +} + +F64Kilobytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, S32 num_periods) +{ +	return getPeriodMin(static_cast<const StatType<MemAccumulator>&>(stat), num_periods); +} + +F64Kilobytes PeriodicRecording::getPeriodMax(const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/) +{ +	num_periods = llmin(num_periods, getNumRecordedPeriods()); + +	F64Kilobytes 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; +} + +F64Kilobytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, S32 num_periods) +{ +	return getPeriodMax(static_cast<const StatType<MemAccumulator>&>(stat), num_periods); +} + +F64Kilobytes PeriodicRecording::getPeriodMean( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) +{ +	num_periods = llmin(num_periods, getNumRecordedPeriods()); + +	F64Kilobytes mean(0); + +	for (S32 i = 1; i <= num_periods; i++) +	{ +		Recording& recording = getPrevRecording(i); +		mean += recording.getMean(stat); +	} + +	return mean / F64(num_periods); +} + +F64Kilobytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, S32 num_periods) +{ +	return getPeriodMean(static_cast<const StatType<MemAccumulator>&>(stat), num_periods); +} + +F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ ) +{ +	num_periods = llmin(num_periods, getNumRecordedPeriods()); + +	F64Kilobytes 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)) +		{ +			F64Kilobytes delta = recording.getMean(stat) - period_mean; +			sum_of_squares += delta.value() * delta.value(); +			valid_period_count++; +		} +	} + +	return F64Kilobytes(valid_period_count +			? sqrt(sum_of_squares / (F64)valid_period_count) +			: NaN); +} + +F64Kilobytes PeriodicRecording::getPeriodStandardDeviation(const MemStatHandle& stat, S32 num_periods) +{ +	return getPeriodStandardDeviation(static_cast<const StatType<MemAccumulator>&>(stat), num_periods); +} + +/////////////////////////////////////////////////////////////////////// +// ExtendableRecording +/////////////////////////////////////////////////////////////////////// + +void ExtendableRecording::extend() +{ +	// push the data back to accepted recording +	mAcceptedRecording.appendRecording(mPotentialRecording); +	// flush data, so we can start from scratch +	mPotentialRecording.reset(); +} + +void ExtendableRecording::handleStart() +{ +	mPotentialRecording.start(); +} + +void ExtendableRecording::handleStop() +{ +	mPotentialRecording.pause(); +} + +void ExtendableRecording::handleReset() +{ +	mAcceptedRecording.reset(); +	mPotentialRecording.reset(); +} + +void ExtendableRecording::handleSplitTo(ExtendableRecording& other) +{ +	mPotentialRecording.splitTo(other.mPotentialRecording); +} + + +/////////////////////////////////////////////////////////////////////// +// ExtendablePeriodicRecording +/////////////////////////////////////////////////////////////////////// + + +ExtendablePeriodicRecording::ExtendablePeriodicRecording()  +:	mAcceptedRecording(0),  +	mPotentialRecording(0) +{} + +void ExtendablePeriodicRecording::extend() +{ +	// push the data back to accepted recording +	mAcceptedRecording.appendPeriodicRecording(mPotentialRecording); +	// flush data, so we can start from scratch +	mPotentialRecording.reset(); +} + + +void ExtendablePeriodicRecording::handleStart() +{ +	mPotentialRecording.start(); +} + +void ExtendablePeriodicRecording::handleStop() +{ +	mPotentialRecording.pause(); +} + +void ExtendablePeriodicRecording::handleReset() +{ +	mAcceptedRecording.reset(); +	mPotentialRecording.reset(); +} + +void ExtendablePeriodicRecording::handleSplitTo(ExtendablePeriodicRecording& other) +{ +	mPotentialRecording.splitTo(other.mPotentialRecording); +} + + +PeriodicRecording& get_frame_recording() +{ +	static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(200, PeriodicRecording::STARTED)); +	return *sRecording; +} + +} + +void LLStopWatchControlsMixinCommon::start() +{ +	switch (mPlayState) +	{ +	case STOPPED: +		handleReset(); +		handleStart(); +		mPlayState = STARTED; +		break; +	case PAUSED: +		handleStart(); +		mPlayState = STARTED; +		break; +	case STARTED: +		break; +	default: +		llassert(false); +		break; +	} +} + +void LLStopWatchControlsMixinCommon::stop() +{ +	switch (mPlayState) +	{ +	case STOPPED: +		break; +	case PAUSED: +		mPlayState = STOPPED; +		break; +	case STARTED: +		handleStop(); +		mPlayState = STOPPED; +		break; +	default: +		llassert(false); +		break; +	} +} + +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; +	} +} + +void LLStopWatchControlsMixinCommon::resume() +{ +	switch (mPlayState) +	{ +	case STOPPED: +		handleStart(); +		mPlayState = STARTED; +		break; +	case PAUSED: +		handleStart(); +		mPlayState = STARTED; +		break; +	case STARTED: +		break; +	default: +		llassert(false); +		break; +	} +} + +void LLStopWatchControlsMixinCommon::restart() +{ +	switch (mPlayState) +	{ +	case STOPPED: +		handleReset(); +		handleStart(); +		mPlayState = STARTED; +		break; +	case PAUSED: +		handleReset(); +		handleStart(); +		mPlayState = STARTED; +		break; +	case STARTED: +		handleReset(); +		break; +	default: +		llassert(false); +		break; +	} +} + +void LLStopWatchControlsMixinCommon::reset() +{ +	handleReset(); +} + +void LLStopWatchControlsMixinCommon::setPlayState( EPlayState state ) +{ +	switch(state) +	{ +	case STOPPED: +		stop(); +		break; +	case PAUSED: +		pause(); +		break; +	case STARTED: +		start(); +		break; +	default: +		llassert(false); +		break; +	} + +	mPlayState = state; +} diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h new file mode 100644 index 0000000000..d0b4a842a6 --- /dev/null +++ b/indra/llcommon/lltracerecording.h @@ -0,0 +1,670 @@ +/**  + * @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 "lltimer.h" +#include "lltraceaccumulators.h" +#include "llpointer.h" + +class LLStopWatchControlsMixinCommon +{ +public: +	virtual ~LLStopWatchControlsMixinCommon() {} + +	enum EPlayState +	{ +		STOPPED, +		PAUSED, +		STARTED +	}; + +	void start();   // moves to started state, resetting if stopped +	void stop();    // moves to stopped state +	void pause();   // moves to paused state, unless stopped +	void unpause(); // moves to started state if paused +	void resume();  // moves to started state, without resetting +	void restart(); // moves to started state, always resetting +	void reset();   // resets + +	bool isStarted() const { return mPlayState == STARTED; } +	bool isPaused() const  { return mPlayState == PAUSED; } +	bool isStopped() const { return mPlayState == STOPPED; } + +	EPlayState getPlayState() const { return mPlayState; } +	// force play state to specific value by calling appropriate handle* methods +	void setPlayState(EPlayState state); + +protected: +	LLStopWatchControlsMixinCommon() +	:	mPlayState(STOPPED) +	{} + +private: +	// override these methods to provide started/stopped semantics + +	// activate behavior (without reset) +	virtual void handleStart() = 0; +	// deactivate behavior +	virtual void handleStop() = 0; +	// clear accumulated state, may be called while started +	virtual void handleReset() = 0; + +	EPlayState mPlayState; +}; + +template<typename DERIVED> +class LLStopWatchControlsMixin +:	public LLStopWatchControlsMixinCommon +{ +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) +	{ +		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) {}; + +}; + +namespace LLTrace +{ +	template<typename T> +	class StatType; + +	template<typename T> +	class CountStatHandle; + +	template<typename T> +	class SampleStatHandle; + +	template<typename T> +	class EventStatHandle; + +	class MemStatHandle; + +	template<typename T> +	struct RelatedTypes +	{ +		typedef F64 fractional_t; +		typedef T	sum_t; +	}; + +	template<typename T, typename UNIT_T> +	struct RelatedTypes<LLUnit<T, UNIT_T> > +	{ +		typedef LLUnit<typename RelatedTypes<T>::fractional_t, UNIT_T> fractional_t; +		typedef LLUnit<typename RelatedTypes<T>::sum_t, UNIT_T> sum_t; +	}; + +	template<> +	struct RelatedTypes<bool> +	{ +		typedef F64 fractional_t; +		typedef S32 sum_t; +	}; + +	class Recording  +	:	public LLStopWatchControlsMixin<Recording> +	{ +	public: +		Recording(EPlayState state = LLStopWatchControlsMixinCommon::STOPPED); + +		Recording(const Recording& other); +		~Recording(); + +		Recording& operator = (const Recording& other); + +		// accumulate data from subsequent, non-overlapping recording +		void appendRecording(Recording& other); + +		// grab latest recorded data +		void update(); + +		// ensure that buffers are exclusively owned by this recording +		void makeUnique() { mBuffers.makeUnique(); } + +		// Timer accessors +		bool hasValue(const StatType<TimeBlockAccumulator>& stat); +		F64Seconds getSum(const StatType<TimeBlockAccumulator>& stat); +		F64Seconds getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat); +		S32 getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat); + +		F64Seconds getPerSec(const StatType<TimeBlockAccumulator>& stat); +		F64Seconds getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat); +		F32 getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat); + +		// 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) +		{ +			return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const StatType<CountAccumulator>&> (stat)); +		} + +		F64 getPerSec(const StatType<CountAccumulator>& stat); +		template <typename T> +		typename RelatedTypes<T>::fractional_t getPerSec(const CountStatHandle<T>& stat) +		{ +			return (typename RelatedTypes<T>::fractional_t)getPerSec(static_cast<const StatType<CountAccumulator>&> (stat)); +		} + +		S32 getSampleCount(const StatType<CountAccumulator>& stat); + + +		// SampleStatHandle accessors +		bool hasValue(const StatType<SampleAccumulator>& stat); + +		F64 getMin(const StatType<SampleAccumulator>& stat); +		template <typename T> +		T getMin(const SampleStatHandle<T>& stat) +		{ +			return (T)getMin(static_cast<const StatType<SampleAccumulator>&> (stat)); +		} + +		F64 getMax(const StatType<SampleAccumulator>& stat); +		template <typename T> +		T getMax(const SampleStatHandle<T>& stat) +		{ +			return (T)getMax(static_cast<const StatType<SampleAccumulator>&> (stat)); +		} + +		F64 getMean(const StatType<SampleAccumulator>& stat); +		template <typename T> +		typename RelatedTypes<T>::fractional_t getMean(SampleStatHandle<T>& stat) +		{ +			return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const StatType<SampleAccumulator>&> (stat)); +		} + +		F64 getStandardDeviation(const StatType<SampleAccumulator>& stat); +		template <typename T> +		typename RelatedTypes<T>::fractional_t getStandardDeviation(const SampleStatHandle<T>& stat) +		{ +			return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const StatType<SampleAccumulator>&> (stat)); +		} + +		F64 getLastValue(const StatType<SampleAccumulator>& stat); +		template <typename T> +		T getLastValue(const SampleStatHandle<T>& stat) +		{ +			return (T)getLastValue(static_cast<const StatType<SampleAccumulator>&> (stat)); +		} + +		S32 getSampleCount(const StatType<SampleAccumulator>& stat); + +		// EventStatHandle accessors +		bool hasValue(const StatType<EventAccumulator>& stat); + +		F64 getSum(const StatType<EventAccumulator>& stat); +		template <typename T> +		typename RelatedTypes<T>::sum_t getSum(const EventStatHandle<T>& stat) +		{ +			return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const StatType<EventAccumulator>&> (stat)); +		} + +		F64 getMin(const StatType<EventAccumulator>& stat); +		template <typename T> +		T getMin(const EventStatHandle<T>& stat) +		{ +			return (T)getMin(static_cast<const StatType<EventAccumulator>&> (stat)); +		} + +		F64 getMax(const StatType<EventAccumulator>& stat); +		template <typename T> +		T getMax(const EventStatHandle<T>& stat) +		{ +			return (T)getMax(static_cast<const StatType<EventAccumulator>&> (stat)); +		} + +		F64 getMean(const StatType<EventAccumulator>& stat); +		template <typename T> +		typename RelatedTypes<T>::fractional_t getMean(EventStatHandle<T>& stat) +		{ +			return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const StatType<EventAccumulator>&> (stat)); +		} + +		F64 getStandardDeviation(const StatType<EventAccumulator>& stat); +		template <typename T> +		typename RelatedTypes<T>::fractional_t getStandardDeviation(const EventStatHandle<T>& stat) +		{ +			return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const StatType<EventAccumulator>&> (stat)); +		} + +		F64 getLastValue(const StatType<EventAccumulator>& stat); +		template <typename T> +		T getLastValue(const EventStatHandle<T>& stat) +		{ +			return (T)getLastValue(static_cast<const StatType<EventAccumulator>&> (stat)); +		} + +		S32 getSampleCount(const StatType<EventAccumulator>& stat); + +		F64Seconds getDuration() const { return mElapsedSeconds; } + +	protected: +		friend class ThreadRecorder; + +		// implementation for LLStopWatchControlsMixin +		/*virtual*/ void handleStart(); +		/*virtual*/ void handleStop(); +		/*virtual*/ void handleReset(); +		/*virtual*/ void handleSplitTo(Recording& other); + +		// returns data for current thread +		class ThreadRecorder* getThreadRecorder();  + +		LLTimer											mSamplingTimer; +		F64Seconds										mElapsedSeconds; +		LLCopyOnWritePointer<AccumulatorBufferGroup>	mBuffers; +		AccumulatorBufferGroup*							mActiveBuffers; + +	}; + +	class LL_COMMON_API PeriodicRecording +	:	public LLStopWatchControlsMixin<PeriodicRecording> +	{ +	public: +		PeriodicRecording(S32 num_periods, EPlayState state = STOPPED); +		~PeriodicRecording(); + +		void nextPeriod(); +		S32 getNumRecordedPeriods()  +		{  +			// current period counts if not active +			return mNumRecordedPeriods + (isStarted() ? 0 : 1);  +		} + +		F64Seconds getDuration() const; + +		void appendPeriodicRecording(PeriodicRecording& other); +		void appendRecording(Recording& recording); +		Recording& getLastRecording(); +		const Recording& getLastRecording() const; +		Recording& getCurRecording(); +		const Recording& getCurRecording() const; +		Recording& getPrevRecording(S32 offset); +		const Recording& getPrevRecording(S32 offset) const; +		Recording snapshotCurRecording() const; + +		template <typename T> +		S32 getSampleCount(const StatType<T>& stat, S32 num_periods = S32_MAX) +        { +			num_periods = llmin(num_periods, getNumRecordedPeriods()); + +            S32 num_samples = 0; +			for (S32 i = 1; i <= num_periods; i++) +			{ +				Recording& recording = getPrevRecording(i); +				num_samples += recording.getSampleCount(stat); +			} +			return num_samples; +        } +         +		// +		// PERIODIC MIN +		// + +		// catch all for stats that have a defined sum +		template <typename T> +		typename T::value_t getPeriodMin(const StatType<T>& stat, S32 num_periods = S32_MAX) +		{ +			num_periods = llmin(num_periods, getNumRecordedPeriods()); + +			bool has_value = false; +			typename T::value_t min_val(std::numeric_limits<typename T::value_t>::max()); +			for (S32 i = 1; i <= num_periods; i++) +			{ +				Recording& recording = getPrevRecording(i); +				if (recording.hasValue(stat)) +				{ +					min_val = llmin(min_val, recording.getSum(stat)); +					has_value = true; +				} +			} + +			return has_value  +				? min_val  +				: T::getDefaultValue(); +		} + +		template<typename T> +		T getPeriodMin(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX) +		{ +			return T(getPeriodMin(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); +		} + +		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 StatType<SampleAccumulator>&>(stat), num_periods)); +		} + +		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 StatType<EventAccumulator>&>(stat), num_periods)); +		} + +		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 StatType<T>& stat, S32 num_periods = S32_MAX) +		{ +			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++) +			{ +				Recording& recording = getPrevRecording(i); +				min_val = llmin(min_val, recording.getPerSec(stat)); +			} +			return (typename RelatedTypes<typename T::value_t>::fractional_t) min_val; +		} + +		template<typename T> +		typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX) +		{ +			return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); +		} + +		// +		// PERIODIC MAX +		// + +		// catch all for stats that have a defined sum +		template <typename T> +		typename T::value_t getPeriodMax(const StatType<T>& stat, S32 num_periods = S32_MAX) +		{ +			num_periods = llmin(num_periods, getNumRecordedPeriods()); + +			bool has_value = false; +			typename T::value_t max_val(std::numeric_limits<typename T::value_t>::min()); +			for (S32 i = 1; i <= num_periods; i++) +			{ +				Recording& recording = getPrevRecording(i); +				if (recording.hasValue(stat)) +				{ +					max_val = llmax(max_val, recording.getSum(stat)); +					has_value = true; +				} +			} + +			return has_value  +				? max_val  +				: T::getDefaultValue(); +		} + +		template<typename T> +		T getPeriodMax(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX) +		{ +			return T(getPeriodMax(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); +		} + +		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 StatType<SampleAccumulator>&>(stat), num_periods)); +		} + +		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 StatType<EventAccumulator>&>(stat), num_periods)); +		} + +		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 StatType<T>& stat, S32 num_periods = S32_MAX) +		{ +			num_periods = llmin(num_periods, getNumRecordedPeriods()); + +			F64 max_val = std::numeric_limits<F64>::min(); +			for (S32 i = 1; i <= num_periods; i++) +			{ +				Recording& recording = getPrevRecording(i); +				max_val = llmax(max_val, recording.getPerSec(stat)); +			} +			return (typename RelatedTypes<typename T::value_t>::fractional_t)max_val; +		} + +		template<typename T> +		typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX) +		{ +			return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); +		} + +		// +		// PERIODIC MEAN +		// + +		// catch all for stats that have a defined sum +		template <typename T> +		typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, S32 num_periods = S32_MAX) +		{ +			num_periods = llmin(num_periods, getNumRecordedPeriods()); + +			typename RelatedTypes<typename T::value_t>::fractional_t mean(0); + +			for (S32 i = 1; i <= num_periods; i++) +			{ +				Recording& recording = getPrevRecording(i); +				if (recording.getDuration() > (F32Seconds)0.f) +				{ +					mean += recording.getSum(stat); +				} +			} +			return (num_periods +				? typename RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods) +				: typename RelatedTypes<typename T::value_t>::fractional_t(NaN)); +		} + +		template<typename T> +		typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX) +		{ +			return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); +		} +		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 StatType<SampleAccumulator>&>(stat), num_periods)); +		} + +		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 StatType<EventAccumulator>&>(stat), num_periods)); +		} + +		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 StatType<T>& stat, S32 num_periods = S32_MAX) +		{ +			num_periods = llmin(num_periods, getNumRecordedPeriods()); + +			typename RelatedTypes<typename T::value_t>::fractional_t mean = 0; + +			for (S32 i = 1; i <= num_periods; i++) +			{ +				Recording& recording = getPrevRecording(i); +				if (recording.getDuration() > (F32Seconds)0.f) +				{ +					mean += recording.getPerSec(stat); +				} +			} + +			return (num_periods +				? typename RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods) +				: typename RelatedTypes<typename T::value_t>::fractional_t(NaN)); +		} + +		template<typename T> +		typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX) +		{ +			return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods)); +		} + +		// +		// PERIODIC STANDARD DEVIATION +		// + +		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 StatType<SampleAccumulator>&>(stat), num_periods)); +		} + +		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 StatType<EventAccumulator>&>(stat), num_periods)); +		} + +		F64Kilobytes getPeriodStandardDeviation(const StatType<MemAccumulator>& stat, S32 num_periods = S32_MAX); +		F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, S32 num_periods = S32_MAX); + +	private: +		// implementation for LLStopWatchControlsMixin +		/*virtual*/ void handleStart(); +		/*virtual*/ void handleStop(); +		/*virtual*/ void handleReset(); +		/*virtual*/ void handleSplitTo(PeriodicRecording& other); + +	private: +		std::vector<Recording>	mRecordingPeriods; +		const bool				mAutoResize; +		S32						mCurPeriod; +		S32						mNumRecordedPeriods; +	}; + +	PeriodicRecording& get_frame_recording(); + +	class ExtendableRecording +	:	public LLStopWatchControlsMixin<ExtendableRecording> +	{ +	public: +		void extend(); + +		Recording& getAcceptedRecording() { return mAcceptedRecording; } +		const Recording& getAcceptedRecording() const {return mAcceptedRecording;} + +		Recording& getPotentialRecording()				{ return mPotentialRecording; } +		const Recording& getPotentialRecording() const	{ return mPotentialRecording;} + +	private: +		// implementation for LLStopWatchControlsMixin +		/*virtual*/ void handleStart(); +		/*virtual*/ void handleStop(); +		/*virtual*/ void handleReset(); +		/*virtual*/ void handleSplitTo(ExtendableRecording& other); + +	private: +		Recording mAcceptedRecording; +		Recording mPotentialRecording; +	}; + +	class ExtendablePeriodicRecording +	:	public LLStopWatchControlsMixin<ExtendablePeriodicRecording> +	{ +	public: +		ExtendablePeriodicRecording(); +		void extend(); + +		PeriodicRecording& getResults()				{ return mAcceptedRecording; } +		const PeriodicRecording& getResults() const	{return mAcceptedRecording;} +		 +		void nextPeriod() { mPotentialRecording.nextPeriod(); } + +	private: +		// implementation for LLStopWatchControlsMixin +		/*virtual*/ void handleStart(); +		/*virtual*/ void handleStop(); +		/*virtual*/ void handleReset(); +		/*virtual*/ void handleSplitTo(ExtendablePeriodicRecording& other); + +	private: +		PeriodicRecording mAcceptedRecording; +		PeriodicRecording mPotentialRecording; +	}; +} + +#endif // LL_LLTRACERECORDING_H diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp new file mode 100644 index 0000000000..181fc2f058 --- /dev/null +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -0,0 +1,329 @@ +/**  + * @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 "lltracethreadrecorder.h" +#include "llfasttimer.h" +#include "lltrace.h" + +namespace LLTrace +{ +extern MemStatHandle gTraceMemStat; + +static ThreadRecorder* sMasterThreadRecorder = NULL; + +/////////////////////////////////////////////////////////////////////// +// ThreadRecorder +/////////////////////////////////////////////////////////////////////// + +ThreadRecorder::ThreadRecorder() +:	mParentRecorder(NULL) +{ +	init(); +} + +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); +	BlockTimerStatHandle& root_time_block = BlockTimer::getRootTimeBlock(); + +	BlockTimerStackRecord* timer_stack = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance(); +	timer_stack->mTimeBlock = &root_time_block; +	timer_stack->mActiveTimer = NULL; + +	mNumTimeBlockTreeNodes = AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer()->size(); + +	mTimeBlockTreeNodes = new TimeBlockTreeNode[mNumTimeBlockTreeNodes]; + +	activate(&mThreadRecordingBuffers); + +	// initialize time block parent pointers +	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& time_block = static_cast<BlockTimerStatHandle&>(*it); +		TimeBlockTreeNode& tree_node = mTimeBlockTreeNodes[it->getIndex()]; +		tree_node.mBlock = &time_block; +		tree_node.mParent = &root_time_block; + +		it->getCurrentAccumulator().mParent = &root_time_block; +	} + +	mRootTimer = new BlockTimer(root_time_block); +	timer_stack->mActiveTimer = mRootTimer; + +	BlockTimer::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1; + +	claim_alloc(gTraceMemStat, this); +	claim_alloc(gTraceMemStat, mRootTimer); +	claim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes); +#endif +} + + +ThreadRecorder::ThreadRecorder( ThreadRecorder& parent ) +:	mParentRecorder(&parent) +{ +	init(); +	mParentRecorder->addChildRecorder(this); +} + + +ThreadRecorder::~ThreadRecorder() +{ +#if LL_TRACE_ENABLED +	LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(NULL); + +	disclaim_alloc(gTraceMemStat, this); +	disclaim_alloc(gTraceMemStat, sizeof(BlockTimer)); +	disclaim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes); + +	deactivate(&mThreadRecordingBuffers); + +	delete mRootTimer; + +	if (!mActiveRecordings.empty()) +	{ +		std::for_each(mActiveRecordings.begin(), mActiveRecordings.end(), DeletePointer()); +		mActiveRecordings.clear(); +	} + +	set_thread_recorder(NULL); +	delete[] mTimeBlockTreeNodes; + +	if (mParentRecorder) +	{ +		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()) +	{ +		AccumulatorBufferGroup& prev_active_recording = mActiveRecordings.back()->mPartialRecording; +		prev_active_recording.sync(); +		BlockTimer::updateTimes(); +		prev_active_recording.handOffTo(active_recording->mPartialRecording); +	} +	mActiveRecordings.push_back(active_recording); + +	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(); +	BlockTimer::updateTimes(); + +	active_recording_list_t::reverse_iterator it, end_it; +	for (it = mActiveRecordings.rbegin(), end_it = mActiveRecordings.rend(); +		it != end_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.rend()) +		{ +			// ...push our gathered data down to it +			(*next_it)->mPartialRecording.append(cur_recording->mPartialRecording); +		} + +		// copy accumulated measurements into result buffer and clear accumulator (mPartialRecording) +		cur_recording->movePartialToTarget(); + +		if (cur_recording->mTargetRecording == recording) +		{ +			// found the recording, so return it +			break; +		} +	} + +	if (it == end_it) +	{ +		LL_WARNS() << "Recording not active on this thread" << LL_ENDL; +	} + +	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()); + +	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()) +		{ +			AccumulatorBufferGroup::clearCurrent(); +		} +		else +		{ +			mActiveRecordings.back()->mPartialRecording.makeCurrent(); +		} +	} +	delete recording_to_remove; +#endif +} + +ThreadRecorder::ActiveRecording::ActiveRecording( AccumulatorBufferGroup* target )  +:	mTargetRecording(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 +} + + +static LLTrace::BlockTimerStatHandle FTM_PULL_TRACE_DATA_FROM_CHILDREN("Pull child thread trace data"); + +void ThreadRecorder::pullFromChildren() +{ +#if LL_TRACE_ENABLED +	LL_RECORD_BLOCK_TIME(FTM_PULL_TRACE_DATA_FROM_CHILDREN); +	if (mActiveRecordings.empty()) return; + +	{ LLMutexLock lock(&mChildListMutex); + +		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); + +			target_recording_buffers.merge((*it)->mSharedRecordingBuffers); +			(*it)->mSharedRecordingBuffers.reset(); +		} +	} +#endif +} + + +void set_master_thread_recorder( ThreadRecorder* recorder ) +{ +	sMasterThreadRecorder = recorder; +} + + +ThreadRecorder* get_master_thread_recorder() +{ +	return sMasterThreadRecorder; +} + +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 new file mode 100644 index 0000000000..a797c6687e --- /dev/null +++ b/indra/llcommon/lltracethreadrecorder.h @@ -0,0 +1,102 @@ +/**  + * @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 "lltraceaccumulators.h" +#include "llthreadlocalstorage.h" + +namespace LLTrace +{ +	class LL_COMMON_API ThreadRecorder +	{ +	protected: +		struct ActiveRecording; +		typedef std::vector<ActiveRecording*> active_recording_list_t; +	public: +		ThreadRecorder(); +		explicit ThreadRecorder(ThreadRecorder& parent); + +		~ThreadRecorder(); + +		AccumulatorBufferGroup* activate(AccumulatorBufferGroup* recording); +		void deactivate(AccumulatorBufferGroup* recording); +		active_recording_list_t::iterator bringUpToDate(AccumulatorBufferGroup* recording); + +		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 +		{ +			ActiveRecording(AccumulatorBufferGroup* target); + +			AccumulatorBufferGroup*	mTargetRecording; +			AccumulatorBufferGroup	mPartialRecording; + +			void movePartialToTarget(); +		}; + +		AccumulatorBufferGroup			mThreadRecordingBuffers; + +		BlockTimerStackRecord			mBlockTimerStackRecord; +		active_recording_list_t			mActiveRecordings; + +		class BlockTimer*				mRootTimer; +		TimeBlockTreeNode*				mTimeBlockTreeNodes; +		size_t							mNumTimeBlockTreeNodes; +		typedef std::list<class ThreadRecorder*> child_thread_recorder_list_t; + +		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*					mParentRecorder; + +	}; + +	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 diff --git a/indra/llcommon/lltypeinfolookup.h b/indra/llcommon/lltypeinfolookup.h deleted file mode 100755 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/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 diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h new file mode 100644 index 0000000000..0e05ecd683 --- /dev/null +++ b/indra/llcommon/llunittype.h @@ -0,0 +1,836 @@ +/**  + * @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 UNITS> +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()) +	:	mValue(value) +	{} + +	// unit initialization and conversion +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE LLUnit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) +	:	mValue(convert(other).mValue) +	{} +	 +	LL_FORCE_INLINE storage_t value() const +	{ +		return mValue; +	} + +	LL_FORCE_INLINE void value(storage_t value) +	{ +		mValue = value; +	} + +	template<typename NEW_UNITS>  +	storage_t valueInUnits() +	{ +		return LLUnit<storage_t, NEW_UNITS>(*this).value(); +	} + +	template<typename NEW_UNITS>  +	void valueInUnits(storage_t value) +	{ +		*this = LLUnit<storage_t, NEW_UNITS>(value); +	} + +	LL_FORCE_INLINE void operator += (self_t other) +	{ +		mValue += convert(other).mValue; +	} + +	LL_FORCE_INLINE void operator -= (self_t other) +	{ +		mValue -= convert(other).mValue; +	} + +	LL_FORCE_INLINE void operator *= (storage_t multiplicand) +	{ +		mValue *= 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."); +	} + +	LL_FORCE_INLINE 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 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 +	{ +		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 +	{ +		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 +	{ +		return mValue >= convert(other).value(); +	} + +	LL_FORCE_INLINE static self_t convert(self_t v)  +	{  +		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_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)  +	{  +		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()); +	} + +protected: +	storage_t mValue; +}; + +template<typename STORAGE_TYPE, typename UNITS> +std::ostream& operator <<(std::ostream& s, const LLUnit<STORAGE_TYPE, UNITS>& unit) +{ +        s << unit.value() << UNITS::getUnitLabel(); +        return s; +} + +template<typename STORAGE_TYPE, typename UNITS> +std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNITS>& unit) +{ +        STORAGE_TYPE val; +        s >> val; +        unit.value(val); +        return s; +} + +template<typename STORAGE_TYPE, typename UNITS> +struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS> +{ +	typedef LLUnitImplicit<STORAGE_TYPE, UNITS> self_t; +	typedef typename LLUnit<STORAGE_TYPE, UNITS>::storage_t storage_t; +	typedef LLUnit<STORAGE_TYPE, UNITS> base_t; + +	LL_FORCE_INLINE LLUnitImplicit(storage_t value = storage_t()) +	:	base_t(value) +	{} + +	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 +	LL_FORCE_INLINE operator storage_t() const +	{ +		return base_t::value(); +	} + +	using base_t::operator +=; +	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_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 -=; +	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_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE void operator -= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) +	{ +        base_t::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 base_t::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 +	{ +		return base_t::mValue == convert(other).value(); +	} + +	template<typename STORAGE_T> +	LL_FORCE_INLINE bool operator == (STORAGE_T other) const +	{ +		return base_t::mValue == other; +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::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 +	{ +		return base_t::mValue != convert(other).value(); +	} + +	template<typename STORAGE_T> +	LL_FORCE_INLINE bool operator != (STORAGE_T other) const +	{ +		return base_t::mValue != other; +	} +	 +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::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 +	{ +		return base_t::mValue < convert(other).value(); +	} + +	template<typename STORAGE_T> +	LL_FORCE_INLINE bool operator < (STORAGE_T other) const +	{ +		return base_t::mValue < other; +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::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 +	{ +		return base_t::mValue <= convert(other).value(); +	} + +	template<typename STORAGE_T> +	LL_FORCE_INLINE bool operator <= (STORAGE_T other) const +	{ +		return base_t::mValue <= other; +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::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 +	{ +		return base_t::mValue > convert(other).value(); +	} + +	template<typename STORAGE_T> +	LL_FORCE_INLINE bool operator > (STORAGE_T other) const +	{ +		return base_t::mValue > other; +	} + +	template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS> +	LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const +	{ +		return base_t::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 +	{ +		return base_t::mValue >= convert(other).value(); +	} + +	template<typename STORAGE_T> +	LL_FORCE_INLINE bool operator >= (STORAGE_T other) const +	{ +		return base_t::mValue >= other; +	} +}; + +template<typename STORAGE_TYPE, typename UNITS> +std::ostream& operator <<(std::ostream& s, const LLUnitImplicit<STORAGE_TYPE, UNITS>& unit) +{ +        s << unit.value() << UNITS::getUnitLabel(); +        return s; +} + +template<typename STORAGE_TYPE, typename UNITS> +std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNITS>& 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 UNITS> +struct LLStorageType<LLUnit<STORAGE_TYPE, UNITS> > +{ +	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 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, UNITS1> result(first); +	result += second; +	return result; +} + +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, UNITS>(0); +} + +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, UNITS>(0); +} + +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, UNITS1> result(first); +	result += second; +	return result; +} + +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, UNITS1> result(first); +	result += second; +	return result; +} + +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, UNITS1> result(first); +	result += LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second); +	return result; +} + +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, UNITS> result(first); +	result += second; +	return result; +} + +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, UNITS> result(first); +	result += second; +	return result; +} + +// +// operator - +// +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, UNITS1> result(first); +	result -= second; +	return result; +} + +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, UNITS>(0); +} + +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, UNITS>(0); +} + +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, UNITS1> result(first); +	result -= second; +	return result; +} + +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, UNITS1> result(first); +	result -= second; +	return result; +} + +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, UNITS1> result(first); +	result -= LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second); +	return result; +} + +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, UNITS> result(first); +	result -= second; +	return result; +} + +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, UNITS> result(first); +	result -= second; +	return result; +} + +// +// operator * +// +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, UNITS1>(); +} + +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, UNITS>(first.value() * 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, UNITS>(first * second.value()); +} + +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, UNITS1>(); +} + +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, UNITS>(first.value() * 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, UNITS>(first * second.value()); +} + + +// +// operator / +// + +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, UNITS>(first.value() / 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 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, UNITS>(first.value() / 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 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 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()); +} + +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 += other * mDivisor; +		return *this; +	} + +	template<typename OTHER_T> +	self_t operator - (OTHER_T other) +	{ +		mValue -= other * mDivisor; +		return *this; +	} + +	T mValue; +	T mDivisor; +}; + +template<typename T> +struct LLUnitInverseLinearOps +{ +	typedef LLUnitInverseLinearOps<T> self_t; + +	LLUnitInverseLinearOps(T val)  +	:	mValue(val), +		mDivisor(1), +		mMultiplicand(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; +		mMultiplicand *= other; +		return *this; +	} + +	template<typename OTHER_T> +	self_t operator + (OTHER_T other) +	{ +		mValue -= other * mMultiplicand; +		return *this; +	} + +	template<typename OTHER_T> +	self_t operator - (OTHER_T other) +	{ +		mValue += other * mMultiplicand; +		return *this; +	} + +	T mValue; +	T mDivisor; +	T mMultiplicand; +}; + +#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> result =                                            \ +		LLUnitInverseLinearOps<result_storage_t>(in.value()) conversion_operation;               \ +	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> result =                                                   \ +		LLUnitLinearOps<result_storage_t>(in.value()) conversion_operation;				         \ +	out = LLUnit<S2, unit_name>((S2)result.mValue);                                              \ +	return result.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/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 0aaa50d231..e3671047b4 100755 --- 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> @@ -234,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;  		} @@ -244,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; @@ -283,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; @@ -308,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/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" diff --git a/indra/llcommon/lluuidhashmap.h b/indra/llcommon/lluuidhashmap.h deleted file mode 100755 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 diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llwin32headers.h index ef68a0eaf5..cf85067d95 100755..100644 --- a/indra/llcommon/llversionserver.h +++ b/indra/llcommon/llwin32headers.h @@ -1,8 +1,8 @@  /**  - * @file llversionserver.h - * @brief + * @file llwindows.h + * @brief sanitized include of windows header files   * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * $LicenseInfo:firstyear=2001&license=viewerlgpl$   * Second Life Viewer Source Code   * Copyright (C) 2010, Linden Research, Inc.   *  @@ -24,15 +24,19 @@   * $/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"; +#ifndef LL_LLWINDOWS_H +#define LL_LLWINDOWS_H +#ifdef LL_WINDOWS +#ifndef NOMINMAX +#define NOMINMAX +#endif +#undef WIN32_LEAN_AND_MEAN +#include <winsock2.h> +#include <windows.h> +// reset to default, which is lean +#define WIN32_LEAN_AND_MEAN +#undef NOMINMAX +#endif  #endif diff --git a/indra/llcommon/lldarrayptr.h b/indra/llcommon/llwin32headerslean.h index c9a0b204d1..f7e71301a8 100755..100644 --- a/indra/llcommon/lldarrayptr.h +++ b/indra/llcommon/llwin32headerslean.h @@ -1,6 +1,6 @@  /**  - * @file lldarrayptr.h - * @brief Wrapped std::vector for backward compatibility. + * @file llwindows.h + * @brief sanitized include of windows header files   *   * $LicenseInfo:firstyear=2001&license=viewerlgpl$   * Second Life Viewer Source Code @@ -23,14 +23,18 @@   * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA   * $/LicenseInfo$   */ -#ifndef LL_LLDARRAYPTR_H -#define LL_LLDARRAYPTR_H -#include "lldarray.h" +#ifndef LL_LLWINDOWS_H +#define LL_LLWINDOWS_H -template <class Type, int BlockSize = 32>  -class LLDynamicArrayPtr : public LLDynamicArray<Type, BlockSize> -{ -}; +#ifdef LL_WINDOWS +#ifndef NOMINMAX +#define NOMINMAX +#endif +#define WIN32_LEAN_AND_MEAN +#include <winsock2.h> +#include <windows.h> +#undef NOMINMAX +#endif -#endif // LL_LLDARRAYPTR_H +#endif 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/llworkerthread.h b/indra/llcommon/llworkerthread.h index be46394d6e..09776816a8 100755 --- 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" diff --git a/indra/llcommon/metaclass.cpp b/indra/llcommon/metaclass.cpp deleted file mode 100755 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 100755 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 100755 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 100755 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 100755 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 100755 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 100755 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 100755 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 100755 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/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/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/lldeadmantimer_test.cpp b/indra/llcommon/tests/lldeadmantimer_test.cpp index 7fd2dde6e0..23167762c3 100644 --- a/indra/llcommon/tests/lldeadmantimer_test.cpp +++ b/indra/llcommon/tests/lldeadmantimer_test.cpp @@ -37,12 +37,12 @@  static LLDeadmanTimer::time_type float_time_to_u64(F64 delta)  { -	return LLDeadmanTimer::time_type(delta * gClockFrequency); +	return LLDeadmanTimer::time_type(delta * get_timer_info().mClockFrequency);  }  static F64 u64_time_to_float(LLDeadmanTimer::time_type delta)  { -	return delta * gClockFrequencyInv; +	return delta * get_timer_info().mClockFrequencyInv;  } @@ -54,7 +54,7 @@ struct deadmantimer_test  	deadmantimer_test()  		{  			// LLTimer internals updating -			update_clock_frequencies(); +			get_timer_info().update();  		}  }; 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/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(); 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; 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();          } diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp index e769c3e22c..c7d4b8a06b 100755 --- a/indra/llcommon/tests/llinstancetracker_test.cpp +++ b/indra/llcommon/tests/llinstancetracker_test.cpp @@ -194,15 +194,15 @@ 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();              } @@ -215,15 +215,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 +238,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/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 3e68ef068e..e4e766d51b 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" @@ -46,9 +45,12 @@  #endif  //namespace lambda = boost::lambda; - -// static instance of this manages APR init/cleanup -static ManageAPR manager; + std::string apr_strerror_helper(apr_status_t rv) +{ +    char errbuf[256]; +    apr_strerror(rv, errbuf, sizeof(errbuf)); +    return errbuf; +}  /*****************************************************************************  *   Helpers @@ -60,7 +62,8 @@ static ManageAPR manager;  #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);  } diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp index 4d436e8897..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()); @@ -268,7 +265,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()); @@ -1723,5 +1720,6 @@ namespace tut                        "This string\n"                        "has several\n"                        "lines."); +              }  } diff --git a/indra/llcommon/tests/lltrace_test.cpp b/indra/llcommon/tests/lltrace_test.cpp new file mode 100644 index 0000000000..0a9d85ad00 --- /dev/null +++ b/indra/llcommon/tests/lltrace_test.cpp @@ -0,0 +1,142 @@ +/**  + * @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(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(Milligrams, "mg", Grams, * 1000); +} + +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)); +		} +		// 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  +				&& 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()); +	} + +} diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp new file mode 100644 index 0000000000..57cf9810af --- /dev/null +++ b/indra/llcommon/tests/llunits_test.cpp @@ -0,0 +1,388 @@ +/**  + * @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 "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(Latinum, "Lat", Quatloos, / 4); +	LL_DECLARE_DERIVED_UNIT(Solari, "Sol", Latinum, * 16); +} + +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; +	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<F32, Quatloos> float_quatloos; +		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 == F32Quatloos(1.f)); + +		LLUnit<S32, Quatloos> int_quatloos; +		ensure("default int unit is zero", int_quatloos == S32Quatloos(0)); + +		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 == F32Quatloos(42.f)); + +		int_quatloos = float_quatloos; +		ensure("int assignment from float preserves value", int_quatloos == S32Quatloos(42)); + +		float_quatloos = F32Quatloos(42.1f); +		int_quatloos = float_quatloos; +		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 == 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 +	template<> template<> +	void units_object_t::test<2>() +	{ +		LLUnit<F32, Quatloos> quatloos(1.f); +		LLUnit<F32, Latinum> latinum_bars(quatloos); +		ensure("conversion between units is automatic via initialization", latinum_bars == F32Latinum(1.f / 4.f)); + +		latinum_bars = S32Latinum(256); +		quatloos = latinum_bars; +		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 == F32Latinum(0.25f)); +	} + +	// conversions across non-base units +	template<> template<> +	void units_object_t::test<3>() +	{ +		LLUnit<F32, Quatloos> quatloos(1024); +		LLUnit<F32, Solari> solari(quatloos); +		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 == S32Latinum(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 == S32Quatloos(4)); +		quatloos = quatloos * 2; +		ensure(quatloos == S32Quatloos(8)); +		quatloos = 2.f * quatloos; +		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 == S32Quatloos(128)); + +		quatloos -= quatloos / 4 * 3; +		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 == S32Quatloos(8)); +		quatloos = quatloos / 4; +		ensure(quatloos == S32Quatloos(2)); + +		F32 ratio = quatloos / LLUnit<F32, Quatloos>(2.f); +		ensure(ratio == 1); +		ratio = quatloos / LLUnit<F32, Solari>(8.f); +		ensure(ratio == 1); + +		quatloos += LLUnit<F32, Solari>(8.f); +		ensure(quatloos == S32Quatloos(4)); +		quatloos -= LLUnit<F32, Latinum>(1.f); +		ensure(quatloos == S32Quatloos(0)); +	} + +	// 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; +	} + +	bool accept_implicit_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 + S32Quatloos(1); +		ensure("can initialize implicit unit from explicit", quatloos_implicit == 1); + +		quatloos = quatloos_implicit; +		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 == S32Quatloos(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("implicit units convert implicitly to regular values", float_val == 16); + +		S32 int_val = quatloos_implicit; +		ensure("implicit units convert implicitly to regular values", int_val == 16); + +		// 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); + +		// 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(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 +	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); +	} + +	// 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); +		S32Degrees deg(rad); +		ensure("radians -> degrees conversion", deg.value() == 360); + +		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); +	} + +	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); +	} +} diff --git a/indra/llcommon/tests/reflection_test.cpp b/indra/llcommon/tests/reflection_test.cpp deleted file mode 100755 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()); -	 -  } -} 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); 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 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  	{  | 
