diff options
| author | Ima Mechanique <ima.mechanique@secondlife.com> | 2013-06-26 17:39:23 +0100 | 
|---|---|---|
| committer | Ima Mechanique <ima.mechanique@secondlife.com> | 2013-06-26 17:39:23 +0100 | 
| commit | b615858d6c41c29b3b610ec0dba09f30b1f8b3a8 (patch) | |
| tree | 2b193625c9ed4a0ca36e5b5f99f1cc765e979d74 /indra/llcommon | |
| parent | e63d92ab504d74399cae2a9cc7625ef3ec330c38 (diff) | |
| parent | 2655c7a17ae38a073dcf8f05b0127b68edc34c95 (diff) | |
Merging last four months of development
Diffstat (limited to 'indra/llcommon')
272 files changed, 3258 insertions, 3445 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 66e2bc9095..3a4a8facc2 100644..100755 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -17,6 +17,7 @@ include_directories(      ${EXPAT_INCLUDE_DIRS}      ${LLCOMMON_INCLUDE_DIRS}      ${ZLIB_INCLUDE_DIRS} +    ${BREAKPAD_INCLUDE_DIRECTORIES}      )  # add_executable(lltreeiterators lltreeiterators.cpp) @@ -53,7 +54,7 @@ set(llcommon_SOURCE_FILES      lleventfilter.cpp      llevents.cpp      lleventtimer.cpp -    llfasttimer_class.cpp +    llfasttimer.cpp      llfile.cpp      llfindlocale.cpp      llfixedbuffer.cpp @@ -71,7 +72,6 @@ set(llcommon_SOURCE_FILES      llmd5.cpp      llmemory.cpp      llmemorystream.cpp -    llmemtype.cpp      llmetrics.cpp      llmetricperformancetester.cpp      llmortician.cpp @@ -168,7 +168,6 @@ set(llcommon_HEADER_FILES      lleventemitter.h      llextendedstatus.h      llfasttimer.h -    llfasttimer_class.h      llfile.h      llfindlocale.h      llfixedbuffer.h @@ -197,7 +196,6 @@ set(llcommon_HEADER_FILES      llmd5.h      llmemory.h      llmemorystream.h -    llmemtype.h      llmetrics.h      llmetricperformancetester.h      llmortician.h @@ -249,7 +247,6 @@ set(llcommon_HEADER_FILES      lluuid.h      lluuidhashmap.h      llversionserver.h -    llversionviewer.h      llworkerthread.h      ll_template_cast.h      metaclass.h @@ -340,6 +337,7 @@ if (LL_TESTS)    LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}") +  LL_ADD_INTEGRATION_TEST(lleventcoro "" "${test_libs};${BOOST_CONTEXT_LIBRARY}")    LL_ADD_INTEGRATION_TEST(llprocess "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llleap "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llstreamqueue "" "${test_libs}") diff --git a/indra/llcommon/bitpack.cpp b/indra/llcommon/bitpack.cpp index cdcaba0765..cdcaba0765 100644..100755 --- a/indra/llcommon/bitpack.cpp +++ b/indra/llcommon/bitpack.cpp diff --git a/indra/llcommon/bitpack.h b/indra/llcommon/bitpack.h index 037300dd14..037300dd14 100644..100755 --- a/indra/llcommon/bitpack.h +++ b/indra/llcommon/bitpack.h diff --git a/indra/llcommon/ctype_workaround.h b/indra/llcommon/ctype_workaround.h index 552be9fb90..552be9fb90 100644..100755 --- a/indra/llcommon/ctype_workaround.h +++ b/indra/llcommon/ctype_workaround.h diff --git a/indra/llcommon/doublelinkedlist.h b/indra/llcommon/doublelinkedlist.h index 0aeaa69df3..0aeaa69df3 100644..100755 --- a/indra/llcommon/doublelinkedlist.h +++ b/indra/llcommon/doublelinkedlist.h diff --git a/indra/llcommon/fix_macros.h b/indra/llcommon/fix_macros.h index ef959decff..ef959decff 100644..100755 --- a/indra/llcommon/fix_macros.h +++ b/indra/llcommon/fix_macros.h diff --git a/indra/llcommon/imageids.cpp b/indra/llcommon/imageids.cpp index fe11465221..7d647e5c36 100644..100755 --- a/indra/llcommon/imageids.cpp +++ b/indra/llcommon/imageids.cpp @@ -68,3 +68,6 @@ const LLUUID TERRAIN_MOUNTAIN_DETAIL	("303cd381-8560-7579-23f1-f0a880799740"); /  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 index e0c2683fdc..18c8ecb074 100644..100755 --- a/indra/llcommon/imageids.h +++ b/indra/llcommon/imageids.h @@ -66,4 +66,5 @@ 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..d32ae6c041 100644..100755 --- a/indra/llcommon/indra_constants.cpp +++ b/indra/llcommon/indra_constants.cpp diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 0da83720bd..0da83720bd 100644..100755 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h diff --git a/indra/llcommon/is_approx_equal_fraction.h b/indra/llcommon/is_approx_equal_fraction.h index 4a9b2e2725..4a9b2e2725 100644..100755 --- a/indra/llcommon/is_approx_equal_fraction.h +++ b/indra/llcommon/is_approx_equal_fraction.h diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h index 5cfcdab41c..5cfcdab41c 100644..100755 --- a/indra/llcommon/linden_common.h +++ b/indra/llcommon/linden_common.h diff --git a/indra/llcommon/linked_lists.h b/indra/llcommon/linked_lists.h index 6b25295b7b..6b25295b7b 100644..100755 --- a/indra/llcommon/linked_lists.h +++ b/indra/llcommon/linked_lists.h diff --git a/indra/llcommon/ll_template_cast.h b/indra/llcommon/ll_template_cast.h index c8f9a2f7eb..c8f9a2f7eb 100644..100755 --- a/indra/llcommon/ll_template_cast.h +++ b/indra/llcommon/ll_template_cast.h diff --git a/indra/llcommon/llaccountingcost.h b/indra/llcommon/llaccountingcost.h index 0ef3b50c6d..0ef3b50c6d 100644..100755 --- a/indra/llcommon/llaccountingcost.h +++ b/indra/llcommon/llaccountingcost.h diff --git a/indra/llcommon/llagentconstants.h b/indra/llcommon/llagentconstants.h index cd237da4eb..cd237da4eb 100644..100755 --- a/indra/llcommon/llagentconstants.h +++ b/indra/llcommon/llagentconstants.h diff --git a/indra/llcommon/llallocator.cpp b/indra/llcommon/llallocator.cpp index 87654b5b97..34fc28d8cc 100644..100755 --- a/indra/llcommon/llallocator.cpp +++ b/indra/llcommon/llallocator.cpp @@ -35,28 +35,6 @@  DECLARE_bool(heap_profile_use_stack_trace);  //DECLARE_double(tcmalloc_release_rate); -// static -void LLAllocator::pushMemType(S32 type) -{ -    if(isProfiling()) -    { -    	PushMemType(type); -    } -} - -// static -S32 LLAllocator::popMemType() -{ -    if (isProfiling()) -    { -    	return PopMemType(); -    } -    else -    { -        return -1; -    } -} -  void LLAllocator::setProfilingEnabled(bool should_enable)  {      // NULL disables dumping to disk @@ -94,17 +72,6 @@ std::string LLAllocator::getRawProfile()  // stub implementations for when tcmalloc is disabled  // -// static -void LLAllocator::pushMemType(S32 type) -{ -} - -// static -S32 LLAllocator::popMemType() -{ -    return -1; -} -  void LLAllocator::setProfilingEnabled(bool should_enable)  {  } diff --git a/indra/llcommon/llallocator.h b/indra/llcommon/llallocator.h index a91dd57d14..d26ad73c5b 100644..100755 --- a/indra/llcommon/llallocator.h +++ b/indra/llcommon/llallocator.h @@ -29,16 +29,10 @@  #include <string> -#include "llmemtype.h"  #include "llallocator_heap_profile.h"  class LL_COMMON_API LLAllocator {      friend class LLMemoryView; -    friend class LLMemType; - -private: -	static void pushMemType(S32 type); -	static S32 popMemType();  public:      void setProfilingEnabled(bool should_enable); diff --git a/indra/llcommon/llallocator_heap_profile.cpp b/indra/llcommon/llallocator_heap_profile.cpp index b574ef668b..b574ef668b 100644..100755 --- a/indra/llcommon/llallocator_heap_profile.cpp +++ b/indra/llcommon/llallocator_heap_profile.cpp diff --git a/indra/llcommon/llallocator_heap_profile.h b/indra/llcommon/llallocator_heap_profile.h index 69300b829b..69300b829b 100644..100755 --- a/indra/llcommon/llallocator_heap_profile.h +++ b/indra/llcommon/llallocator_heap_profile.h diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index ca258900c7..67a98d5fb8 100644..100755 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -69,10 +69,16 @@ bool windows_post_minidump_callback(const wchar_t* dump_path,  void setup_signals();  void default_unix_signal_handler(int signum, siginfo_t *info, void *); +#if LL_LINUX +#include "google_breakpad/minidump_descriptor.h" +bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc, void* context, bool succeeded); +#else  // Called by breakpad exception handler after the minidump has been generated.  bool unix_post_minidump_callback(const char *dump_dir,  					  const char *minidump_id,  					  void *context, bool succeeded); +#endif +  # if LL_DARWIN  /* OSX doesn't support SIGRT* */  S32 LL_SMACKDOWN_SIGNAL = SIGUSR1; @@ -313,7 +319,7 @@ void LLApp::setupErrorHandling()  	// Add google breakpad exception handler configured for Darwin/Linux.  	bool installHandler = true; -#ifdef LL_DARWIN +#if LL_DARWIN  	// For the special case of Darwin, we do not want to install the handler if  	// the process is being debugged as the app will exit with value ABRT (6) if  	// we do.  Unfortunately, the code below which performs that test relies on @@ -346,14 +352,21 @@ void LLApp::setupErrorHandling()  		installHandler = true;  	}  	#endif -#endif +  	if(installHandler && (mExceptionHandler == 0))  	{  		std::string dumpPath = "/tmp/"; -		mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, 0, &unix_post_minidump_callback, 0, true); +		mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, 0, &unix_post_minidump_callback, 0, true, 0); +	} +#elif LL_LINUX +	if(installHandler && (mExceptionHandler == 0)) +	{ +		google_breakpad::MinidumpDescriptor desc("/tmp"); +	        new google_breakpad::ExceptionHandler(desc, 0, &unix_minidump_callback, 0, true, 0);  	}  #endif +#endif  	startErrorThread();  } @@ -410,6 +423,9 @@ void LLApp::setMiniDumpDir(const std::string &path)  	wchar_t buffer[MAX_MINDUMP_PATH_LENGTH];  	mbstowcs(buffer, path.c_str(), MAX_MINDUMP_PATH_LENGTH);  	mExceptionHandler->set_dump_path(std::wstring(buffer)); +#elif LL_LINUX +        google_breakpad::MinidumpDescriptor desc(path); +	mExceptionHandler->set_minidump_descriptor(desc);  #else  	mExceptionHandler->set_dump_path(path);  #endif @@ -857,6 +873,43 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)  	}  } +#if LL_LINUX +bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc, void* context, bool succeeded) +{ +	// Copy minidump file path into fixed buffer in the app instance to avoid +	// heap allocations in a crash handler. +	 +	// path format: <dump_dir>/<minidump_id>.dmp +	int dirPathLength = strlen(minidump_desc.path()); +	 +	// The path must not be truncated. +	llassert((dirPathLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH); +	 +	char * path = LLApp::instance()->getMiniDumpFilename(); +	S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; +	strncpy(path, minidump_desc.path(), remaining); +	remaining -= dirPathLength; +	path += dirPathLength; +	if (remaining > 0 && dirPathLength > 0 && path[-1] != '/') +	{ +		*path++ = '/'; +		--remaining; +	} +	 +	llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl; +	LLApp::runErrorHandler(); +	 +#ifndef LL_RELEASE_FOR_DOWNLOAD +	clear_signals(); +	return false; +#else +	return true; +#endif + +} +#endif + +  bool unix_post_minidump_callback(const char *dump_dir,  					  const char *minidump_id,  					  void *context, bool succeeded) @@ -933,9 +986,9 @@ bool windows_post_minidump_callback(const wchar_t* dump_path,  	}  	llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl; -    // *NOTE:Mani - this code is stolen from LLApp, where its never actually used. +   // *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 +   // *TODO: Translate the signals/exceptions into cross-platform stuff  	// Windows implementation  	llinfos << "Entering Windows Exception Handler..." << llendl; diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index a536a06ea5..afa06df23e 100644..100755 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -38,7 +38,7 @@ typedef LLAtomic32<U32> LLAtomicU32;  class LLErrorThread;  class LLLiveFile;  #if LL_LINUX -typedef struct siginfo siginfo_t; +#include <signal.h>  #endif  typedef void (*LLAppErrorHandler)(); diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index d1c44c9403..a0802c6adf 100644..100755 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -226,9 +226,7 @@ void LLVolatileAPRPool::clearVolatileAPRPool()  		llassert_always(mNumActiveRef > 0) ;  	} -	//paranoia check if the pool is jammed. -	//will remove the check before going to release. -	llassert_always(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ; +	llassert(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ;  }  BOOL LLVolatileAPRPool::isFull() diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index 034546c3f3..752574c65d 100644..100755 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -182,8 +182,10 @@ typedef LLAtomic32<S32> LLAtomicS32;  // abbreviated flags  #define LL_APR_R (APR_READ) // "r"  #define LL_APR_W (APR_CREATE|APR_TRUNCATE|APR_WRITE) // "w" +#define LL_APR_A (APR_CREATE|APR_WRITE|APR_APPEND) // "w"  #define LL_APR_RB (APR_READ|APR_BINARY) // "rb"  #define LL_APR_WB (APR_CREATE|APR_TRUNCATE|APR_WRITE|APR_BINARY) // "wb" +#define LL_APR_AB (APR_CREATE|APR_WRITE|APR_BINARY|APR_APPEND)  #define LL_APR_RPB (APR_READ|APR_WRITE|APR_BINARY) // "r+b"  #define LL_APR_WPB (APR_CREATE|APR_TRUNCATE|APR_READ|APR_WRITE|APR_BINARY) // "w+b" diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 5e566d6c7c..5ae2df3994 100644..100755 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -95,6 +95,7 @@ LLAssetDictionary::LLAssetDictionary()  	addEntry(LLAssetType::AT_LINK_FOLDER, 		new AssetEntry("FOLDER_LINK",		"link_f", 	"sym folder link",	false,		false,		true));  	addEntry(LLAssetType::AT_MESH,              new AssetEntry("MESH",              "mesh",     "mesh",             false,      false,      false));  	addEntry(LLAssetType::AT_WIDGET,            new AssetEntry("WIDGET",            "widget",   "widget",           false,      false,      false)); +	addEntry(LLAssetType::AT_PERSON,            new AssetEntry("PERSON",            "person",   "person",           false,      false,      false));  	addEntry(LLAssetType::AT_NONE, 				new AssetEntry("NONE",				"-1",		NULL,		  		FALSE,		FALSE,		FALSE));  }; diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index d538accbf7..69b01731e5 100644..100755 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -112,6 +112,9 @@ public:  		AT_WIDGET = 40,  			// UI Widget: this is *not* an inventory asset type, only a viewer side asset (e.g. button, other ui items...) +		AT_PERSON = 45, +			// A user uuid  which is not an inventory asset type, used in viewer only for adding a person to a chat via drag and drop. +  		AT_MESH = 49,  			// Mesh data in our proprietary SLM format diff --git a/indra/llcommon/llassoclist.h b/indra/llcommon/llassoclist.h index 2950504155..2950504155 100644..100755 --- a/indra/llcommon/llassoclist.h +++ b/indra/llcommon/llassoclist.h diff --git a/indra/llcommon/llavatarconstants.h b/indra/llcommon/llavatarconstants.h index f47f447b45..f47f447b45 100644..100755 --- a/indra/llcommon/llavatarconstants.h +++ b/indra/llcommon/llavatarconstants.h diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp index 3206843bf4..642bd82e90 100644..100755 --- a/indra/llcommon/llavatarname.cpp +++ b/indra/llcommon/llavatarname.cpp @@ -30,6 +30,7 @@  #include "llavatarname.h"  #include "lldate.h" +#include "llframetimer.h"  #include "llsd.h"  // Store these in pre-built std::strings to avoid memory allocations in @@ -42,6 +43,14 @@ static const std::string IS_DISPLAY_NAME_DEFAULT("is_display_name_default");  static const std::string DISPLAY_NAME_EXPIRES("display_name_expires");  static const std::string DISPLAY_NAME_NEXT_UPDATE("display_name_next_update"); +bool LLAvatarName::sUseDisplayNames = true; + +// Minimum time-to-live (in seconds) for a name entry. +// Avatar name should always guarantee to expire reasonably soon by default +// so if the failure to get a valid expiration time was due to something temporary  +// we will eventually request and get the right data. +const F64 MIN_ENTRY_LIFETIME = 60.0; +  LLAvatarName::LLAvatarName()  :	mUsername(),  	mDisplayName(), @@ -61,6 +70,17 @@ bool LLAvatarName::operator<(const LLAvatarName& rhs) const  		return mUsername < rhs.mUsername;  } +//static  +void LLAvatarName::setUseDisplayNames(bool use) +{ +	sUseDisplayNames = use; +} +//static  +bool LLAvatarName::useDisplayNames()  +{  +	return sUseDisplayNames;  +} +  LLSD LLAvatarName::asLLSD() const  {  	LLSD sd; @@ -85,21 +105,75 @@ void LLAvatarName::fromLLSD(const LLSD& sd)  	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 (mUsername.empty() || mIsDisplayNameDefault) -	// If the display name feature is off -	// OR 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. +	if (sUseDisplayNames)  	{ -		name = mDisplayName; +		if (mUsername.empty() || mIsDisplayNameDefault) +		{ +			// If this particular display name is defaulted (i.e. based on user name), +			// then display only the easier to read instance of the person's name. +			name = mDisplayName; +		} +		else +		{ +			name = mDisplayName + " (" + mUsername + ")"; +		}  	}  	else  	{ -		name = mDisplayName + " (" + mUsername + ")"; +		name = getUserName();  	}  	return name;  } @@ -118,3 +192,48 @@ std::string LLAvatarName::getLegacyName() const  	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 index ba258d6d52..5d2fccc5ba 100644..100755 --- a/indra/llcommon/llavatarname.h +++ b/indra/llcommon/llavatarname.h @@ -39,23 +39,67 @@ public:  	bool operator<(const LLAvatarName& rhs) const; +	// Conversion to and from LLSD (cache file or server response)  	LLSD asLLSD() const; -  	void fromLLSD(const LLSD& sd); +	// Used only in legacy mode when the display name capability is not provided server side +	// or to otherwise create a temporary valid item. +	void fromString(const std::string& full_name); +	 +	// Set the name object to become invalid in "expires" seconds from now +	void setExpires(F64 expires); + +	// Set and get the display name flag set by the user in preferences. +	static void setUseDisplayNames(bool use); +	static bool useDisplayNames(); +	 +	// A name object is valid if not temporary and not yet expired (default is expiration not checked) +	bool isValidName(F64 max_unrefreshed = 0.0f) const { return !mIsTemporaryName && (mExpires >= max_unrefreshed); } +	 +	// Return true if the name is made up from legacy or temporary data +	bool isDisplayNameDefault() const { return mIsDisplayNameDefault; } +	  	// For normal names, returns "James Linden (james.linden)"  	// When display names are disabled returns just "James Linden"  	std::string getCompleteName() const; - +	  	// Returns "James Linden" or "bobsmith123 Resident" for backwards  	// compatibility with systems like voice and muting  	// *TODO: Eliminate this in favor of username only  	std::string getLegacyName() const; +	 +	// "José Sanchez" or "James Linden", UTF-8 encoded Unicode +	// Takes the display name preference into account. This is truly the name that should  +	// be used for all UI where an avatar name has to be used unless we truly want something else (rare) +	std::string getDisplayName() const; +	 +	// Returns "James Linden" or "bobsmith123 Resident" +	// Used where we explicitely prefer or need a non UTF-8 legacy (ASCII) name +	// Also used for backwards compatibility with systems like voice and muting +	std::string getUserName() const; +	 +	// Returns "james.linden" or the legacy name for very old names +	std::string getAccountName() const { return mUsername; } +	// Debug print of the object +	void dump() const; +	 +	// Names can change, so need to keep track of when name was +	// last checked. +	// Unix time-from-epoch seconds for efficiency +	F64 mExpires; +	 +	// You can only change your name every N hours, so record +	// when the next update is allowed +	// Unix time-from-epoch seconds +	F64 mNextUpdate; +	 +private:  	// "bobsmith123" or "james.linden", US-ASCII only  	std::string mUsername; -	// "Jose' Sanchez" or "James Linden", UTF-8 encoded Unicode +	// "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; @@ -81,15 +125,9 @@ public:  	// shown in UI, but are not serialized.  	bool mIsTemporaryName; -	// 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; +	// Global flag indicating if display name should be used or not +	// This will affect the output of the high level "get" methods +	static bool sUseDisplayNames;  };  #endif diff --git a/indra/llcommon/llbase32.cpp b/indra/llcommon/llbase32.cpp index 053ac0d32f..053ac0d32f 100644..100755 --- a/indra/llcommon/llbase32.cpp +++ b/indra/llcommon/llbase32.cpp diff --git a/indra/llcommon/llbase32.h b/indra/llcommon/llbase32.h index eeb96d789d..eeb96d789d 100644..100755 --- a/indra/llcommon/llbase32.h +++ b/indra/llcommon/llbase32.h diff --git a/indra/llcommon/llbase64.cpp b/indra/llcommon/llbase64.cpp index 4e82cf7f20..4e82cf7f20 100644..100755 --- a/indra/llcommon/llbase64.cpp +++ b/indra/llcommon/llbase64.cpp diff --git a/indra/llcommon/llbase64.h b/indra/llcommon/llbase64.h index 16d2c217d0..16d2c217d0 100644..100755 --- a/indra/llcommon/llbase64.h +++ b/indra/llcommon/llbase64.h diff --git a/indra/llcommon/llboost.h b/indra/llcommon/llboost.h index 57d958a51a..57d958a51a 100644..100755 --- a/indra/llcommon/llboost.h +++ b/indra/llcommon/llboost.h diff --git a/indra/llcommon/llchat.h b/indra/llcommon/llchat.h index f5b242fdfc..f5b242fdfc 100644..100755 --- a/indra/llcommon/llchat.h +++ b/indra/llcommon/llchat.h diff --git a/indra/llcommon/llclickaction.h b/indra/llcommon/llclickaction.h index 1f87d8eec3..1f87d8eec3 100644..100755 --- a/indra/llcommon/llclickaction.h +++ b/indra/llcommon/llclickaction.h diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 8be9e4f4de..8be9e4f4de 100644..100755 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp diff --git a/indra/llcommon/llcommon.h b/indra/llcommon/llcommon.h index ca9cad5d05..ca9cad5d05 100644..100755 --- a/indra/llcommon/llcommon.h +++ b/indra/llcommon/llcommon.h diff --git a/indra/llcommon/llcommonutils.cpp b/indra/llcommon/llcommonutils.cpp index d82554c202..d82554c202 100644..100755 --- a/indra/llcommon/llcommonutils.cpp +++ b/indra/llcommon/llcommonutils.cpp diff --git a/indra/llcommon/llcommonutils.h b/indra/llcommon/llcommonutils.h index 755dc41fb4..755dc41fb4 100644..100755 --- a/indra/llcommon/llcommonutils.h +++ b/indra/llcommon/llcommonutils.h diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index 0b5829eb7e..baaddcaed1 100644..100755 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -39,7 +39,12 @@  #include "llerror.h"  #include "stringize.h" -LLCoros::LLCoros() +LLCoros::LLCoros(): +    // MAINT-2724: default coroutine stack size too small on Windows. +    // Previously we used +    // boost::context::guarded_stack_allocator::default_stacksize(); +    // empirically this is 64KB on Windows and Linux. Try quadrupling. +    mStackSize(256*1024)  {      // Register our cleanup() method for "mainloop" ticks      LLEventPumps::instance().obtain("mainloop").listen( @@ -55,7 +60,7 @@ bool LLCoros::cleanup(const LLSD&)          // since last tick?          if (mi->second->exited())          { -            LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL; +			   LL_INFOS("LLCoros") << "LLCoros: cleaning up coroutine " << mi->first << LL_ENDL;              // The erase() call will invalidate its passed iterator value --              // so increment mi FIRST -- but pass its original value to              // erase(). This is what postincrement is all about. @@ -89,7 +94,7 @@ std::string LLCoros::generateDistinctName(const std::string& prefix) const      {          if (mCoros.find(name) == mCoros.end())          { -            LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL; +			   LL_INFOS("LLCoros") << "LLCoros: launching coroutine " << name << LL_ENDL;              return name;          }      } @@ -115,7 +120,7 @@ std::string LLCoros::getNameByID(const void* self_id) const      // passed to us comes.      for (CoroMap::const_iterator mi(mCoros.begin()), mend(mCoros.end()); mi != mend; ++mi)      { -        namespace coro_private = boost::coroutines::detail; +        namespace coro_private = boost::dcoroutines::detail;          if (static_cast<void*>(coro_private::coroutine_accessor::get_impl(const_cast<coro&>(*mi->second)).get())              == self_id)          { @@ -125,6 +130,12 @@ std::string LLCoros::getNameByID(const void* self_id) const      return "";  } +void LLCoros::setStackSize(S32 stacksize) +{ +    LL_INFOS("LLCoros") << "Setting coroutine stack size to " << stacksize << LL_ENDL; +    mStackSize = stacksize; +} +  /*****************************************************************************  *   MUST BE LAST  *****************************************************************************/ diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index d75f28ec1a..01ee11da1a 100644..100755 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -29,7 +29,7 @@  #if ! defined(LL_LLCOROS_H)  #define LL_LLCOROS_H -#include <boost/coroutine/coroutine.hpp> +#include <boost/dcoroutine/coroutine.hpp>  #include "llsingleton.h"  #include <boost/ptr_container/ptr_map.hpp>  #include <string> @@ -78,8 +78,8 @@  class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>  {  public: -    /// Canonical boost::coroutines::coroutine signature we use -    typedef boost::coroutines::coroutine<void()> coro; +    /// Canonical boost::dcoroutines::coroutine signature we use +    typedef boost::dcoroutines::coroutine<void()> coro;      /// Canonical 'self' type      typedef coro::self self; @@ -125,7 +125,7 @@ public:      template <typename CALLABLE>      std::string launch(const std::string& prefix, const CALLABLE& callable)      { -        return launchImpl(prefix, new coro(callable)); +        return launchImpl(prefix, new coro(callable, mStackSize));      }      /** @@ -152,6 +152,9 @@ public:      /// getName() by self.get_id()      std::string getNameByID(const void* self_id) const; +    /// for delayed initialization +    void setStackSize(S32 stacksize); +  private:      friend class LLSingleton<LLCoros>;      LLCoros(); @@ -159,6 +162,7 @@ private:      std::string generateDistinctName(const std::string& prefix) const;      bool cleanup(const LLSD&); +    S32 mStackSize;      typedef boost::ptr_map<std::string, coro> CoroMap;      CoroMap mCoros;  }; diff --git a/indra/llcommon/llcrc.cpp b/indra/llcommon/llcrc.cpp index e80da0bb0d..e80da0bb0d 100644..100755 --- a/indra/llcommon/llcrc.cpp +++ b/indra/llcommon/llcrc.cpp diff --git a/indra/llcommon/llcrc.h b/indra/llcommon/llcrc.h index 2d291d92a1..2d291d92a1 100644..100755 --- a/indra/llcommon/llcrc.h +++ b/indra/llcommon/llcrc.h diff --git a/indra/llcommon/llcriticaldamp.cpp b/indra/llcommon/llcriticaldamp.cpp index 87d79b1ee0..87d79b1ee0 100644..100755 --- a/indra/llcommon/llcriticaldamp.cpp +++ b/indra/llcommon/llcriticaldamp.cpp diff --git a/indra/llcommon/llcriticaldamp.h b/indra/llcommon/llcriticaldamp.h index 52f052ae25..52f052ae25 100644..100755 --- a/indra/llcommon/llcriticaldamp.h +++ b/indra/llcommon/llcriticaldamp.h diff --git a/indra/llcommon/llcursortypes.cpp b/indra/llcommon/llcursortypes.cpp index ec60097195..ec60097195 100644..100755 --- a/indra/llcommon/llcursortypes.cpp +++ b/indra/llcommon/llcursortypes.cpp diff --git a/indra/llcommon/llcursortypes.h b/indra/llcommon/llcursortypes.h index cb6d6636a0..cb6d6636a0 100644..100755 --- a/indra/llcommon/llcursortypes.h +++ b/indra/llcommon/llcursortypes.h diff --git a/indra/llcommon/lldarray.h b/indra/llcommon/lldarray.h index 131b819c99..131b819c99 100644..100755 --- a/indra/llcommon/lldarray.h +++ b/indra/llcommon/lldarray.h diff --git a/indra/llcommon/lldarrayptr.h b/indra/llcommon/lldarrayptr.h index c9a0b204d1..c9a0b204d1 100644..100755 --- a/indra/llcommon/lldarrayptr.h +++ b/indra/llcommon/lldarrayptr.h diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index 030ef6a3c7..030ef6a3c7 100644..100755 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index 7ff8b550ad..7ff8b550ad 100644..100755 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h index 5a4b8325f4..5a4b8325f4 100644..100755 --- a/indra/llcommon/lldefs.h +++ b/indra/llcommon/lldefs.h diff --git a/indra/llcommon/lldeleteutils.h b/indra/llcommon/lldeleteutils.h index f250dc3028..f250dc3028 100644..100755 --- a/indra/llcommon/lldeleteutils.h +++ b/indra/llcommon/lldeleteutils.h diff --git a/indra/llcommon/lldependencies.cpp b/indra/llcommon/lldependencies.cpp index 0e72c175cb..0e72c175cb 100644..100755 --- a/indra/llcommon/lldependencies.cpp +++ b/indra/llcommon/lldependencies.cpp diff --git a/indra/llcommon/lldependencies.h b/indra/llcommon/lldependencies.h index e0294e271b..e0294e271b 100644..100755 --- a/indra/llcommon/lldependencies.h +++ b/indra/llcommon/lldependencies.h diff --git a/indra/llcommon/lldepthstack.h b/indra/llcommon/lldepthstack.h index d9db54efc7..d9db54efc7 100644..100755 --- a/indra/llcommon/lldepthstack.h +++ b/indra/llcommon/lldepthstack.h diff --git a/indra/llcommon/lldictionary.cpp b/indra/llcommon/lldictionary.cpp index e16c35ed6a..e16c35ed6a 100644..100755 --- a/indra/llcommon/lldictionary.cpp +++ b/indra/llcommon/lldictionary.cpp diff --git a/indra/llcommon/lldictionary.h b/indra/llcommon/lldictionary.h index bc3bc3e74a..c752859a36 100644..100755 --- a/indra/llcommon/lldictionary.h +++ b/indra/llcommon/lldictionary.h @@ -30,6 +30,8 @@  #include <map>  #include <string> +#include "llerror.h" +  struct LL_COMMON_API LLDictionaryEntry  {  	LLDictionaryEntry(const std::string &name); diff --git a/indra/llcommon/lldlinked.h b/indra/llcommon/lldlinked.h index 3f7c197be7..3f7c197be7 100644..100755 --- a/indra/llcommon/lldlinked.h +++ b/indra/llcommon/lldlinked.h diff --git a/indra/llcommon/lldoubledispatch.h b/indra/llcommon/lldoubledispatch.h index 8ed295b6f1..8ed295b6f1 100644..100755 --- a/indra/llcommon/lldoubledispatch.h +++ b/indra/llcommon/lldoubledispatch.h diff --git a/indra/llcommon/lldqueueptr.h b/indra/llcommon/lldqueueptr.h index 9fe08191e1..9fe08191e1 100644..100755 --- a/indra/llcommon/lldqueueptr.h +++ b/indra/llcommon/lldqueueptr.h diff --git a/indra/llcommon/llendianswizzle.h b/indra/llcommon/llendianswizzle.h index 4c08074a9c..4c08074a9c 100644..100755 --- a/indra/llcommon/llendianswizzle.h +++ b/indra/llcommon/llendianswizzle.h diff --git a/indra/llcommon/llenum.h b/indra/llcommon/llenum.h index f57b2bc0b5..f57b2bc0b5 100644..100755 --- a/indra/llcommon/llenum.h +++ b/indra/llcommon/llenum.h diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 9b0141eb76..d2af004cde 100644..100755 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -201,10 +201,7 @@ namespace {  		virtual void recordMessage(LLError::ELevel level,  								   const std::string& message)  		{ -			llutf16string utf16str = -				wstring_to_utf16str(utf8str_to_wstring(message)); -			utf16str += '\n'; -			OutputDebugString(utf16str.c_str()); +			LL_WINDOWS_OUTPUT_DEBUG(message);  		}  	};  #endif @@ -1401,5 +1398,27 @@ 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 b65b410153..0b723aeb5d 100644..100755 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -34,7 +34,6 @@  #include "llerrorlegacy.h"  #include "stdtypes.h" -  /** Error Logging Facility  	Information for most users: @@ -199,8 +198,20 @@ 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 \ diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index 480654b1a2..480654b1a2 100644..100755 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h index 37cee579cd..37cee579cd 100644..100755 --- a/indra/llcommon/llerrorlegacy.h +++ b/indra/llcommon/llerrorlegacy.h diff --git a/indra/llcommon/llerrorthread.cpp b/indra/llcommon/llerrorthread.cpp index 950fcd6e83..950fcd6e83 100644..100755 --- a/indra/llcommon/llerrorthread.cpp +++ b/indra/llcommon/llerrorthread.cpp diff --git a/indra/llcommon/llerrorthread.h b/indra/llcommon/llerrorthread.h index 474cef3a50..474cef3a50 100644..100755 --- a/indra/llcommon/llerrorthread.h +++ b/indra/llcommon/llerrorthread.h diff --git a/indra/llcommon/llevent.cpp b/indra/llcommon/llevent.cpp index 633df01588..633df01588 100644..100755 --- a/indra/llcommon/llevent.cpp +++ b/indra/llcommon/llevent.cpp diff --git a/indra/llcommon/llevent.h b/indra/llcommon/llevent.h index 8cd682b8bf..8cd682b8bf 100644..100755 --- a/indra/llcommon/llevent.h +++ b/indra/llcommon/llevent.h diff --git a/indra/llcommon/lleventapi.cpp b/indra/llcommon/lleventapi.cpp index ff5459c1eb..ff5459c1eb 100644..100755 --- a/indra/llcommon/lleventapi.cpp +++ b/indra/llcommon/lleventapi.cpp diff --git a/indra/llcommon/lleventapi.h b/indra/llcommon/lleventapi.h index 1a37d780b6..1a37d780b6 100644..100755 --- a/indra/llcommon/lleventapi.h +++ b/indra/llcommon/lleventapi.h diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp index 81cc33fbba..81cc33fbba 100644..100755 --- a/indra/llcommon/lleventcoro.cpp +++ b/indra/llcommon/lleventcoro.cpp diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h index 88a5e6ec74..a42af63b65 100644..100755 --- a/indra/llcommon/lleventcoro.h +++ b/indra/llcommon/lleventcoro.h @@ -29,8 +29,8 @@  #if ! defined(LL_LLEVENTCORO_H)  #define LL_LLEVENTCORO_H -#include <boost/coroutine/coroutine.hpp> -#include <boost/coroutine/future.hpp> +#include <boost/dcoroutine/coroutine.hpp> +#include <boost/dcoroutine/future.hpp>  #include <boost/optional.hpp>  #include <string>  #include <stdexcept> @@ -206,13 +206,13 @@ LLSD postAndWait(SELF& self, const LLSD& event, const LLEventPumpOrPumpName& req                   const LLEventPumpOrPumpName& replyPump, const LLSD& replyPumpNamePath=LLSD())  {      // declare the future -    boost::coroutines::future<LLSD> future(self); +    boost::dcoroutines::future<LLSD> future(self);      // make a callback that will assign a value to the future, and listen on      // the specified LLEventPump with that callback      std::string listenerName(LLEventDetail::listenerNameForCoro(self));      LLTempBoundListener connection(          replyPump.getPump().listen(listenerName, -                                   voidlistener(boost::coroutines::make_callback(future)))); +                                   voidlistener(boost::dcoroutines::make_callback(future))));      // skip the "post" part if requestPump is default-constructed      if (requestPump)      { @@ -257,7 +257,7 @@ namespace LLEventDetail       * This helper is specifically for the two-pump version of waitForEventOn().       * We use a single future object, but we want to listen on two pumps with it.       * Since we must still adapt from (the callable constructed by) -     * boost::coroutines::make_callback() (void return) to provide an event +     * boost::dcoroutines::make_callback() (void return) to provide an event       * listener (bool return), we've adapted LLVoidListener for the purpose. The       * basic idea is that we construct a distinct instance of WaitForEventOnHelper       * -- binding different instance data -- for each of the pumps. Then, when a @@ -331,16 +331,16 @@ LLEventWithID postAndWait2(SELF& self, const LLSD& event,                             const LLSD& replyPump1NamePath=LLSD())  {      // declare the future -    boost::coroutines::future<LLEventWithID> future(self); +    boost::dcoroutines::future<LLEventWithID> future(self);      // either callback will assign a value to this future; listen on      // each specified LLEventPump with a callback      std::string name(LLEventDetail::listenerNameForCoro(self));      LLTempBoundListener connection0(          replyPump0.getPump().listen(name + "a", -                               LLEventDetail::wfeoh(boost::coroutines::make_callback(future), 0))); +                               LLEventDetail::wfeoh(boost::dcoroutines::make_callback(future), 0)));      LLTempBoundListener connection1(          replyPump1.getPump().listen(name + "b", -                               LLEventDetail::wfeoh(boost::coroutines::make_callback(future), 1))); +                               LLEventDetail::wfeoh(boost::dcoroutines::make_callback(future), 1)));      // skip the "post" part if requestPump is default-constructed      if (requestPump)      { diff --git a/indra/llcommon/lleventdispatcher.cpp b/indra/llcommon/lleventdispatcher.cpp index 5b6d4efbe9..5b6d4efbe9 100644..100755 --- a/indra/llcommon/lleventdispatcher.cpp +++ b/indra/llcommon/lleventdispatcher.cpp diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h index 7acc61de4e..7acc61de4e 100644..100755 --- a/indra/llcommon/lleventdispatcher.h +++ b/indra/llcommon/lleventdispatcher.h diff --git a/indra/llcommon/lleventemitter.h b/indra/llcommon/lleventemitter.h index cd82fc56f9..cd82fc56f9 100644..100755 --- a/indra/llcommon/lleventemitter.h +++ b/indra/llcommon/lleventemitter.h diff --git a/indra/llcommon/lleventfilter.cpp b/indra/llcommon/lleventfilter.cpp index d36a107254..d36a107254 100644..100755 --- a/indra/llcommon/lleventfilter.cpp +++ b/indra/llcommon/lleventfilter.cpp diff --git a/indra/llcommon/lleventfilter.h b/indra/llcommon/lleventfilter.h index e822a664f5..e822a664f5 100644..100755 --- a/indra/llcommon/lleventfilter.h +++ b/indra/llcommon/lleventfilter.h diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 0855180dcd..0855180dcd 100644..100755 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index 65b0fef354..65b0fef354 100644..100755 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h diff --git a/indra/llcommon/lleventtimer.cpp b/indra/llcommon/lleventtimer.cpp index 0d96e03da4..0d96e03da4 100644..100755 --- a/indra/llcommon/lleventtimer.cpp +++ b/indra/llcommon/lleventtimer.cpp diff --git a/indra/llcommon/lleventtimer.h b/indra/llcommon/lleventtimer.h index 7f42623d01..7f42623d01 100644..100755 --- a/indra/llcommon/lleventtimer.h +++ b/indra/llcommon/lleventtimer.h diff --git a/indra/llcommon/llextendedstatus.h b/indra/llcommon/llextendedstatus.h index 8ce173d1ff..8ce173d1ff 100644..100755 --- a/indra/llcommon/llextendedstatus.h +++ b/indra/llcommon/llextendedstatus.h diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer.cpp index 463f558c2c..024fdd1b4d 100644..100755 --- a/indra/llcommon/llfasttimer_class.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -1,5 +1,5 @@  /**  - * @file llfasttimer_class.cpp + * @file llfasttimer.cpp   * @brief Implementation of the fast timer.   *   * $LicenseInfo:firstyear=2004&license=viewerlgpl$ @@ -64,19 +64,12 @@ BOOL LLFastTimer::sMetricLog = FALSE;  LLMutex* LLFastTimer::sLogLock = NULL;  std::queue<LLSD> LLFastTimer::sLogQueue; -#define USE_RDTSC 0 -  #if LL_LINUX || LL_SOLARIS  U64 LLFastTimer::sClockResolution = 1000000000; // Nanosecond resolution  #else  U64 LLFastTimer::sClockResolution = 1000000; // Microsecond resolution  #endif -std::vector<LLFastTimer::FrameState>* LLFastTimer::sTimerInfos = NULL; -U64				LLFastTimer::sTimerCycles = 0; -U32				LLFastTimer::sTimerCalls = 0; - -  // FIXME: move these declarations to the relevant modules  // helper functions @@ -109,52 +102,35 @@ static timer_tree_dfs_iterator_t end_timer_tree()  	return timer_tree_dfs_iterator_t();   } - -  // factory class that creates NamedTimers via static DeclareTimer objects  class NamedTimerFactory : public LLSingleton<NamedTimerFactory>  {  public:  	NamedTimerFactory() -		: mActiveTimerRoot(NULL), -		  mTimerRoot(NULL), -		  mAppTimer(NULL), -		  mRootFrameState(NULL) +	:	mTimerRoot(NULL)  	{}  	/*virtual */ void initSingleton()  	{  		mTimerRoot = new LLFastTimer::NamedTimer("root"); - -		mActiveTimerRoot = new LLFastTimer::NamedTimer("Frame"); -		mActiveTimerRoot->setCollapsed(false); - -		mRootFrameState = new LLFastTimer::FrameState(mActiveTimerRoot); -		mRootFrameState->mParent = &mTimerRoot->getFrameState(); -		mActiveTimerRoot->setParent(mTimerRoot); - -		mAppTimer = new LLFastTimer(mRootFrameState); +		mRootFrameState.setNamedTimer(mTimerRoot); +		mTimerRoot->setFrameState(&mRootFrameState); +		mTimerRoot->mParent = mTimerRoot; +		mTimerRoot->setCollapsed(false); +		mRootFrameState.mParent = &mRootFrameState;  	}  	~NamedTimerFactory()  	{  		std::for_each(mTimers.begin(), mTimers.end(), DeletePairedPointer()); -		delete mAppTimer; -		delete mActiveTimerRoot;   		delete mTimerRoot; -		delete mRootFrameState;  	} -	LLFastTimer::NamedTimer& createNamedTimer(const std::string& name) +	LLFastTimer::NamedTimer& createNamedTimer(const std::string& name, LLFastTimer::FrameState* state)  	{ -		timer_map_t::iterator found_it = mTimers.find(name); -		if (found_it != mTimers.end()) -		{ -			return *found_it->second; -		} -  		LLFastTimer::NamedTimer* timer = new LLFastTimer::NamedTimer(name); +		timer->setFrameState(state);  		timer->setParent(mTimerRoot);  		mTimers.insert(std::make_pair(name, timer)); @@ -171,12 +147,9 @@ public:  		return NULL;  	} -	LLFastTimer::NamedTimer* getActiveRootTimer() { return mActiveTimerRoot; }  	LLFastTimer::NamedTimer* getRootTimer() { return mTimerRoot; } -	const LLFastTimer* getAppTimer() { return mAppTimer; } -	LLFastTimer::FrameState& getRootFrameState() { return *mRootFrameState; } -	typedef std::map<std::string, LLFastTimer::NamedTimer*> timer_map_t; +	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(); } @@ -184,55 +157,19 @@ public:  private:  	timer_map_t mTimers; -	LLFastTimer::NamedTimer*		mActiveTimerRoot;  	LLFastTimer::NamedTimer*		mTimerRoot; -	LLFastTimer*						mAppTimer; -	LLFastTimer::FrameState*		mRootFrameState; +	LLFastTimer::FrameState			mRootFrameState;  }; -void update_cached_pointers_if_changed() -{ -	// detect when elements have moved and update cached pointers -	static LLFastTimer::FrameState* sFirstTimerAddress = NULL; -	if (&*(LLFastTimer::getFrameStateList().begin()) != sFirstTimerAddress) -	{ -		LLFastTimer::DeclareTimer::updateCachedPointers(); -	} -	sFirstTimerAddress = &*(LLFastTimer::getFrameStateList().begin()); -} -  LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name, bool open ) -:	mTimer(NamedTimerFactory::instance().createNamedTimer(name)) +:	mTimer(NamedTimerFactory::instance().createNamedTimer(name, &mFrameState))  {  	mTimer.setCollapsed(!open); -	mFrameState = &mTimer.getFrameState(); -	update_cached_pointers_if_changed();  }  LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name) -:	mTimer(NamedTimerFactory::instance().createNamedTimer(name)) +:	mTimer(NamedTimerFactory::instance().createNamedTimer(name, &mFrameState))  { -	mFrameState = &mTimer.getFrameState(); -	update_cached_pointers_if_changed(); -} - -// static -void LLFastTimer::DeclareTimer::updateCachedPointers() -{ -	// propagate frame state pointers to timer declarations -	for (instance_iter it = beginInstances(); it != endInstances(); ++it) -	{ -		// update cached pointer -		it->mFrameState = &it->mTimer.getFrameState(); -	} - -	// also update frame states of timers on stack -	LLFastTimer* cur_timerp = LLFastTimer::sCurTimerData.mCurTimer; -	while(cur_timerp->mLastTimerData.mCurTimer != cur_timerp)	 -	{ -		cur_timerp->mFrameState = &cur_timerp->mFrameState->mTimer->getFrameState(); -		cur_timerp = cur_timerp->mLastTimerData.mCurTimer; -	}  }  //static @@ -244,7 +181,7 @@ U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer  #else // windows or x86-mac or x86-linux or x86-solaris  U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer  { -#if USE_RDTSC || !LL_WINDOWS +#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); @@ -265,14 +202,13 @@ U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer  }  #endif -LLFastTimer::FrameState::FrameState(LLFastTimer::NamedTimer* timerp) +LLFastTimer::FrameState::FrameState()  :	mActiveCount(0),  	mCalls(0),  	mSelfTimeCounter(0),  	mParent(NULL),  	mLastCaller(NULL), -	mMoveUpTree(false), -	mTimer(timerp) +	mMoveUpTree(false)  {} @@ -283,12 +219,9 @@ LLFastTimer::NamedTimer::NamedTimer(const std::string& name)  	mTotalTimeCounter(0),  	mCountAverage(0),  	mCallAverage(0), -	mNeedsSorting(false) +	mNeedsSorting(false), +	mFrameState(NULL)  { -	info_list_t& frame_state_list = getFrameStateList(); -	mFrameStateIndex = frame_state_list.size(); -	getFrameStateList().push_back(FrameState(this)); -  	mCountHistory = new U32[HISTORY_NUM];  	memset(mCountHistory, 0, sizeof(U32) * HISTORY_NUM);  	mCallHistory = new U32[HISTORY_NUM]; @@ -355,6 +288,7 @@ S32 LLFastTimer::NamedTimer::getDepth()  	while(timerp)  	{  		depth++; +		if (timerp->getParent() == timerp) break;  		timerp = timerp->mParent;  	}  	return depth; @@ -369,15 +303,6 @@ void LLFastTimer::NamedTimer::processTimes()  	accumulateTimings();  } -// sort timer info structs by depth first traversal order -struct SortTimersDFS -{ -	bool operator()(const LLFastTimer::FrameState& i1, const LLFastTimer::FrameState& i2) -	{ -		return i1.mTimer->getFrameStateIndex() < i2.mTimer->getFrameStateIndex(); -	} -}; -  // sort child timers by name  struct SortTimerByName  { @@ -425,8 +350,8 @@ void LLFastTimer::NamedTimer::buildHierarchy()  		{  			// since ancestors have already been visited, reparenting won't affect tree traversal  			//step up tree, bringing our descendants with us -			//llinfos << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() << -			//	" to child of " << timerp->getParent()->getParent()->getName() << llendl; +			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; @@ -458,7 +383,7 @@ void LLFastTimer::NamedTimer::accumulateTimings()  	LLFastTimer* cur_timer = sCurTimerData.mCurTimer;  	// root defined by parent pointing to self  	CurTimerData* cur_data = &sCurTimerData; -	while(cur_timer->mLastTimerData.mCurTimer != cur_timer) +	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; @@ -473,7 +398,7 @@ void LLFastTimer::NamedTimer::accumulateTimings()  	}  	// traverse tree in DFS post order, or bottom up -	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getActiveRootTimer()); +	for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getRootTimer());  		it != end_timer_tree_bottom_up();  		++it)  	{ @@ -507,12 +432,12 @@ void LLFastTimer::NamedTimer::resetFrame()  		static S32 call_count = 0;  		if (call_count % 100 == 0)  		{ -			llinfos << "countsPerSecond (32 bit): " << countsPerSecond() << llendl; -			llinfos << "get_clock_count (64 bit): " << get_clock_count() << llendl; -			llinfos << "LLProcessorInfo().getCPUFrequency() " << LLProcessorInfo().getCPUFrequency() << llendl; -			llinfos << "getCPUClockCount32() " << getCPUClockCount32() << llendl; -			llinfos << "getCPUClockCount64() " << getCPUClockCount64() << llendl; -			llinfos << "elapsed sec " << ((F64)getCPUClockCount64())/((F64)LLProcessorInfo().getCPUFrequency()*1000000.0) << llendl; +			LL_DEBUGS("FastTimers") << "countsPerSecond (32 bit): " << countsPerSecond() << LL_ENDL; +			LL_DEBUGS("FastTimers") << "get_clock_count (64 bit): " << get_clock_count() << llendl; +			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;  		}  		call_count++; @@ -544,48 +469,22 @@ void LLFastTimer::NamedTimer::resetFrame()  		}  	} - -	// tag timers by position in depth first traversal of tree -	S32 index = 0; -	for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer()); -		it != end_timer_tree(); -		++it) -	{ -		NamedTimer* timerp = (*it); -		 -		timerp->mFrameStateIndex = index; -		index++; - -		llassert_always(timerp->mFrameStateIndex < (S32)getFrameStateList().size()); -	} - -	// sort timers by DFS traversal order to improve cache coherency -	std::sort(getFrameStateList().begin(), getFrameStateList().end(), SortTimersDFS()); - -	// update pointers into framestatelist now that we've sorted it -	DeclareTimer::updateCachedPointers(); -  	// reset for next frame +	for (instance_iter it = beginInstances(); it != endInstances(); ++it)  	{ -		for (instance_iter it = beginInstances(); it != endInstances(); ++it) -		{ -			NamedTimer& timer = *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(); -			} +		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();  		}  	} - -	//sTimerCycles = 0; -	//sTimerCalls = 0;  }  //static @@ -600,7 +499,7 @@ void LLFastTimer::NamedTimer::reset()  	// root defined by parent pointing to self  	CurTimerData* cur_data = &sCurTimerData;  	LLFastTimer* cur_timer = cur_data->mCurTimer; -	while(cur_timer->mLastTimerData.mCurTimer != cur_timer) +	while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)  	{  		cur_timer->mStartTime = cur_time;  		cur_data->mChildTime = 0; @@ -630,17 +529,6 @@ void LLFastTimer::NamedTimer::reset()  	sCurFrameIndex = 0;  } -//static  -LLFastTimer::info_list_t& LLFastTimer::getFrameStateList()  -{  -	if (!sTimerInfos)  -	{  -		sTimerInfos = new info_list_t();  -	}  -	return *sTimerInfos;  -} - -  U32 LLFastTimer::NamedTimer::getHistoricalCount(S32 history_index) const  {  	S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM; @@ -655,18 +543,7 @@ U32 LLFastTimer::NamedTimer::getHistoricalCalls(S32 history_index ) const  LLFastTimer::FrameState& LLFastTimer::NamedTimer::getFrameState() const  { -	llassert_always(mFrameStateIndex >= 0); -	if (this == NamedTimerFactory::instance().getActiveRootTimer())  -	{ -		return NamedTimerFactory::instance().getRootFrameState(); -	} -	return getFrameStateList()[mFrameStateIndex]; -} - -// static -LLFastTimer::NamedTimer& LLFastTimer::NamedTimer::getRootNamedTimer() -{  -	return *NamedTimerFactory::instance().getActiveRootTimer();  +	return *mFrameState;  }  std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::beginChildren() @@ -685,6 +562,12 @@ std::vector<LLFastTimer::NamedTimer*>& LLFastTimer::NamedTimer::getChildren()  }  //static +LLFastTimer::NamedTimer& LLFastTimer::NamedTimer::getRootNamedTimer() +{ +        return *NamedTimerFactory::instance().getRootTimer(); +} + +//static  void LLFastTimer::nextFrame()  {  	countsPerSecond(); // good place to calculate clock frequency @@ -777,145 +660,3 @@ LLFastTimer::LLFastTimer(LLFastTimer::FrameState* state)  } -////////////////////////////////////////////////////////////////////////////// -// -// Important note: These implementations must be FAST! -// - - -#if LL_WINDOWS -// -// Windows implementation of CPU clock -// - -// -// NOTE: put back in when we aren't using platform sdk anymore -// -// because MS has different signatures for these functions in winnt.h -// need to rename them to avoid conflicts -//#define _interlockedbittestandset _renamed_interlockedbittestandset -//#define _interlockedbittestandreset _renamed_interlockedbittestandreset -//#include <intrin.h> -//#undef _interlockedbittestandset -//#undef _interlockedbittestandreset - -//inline U32 LLFastTimer::getCPUClockCount32() -//{ -//	U64 time_stamp = __rdtsc(); -//	return (U32)(time_stamp >> 8); -//} -// -//// return full timer value, *not* shifted by 8 bits -//inline U64 LLFastTimer::getCPUClockCount64() -//{ -//	return __rdtsc(); -//} - -// shift off lower 8 bits for lower resolution but longer term timing -// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing -#if USE_RDTSC -U32 LLFastTimer::getCPUClockCount32() -{ -	U32 ret_val; -	__asm -	{ -        _emit   0x0f -        _emit   0x31 -		shr eax,8 -		shl edx,24 -		or eax, edx -		mov dword ptr [ret_val], eax -	} -    return ret_val; -} - -// return full timer value, *not* shifted by 8 bits -U64 LLFastTimer::getCPUClockCount64() -{ -	U64 ret_val; -	__asm -	{ -        _emit   0x0f -        _emit   0x31 -		mov eax,eax -		mov edx,edx -		mov dword ptr [ret_val+4], edx -		mov dword ptr [ret_val], eax -	} -    return ret_val; -} - -std::string LLFastTimer::sClockType = "rdtsc"; - -#else -//LL_COMMON_API U64 get_clock_count(); // in lltimer.cpp -// These use QueryPerformanceCounter, which is arguably fine and also works on AMD architectures. -U32 LLFastTimer::getCPUClockCount32() -{ -	return (U32)(get_clock_count()>>8); -} - -U64 LLFastTimer::getCPUClockCount64() -{ -	return get_clock_count(); -} - -std::string LLFastTimer::sClockType = "QueryPerformanceCounter"; -#endif - -#endif - - -#if (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__)) -// -// Linux and Solaris implementation of CPU clock - non-x86. -// This is accurate but SLOW!  Only use out of desperation. -// -// Try to use the MONOTONIC clock if available, this is a constant time counter -// with nanosecond resolution (but not necessarily accuracy) and attempts are -// made to synchronize this value between cores at kernel start. It should not -// be affected by CPU frequency. If not available use the REALTIME clock, but -// this may be affected by NTP adjustments or other user activity affecting -// the system time. -U64 LLFastTimer::getCPUClockCount64() -{ -	struct timespec tp; -	 -#ifdef CLOCK_MONOTONIC // MONOTONIC supported at build-time? -	if (-1 == clock_gettime(CLOCK_MONOTONIC,&tp)) // if MONOTONIC isn't supported at runtime then ouch, try REALTIME -#endif -		clock_gettime(CLOCK_REALTIME,&tp); - -	return (tp.tv_sec*LLFastTimer::sClockResolution)+tp.tv_nsec;         -} - -U32 LLFastTimer::getCPUClockCount32() -{ -	return (U32)(LLFastTimer::getCPUClockCount64() >> 8); -} - -std::string LLFastTimer::sClockType = "clock_gettime"; - -#endif // (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__)) - - -#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__)) -// -// Mac+Linux+Solaris FAST x86 implementation of CPU clock -U32 LLFastTimer::getCPUClockCount32() -{ -	U64 x; -	__asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); -	return (U32)(x >> 8); -} - -U64 LLFastTimer::getCPUClockCount64() -{ -	U64 x; -	__asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); -	return x; -} - -std::string LLFastTimer::sClockType = "rdtsc"; -#endif - diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 2b25f2fabb..81c4b78775 100644..100755 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -1,6 +1,6 @@  /**   * @file llfasttimer.h - * @brief Inline implementations of fast timers. + * @brief Declaration of a fast timer.   *   * $LicenseInfo:firstyear=2004&license=viewerlgpl$   * Second Life Viewer Source Code @@ -27,9 +27,365 @@  #ifndef LL_FASTTIMER_H  #define LL_FASTTIMER_H -// Implementation of getCPUClockCount32() and getCPUClockCount64 are now in llfastertimer_class.cpp. +#include "llinstancetracker.h" -// pull in the actual class definition -#include "llfasttimer_class.h" +#define FAST_TIMER_ON 1 +#define DEBUG_FAST_TIMER_THREADS 1 + +class LLMutex; + +#include <queue> +#include "llsd.h" + +#define LL_FASTTIMER_USE_RDTSC 1 + + +LL_COMMON_API void assert_main_thread(); + +class LL_COMMON_API LLFastTimer +{ +public: +	class NamedTimer; + +	struct LL_COMMON_API FrameState +	{ +		FrameState(); +		void setNamedTimer(NamedTimer* timerp) { mTimer = timerp; } + +		U32 				mSelfTimeCounter; +		U32 				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 +	} + +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(); + +	// dumps current cumulative frame stats to log +	// call nextFrame() to reset timers +	static void dumpCurTimes(); + +	// call this to reset timer hierarchy, averages, etc. +	static void reset(); + +	static 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! +	// + + +#if LL_WINDOWS +	// +	// Windows implementation of CPU clock +	// + +	// +	// NOTE: put back in when we aren't using platform sdk anymore +	// +	// because MS has different signatures for these functions in winnt.h +	// need to rename them to avoid conflicts +	//#define _interlockedbittestandset _renamed_interlockedbittestandset +	//#define _interlockedbittestandreset _renamed_interlockedbittestandreset +	//#include <intrin.h> +	//#undef _interlockedbittestandset +	//#undef _interlockedbittestandreset + +	//inline U32 LLFastTimer::getCPUClockCount32() +	//{ +	//	U64 time_stamp = __rdtsc(); +	//	return (U32)(time_stamp >> 8); +	//} +	// +	//// return full timer value, *not* shifted by 8 bits +	//inline U64 LLFastTimer::getCPUClockCount64() +	//{ +	//	return __rdtsc(); +	//} + +	// shift off lower 8 bits for lower resolution but longer term timing +	// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing +#if LL_FASTTIMER_USE_RDTSC +	static U32 getCPUClockCount32() +	{ +		U32 ret_val; +		__asm +		{ +			_emit   0x0f +				_emit   0x31 +				shr eax,8 +				shl edx,24 +				or eax, edx +				mov dword ptr [ret_val], eax +		} +		return ret_val; +	} + +	// return full timer value, *not* shifted by 8 bits +	static U64 getCPUClockCount64() +	{ +		U64 ret_val; +		__asm +		{ +			_emit   0x0f +				_emit   0x31 +				mov eax,eax +				mov edx,edx +				mov dword ptr [ret_val+4], edx +				mov dword ptr [ret_val], eax +		} +		return ret_val; +	} + +#else +	//LL_COMMON_API U64 get_clock_count(); // in lltimer.cpp +	// These use QueryPerformanceCounter, which is arguably fine and also works on AMD architectures. +	static U32 getCPUClockCount32() +	{ +		return (U32)(get_clock_count()>>8); +	} + +	static U64 getCPUClockCount64() +	{ +		return get_clock_count(); +	} + +#endif + +#endif + + +#if (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__)) +	// +	// Linux and Solaris implementation of CPU clock - non-x86. +	// This is accurate but SLOW!  Only use out of desperation. +	// +	// Try to use the MONOTONIC clock if available, this is a constant time counter +	// with nanosecond resolution (but not necessarily accuracy) and attempts are +	// made to synchronize this value between cores at kernel start. It should not +	// be affected by CPU frequency. If not available use the REALTIME clock, but +	// this may be affected by NTP adjustments or other user activity affecting +	// the system time. +	static U64 getCPUClockCount64() +	{ +		struct timespec tp; + +#ifdef CLOCK_MONOTONIC // MONOTONIC supported at build-time? +		if (-1 == clock_gettime(CLOCK_MONOTONIC,&tp)) // if MONOTONIC isn't supported at runtime then ouch, try REALTIME +#endif +			clock_gettime(CLOCK_REALTIME,&tp); + +		return (tp.tv_sec*sClockResolution)+tp.tv_nsec;         +	} + +	static U32 getCPUClockCount32() +	{ +		return (U32)(getCPUClockCount64() >> 8); +	} + +#endif // (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__)) + + +#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__)) +	// +	// Mac+Linux+Solaris FAST x86 implementation of CPU clock +	static U32 getCPUClockCount32() +	{ +		U64 x; +		__asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); +		return (U32)(x >> 8); +	} + +	static U64 getCPUClockCount64() +	{ +		U64 x; +		__asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); +		return x; +	} + +#endif + +	static U64 sClockResolution; + +	static S32				sCurFrameIndex; +	static S32				sLastFrameIndex; +	static U64				sLastFrameTime; + +	U32							mStartTime; +	LLFastTimer::FrameState*	mFrameState; +	LLFastTimer::CurTimerData	mLastTimerData; + +}; + +typedef class LLFastTimer LLFastTimer;  #endif // LL_LLFASTTIMER_H diff --git a/indra/llcommon/llfasttimer_class.h b/indra/llcommon/llfasttimer_class.h deleted file mode 100644 index f481e968a6..0000000000 --- a/indra/llcommon/llfasttimer_class.h +++ /dev/null @@ -1,276 +0,0 @@ -/** - * @file llfasttimer_class.h - * @brief Declaration of a fast timer. - * - * $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_FASTTIMER_CLASS_H -#define LL_FASTTIMER_CLASS_H - -#include "llinstancetracker.h" - -#define FAST_TIMER_ON 1 -#define TIME_FAST_TIMERS 0 -#define DEBUG_FAST_TIMER_THREADS 1 - -class LLMutex; - -#include <queue> -#include "llsd.h" - -LL_COMMON_API void assert_main_thread(); - -class LL_COMMON_API LLFastTimer -{ -public: -	class NamedTimer; - -	struct LL_COMMON_API FrameState -	{ -		FrameState(NamedTimer* 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(); - -		S32 getFrameStateIndex() const { return mFrameStateIndex; } - -		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 -		// -		S32			mFrameStateIndex; - -		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); - -		static void updateCachedPointers(); - -	private: -		NamedTimer&		mTimer; -		FrameState*		mFrameState; -	}; - -public: -	LLFastTimer(LLFastTimer::FrameState* state); - -	LL_FORCE_INLINE LLFastTimer(LLFastTimer::DeclareTimer& timer) -	:	mFrameState(timer.mFrameState) -	{ -#if TIME_FAST_TIMERS -		U64 timer_start = getCPUClockCount64(); -#endif -#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 TIME_FAST_TIMERS -		U64 timer_end = getCPUClockCount64(); -		sTimerCycles += timer_end - timer_start; -#endif -#if DEBUG_FAST_TIMER_THREADS -#if !LL_RELEASE -		assert_main_thread(); -#endif -#endif -	} - -	LL_FORCE_INLINE ~LLFastTimer() -	{ -#if TIME_FAST_TIMERS -		U64 timer_start = getCPUClockCount64(); -#endif -#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 -#if TIME_FAST_TIMERS -		U64 timer_end = getCPUClockCount64(); -		sTimerCycles += timer_end - timer_start; -		sTimerCalls++; -#endif -	} - -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; -	static U64				sTimerCycles; -	static U32				sTimerCalls; - -	typedef std::vector<FrameState> info_list_t; -	static info_list_t& getFrameStateList(); - - -	// call this once a frame to reset timers -	static void nextFrame(); - -	// dumps current cumulative frame stats to log -	// call nextFrame() to reset timers -	static void dumpCurTimes(); - -	// call this to reset timer hierarchy, averages, etc. -	static void reset(); - -	static 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; -	static std::string sClockType; - -private: -	static U32 getCPUClockCount32(); -	static U64 getCPUClockCount64(); -	static U64 sClockResolution; - -	static S32				sCurFrameIndex; -	static S32				sLastFrameIndex; -	static U64				sLastFrameTime; -	static info_list_t*		sTimerInfos; - -	U32							mStartTime; -	LLFastTimer::FrameState*	mFrameState; -	LLFastTimer::CurTimerData	mLastTimerData; - -}; - -typedef class LLFastTimer LLFastTimer; - -#endif // LL_LLFASTTIMER_CLASS_H diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index c51d042a3d..c3a0f0bfe0 100644..100755 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -56,6 +56,8 @@ std::string strerr(int errn)  	return buffer;  } +typedef std::basic_ios<char,std::char_traits < char > > _Myios; +  #else  // On Posix we want to call strerror_r(), but alarmingly, there are two  // different variants. The one that returns int always populates the passed @@ -324,9 +326,10 @@ const char *LLFile::tmpdir()  /***************** Modified file stream created to overcome the incorrect behaviour of posix fopen in windows *******************/ -#if USE_LLFILESTREAMS +#if LL_WINDOWS -LLFILE *	LLFile::_Fiopen(const std::string& filename, std::ios::openmode mode,int)	// protection currently unused +LLFILE *	LLFile::_Fiopen(const std::string& filename,  +		std::ios::openmode mode)  {	// open a file  	static const char *mods[] =  	{	// fopen mode strings corresponding to valid[i] @@ -385,117 +388,690 @@ LLFILE *	LLFile::_Fiopen(const std::string& filename, std::ios::openmode mode,in  	return (0);  } -/************** input file stream ********************************/ +#endif /* LL_WINDOWS */ -void llifstream::close() -{	// close the C stream -	if (_Filebuffer && _Filebuffer->close() == 0) +/************** llstdio file buffer ********************************/ + + +//llstdio_filebuf* llstdio_filebuf::open(const char *_Filename, +//	ios_base::openmode _Mode) +//{ +//#if LL_WINDOWS +//	_Filet *_File; +//	if (is_open() || (_File = LLFILE::_Fiopen(_Filename, _Mode)) == 0) +//		return (0);	// open failed +// +//	_Init(_File, _Openfl); +//	_Initcvt(&_USE(_Mysb::getloc(), _Cvt)); +//	return (this);	// open succeeded +//#else +//	std::filebuf* _file = std::filebuf::open(_Filename, _Mode); +//	if (NULL == _file) return NULL; +//	return this; +//#endif +//} + + +// *TODO: Seek the underlying c stream for better cross-platform compatibility? +#if !LL_WINDOWS +llstdio_filebuf::int_type llstdio_filebuf::overflow(llstdio_filebuf::int_type __c) +{ +	int_type __ret = traits_type::eof(); +	const bool __testeof = traits_type::eq_int_type(__c, __ret); +	const bool __testout = _M_mode & ios_base::out; +	if (__testout && !_M_reading)  	{ -		_Myios::setstate(ios_base::failbit);	/*Flawfinder: ignore*/ +		if (this->pbase() < this->pptr()) +		{ +			// If appropriate, append the overflow char. +			if (!__testeof) +			{ +				*this->pptr() = traits_type::to_char_type(__c); +				this->pbump(1); +			} + +			// Convert pending sequence to external representation, +			// and output. +			if (_convert_to_external(this->pbase(), +					 this->pptr() - this->pbase())) +			{ +				_M_set_buffer(0); +				__ret = traits_type::not_eof(__c); +			} +	} +		else if (_M_buf_size > 1) +		{ +			// Overflow in 'uncommitted' mode: set _M_writing, set +			// the buffer to the initial 'write' mode, and put __c +			// into the buffer. +			_M_set_buffer(0); +			_M_writing = true; +			if (!__testeof) +			{ +				*this->pptr() = traits_type::to_char_type(__c); +				this->pbump(1); +			} +			__ret = traits_type::not_eof(__c); +		} +		else +		{ +			// Unbuffered. +			char_type __conv = traits_type::to_char_type(__c); +			if (__testeof || _convert_to_external(&__conv, 1)) +			{ +				_M_writing = true; +				__ret = traits_type::not_eof(__c); +			} +		}  	} +	return __ret;  } -void llifstream::open(const std::string& _Filename,	/* Flawfinder: ignore */ -	ios_base::openmode _Mode, -	int _Prot) -{	// open a C stream with specified mode +bool llstdio_filebuf::_convert_to_external(char_type* __ibuf, +						std::streamsize __ilen) +{ +	// Sizes of external and pending output. +	streamsize __elen; +	streamsize __plen; +	if (__check_facet(_M_codecvt).always_noconv()) +	{ +		//__elen = _M_file.xsputn(reinterpret_cast<char*>(__ibuf), __ilen); +		__elen = fwrite(reinterpret_cast<void*>(__ibuf), 1, +						__ilen, _M_file.file()); +		__plen = __ilen; +	} +	else +	{ +		// Worst-case number of external bytes needed. +		// XXX Not done encoding() == -1. +		streamsize __blen = __ilen * _M_codecvt->max_length(); +		char* __buf = static_cast<char*>(__builtin_alloca(__blen)); + +		char* __bend; +		const char_type* __iend; +		codecvt_base::result __r; +		__r = _M_codecvt->out(_M_state_cur, __ibuf, __ibuf + __ilen, +				__iend, __buf, __buf + __blen, __bend); -	LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::in, _Prot); -	if(filep == NULL) +		if (__r == codecvt_base::ok || __r == codecvt_base::partial) +			__blen = __bend - __buf; +		else if (__r == codecvt_base::noconv)  	{ -		_Myios::setstate(ios_base::failbit);	/*Flawfinder: ignore*/ -		return; +			// Same as the always_noconv case above. +			__buf = reinterpret_cast<char*>(__ibuf); +			__blen = __ilen;  	} -	llassert(_Filebuffer == NULL); -	_Filebuffer = new _Myfb(filep); -	_ShouldClose = true; -	_Myios::init(_Filebuffer); +		else +			__throw_ios_failure(__N("llstdio_filebuf::_convert_to_external " +									"conversion error")); +   +		//__elen = _M_file.xsputn(__buf, __blen); +		__elen = fwrite(__buf, 1, __blen, _M_file.file()); +		__plen = __blen; + +		// Try once more for partial conversions. +		if (__r == codecvt_base::partial && __elen == __plen) +		{ +			const char_type* __iresume = __iend; +			streamsize __rlen = this->pptr() - __iend; +			__r = _M_codecvt->out(_M_state_cur, __iresume, +					__iresume + __rlen, __iend, __buf, +					__buf + __blen, __bend); +			if (__r != codecvt_base::error) +			{ +				__rlen = __bend - __buf; +				//__elen = _M_file.xsputn(__buf, __rlen); +				__elen = fwrite(__buf, 1, __rlen, _M_file.file()); +				__plen = __rlen; +			} +			else +			{ +				__throw_ios_failure(__N("llstdio_filebuf::_convert_to_external " +										"conversion error")); +			} +		} +	} +	return __elen == __plen;  } -bool llifstream::is_open() const -{	// test if C stream has been opened -	if(_Filebuffer) -		return (_Filebuffer->is_open()); -	return false; +llstdio_filebuf::int_type llstdio_filebuf::underflow() +{ +	int_type __ret = traits_type::eof(); +	const bool __testin = _M_mode & ios_base::in; +	if (__testin) +	{ +		if (_M_writing) +		{ +			if (overflow() == traits_type::eof()) +			return __ret; +			//_M_set_buffer(-1); +			//_M_writing = false; +		} +		// Check for pback madness, and if so switch back to the +		// normal buffers and jet outta here before expensive +		// fileops happen... +		_M_destroy_pback(); + +		if (this->gptr() < this->egptr()) +			return traits_type::to_int_type(*this->gptr()); + +		// Get and convert input sequence. +		const size_t __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1; + +		// Will be set to true if ::fread() returns 0 indicating EOF. +		bool __got_eof = false; +		// Number of internal characters produced. +		streamsize __ilen = 0; +		codecvt_base::result __r = codecvt_base::ok; +		if (__check_facet(_M_codecvt).always_noconv()) +		{ +			//__ilen = _M_file.xsgetn(reinterpret_cast<char*>(this->eback()), +			//			__buflen); +			__ilen = fread(reinterpret_cast<void*>(this->eback()), 1, +						__buflen, _M_file.file()); +			if (__ilen == 0) +				__got_eof = true; +		} +		else +	    { +			// Worst-case number of external bytes. +			// XXX Not done encoding() == -1. +			const int __enc = _M_codecvt->encoding(); +			streamsize __blen; // Minimum buffer size. +			streamsize __rlen; // Number of chars to read. +			if (__enc > 0) +				__blen = __rlen = __buflen * __enc; +			else +			{ +				__blen = __buflen + _M_codecvt->max_length() - 1; +				__rlen = __buflen; +			} +			const streamsize __remainder = _M_ext_end - _M_ext_next; +			__rlen = __rlen > __remainder ? __rlen - __remainder : 0; + +			// An imbue in 'read' mode implies first converting the external +			// chars already present. +			if (_M_reading && this->egptr() == this->eback() && __remainder) +				__rlen = 0; + +			// Allocate buffer if necessary and move unconverted +			// bytes to front. +			if (_M_ext_buf_size < __blen) +			{ +				char* __buf = new char[__blen]; +				if (__remainder) +					__builtin_memcpy(__buf, _M_ext_next, __remainder); + +				delete [] _M_ext_buf; +				_M_ext_buf = __buf; +				_M_ext_buf_size = __blen; +			} +			else if (__remainder) +				__builtin_memmove(_M_ext_buf, _M_ext_next, __remainder); + +			_M_ext_next = _M_ext_buf; +			_M_ext_end = _M_ext_buf + __remainder; +			_M_state_last = _M_state_cur; + +			do +			{ +				if (__rlen > 0) +				{ +					// Sanity check! +					// This may fail if the return value of +					// codecvt::max_length() is bogus. +					if (_M_ext_end - _M_ext_buf + __rlen > _M_ext_buf_size) +					{ +						__throw_ios_failure(__N("llstdio_filebuf::underflow " +							"codecvt::max_length() " +							"is not valid")); +					} +					//streamsize __elen = _M_file.xsgetn(_M_ext_end, __rlen); +					streamsize __elen = fread(_M_ext_end, 1, +						__rlen, _M_file.file()); +					if (__elen == 0) +						__got_eof = true; +					else if (__elen == -1) +					break; +					//_M_ext_end += __elen; +				} + +				char_type* __iend = this->eback(); +				if (_M_ext_next < _M_ext_end) +				{ +					__r = _M_codecvt->in(_M_state_cur, _M_ext_next, +							_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(), +						reinterpret_cast<char_type*> +						(_M_ext_buf), __ilen); +					_M_ext_next = _M_ext_buf + __ilen; +				} +				else +					__ilen = __iend - this->eback(); + +				// _M_codecvt->in may return error while __ilen > 0: this is +				// ok, and actually occurs in case of mixed encodings (e.g., +				// XML files). +				if (__r == codecvt_base::error) +					break; + +				__rlen = 1; +			} while (__ilen == 0 && !__got_eof); +		} + +		if (__ilen > 0) +		{ +			_M_set_buffer(__ilen); +			_M_reading = true; +			__ret = traits_type::to_int_type(*this->gptr()); +		} +		else if (__got_eof) +		{ +			// If the actual end of file is reached, set 'uncommitted' +			// mode, thus allowing an immediate write without an +			// intervening seek. +			_M_set_buffer(-1); +			_M_reading = false; +			// However, reaching it while looping on partial means that +			// the file has got an incomplete character. +			if (__r == codecvt_base::partial) +				__throw_ios_failure(__N("llstdio_filebuf::underflow " +					"incomplete character in file")); +		} +		else if (__r == codecvt_base::error) +			__throw_ios_failure(__N("llstdio_filebuf::underflow " +					"invalid byte sequence in file")); +		else +			__throw_ios_failure(__N("llstdio_filebuf::underflow " +					"error reading the file")); +	} +	return __ret; +} + +std::streamsize llstdio_filebuf::xsgetn(char_type* __s, std::streamsize __n) +{ +	// Clear out pback buffer before going on to the real deal... +	streamsize __ret = 0; +	if (_M_pback_init) +	{ +		if (__n > 0 && this->gptr() == this->eback()) +		{ +			*__s++ = *this->gptr(); +			this->gbump(1); +			__ret = 1; +			--__n; +		} +		_M_destroy_pback(); +	} +        +	// Optimization in the always_noconv() case, to be generalized in the +	// future: when __n > __buflen we read directly instead of using the +	// buffer repeatedly. +	const bool __testin = _M_mode & ios_base::in; +	const streamsize __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1; + +	if (__n > __buflen && __check_facet(_M_codecvt).always_noconv() +		&& __testin && !_M_writing) +	{ +		// First, copy the chars already present in the buffer. +		const streamsize __avail = this->egptr() - this->gptr(); +		if (__avail != 0) +		{ +			if (__avail == 1) +				*__s = *this->gptr(); +			else +				traits_type::copy(__s, this->gptr(), __avail); +			__s += __avail; +			this->gbump(__avail); +			__ret += __avail; +			__n -= __avail; +		} + +		// Need to loop in case of short reads (relatively common +		// with pipes). +		streamsize __len; +		for (;;) +		{ +			//__len = _M_file.xsgetn(reinterpret_cast<char*>(__s), __n); +			__len = fread(reinterpret_cast<void*>(__s), 1,  +						__n, _M_file.file()); +			if (__len == -1) +				__throw_ios_failure(__N("llstdio_filebuf::xsgetn " +										"error reading the file")); +			if (__len == 0) +				break; + +			__n -= __len; +			__ret += __len; +			if (__n == 0) +				break; + +			__s += __len; +		} + +		if (__n == 0) +		{ +			_M_set_buffer(0); +			_M_reading = true; +		} +		else if (__len == 0) +		{ +			// If end of file is reached, set 'uncommitted' +			// mode, thus allowing an immediate write without +			// an intervening seek. +			_M_set_buffer(-1); +			_M_reading = false; +		} +	} +	else +		__ret += __streambuf_type::xsgetn(__s, __n); + +	return __ret;  } -llifstream::~llifstream() + +std::streamsize llstdio_filebuf::xsputn(char_type* __s, std::streamsize __n)  { -	if (_ShouldClose) +	// Optimization in the always_noconv() case, to be generalized in the +	// future: when __n is sufficiently large we write directly instead of +	// using the buffer. +	streamsize __ret = 0; +	const bool __testout = _M_mode & ios_base::out; +	if (__check_facet(_M_codecvt).always_noconv() +		&& __testout && !_M_reading) +	{ +		// Measurement would reveal the best choice. +		const streamsize __chunk = 1ul << 10; +		streamsize __bufavail = this->epptr() - this->pptr(); + +		// Don't mistake 'uncommitted' mode buffered with unbuffered. +		if (!_M_writing && _M_buf_size > 1) +			__bufavail = _M_buf_size - 1; + +		const streamsize __limit = std::min(__chunk, __bufavail); +		if (__n >= __limit) +		{ +			const streamsize __buffill = this->pptr() - this->pbase(); +			const char* __buf = reinterpret_cast<const char*>(this->pbase()); +			//__ret = _M_file.xsputn_2(__buf, __buffill, +			//			reinterpret_cast<const char*>(__s), __n); +			if (__buffill) +			{ +				__ret = fwrite(__buf, 1, __buffill, _M_file.file()); +			} +			if (__ret == __buffill)  	{ -		close(); +				__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 +				__ret = 0; +		} +		else +			__ret = __streambuf_type::xsputn(__s, __n);  	} -	delete _Filebuffer; +	else +		__ret = __streambuf_type::xsputn(__s, __n); +    return __ret; +} + +int llstdio_filebuf::sync() +{ +	return (_M_file.sync() == 0 ? 0 : -1);  } +#endif + +/************** input file stream ********************************/ + +llifstream::llifstream() : _M_filebuf(), +#if LL_WINDOWS +	std::istream(&_M_filebuf) {} +#else +	std::istream() +{ +	this->init(&_M_filebuf); +} +#endif + +// explicit  llifstream::llifstream(const std::string& _Filename, -	ios_base::openmode _Mode, -	int _Prot) -	: std::basic_istream< char , std::char_traits< char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false) +		ios_base::openmode _Mode) : _M_filebuf(), +#if LL_WINDOWS +	std::istream(&_M_filebuf) +{ +	llutf16string wideName = utf8str_to_utf16str( _Filename ); +	if (_M_filebuf.open(wideName.c_str(), _Mode | ios_base::in) == 0) +	{ +		_Myios::setstate(ios_base::failbit); +	} +} +#else +	std::istream() +{ +	this->init(&_M_filebuf); +	this->open(_Filename.c_str(), _Mode | ios_base::in); +} +#endif -{	// construct with named file and specified mode -	open(_Filename, _Mode | ios_base::in, _Prot);	/* Flawfinder: ignore */ +// explicit +llifstream::llifstream(const char* _Filename,  +		ios_base::openmode _Mode) : _M_filebuf(), +#if LL_WINDOWS +	std::istream(&_M_filebuf) +{ +	llutf16string wideName = utf8str_to_utf16str( _Filename ); +	if (_M_filebuf.open(wideName.c_str(), _Mode | ios_base::in) == 0) +	{ +		_Myios::setstate(ios_base::failbit); +} +} +#else +	std::istream() +{ +	this->init(&_M_filebuf); +	this->open(_Filename, _Mode | ios_base::in);  } +#endif -/************** output file stream ********************************/ +// explicit +llifstream::llifstream(_Filet *_File, +		ios_base::openmode _Mode, size_t _Size) : +	_M_filebuf(_File, _Mode, _Size), +#if LL_WINDOWS +	std::istream(&_M_filebuf) {} +#else +	std::istream() +{ +	this->init(&_M_filebuf); +} +#endif -bool llofstream::is_open() const +#if !LL_WINDOWS +// explicit +llifstream::llifstream(int __fd, +		ios_base::openmode _Mode, size_t _Size) : +	_M_filebuf(__fd, _Mode, _Size), +	std::istream() +{ +	this->init(&_M_filebuf); +} +#endif + +bool llifstream::is_open() const  {	// test if C stream has been opened -	if(_Filebuffer) -		return (_Filebuffer->is_open()); -	return false; +	return _M_filebuf.is_open();  } -void llofstream::open(const std::string& _Filename,	/* Flawfinder: ignore */ -	ios_base::openmode _Mode, -	int _Prot) +void llifstream::open(const char* _Filename, ios_base::openmode _Mode)  {	// open a C stream with specified mode -	LLFILE* filep = LLFile::_Fiopen(_Filename,_Mode | ios_base::out, _Prot); -	if(filep == NULL) +#if LL_WINDOWS +	llutf16string wideName = utf8str_to_utf16str( _Filename ); +	if (_M_filebuf.open( wideName.c_str(), _Mode | ios_base::in) == 0)  	{ -		_Myios::setstate(ios_base::failbit);	/*Flawfinder: ignore*/ -		return; +		_Myios::setstate(ios_base::failbit);  	} -	llassert(_Filebuffer==NULL); -	_Filebuffer = new _Myfb(filep); -	_ShouldClose = true; -	_Myios::init(_Filebuffer); +	else +	{ +		_Myios::clear(); +	} +#else +	if (_M_filebuf.open(_Filename, _Mode | ios_base::in) == 0) +	{ +		this->setstate(ios_base::failbit); +	} +	else +	{ +		this->clear(); +	} +#endif  } -void llofstream::close() +void llifstream::close()  {	// close the C stream -	if(is_open()) +	if (_M_filebuf.close() == 0)  	{ -		if (_Filebuffer->close() == 0) -		{ -			_Myios::setstate(ios_base::failbit);	/*Flawfinder: ignore*/ +#if LL_WINDOWS +		_Myios::setstate(ios_base::failbit); +#else +		this->setstate(ios_base::failbit); +#endif  		} -		delete _Filebuffer; -		_Filebuffer = NULL; -		_ShouldClose = false;  	} + + +/************** output file stream ********************************/ + + +llofstream::llofstream() : _M_filebuf(), +#if LL_WINDOWS +	std::ostream(&_M_filebuf) {} +#else +	std::ostream() +{ +	this->init(&_M_filebuf);  } +#endif +// explicit  llofstream::llofstream(const std::string& _Filename, -	std::ios_base::openmode _Mode, -	int _Prot) -		: std::basic_ostream<char,std::char_traits < char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false) -{	// construct with named file and specified mode -	open(_Filename, _Mode , _Prot);	/* Flawfinder: ignore */ +		ios_base::openmode _Mode) : _M_filebuf(), +#if LL_WINDOWS +	std::ostream(&_M_filebuf) +{ +	llutf16string wideName = utf8str_to_utf16str( _Filename ); +	if (_M_filebuf.open( wideName.c_str(), _Mode | ios_base::out) == 0) +	{ +		_Myios::setstate(ios_base::failbit); +	} +} +#else +	std::ostream() +{ +	this->init(&_M_filebuf); +	this->open(_Filename.c_str(), _Mode | ios_base::out); +} +#endif + +// explicit +llofstream::llofstream(const char* _Filename, +		ios_base::openmode _Mode) : _M_filebuf(), +#if LL_WINDOWS +	std::ostream(&_M_filebuf) +{ +	llutf16string wideName = utf8str_to_utf16str( _Filename ); +	if (_M_filebuf.open( wideName.c_str(), _Mode | ios_base::out) == 0) +	{ +		_Myios::setstate(ios_base::failbit); +	} +} +#else +	std::ostream() +{ +	this->init(&_M_filebuf); +	this->open(_Filename, _Mode | ios_base::out); +} +#endif + +// explicit +llofstream::llofstream(_Filet *_File, +			ios_base::openmode _Mode, size_t _Size) : +	_M_filebuf(_File, _Mode, _Size), +#if LL_WINDOWS +	std::ostream(&_M_filebuf) {} +#else +	std::ostream() +{ +	this->init(&_M_filebuf);  } +#endif -llofstream::~llofstream() +#if !LL_WINDOWS +// explicit +llofstream::llofstream(int __fd, +			ios_base::openmode _Mode, size_t _Size) : +	_M_filebuf(__fd, _Mode, _Size), +	std::ostream()  { -	// destroy the object -	if (_ShouldClose) +	this->init(&_M_filebuf); +} +#endif + +bool llofstream::is_open() const +{	// test if C stream has been opened +	return _M_filebuf.is_open(); +} + +void llofstream::open(const char* _Filename, ios_base::openmode _Mode) +{	// open a C stream with specified 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  	{ -		close(); +		_Myios::clear();  	} -	delete _Filebuffer; +#else +	if (_M_filebuf.open(_Filename, _Mode | ios_base::out) == 0) +	{ +		this->setstate(ios_base::failbit); +	} +	else +	{ +		this->clear(); +	} +#endif  } -#endif // #if USE_LLFILESTREAMS +void llofstream::close() +{	// close the C stream +	if (_M_filebuf.close() == 0) +	{ +#if LL_WINDOWS +		_Myios::setstate(ios_base::failbit); +#else +		this->setstate(ios_base::failbit); +#endif +	} +}  /************** helper functions ********************************/ diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h index dd7d36513a..d59e68367e 100644..100755 --- a/indra/llcommon/llfile.h +++ b/indra/llcommon/llfile.h @@ -38,13 +38,6 @@  typedef FILE	LLFILE;  #include <fstream> - -#ifdef LL_WINDOWS -#define	USE_LLFILESTREAMS	1 -#else -#define	USE_LLFILESTREAMS	0 -#endif -  #include <sys/stat.h>  #if LL_WINDOWS @@ -52,6 +45,8 @@ typedef FILE	LLFILE;  typedef struct _stat	llstat;  #else  typedef struct stat		llstat; +#include <ext/stdio_filebuf.h> +#include <bits/postypes.h>  #endif  #ifndef S_ISREG @@ -83,142 +78,342 @@ public:  	static	int		stat(const std::string&	filename,llstat*	file_status);  	static	bool	isdir(const std::string&	filename);  	static	bool	isfile(const std::string&	filename); -	static	LLFILE *	_Fiopen(const std::string& filename, std::ios::openmode mode,int);	// protection currently unused +	static	LLFILE *	_Fiopen(const std::string& filename,  +			std::ios::openmode mode);  	static  const char * tmpdir();  }; +/** + *  @brief Provides a layer of compatibility for C/POSIX. + * + *  This is taken from both the GNU __gnu_cxx::stdio_filebuf extension and  + *  VC's basic_filebuf implementation. + *  This file buffer provides extensions for working with standard C FILE*'s  + *  and POSIX file descriptors for platforms that support this. +*/ +namespace +{ +#if LL_WINDOWS +typedef std::filebuf						_Myfb; +#else +typedef  __gnu_cxx::stdio_filebuf< char >	_Myfb; +typedef std::__c_file						_Filet; +#endif /* LL_WINDOWS */ +} -#if USE_LLFILESTREAMS - -class LL_COMMON_API llifstream	:	public	std::basic_istream < char , std::char_traits < char > > +class LL_COMMON_API llstdio_filebuf : public _Myfb  { -	// input stream associated with a C stream  public: -	typedef std::basic_ifstream<char,std::char_traits < char > > _Myt; -	typedef std::basic_filebuf<char,std::char_traits< char > > _Myfb; -	typedef std::basic_ios<char,std::char_traits< char > > _Myios; - -	llifstream() -		: std::basic_istream<char,std::char_traits< char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false) -	{	// construct unopened -	} +	/** +	 * deferred initialization / destruction +	*/ +	llstdio_filebuf() : _Myfb() {} +	virtual ~llstdio_filebuf() {}  + +	/** +	 *  @param  f  An open @c FILE*. +	 *  @param  mode  Same meaning as in a standard filebuf. +	 *  @param  size  Optimal or preferred size of internal buffer, in chars. +	 *                Defaults to system's @c BUFSIZ. +	 * +	 *  This constructor associates a file stream buffer with an open +	 *  C @c FILE*.  The @c FILE* will not be automatically closed when the +	 *  stdio_filebuf is closed/destroyed. +	*/ +	llstdio_filebuf(_Filet* __f, std::ios_base::openmode __mode, +		    //size_t __size = static_cast<size_t>(BUFSIZ)) : +		    size_t __size = static_cast<size_t>(1)) : +#if LL_WINDOWS +		_Myfb(__f) {} +#else +		_Myfb(__f, __mode, __size) {} +#endif -	explicit llifstream(const std::string& _Filename, -		ios_base::openmode _Mode = ios_base::in, -		int _Prot = (int)ios_base::_Openprot); - -	explicit llifstream(_Filet *_File) -		: std::basic_istream<char,std::char_traits< char > >(NULL,true), -			_Filebuffer(new _Myfb(_File)), -			_ShouldClose(false) -	{	// construct with specified C stream -	} -	virtual ~llifstream(); - -	_Myfb *rdbuf() const -	{	// return pointer to file buffer -		return _Filebuffer; -	} -	bool is_open() const; -	void open(const std::string& _Filename,	/* Flawfinder: ignore */ -		ios_base::openmode _Mode = ios_base::in, -		int _Prot = (int)ios_base::_Openprot);	 -	void close(); +	/** +	 *  @brief  Opens an external file. +	 *  @param  s  The name of the file. +	 *  @param  mode  The open mode flags. +	 *  @return  @c this on success, NULL on failure +	 * +	 *  If a file is already open, this function immediately fails. +	 *  Otherwise it tries to open the file named @a s using the flags +	 *  given in @a mode. +	*/ +	//llstdio_filebuf* open(const char *_Filename, +	//		std::ios_base::openmode _Mode); + +	/** +	 *  @param  fd  An open file descriptor. +	 *  @param  mode  Same meaning as in a standard filebuf. +	 *  @param  size  Optimal or preferred size of internal buffer, in chars. +	 * +	 *  This constructor associates a file stream buffer with an open +	 *  POSIX file descriptor. The file descriptor will be automatically +	 *  closed when the stdio_filebuf is closed/destroyed. +	*/ +#if !LL_WINDOWS +	llstdio_filebuf(int __fd, std::ios_base::openmode __mode, +		//size_t __size = static_cast<size_t>(BUFSIZ)) : +		size_t __size = static_cast<size_t>(1)) : +		_Myfb(__fd, __mode, __size) {} +#endif -private: -	_Myfb* _Filebuffer;	// the file buffer -	bool _ShouldClose; +// *TODO: Seek the underlying c stream for better cross-platform compatibility? +#if !LL_WINDOWS +protected: +	/** underflow() and uflow() functions are called to get the next +	 *  character from the real input source when the buffer is empty. +	 *  Buffered input uses underflow() +	*/ +	/*virtual*/ int_type underflow(); + +	/*  Convert internal byte sequence to external, char-based +	 * sequence via codecvt. +	*/ +	bool _convert_to_external(char_type*, std::streamsize); + +	/** The overflow() function is called to transfer characters to the +	 *  real output destination when the buffer is full. A call to +	 *  overflow(c) outputs the contents of the buffer plus the +	 *  character c. +	 *  Consume some sequence of the characters in the pending sequence. +	*/ +	/*virtual*/ int_type overflow(int_type __c = traits_type::eof()); + +	/** sync() flushes the underlying @c FILE* stream. +	*/ +	/*virtual*/ int sync(); + +	std::streamsize xsgetn(char_type*, std::streamsize); +	std::streamsize xsputn(char_type*, std::streamsize); +#endif  }; -class LL_COMMON_API llofstream	:	public	std::basic_ostream< char , std::char_traits < char > > +/** + *  @brief  Controlling input for files. + * + *  This class supports reading from named files, using the inherited + *  functions from std::basic_istream.  To control the associated + *  sequence, an instance of std::basic_filebuf (or a platform-specific derivative) + *  which allows construction using a pre-exisintg file stream buffer.  + *  We refer to this std::basic_filebuf (or derivative) as @c sb. +*/ +class LL_COMMON_API llifstream	:	public	std::istream  { +	// input stream associated with a C stream  public: -	typedef std::basic_ostream< char , std::char_traits < char > > _Myt; -	typedef std::basic_filebuf< char , std::char_traits < char > > _Myfb; -	typedef std::basic_ios<char,std::char_traits < char > > _Myios; - -	llofstream() -		: std::basic_ostream<char,std::char_traits < char > >(NULL,true),_Filebuffer(NULL),_ShouldClose(false) -	{	// construct unopened -	} - -	explicit llofstream(const std::string& _Filename, -		std::ios_base::openmode _Mode = ios_base::out, -		int _Prot = (int)std::ios_base::_Openprot); +	// Constructors: +	/** +	 *  @brief  Default constructor. +	 * +	 *  Initializes @c sb using its default constructor, and passes +	 *  @c &sb to the base class initializer.  Does not open any files +	 *  (you haven't given it a filename to open). +	*/ +	llifstream(); + +	/** +	 *  @brief  Create an input file stream. +	 *  @param  Filename  String specifying the filename. +	 *  @param  Mode  Open file in specified mode (see std::ios_base). +	 * +     *  @c ios_base::in is automatically included in @a mode. +	*/ +	explicit llifstream(const std::string& _Filename, +			ios_base::openmode _Mode = ios_base::in); +	explicit llifstream(const char* _Filename, +			ios_base::openmode _Mode = ios_base::in); + +	/** +	 *  @brief  Create a stream using an open c file stream. +	 *  @param  File  An open @c FILE*. +        @param  Mode  Same meaning as in a standard filebuf. +        @param  Size  Optimal or preferred size of internal buffer, in chars. +                      Defaults to system's @c BUFSIZ. +	*/ +	explicit llifstream(_Filet *_File, +			ios_base::openmode _Mode = ios_base::in, +			//size_t _Size = static_cast<size_t>(BUFSIZ)); +			size_t _Size = static_cast<size_t>(1)); +	/** +	 *  @brief  Create a stream using an open file descriptor. +	 *  @param  fd    An open file descriptor. +        @param  Mode  Same meaning as in a standard filebuf. +        @param  Size  Optimal or preferred size of internal buffer, in chars. +                      Defaults to system's @c BUFSIZ. +	*/ +#if !LL_WINDOWS +	explicit llifstream(int __fd, +			ios_base::openmode _Mode = ios_base::in, +			//size_t _Size = static_cast<size_t>(BUFSIZ)); +			size_t _Size = static_cast<size_t>(1)); +#endif -	explicit llofstream(_Filet *_File) -		: std::basic_ostream<char,std::char_traits < char > >(NULL,true), -			_Filebuffer(new _Myfb(_File)),//_File) -			_ShouldClose(false) -	{	// construct with specified C stream -	} - -	virtual ~llofstream(); - -	_Myfb *rdbuf() const -	{	// return pointer to file buffer -		return _Filebuffer; -	} - +	/** +	 *  @brief  The destructor does nothing. +	 * +	 *  The file is closed by the filebuf object, not the formatting +	 *  stream. +	*/ +	virtual ~llifstream() {} + +	// Members: +	/** +	 *  @brief  Accessing the underlying buffer. +	 *  @return  The current basic_filebuf buffer. +	 * +	 *  This hides both signatures of std::basic_ios::rdbuf(). +	*/ +	llstdio_filebuf* rdbuf() const +	{ return const_cast<llstdio_filebuf*>(&_M_filebuf); } + +	/** +	 *  @brief  Wrapper to test for an open file. +	 *  @return  @c rdbuf()->is_open() +	*/  	bool is_open() const; -	void open(const std::string& _Filename,ios_base::openmode _Mode = ios_base::out,int _Prot = (int)ios_base::_Openprot);	/* Flawfinder: ignore */ - +	/** +	 *  @brief  Opens an external file. +	 *  @param  Filename  The name of the file. +	 *  @param  Node  The open mode flags. +	 * +	 *  Calls @c llstdio_filebuf::open(s,mode|in).  If that function +	 *  fails, @c failbit is set in the stream's error state. +	*/ +	void open(const std::string& _Filename, +			ios_base::openmode _Mode = ios_base::in) +	{ open(_Filename.c_str(), _Mode); } +	void open(const char* _Filename, +			ios_base::openmode _Mode = ios_base::in); + +	/** +	 *  @brief  Close the file. +	 * +	 *  Calls @c llstdio_filebuf::close().  If that function +	 *  fails, @c failbit is set in the stream's error state. +	*/  	void close();  private: -	_Myfb *_Filebuffer;	// the file buffer -	bool _ShouldClose; -}; - - - -#else -//Use standard file streams on non windows platforms -//#define	llifstream	std::ifstream -//#define	llofstream	std::ofstream - -class LL_COMMON_API llifstream	:	public	std::ifstream -{ -public: -	llifstream() : std::ifstream() -	{ -	} - -	explicit llifstream(const std::string& _Filename, std::_Ios_Openmode _Mode = in) -		: std::ifstream(_Filename.c_str(), _Mode) -	{ -	} -	void open(const std::string& _Filename, std::_Ios_Openmode _Mode = in)	/* Flawfinder: ignore */ -	{ -		std::ifstream::open(_Filename.c_str(), _Mode); -	} +	llstdio_filebuf _M_filebuf;  }; -class LL_COMMON_API llofstream	:	public	std::ofstream +/** + *  @brief  Controlling output for files. + * + *  This class supports writing to named files, using the inherited + *  functions from std::basic_ostream.  To control the associated + *  sequence, an instance of std::basic_filebuf (or a platform-specific derivative) + *  which allows construction using a pre-exisintg file stream buffer.  + *  We refer to this std::basic_filebuf (or derivative) as @c sb. +*/ +class LL_COMMON_API llofstream	:	public	std::ostream  {  public: -	llofstream() : std::ofstream() -	{ -	} +	// Constructors: +	/** +	 *  @brief  Default constructor. +	 * +	 *  Initializes @c sb using its default constructor, and passes +	 *  @c &sb to the base class initializer.  Does not open any files +	 *  (you haven't given it a filename to open). +	*/ +	llofstream(); + +	/** +	 *  @brief  Create an output file stream. +	 *  @param  Filename  String specifying the filename. +	 *  @param  Mode  Open file in specified mode (see std::ios_base). +	 * +	 *  @c ios_base::out|ios_base::trunc is automatically included in +	 *  @a mode. +	*/ +	explicit llofstream(const std::string& _Filename, +			ios_base::openmode _Mode = ios_base::out|ios_base::trunc); +	explicit llofstream(const char* _Filename, +			ios_base::openmode _Mode = ios_base::out|ios_base::trunc); + +	/** +	 *  @brief  Create a stream using an open c file stream. +	 *  @param  File  An open @c FILE*. +        @param  Mode  Same meaning as in a standard filebuf. +        @param  Size  Optimal or preferred size of internal buffer, in chars. +                      Defaults to system's @c BUFSIZ. +	*/ +	explicit llofstream(_Filet *_File, +			ios_base::openmode _Mode = ios_base::out, +			//size_t _Size = static_cast<size_t>(BUFSIZ)); +			size_t _Size = static_cast<size_t>(1)); + +	/** +	 *  @brief  Create a stream using an open file descriptor. +	 *  @param  fd    An open file descriptor. +        @param  Mode  Same meaning as in a standard filebuf. +        @param  Size  Optimal or preferred size of internal buffer, in chars. +                      Defaults to system's @c BUFSIZ. +	*/ +#if !LL_WINDOWS +	explicit llofstream(int __fd, +			ios_base::openmode _Mode = ios_base::out, +			//size_t _Size = static_cast<size_t>(BUFSIZ)); +			size_t _Size = static_cast<size_t>(1)); +#endif -	explicit llofstream(const std::string& _Filename, std::_Ios_Openmode _Mode = out) -		: std::ofstream(_Filename.c_str(), _Mode) -	{ -	} +	/** +	 *  @brief  The destructor does nothing. +	 * +	 *  The file is closed by the filebuf object, not the formatting +	 *  stream. +	*/ +	virtual ~llofstream() {} + +	// Members: +	/** +	 *  @brief  Accessing the underlying buffer. +	 *  @return  The current basic_filebuf buffer. +	 * +	 *  This hides both signatures of std::basic_ios::rdbuf(). +	*/ +	llstdio_filebuf* rdbuf() const +	{ return const_cast<llstdio_filebuf*>(&_M_filebuf); } + +	/** +	 *  @brief  Wrapper to test for an open file. +	 *  @return  @c rdbuf()->is_open() +	*/ +	bool is_open() const; -	void open(const std::string& _Filename, std::_Ios_Openmode _Mode = out)	/* Flawfinder: ignore */ -	{ -		std::ofstream::open(_Filename.c_str(), _Mode); -	} +	/** +	 *  @brief  Opens an external file. +	 *  @param  Filename  The name of the file. +	 *  @param  Node  The open mode flags. +	 * +	 *  Calls @c llstdio_filebuf::open(s,mode|out).  If that function +	 *  fails, @c failbit is set in the stream's error state. +	*/ +	void open(const std::string& _Filename, +			ios_base::openmode _Mode = ios_base::out|ios_base::trunc) +	{ open(_Filename.c_str(), _Mode); } +	void open(const char* _Filename, +			ios_base::openmode _Mode = ios_base::out|ios_base::trunc); + +	/** +	 *  @brief  Close the file. +	 * +	 *  Calls @c llstdio_filebuf::close().  If that function +	 *  fails, @c failbit is set in the stream's error state. +	*/ +	void close(); +private: +	llstdio_filebuf _M_filebuf;  }; -#endif  /**   * @breif filesize helpers. diff --git a/indra/llcommon/llfindlocale.cpp b/indra/llcommon/llfindlocale.cpp index cd7c0c7c09..cd7c0c7c09 100644..100755 --- a/indra/llcommon/llfindlocale.cpp +++ b/indra/llcommon/llfindlocale.cpp diff --git a/indra/llcommon/llfindlocale.h b/indra/llcommon/llfindlocale.h index 6770db5774..6770db5774 100644..100755 --- a/indra/llcommon/llfindlocale.h +++ b/indra/llcommon/llfindlocale.h diff --git a/indra/llcommon/llfixedbuffer.cpp b/indra/llcommon/llfixedbuffer.cpp index d394f179fb..d394f179fb 100644..100755 --- a/indra/llcommon/llfixedbuffer.cpp +++ b/indra/llcommon/llfixedbuffer.cpp diff --git a/indra/llcommon/llfixedbuffer.h b/indra/llcommon/llfixedbuffer.h index 554cf48a4c..554cf48a4c 100644..100755 --- a/indra/llcommon/llfixedbuffer.h +++ b/indra/llcommon/llfixedbuffer.h diff --git a/indra/llcommon/llfoldertype.cpp b/indra/llcommon/llfoldertype.cpp index f6d0f5bce8..f6d0f5bce8 100644..100755 --- a/indra/llcommon/llfoldertype.cpp +++ b/indra/llcommon/llfoldertype.cpp diff --git a/indra/llcommon/llfoldertype.h b/indra/llcommon/llfoldertype.h index a0c847914f..a0c847914f 100644..100755 --- a/indra/llcommon/llfoldertype.h +++ b/indra/llcommon/llfoldertype.h diff --git a/indra/llcommon/llformat.cpp b/indra/llcommon/llformat.cpp index 3b2b3038ea..3b2b3038ea 100644..100755 --- a/indra/llcommon/llformat.cpp +++ b/indra/llcommon/llformat.cpp diff --git a/indra/llcommon/llformat.h b/indra/llcommon/llformat.h index a4ec5e01de..a4ec5e01de 100644..100755 --- a/indra/llcommon/llformat.h +++ b/indra/llcommon/llformat.h diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp index ec64195b21..ec64195b21 100644..100755 --- a/indra/llcommon/llframetimer.cpp +++ b/indra/llcommon/llframetimer.cpp diff --git a/indra/llcommon/llframetimer.h b/indra/llcommon/llframetimer.h index 45754f3785..45754f3785 100644..100755 --- a/indra/llcommon/llframetimer.h +++ b/indra/llcommon/llframetimer.h diff --git a/indra/llcommon/llhandle.h b/indra/llcommon/llhandle.h index 6af5e198d6..401e4d759a 100644..100755 --- a/indra/llcommon/llhandle.h +++ b/indra/llcommon/llhandle.h @@ -194,13 +194,6 @@ public:  		return mHandle;   	} -protected: -	typedef LLHandle<T> handle_type_t; -	LLHandleProvider()  -	{ -		// provided here to enforce T deriving from LLHandleProvider<T> -	}  -  	template <typename U>  	LLHandle<U> getDerivedHandle(typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0) const  	{ @@ -209,6 +202,12 @@ protected:  		return downcast_handle;  	} +protected: +	typedef LLHandle<T> handle_type_t; +	LLHandleProvider()  +	{ +		// provided here to enforce T deriving from LLHandleProvider<T> +	}   private:  	mutable LLRootHandle<T> mHandle; diff --git a/indra/llcommon/llhash.h b/indra/llcommon/llhash.h index c077ebe93f..c077ebe93f 100644..100755 --- a/indra/llcommon/llhash.h +++ b/indra/llcommon/llhash.h diff --git a/indra/llcommon/llheartbeat.cpp b/indra/llcommon/llheartbeat.cpp index 18a0c489bd..18a0c489bd 100644..100755 --- a/indra/llcommon/llheartbeat.cpp +++ b/indra/llcommon/llheartbeat.cpp diff --git a/indra/llcommon/llheartbeat.h b/indra/llcommon/llheartbeat.h index 4a75fcc103..4a75fcc103 100644..100755 --- a/indra/llcommon/llheartbeat.h +++ b/indra/llcommon/llheartbeat.h diff --git a/indra/llcommon/llhttpstatuscodes.h b/indra/llcommon/llhttpstatuscodes.h index 0173461dad..0173461dad 100644..100755 --- a/indra/llcommon/llhttpstatuscodes.h +++ b/indra/llcommon/llhttpstatuscodes.h diff --git a/indra/llcommon/llindexedqueue.h b/indra/llcommon/llindexedqueue.h index aa2675d87d..aa2675d87d 100644..100755 --- a/indra/llcommon/llindexedqueue.h +++ b/indra/llcommon/llindexedqueue.h diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp index db72aa19b9..89c831d296 100644..100755 --- a/indra/llcommon/llinitparam.cpp +++ b/indra/llcommon/llinitparam.cpp @@ -40,7 +40,9 @@ namespace LLInitParam  	{  		const U8* my_addr = reinterpret_cast<const U8*>(this);  		const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block); -		mEnclosingBlockOffset = 0x7FFFffff & (U32)(my_addr - block_addr); +		U32 enclosing_block_offset = 0x7FFFffff & (U32)(my_addr - block_addr); +		mEnclosingBlockOffsetLow = enclosing_block_offset & 0x0000ffff; +		mEnclosingBlockOffsetHigh = (enclosing_block_offset & 0x007f0000) >> 16;  	}  	// @@ -112,6 +114,35 @@ namespace LLInitParam  		std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams));  	} +	void BlockDescriptor::addParam(const ParamDescriptorPtr in_param, const char* char_name) +	{ +		// create a copy of the param descriptor in mAllParams +		// so other data structures can store a pointer to it +		mAllParams.push_back(in_param); +		ParamDescriptorPtr param(mAllParams.back()); + +		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; +		} + +		if (name.empty()) +		{ +			mUnnamedParams.push_back(param); +		} +		else +		{ +			// don't use insert, since we want to overwrite existing entries +			mNamedParams[name] = param; +		} + +		if (param->mValidationFunc) +		{ +			mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc)); +		} +	} +  	BlockDescriptor::BlockDescriptor()  	:	mMaxParamOffset(0),  		mInitializationState(UNINITIALIZED), @@ -150,7 +181,8 @@ namespace LLInitParam  	bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent)  	{ -		if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()), true)) +		Parser::name_stack_range_t range = std::make_pair(name_stack.begin(), name_stack.end()); +		if (!deserializeBlock(p, range, true))  		{  			if (!silent)  			{ @@ -196,12 +228,7 @@ namespace LLInitParam  			if (serialize_func)  			{  				const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; -				// each param descriptor remembers its serial number -				// so we can inspect the same param under different names -				// and see that it has the same number -				name_stack.push_back(std::make_pair("", true));  				serialize_func(*param, parser, name_stack, diff_param); -				name_stack.pop_back();  			}  		} @@ -295,7 +322,7 @@ namespace LLInitParam  		return true;  	} -	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool ignored) +	bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool ignored)  	{  		BlockDescriptor& block_data = mostDerivedBlockDescriptor();  		bool names_left = name_stack_range.first != name_stack_range.second; @@ -308,15 +335,12 @@ namespace LLInitParam  		{  			const std::string& top_name = name_stack_range.first->first; -			ParamDescriptor::deserialize_func_t deserialize_func = NULL; -			Param* paramp = NULL; -  			BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name);  			if (found_it != block_data.mNamedParams.end())  			{  				// find pointer to member parameter from offset table -				paramp = getParamFromHandle(found_it->second->mParamHandle); -				deserialize_func = found_it->second->mDeserializeFunc; +				Param* paramp = getParamFromHandle(found_it->second->mParamHandle); +				ParamDescriptor::deserialize_func_t deserialize_func = found_it->second->mDeserializeFunc;  				Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second);  				++new_name_stack.first; @@ -358,36 +382,6 @@ namespace LLInitParam  		return false;  	} -	//static  -	void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name) -	{ -		// create a copy of the param descriptor in mAllParams -		// so other data structures can store a pointer to it -		block_data.mAllParams.push_back(in_param); -		ParamDescriptorPtr param(block_data.mAllParams.back()); - -		std::string name(char_name); -		if ((size_t)param->mParamHandle > 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; -		} - -		if (name.empty()) -		{ -			block_data.mUnnamedParams.push_back(param); -		} -		else -		{ -			// don't use insert, since we want to overwrite existing entries -			block_data.mNamedParams[name] = param; -		} - -		if (param->mValidationFunc) -		{ -			block_data.mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc)); -		} -	} -  	void BaseBlock::addSynonym(Param& param, const std::string& synonym)  	{  		BlockDescriptor& block_data = mostDerivedBlockDescriptor(); @@ -460,7 +454,7 @@ namespace LLInitParam  			if (merge_func)  			{  				Param* paramp = getParamFromHandle((*it)->mParamHandle); -				llassert(paramp->mEnclosingBlockOffset == (*it)->mParamHandle); +				llassert(paramp->getEnclosingBlockOffset() == (*it)->mParamHandle);  				some_param_changed |= merge_func(*paramp, *other_paramp, overwrite);  			}  		} diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index 9a6d1eff5c..ae836645b9 100644..100755 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -31,12 +31,78 @@  #include <vector>  #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" +namespace LLTypeTags +{ +	template <typename INNER_TYPE, int _SORT_ORDER> +	struct TypeTagBase +	{ +		typedef void		is_tag_t; +		typedef INNER_TYPE	inner_t; +		static const int	SORT_ORDER=_SORT_ORDER; +	}; + +	template <int VAL1, int VAL2> +	struct GreaterThan +	{ +		static const bool value = VAL1 > VAL2; +	}; + +	template<typename ITEM, typename REST, bool NEEDS_SWAP = GreaterThan<ITEM::SORT_ORDER, REST::SORT_ORDER>::value > +	struct Swap +	{ +		typedef typename ITEM::template Cons<REST>::value_t value_t; +	}; + +	template<typename ITEM, typename REST> +	struct Swap<ITEM, REST, true> +	{ +		typedef typename REST::template Cons<Swap<ITEM, typename REST::inner_t>::value_t>::value_t value_t; +	}; + +	template<typename T, typename SORTABLE = void> +	struct IsSortable +	{ +		static const bool value = false; +	}; + +	template<typename T> +	struct IsSortable<T, typename T::is_tag_t> +	{ +		static const bool value = true; +	}; + +	template<typename ITEM, typename REST, bool IS_REST_SORTABLE = IsSortable<REST>::value> +	struct InsertInto +	{ +		typedef typename ITEM::template Cons<REST>::value_t value_t; +	}; + +	template<typename ITEM, typename REST> +	struct InsertInto <ITEM, REST, true> +	{ +		typedef typename Swap<ITEM, REST>::value_t value_t; +	}; + +	template<typename T, bool SORTABLE = IsSortable<T>::value> +	struct Sorted +	{ +		typedef T value_t; +	}; + +	template<typename T> +	struct Sorted <T, true> +	{ +		typedef typename InsertInto<T, typename Sorted<typename T::inner_t>::value_t>::value_t value_t; +	}; +} +  namespace LLInitParam  {  	// used to indicate no matching value to a given name when parsing @@ -44,6 +110,8 @@ namespace LLInitParam  	template<typename T> const T& defaultValue() { static T value; return value; } +	// wraps comparison operator between any 2 values of the same type +	// specialize to handle cases where equality isn't defined well, or at all  	template <typename T, bool IS_BOOST_FUNCTION = boost::is_convertible<T, boost::function_base>::value >      struct ParamCompare   	{ @@ -78,24 +146,123 @@ namespace LLInitParam  	// helper functions and classes  	typedef ptrdiff_t param_handle_t; +	struct IS_A_BLOCK {}; +	struct NOT_BLOCK {}; + +	// these templates allow us to distinguish between template parameters +	// that derive from BaseBlock and those that don't +	template<typename T, typename BLOCK_IDENTIFIER = void> +	struct IsBlock +	{ +		typedef NOT_BLOCK value_t; +	}; + +	template<typename T> +	struct IsBlock<T, typename T::baseblock_base_class_t> +	{ +		typedef IS_A_BLOCK value_t; +	}; + +	// ParamValue class directly manages the wrapped value +	// by holding on to a copy (scalar params) +	// or deriving from it (blocks) +	// has specializations for custom value behavior +	// and "tag" values like Lazy and Atomic +	template<typename T, typename VALUE_IS_BLOCK = typename IsBlock<T>::value_t> +	class ParamValue +	{ +		typedef ParamValue<T, VALUE_IS_BLOCK>	self_t; + +	public: +		typedef T	default_value_t; +		typedef T	value_t; + +		ParamValue(): mValue() {} +		ParamValue(const default_value_t& other) : mValue(other) {} + +		void setValue(const value_t& val) +		{ +			mValue = val; +		} + +		const value_t& getValue() const +		{ +			return mValue; +		} + +		T& getValue() +		{ +			return mValue; +		} + +	protected: +		T mValue; +	}; + +	template<typename T> +	class ParamValue<T, IS_A_BLOCK>  +	:	public T +	{ +		typedef ParamValue<T, IS_A_BLOCK>	self_t; +	public: +		typedef T	default_value_t; +		typedef T	value_t; + +		ParamValue()  +		:	T(), +			mValidated(false) +		{} + +		ParamValue(const default_value_t& other) +		:	T(other), +			mValidated(false) +		{} + +		void setValue(const value_t& val) +		{ +			*this = val; +		} + +		const value_t& getValue() const +		{ +			return *this; +		} + +		T& getValue() +		{ +			return *this; +		} + +	protected: +		mutable bool 	mValidated; // lazy validation flag +	}; +  	// empty default implementation of key cache  	// leverages empty base class optimization  	template <typename T>  	class TypeValues +	:	public ParamValue<typename LLTypeTags::Sorted<T>::value_t>  	{  	private:  		struct Inaccessable{};  	public:  		typedef std::map<std::string, T> value_name_map_t;  		typedef Inaccessable name_t; +		typedef TypeValues<T> type_value_t; +		typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t>	param_value_t; +		typedef typename param_value_t::value_t	value_t; + +		TypeValues(const typename param_value_t::value_t& val) +		:	param_value_t(val) +		{}  		void setValueName(const std::string& key) {}  		std::string getValueName() const { return ""; } -		std::string calcValueName(const T& value) const { return ""; } +		std::string calcValueName(const value_t& value) const { return ""; }  		void clearValueName() const {} -		static bool getValueFromName(const std::string& name, T& value) +		static bool getValueFromName(const std::string& name, value_t& value)  		{  			return false;  		} @@ -110,15 +277,39 @@ namespace LLInitParam  			return NULL;  		} +		void assignNamedValue(const Inaccessable& name) +		{} + +		operator const value_t&() const +		{ +			return param_value_t::getValue(); +		} + +		const value_t& operator()() const +		{ +			return param_value_t::getValue(); +		} +  		static value_name_map_t* getValueNames() {return NULL;}  	}; -	template <typename T, typename DERIVED_TYPE = TypeValues<T> > +	// helper class to implement name value lookups +	// and caching of last used name +	template <typename T, typename DERIVED_TYPE = TypeValues<T>, bool IS_SPECIALIZED = true >  	class TypeValuesHelper +	:	public ParamValue<typename LLTypeTags::Sorted<T>::value_t>  	{ +		typedef TypeValuesHelper<T, DERIVED_TYPE, IS_SPECIALIZED> self_t;  	public:  		typedef typename std::map<std::string, T> value_name_map_t;  		typedef std::string name_t; +		typedef self_t type_value_t; +		typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; +		typedef typename param_value_t::value_t	value_t; + +		TypeValuesHelper(const typename param_value_t::value_t& val) +		:	param_value_t(val) +		{}  		//TODO: cache key by index to save on param block size  		void setValueName(const std::string& value_name)  @@ -131,7 +322,7 @@ namespace LLInitParam  			return mValueName;   		} -		std::string calcValueName(const T& value) const +		std::string calcValueName(const value_t& value) const  		{  			value_name_map_t* map = getValueNames();  			for (typename value_name_map_t::iterator it = map->begin(), end_it = map->end(); @@ -152,7 +343,7 @@ namespace LLInitParam  			mValueName.clear();  		} -		static bool getValueFromName(const std::string& name, T& value) +		static bool getValueFromName(const std::string& name, value_t& value)  		{  			value_name_map_t* map = getValueNames();  			typename value_name_map_t::iterator found_it = map->find(name); @@ -194,24 +385,94 @@ namespace LLInitParam  			return &sValues;  		} -		static void declare(const std::string& name, const T& value) +		static void declare(const std::string& name, const value_t& value)  		{  			(*getValueNames())[name] = value;  		} +		void operator ()(const std::string& name) +		{ +			*this = name; +		} + +		void assignNamedValue(const std::string& name) +		{ +			if (getValueFromName(name, param_value_t::getValue())) +			{ +				setValueName(name); +			} +		} + +		operator const value_t&() const +		{ +			return param_value_t::getValue(); +		} + +		const value_t& operator()() const +		{ +			return param_value_t::getValue(); +		} +  	protected: -		static void getName(const std::string& name, const T& value) +		static void getName(const std::string& name, const value_t& value)  		{}  		mutable std::string	mValueName;  	}; +	// string types can support custom named values, but need +	// to disambiguate in code between a string that is a named value +	// and a string that is a name +	template <typename DERIVED_TYPE> +	class TypeValuesHelper<std::string, DERIVED_TYPE, true> +	:	public TypeValuesHelper<std::string, DERIVED_TYPE, false> +	{ +	public: +		typedef TypeValuesHelper<std::string, DERIVED_TYPE, true> self_t; +		typedef TypeValuesHelper<std::string, DERIVED_TYPE, false> base_t; +		typedef std::string value_t; +		typedef std::string name_t; +		typedef self_t type_value_t; + +		TypeValuesHelper(const std::string& val) +		:	TypeValuesHelper(val) +		{} + +		void operator ()(const std::string& name) +	{ +			*this = name; +		} + +		self_t& operator =(const std::string& name) +		{ +			if (base_t::getValueFromName(name, ParamValue<std::string>::getValue())) +			{ +				base_t::setValueName(name); +			} +			else +			{ +				ParamValue<std::string>::setValue(name); +			} +			return *this; +		} +		 +		operator const value_t&() const +		{ +			return ParamValue<std::string>::getValue(); +		} + +		const value_t& operator()() const +		{ +			return ParamValue<std::string>::getValue(); +		} + +	}; + +	// parser base class with mechanisms for registering readers/writers/inspectors of different types  	class LL_COMMON_API Parser  	{  		LOG_CLASS(Parser); -  	public: -		  		typedef std::vector<std::pair<std::string, bool> >					name_stack_t;  		typedef std::pair<name_stack_t::iterator, name_stack_t::iterator>	name_stack_range_t;  		typedef std::vector<std::string>									possible_values_t; @@ -224,33 +485,58 @@ namespace LLInitParam  		typedef std::map<const std::type_info*, parser_write_func_t>	parser_write_func_map_t;  		typedef std::map<const std::type_info*, parser_inspect_func_t>	parser_inspect_func_map_t; +	public: +  		Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)  		:	mParseSilently(false),  			mParserReadFuncs(&read_map),  			mParserWriteFuncs(&write_map),  			mParserInspectFuncs(&inspect_map)  		{} +  		virtual ~Parser(); -		template <typename T> bool readValue(T& param) -	    { -		    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; -	    } +		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; +			} +			 +		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()) +				{ +					S32 int_value; +					bool parsed = found_it->second(*this, (void*)&int_value); +					param = (T)int_value; +					return parsed; +					} +				} +				return false; +			}  		template <typename T> bool writeValue(const T& param, name_stack_t& name_stack) -		{ -		    parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T)); -		    if (found_it != mParserWriteFuncs->end()) -		    { -			    return found_it->second(*this, (const void*)¶m, name_stack); -		    } -		    return false; -		} +			{ +			parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T)); +			if (found_it != mParserWriteFuncs->end()) +				{ +				return found_it->second(*this, (const void*)¶m, name_stack); +				} +				return false; +			}  		// dispatch inspection to registered inspection functions, for each parameter in a param block  		template <typename T> bool inspectValue(name_stack_t& name_stack, S32 min_count, S32 max_count, const possible_values_t* possible_values) @@ -302,7 +588,7 @@ namespace LLInitParam  		};  		typedef bool(*merge_func_t)(Param&, const Param&, bool); -		typedef bool(*deserialize_func_t)(Param&, Parser&, const Parser::name_stack_range_t&, bool); +		typedef 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 void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count);  		typedef bool(*validation_func_t)(const Param*); @@ -347,6 +633,7 @@ namespace LLInitParam  		} EInitializationState;  		void aggregateBlockData(BlockDescriptor& src_block_data); +		void addParam(ParamDescriptorPtr param, const char* name);  		typedef boost::unordered_map<const std::string, ParamDescriptorPtr>						param_map_t;   		typedef std::vector<ParamDescriptorPtr>													param_list_t;  @@ -362,48 +649,58 @@ namespace LLInitParam  		class BaseBlock*				mCurrentBlockPtr;		// pointer to block currently being constructed  	}; -	class LL_COMMON_API BaseBlock -	{ -	public:  		//TODO: implement in terms of owned_ptr  		template<typename T> -		class Lazy +	class LazyValue  		{  		public: -			Lazy() +		LazyValue()  				: mPtr(NULL)  			{} -			~Lazy() +		~LazyValue()  			{  				delete mPtr;  			} -			Lazy(const Lazy& other) +		LazyValue(const T& value)  			{ -				if (other.mPtr) +			mPtr = new T(value); +		} + +		LazyValue(const LazyValue& other) +		:	mPtr(NULL)  				{ -					mPtr = new T(*other.mPtr); +			*this = other;  				} -				else + +		LazyValue& operator = (const LazyValue& other)  				{ +			if (!other.mPtr) +			{ +				delete mPtr;  					mPtr = NULL;  				} -			} - -			Lazy<T>& operator = (const Lazy<T>& other) +			else  			{ -				if (other.mPtr) +				if (!mPtr)  				{  					mPtr = new T(*other.mPtr);  				}  				else  				{ -					mPtr = NULL; +					*mPtr = *(other.mPtr); +				}  				}  				return *this;  			} +		bool operator==(const LazyValue& other) const +		{ +			if (empty() || other.empty()) return false; +			return *mPtr == *other.mPtr; +		} +  			bool empty() const  			{  				return mPtr == NULL; @@ -411,18 +708,29 @@ namespace LLInitParam  			void set(const T& other)  			{ -				delete mPtr; +			if (!mPtr) +			{  				mPtr = new T(other);  			} +			else +			{ +				*mPtr = other; +			} +		}  			const T& get() const  			{ -				return ensureInstance(); +			return *ensureInstance();  			}  			T& get()  			{ -				return ensureInstance(); +			return *ensureInstance(); +		} + +		operator const T&() const +		{  +			return get();   			}  		private: @@ -437,13 +745,50 @@ namespace LLInitParam  			}  		private: -			// if you get a compilation error with this, that means you are using a forward declared struct for T -			// unfortunately, the type traits we rely on don't work with forward declared typed -			//static const int dummy = sizeof(T);  			mutable T* mPtr;  		}; +	// root class of all parameter blocks + +	class LL_COMMON_API BaseBlock +	{ +	public: +		// lift block tags into baseblock namespace so derived classes do not need to qualify them +		typedef LLInitParam::IS_A_BLOCK IS_A_BLOCK; +		typedef LLInitParam::NOT_BLOCK NOT_A_BLOCK; + +		template<typename T> +		struct Sequential : public LLTypeTags::TypeTagBase<T, 2> +		{ +			template <typename S> struct Cons { typedef Sequential<ParamValue<S> > value_t; }; +			template <typename S> struct Cons<Sequential<S> > { typedef Sequential<S> value_t; }; +		}; + +		template<typename T> +		struct Atomic : public LLTypeTags::TypeTagBase<T, 1> +		{ +			template <typename S> struct Cons { typedef Atomic<ParamValue<S> > value_t; }; +			template <typename S> struct Cons<Atomic<S> > { typedef Atomic<S> value_t; }; +		}; + +		template<typename T, typename BLOCK_T = typename IsBlock<T>::value_t > +		struct Lazy : public LLTypeTags::TypeTagBase<T, 0> +		{ +			template <typename S> struct Cons +			{ +				typedef Lazy<ParamValue<S, BLOCK_T>, BLOCK_T> value_t; +			}; +			template <typename S> struct Cons<Lazy<S, IS_A_BLOCK> > +			{ +				typedef Lazy<S, IS_A_BLOCK> value_t; +			}; +			template <typename S> struct Cons<Lazy<S, NOT_A_BLOCK> > +			{ +				typedef Lazy<S, BLOCK_T> value_t; +			}; +		}; +  		// "Multiple" constraint types, put here in root class to avoid ambiguity during use  		struct AnyAmount  		{ @@ -509,12 +854,12 @@ namespace LLInitParam  		// Blocks can override this to do custom tracking of changes  		virtual void paramChanged(const Param& changed_param, bool user_provided) {} -		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); +		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 inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const; -		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } -		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } +		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } +		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); }  		// take all provided params from other and apply to self  		bool overwriteFrom(const BaseBlock& other) @@ -528,10 +873,17 @@ namespace LLInitParam  			return false;  		} -		static void addParam(BlockDescriptor& block_data, ParamDescriptorPtr param, const char* name); -  		ParamDescriptorPtr findParamDescriptor(const Param& param); +		// take all provided params from other and apply to self +		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); + +		static BlockDescriptor& getBlockDescriptor() +		{ +			static BlockDescriptor sBlockDescriptor; +			return sBlockDescriptor; +		} +  	protected:  		void init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size); @@ -540,25 +892,11 @@ namespace LLInitParam  		{  			return mergeBlock(block_data, source, overwrite);  		} -		// take all provided params from other and apply to self -		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite); - -		static BlockDescriptor& selfBlockDescriptor() -		{ -			static BlockDescriptor sBlockDescriptor; -			return sBlockDescriptor; -		}  	private:  		const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const;  	}; -	template<typename T> -	struct ParamCompare<BaseBlock::Lazy<T>, false > -	{ -		static bool equals(const BaseBlock::Lazy<T>& a, const BaseBlock::Lazy<T>& b) { return !a.empty() || !b.empty(); } -	}; -  	class LL_COMMON_API Param  	{  	public: @@ -587,284 +925,90 @@ namespace LLInitParam  			// get address of enclosing BLOCK class using stored offset to enclosing BaseBlock class  			return *const_cast<BaseBlock*>  				(reinterpret_cast<const BaseBlock*> -					(my_addr - (ptrdiff_t)(S32)mEnclosingBlockOffset)); -		} - -	private: -		friend class BaseBlock; - -		U32		mEnclosingBlockOffset:31; -		U32		mIsProvided:1; - -	}; - -	// these templates allow us to distinguish between template parameters -	// that derive from BaseBlock and those that don't -	template<typename T, typename Void = void> -	struct IsBlock -	{ -		static const bool value = false; -		struct EmptyBase {}; -		typedef EmptyBase base_class_t; -	}; - -	template<typename T> -	struct IsBlock<T, typename T::baseblock_base_class_t> -	{ -		static const bool value = true; -		typedef BaseBlock base_class_t; -	}; - -	template<typename T> -	struct IsBlock<BaseBlock::Lazy<T>, typename T::baseblock_base_class_t > -	{ -		static const bool value = true; -		typedef BaseBlock base_class_t; -	}; - -	template<typename T, typename NAME_VALUE_LOOKUP, bool VALUE_IS_BLOCK = IsBlock<T>::value> -	class ParamValue : public NAME_VALUE_LOOKUP -	{ -	public: -		typedef const T&							value_assignment_t; -		typedef T									value_t; -		typedef ParamValue<T, NAME_VALUE_LOOKUP, VALUE_IS_BLOCK>	self_t; - -		ParamValue(): mValue() {} -		ParamValue(value_assignment_t other) : mValue(other) {} - -		void setValue(value_assignment_t val) -		{ -			mValue = val; -		} - -		value_assignment_t getValue() const -		{ -			return mValue; -		} - -		T& getValue() -		{ -			return mValue; -		} - -		operator value_assignment_t() const -		{ -			return mValue; -		} - -		value_assignment_t operator()() const -		{ -			return mValue; -		} - -		void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name) -		{ -			*this = name; -		} - -		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) -		{ -			if (NAME_VALUE_LOOKUP::getValueFromName(name, mValue)) -			{ -				setValueName(name); -			} - -			return *this; +					(my_addr - (ptrdiff_t)getEnclosingBlockOffset()));  		} -	protected: -		T mValue; -	}; - -	template<typename T, typename NAME_VALUE_LOOKUP> -	class ParamValue<T, NAME_VALUE_LOOKUP, true>  -	:	public T, -		public NAME_VALUE_LOOKUP +		U32 getEnclosingBlockOffset() const  	{ -	public: -		typedef const T&							value_assignment_t; -		typedef T									value_t; -		typedef ParamValue<T, NAME_VALUE_LOOKUP, true>	self_t; - -		ParamValue()  -		:	T(), -			mValidated(false) -		{} - -		ParamValue(value_assignment_t other) -		:	T(other), -			mValidated(false) -		{} - -		void setValue(value_assignment_t val) -		{ -			*this = val; -		} - -		value_assignment_t getValue() const -		{ -			return *this; -		} - -		T& getValue() -		{ -			return *this; -		} - -		operator value_assignment_t() const -		{ -			return *this; -		} -		 -		value_assignment_t operator()() const -		{ -			return *this; -		} - -		void operator ()(const typename NAME_VALUE_LOOKUP::name_t& name) -		{ -			*this = name; -		} - -		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) -		{ -			if (NAME_VALUE_LOOKUP::getValueFromName(name, *this)) -			{ -				setValueName(name); -			} - -			return *this; -		} - -	protected: -		mutable bool 	mValidated; // lazy validation flag -	}; - -	template<typename NAME_VALUE_LOOKUP> -	class ParamValue<std::string, NAME_VALUE_LOOKUP, false> -	: public NAME_VALUE_LOOKUP -	{ -	public: -		typedef const std::string&	value_assignment_t; -		typedef std::string			value_t; -		typedef ParamValue<std::string, NAME_VALUE_LOOKUP, false>	self_t; - -		ParamValue(): mValue() {} -		ParamValue(value_assignment_t other) : mValue(other) {} - -		void setValue(value_assignment_t val) -		{ -			if (NAME_VALUE_LOOKUP::getValueFromName(val, mValue)) -			{ -				NAME_VALUE_LOOKUP::setValueName(val); -			} -			else -			{ -				mValue = val; -			} -		} - -		value_assignment_t getValue() const -		{ -			return mValue; -		} - -		std::string& getValue() -		{ -			return mValue; +			return ((U32)mEnclosingBlockOffsetHigh << 16) | (U32)mEnclosingBlockOffsetLow;  		} -		operator value_assignment_t() const -		{ -			return mValue; -		} +	private: +		friend class BaseBlock; -		value_assignment_t operator()() const -		{ -			return mValue; -		} +		//24 bits for member offset field and 1 bit for provided flag +		U16		mEnclosingBlockOffsetLow; +		U8		mEnclosingBlockOffsetHigh:7; +		U8		mIsProvided:1; -	protected: -		std::string mValue;  	}; -  	template<typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> >  	struct ParamIterator  	{ -		typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::const_iterator		const_iterator; -		typedef typename std::vector<ParamValue<T, NAME_VALUE_LOOKUP> >::iterator			iterator; +		typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t >::const_iterator	const_iterator; +		typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t >::iterator			iterator;  	}; -	// specialize for custom parsing/decomposition of specific classes -	// e.g. TypedParam<LLRect> has left, top, right, bottom, etc... +	// wrapper for parameter with a known type +	// specialized to handle 4 cases: +	// simple "scalar" value +	// parameter that is itself a block +	// multiple scalar values, stored in a vector +	// multiple blocks, stored in a vector  	template<typename	T,  			typename	NAME_VALUE_LOOKUP = TypeValues<T>,  			bool		HAS_MULTIPLE_VALUES = false, -			bool		VALUE_IS_BLOCK = IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value> +			typename	VALUE_IS_BLOCK = typename IsBlock<ParamValue<typename LLTypeTags::Sorted<T>::value_t> >::value_t>  	class TypedParam   	:	public Param,  -		public ParamValue<T, NAME_VALUE_LOOKUP> +		public NAME_VALUE_LOOKUP::type_value_t  	{ +	protected: +		typedef	TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK>	self_t; +		typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t>						param_value_t; +		typedef typename param_value_t::default_value_t									default_value_t; +		typedef typename NAME_VALUE_LOOKUP::type_value_t								named_value_t;  	public: -		typedef	TypedParam<T, NAME_VALUE_LOOKUP, HAS_MULTIPLE_VALUES, VALUE_IS_BLOCK>		self_t; -		typedef ParamValue<T, NAME_VALUE_LOOKUP>											param_value_t; -		typedef typename param_value_t::value_assignment_t				value_assignment_t; -		typedef NAME_VALUE_LOOKUP															name_value_lookup_t; +		typedef typename param_value_t::value_t											value_t; -		using param_value_t::operator(); +		using named_value_t::operator(); -		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  -		:	Param(block_descriptor.mCurrentBlockPtr) +		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), +			named_value_t(value)  		{  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ - 				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( -												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), -												&mergeWith, -												&deserializeParam, -												&serializeParam, -												validate_func, -												&inspectParam, -												min_count, max_count)); -				BaseBlock::addParam(block_descriptor, param_descriptor, name); +				init(block_descriptor, validate_func, min_count, max_count, name);  			} - -			setValue(value);  		}   		bool isProvided() const { return Param::anyProvided(); } -		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) +		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);  			// no further names in stack, attempt to parse value now  			if (name_stack_range.first == name_stack_range.second) -			{ -				if (parser.readValue(typed_param.getValue())) +			{	 +				std::string name; + +				// try to parse a known named value +				if(named_value_t::valueNamesExist() +					&& parser.readValue(name) +					&& named_value_t::getValueFromName(name, typed_param.getValue()))  				{ -					typed_param.clearValueName(); +					typed_param.setValueName(name);  					typed_param.setProvided();  					return true;  				} -				 -				// try to parse a known named value -				if(name_value_lookup_t::valueNamesExist()) +				// try to read value directly +				else if (parser.readValue(typed_param.getValue()))  				{ -					// try to parse a known named value -					std::string name; -					if (parser.readValue(name)) -					{ -						// try to parse a per type named value -						if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) -						{ -							typed_param.setValueName(name); -							typed_param.setProvided(); -							return true; -						} - -					} +					typed_param.clearValueName(); +					typed_param.setProvided(); +					return true;  				}  			}  			return false; @@ -897,7 +1041,9 @@ namespace LLInitParam  				if (!parser.writeValue(typed_param.getValue(), name_stack))   				{  					std::string calculated_key = typed_param.calcValueName(typed_param.getValue()); -					if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key)) +					if (calculated_key.size()  +						&& (!diff_param  +							|| !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key)))  					{  						parser.writeValue(calculated_key, name_stack);  					} @@ -910,22 +1056,23 @@ namespace LLInitParam  			// tell parser about our actual type  			parser.inspectValue<T>(name_stack, min_count, max_count, NULL);  			// then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) -			if (name_value_lookup_t::getPossibleValues()) +			if (named_value_t::getPossibleValues())  			{ -				parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); +				parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());  			}  		} -		void set(value_assignment_t val, bool flag_as_provided = true) +		void set(const value_t& val, bool flag_as_provided = true)  		{ -			param_value_t::clearValueName(); +			named_value_t::clearValueName();  			setValue(val);  			setProvided(flag_as_provided);  		} -		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) +		self_t& operator =(const typename named_value_t::name_t& name)  		{ -			return static_cast<self_t&>(param_value_t::operator =(name)); +			named_value_t::assignNamedValue(name); +			return *this;  		}  	protected: @@ -950,67 +1097,72 @@ namespace LLInitParam  			}  			return false;  		} +	private: +		void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )  +		{ +			ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +				block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +				&mergeWith, +				&deserializeParam, +				&serializeParam, +				validate_func, +				&inspectParam, +				min_count, max_count)); +			block_descriptor.addParam(param_descriptor, name); +		}  	};  	// parameter that is a block  	template <typename T, typename NAME_VALUE_LOOKUP> -	class TypedParam<T, NAME_VALUE_LOOKUP, false, true>  +	class TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK>   	:	public Param, -		public ParamValue<T, NAME_VALUE_LOOKUP> +		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;  	public: -		typedef ParamValue<T, NAME_VALUE_LOOKUP>				param_value_t; -		typedef typename param_value_t::value_assignment_t		value_assignment_t; -		typedef TypedParam<T, NAME_VALUE_LOOKUP, false, true>	self_t; -		typedef NAME_VALUE_LOOKUP								name_value_lookup_t; +		using named_value_t::operator(); +		typedef typename param_value_t::value_t						value_t; -		using param_value_t::operator(); - -		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) +		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_value_t(value) +			named_value_t(value)  		{  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ -				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( -												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), -												&mergeWith, -												&deserializeParam, -												&serializeParam, -												validate_func,  -												&inspectParam, -												min_count, max_count)); -				BaseBlock::addParam(block_descriptor, param_descriptor, name); +				init(block_descriptor, validate_func, min_count, max_count, name);  			}  		} -		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) +		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); -			// attempt to parse block... + +			if (name_stack_range.first == name_stack_range.second) +			{	// try to parse a known named value +				std::string name; + +				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; +				} +			} +			  			if(typed_param.deserializeBlock(parser, name_stack_range, new_name)) -			{ +			{	// attempt to parse block...  				typed_param.clearValueName();  				typed_param.setProvided();  				return true;  			} -			if(name_value_lookup_t::valueNamesExist()) -			{ -				// try to parse a known named value -				std::string name; -				if (parser.readValue(name)) -				{ -					// try to parse a per type named value -					if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) -					{ -						typed_param.setValueName(name); -						typed_param.setProvided(); -						return true; -					} -				} -			}  			return false;  		} @@ -1027,9 +1179,9 @@ namespace LLInitParam  			std::string key = typed_param.getValueName();  			if (!key.empty())  			{ -				if (!parser.writeValue(key, name_stack)) +				if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))  				{ -					return; +					parser.writeValue(key, name_stack);  				}  			}  			else @@ -1040,8 +1192,16 @@ namespace LLInitParam  		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)  		{ -			// I am a param that is also a block, so just recurse into my contents  			const self_t& typed_param = static_cast<const self_t&>(param); + +			// tell parser about our actual type +			parser.inspectValue<value_t>(name_stack, min_count, max_count, NULL); +			// then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) +			if (named_value_t::getPossibleValues()) +			{ +				parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues()); +			} +  			typed_param.inspectBlock(parser, name_stack, min_count, max_count);  		} @@ -1059,32 +1219,34 @@ namespace LLInitParam  		}  		// assign block contents to this param-that-is-a-block -		void set(value_assignment_t val, bool flag_as_provided = true) +		void set(const value_t& val, bool flag_as_provided = true)  		{  			setValue(val); -			param_value_t::clearValueName(); +			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);  		} -		self_t& operator =(const typename NAME_VALUE_LOOKUP::name_t& name) +		self_t& operator =(const typename named_value_t::name_t& name)  		{ -			return static_cast<self_t&>(param_value_t::operator =(name)); +			named_value_t::assignNamedValue(name); +			return *this;  		}  		// propagate changed status up to enclosing block  		/*virtual*/ void paramChanged(const Param& changed_param, bool user_provided)  		{   			param_value_t::paramChanged(changed_param, user_provided); +  			if (user_provided)  			{  				// a child param has been explicitly changed  				// so *some* aspect of this block is now provided  				param_value_t::mValidated = false;  				setProvided(); -				param_value_t::clearValueName(); +				named_value_t::clearValueName();  			}  			else  			{ @@ -1108,7 +1270,7 @@ namespace LLInitParam  			if (src_typed_param.anyProvided())  			{ -				if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::selfBlockDescriptor(), src_typed_param, overwrite)) +				if (dst_typed_param.mergeBlockParam(src_typed_param.isProvided(), dst_typed_param.isProvided(), param_value_t::getBlockDescriptor(), src_typed_param, overwrite))  				{  					dst_typed_param.clearValueName();  					dst_typed_param.setProvided(true); @@ -1117,73 +1279,81 @@ namespace LLInitParam  			}  			return false;  		} + +	private: +		void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )  +		{ +			ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +				block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +				&mergeWith, +				&deserializeParam, +				&serializeParam, +				validate_func,  +				&inspectParam, +				min_count, max_count)); +			block_descriptor.addParam(param_descriptor, name); +		}  	}; -	// container of non-block parameters +	// list of non-block parameters  	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> -	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false>  +	class TypedParam<VALUE_TYPE, 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 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; +		  	public: -		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false>		self_t; -		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>					param_value_t; -		typedef typename std::vector<param_value_t>							container_t; -		typedef const container_t&											value_assignment_t; -  		typedef typename param_value_t::value_t								value_t; -		typedef NAME_VALUE_LOOKUP											name_value_lookup_t; -		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  +		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)  		{  			std::copy(value.begin(), value.end(), std::back_inserter(mValues));  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ -				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( -												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), -												&mergeWith, -												&deserializeParam, -												&serializeParam, -												validate_func, -												&inspectParam, -												min_count, max_count)); -				BaseBlock::addParam(block_descriptor, param_descriptor, name); +				init(block_descriptor, validate_func, min_count, max_count, name); +  			}  		}   		bool isProvided() const { return Param::anyProvided(); } -		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) +		static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)  		{  +			Parser::name_stack_range_t new_name_stack_range(name_stack_range);  			self_t& typed_param = static_cast<self_t&>(param);  			value_t value; + +			// pop first element if empty string +			if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty()) +			{ +				++new_name_stack_range.first; +			} +  			// no further names in stack, attempt to parse value now  			if (name_stack_range.first == name_stack_range.second) -			{ -				// attempt to read value directly -				if (parser.readValue(value)) +			{	 +				std::string name; +				 +				// try to parse a known named value +				if(named_value_t::valueNamesExist() +					&& parser.readValue(name) +					&& named_value_t::getValueFromName(name, value))  				{  					typed_param.add(value); +					typed_param.mValues.back().setValueName(name);  					return true;  				} -				 -				// try to parse a known named value -				if(name_value_lookup_t::valueNamesExist()) +				else if (parser.readValue(value)) 	// attempt to read value directly  				{ -					// try to parse a known named value -					std::string name; -					if (parser.readValue(name)) -					{ -						// try to parse a per type named value -						if (name_value_lookup_t::getValueFromName(name, value)) -						{ -							typed_param.add(value); -							typed_param.mValues.back().setValueName(name); -							return true; -						} - -					} +					typed_param.add(value); +					return true;  				}  			}  			return false; @@ -1192,14 +1362,14 @@ namespace LLInitParam  		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)  		{  			const self_t& typed_param = static_cast<const self_t&>(param); -			if (!typed_param.isProvided() || name_stack.empty()) return; +			if (!typed_param.isProvided()) return;  			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();  				it != end_it;  				++it)  			{  				std::string key = it->getValueName(); -				name_stack.back().second = true; +				name_stack.push_back(std::make_pair(std::string(), true));  				if(key.empty())  				// not parsed via name values, write out value directly @@ -1221,19 +1391,21 @@ namespace LLInitParam  						break;  					}  				} + +				name_stack.pop_back();  			}  		}  		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); -			if (name_value_lookup_t::getPossibleValues()) +			if (named_value_t::getPossibleValues())  			{ -				parser.inspectValue<std::string>(name_stack, min_count, max_count, name_value_lookup_t::getPossibleValues()); +				parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());  			}  		} -		void set(value_assignment_t val, bool flag_as_provided = true) +		void set(const container_t& val, bool flag_as_provided = true)  		{  			mValues = val;  			setProvided(flag_as_provided); @@ -1241,26 +1413,24 @@ namespace LLInitParam  		param_value_t& add()  		{ -			mValues.push_back(param_value_t(value_t())); +			mValues.push_back(value_t());  			Param::setProvided();  			return mValues.back();  		}  		self_t& add(const value_t& item)  		{ -			param_value_t param_value; -			param_value.setValue(item); -			mValues.push_back(param_value); +			mValues.push_back(item);  			setProvided();  			return *this;  		} -		self_t& add(const typename name_value_lookup_t::name_t& name) +		self_t& add(const typename named_value_t::name_t& name)  		{  			value_t value;  			// try to parse a per type named value -			if (name_value_lookup_t::getValueFromName(name, value)) +			if (named_value_t::getValueFromName(name, value))  			{  				add(value);  				mValues.back().setValueName(name); @@ -1270,9 +1440,9 @@ namespace LLInitParam  		}  		// implicit conversion -		operator value_assignment_t() const { return mValues; }  +		operator const container_t&() const { return mValues; }   		// explicit conversion		 -		value_assignment_t operator()() const { return mValues; } +		const container_t& operator()() const { return mValues; }  		typedef typename container_t::iterator iterator;  		typedef typename container_t::const_iterator const_iterator; @@ -1313,78 +1483,98 @@ namespace LLInitParam  		}  		container_t		mValues; + +	private: +		void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )  +		{ +			ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +				block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +				&mergeWith, +				&deserializeParam, +				&serializeParam, +				validate_func, +				&inspectParam, +				min_count, max_count)); +			block_descriptor.addParam(param_descriptor, name); +		}  	}; -	// container of block parameters +	// list of block parameters  	template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> -	class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true>  +	class TypedParam<VALUE_TYPE, 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 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; +		typedef typename container_t::iterator									iterator; +		typedef typename container_t::const_iterator							const_iterator;  	public: -		typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true>	self_t; -		typedef ParamValue<VALUE_TYPE, NAME_VALUE_LOOKUP>				param_value_t; -		typedef typename std::vector<param_value_t>						container_t; -		typedef const container_t&										value_assignment_t;  		typedef typename param_value_t::value_t							value_t; -		typedef NAME_VALUE_LOOKUP										name_value_lookup_t; -		TypedParam(BlockDescriptor& block_descriptor, const char* name, value_assignment_t value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)  +		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)  		{  			std::copy(value.begin(), value.end(), back_inserter(mValues));  			if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  			{ -				ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( -												block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), -												&mergeWith, -												&deserializeParam, -												&serializeParam, -												validate_func, -												&inspectParam, -												min_count, max_count)); -				BaseBlock::addParam(block_descriptor, param_descriptor, name); +				init(block_descriptor, validate_func, min_count, max_count, name);  			}  		}   		bool isProvided() const { return Param::anyProvided(); } -		static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name)  +		static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)   		{  +			Parser::name_stack_range_t new_name_stack_range(name_stack_range);  			self_t& typed_param = static_cast<self_t&>(param);  			bool new_value = false; +			bool new_array_value = false; + +			// pop first element if empty string +			if (new_name_stack_range.first != new_name_stack_range.second && new_name_stack_range.first->first.empty()) +			{ +				new_array_value = new_name_stack_range.first->second; +				++new_name_stack_range.first; +			} -			if (new_name || typed_param.mValues.empty()) +			if (new_name || new_array_value || typed_param.mValues.empty())  			{  				new_value = true;  				typed_param.mValues.push_back(value_t());  			} -  			param_value_t& value = typed_param.mValues.back(); +			if (name_stack_range.first == name_stack_range.second) +			{	// try to parse a known named value +				std::string name; + +				if(named_value_t::valueNamesExist() +					&& parser.readValue(name) +					&& named_value_t::getValueFromName(name, value.getValue())) +				{ +					typed_param.mValues.back().setValueName(name); +					typed_param.setProvided(); +					return true; +				} +			} +  			// attempt to parse block... -			if(value.deserializeBlock(parser, name_stack_range, new_name)) +			if(value.deserializeBlock(parser, new_name_stack_range, new_name))  			{  				typed_param.setProvided(); -				return true; -			} -			else if(name_value_lookup_t::valueNamesExist()) -			{ -				// try to parse a known named value -				std::string name; -				if (parser.readValue(name)) +				if (new_array_value)  				{ -					// try to parse a per type named value -					if (name_value_lookup_t::getValueFromName(name, value.getValue())) -					{ -						typed_param.mValues.back().setValueName(name); -						typed_param.setProvided(); -						return true; -					} - +					name_stack_range.first->second = false;  				} +				return true;  			} +  			if (new_value)  			{	// failed to parse new value, pop it off  				typed_param.mValues.pop_back(); @@ -1396,13 +1586,13 @@ namespace LLInitParam  		static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)  		{  			const self_t& typed_param = static_cast<const self_t&>(param); -			if (!typed_param.isProvided() || name_stack.empty()) return; +			if (!typed_param.isProvided()) return;  			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();  				it != end_it;  				++it)  			{ -				name_stack.back().second = true; +				name_stack.push_back(std::make_pair(std::string(), true));  				std::string key = it->getValueName();  				if (!key.empty()) @@ -1415,16 +1605,27 @@ namespace LLInitParam  				{  					it->serializeBlock(parser, name_stack, NULL);  				} + +				name_stack.pop_back();  			}  		}  		static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)  		{ -			// I am a vector of blocks, so describe my contents recursively -			param_value_t(value_t()).inspectBlock(parser, name_stack, min_count, max_count); +			const param_value_t& value_param = param_value_t(value_t()); + +			// tell parser about our actual type +			parser.inspectValue<value_t>(name_stack, min_count, max_count, NULL); +			// then tell it about string-based alternatives ("red", "blue", etc. for LLColor4) +			if (named_value_t::getPossibleValues()) +			{ +				parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues()); +		} + +			value_param.inspectBlock(parser, name_stack, min_count, max_count);  		} -		void set(value_assignment_t val, bool flag_as_provided = true) +		void set(const container_t& val, bool flag_as_provided = true)  		{  			mValues = val;  			setProvided(flag_as_provided); @@ -1444,12 +1645,12 @@ namespace LLInitParam  			return *this;  		} -		self_t& add(const typename name_value_lookup_t::name_t& name) +		self_t& add(const typename named_value_t::name_t& name)  		{  			value_t value;  			// try to parse a per type named value -			if (name_value_lookup_t::getValueFromName(name, value)) +			if (named_value_t::getValueFromName(name, value))  			{  				add(value);  				mValues.back().setValueName(name); @@ -1458,12 +1659,10 @@ namespace LLInitParam  		}  		// implicit conversion -		operator value_assignment_t() const { return mValues; }  +		operator const container_t&() const { return mValues; }   		// explicit conversion -		value_assignment_t operator()() const { return mValues; } +		const container_t& operator()() const { return mValues; } -		typedef typename container_t::iterator iterator; -		typedef typename container_t::const_iterator const_iterator;  		iterator begin() { return mValues.begin(); }  		iterator end() { return mValues.end(); }  		const_iterator begin() const { return mValues.begin(); } @@ -1510,6 +1709,20 @@ namespace LLInitParam  		}  		container_t			mValues; + +	private: +		void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )  +		{ +			ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( +				block_descriptor.mCurrentBlockPtr->getHandleFromParam(this), +				&mergeWith, +				&deserializeParam, +				&serializeParam, +				validate_func, +				&inspectParam, +				min_count, max_count)); +			block_descriptor.addParam(param_descriptor, name); +		}  	};  	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock> @@ -1524,13 +1737,13 @@ namespace LLInitParam  		// take all provided params from other and apply to self  		bool overwriteFrom(const self_t& other)  		{ -			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true); +			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, true);  		}  		// take all provided params that are not already provided, and apply to self  		bool fillFrom(const self_t& other)  		{ -			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false); +			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, false);  		}  		bool mergeBlockParam(bool source_provided, bool dest_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) @@ -1548,7 +1761,7 @@ namespace LLInitParam  		bool mergeBlock(BlockDescriptor& block_data, const self_t& other, bool overwrite)  		{  			mCurChoice = other.mCurChoice; -			return base_block_t::mergeBlock(selfBlockDescriptor(), other, overwrite); +			return base_block_t::mergeBlock(getBlockDescriptor(), other, overwrite);  		}  		// clear out old choice when param has changed @@ -1569,38 +1782,38 @@ namespace LLInitParam  			base_block_t::paramChanged(changed_param, user_provided);  		} -		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } -		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } +		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } +		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); }  	protected:  		ChoiceBlock()  		:	mCurChoice(0)  		{ -			BaseBlock::init(selfBlockDescriptor(), base_block_t::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); +			BaseBlock::init(getBlockDescriptor(), base_block_t::getBlockDescriptor(), sizeof(DERIVED_BLOCK));  		}  		// Alternatives are mutually exclusive wrt other Alternatives in the same block.    		// One alternative in a block will always have isChosen() == true.  		// At most one alternative in a block will have isProvided() == true. -		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > +		template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >  		class Alternative : public TypedParam<T, NAME_VALUE_LOOKUP, false>  		{ +			typedef TypedParam<T, NAME_VALUE_LOOKUP, false>	super_t; +			typedef typename super_t::value_t				value_t; +			typedef typename super_t::default_value_t		default_value_t; +  		public:  			friend class ChoiceBlock<DERIVED_BLOCK>; -			typedef Alternative<T, NAME_VALUE_LOOKUP>									self_t; -			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t; -			typedef typename super_t::value_assignment_t								value_assignment_t; -  			using super_t::operator =; -			explicit Alternative(const char* name = "", value_assignment_t val = defaultValue<T>()) -			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1), +			explicit Alternative(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) +			:	super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1),  				mOriginalValue(val)  			{  				// assign initial choice to first declared option -				DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr); -				if (LL_UNLIKELY(DERIVED_BLOCK::selfBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING)) +				DERIVED_BLOCK* blockp = ((DERIVED_BLOCK*)DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr); +				if (LL_UNLIKELY(DERIVED_BLOCK::getBlockDescriptor().mInitializationState == BlockDescriptor::INITIALIZING))  				{  					if(blockp->mCurChoice == 0)  					{ @@ -1614,27 +1827,27 @@ namespace LLInitParam  				static_cast<enclosing_block_t&>(Param::enclosingBlock()).paramChanged(*this, true);  			} -			void chooseAs(value_assignment_t val) +			void chooseAs(const value_t& val)  			{  				super_t::set(val);  			} -			void operator =(value_assignment_t val) +			void operator =(const value_t& val)  			{  				super_t::set(val);  			} -			void operator()(typename super_t::value_assignment_t val)  +			void operator()(const value_t& val)   			{   				super_t::set(val);  			} -			operator value_assignment_t() const  +			operator const value_t&() const   			{  				return (*this)();  			}  -			value_assignment_t operator()() const  +			const value_t& operator()() const   			{   				if (static_cast<enclosing_block_t&>(Param::enclosingBlock()).getCurrentChoice() == this)  				{ @@ -1649,11 +1862,11 @@ namespace LLInitParam  			}  		private: -			T			mOriginalValue; +			default_value_t mOriginalValue;  		}; -	protected: -		static BlockDescriptor& selfBlockDescriptor() +	public: +		static BlockDescriptor& getBlockDescriptor()  		{  			static BlockDescriptor sBlockDescriptor;  			return sBlockDescriptor; @@ -1673,6 +1886,8 @@ namespace LLInitParam  	:	public BASE_BLOCK  	{  		typedef Block<DERIVED_BLOCK, BASE_BLOCK>	self_t; + +	protected:  		typedef Block<DERIVED_BLOCK, BASE_BLOCK>	block_t;  	public: @@ -1681,80 +1896,82 @@ namespace LLInitParam  		// take all provided params from other and apply to self  		bool overwriteFrom(const self_t& other)  		{ -			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, true); +			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, true);  		}  		// take all provided params that are not already provided, and apply to self  		bool fillFrom(const self_t& other)  		{ -			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(selfBlockDescriptor(), other, false); +			return static_cast<DERIVED_BLOCK*>(this)->mergeBlock(getBlockDescriptor(), other, false);  		} -		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return selfBlockDescriptor(); } -		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return selfBlockDescriptor(); } +		virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } +		virtual BlockDescriptor& mostDerivedBlockDescriptor() { return getBlockDescriptor(); }  	protected:  		Block()  		{  			//#pragma message("Parsing LLInitParam::Block") -			BaseBlock::init(selfBlockDescriptor(), BASE_BLOCK::selfBlockDescriptor(), sizeof(DERIVED_BLOCK)); +			BaseBlock::init(getBlockDescriptor(), BASE_BLOCK::getBlockDescriptor(), sizeof(DERIVED_BLOCK));  		}  		//  		// Nested classes for declaring parameters  		// -		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > +		template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >  		class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false>  		{ -		public: -			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t; -			typedef typename super_t::value_assignment_t								value_assignment_t; +			typedef TypedParam<T, NAME_VALUE_LOOKUP, false>		super_t; +			typedef typename super_t::value_t					value_t; +			typedef typename super_t::default_value_t			default_value_t; +		public:  			using super_t::operator();  			using super_t::operator =; -			explicit Optional(const char* name = "", value_assignment_t val = defaultValue<T>()) -			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, NULL, 0, 1) +			explicit Optional(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) +			:	super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, NULL, 0, 1)  			{  				//#pragma message("Parsing LLInitParam::Block::Optional")  			} -			Optional& operator =(value_assignment_t val) +			Optional& operator =(const value_t& val)  			{  				set(val);  				return *this;  			} -			DERIVED_BLOCK& operator()(value_assignment_t val) +			DERIVED_BLOCK& operator()(const value_t& val)  			{  				super_t::set(val);  				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock());  			}  		}; -		template <typename T, typename NAME_VALUE_LOOKUP = TypeValues<T> > +		template <typename T, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >  		class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false>  		{ -		public: -			typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>		super_t; +			typedef TypedParam<T, NAME_VALUE_LOOKUP, false>		super_t;  			typedef Mandatory<T, NAME_VALUE_LOOKUP>										self_t; -			typedef typename super_t::value_assignment_t								value_assignment_t; +			typedef typename super_t::value_t					value_t; +			typedef typename super_t::default_value_t			default_value_t; +		public:  			using super_t::operator();  			using super_t::operator =;  			// mandatory parameters require a name to be parseable -			explicit Mandatory(const char* name = "", value_assignment_t val = defaultValue<T>()) -			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, val, &validate, 1, 1) +			explicit Mandatory(const char* name = "", const default_value_t& val = defaultValue<default_value_t>()) +			:	super_t(DERIVED_BLOCK::getBlockDescriptor(), name, val, &validate, 1, 1)  			{} -			Mandatory& operator =(value_assignment_t val) +			Mandatory& operator =(const value_t& val)  			{  				set(val);  				return *this;  			} -			DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) +			DERIVED_BLOCK& operator()(const value_t& val)  			{  				super_t::set(val);  				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); @@ -1768,28 +1985,29 @@ namespace LLInitParam  		}; -		template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = TypeValues<T> > +		template <typename T, typename RANGE = BaseBlock::AnyAmount, typename NAME_VALUE_LOOKUP = typename TypeValues<T>::type_value_t >  		class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true>  		{ -		public: -			typedef TypedParam<T, NAME_VALUE_LOOKUP, true, IsBlock<ParamValue<T, NAME_VALUE_LOOKUP> >::value>	super_t; +			typedef TypedParam<T, NAME_VALUE_LOOKUP, true>	super_t;  			typedef Multiple<T, RANGE, NAME_VALUE_LOOKUP>							self_t;  			typedef typename super_t::container_t									container_t; -			typedef typename super_t::value_assignment_t							value_assignment_t; +			typedef typename super_t::value_t				value_t; + +		public:  			typedef typename super_t::iterator										iterator;  			typedef typename super_t::const_iterator								const_iterator;  			explicit Multiple(const char* name = "") -			:	super_t(DERIVED_BLOCK::selfBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount) +			:	super_t(DERIVED_BLOCK::getBlockDescriptor(), name, container_t(), &validate, RANGE::minCount, RANGE::maxCount)  			{} -			Multiple& operator =(value_assignment_t val) +			Multiple& operator =(const container_t& val)  			{  				set(val);  				return *this;  			} -			DERIVED_BLOCK& operator()(typename super_t::value_assignment_t val) +			DERIVED_BLOCK& operator()(const container_t& val)  			{  				super_t::set(val);  				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); @@ -1802,13 +2020,15 @@ namespace LLInitParam  			}  		}; -		class Deprecated : public Param +		// can appear in data files, but will ignored during parsing +		// cannot read or write in code +		class Ignored : public Param  		{  		public: -			explicit Deprecated(const char* name) -			:	Param(DERIVED_BLOCK::selfBlockDescriptor().mCurrentBlockPtr) +			explicit Ignored(const char* name) +			:	Param(DERIVED_BLOCK::getBlockDescriptor().mCurrentBlockPtr)  			{ -				BlockDescriptor& block_descriptor = DERIVED_BLOCK::selfBlockDescriptor(); +				BlockDescriptor& block_descriptor = DERIVED_BLOCK::getBlockDescriptor();  				if (LL_UNLIKELY(block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING))  				{  					ParamDescriptorPtr param_descriptor = ParamDescriptorPtr(new ParamDescriptor( @@ -1819,11 +2039,11 @@ namespace LLInitParam  													NULL,  													NULL,   													0, S32_MAX)); -					BaseBlock::addParam(block_descriptor, param_descriptor, name); +					block_descriptor.addParam(param_descriptor, name);  				}  			} -			static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) +			static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)  			{  				if (name_stack_range.first == name_stack_range.second)  				{ @@ -1836,19 +2056,46 @@ namespace LLInitParam  			}  		}; -		// different semantics for documentation purposes, but functionally identical -		typedef Deprecated Ignored; +		// can appear in data files, or be written to in code, but data will be ignored +		// cannot be read in code +		class Deprecated : public Ignored +		{ +		public: +			explicit Deprecated(const char* name) : Ignored(name) {} -	protected: -		static BlockDescriptor& selfBlockDescriptor() +			// dummy writer interfaces +			template<typename T> +			Deprecated& operator =(const T& val) +		{ +				// do nothing +				return *this; +			} + +			template<typename T> +			DERIVED_BLOCK& operator()(const T& val) +			{ +				// do nothing +				return static_cast<DERIVED_BLOCK&>(Param::enclosingBlock()); +			} + +			template<typename T> +			void set(const T& val, bool flag_as_provided = true) +			{ +				// do nothing +			} +		}; + +	public: +		static BlockDescriptor& getBlockDescriptor()  		{  			static BlockDescriptor sBlockDescriptor;  			return sBlockDescriptor;  		} -		template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, bool is_block> +	protected: +		template <typename T, typename NAME_VALUE_LOOKUP, bool multiple, typename is_block>  		void changeDefault(TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>& param,  -			typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_assignment_t value) +			const typename TypedParam<T, NAME_VALUE_LOOKUP, multiple, is_block>::value_t& value)  		{  			if (!param.isProvided())  			{ @@ -1858,204 +2105,420 @@ namespace LLInitParam  	}; -	template <typename DERIVED_BLOCK, typename BASE_BLOCK = BaseBlock> -	class BatchBlock -	:	public Block<DERIVED_BLOCK, BASE_BLOCK> +	template<typename T, typename BLOCK_T> +	struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::IS_A_BLOCK>, BLOCK_T >, void> +	{ +		typedef IS_A_BLOCK value_t; +	}; + +	template<typename T, typename BLOCK_T> +	struct IsBlock<ParamValue<BaseBlock::Lazy<T, BaseBlock::NOT_A_BLOCK>, BLOCK_T >, void> +	{ +		typedef NOT_BLOCK value_t; +	}; + +	template<typename T, typename BLOCK_IDENTIFIER> +	struct IsBlock<ParamValue<BaseBlock::Atomic<T>, typename IsBlock<BaseBlock::Atomic<T> >::value_t >, BLOCK_IDENTIFIER> +	{ +		typedef typename IsBlock<T>::value_t value_t; +	}; + +	template<typename T, typename BLOCK_IDENTIFIER> +	struct IsBlock<ParamValue<BaseBlock::Sequential<T>, typename IsBlock<BaseBlock::Sequential<T> >::value_t >, BLOCK_IDENTIFIER> +	{ +		typedef typename IsBlock<T>::value_t value_t; +	}; + + +	template<typename T> +	struct InnerMostType +	{ +		typedef T value_t; +	}; + +	template<typename T> +	struct InnerMostType<ParamValue<T, NOT_BLOCK> > +	{ +		typedef typename InnerMostType<T>::value_t value_t; +	}; + +	template<typename T> +	struct InnerMostType<ParamValue<T, IS_A_BLOCK> > +	{ +		typedef typename InnerMostType<T>::value_t value_t; +	}; + +	template<typename T, typename BLOCK_T> +	class ParamValue <BaseBlock::Atomic<T>, BLOCK_T>  	{ +		typedef ParamValue <BaseBlock::Atomic<T>, BLOCK_T> self_t; +  	public: -		typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> self_t; -		typedef Block<DERIVED_BLOCK, BASE_BLOCK> super_t; +		typedef typename InnerMostType<T>::value_t	value_t; +		typedef T									default_value_t; + +		ParamValue() +		:	mValue(), +			mValidated(false) +		{} -		BatchBlock() +		ParamValue(const default_value_t& value) +		:	mValue(value), +			mValidated(false)  		{} -		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) +		void setValue(const value_t& val) +		{ +			mValue.setValue(val); +		} + +		const value_t& getValue() const +		{ +			return mValue.getValue(); +		} + +		value_t& getValue() +		{ +			return mValue.getValue(); +		} + +		bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name)  		{  			if (new_name)  			{ -				// reset block -				*static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue(); +				resetToDefault();  			} -			return super_t::deserializeBlock(p, name_stack_range, new_name); +			return mValue.deserializeBlock(p, name_stack_range, new_name);  		} -		bool mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) +		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const  		{ -			if (overwrite) +			const BaseBlock* base_block = diff_block +				? &(diff_block->mValue) +				: NULL; +			mValue.serializeBlock(p, name_stack, 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  			{ -				*static_cast<DERIVED_BLOCK*>(this) = defaultBatchValue(); -				// merge individual parameters into destination -				return super_t::mergeBlock(super_t::selfBlockDescriptor(), other, overwrite); +			return mValue.inspectBlock(p, name_stack, min_count, max_count);  			} -			return false; + +		bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) +		{ +			if ((overwrite && source_provided) // new values coming in on top or... +				|| (!overwrite && !dst_provided)) // values being pushed under with nothing already there +			{ +				// clear away what is there and take the new stuff as a whole +				resetToDefault(); +				return mValue.mergeBlock(block_data, source.getValue(), overwrite);  		} -	protected: -		static const DERIVED_BLOCK& defaultBatchValue() +			 + +			return mValue.mergeBlock(block_data, source.getValue(), overwrite); +		} + +		bool validateBlock(bool emit_errors = true) const +		{ +			return mValue.validateBlock(emit_errors); +		} + +		static BlockDescriptor& getBlockDescriptor()  		{ -			static DERIVED_BLOCK default_value; -			return default_value; +			return value_t::getBlockDescriptor();  		} + + +		mutable bool 	mValidated; // lazy validation flag + +	private: +		void resetToDefault() +		{ +			static T default_value; +			mValue = default_value; +		} + +		T	mValue;  	}; -	// FIXME: this specialization is not currently used, as it only matches against the BatchBlock base class -	// and not the derived class with the actual params -	template<typename DERIVED_BLOCK, -			typename BASE_BLOCK, -			typename NAME_VALUE_LOOKUP> -	class ParamValue <BatchBlock<DERIVED_BLOCK, BASE_BLOCK>, -					NAME_VALUE_LOOKUP, -					true> -	:	public NAME_VALUE_LOOKUP, -		protected BatchBlock<DERIVED_BLOCK, BASE_BLOCK> +	template<typename T> +	class ParamValue <BaseBlock::Sequential<T>, IS_A_BLOCK>  	{ +		typedef ParamValue <BaseBlock::Sequential<T>, IS_A_BLOCK> self_t; +  	public: -		typedef BatchBlock<DERIVED_BLOCK, BASE_BLOCK> block_t; -		typedef const BatchBlock<DERIVED_BLOCK, BASE_BLOCK>&	value_assignment_t; -		typedef block_t value_t; +		typedef typename InnerMostType<T>::value_t	value_t; +		typedef T									default_value_t;  		ParamValue() -		:	block_t(), +		:	mValue(),  			mValidated(false) -		{} +		{ +			mCurParam = getBlockDescriptor().mAllParams.begin(); +		} -		ParamValue(value_assignment_t other) -		:	block_t(other), +		ParamValue(const default_value_t& value) +		:	mValue(value),  			mValidated(false)  		{ +			mCurParam = getBlockDescriptor().mAllParams.begin();  		} -		void setValue(value_assignment_t val) +		void setValue(const value_t& val)  		{ -			*this = val; +			mValue.setValue(val);  		} -		value_assignment_t getValue() const +		const value_t& getValue() const  		{ -			return *this; +			return mValue.getValue();  		} -		BatchBlock<DERIVED_BLOCK, BASE_BLOCK>& getValue() +		value_t& getValue()  		{ -			return *this; +			return mValue.getValue();  		} -		operator value_assignment_t() const +		bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name)  		{ -			return *this; +			if (new_name) +			{ +				mCurParam = getBlockDescriptor().mAllParams.begin();  		} +			if (name_stack_range.first == name_stack_range.second  +				&& mCurParam != getBlockDescriptor().mAllParams.end()) +			{ +				// deserialize to mCurParam +				ParamDescriptor& pd = *(*mCurParam); +				ParamDescriptor::deserialize_func_t deserialize_func = pd.mDeserializeFunc; +				Param* paramp = mValue.getParamFromHandle(pd.mParamHandle); -		value_assignment_t operator()() const +				if (deserialize_func  +					&& paramp  +					&& deserialize_func(*paramp, p, name_stack_range, new_name))  		{ -			return *this; +					++mCurParam; +					return true; +				} +				else +				{ +					return false; +				} +		} +			else +			{ +				return mValue.deserializeBlock(p, name_stack_range, new_name); +			}  		} -	protected: +		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const +		{ +			const BaseBlock* base_block = diff_block +				? &(diff_block->mValue) +				: NULL; +			mValue.serializeBlock(p, name_stack, 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) +		{ +			return mValue.mergeBlock(block_data, source.getValue(), overwrite); +		} + +		bool validateBlock(bool emit_errors = true) const +		{ +			return mValue.validateBlock(emit_errors); +		} + +		static BlockDescriptor& getBlockDescriptor() +		{ +			return value_t::getBlockDescriptor(); +		} + +		mutable bool 	mValidated; // lazy validation flag + +	private: + +		BlockDescriptor::all_params_list_t::iterator	mCurParam; +		T												mValue; +	}; + +	template<typename T> +	class ParamValue <BaseBlock::Sequential<T>, NOT_BLOCK> +	: public T +	{ +		typedef ParamValue <BaseBlock::Sequential<T>, NOT_BLOCK> self_t; + +	public: +		typedef typename InnerMostType<T>::value_t	value_t; +		typedef T									default_value_t; + +		ParamValue() +		:	T(), +			mValidated(false) +		{} +	 +		ParamValue(const default_value_t& value) +		:	T(value.getValue()), +			mValidated(false) +		{} +  		mutable bool 	mValidated; // lazy validation flag  	}; -	template<typename T, bool IS_BLOCK> -	class ParamValue <BaseBlock::Lazy<T>, -					TypeValues<T>, -					IS_BLOCK> -	:	public IsBlock<T>::base_class_t +	template<typename T, typename BLOCK_T> +	class ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T>   	{ +		typedef ParamValue <BaseBlock::Lazy<T, IS_A_BLOCK>, BLOCK_T> self_t; +  	public: -		typedef ParamValue <BaseBlock::Lazy<T>, TypeValues<T>, false> self_t; -		typedef const T& value_assignment_t; -		typedef T value_t; +		typedef typename InnerMostType<T>::value_t	value_t; +		typedef LazyValue<T>						default_value_t;  		ParamValue()  		:	mValue(),  			mValidated(false)  		{} -		ParamValue(value_assignment_t other) +		ParamValue(const default_value_t& other)  		:	mValue(other),  			mValidated(false)  		{} -		void setValue(value_assignment_t val) +		ParamValue(const T& value) +		:	mValue(value), +			mValidated(false) +		{} + +		void setValue(const value_t& val)  		{  			mValue.set(val);  		} -		value_assignment_t getValue() const +		const value_t& getValue() const  		{ -			return mValue.get(); +			return mValue.get().getValue();  		} -		T& getValue() +		value_t& getValue()  		{ -			return mValue.get(); +			return mValue.get().getValue();  		} -		operator value_assignment_t() const +		bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name)  		{ -			return mValue.get(); +			return mValue.get().deserializeBlock(p, name_stack_range, new_name);  		} -		value_assignment_t operator()() const +		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const  		{ -			return mValue.get(); +			if (mValue.empty()) return; +			 +			const BaseBlock* base_block = (diff_block && !diff_block->mValue.empty()) +											? &(diff_block->mValue.get().getValue()) +											: NULL; +			mValue.get().serializeBlock(p, name_stack, base_block);  		} -		bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name) +		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.get().deserializeBlock(p, name_stack_range, new_name); +			return mValue.get().inspectBlock(p, name_stack, min_count, max_count);  		} -		void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const +		bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)  		{ -			if (mValue.empty()) return; +			return source.mValue.empty() || mValue.get().mergeBlock(block_data, source.getValue(), overwrite); +		} -			mValue.get().serializeBlock(p, name_stack, diff_block); +		bool validateBlock(bool emit_errors = true) const +		{ +			return mValue.empty() || mValue.get().validateBlock(emit_errors);  		} -		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const +		static BlockDescriptor& getBlockDescriptor()  		{ -			if (mValue.empty()) return false; +			return value_t::getBlockDescriptor(); +		} -			return mValue.get().inspectBlock(p, name_stack, min_count, max_count); +		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: +		typedef typename InnerMostType<T>::value_t	value_t; +		typedef LazyValue<T>						default_value_t; + +		ParamValue() +		:	mValue(), +			mValidated(false) +		{} + +		ParamValue(const default_value_t& other) +		:	mValue(other), +			mValidated(false) +		{} + +		ParamValue(const T& value) +		:	mValue(value), +			mValidated(false) +		{} +			 +		void setValue(const value_t& val) +		{ +			mValue.set(val); +		} + +		const value_t& getValue() const +		{ +			return mValue.get().getValue(); +		} + +		value_t& getValue() +		{ +			return mValue.get().getValue();  		} -	protected:  		mutable bool 	mValidated; // lazy validation flag  	private: -		BaseBlock::Lazy<T>	mValue; +		LazyValue<T>	mValue;  	};  	template <> -	class ParamValue <LLSD, -					TypeValues<LLSD>, -					false> -	:	public TypeValues<LLSD>, -		public BaseBlock +	class ParamValue <LLSD, NOT_BLOCK> +	:	public BaseBlock  	{  	public: -		typedef ParamValue<LLSD, TypeValues<LLSD>, false> self_t; -		typedef const LLSD&	value_assignment_t; +		typedef LLSD			value_t; +		typedef LLSD			default_value_t;  		ParamValue()  		:	mValidated(false)  		{} -		ParamValue(value_assignment_t other) +		ParamValue(const default_value_t& other)  		:	mValue(other),  			mValidated(false)  		{} -		void setValue(value_assignment_t val) { mValue = val; } +		void setValue(const value_t& val) { mValue = val; } -		value_assignment_t getValue() const { return mValue; } +		const value_t& getValue() const { return mValue; }  		LLSD& getValue() { return mValue; } -		operator value_assignment_t() const { return mValue; } -		value_assignment_t operator()() const { return mValue; } -		 -  		// block param interface -		LL_COMMON_API bool deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool new_name); +		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;  		bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const  		{ @@ -2074,8 +2537,7 @@ namespace LLInitParam  	template<typename T>  	class CustomParamValue -	:	public Block<ParamValue<T, TypeValues<T> > >, -		public TypeValues<T> +	:	public Block<ParamValue<T> >  	{  	public:  		typedef enum e_value_age @@ -2085,20 +2547,21 @@ namespace LLInitParam  			BLOCK_AUTHORITATIVE		// mValue is derived from the block parameters, which are authoritative  		} EValueAge; -		typedef ParamValue<T, TypeValues<T> >	derived_t; +		typedef ParamValue<T>			derived_t;  		typedef CustomParamValue<T>				self_t;  		typedef Block<derived_t>				block_t; -		typedef const T&						value_assignment_t; +		typedef T						default_value_t;  		typedef T								value_t; +		typedef void					baseblock_base_class_t; -		CustomParamValue(const T& value = T()) +		CustomParamValue(const default_value_t& value = T())  		:	mValue(value),  			mValueAge(VALUE_AUTHORITATIVE),  			mValidated(false)  		{} -		bool deserializeBlock(Parser& parser, Parser::name_stack_range_t name_stack_range, bool new_name) +		bool deserializeBlock(Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)  		{  			derived_t& typed_param = static_cast<derived_t&>(*this);  			// try to parse direct value T @@ -2109,8 +2572,6 @@ namespace LLInitParam  					typed_param.mValueAge = VALUE_AUTHORITATIVE;  					typed_param.updateBlockFromValue(false); -					typed_param.clearValueName(); -  					return true;  				}  			} @@ -2124,18 +2585,8 @@ namespace LLInitParam  			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)) -				{ -					parser.writeValue(key, name_stack); -				} -			}  			// then try to serialize value directly -			else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue())) +			if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue()))              {  				if (!parser.writeValue(typed_param.getValue(), name_stack))  @@ -2165,19 +2616,6 @@ namespace LLInitParam  			}  		} -		bool inspectBlock(Parser& parser, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const -		{ -			// first, inspect with actual type... -			parser.inspectValue<T>(name_stack, min_count, max_count, NULL); -			if (TypeValues<T>::getPossibleValues()) -			{ -				//...then inspect with possible string values... -				parser.inspectValue<std::string>(name_stack, min_count, max_count, TypeValues<T>::getPossibleValues()); -			} -			// then recursively inspect contents... -			return block_t::inspectBlock(parser, name_stack, min_count, max_count); -		} -  		bool validateBlock(bool emit_errors = true) const  		{  			if (mValueAge == VALUE_NEEDS_UPDATE) @@ -2185,7 +2623,6 @@ namespace LLInitParam  				if (block_t::validateBlock(emit_errors))  				{  					// clear stale keyword associated with old value -					TypeValues<T>::clearValueName();  					mValueAge = BLOCK_AUTHORITATIVE;  					static_cast<derived_t*>(const_cast<self_t*>(this))->updateValueFromBlock();  					return true; @@ -2215,17 +2652,15 @@ namespace LLInitParam  			}  		} -		void setValue(value_assignment_t val) +		void setValue(const value_t& val)  		{ -			derived_t& typed_param = static_cast<derived_t&>(*this);  			// set param version number to be up to date, so we ignore block contents  			mValueAge = VALUE_AUTHORITATIVE;  			mValue = val; -			typed_param.clearValueName();  			static_cast<derived_t*>(this)->updateBlockFromValue(false);  		} -		value_assignment_t getValue() const +		const value_t& getValue() const  		{  			validateBlock(true);  			return mValue; @@ -2237,20 +2672,10 @@ namespace LLInitParam  			return mValue;  		} -		operator value_assignment_t() const -		{ -			return getValue(); -		} - -		value_assignment_t operator()() const -		{ -			return getValue(); -		} -  	protected:  		// use this from within updateValueFromBlock() to set the value without making it authoritative -		void updateValue(value_assignment_t value) +		void updateValue(const value_t& value)  		{  			mValue = value;  		} diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp index 5dc3ea5d7b..5dc3ea5d7b 100644..100755 --- a/indra/llcommon/llinstancetracker.cpp +++ b/indra/llcommon/llinstancetracker.cpp diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 403df08990..1eab270e3c 100644..100755 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -43,7 +43,7 @@   * semantics: one instance per process, rather than one instance per module as   * sometimes happens with data simply declared static.   */ -class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable +class LL_COMMON_API LLInstanceTrackerBase  {  protected:  	/// Get a process-unique void* pointer slot for the specified type_info @@ -210,6 +210,9 @@ protected:  	virtual const KEY& getKey() const { return mInstanceKey; }  private: +	LLInstanceTracker( const LLInstanceTracker& ); +	const LLInstanceTracker& operator=( const LLInstanceTracker& ); +  	void add_(KEY key)   	{   		mInstanceKey = key;  diff --git a/indra/llcommon/llkeythrottle.h b/indra/llcommon/llkeythrottle.h index 1f576cc19e..1f576cc19e 100644..100755 --- a/indra/llcommon/llkeythrottle.h +++ b/indra/llcommon/llkeythrottle.h diff --git a/indra/llcommon/llkeyusetracker.h b/indra/llcommon/llkeyusetracker.h index 1fb222dd40..1fb222dd40 100644..100755 --- a/indra/llcommon/llkeyusetracker.h +++ b/indra/llcommon/llkeyusetracker.h diff --git a/indra/llcommon/lllazy.cpp b/indra/llcommon/lllazy.cpp index 29fa040387..29fa040387 100644..100755 --- a/indra/llcommon/lllazy.cpp +++ b/indra/llcommon/lllazy.cpp diff --git a/indra/llcommon/lllazy.h b/indra/llcommon/lllazy.h index 5f3bbce79e..5f3bbce79e 100644..100755 --- a/indra/llcommon/lllazy.h +++ b/indra/llcommon/lllazy.h diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index 0a57ef1c48..0a57ef1c48 100644..100755 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp diff --git a/indra/llcommon/llleap.h b/indra/llcommon/llleap.h index 1a1ad23d39..1a1ad23d39 100644..100755 --- a/indra/llcommon/llleap.h +++ b/indra/llcommon/llleap.h diff --git a/indra/llcommon/llleaplistener.cpp b/indra/llcommon/llleaplistener.cpp index fa5730f112..fa5730f112 100644..100755 --- a/indra/llcommon/llleaplistener.cpp +++ b/indra/llcommon/llleaplistener.cpp diff --git a/indra/llcommon/llleaplistener.h b/indra/llcommon/llleaplistener.h index 2193d81b9e..2193d81b9e 100644..100755 --- a/indra/llcommon/llleaplistener.h +++ b/indra/llcommon/llleaplistener.h diff --git a/indra/llcommon/lllinkedqueue.h b/indra/llcommon/lllinkedqueue.h index 8336608809..8336608809 100644..100755 --- a/indra/llcommon/lllinkedqueue.h +++ b/indra/llcommon/lllinkedqueue.h diff --git a/indra/llcommon/lllistenerwrapper.h b/indra/llcommon/lllistenerwrapper.h index 09d074abca..09d074abca 100644..100755 --- a/indra/llcommon/lllistenerwrapper.h +++ b/indra/llcommon/lllistenerwrapper.h diff --git a/indra/llcommon/llliveappconfig.cpp b/indra/llcommon/llliveappconfig.cpp index 3a3dfa9f28..3a3dfa9f28 100644..100755 --- a/indra/llcommon/llliveappconfig.cpp +++ b/indra/llcommon/llliveappconfig.cpp diff --git a/indra/llcommon/llliveappconfig.h b/indra/llcommon/llliveappconfig.h index 4fd7c26a07..4fd7c26a07 100644..100755 --- a/indra/llcommon/llliveappconfig.h +++ b/indra/llcommon/llliveappconfig.h diff --git a/indra/llcommon/lllivefile.cpp b/indra/llcommon/lllivefile.cpp index c1987baf55..c1987baf55 100644..100755 --- a/indra/llcommon/lllivefile.cpp +++ b/indra/llcommon/lllivefile.cpp diff --git a/indra/llcommon/lllivefile.h b/indra/llcommon/lllivefile.h index 320aa4bc3e..320aa4bc3e 100644..100755 --- a/indra/llcommon/lllivefile.h +++ b/indra/llcommon/lllivefile.h diff --git a/indra/llcommon/lllocalidhashmap.h b/indra/llcommon/lllocalidhashmap.h index 8f4f91a560..8f4f91a560 100644..100755 --- a/indra/llcommon/lllocalidhashmap.h +++ b/indra/llcommon/lllocalidhashmap.h diff --git a/indra/llcommon/lllog.cpp b/indra/llcommon/lllog.cpp index fc4058b5c9..fc4058b5c9 100644..100755 --- a/indra/llcommon/lllog.cpp +++ b/indra/llcommon/lllog.cpp diff --git a/indra/llcommon/lllog.h b/indra/llcommon/lllog.h index 7964412e83..7964412e83 100644..100755 --- a/indra/llcommon/lllog.h +++ b/indra/llcommon/lllog.h diff --git a/indra/llcommon/lllslconstants.h b/indra/llcommon/lllslconstants.h index 9f32598e61..9f32598e61 100644..100755 --- a/indra/llcommon/lllslconstants.h +++ b/indra/llcommon/lllslconstants.h diff --git a/indra/llcommon/llmap.h b/indra/llcommon/llmap.h index 6294a15d3b..6294a15d3b 100644..100755 --- a/indra/llcommon/llmap.h +++ b/indra/llcommon/llmap.h diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp index 1409c55d1c..1409c55d1c 100644..100755 --- a/indra/llcommon/llmd5.cpp +++ b/indra/llcommon/llmd5.cpp diff --git a/indra/llcommon/llmd5.h b/indra/llcommon/llmd5.h index 1526e6ac3c..1526e6ac3c 100644..100755 --- a/indra/llcommon/llmd5.h +++ b/indra/llcommon/llmd5.h diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index 70ad10ad55..70ad10ad55 100644..100755 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 10013e0f92..e725bdd9fa 100644..100755 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -26,7 +26,9 @@  #ifndef LLMEMORY_H  #define LLMEMORY_H -#include "llmemtype.h" +#include "linden_common.h" + +class LLMutex ;  #if LL_WINDOWS && LL_DEBUG  #define LL_CHECK_MEMORY llassert(_CrtCheckMemory()); diff --git a/indra/llcommon/llmemorystream.cpp b/indra/llcommon/llmemorystream.cpp index 723d94f025..723d94f025 100644..100755 --- a/indra/llcommon/llmemorystream.cpp +++ b/indra/llcommon/llmemorystream.cpp diff --git a/indra/llcommon/llmemorystream.h b/indra/llcommon/llmemorystream.h index e28f012192..e28f012192 100644..100755 --- a/indra/llcommon/llmemorystream.h +++ b/indra/llcommon/llmemorystream.h diff --git a/indra/llcommon/llmemtype.cpp b/indra/llcommon/llmemtype.cpp deleted file mode 100644 index 6290a7158f..0000000000 --- a/indra/llcommon/llmemtype.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/**  - * @file llmemtype.cpp - * @brief Simple memory allocation/deallocation tracking stuff here - * - * $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$ - */ - -#include "llmemtype.h" -#include "llallocator.h" - -std::vector<char const *> LLMemType::DeclareMemType::mNameList; - -LLMemType::DeclareMemType LLMemType::MTYPE_INIT("Init"); -LLMemType::DeclareMemType LLMemType::MTYPE_STARTUP("Startup"); -LLMemType::DeclareMemType LLMemType::MTYPE_MAIN("Main"); -LLMemType::DeclareMemType LLMemType::MTYPE_FRAME("Frame"); - -LLMemType::DeclareMemType LLMemType::MTYPE_GATHER_INPUT("GatherInput"); -LLMemType::DeclareMemType LLMemType::MTYPE_JOY_KEY("JoyKey"); - -LLMemType::DeclareMemType LLMemType::MTYPE_IDLE("Idle"); -LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_PUMP("IdlePump"); -LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_NETWORK("IdleNetwork"); -LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_REGIONS("IdleUpdateRegions"); -LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_VIEWER_REGION("IdleUpdateViewerRegion"); -LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_SURFACE("IdleUpdateSurface"); -LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_PARCEL_OVERLAY("IdleUpdateParcelOverlay"); -LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_AUDIO("IdleAudio"); - -LLMemType::DeclareMemType LLMemType::MTYPE_CACHE_PROCESS_PENDING("CacheProcessPending"); -LLMemType::DeclareMemType LLMemType::MTYPE_CACHE_PROCESS_PENDING_ASKS("CacheProcessPendingAsks"); -LLMemType::DeclareMemType LLMemType::MTYPE_CACHE_PROCESS_PENDING_REPLIES("CacheProcessPendingReplies"); - -LLMemType::DeclareMemType LLMemType::MTYPE_MESSAGE_CHECK_ALL("MessageCheckAll"); -LLMemType::DeclareMemType LLMemType::MTYPE_MESSAGE_PROCESS_ACKS("MessageProcessAcks"); - -LLMemType::DeclareMemType LLMemType::MTYPE_RENDER("Render"); -LLMemType::DeclareMemType LLMemType::MTYPE_SLEEP("Sleep"); - -LLMemType::DeclareMemType LLMemType::MTYPE_NETWORK("Network"); -LLMemType::DeclareMemType LLMemType::MTYPE_PHYSICS("Physics"); -LLMemType::DeclareMemType LLMemType::MTYPE_INTERESTLIST("InterestList"); - -LLMemType::DeclareMemType LLMemType::MTYPE_IMAGEBASE("ImageBase"); -LLMemType::DeclareMemType LLMemType::MTYPE_IMAGERAW("ImageRaw"); -LLMemType::DeclareMemType LLMemType::MTYPE_IMAGEFORMATTED("ImageFormatted"); -		 -LLMemType::DeclareMemType LLMemType::MTYPE_APPFMTIMAGE("AppFmtImage"); -LLMemType::DeclareMemType LLMemType::MTYPE_APPRAWIMAGE("AppRawImage"); -LLMemType::DeclareMemType LLMemType::MTYPE_APPAUXRAWIMAGE("AppAuxRawImage"); -		 -LLMemType::DeclareMemType LLMemType::MTYPE_DRAWABLE("Drawable"); - -LLMemType::DeclareMemType LLMemType::MTYPE_OBJECT("Object"); -LLMemType::DeclareMemType LLMemType::MTYPE_OBJECT_PROCESS_UPDATE("ObjectProcessUpdate"); -LLMemType::DeclareMemType LLMemType::MTYPE_OBJECT_PROCESS_UPDATE_CORE("ObjectProcessUpdateCore"); - -LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY("Display"); -LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE("DisplayUpdate"); -LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA("DisplayUpdateCam"); -LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE_GEOM("DisplayUpdateGeom"); -LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_SWAP("DisplaySwap"); -LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE_HUD("DisplayUpdateHud"); -LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_GEN_REFLECTION("DisplayGenRefl"); -LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_IMAGE_UPDATE("DisplayImageUpdate"); -LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_STATE_SORT("DisplayStateSort"); -LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_SKY("DisplaySky"); -LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_GEOM("DisplayRenderGeom"); -LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_FLUSH("DisplayRenderFlush"); -LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_UI("DisplayRenderUI"); -LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_ATTACHMENTS("DisplayRenderAttach"); - -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DATA("VertexData"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CONSTRUCTOR("VertexConstr"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DESTRUCTOR("VertexDestr"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CREATE_VERTICES("VertexCreateVerts"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CREATE_INDICES("VertexCreateIndices"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DESTROY_BUFFER("VertexDestroyBuff");	 -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DESTROY_INDICES("VertexDestroyIndices"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_UPDATE_VERTS("VertexUpdateVerts"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_UPDATE_INDICES("VertexUpdateIndices"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_ALLOCATE_BUFFER("VertexAllocateBuffer"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_RESIZE_BUFFER("VertexResizeBuffer"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_MAP_BUFFER("VertexMapBuffer"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES("VertexMapBufferVerts"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES("VertexMapBufferIndices"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_UNMAP_BUFFER("VertexUnmapBuffer"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_SET_STRIDE("VertexSetStride"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_SET_BUFFER("VertexSetBuffer"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_SETUP_VERTEX_BUFFER("VertexSetupVertBuff"); -LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CLEANUP_CLASS("VertexCleanupClass"); - -LLMemType::DeclareMemType LLMemType::MTYPE_SPACE_PARTITION("SpacePartition"); - -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE("Pipeline"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_INIT("PipelineInit"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_CREATE_BUFFERS("PipelineCreateBuffs"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RESTORE_GL("PipelineRestroGL"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UNLOAD_SHADERS("PipelineUnloadShaders"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_LIGHTING_DETAIL("PipelineLightingDetail"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_GET_POOL_TYPE("PipelineGetPoolType"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_ADD_POOL("PipelineAddPool"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_ALLOCATE_DRAWABLE("PipelineAllocDrawable"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_ADD_OBJECT("PipelineAddObj"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_CREATE_OBJECTS("PipelineCreateObjs"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UPDATE_MOVE("PipelineUpdateMove"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UPDATE_GEOM("PipelineUpdateGeom"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_VISIBLE("PipelineMarkVisible"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_MOVED("PipelineMarkMoved"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_SHIFT("PipelineMarkShift"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_SHIFT_OBJECTS("PipelineShiftObjs"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_TEXTURED("PipelineMarkTextured"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_REBUILD("PipelineMarkRebuild"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UPDATE_CULL("PipelineUpdateCull"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_STATE_SORT("PipelineStateSort"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_POST_SORT("PipelinePostSort"); -		 -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_HUD_ELS("PipelineHudEls"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_HL("PipelineRenderHL"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM("PipelineRenderGeom"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED("PipelineRenderGeomDef"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM_POST_DEF("PipelineRenderGeomPostDef"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM_SHADOW("PipelineRenderGeomShadow"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_SELECT("PipelineRenderSelect"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_REBUILD_POOLS("PipelineRebuildPools"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_QUICK_LOOKUP("PipelineQuickLookup"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_OBJECTS("PipelineRenderObjs"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR("PipelineGenImpostors"); -LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_BLOOM("PipelineRenderBloom"); - -LLMemType::DeclareMemType LLMemType::MTYPE_UPKEEP_POOLS("UpkeepPools"); - -LLMemType::DeclareMemType LLMemType::MTYPE_AVATAR("Avatar"); -LLMemType::DeclareMemType LLMemType::MTYPE_AVATAR_MESH("AvatarMesh"); -LLMemType::DeclareMemType LLMemType::MTYPE_PARTICLES("Particles"); -LLMemType::DeclareMemType LLMemType::MTYPE_REGIONS("Regions"); - -LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY("Inventory"); -LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_DRAW("InventoryDraw"); -LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_BUILD_NEW_VIEWS("InventoryBuildNewViews"); -LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_DO_FOLDER("InventoryDoFolder"); -LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_POST_BUILD("InventoryPostBuild"); -LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_FROM_XML("InventoryFromXML"); -LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_CREATE_NEW_ITEM("InventoryCreateNewItem"); -LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_VIEW_INIT("InventoryViewInit"); -LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_VIEW_SHOW("InventoryViewShow"); -LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_VIEW_TOGGLE("InventoryViewToggle"); - -LLMemType::DeclareMemType LLMemType::MTYPE_ANIMATION("Animation"); -LLMemType::DeclareMemType LLMemType::MTYPE_VOLUME("Volume"); -LLMemType::DeclareMemType LLMemType::MTYPE_PRIMITIVE("Primitive"); -		 -LLMemType::DeclareMemType LLMemType::MTYPE_SCRIPT("Script"); -LLMemType::DeclareMemType LLMemType::MTYPE_SCRIPT_RUN("ScriptRun"); -LLMemType::DeclareMemType LLMemType::MTYPE_SCRIPT_BYTECODE("ScriptByteCode"); -		 -LLMemType::DeclareMemType LLMemType::MTYPE_IO_PUMP("IoPump"); -LLMemType::DeclareMemType LLMemType::MTYPE_IO_TCP("IoTCP"); -LLMemType::DeclareMemType LLMemType::MTYPE_IO_BUFFER("IoBuffer"); -LLMemType::DeclareMemType LLMemType::MTYPE_IO_HTTP_SERVER("IoHttpServer"); -LLMemType::DeclareMemType LLMemType::MTYPE_IO_SD_SERVER("IoSDServer"); -LLMemType::DeclareMemType LLMemType::MTYPE_IO_SD_CLIENT("IoSDClient"); -LLMemType::DeclareMemType LLMemType::MTYPE_IO_URL_REQUEST("IOUrlRequest"); - -LLMemType::DeclareMemType LLMemType::MTYPE_DIRECTX_INIT("DirectXInit"); - -LLMemType::DeclareMemType LLMemType::MTYPE_TEMP1("Temp1"); -LLMemType::DeclareMemType LLMemType::MTYPE_TEMP2("Temp2"); -LLMemType::DeclareMemType LLMemType::MTYPE_TEMP3("Temp3"); -LLMemType::DeclareMemType LLMemType::MTYPE_TEMP4("Temp4"); -LLMemType::DeclareMemType LLMemType::MTYPE_TEMP5("Temp5"); -LLMemType::DeclareMemType LLMemType::MTYPE_TEMP6("Temp6"); -LLMemType::DeclareMemType LLMemType::MTYPE_TEMP7("Temp7"); -LLMemType::DeclareMemType LLMemType::MTYPE_TEMP8("Temp8"); -LLMemType::DeclareMemType LLMemType::MTYPE_TEMP9("Temp9"); - -LLMemType::DeclareMemType LLMemType::MTYPE_OTHER("Other"); - - -LLMemType::DeclareMemType::DeclareMemType(char const * st) -{ -	mID = (S32)mNameList.size(); -	mName = st; - -	mNameList.push_back(mName); -} - -LLMemType::DeclareMemType::~DeclareMemType() -{ -} - -LLMemType::LLMemType(LLMemType::DeclareMemType& dt) -{ -	mTypeIndex = dt.mID; -	LLAllocator::pushMemType(dt.mID); -} - -LLMemType::~LLMemType() -{ -	LLAllocator::popMemType(); -} - -char const * LLMemType::getNameFromID(S32 id) -{ -	if (id < 0 || id >= (S32)DeclareMemType::mNameList.size()) -	{ -		return "INVALID"; -	} - -	return DeclareMemType::mNameList[id]; -} - -//-------------------------------------------------------------------------------------------------- diff --git a/indra/llcommon/llmemtype.h b/indra/llcommon/llmemtype.h deleted file mode 100644 index 4945dbaf60..0000000000 --- a/indra/llcommon/llmemtype.h +++ /dev/null @@ -1,242 +0,0 @@ -/**  - * @file llmemtype.h - * @brief Runtime memory usage debugging utilities. - * - * $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$ - */ - -#ifndef LL_MEMTYPE_H -#define LL_MEMTYPE_H - -//---------------------------------------------------------------------------- -//---------------------------------------------------------------------------- - -//---------------------------------------------------------------------------- - -#include "linden_common.h" -//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -// WARNING: Never commit with MEM_TRACK_MEM == 1 -//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -#define MEM_TRACK_MEM (0 && LL_WINDOWS) - -#include <vector> - -#define MEM_TYPE_NEW(T) - -class LL_COMMON_API LLMemType -{ -public: - -	// class we'll initialize all instances of as -	// static members of MemType.  Then use -	// to construct any new mem type. -	class LL_COMMON_API DeclareMemType -	{ -	public: -		DeclareMemType(char const * st); -		~DeclareMemType(); -	 -		S32 mID; -		char const * mName; -		 -		// array so we can map an index ID to Name -		static std::vector<char const *> mNameList; -	}; - -	LLMemType(DeclareMemType& dt); -	~LLMemType(); - -	static char const * getNameFromID(S32 id); - -	static DeclareMemType MTYPE_INIT; -	static DeclareMemType MTYPE_STARTUP; -	static DeclareMemType MTYPE_MAIN; -	static DeclareMemType MTYPE_FRAME; - -	static DeclareMemType MTYPE_GATHER_INPUT; -	static DeclareMemType MTYPE_JOY_KEY; - -	static DeclareMemType MTYPE_IDLE; -	static DeclareMemType MTYPE_IDLE_PUMP; -	static DeclareMemType MTYPE_IDLE_NETWORK; -	static DeclareMemType MTYPE_IDLE_UPDATE_REGIONS; -	static DeclareMemType MTYPE_IDLE_UPDATE_VIEWER_REGION; -	static DeclareMemType MTYPE_IDLE_UPDATE_SURFACE; -	static DeclareMemType MTYPE_IDLE_UPDATE_PARCEL_OVERLAY; -	static DeclareMemType MTYPE_IDLE_AUDIO; - -	static DeclareMemType MTYPE_CACHE_PROCESS_PENDING; -	static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_ASKS; -	static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_REPLIES; - -	static DeclareMemType MTYPE_MESSAGE_CHECK_ALL; -	static DeclareMemType MTYPE_MESSAGE_PROCESS_ACKS; - -	static DeclareMemType MTYPE_RENDER; -	static DeclareMemType MTYPE_SLEEP; - -	static DeclareMemType MTYPE_NETWORK; -	static DeclareMemType MTYPE_PHYSICS; -	static DeclareMemType MTYPE_INTERESTLIST; - -	static DeclareMemType MTYPE_IMAGEBASE; -	static DeclareMemType MTYPE_IMAGERAW; -	static DeclareMemType MTYPE_IMAGEFORMATTED; -	 -	static DeclareMemType MTYPE_APPFMTIMAGE; -	static DeclareMemType MTYPE_APPRAWIMAGE; -	static DeclareMemType MTYPE_APPAUXRAWIMAGE; -	 -	static DeclareMemType MTYPE_DRAWABLE; -	 -	static DeclareMemType MTYPE_OBJECT; -	static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE; -	static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE_CORE; - -	static DeclareMemType MTYPE_DISPLAY; -	static DeclareMemType MTYPE_DISPLAY_UPDATE; -	static DeclareMemType MTYPE_DISPLAY_UPDATE_CAMERA; -	static DeclareMemType MTYPE_DISPLAY_UPDATE_GEOM; -	static DeclareMemType MTYPE_DISPLAY_SWAP; -	static DeclareMemType MTYPE_DISPLAY_UPDATE_HUD; -	static DeclareMemType MTYPE_DISPLAY_GEN_REFLECTION; -	static DeclareMemType MTYPE_DISPLAY_IMAGE_UPDATE; -	static DeclareMemType MTYPE_DISPLAY_STATE_SORT; -	static DeclareMemType MTYPE_DISPLAY_SKY; -	static DeclareMemType MTYPE_DISPLAY_RENDER_GEOM; -	static DeclareMemType MTYPE_DISPLAY_RENDER_FLUSH; -	static DeclareMemType MTYPE_DISPLAY_RENDER_UI; -	static DeclareMemType MTYPE_DISPLAY_RENDER_ATTACHMENTS; - -	static DeclareMemType MTYPE_VERTEX_DATA; -	static DeclareMemType MTYPE_VERTEX_CONSTRUCTOR; -	static DeclareMemType MTYPE_VERTEX_DESTRUCTOR; -	static DeclareMemType MTYPE_VERTEX_CREATE_VERTICES; -	static DeclareMemType MTYPE_VERTEX_CREATE_INDICES; -	static DeclareMemType MTYPE_VERTEX_DESTROY_BUFFER;	 -	static DeclareMemType MTYPE_VERTEX_DESTROY_INDICES; -	static DeclareMemType MTYPE_VERTEX_UPDATE_VERTS; -	static DeclareMemType MTYPE_VERTEX_UPDATE_INDICES; -	static DeclareMemType MTYPE_VERTEX_ALLOCATE_BUFFER; -	static DeclareMemType MTYPE_VERTEX_RESIZE_BUFFER; -	static DeclareMemType MTYPE_VERTEX_MAP_BUFFER; -	static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_VERTICES; -	static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_INDICES; -	static DeclareMemType MTYPE_VERTEX_UNMAP_BUFFER; -	static DeclareMemType MTYPE_VERTEX_SET_STRIDE; -	static DeclareMemType MTYPE_VERTEX_SET_BUFFER; -	static DeclareMemType MTYPE_VERTEX_SETUP_VERTEX_BUFFER; -	static DeclareMemType MTYPE_VERTEX_CLEANUP_CLASS; - -	static DeclareMemType MTYPE_SPACE_PARTITION; - -	static DeclareMemType MTYPE_PIPELINE; -	static DeclareMemType MTYPE_PIPELINE_INIT; -	static DeclareMemType MTYPE_PIPELINE_CREATE_BUFFERS; -	static DeclareMemType MTYPE_PIPELINE_RESTORE_GL; -	static DeclareMemType MTYPE_PIPELINE_UNLOAD_SHADERS; -	static DeclareMemType MTYPE_PIPELINE_LIGHTING_DETAIL; -	static DeclareMemType MTYPE_PIPELINE_GET_POOL_TYPE; -	static DeclareMemType MTYPE_PIPELINE_ADD_POOL; -	static DeclareMemType MTYPE_PIPELINE_ALLOCATE_DRAWABLE; -	static DeclareMemType MTYPE_PIPELINE_ADD_OBJECT; -	static DeclareMemType MTYPE_PIPELINE_CREATE_OBJECTS; -	static DeclareMemType MTYPE_PIPELINE_UPDATE_MOVE; -	static DeclareMemType MTYPE_PIPELINE_UPDATE_GEOM; -	static DeclareMemType MTYPE_PIPELINE_MARK_VISIBLE; -	static DeclareMemType MTYPE_PIPELINE_MARK_MOVED; -	static DeclareMemType MTYPE_PIPELINE_MARK_SHIFT; -	static DeclareMemType MTYPE_PIPELINE_SHIFT_OBJECTS; -	static DeclareMemType MTYPE_PIPELINE_MARK_TEXTURED; -	static DeclareMemType MTYPE_PIPELINE_MARK_REBUILD; -	static DeclareMemType MTYPE_PIPELINE_UPDATE_CULL; -	static DeclareMemType MTYPE_PIPELINE_STATE_SORT; -	static DeclareMemType MTYPE_PIPELINE_POST_SORT; -	 -	static DeclareMemType MTYPE_PIPELINE_RENDER_HUD_ELS; -	static DeclareMemType MTYPE_PIPELINE_RENDER_HL; -	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM; -	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED; -	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_POST_DEF; -	static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_SHADOW; -	static DeclareMemType MTYPE_PIPELINE_RENDER_SELECT; -	static DeclareMemType MTYPE_PIPELINE_REBUILD_POOLS; -	static DeclareMemType MTYPE_PIPELINE_QUICK_LOOKUP; -	static DeclareMemType MTYPE_PIPELINE_RENDER_OBJECTS; -	static DeclareMemType MTYPE_PIPELINE_GENERATE_IMPOSTOR; -	static DeclareMemType MTYPE_PIPELINE_RENDER_BLOOM; - -	static DeclareMemType MTYPE_UPKEEP_POOLS; - -	static DeclareMemType MTYPE_AVATAR; -	static DeclareMemType MTYPE_AVATAR_MESH; -	static DeclareMemType MTYPE_PARTICLES; -	static DeclareMemType MTYPE_REGIONS; - -	static DeclareMemType MTYPE_INVENTORY; -	static DeclareMemType MTYPE_INVENTORY_DRAW; -	static DeclareMemType MTYPE_INVENTORY_BUILD_NEW_VIEWS; -	static DeclareMemType MTYPE_INVENTORY_DO_FOLDER; -	static DeclareMemType MTYPE_INVENTORY_POST_BUILD; -	static DeclareMemType MTYPE_INVENTORY_FROM_XML; -	static DeclareMemType MTYPE_INVENTORY_CREATE_NEW_ITEM; -	static DeclareMemType MTYPE_INVENTORY_VIEW_INIT; -	static DeclareMemType MTYPE_INVENTORY_VIEW_SHOW; -	static DeclareMemType MTYPE_INVENTORY_VIEW_TOGGLE; - -	static DeclareMemType MTYPE_ANIMATION; -	static DeclareMemType MTYPE_VOLUME; -	static DeclareMemType MTYPE_PRIMITIVE; -	 -	static DeclareMemType MTYPE_SCRIPT; -	static DeclareMemType MTYPE_SCRIPT_RUN; -	static DeclareMemType MTYPE_SCRIPT_BYTECODE; -	 -	static DeclareMemType MTYPE_IO_PUMP; -	static DeclareMemType MTYPE_IO_TCP; -	static DeclareMemType MTYPE_IO_BUFFER; -	static DeclareMemType MTYPE_IO_HTTP_SERVER; -	static DeclareMemType MTYPE_IO_SD_SERVER; -	static DeclareMemType MTYPE_IO_SD_CLIENT; -	static DeclareMemType MTYPE_IO_URL_REQUEST; - -	static DeclareMemType MTYPE_DIRECTX_INIT; - -	static DeclareMemType MTYPE_TEMP1; -	static DeclareMemType MTYPE_TEMP2; -	static DeclareMemType MTYPE_TEMP3; -	static DeclareMemType MTYPE_TEMP4; -	static DeclareMemType MTYPE_TEMP5; -	static DeclareMemType MTYPE_TEMP6; -	static DeclareMemType MTYPE_TEMP7; -	static DeclareMemType MTYPE_TEMP8; -	static DeclareMemType MTYPE_TEMP9; - -	static DeclareMemType MTYPE_OTHER; // Special; used by display code - -	S32 mTypeIndex; -}; - -//---------------------------------------------------------------------------- - -#endif - diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp index 41d3eb0bf3..731e58bd20 100644..100755 --- a/indra/llcommon/llmetricperformancetester.cpp +++ b/indra/llcommon/llmetricperformancetester.cpp @@ -100,7 +100,7 @@ LLSD LLMetricPerformanceTesterBasic::analyzeMetricPerformanceLog(std::istream& i  	LLSD ret;  	LLSD cur; -	while (!is.eof() && LLSDSerialize::fromXML(cur, is)) +	while (!is.eof() && LLSDParser::PARSE_FAILURE != LLSDSerialize::fromXML(cur, is))  	{  		for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter)  		{ diff --git a/indra/llcommon/llmetricperformancetester.h b/indra/llcommon/llmetricperformancetester.h index 1a18cdf36f..1a18cdf36f 100644..100755 --- a/indra/llcommon/llmetricperformancetester.h +++ b/indra/llcommon/llmetricperformancetester.h diff --git a/indra/llcommon/llmetrics.cpp b/indra/llcommon/llmetrics.cpp index 3078139f43..3078139f43 100644..100755 --- a/indra/llcommon/llmetrics.cpp +++ b/indra/llcommon/llmetrics.cpp diff --git a/indra/llcommon/llmetrics.h b/indra/llcommon/llmetrics.h index 4f0ae56338..4f0ae56338 100644..100755 --- a/indra/llcommon/llmetrics.h +++ b/indra/llcommon/llmetrics.h diff --git a/indra/llcommon/llmortician.cpp b/indra/llcommon/llmortician.cpp index 287f096eae..287f096eae 100644..100755 --- a/indra/llcommon/llmortician.cpp +++ b/indra/llcommon/llmortician.cpp diff --git a/indra/llcommon/llmortician.h b/indra/llcommon/llmortician.h index 319955ef93..319955ef93 100644..100755 --- a/indra/llcommon/llmortician.h +++ b/indra/llcommon/llmortician.h diff --git a/indra/llcommon/llnametable.h b/indra/llcommon/llnametable.h index d3283543f3..d3283543f3 100644..100755 --- a/indra/llcommon/llnametable.h +++ b/indra/llcommon/llnametable.h diff --git a/indra/llcommon/lloptioninterface.cpp b/indra/llcommon/lloptioninterface.cpp index 23fae76dc0..23fae76dc0 100644..100755 --- a/indra/llcommon/lloptioninterface.cpp +++ b/indra/llcommon/lloptioninterface.cpp diff --git a/indra/llcommon/lloptioninterface.h b/indra/llcommon/lloptioninterface.h index 93b465db32..93b465db32 100644..100755 --- a/indra/llcommon/lloptioninterface.h +++ b/indra/llcommon/lloptioninterface.h diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h index 88c09c8dca..88c09c8dca 100644..100755 --- a/indra/llcommon/llpointer.h +++ b/indra/llcommon/llpointer.h diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index 7fdb537ab5..7fdb537ab5 100644..100755 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h diff --git a/indra/llcommon/llpriqueuemap.h b/indra/llcommon/llpriqueuemap.h index da997c7b04..da997c7b04 100644..100755 --- a/indra/llcommon/llpriqueuemap.h +++ b/indra/llcommon/llpriqueuemap.h diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp index 715df36f39..715df36f39 100644..100755 --- a/indra/llcommon/llprocess.cpp +++ b/indra/llcommon/llprocess.cpp diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h index d711ce2f74..d711ce2f74 100644..100755 --- a/indra/llcommon/llprocess.h +++ b/indra/llcommon/llprocess.h diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index fd8f603d21..fd8f603d21 100644..100755 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index 6364d3c8bb..6364d3c8bb 100644..100755 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h diff --git a/indra/llcommon/llptrskiplist.h b/indra/llcommon/llptrskiplist.h index 67c7cde352..67c7cde352 100644..100755 --- a/indra/llcommon/llptrskiplist.h +++ b/indra/llcommon/llptrskiplist.h diff --git a/indra/llcommon/llptrskipmap.h b/indra/llcommon/llptrskipmap.h index 94bc71ec55..94bc71ec55 100644..100755 --- a/indra/llcommon/llptrskipmap.h +++ b/indra/llcommon/llptrskipmap.h diff --git a/indra/llcommon/llptrto.cpp b/indra/llcommon/llptrto.cpp index b270291bd6..b270291bd6 100644..100755 --- a/indra/llcommon/llptrto.cpp +++ b/indra/llcommon/llptrto.cpp diff --git a/indra/llcommon/llptrto.h b/indra/llcommon/llptrto.h index 7091d36f6b..7091d36f6b 100644..100755 --- a/indra/llcommon/llptrto.h +++ b/indra/llcommon/llptrto.h diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index abf47a0f57..abf47a0f57 100644..100755 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h index d3704b0fe2..d3704b0fe2 100644..100755 --- a/indra/llcommon/llqueuedthread.h +++ b/indra/llcommon/llqueuedthread.h diff --git a/indra/llcommon/llrand.cpp b/indra/llcommon/llrand.cpp index cb28a8f5c3..cb28a8f5c3 100644..100755 --- a/indra/llcommon/llrand.cpp +++ b/indra/llcommon/llrand.cpp diff --git a/indra/llcommon/llrand.h b/indra/llcommon/llrand.h index ad317d5bf7..ad317d5bf7 100644..100755 --- a/indra/llcommon/llrand.h +++ b/indra/llcommon/llrand.h diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp index e1876599fc..e1876599fc 100644..100755 --- a/indra/llcommon/llrefcount.cpp +++ b/indra/llcommon/llrefcount.cpp diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h index 8eb5d53f3f..32ae15435a 100644..100755 --- a/indra/llcommon/llrefcount.h +++ b/indra/llcommon/llrefcount.h @@ -27,6 +27,7 @@  #define LLREFCOUNT_H  #include <boost/noncopyable.hpp> +#include <boost/intrusive_ptr.hpp>  #define LL_REF_COUNT_DEBUG 0  #if LL_REF_COUNT_DEBUG @@ -86,4 +87,22 @@ private:  #endif  }; +/** + * intrusive pointer support + * this allows you to use boost::intrusive_ptr with any LLRefCount-derived type + */ +namespace boost +{ +	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 853c427a13..bb0d60247e 100644..100755 --- a/indra/llcommon/llregistry.h +++ b/indra/llcommon/llregistry.h @@ -307,6 +307,10 @@ public:  		virtual ~StaticRegistrar() {}  		StaticRegistrar(ref_const_key_t key, ref_const_value_t value)  		{ +			if (singleton_t::instance().exists(key)) +			{ +				llerrs << "Duplicate registry entry under key \"" << key << "\"" << llendl; +			}  			singleton_t::instance().mStaticScope->add(key, value);  		}  	}; diff --git a/indra/llcommon/llrun.cpp b/indra/llcommon/llrun.cpp index f5d3f302fa..f5d3f302fa 100644..100755 --- a/indra/llcommon/llrun.cpp +++ b/indra/llcommon/llrun.cpp diff --git a/indra/llcommon/llrun.h b/indra/llcommon/llrun.h index a117405366..a117405366 100644..100755 --- a/indra/llcommon/llrun.h +++ b/indra/llcommon/llrun.h diff --git a/indra/llcommon/llsafehandle.h b/indra/llcommon/llsafehandle.h index 8d52d9bb15..8d52d9bb15 100644..100755 --- a/indra/llcommon/llsafehandle.h +++ b/indra/llcommon/llsafehandle.h diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index 8276ec836a..8276ec836a 100644..100755 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h index 5eb69059ac..5eb69059ac 100644..100755 --- a/indra/llcommon/llsd.h +++ b/indra/llcommon/llsd.h diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp index 0e29873bb0..9f4460a988 100644..100755 --- a/indra/llcommon/llsdparam.cpp +++ b/indra/llcommon/llsdparam.cpp @@ -223,10 +223,14 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser:  	{  		bool new_traversal = it->second; -		LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first]; - -		if (child_sd->isArray()) +		LLSD* child_sd; +		if (it->first.empty())  		{ +			child_sd = sd_to_write; +			if (child_sd->isUndefined()) +			{ +				*child_sd = LLSD::emptyArray(); +			}  			if (new_traversal)  			{  				// write to new element at end @@ -240,22 +244,7 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser:  		}  		else  		{ -			if (new_traversal  -				&& child_sd->isDefined()  -				&& !child_sd->isArray()) -			{ -				// copy child contents into first element of an array -				LLSD new_array = LLSD::emptyArray(); -				new_array.append(*child_sd); -				// assign array to slot that previously held the single value -				*child_sd = new_array; -				// return next element in that array -				sd_to_write = &((*child_sd)[1]); -			} -			else -			{ -				sd_to_write = child_sd; -			} +			sd_to_write = &(*sd_to_write)[it->first];  		}  		it->second = false;  	} @@ -283,8 +272,9 @@ void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLI  			it != sd.endArray();  			++it)  		{ -			stack.back().second = true; +			stack.push_back(make_pair(std::string(), true));  			readSDValues(cb, *it, stack); +			stack.pop_back();  		}  	}  	else if (sd.isUndefined()) @@ -313,8 +303,14 @@ namespace LLInitParam  {  	// LLSD specialization  	// block param interface -	bool ParamValue<LLSD, TypeValues<LLSD>, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name) +	bool ParamValue<LLSD, NOT_BLOCK>::deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack, bool new_name)  	{ +		if (name_stack.first == name_stack.second +			&& p.readValue<LLSD>(mValue)) +		{ +			return true; +		} +  		LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack);  		LLSD::String string; @@ -328,15 +324,18 @@ namespace LLInitParam  	}  	//static -	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack) +	void ParamValue<LLSD, NOT_BLOCK>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack)  	{  		p.writeValue<LLSD::String>(sd.asString(), name_stack);  	} -	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const +	void ParamValue<LLSD, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const  	{ -		// read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) -		Parser::name_stack_t stack; -		LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack); +		// attempt to write LLSD out directly +		if (!p.writeValue<LLSD>(mValue, name_stack)) +		{ +			// otherwise read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) +			LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack); +		}  	}  } diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h index 6ef5debd7b..6ef5debd7b 100644..100755 --- a/indra/llcommon/llsdparam.h +++ b/indra/llcommon/llsdparam.h diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index 6b549e4b6f..ad4fce6f35 100644..100755 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -1453,8 +1453,8 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option  	case LLSD::TypeUUID:  	{  		ostr.put('u'); -		LLSD::UUID value = data.asUUID(); -		ostr.write((const char*)(&value.mData), UUID_BYTES); +		LLUUID temp = data.asUUID(); +		ostr.write((const char*)(&(temp.mData)), UUID_BYTES);  		break;  	} diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index 86e3fc864c..e7a5507385 100644..100755 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -300,7 +300,7 @@ public:  	/**   	 * @brief Constructor  	 */ -	LLSDXMLParser(); +	LLSDXMLParser(bool emit_errors=true);  protected:  	/**  @@ -747,25 +747,25 @@ public:  		return f->format(sd, str, LLSDFormatter::OPTIONS_PRETTY);  	} -	static S32 fromXMLEmbedded(LLSD& sd, std::istream& str) +	static S32 fromXMLEmbedded(LLSD& sd, std::istream& str, bool emit_errors=true)  	{  		// no need for max_bytes since xml formatting is not  		// subvertable by bad sizes. -		LLPointer<LLSDXMLParser> p = new LLSDXMLParser; +		LLPointer<LLSDXMLParser> p = new LLSDXMLParser(emit_errors);  		return p->parse(str, sd, LLSDSerialize::SIZE_UNLIMITED);  	}  	// Line oriented parser, 30% faster than fromXML(), but can  	// only be used when you know you have the complete XML  	// document available in the stream. -	static S32 fromXMLDocument(LLSD& sd, std::istream& str) +	static S32 fromXMLDocument(LLSD& sd, std::istream& str, bool emit_errors=true)  	{ -		LLPointer<LLSDXMLParser> p = new LLSDXMLParser(); +		LLPointer<LLSDXMLParser> p = new LLSDXMLParser(emit_errors);  		return p->parseLines(str, sd);  	} -	static S32 fromXML(LLSD& sd, std::istream& str) +	static S32 fromXML(LLSD& sd, std::istream& str, bool emit_errors=true)  	{ -		return fromXMLEmbedded(sd, str); -//		return fromXMLDocument(sd, str); +		return fromXMLEmbedded(sd, str, emit_errors); +//		return fromXMLDocument(sd, str, emit_errors);  	}  	/* diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index 34b3dbb99a..614a2d5636 100644..100755 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -250,7 +250,7 @@ std::string LLSDXMLFormatter::escapeString(const std::string& in)  class LLSDXMLParser::Impl  {  public: -	Impl(); +	Impl(bool emit_errors);  	~Impl();  	S32 parse(std::istream& input, LLSD& data); @@ -294,6 +294,7 @@ private:  	static const XML_Char* findAttribute(const XML_Char* name, const XML_Char** pairs); +	bool mEmitErrors;  	XML_Parser	mParser; @@ -315,7 +316,8 @@ private:  }; -LLSDXMLParser::Impl::Impl() +LLSDXMLParser::Impl::Impl(bool emit_errors) +	: mEmitErrors(emit_errors)  {  	mParser = XML_ParserCreate(NULL);  	reset(); @@ -402,7 +404,10 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data)  		{  			((char*) buffer)[count ? count - 1 : 0] = '\0';  		} +		if (mEmitErrors) +		{  		llinfos << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:" << (char*) buffer << llendl; +		}  		data = LLSD();  		return LLSDParser::PARSE_FAILURE;  	} @@ -480,7 +485,10 @@ S32 LLSDXMLParser::Impl::parseLines(std::istream& input, LLSD& data)  	if (status == XML_STATUS_ERROR    		&& !mGracefullStop)  	{ +		if (mEmitErrors) +		{  		llinfos << "LLSDXMLParser::Impl::parseLines: XML_STATUS_ERROR" << llendl; +		}  		return LLSDParser::PARSE_FAILURE;  	} @@ -897,7 +905,7 @@ LLSDXMLParser::Impl::Element LLSDXMLParser::Impl::readElement(const XML_Char* na  /**   * LLSDXMLParser   */ -LLSDXMLParser::LLSDXMLParser() : impl(* new Impl) +LLSDXMLParser::LLSDXMLParser(bool emit_errors /* = true */) : impl(* new Impl(emit_errors))  {  } diff --git a/indra/llcommon/llsdserialize_xml.h b/indra/llcommon/llsdserialize_xml.h index dcc5f3d3c7..dcc5f3d3c7 100644..100755 --- a/indra/llcommon/llsdserialize_xml.h +++ b/indra/llcommon/llsdserialize_xml.h diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp index 803417d368..803417d368 100644..100755 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h index 532d3f9341..532d3f9341 100644..100755 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h diff --git a/indra/llcommon/llsecondlifeurls.cpp b/indra/llcommon/llsecondlifeurls.cpp index 9154e05e43..9154e05e43 100644..100755 --- a/indra/llcommon/llsecondlifeurls.cpp +++ b/indra/llcommon/llsecondlifeurls.cpp diff --git a/indra/llcommon/llsecondlifeurls.h b/indra/llcommon/llsecondlifeurls.h index 62f357ffed..62f357ffed 100644..100755 --- a/indra/llcommon/llsecondlifeurls.h +++ b/indra/llcommon/llsecondlifeurls.h diff --git a/indra/llcommon/llsimplehash.h b/indra/llcommon/llsimplehash.h index 727b4568d8..727b4568d8 100644..100755 --- a/indra/llcommon/llsimplehash.h +++ b/indra/llcommon/llsimplehash.h diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index eb8e2c9456..eb8e2c9456 100644..100755 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 49d99f2cd0..49d99f2cd0 100644..100755 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h diff --git a/indra/llcommon/llskiplist.h b/indra/llcommon/llskiplist.h index ed132381f9..ed132381f9 100644..100755 --- a/indra/llcommon/llskiplist.h +++ b/indra/llcommon/llskiplist.h diff --git a/indra/llcommon/llskipmap.h b/indra/llcommon/llskipmap.h index 49ff2928d1..49ff2928d1 100644..100755 --- a/indra/llcommon/llskipmap.h +++ b/indra/llcommon/llskipmap.h diff --git a/indra/llcommon/llsmoothstep.h b/indra/llcommon/llsmoothstep.h index 1f97a3ec89..1f97a3ec89 100644..100755 --- a/indra/llcommon/llsmoothstep.h +++ b/indra/llcommon/llsmoothstep.h diff --git a/indra/llcommon/llsortedvector.h b/indra/llcommon/llsortedvector.h index 391b82ee44..391b82ee44 100644..100755 --- a/indra/llcommon/llsortedvector.h +++ b/indra/llcommon/llsortedvector.h diff --git a/indra/llcommon/llstack.h b/indra/llcommon/llstack.h index 315de6ba2d..315de6ba2d 100644..100755 --- a/indra/llcommon/llstack.h +++ b/indra/llcommon/llstack.h diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp index ccd7ef91c2..ccd7ef91c2 100644..100755 --- a/indra/llcommon/llstacktrace.cpp +++ b/indra/llcommon/llstacktrace.cpp diff --git a/indra/llcommon/llstacktrace.h b/indra/llcommon/llstacktrace.h index ca72c64c5d..ca72c64c5d 100644..100755 --- a/indra/llcommon/llstacktrace.h +++ b/indra/llcommon/llstacktrace.h diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp index b82d52797e..3678c8e1c1 100644..100755 --- a/indra/llcommon/llstat.cpp +++ b/indra/llcommon/llstat.cpp @@ -37,736 +37,30 @@  // statics -S32	            LLPerfBlock::sStatsFlags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS;       // Control what is being recorded -LLPerfBlock::stat_map_t    LLPerfBlock::sStatMap;    // Map full path string to LLStatTime objects, tracks all active objects -std::string        LLPerfBlock::sCurrentStatPath = "";    // Something like "/total_time/physics/physics step" - -//------------------------------------------------------------------------ -// Live config file to trigger stats logging -static const char    STATS_CONFIG_FILE_NAME[]            = "/dev/shm/simperf/simperf_proc_config.llsd"; -static const F32    STATS_CONFIG_REFRESH_RATE            = 5.0;        // seconds - -class LLStatsConfigFile : public LLLiveFile -{ -public: -    LLStatsConfigFile() -        : LLLiveFile(filename(), STATS_CONFIG_REFRESH_RATE), -        mChanged(false), mStatsp(NULL) { } - -    static std::string filename(); -     -protected: -    /* virtual */ bool loadFile(); - -public: -    void init(LLPerfStats* statsp); -    static LLStatsConfigFile& instance(); -        // return the singleton stats config file - -    bool mChanged; - -protected: -    LLPerfStats*    mStatsp; -}; - -std::string LLStatsConfigFile::filename() -{ -    return STATS_CONFIG_FILE_NAME; -} - -void LLStatsConfigFile::init(LLPerfStats* statsp) -{ -    mStatsp = statsp; -} - -LLStatsConfigFile& LLStatsConfigFile::instance() -{ -    static LLStatsConfigFile the_file; -    return the_file; -} - - -/* virtual */ -// Load and parse the stats configuration file -bool LLStatsConfigFile::loadFile() -{ -    if (!mStatsp) -    { -        llwarns << "Tries to load performance configure file without initializing LPerfStats" << llendl; -        return false; -    } -    mChanged = true; -     -    LLSD stats_config; -    { -        llifstream file(filename().c_str()); -        if (file.is_open()) -        { -            LLSDSerialize::fromXML(stats_config, file); -            if (stats_config.isUndefined()) -            { -                llinfos << "Performance statistics configuration file ill-formed, not recording statistics" << llendl; -                mStatsp->setReportPerformanceDuration( 0.f ); -                return false; -            } -        } -        else  -        {    // File went away, turn off stats if it was on -            if ( mStatsp->frameStatsIsRunning() ) -            { -                llinfos << "Performance statistics configuration file deleted, not recording statistics" << llendl; -                mStatsp->setReportPerformanceDuration( 0.f ); -            } -            return true; -        } -    } - -    F32 duration = 0.f; -    F32 interval = 0.f; -	S32 flags = LLPerfBlock::LLSTATS_BASIC_STATS; - -    const char * w = "duration"; -    if (stats_config.has(w)) -    { -        duration = (F32)stats_config[w].asReal(); -    }  -    w = "interval"; -    if (stats_config.has(w)) -    { -        interval = (F32)stats_config[w].asReal(); -    }  -    w = "flags"; -    if (stats_config.has(w)) -    { -		flags = (S32)stats_config[w].asInteger(); -		if (flags == LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS && -			duration > 0) -		{   // No flags passed in, but have a duration, so reset to basic stats -			flags = LLPerfBlock::LLSTATS_BASIC_STATS; -		} -    }  - -    mStatsp->setReportPerformanceDuration( duration, flags ); -    mStatsp->setReportPerformanceInterval( interval ); - -    if ( duration > 0 ) -    { -        if ( interval == 0.f ) -        { -            llinfos << "Recording performance stats every frame for " << duration << " sec" << llendl; -        } -        else -        { -            llinfos << "Recording performance stats every " << interval << " seconds for " << duration << " seconds" << llendl; -        } -    } -    else -    { -        llinfos << "Performance stats recording turned off" << llendl; -    } -	return true; -} - - -//------------------------------------------------------------------------ - -LLPerfStats::LLPerfStats(const std::string& process_name, S32 process_pid) :  -    mFrameStatsFileFailure(FALSE), -    mSkipFirstFrameStats(FALSE), -    mProcessName(process_name), -    mProcessPID(process_pid), -    mReportPerformanceStatInterval(1.f), -    mReportPerformanceStatEnd(0.0)  -{ } - -LLPerfStats::~LLPerfStats() -{ -    LLPerfBlock::clearDynamicStats(); -    mFrameStatsFile.close(); -} - -void LLPerfStats::init() -{ -    // Initialize the stats config file instance. -    (void) LLStatsConfigFile::instance().init(this); -    (void) LLStatsConfigFile::instance().checkAndReload(); -} - -// Open file for statistics -void    LLPerfStats::openPerfStatsFile() -{ -    if ( !mFrameStatsFile -        && !mFrameStatsFileFailure ) -    { -        std::string stats_file = llformat("/dev/shm/simperf/%s_proc.%d.llsd", mProcessName.c_str(), mProcessPID); -        mFrameStatsFile.close(); -        mFrameStatsFile.clear(); -        mFrameStatsFile.open(stats_file, llofstream::out); -        if ( mFrameStatsFile.fail() ) -        { -            llinfos << "Error opening statistics log file " << stats_file << llendl; -            mFrameStatsFileFailure = TRUE; -        } -        else -        { -            LLSD process_info = LLSD::emptyMap(); -            process_info["name"] = mProcessName; -            process_info["pid"] = (LLSD::Integer) mProcessPID; -            process_info["stat_rate"] = (LLSD::Integer) mReportPerformanceStatInterval; -            // Add process-specific info. -            addProcessHeaderInfo(process_info); - -            mFrameStatsFile << LLSDNotationStreamer(process_info) << std::endl;  -        } -    } -} - -// Dump out performance metrics over some time interval -void LLPerfStats::dumpIntervalPerformanceStats() -{ -    // Ensure output file is OK -    openPerfStatsFile(); - -    if ( mFrameStatsFile ) -    { -        LLSD stats = LLSD::emptyMap(); - -        LLStatAccum::TimeScale scale; -        if ( getReportPerformanceInterval() == 0.f ) -        { -            scale = LLStatAccum::SCALE_PER_FRAME; -        } -        else if ( getReportPerformanceInterval() < 0.5f ) -        { -            scale = LLStatAccum::SCALE_100MS; -        } -        else -        { -            scale = LLStatAccum::SCALE_SECOND; -        } - -        // Write LLSD into log -        stats["utc_time"] = (LLSD::String) LLError::utcTime(); -        stats["timestamp"] = U64_to_str((totalTime() / 1000) + (gUTCOffset * 1000));    // milliseconds since epoch -        stats["frame_number"] = (LLSD::Integer) LLFrameTimer::getFrameCount(); - -        // Add process-specific frame info. -        addProcessFrameInfo(stats, scale); -        LLPerfBlock::addStatsToLLSDandReset( stats, scale ); - -        mFrameStatsFile << LLSDNotationStreamer(stats) << std::endl;  -    } -} - -// Set length of performance stat recording.   -// If turning stats on, caller must provide flags -void    LLPerfStats::setReportPerformanceDuration( F32 seconds, S32 flags /* = LLSTATS_NO_OPTIONAL_STATS */ ) -{  -	if ( seconds <= 0.f ) -	{ -		mReportPerformanceStatEnd = 0.0; -		LLPerfBlock::setStatsFlags(LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS);		// Make sure all recording is off -		mFrameStatsFile.close(); -		LLPerfBlock::clearDynamicStats(); -	} -	else -	{ -		mReportPerformanceStatEnd = LLFrameTimer::getElapsedSeconds() + ((F64) seconds); -		// Clear failure flag to try and create the log file once -		mFrameStatsFileFailure = FALSE; -		mSkipFirstFrameStats = TRUE;		// Skip the first report (at the end of this frame) -		LLPerfBlock::setStatsFlags(flags); -	} -} - -void LLPerfStats::updatePerFrameStats() -{ -    (void) LLStatsConfigFile::instance().checkAndReload(); -	static LLFrameTimer performance_stats_timer; -	if ( frameStatsIsRunning() ) -	{ -		if ( mReportPerformanceStatInterval == 0 ) -		{	// Record info every frame -			if ( mSkipFirstFrameStats ) -			{	// Skip the first time - was started this frame -				mSkipFirstFrameStats = FALSE; -			} -			else -			{ -				dumpIntervalPerformanceStats(); -			} -		} -		else -		{ -			performance_stats_timer.setTimerExpirySec( getReportPerformanceInterval() ); -			if (performance_stats_timer.checkExpirationAndReset( mReportPerformanceStatInterval )) -			{ -				dumpIntervalPerformanceStats(); -			} -		} -		 -		if ( LLFrameTimer::getElapsedSeconds() > mReportPerformanceStatEnd ) -		{	// Reached end of time, clear it to stop reporting -			setReportPerformanceDuration(0.f);			// Don't set mReportPerformanceStatEnd directly	 -            llinfos << "Recording performance stats completed" << llendl; -		} -	} -} - -  //------------------------------------------------------------------------ - -U64 LLStatAccum::sScaleTimes[NUM_SCALES] = -{ -	USEC_PER_SEC / 10,				// 100 millisec -	USEC_PER_SEC * 1,				// seconds -	USEC_PER_SEC * 60,				// minutes -#if ENABLE_LONG_TIME_STATS -	// enable these when more time scales are desired -	USEC_PER_SEC * 60*60,			// hours -	USEC_PER_SEC * 24*60*60,		// days -	USEC_PER_SEC * 7*24*60*60,		// weeks -#endif -}; - - - -LLStatAccum::LLStatAccum(bool useFrameTimer) -	: mUseFrameTimer(useFrameTimer), -	  mRunning(FALSE), -	  mLastTime(0), -	  mLastSampleValue(0.0), -	  mLastSampleValid(FALSE) -{ -} - -LLStatAccum::~LLStatAccum() -{ -} - - - -void LLStatAccum::reset(U64 when) -{ -	mRunning = TRUE; -	mLastTime = when; - -	for (int i = 0; i < NUM_SCALES; ++i) -	{ -		mBuckets[i].accum = 0.0; -		mBuckets[i].endTime = when + sScaleTimes[i]; -		mBuckets[i].lastValid = false; -	} -} - -void LLStatAccum::sum(F64 value) -{ -	sum(value, getCurrentUsecs()); -} - -void LLStatAccum::sum(F64 value, U64 when) -{ -	if (!mRunning) -	{ -		reset(when); -		return; -	} -	if (when < mLastTime) -	{ -		// This happens a LOT on some dual core systems. -		lldebugs << "LLStatAccum::sum clock has gone backwards from " -			<< mLastTime << " to " << when << ", resetting" << llendl; - -		reset(when); -		return; -	} - -	// how long is this value for -	U64 timeSpan = when - mLastTime; - -	for (int i = 0; i < NUM_SCALES; ++i) -	{ -		Bucket& bucket = mBuckets[i]; - -		if (when < bucket.endTime) -		{ -			bucket.accum += value; -		} -		else -		{ -			U64 timeScale = sScaleTimes[i]; - -			U64 timeLeft = when - bucket.endTime; -				// how much time is left after filling this bucket -			 -			if (timeLeft < timeScale) -			{ -				F64 valueLeft = value * timeLeft / timeSpan; - -				bucket.lastValid = true; -				bucket.lastAccum = bucket.accum + (value - valueLeft); -				bucket.accum = valueLeft; -				bucket.endTime += timeScale; -			} -			else -			{ -				U64 timeTail = timeLeft % timeScale; - -				bucket.lastValid = true; -				bucket.lastAccum = value * timeScale / timeSpan; -				bucket.accum = value * timeTail / timeSpan; -				bucket.endTime += (timeLeft - timeTail) + timeScale; -			} -		} -	} - -	mLastTime = when; -} - - -F32 LLStatAccum::meanValue(TimeScale scale) const -{ -	if (!mRunning) -	{ -		return 0.0; -	} -	if ( scale == SCALE_PER_FRAME ) -	{	// Per-frame not supported here -		scale = SCALE_100MS; -	} - -	if (scale < 0 || scale >= NUM_SCALES) -	{ -		llwarns << "llStatAccum::meanValue called for unsupported scale: " -			<< scale << llendl; -		return 0.0; -	} - -	const Bucket& bucket = mBuckets[scale]; - -	F64 value = bucket.accum; -	U64 timeLeft = bucket.endTime - mLastTime; -	U64 scaleTime = sScaleTimes[scale]; - -	if (bucket.lastValid) -	{ -		value += bucket.lastAccum * timeLeft / scaleTime; -	} -	else if (timeLeft < scaleTime) -	{ -		value *= scaleTime / (scaleTime - timeLeft); -	} -	else -	{ -		value = 0.0; -	} - -	return (F32)(value / scaleTime); -} - - -U64 LLStatAccum::getCurrentUsecs() const -{ -	if (mUseFrameTimer) -	{ -		return LLFrameTimer::getTotalTime(); -	} -	else -	{ -		return totalTime(); -	} -} - - -// ------------------------------------------------------------------------ - -LLStatRate::LLStatRate(bool use_frame_timer) -	: LLStatAccum(use_frame_timer) -{ -} - -void LLStatRate::count(U32 value) -{ -	sum((F64)value * sScaleTimes[SCALE_SECOND]); -} - - -void LLStatRate::mark() - {  -	// Effectively the same as count(1), but sets mLastSampleValue -	U64 when = getCurrentUsecs(); - -	if ( mRunning  -		 && (when > mLastTime) ) -	{	// Set mLastSampleValue to the time from the last mark() -		F64 duration = ((F64)(when - mLastTime)) / sScaleTimes[SCALE_SECOND]; -		if ( duration > 0.0 ) -		{ -			mLastSampleValue = 1.0 / duration; -		} -		else -		{ -			mLastSampleValue = 0.0; -		} -	} - -	sum( (F64) sScaleTimes[SCALE_SECOND], when); - } - - -// ------------------------------------------------------------------------ - - -LLStatMeasure::LLStatMeasure(bool use_frame_timer) -	: LLStatAccum(use_frame_timer) -{ -} - -void LLStatMeasure::sample(F64 value) -{ -	U64 when = getCurrentUsecs(); - -	if (mLastSampleValid) -	{ -		F64 avgValue = (value + mLastSampleValue) / 2.0; -		F64 interval = (F64)(when - mLastTime); - -		sum(avgValue * interval, when); -	} -	else -	{ -		reset(when); -	} - -	mLastSampleValid = TRUE; -	mLastSampleValue = value; -} - - -// ------------------------------------------------------------------------ - -LLStatTime::LLStatTime(const std::string & key) -	: LLStatAccum(false), -	  mFrameNumber(LLFrameTimer::getFrameCount()), -	  mTotalTimeInFrame(0), -	  mKey(key) -#if LL_DEBUG -	  , mRunning(FALSE) -#endif -{ -} - -void LLStatTime::start() -{ -	// Reset frame accumluation if the frame number has changed -	U32 frame_number = LLFrameTimer::getFrameCount(); -	if ( frame_number != mFrameNumber ) -	{ -		mFrameNumber = frame_number; -		mTotalTimeInFrame = 0; -	} - -	sum(0.0); - -#if LL_DEBUG -	// Shouldn't be running already -	llassert( !mRunning ); -	mRunning = TRUE; -#endif -} - -void LLStatTime::stop() -{ -	U64 end_time = getCurrentUsecs(); -	U64 duration = end_time - mLastTime; -	sum(F64(duration), end_time); -	//llinfos << "mTotalTimeInFrame incremented from  " << mTotalTimeInFrame << " to " << (mTotalTimeInFrame + duration) << llendl;  -	mTotalTimeInFrame += duration; - -#if LL_DEBUG -	mRunning = FALSE; -#endif -} - -/* virtual */ F32 LLStatTime::meanValue(TimeScale scale) const -{ -    if ( LLStatAccum::SCALE_PER_FRAME == scale ) -    { -        return (F32)mTotalTimeInFrame; -    } -    else -    { -        return LLStatAccum::meanValue(scale); -    } -} - - -// ------------------------------------------------------------------------ - - -// Use this constructor for pre-defined LLStatTime objects -LLPerfBlock::LLPerfBlock(LLStatTime* stat ) : mPredefinedStat(stat), mDynamicStat(NULL) -{ -    if (mPredefinedStat) -    { -        // If dynamic stats are turned on, this will create a separate entry in the stat map. -        initDynamicStat(mPredefinedStat->mKey); - -        // Start predefined stats.  These stats are not part of the stat map. -        mPredefinedStat->start(); -    } -} - -// Use this constructor for normal, optional LLPerfBlock time slices -LLPerfBlock::LLPerfBlock( const char* key ) : mPredefinedStat(NULL), mDynamicStat(NULL) -{ -    if ((sStatsFlags & LLSTATS_BASIC_STATS) == 0) -	{	// These are off unless the base set is enabled -		return; -	} - -	initDynamicStat(key); -} - -	 -// Use this constructor for dynamically created LLPerfBlock time slices -// that are only enabled by specific control flags -LLPerfBlock::LLPerfBlock( const char* key1, const char* key2, S32 flags ) : mPredefinedStat(NULL), mDynamicStat(NULL) -{ -    if ((sStatsFlags & flags) == 0) -	{ -		return; -	} - -    if (NULL == key2 || strlen(key2) == 0) -    { -        initDynamicStat(key1); -    } -    else -    { -        std::ostringstream key; -        key << key1 << "_" << key2; -        initDynamicStat(key.str()); -    } -} - -// Set up the result data map if dynamic stats are enabled -void LLPerfBlock::initDynamicStat(const std::string& key) -{ -    // Early exit if dynamic stats aren't enabled. -    if (sStatsFlags == LLSTATS_NO_OPTIONAL_STATS)  -		return; - -    mLastPath = sCurrentStatPath;		// Save and restore current path -    sCurrentStatPath += "/" + key;		// Add key to current path - -    // See if the LLStatTime object already exists -    stat_map_t::iterator iter = sStatMap.find(sCurrentStatPath); -    if ( iter == sStatMap.end() ) -    { -        // StatEntry object doesn't exist, so create it -        mDynamicStat = new StatEntry( key ); -        sStatMap[ sCurrentStatPath ] = mDynamicStat;	// Set the entry for this path -    } -    else -    { -        // Found this path in the map, use the object there -        mDynamicStat = (*iter).second;		// Get StatEntry for the current path -    } - -    if (mDynamicStat) -    { -        mDynamicStat->mStat.start(); -        mDynamicStat->mCount++; -    } -    else -    { -        llwarns << "Initialized NULL dynamic stat at '" << sCurrentStatPath << "'" << llendl; -       sCurrentStatPath = mLastPath; -    } -} - - -// Destructor does the time accounting -LLPerfBlock::~LLPerfBlock() -{ -    if (mPredefinedStat) mPredefinedStat->stop(); -    if (mDynamicStat) -    { -        mDynamicStat->mStat.stop(); -        sCurrentStatPath = mLastPath;	// Restore the path in case sStatsEnabled changed during this block -    } -} - - -// Clear the map of any dynamic stats.  Static routine -void LLPerfBlock::clearDynamicStats() -{ -    std::for_each(sStatMap.begin(), sStatMap.end(), DeletePairedPointer()); -    sStatMap.clear(); -} - -// static - Extract the stat info into LLSD -void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats, -										  LLStatAccum::TimeScale scale ) -{ -    // If we aren't in per-frame scale, we need to go from second to microsecond. -    U32 scale_adjustment = 1; -    if (LLStatAccum::SCALE_PER_FRAME != scale) -    { -        scale_adjustment = USEC_PER_SEC; -    } -	stat_map_t::iterator iter = sStatMap.begin(); -	for ( ; iter != sStatMap.end(); ++iter ) -	{	// Put the entry into LLSD "/full/path/to/stat/" = microsecond total time -		const std::string & stats_full_path = (*iter).first; - -		StatEntry * stat = (*iter).second; -		if (stat) -		{ -            if (stat->mCount > 0) -            { -                stats[stats_full_path] = LLSD::emptyMap(); -                stats[stats_full_path]["us"] = (LLSD::Integer) (scale_adjustment * stat->mStat.meanValue(scale)); -                if (stat->mCount > 1) -                { -                    stats[stats_full_path]["count"] = (LLSD::Integer) stat->mCount; -                } -                stat->mCount = 0; -            } -		} -		else -		{	// Shouldn't have a NULL pointer in the map. -            llwarns << "Unexpected NULL dynamic stat at '" << stats_full_path << "'" << llendl; -		} -	}	 -} - - -// ------------------------------------------------------------------------ -  LLTimer LLStat::sTimer;  LLFrameTimer LLStat::sFrameTimer; -void LLStat::init() +void LLStat::reset()  { -	llassert(mNumBins > 0);  	mNumValues = 0;  	mLastValue = 0.f; -	mLastTime = 0.f; -	mCurBin = (mNumBins-1); +	delete[] mBins; +	mBins      = new ValueEntry[mNumBins]; +	mCurBin = mNumBins-1;  	mNextBin = 0; -	mBins      = new F32[mNumBins]; -	mBeginTime = new F64[mNumBins]; -	mTime      = new F64[mNumBins]; -	mDT        = new F32[mNumBins]; -	for (U32 i = 0; i < mNumBins; i++) -	{ -		mBins[i]      = 0.f; -		mBeginTime[i] = 0.0; -		mTime[i]      = 0.0; -		mDT[i]        = 0.f; -	} +} + +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())  	{ @@ -783,27 +77,10 @@ LLStat::stat_map_t& LLStat::getStatList()  	return stat_list;  } -LLStat::LLStat(const U32 num_bins, const BOOL use_frame_timer) -	: mUseFrameTimer(use_frame_timer), -	  mNumBins(num_bins) -{ -	init(); -} - -LLStat::LLStat(std::string name, U32 num_bins, BOOL use_frame_timer) -	: mUseFrameTimer(use_frame_timer), -	  mNumBins(num_bins), -	  mName(name) -{ -	init(); -}  LLStat::~LLStat()  {  	delete[] mBins; -	delete[] mBeginTime; -	delete[] mTime; -	delete[] mDT;  	if (!mName.empty())  	{ @@ -815,76 +92,15 @@ LLStat::~LLStat()  	}  } -void LLStat::reset() -{ -	U32 i; - -	mNumValues = 0; -	mLastValue = 0.f; -	mCurBin = (mNumBins-1); -	delete[] mBins; -	delete[] mBeginTime; -	delete[] mTime; -	delete[] mDT; -	mBins      = new F32[mNumBins]; -	mBeginTime = new F64[mNumBins]; -	mTime      = new F64[mNumBins]; -	mDT        = new F32[mNumBins]; -	for (i = 0; i < mNumBins; i++) -	{ -		mBins[i]      = 0.f; -		mBeginTime[i] = 0.0; -		mTime[i]      = 0.0; -		mDT[i]        = 0.f; -	} -} - -void LLStat::setBeginTime(const F64 time) -{ -	mBeginTime[mNextBin] = time; -} - -void LLStat::addValueTime(const F64 time, const F32 value) -{ -	if (mNumValues < mNumBins) -	{ -		mNumValues++; -	} - -	// Increment the bin counters. -	mCurBin++; -	if ((U32)mCurBin == mNumBins) -	{ -		mCurBin = 0; -	} -	mNextBin++; -	if ((U32)mNextBin == mNumBins) -	{ -		mNextBin = 0; -	} - -	mBins[mCurBin] = value; -	mTime[mCurBin] = time; -	mDT[mCurBin] = (F32)(mTime[mCurBin] - mBeginTime[mCurBin]); -	//this value is used to prime the min/max calls -	mLastTime = mTime[mCurBin]; -	mLastValue = value; - -	// Set the begin time for the next stat segment. -	mBeginTime[mNextBin] = mTime[mCurBin]; -	mTime[mNextBin] = mTime[mCurBin]; -	mDT[mNextBin] = 0.f; -} -  void LLStat::start()  {  	if (mUseFrameTimer)  	{ -		mBeginTime[mNextBin] = sFrameTimer.getElapsedSeconds(); +		mBins[mNextBin].mBeginTime = sFrameTimer.getElapsedSeconds();  	}  	else  	{ -		mBeginTime[mNextBin] = sTimer.getElapsedTimeF64(); +		mBins[mNextBin].mBeginTime = sTimer.getElapsedTimeF64();  	}  } @@ -897,41 +113,41 @@ void LLStat::addValue(const F32 value)  	// Increment the bin counters.  	mCurBin++; -	if ((U32)mCurBin == mNumBins) +	if (mCurBin >= mNumBins)  	{  		mCurBin = 0;  	}  	mNextBin++; -	if ((U32)mNextBin == mNumBins) +	if (mNextBin >= mNumBins)  	{  		mNextBin = 0;  	} -	mBins[mCurBin] = value; +	mBins[mCurBin].mValue = value;  	if (mUseFrameTimer)  	{ -		mTime[mCurBin] = sFrameTimer.getElapsedSeconds(); +		mBins[mCurBin].mTime = sFrameTimer.getElapsedSeconds();  	}  	else  	{ -		mTime[mCurBin] = sTimer.getElapsedTimeF64(); +		mBins[mCurBin].mTime = sTimer.getElapsedTimeF64();  	} -	mDT[mCurBin] = (F32)(mTime[mCurBin] - mBeginTime[mCurBin]); +	mBins[mCurBin].mDT = (F32)(mBins[mCurBin].mTime - mBins[mCurBin].mBeginTime);  	//this value is used to prime the min/max calls -	mLastTime = mTime[mCurBin]; +	mLastTime = mBins[mCurBin].mTime;  	mLastValue = value;  	// Set the begin time for the next stat segment. -	mBeginTime[mNextBin] = mTime[mCurBin]; -	mTime[mNextBin] = mTime[mCurBin]; -	mDT[mNextBin] = 0.f; +	mBins[mNextBin].mBeginTime = mBins[mCurBin].mTime; +	mBins[mNextBin].mTime = mBins[mCurBin].mTime; +	mBins[mNextBin].mDT = 0.f;  }  F32 LLStat::getMax() const  { -	U32 i; +	S32 i;  	F32 current_max = mLastValue;  	if (mNumBins == 0)  	{ @@ -942,13 +158,13 @@ F32 LLStat::getMax() const  		for (i = 0; (i < mNumBins) && (i < mNumValues); i++)  		{  			// Skip the bin we're currently filling. -			if (i == (U32)mNextBin) +			if (i == mNextBin)  			{  				continue;  			} -			if (mBins[i] > current_max) +			if (mBins[i].mValue > current_max)  			{ -				current_max = mBins[i]; +				current_max = mBins[i].mValue;  			}  		}  	} @@ -957,17 +173,17 @@ F32 LLStat::getMax() const  F32 LLStat::getMean() const  { -	U32 i; +	S32 i;  	F32 current_mean = 0.f; -	U32 samples = 0; +	S32 samples = 0;  	for (i = 0; (i < mNumBins) && (i < mNumValues); i++)  	{  		// Skip the bin we're currently filling. -		if (i == (U32)mNextBin) +		if (i == mNextBin)  		{  			continue;  		} -		current_mean += mBins[i]; +		current_mean += mBins[i].mValue;  		samples++;  	} @@ -985,7 +201,7 @@ F32 LLStat::getMean() const  F32 LLStat::getMin() const  { -	U32 i; +	S32 i;  	F32 current_min = mLastValue;  	if (mNumBins == 0) @@ -997,53 +213,19 @@ F32 LLStat::getMin() const  		for (i = 0; (i < mNumBins) && (i < mNumValues); i++)  		{  			// Skip the bin we're currently filling. -			if (i == (U32)mNextBin) +			if (i == mNextBin)  			{  				continue;  			} -			if (mBins[i] < current_min) +			if (mBins[i].mValue < current_min)  			{ -				current_min = mBins[i]; +				current_min = mBins[i].mValue;  			}  		}  	}  	return current_min;  } -F32 LLStat::getSum() const -{ -	U32 i; -	F32 sum = 0.f; -	for (i = 0; (i < mNumBins) && (i < mNumValues); i++) -	{ -		// Skip the bin we're currently filling. -		if (i == (U32)mNextBin) -		{ -			continue; -		} -		sum += mBins[i]; -	} - -	return sum; -} - -F32 LLStat::getSumDuration() const -{ -	U32 i; -	F32 sum = 0.f; -	for (i = 0; (i < mNumBins) && (i < mNumValues); i++) -	{ -		// Skip the bin we're currently filling. -		if (i == (U32)mNextBin) -		{ -			continue; -		} -		sum += mDT[i]; -	} - -	return sum; -} -  F32 LLStat::getPrev(S32 age) const  {  	S32 bin; @@ -1059,7 +241,7 @@ F32 LLStat::getPrev(S32 age) const  		// Bogus for bin we're currently working on.  		return 0.f;  	} -	return mBins[bin]; +	return mBins[bin].mValue;  }  F32 LLStat::getPrevPerSec(S32 age) const @@ -1077,107 +259,34 @@ F32 LLStat::getPrevPerSec(S32 age) const  		// Bogus for bin we're currently working on.  		return 0.f;  	} -	return mBins[bin] / mDT[bin]; -} - -F64 LLStat::getPrevBeginTime(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 mBeginTime[bin]; -} - -F64 LLStat::getPrevTime(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 mTime[bin]; -} - -F32 LLStat::getBin(S32 bin) const -{ -	return mBins[bin]; -} - -F32 LLStat::getBinPerSec(S32 bin) const -{ -	return mBins[bin] / mDT[bin]; -} - -F64 LLStat::getBinBeginTime(S32 bin) const -{ -	return mBeginTime[bin]; -} - -F64 LLStat::getBinTime(S32 bin) const -{ -	return mTime[bin]; +	return mBins[bin].mValue / mBins[bin].mDT;  }  F32 LLStat::getCurrent() const  { -	return mBins[mCurBin]; +	return mBins[mCurBin].mValue;  }  F32 LLStat::getCurrentPerSec() const  { -	return mBins[mCurBin] / mDT[mCurBin]; -} - -F64 LLStat::getCurrentBeginTime() const -{ -	return mBeginTime[mCurBin]; -} - -F64 LLStat::getCurrentTime() const -{ -	return mTime[mCurBin]; -} - -F32 LLStat::getCurrentDuration() const -{ -	return mDT[mCurBin]; +	return mBins[mCurBin].mValue / mBins[mCurBin].mDT;  }  F32 LLStat::getMeanPerSec() const  { -	U32 i; +	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 == (U32)mNextBin) +		if (i == mNextBin)  		{  			continue;  		} -		value += mBins[i]; -		dt    += mDT[i]; +		value += mBins[i].mValue; +		dt    += mBins[i].mDT;  	}  	if (dt > 0.f) @@ -1193,14 +302,14 @@ F32 LLStat::getMeanPerSec() const  F32 LLStat::getMeanDuration() const  {  	F32 dur = 0.0f; -	U32 count = 0; -	for (U32 i=0; (i < mNumBins) && (i < mNumValues); i++) +	S32 count = 0; +	for (S32 i=0; (i < mNumBins) && (i < mNumValues); i++)  	{ -		if (i == (U32)mNextBin) +		if (i == mNextBin)  		{  			continue;  		} -		dur += mDT[i]; +		dur += mBins[i].mDT;  		count++;  	} @@ -1217,46 +326,45 @@ F32 LLStat::getMeanDuration() const  F32 LLStat::getMaxPerSec() const  { -	U32 i;  	F32 value;  	if (mNextBin != 0)  	{ -		value = mBins[0]/mDT[0]; +		value = mBins[0].mValue/mBins[0].mDT;  	}  	else if (mNumValues > 0)  	{ -		value = mBins[1]/mDT[1]; +		value = mBins[1].mValue/mBins[1].mDT;  	}  	else  	{  		value = 0.f;  	} -	for (i = 0; (i < mNumBins) && (i < mNumValues); i++) +	for (S32 i = 0; (i < mNumBins) && (i < mNumValues); i++)  	{  		// Skip the bin we're currently filling. -		if (i == (U32)mNextBin) +		if (i == mNextBin)  		{  			continue;  		} -		value = llmax(value, mBins[i]/mDT[i]); +		value = llmax(value, mBins[i].mValue/mBins[i].mDT);  	}  	return value;  }  F32 LLStat::getMinPerSec() const  { -	U32 i; +	S32 i;  	F32 value;  	if (mNextBin != 0)  	{ -		value = mBins[0]/mDT[0]; +		value = mBins[0].mValue/mBins[0].mDT;  	}  	else if (mNumValues > 0)  	{ -		value = mBins[1]/mDT[1]; +		value = mBins[1].mValue/mBins[0].mDT;  	}  	else  	{ @@ -1266,25 +374,15 @@ F32 LLStat::getMinPerSec() const  	for (i = 0; (i < mNumBins) && (i < mNumValues); i++)  	{  		// Skip the bin we're currently filling. -		if (i == (U32)mNextBin) +		if (i == mNextBin)  		{  			continue;  		} -		value = llmin(value, mBins[i]/mDT[i]); +		value = llmin(value, mBins[i].mValue/mBins[i].mDT);  	}  	return value;  } -F32 LLStat::getMinDuration() const -{ -	F32 dur = 0.0f; -	for (U32 i=0; (i < mNumBins) && (i < mNumValues); i++) -	{ -		dur = llmin(dur, mDT[i]); -	} -	return dur; -} -  U32 LLStat::getNumValues() const  {  	return mNumValues; @@ -1295,11 +393,6 @@ S32 LLStat::getNumBins() const  	return mNumBins;  } -S32 LLStat::getCurBin() const -{ -	return mCurBin; -} -  S32 LLStat::getNextBin() const  {  	return mNextBin; diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h index 1a8404cc07..38377a010b 100644..100755 --- a/indra/llcommon/llstat.h +++ b/indra/llcommon/llstat.h @@ -27,294 +27,46 @@  #ifndef LL_LLSTAT_H  #define LL_LLSTAT_H -#include <deque>  #include <map>  #include "lltimer.h"  #include "llframetimer.h" -#include "llfile.h"  class	LLSD; -// Set this if longer stats are needed -#define ENABLE_LONG_TIME_STATS	0 - -// -// Accumulates statistics for an arbitrary length of time. -// Does this by maintaining a chain of accumulators, each one -// accumulation the results of the parent.  Can scale to arbitrary -// amounts of time with very low memory cost. -// - -class LL_COMMON_API LLStatAccum -{ -protected: -	LLStatAccum(bool use_frame_timer); -	virtual ~LLStatAccum(); - -public: -	enum TimeScale { -		SCALE_100MS, -		SCALE_SECOND, -		SCALE_MINUTE, -#if ENABLE_LONG_TIME_STATS -		SCALE_HOUR, -		SCALE_DAY, -		SCALE_WEEK, -#endif -		NUM_SCALES,			// Use to size storage arrays -		SCALE_PER_FRAME		// For latest frame information - should be after NUM_SCALES since this doesn't go into the time buckets -	}; - -	static U64 sScaleTimes[NUM_SCALES]; - -	virtual F32 meanValue(TimeScale scale) const; -		// see the subclasses for the specific meaning of value - -	F32 meanValueOverLast100ms()  const { return meanValue(SCALE_100MS);  } -	F32 meanValueOverLastSecond() const	{ return meanValue(SCALE_SECOND); } -	F32 meanValueOverLastMinute() const	{ return meanValue(SCALE_MINUTE); } - -	void reset(U64 when); - -	void sum(F64 value); -	void sum(F64 value, U64 when); - -	U64 getCurrentUsecs() const; -		// Get current microseconds based on timer type - -	BOOL	mUseFrameTimer; -	BOOL	mRunning; - -	U64		mLastTime; -	 -	struct Bucket -	{ -		Bucket() : -			accum(0.0), -			endTime(0), -			lastValid(false), -			lastAccum(0.0) -		{} - -		F64	accum; -		U64	endTime; - -		bool	lastValid; -		F64	lastAccum; -	}; - -	Bucket	mBuckets[NUM_SCALES]; - -	BOOL 	mLastSampleValid; -	F64 	mLastSampleValue; -}; - -class LL_COMMON_API LLStatMeasure : public LLStatAccum -	// gathers statistics about things that are measured -	// ex.: tempature, time dilation -{ -public: -	LLStatMeasure(bool use_frame_timer = true); - -	void sample(F64); -	void sample(S32 v) { sample((F64)v); } -	void sample(U32 v) { sample((F64)v); } -	void sample(S64 v) { sample((F64)v); } -	void sample(U64 v) { sample((F64)v); } -}; - - -class LL_COMMON_API LLStatRate : public LLStatAccum -	// gathers statistics about things that can be counted over time -	// ex.: LSL instructions executed, messages sent, simulator frames completed -	// renders it in terms of rate of thing per second -{ -public: -	LLStatRate(bool use_frame_timer = true); - -	void count(U32); -		// used to note that n items have occured -	 -	void mark(); -		// used for counting the rate thorugh a point in the code -}; - - -class LL_COMMON_API LLStatTime : public LLStatAccum -	// gathers statistics about time spent in a block of code -	// measure average duration per second in the block -{ -public: -	LLStatTime( const std::string & key = "undefined" ); - -	U32		mFrameNumber;		// Current frame number -	U64		mTotalTimeInFrame;	// Total time (microseconds) accumulated during the last frame - -	void	setKey( const std::string & key )		{ mKey = key;	}; - -	virtual F32 meanValue(TimeScale scale) const; - -private: -	void start();				// Start and stop measuring time block -	void stop(); - -	std::string		mKey;		// Tag representing this time block - -#if LL_DEBUG -	BOOL			mRunning;	// TRUE if start() has been called -#endif - -	friend class LLPerfBlock; -}; - -// ---------------------------------------------------------------------------- - - -// Use this class on the stack to record statistics about an area of code -class LL_COMMON_API LLPerfBlock -{ -public: -    struct StatEntry -    { -            StatEntry(const std::string& key) : mStat(LLStatTime(key)), mCount(0) {} -            LLStatTime  mStat; -            U32         mCount; -    }; -    typedef std::map<std::string, StatEntry*>		stat_map_t; - -	// Use this constructor for pre-defined LLStatTime objects -	LLPerfBlock(LLStatTime* stat); - -	// Use this constructor for normal, optional LLPerfBlock time slices -	LLPerfBlock( const char* key ); - -	// Use this constructor for dynamically created LLPerfBlock time slices -	// that are only enabled by specific control flags -	LLPerfBlock( const char* key1, const char* key2, S32 flags = LLSTATS_BASIC_STATS ); - -	~LLPerfBlock(); - -	enum -	{	// Stats bitfield flags -		LLSTATS_NO_OPTIONAL_STATS	= 0x00,		// No optional stats gathering, just pre-defined LLStatTime objects -		LLSTATS_BASIC_STATS			= 0x01,		// Gather basic optional runtime stats -		LLSTATS_SCRIPT_FUNCTIONS	= 0x02,		// Include LSL function calls -	}; -	static void setStatsFlags( S32 flags )	{ sStatsFlags = flags;	}; -	static S32  getStatsFlags()				{ return sStatsFlags;	}; - -	static void clearDynamicStats();		// Reset maps to clear out dynamic objects -	static void addStatsToLLSDandReset( LLSD & stats,		// Get current information and clear time bin -										LLStatAccum::TimeScale scale ); - -private: -	// Initialize dynamically created LLStatTime objects -    void initDynamicStat(const std::string& key); - -	std::string				mLastPath;				// Save sCurrentStatPath when this is called -	LLStatTime * 			mPredefinedStat;		// LLStatTime object to get data -	StatEntry *				mDynamicStat;   		// StatEntryobject to get data - -	static S32				sStatsFlags;			// Control what is being recorded -    static stat_map_t		sStatMap;				// Map full path string to LLStatTime objects -	static std::string		sCurrentStatPath;		// Something like "frame/physics/physics step" -}; - -// ---------------------------------------------------------------------------- - -class LL_COMMON_API LLPerfStats -{ -public: -    LLPerfStats(const std::string& process_name = "unknown", S32 process_pid = 0); -    virtual ~LLPerfStats(); - -    virtual void init();    // Reset and start all stat timers -    virtual void updatePerFrameStats(); -    // Override these function to add process-specific information to the performance log header and per-frame logging. -    virtual void addProcessHeaderInfo(LLSD& info) { /* not implemented */ } -    virtual void addProcessFrameInfo(LLSD& info, LLStatAccum::TimeScale scale) { /* not implemented */ } - -    // High-resolution frame stats -    BOOL    frameStatsIsRunning()                                { return (mReportPerformanceStatEnd > 0.);        }; -    F32     getReportPerformanceInterval() const                { return mReportPerformanceStatInterval;        }; -    void    setReportPerformanceInterval( F32 interval )        { mReportPerformanceStatInterval = interval;    }; -    void    setReportPerformanceDuration( F32 seconds, S32 flags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS ); -    void    setProcessName(const std::string& process_name) { mProcessName = process_name; } -    void    setProcessPID(S32 process_pid) { mProcessPID = process_pid; } - -protected: -    void    openPerfStatsFile();                    // Open file for high resolution metrics logging -    void    dumpIntervalPerformanceStats(); - -    llofstream      mFrameStatsFile;            // File for per-frame stats -    BOOL            mFrameStatsFileFailure;        // Flag to prevent repeat opening attempts -    BOOL            mSkipFirstFrameStats;        // Flag to skip one (partial) frame report -    std::string     mProcessName; -    S32             mProcessPID; - -private: -    F32 mReportPerformanceStatInterval;    // Seconds between performance stats -    F64 mReportPerformanceStatEnd;        // End time (seconds) for performance stats -}; -  // ----------------------------------------------------------------------------  class LL_COMMON_API LLStat  {  private:  	typedef std::multimap<std::string, LLStat*> stat_map_t; -	void init();  	static stat_map_t& getStatList();  public: -	LLStat(U32 num_bins = 32, BOOL use_frame_timer = FALSE); -	LLStat(std::string name, U32 num_bins = 32, BOOL use_frame_timer = FALSE); +	LLStat(std::string name = std::string(), S32 num_bins = 32, BOOL use_frame_timer = FALSE);  	~LLStat(); -	void reset(); -  	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); } -	void setBeginTime(const F64 time); -	void addValueTime(const F64 time, const F32 value = 1.f); -	 -	S32 getCurBin() const;  	S32 getNextBin() const; -	F32 getCurrent() const; -	F32 getCurrentPerSec() const; -	F64 getCurrentBeginTime() const; -	F64 getCurrentTime() const; -	F32 getCurrentDuration() 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 -	F64 getPrevBeginTime(S32 age) const; -	F64 getPrevTime(S32 age) const; -	 -	F32 getBin(S32 bin) const; -	F32 getBinPerSec(S32 bin) const; -	F64 getBinBeginTime(S32 bin) const; -	F64 getBinTime(S32 bin) const; - -	F32 getMax() const; -	F32 getMaxPerSec() const; +	F32 getCurrent() const; +	F32 getCurrentPerSec() const; +	F32 getMin() const; +	F32 getMinPerSec() const;  	F32 getMean() const;  	F32 getMeanPerSec() const;  	F32 getMeanDuration() const; - -	F32 getMin() const; -	F32 getMinPerSec() const; -	F32 getMinDuration() const; - -	F32 getSum() const; -	F32 getSumDuration() const; +	F32 getMax() const; +	F32 getMaxPerSec() const;  	U32 getNumValues() const;  	S32 getNumBins() const; @@ -326,10 +78,21 @@ private:  	U32 mNumBins;  	F32 mLastValue;  	F64 mLastTime; -	F32 *mBins; -	F64 *mBeginTime; -	F64 *mTime; -	F32 *mDT; + +	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; diff --git a/indra/llcommon/llstatenums.h b/indra/llcommon/llstatenums.h index 81c4085d16..81c4085d16 100644..100755 --- a/indra/llcommon/llstatenums.h +++ b/indra/llcommon/llstatenums.h diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index d3941e1bc9..d3941e1bc9 100644..100755 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h diff --git a/indra/llcommon/llstreamqueue.cpp b/indra/llcommon/llstreamqueue.cpp index 1116a2b6a2..1116a2b6a2 100644..100755 --- a/indra/llcommon/llstreamqueue.cpp +++ b/indra/llcommon/llstreamqueue.cpp diff --git a/indra/llcommon/llstreamqueue.h b/indra/llcommon/llstreamqueue.h index 0726bad175..0726bad175 100644..100755 --- a/indra/llcommon/llstreamqueue.h +++ b/indra/llcommon/llstreamqueue.h diff --git a/indra/llcommon/llstreamtools.cpp b/indra/llcommon/llstreamtools.cpp index d7a6f47932..d7a6f47932 100644..100755 --- a/indra/llcommon/llstreamtools.cpp +++ b/indra/llcommon/llstreamtools.cpp diff --git a/indra/llcommon/llstreamtools.h b/indra/llcommon/llstreamtools.h index 1b04bf91d7..1b04bf91d7 100644..100755 --- a/indra/llcommon/llstreamtools.h +++ b/indra/llcommon/llstreamtools.h diff --git a/indra/llcommon/llstrider.h b/indra/llcommon/llstrider.h index ed9284d2c5..ed9284d2c5 100644..100755 --- a/indra/llcommon/llstrider.h +++ b/indra/llcommon/llstrider.h diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 0c32679744..22c8681983 100644..100755 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -52,6 +52,23 @@ std::string ll_safe_string(const char* in, S32 maxlen)  	return std::string();  } +bool is_char_hex(char hex) +{ +	if((hex >= '0') && (hex <= '9')) +	{ +		return true; +	} +	else if((hex >= 'a') && (hex <='f')) +	{ +		return true; +	} +	else if((hex >= 'A') && (hex <='F')) +	{ +		return true; +	} +	return false; // uh - oh, not hex any more... +} +  U8 hex_as_nybble(char hex)  {  	if((hex >= '0') && (hex <= '9')) diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 119efc7957..f9702868c8 100644..100755 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -470,6 +470,7 @@ inline std::string chop_tail_copy(   * @brief This translates a nybble stored as a hex value from 0-f back   * to a nybble in the low order bits of the return byte.   */ +LL_COMMON_API bool is_char_hex(char hex);  LL_COMMON_API U8 hex_as_nybble(char hex);  /** diff --git a/indra/llcommon/llstringtable.cpp b/indra/llcommon/llstringtable.cpp index 7ad3805351..7ad3805351 100644..100755 --- a/indra/llcommon/llstringtable.cpp +++ b/indra/llcommon/llstringtable.cpp diff --git a/indra/llcommon/llstringtable.h b/indra/llcommon/llstringtable.h index 59d7372ed4..59d7372ed4 100644..100755 --- a/indra/llcommon/llstringtable.h +++ b/indra/llcommon/llstringtable.h diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index c96f2191f3..57a6de9060 100644..100755 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -80,6 +80,7 @@ using namespace llsd;  #	include <sys/sysinfo.h>  #   include <stdexcept>  const char MEMINFO_FILE[] = "/proc/meminfo"; +#   include <gnu/libc-version.h>  #elif LL_SOLARIS  #	include <stdio.h>  #	include <unistd.h> @@ -175,8 +176,41 @@ bool get_shell32_dll_version(DWORD& major, DWORD& minor, DWORD& build_number)  }  #endif // LL_WINDOWS +// Wrap boost::regex_match() with a function that doesn't throw. +template <typename S, typename M, typename R> +static bool regex_match_no_exc(const S& string, M& match, const R& regex) +{ +    try +    { +        return boost::regex_match(string, match, regex); +    } +    catch (const std::runtime_error& e) +    { +        LL_WARNS("LLMemoryInfo") << "error matching with '" << regex.str() << "': " +                                 << e.what() << ":\n'" << string << "'" << LL_ENDL; +        return false; +    } +} + +// Wrap boost::regex_search() with a function that doesn't throw. +template <typename S, typename M, typename R> +static bool regex_search_no_exc(const S& string, M& match, const R& regex) +{ +    try +    { +        return boost::regex_search(string, match, regex); +    } +    catch (const std::runtime_error& e) +    { +        LL_WARNS("LLMemoryInfo") << "error searching with '" << regex.str() << "': " +                                 << e.what() << ":\n'" << string << "'" << LL_ENDL; +        return false; +    } +} + +  LLOSInfo::LLOSInfo() : -	mMajorVer(0), mMinorVer(0), mBuild(0) +	mMajorVer(0), mMinorVer(0), mBuild(0), mOSVersionString("")	   {  #if LL_WINDOWS @@ -412,6 +446,102 @@ LLOSInfo::LLOSInfo() :  		mOSString = mOSStringSimple;  	} +#elif LL_LINUX +	 +	struct utsname un; +	if(uname(&un) != -1) +	{ +		mOSStringSimple.append(un.sysname); +		mOSStringSimple.append(" "); +		mOSStringSimple.append(un.release); + +		mOSString = mOSStringSimple; +		mOSString.append(" "); +		mOSString.append(un.version); +		mOSString.append(" "); +		mOSString.append(un.machine); + +		// Simplify 'Simple' +		std::string ostype = mOSStringSimple.substr(0, mOSStringSimple.find_first_of(" ", 0)); +		if (ostype == "Linux") +		{ +			// Only care about major and minor Linux versions, truncate at second '.' +			std::string::size_type idx1 = mOSStringSimple.find_first_of(".", 0); +			std::string::size_type idx2 = (idx1 != std::string::npos) ? mOSStringSimple.find_first_of(".", idx1+1) : std::string::npos; +			std::string simple = mOSStringSimple.substr(0, idx2); +			if (simple.length() > 0) +				mOSStringSimple = simple; +		} +	} +	else +	{ +		mOSStringSimple.append("Unable to collect OS info"); +		mOSString = mOSStringSimple; +	} + +	const char OS_VERSION_MATCH_EXPRESSION[] = "([0-9]+)\\.([0-9]+)(\\.([0-9]+))?"; +	boost::regex os_version_parse(OS_VERSION_MATCH_EXPRESSION); +	boost::smatch matched; + +	std::string glibc_version(gnu_get_libc_version()); +	if ( regex_match_no_exc(glibc_version, matched, os_version_parse) ) +	{ +		LL_INFOS("AppInit") << "Using glibc version '" << glibc_version << "' as OS version" << LL_ENDL; +	 +		std::string version_value; + +		if ( matched[1].matched ) // Major version +		{ +			version_value.assign(matched[1].first, matched[1].second); +			if (sscanf(version_value.c_str(), "%d", &mMajorVer) != 1) +			{ +			  LL_WARNS("AppInit") << "failed to parse major version '" << version_value << "' as a number" << LL_ENDL; +			} +		} +		else +		{ +			LL_ERRS("AppInit") +				<< "OS version regex '" << OS_VERSION_MATCH_EXPRESSION  +				<< "' returned true, but major version [1] did not match" +				<< LL_ENDL; +		} + +		if ( matched[2].matched ) // Minor version +		{ +			version_value.assign(matched[2].first, matched[2].second); +			if (sscanf(version_value.c_str(), "%d", &mMinorVer) != 1) +			{ +			  LL_ERRS("AppInit") << "failed to parse minor version '" << version_value << "' as a number" << LL_ENDL; +			} +		} +		else +		{ +			LL_ERRS("AppInit") +				<< "OS version regex '" << OS_VERSION_MATCH_EXPRESSION  +				<< "' returned true, but minor version [1] did not match" +				<< LL_ENDL; +		} + +		if ( matched[4].matched ) // Build version (optional) - note that [3] includes the '.' +		{ +			version_value.assign(matched[4].first, matched[4].second); +			if (sscanf(version_value.c_str(), "%d", &mBuild) != 1) +			{ +			  LL_ERRS("AppInit") << "failed to parse build version '" << version_value << "' as a number" << LL_ENDL; +			} +		} +		else +		{ +			LL_INFOS("AppInit") +				<< "OS build version not provided; using zero" +				<< LL_ENDL; +		} +	} +	else +	{ +		LL_WARNS("AppInit") << "glibc version '" << glibc_version << "' cannot be parsed to three numbers; using all zeros" << LL_ENDL; +	} +  #else  	struct utsname un; @@ -444,8 +574,13 @@ LLOSInfo::LLOSInfo() :  		mOSStringSimple.append("Unable to collect OS info");  		mOSString = mOSStringSimple;  	} +  #endif +	std::stringstream dotted_version_string; +	dotted_version_string << mMajorVer << "." << mMinorVer << "." << mBuild; +	mOSVersionString.append(dotted_version_string.str()); +  }  #ifndef LL_WINDOWS @@ -496,6 +631,11 @@ const std::string& LLOSInfo::getOSStringSimple() const  	return mOSStringSimple;  } +const std::string& LLOSInfo::getOSVersionString() const +{ +	return mOSVersionString; +} +  const S32 STATUS_SIZE = 8192;  //static @@ -687,38 +827,6 @@ private:  	LLSD mStats;  }; -// Wrap boost::regex_match() with a function that doesn't throw. -template <typename S, typename M, typename R> -static bool regex_match_no_exc(const S& string, M& match, const R& regex) -{ -    try -    { -        return boost::regex_match(string, match, regex); -    } -    catch (const std::runtime_error& e) -    { -        LL_WARNS("LLMemoryInfo") << "error matching with '" << regex.str() << "': " -                                 << e.what() << ":\n'" << string << "'" << LL_ENDL; -        return false; -    } -} - -// Wrap boost::regex_search() with a function that doesn't throw. -template <typename S, typename M, typename R> -static bool regex_search_no_exc(const S& string, M& match, const R& regex) -{ -    try -    { -        return boost::regex_search(string, match, regex); -    } -    catch (const std::runtime_error& e) -    { -        LL_WARNS("LLMemoryInfo") << "error searching with '" << regex.str() << "': " -                                 << e.what() << ":\n'" << string << "'" << LL_ENDL; -        return false; -    } -} -  LLMemoryInfo::LLMemoryInfo()  {  	refresh(); diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index 739e795d3a..cfed0fff17 100644..100755 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -49,6 +49,8 @@ public:  	const std::string& getOSString() const;  	const std::string& getOSStringSimple() const; +	const std::string& getOSVersionString() const; +	  	S32 mMajorVer;  	S32 mMinorVer;  	S32 mBuild; @@ -62,6 +64,7 @@ public:  private:  	std::string mOSString;  	std::string mOSStringSimple; +	std::string mOSVersionString;  }; diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 1d56a52c32..1d56a52c32 100644..100755 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index 5c8bbca2ca..0fb89c5613 100644..100755 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -30,6 +30,7 @@  #include "llapp.h"  #include "llapr.h"  #include "apr_thread_cond.h" +#include "boost/intrusive_ptr.hpp"  class LLThread;  class LLMutex; @@ -284,6 +285,22 @@ private:  	S32	mRef;   }; +/** + * intrusive pointer support for LLThreadSafeRefCount + * this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type + */ +namespace boost +{ +	inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p)  +	{ +		p->ref(); +	} + +	inline void intrusive_ptr_release(LLThreadSafeRefCount* p)  +	{ +		p->unref();  +	} +};  //============================================================================  // Simple responder for self destructing callbacks diff --git a/indra/llcommon/llthreadsafequeue.cpp b/indra/llcommon/llthreadsafequeue.cpp index 8a73e632a9..8a73e632a9 100644..100755 --- a/indra/llcommon/llthreadsafequeue.cpp +++ b/indra/llcommon/llthreadsafequeue.cpp diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h index 58cac38769..58cac38769 100644..100755 --- a/indra/llcommon/llthreadsafequeue.h +++ b/indra/llcommon/llthreadsafequeue.h diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 9ebc6de7f4..9ebc6de7f4 100644..100755 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index 513de0605d..513de0605d 100644..100755 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h diff --git a/indra/llcommon/lltreeiterators.h b/indra/llcommon/lltreeiterators.h index ba861ae70b..ba861ae70b 100644..100755 --- a/indra/llcommon/lltreeiterators.h +++ b/indra/llcommon/lltreeiterators.h diff --git a/indra/llcommon/lltypeinfolookup.h b/indra/llcommon/lltypeinfolookup.h index 0b6862444e..0b6862444e 100644..100755 --- a/indra/llcommon/lltypeinfolookup.h +++ b/indra/llcommon/lltypeinfolookup.h diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp index 21456a599b..37f5b3d6a3 100644..100755 --- a/indra/llcommon/lluri.cpp +++ b/indra/llcommon/lluri.cpp @@ -129,11 +129,30 @@ std::string LLURI::unescape(const std::string& str)  		{  			++it;  			if(it == end) break; -			U8 c = hex_as_nybble(*it++); -			c = c << 4; -			if (it == end) break; -			c |= hex_as_nybble(*it); -			ostr.put((char)c); + +			if(is_char_hex(*it)) +			{ +				U8 c = hex_as_nybble(*it++); + +				c = c << 4; +				if (it == end) break; + +				if(is_char_hex(*it)) +				{ +					c |= hex_as_nybble(*it); +					ostr.put((char)c); +				} +				else +				{ +					ostr.put((char)c); +					ostr.put(*it); +				} +			} +			else +			{ +				ostr.put('%'); +				ostr.put(*it); +			}  		}  		else  		{ diff --git a/indra/llcommon/lluri.h b/indra/llcommon/lluri.h index c82a666e48..c82a666e48 100644..100755 --- a/indra/llcommon/lluri.h +++ b/indra/llcommon/lluri.h diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index db8c9c85ab..0aaa50d231 100644..100755 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -44,10 +44,16 @@  #include "llmd5.h"  #include "llstring.h"  #include "lltimer.h" +#include "llthread.h"  const LLUUID LLUUID::null;  const LLTransactionID LLTransactionID::tnull; +// static  +LLMutex * LLUUID::mMutex = NULL; + + +  /*  NOT DONE YET!!! @@ -734,6 +740,7 @@ void LLUUID::getCurrentTime(uuid_time_t *timestamp)        getSystemTime(&time_last);        uuids_this_tick = uuids_per_tick;        init = TRUE; +	  mMutex = new LLMutex(NULL);     }     uuid_time_t time_now = {0,0}; @@ -785,6 +792,7 @@ void LLUUID::generate()  #endif  	if (!has_init)   	{ +		has_init = 1;  		if (getNodeID(node_id) <= 0)   		{  			get_random_bytes(node_id, 6); @@ -806,18 +814,24 @@ void LLUUID::generate()  #else  		clock_seq = (U16)ll_rand(65536);  #endif -		has_init = 1;  	}  	// get current time  	getCurrentTime(×tamp); +	U16 our_clock_seq = clock_seq; -	// if clock went backward change clockseq -	if (cmpTime(×tamp, &time_last) == -1) { +	// if clock hasn't changed or went backward, change clockseq +	if (cmpTime(×tamp, &time_last) != 1)  +	{ +		LLMutexLock	lock(mMutex);  		clock_seq = (clock_seq + 1) & 0x3FFF; -		if (clock_seq == 0) clock_seq++; +		if (clock_seq == 0)  +			clock_seq++; +		our_clock_seq = clock_seq;	// Ensure we're using a different clock_seq value from previous time  	} +    time_last = timestamp; +  	memcpy(mData+10, node_id, 6);		/* Flawfinder: ignore */  	U32 tmp;  	tmp = timestamp.low; @@ -839,7 +853,8 @@ void LLUUID::generate()  	tmp >>= 8;  	mData[6] = (unsigned char) tmp; -	tmp = clock_seq; +	tmp = our_clock_seq; +  	mData[9] = (unsigned char) tmp;  	tmp >>= 8;  	mData[8] = (unsigned char) tmp; @@ -849,8 +864,6 @@ void LLUUID::generate()  	md5_uuid.update(mData,16);  	md5_uuid.finalize();  	md5_uuid.raw_digest(mData); - -    time_last = timestamp;  }  void LLUUID::generate(const std::string& hash_string) @@ -864,8 +877,14 @@ U32 LLUUID::getRandomSeed()     static unsigned char seed[16];		/* Flawfinder: ignore */     getNodeID(&seed[0]); -   seed[6]='\0'; -   seed[7]='\0'; + +   // Incorporate the pid into the seed to prevent +   // processes that start on the same host at the same +   // time from generating the same seed. +   pid_t pid = LLApp::getPid(); + +   seed[6]=(unsigned char)(pid >> 8); +   seed[7]=(unsigned char)(pid);     getSystemTime((uuid_time_t *)(&seed[8]));     LLMD5 md5_seed; diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index 0b9e7d0cd0..7889828c85 100644..100755 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -31,6 +31,8 @@  #include "stdtypes.h"  #include "llpreprocessor.h" +class LLMutex; +  const S32 UUID_BYTES = 16;  const S32 UUID_WORDS = 4;  const S32 UUID_STR_LENGTH = 37;	// actually wrong, should be 36 and use size below @@ -118,6 +120,7 @@ public:  	static BOOL validate(const std::string& in_string); // Validate that the UUID string is legal.  	static const LLUUID null; +	static LLMutex * mMutex;  	static U32 getRandomSeed();  	static S32 getNodeID(unsigned char * node_id); diff --git a/indra/llcommon/lluuidhashmap.h b/indra/llcommon/lluuidhashmap.h index e294670030..e294670030 100644..100755 --- a/indra/llcommon/lluuidhashmap.h +++ b/indra/llcommon/lluuidhashmap.h diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h index b19ba3bf74..ef68a0eaf5 100644..100755 --- a/indra/llcommon/llversionserver.h +++ b/indra/llcommon/llversionserver.h @@ -30,7 +30,7 @@  const S32 LL_VERSION_MAJOR = 2;  const S32 LL_VERSION_MINOR = 1;  const S32 LL_VERSION_PATCH = 0; -const S32 LL_VERSION_BUILD = 13828; +const S32 LL_VERSION_BUILD = 264760;  const char * const LL_CHANNEL = "Second Life Server"; diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h deleted file mode 100644 index 8585af0a29..0000000000 --- a/indra/llcommon/llversionviewer.h +++ /dev/null @@ -1,41 +0,0 @@ -/**  - * @file llversionviewer.h - * @brief - * - * $LicenseInfo:firstyear=2002&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLVERSIONVIEWER_H -#define LL_LLVERSIONVIEWER_H - -const S32 LL_VERSION_MAJOR = 3; -const S32 LL_VERSION_MINOR = 4; -const S32 LL_VERSION_PATCH = 4; -const S32 LL_VERSION_BUILD = 0; - -const char * const LL_CHANNEL = "Second Life Developer"; - -#if LL_DARWIN -const char * const LL_VERSION_BUNDLE_ID = "com.secondlife.indra.viewer"; -#endif - -#endif diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp index 3d05a30ac2..3d05a30ac2 100644..100755 --- a/indra/llcommon/llworkerthread.cpp +++ b/indra/llcommon/llworkerthread.cpp diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h index be46394d6e..be46394d6e 100644..100755 --- a/indra/llcommon/llworkerthread.h +++ b/indra/llcommon/llworkerthread.h diff --git a/indra/llcommon/metaclass.cpp b/indra/llcommon/metaclass.cpp index 5e403511cf..5e403511cf 100644..100755 --- a/indra/llcommon/metaclass.cpp +++ b/indra/llcommon/metaclass.cpp diff --git a/indra/llcommon/metaclass.h b/indra/llcommon/metaclass.h index 626757d58d..626757d58d 100644..100755 --- a/indra/llcommon/metaclass.h +++ b/indra/llcommon/metaclass.h diff --git a/indra/llcommon/metaclasst.h b/indra/llcommon/metaclasst.h index b9a7ae219d..b9a7ae219d 100644..100755 --- a/indra/llcommon/metaclasst.h +++ b/indra/llcommon/metaclasst.h diff --git a/indra/llcommon/metaproperty.cpp b/indra/llcommon/metaproperty.cpp index 98d850bf1e..98d850bf1e 100644..100755 --- a/indra/llcommon/metaproperty.cpp +++ b/indra/llcommon/metaproperty.cpp diff --git a/indra/llcommon/metaproperty.h b/indra/llcommon/metaproperty.h index bd5bb1a30f..bd5bb1a30f 100644..100755 --- a/indra/llcommon/metaproperty.h +++ b/indra/llcommon/metaproperty.h diff --git a/indra/llcommon/metapropertyt.h b/indra/llcommon/metapropertyt.h index 7a36c161da..7a36c161da 100644..100755 --- a/indra/llcommon/metapropertyt.h +++ b/indra/llcommon/metapropertyt.h diff --git a/indra/llcommon/reflective.cpp b/indra/llcommon/reflective.cpp index 2cc0e7e1f2..2cc0e7e1f2 100644..100755 --- a/indra/llcommon/reflective.cpp +++ b/indra/llcommon/reflective.cpp diff --git a/indra/llcommon/reflective.h b/indra/llcommon/reflective.h index da5c5a2630..da5c5a2630 100644..100755 --- a/indra/llcommon/reflective.h +++ b/indra/llcommon/reflective.h diff --git a/indra/llcommon/reflectivet.h b/indra/llcommon/reflectivet.h index 958921f23e..958921f23e 100644..100755 --- a/indra/llcommon/reflectivet.h +++ b/indra/llcommon/reflectivet.h diff --git a/indra/llcommon/roles_constants.h b/indra/llcommon/roles_constants.h index effd15ea72..effd15ea72 100644..100755 --- a/indra/llcommon/roles_constants.h +++ b/indra/llcommon/roles_constants.h diff --git a/indra/llcommon/stdenums.h b/indra/llcommon/stdenums.h index 40b3364b36..efcbe76795 100644..100755 --- a/indra/llcommon/stdenums.h +++ b/indra/llcommon/stdenums.h @@ -51,7 +51,8 @@ enum EDragAndDropType  	DAD_LINK			= 14,  	DAD_MESH            = 15,  	DAD_WIDGET          = 16, -	DAD_COUNT           = 17,   // number of types in this enum +	DAD_PERSON          = 17, +	DAD_COUNT           = 18,   // number of types in this enum  };  // Reasons for drags to be denied. diff --git a/indra/llcommon/stdtypes.h b/indra/llcommon/stdtypes.h index bf3f3f9ee8..bf3f3f9ee8 100644..100755 --- a/indra/llcommon/stdtypes.h +++ b/indra/llcommon/stdtypes.h diff --git a/indra/llcommon/string_table.h b/indra/llcommon/string_table.h index fe6416fb50..fe6416fb50 100644..100755 --- a/indra/llcommon/string_table.h +++ b/indra/llcommon/string_table.h diff --git a/indra/llcommon/stringize.h b/indra/llcommon/stringize.h index 72f2e58ce1..72f2e58ce1 100644..100755 --- a/indra/llcommon/stringize.h +++ b/indra/llcommon/stringize.h diff --git a/indra/llcommon/tests/StringVec.h b/indra/llcommon/tests/StringVec.h index a380b00a05..a380b00a05 100644..100755 --- a/indra/llcommon/tests/StringVec.h +++ b/indra/llcommon/tests/StringVec.h diff --git a/indra/llcommon/tests/bitpack_test.cpp b/indra/llcommon/tests/bitpack_test.cpp index 4c3bc674af..afc0c18cd0 100644..100755 --- a/indra/llcommon/tests/bitpack_test.cpp +++ b/indra/llcommon/tests/bitpack_test.cpp @@ -71,7 +71,6 @@ namespace tut  		U8 packbuffer[255];  		U8 unpackbuffer[255];  		int pack_bufsize = 0; -		int unpack_bufsize = 0;  		LLBitPack bitpack(packbuffer, 255); @@ -81,21 +80,20 @@ namespace tut  		pack_bufsize = bitpack.flushBitPack();  		LLBitPack bitunpack(packbuffer, pack_bufsize*8); -		unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); +		bitunpack.bitUnpack(&unpackbuffer[0], 8);  		ensure("bitPack: individual unpack: 0", unpackbuffer[0] == (U8) str[0]); -		unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); +		bitunpack.bitUnpack(&unpackbuffer[0], 8);  		ensure("bitPack: individual unpack: 1", unpackbuffer[0] == (U8) str[1]); -		unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); +		bitunpack.bitUnpack(&unpackbuffer[0], 8);  		ensure("bitPack: individual unpack: 2", unpackbuffer[0] == (U8) str[2]); -		unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); +		bitunpack.bitUnpack(&unpackbuffer[0], 8);  		ensure("bitPack: individual unpack: 3", unpackbuffer[0] == (U8) str[3]); -		unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); +		bitunpack.bitUnpack(&unpackbuffer[0], 8);  		ensure("bitPack: individual unpack: 4", unpackbuffer[0] == (U8) str[4]); -		unpack_bufsize = bitunpack.bitUnpack(&unpackbuffer[0], 8); +		bitunpack.bitUnpack(&unpackbuffer[0], 8);  		ensure("bitPack: individual unpack: 5", unpackbuffer[0] == (U8) str[5]); -		unpack_bufsize = bitunpack.bitUnpack(unpackbuffer, 8*4); // Life +		bitunpack.bitUnpack(unpackbuffer, 8*4); // Life  		ensure_memory_matches("bitPack: 4 bytes unpack:", unpackbuffer, 4, str+6, 4); -		ensure("keep compiler quiet", unpack_bufsize == unpack_bufsize);  	}  	// U32 packing diff --git a/indra/llcommon/tests/commonmisc_test.cpp b/indra/llcommon/tests/commonmisc_test.cpp index b115c153c1..b115c153c1 100644..100755 --- a/indra/llcommon/tests/commonmisc_test.cpp +++ b/indra/llcommon/tests/commonmisc_test.cpp diff --git a/indra/llcommon/tests/listener.h b/indra/llcommon/tests/listener.h index 9c5c18a150..9c5c18a150 100644..100755 --- a/indra/llcommon/tests/listener.h +++ b/indra/llcommon/tests/listener.h diff --git a/indra/llcommon/tests/llallocator_heap_profile_test.cpp b/indra/llcommon/tests/llallocator_heap_profile_test.cpp index 44a9705803..44a9705803 100644..100755 --- a/indra/llcommon/tests/llallocator_heap_profile_test.cpp +++ b/indra/llcommon/tests/llallocator_heap_profile_test.cpp diff --git a/indra/llcommon/tests/llallocator_test.cpp b/indra/llcommon/tests/llallocator_test.cpp index 4e62eaee67..4e62eaee67 100644..100755 --- a/indra/llcommon/tests/llallocator_test.cpp +++ b/indra/llcommon/tests/llallocator_test.cpp diff --git a/indra/llcommon/tests/llbase64_test.cpp b/indra/llcommon/tests/llbase64_test.cpp index d0394150fa..d0394150fa 100644..100755 --- a/indra/llcommon/tests/llbase64_test.cpp +++ b/indra/llcommon/tests/llbase64_test.cpp diff --git a/indra/llcommon/tests/lldate_test.cpp b/indra/llcommon/tests/lldate_test.cpp index 7c95ccb91f..7c95ccb91f 100644..100755 --- a/indra/llcommon/tests/lldate_test.cpp +++ b/indra/llcommon/tests/lldate_test.cpp diff --git a/indra/llcommon/tests/lldependencies_test.cpp b/indra/llcommon/tests/lldependencies_test.cpp index 5395d785b6..5395d785b6 100644..100755 --- a/indra/llcommon/tests/lldependencies_test.cpp +++ b/indra/llcommon/tests/lldependencies_test.cpp diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index 279a90e51b..279a90e51b 100644..100755 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp diff --git a/indra/llcommon/tests/lleventcoro_test.cpp b/indra/llcommon/tests/lleventcoro_test.cpp index 901ba35b2f..5ebde1a31d 100644..100755 --- a/indra/llcommon/tests/lleventcoro_test.cpp +++ b/indra/llcommon/tests/lleventcoro_test.cpp @@ -64,10 +64,10 @@  // Boost.Coroutine #include is the *first* #include of the platform header.  // That means that client code must generally #include Boost.Coroutine headers  // before anything else. -#include <boost/coroutine/coroutine.hpp> +#include <boost/dcoroutine/coroutine.hpp>  // Normally, lleventcoro.h obviates future.hpp. We only include this because  // we implement a "by hand" test of future functionality. -#include <boost/coroutine/future.hpp> +#include <boost/dcoroutine/future.hpp>  #include <boost/bind.hpp>  #include <boost/range.hpp> @@ -78,6 +78,7 @@  #include "../test/lltut.h"  #include "llsd.h" +#include "llsdutil.h"  #include "llevents.h"  #include "tests/wrapllerrs.h"  #include "stringize.h" @@ -87,7 +88,7 @@  /*****************************************************************************  *   from the banana.cpp example program borrowed for test<1>()  *****************************************************************************/ -namespace coroutines = boost::coroutines; +namespace coroutines = boost::dcoroutines;  using coroutines::coroutine;  template<typename Iter> @@ -108,7 +109,7 @@ match_substring(BidirectionalIterator begin,  		BidirectionalIterator end,   		std::string xmatch,  		BOOST_DEDUCED_TYPENAME coroutine<BidirectionalIterator(void)>::self& self) {  -  BidirectionalIterator begin_ = begin; +//BidirectionalIterator begin_ = begin;    for(; begin != end; ++begin)       if(match(begin, end, xmatch)) {        self.yield(begin); @@ -122,7 +123,7 @@ typedef coroutine<std::string::iterator(void)> match_coroutine_type;  *   Test helpers  *****************************************************************************/  // I suspect this will be typical of coroutines used in Linden software -typedef boost::coroutines::coroutine<void()> coroutine_type; +typedef boost::dcoroutines::coroutine<void()> coroutine_type;  /// Simulate an event API whose response is immediate: sent on receipt of the  /// initial request, rather than after some delay. This is the case that @@ -173,10 +174,10 @@ namespace tut                  // ... do whatever preliminary stuff must happen ...                  // declare the future -                boost::coroutines::future<LLSD> future(self); +                boost::dcoroutines::future<LLSD> future(self);                  // tell the future what to wait for                  LLTempBoundListener connection( -                    LLEventPumps::instance().obtain("source").listen("coro", voidlistener(boost::coroutines::make_callback(future)))); +                    LLEventPumps::instance().obtain("source").listen("coro", voidlistener(boost::dcoroutines::make_callback(future))));                  ensure("Not yet", ! future);                  // attempting to dereference ("resolve") the future causes the calling                  // coroutine to wait for it @@ -213,7 +214,7 @@ namespace tut              BEGIN              {                  result = postAndWait(self, -                                     LLSD().insert("value", 17), // request event +                                     LLSDMap("value", 17),       // request event                                       immediateAPI.getPump(),     // requestPump                                       "reply1",                   // replyPump                                       "reply");                   // request["reply"] = name @@ -226,7 +227,7 @@ namespace tut              BEGIN              {                  LLEventWithID pair = ::postAndWait2(self, -                                                    LLSD().insert("value", 18), +                                                    LLSDMap("value", 18),                                                      immediateAPI.getPump(),                                                      "reply2",                                                      "error2", @@ -244,7 +245,7 @@ namespace tut              BEGIN              {                  LLEventWithID pair = ::postAndWait2(self, -                                                    LLSD().insert("value", 18).insert("fail", LLSD()), +                                                    LLSDMap("value", 18)("fail", LLSD()),                                                      immediateAPI.getPump(),                                                      "reply2",                                                      "error2", @@ -273,7 +274,7 @@ namespace tut              BEGIN              {                  LLCoroEventPump waiter; -                result = waiter.postAndWait(self, LLSD().insert("value", 17), +                result = waiter.postAndWait(self, LLSDMap("value", 17),                                              immediateAPI.getPump(), "reply");              }              END @@ -365,7 +366,7 @@ namespace tut              BEGIN              {                  LLCoroEventPumps waiter; -                LLEventWithID pair(waiter.postAndWait(self, LLSD().insert("value", 23), +                LLEventWithID pair(waiter.postAndWait(self, LLSDMap("value", 23),                                                        immediateAPI.getPump(), "reply", "error"));                  result = pair.first;                  which  = pair.second; @@ -379,7 +380,7 @@ namespace tut              {                  LLCoroEventPumps waiter;                  LLEventWithID pair( -                    waiter.postAndWait(self, LLSD().insert("value", 23).insert("fail", LLSD()), +                    waiter.postAndWait(self, LLSDMap("value", 23)("fail", LLSD()),                                         immediateAPI.getPump(), "reply", "error"));                  result = pair.first;                  which  = pair.second; @@ -392,7 +393,7 @@ namespace tut              BEGIN              {                  LLCoroEventPumps waiter; -                result = waiter.postAndWaitWithException(self, LLSD().insert("value", 8), +                result = waiter.postAndWaitWithException(self, LLSDMap("value", 8),                                                           immediateAPI.getPump(), "reply", "error");              }              END @@ -406,7 +407,7 @@ namespace tut                  try                  {                      result = waiter.postAndWaitWithException(self, -                        LLSD().insert("value", 9).insert("fail", LLSD()), +                        LLSDMap("value", 9)("fail", LLSD()),                          immediateAPI.getPump(), "reply", "error");                      debug("no exception");                  } @@ -424,7 +425,7 @@ namespace tut              BEGIN              {                  LLCoroEventPumps waiter; -                result = waiter.postAndWaitWithLog(self, LLSD().insert("value", 30), +                result = waiter.postAndWaitWithLog(self, LLSDMap("value", 30),                                                     immediateAPI.getPump(), "reply", "error");              }              END @@ -439,7 +440,7 @@ namespace tut                  try                  {                      result = waiter.postAndWaitWithLog(self, -                        LLSD().insert("value", 31).insert("fail", LLSD()), +                        LLSDMap("value", 31)("fail", LLSD()),                          immediateAPI.getPump(), "reply", "error");                      debug("no exception");                  } @@ -796,4 +797,18 @@ namespace tut          ensure("no result", result.isUndefined());          ensure_contains("got error", threw, "32");      } +} + +/*==========================================================================*| +#include <boost/context/guarded_stack_allocator.hpp> + +namespace tut +{ +    template<> template<> +    void object::test<23>() +    { +        set_test_name("stacksize"); +        std::cout << "default_stacksize: " << boost::context::guarded_stack_allocator::default_stacksize() << '\n'; +    }  } // namespace tut +|*==========================================================================*/ diff --git a/indra/llcommon/tests/lleventdispatcher_test.cpp b/indra/llcommon/tests/lleventdispatcher_test.cpp index 263c9b171f..263c9b171f 100644..100755 --- a/indra/llcommon/tests/lleventdispatcher_test.cpp +++ b/indra/llcommon/tests/lleventdispatcher_test.cpp diff --git a/indra/llcommon/tests/lleventfilter_test.cpp b/indra/llcommon/tests/lleventfilter_test.cpp index ca05ef62a9..ca05ef62a9 100644..100755 --- a/indra/llcommon/tests/lleventfilter_test.cpp +++ b/indra/llcommon/tests/lleventfilter_test.cpp diff --git a/indra/llcommon/tests/llframetimer_test.cpp b/indra/llcommon/tests/llframetimer_test.cpp index 8ac1c91a3a..8ac1c91a3a 100644..100755 --- a/indra/llcommon/tests/llframetimer_test.cpp +++ b/indra/llcommon/tests/llframetimer_test.cpp diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp index 454695ff9f..e769c3e22c 100644..100755 --- a/indra/llcommon/tests/llinstancetracker_test.cpp +++ b/indra/llcommon/tests/llinstancetracker_test.cpp @@ -267,7 +267,6 @@ namespace tut          {              existing.insert(&*uki);          } -        Unkeyed* puk = NULL;          try          {              // We don't expect the assignment to take place because we expect @@ -280,7 +279,7 @@ namespace tut              // realize we're testing the C++ implementation more than              // Unkeyed's implementation, but this seems an important point to              // nail down. -            puk = new Unkeyed("throw"); +            new Unkeyed("throw");          }          catch (const Badness&)          { diff --git a/indra/llcommon/tests/lllazy_test.cpp b/indra/llcommon/tests/lllazy_test.cpp index 32a717f4fc..32a717f4fc 100644..100755 --- a/indra/llcommon/tests/lllazy_test.cpp +++ b/indra/llcommon/tests/lllazy_test.cpp diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp index 9b755e9ca5..29060d4ef5 100644..100755 --- a/indra/llcommon/tests/llleap_test.cpp +++ b/indra/llcommon/tests/llleap_test.cpp @@ -122,13 +122,10 @@ namespace tut                     // finding indra/lib/python. Use our __FILE__, with                     // raw-string syntax to deal with Windows pathnames.                     "mydir = os.path.dirname(r'" << __FILE__ << "')\n" -                   "try:\n" -                   "    from llbase import llsd\n" -                   "except ImportError:\n"                     // We expect mydir to be .../indra/llcommon/tests. -                   "    sys.path.insert(0,\n" -                   "        os.path.join(mydir, os.pardir, os.pardir, 'lib', 'python'))\n" -                   "    from indra.base import llsd\n" +                   "sys.path.insert(0,\n" +                   "    os.path.join(mydir, os.pardir, os.pardir, 'lib', 'python'))\n" +                   "from indra.base import llsd\n"                     "\n"                     "class ProtocolError(Exception):\n"                     "    def __init__(self, msg, data):\n" diff --git a/indra/llcommon/tests/llmemtype_test.cpp b/indra/llcommon/tests/llmemtype_test.cpp index 1f050d6dc7..1f050d6dc7 100644..100755 --- a/indra/llcommon/tests/llmemtype_test.cpp +++ b/indra/llcommon/tests/llmemtype_test.cpp diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp index 99186ed434..f188865eb0 100644..100755 --- a/indra/llcommon/tests/llprocess_test.cpp +++ b/indra/llcommon/tests/llprocess_test.cpp @@ -608,6 +608,9 @@ namespace tut      void object::test<5>()      {          set_test_name("exit(2)"); +#if LL_WINDOWS +		skip("MAINT-2302: This frequently (though not always) fails on Windows."); +#endif          PythonProcessLauncher py(get_test_name(),                                   "import sys\n"                                   "sys.exit(2)\n"); @@ -620,6 +623,9 @@ namespace tut      void object::test<6>()      {          set_test_name("syntax_error:"); +#if LL_WINDOWS +		skip("MAINT-2302: This frequently (though not always) fails on Windows."); +#endif          PythonProcessLauncher py(get_test_name(),                                   "syntax_error:\n");          py.mParams.files.add(LLProcess::FileParam()); // inherit stdin @@ -641,6 +647,9 @@ namespace tut      void object::test<7>()      {          set_test_name("explicit kill()"); +#if LL_WINDOWS +		skip("MAINT-2302: This frequently (though not always) fails on Windows."); +#endif          PythonProcessLauncher py(get_test_name(),                                   "from __future__ import with_statement\n"                                   "import sys, time\n" @@ -685,6 +694,9 @@ namespace tut      void object::test<8>()      {          set_test_name("implicit kill()"); +#if LL_WINDOWS +		skip("MAINT-2302: This frequently (though not always) fails on Windows."); +#endif          NamedTempFile out("out", "not started");          LLProcess::handle phandle(0);          { @@ -957,10 +969,7 @@ namespace tut                        childout.getline(), "ok");          // important to get the implicit flush from std::endl          py.mPy->getWritePipe().get_ostream() << "go" << std::endl; -        for (i = 0; i < timeout && py.mPy->isRunning() && ! childout.contains("\n"); ++i) -        { -            yield(); -        } +        waitfor(*py.mPy);          ensure("script never replied", childout.contains("\n"));          ensure_equals("child didn't ack", childout.getline(), "ack");          ensure_equals("bad child termination", py.mPy->getStatus().mState, LLProcess::EXITED); diff --git a/indra/llcommon/tests/llprocessor_test.cpp b/indra/llcommon/tests/llprocessor_test.cpp index 884e1b5e5b..884e1b5e5b 100644..100755 --- a/indra/llcommon/tests/llprocessor_test.cpp +++ b/indra/llcommon/tests/llprocessor_test.cpp diff --git a/indra/llcommon/tests/llrand_test.cpp b/indra/llcommon/tests/llrand_test.cpp index 383e6f9e0a..383e6f9e0a 100644..100755 --- a/indra/llcommon/tests/llrand_test.cpp +++ b/indra/llcommon/tests/llrand_test.cpp diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp index e625545763..4d436e8897 100644..100755 --- a/indra/llcommon/tests/llsdserialize_test.cpp +++ b/indra/llcommon/tests/llsdserialize_test.cpp @@ -1523,10 +1523,7 @@ namespace tut                          "sys.path.insert(0,\n"                          "    os.path.join(os.path.dirname(r'" __FILE__ "'),\n"                          "                 os.pardir, os.pardir, 'lib', 'python'))\n" -                        "try:\n" -                        "    from llbase import llsd\n" -                        "except ImportError:\n" -                        "    from indra.base import llsd\n") +                        "from indra.base import llsd\n")          {}          ~TestPythonCompatible() {} diff --git a/indra/llcommon/tests/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp index 385289aefe..385289aefe 100644..100755 --- a/indra/llcommon/tests/llsingleton_test.cpp +++ b/indra/llcommon/tests/llsingleton_test.cpp diff --git a/indra/llcommon/tests/llstreamqueue_test.cpp b/indra/llcommon/tests/llstreamqueue_test.cpp index 050ad5c5bf..050ad5c5bf 100644..100755 --- a/indra/llcommon/tests/llstreamqueue_test.cpp +++ b/indra/llcommon/tests/llstreamqueue_test.cpp diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp index 93d3968dbf..93d3968dbf 100644..100755 --- a/indra/llcommon/tests/llstring_test.cpp +++ b/indra/llcommon/tests/llstring_test.cpp diff --git a/indra/llcommon/tests/lltreeiterators_test.cpp b/indra/llcommon/tests/lltreeiterators_test.cpp index 1d619867d4..1d619867d4 100644..100755 --- a/indra/llcommon/tests/lltreeiterators_test.cpp +++ b/indra/llcommon/tests/lltreeiterators_test.cpp diff --git a/indra/llcommon/tests/lluri_test.cpp b/indra/llcommon/tests/lluri_test.cpp index 4c64f15ca7..4c64f15ca7 100644..100755 --- a/indra/llcommon/tests/lluri_test.cpp +++ b/indra/llcommon/tests/lluri_test.cpp diff --git a/indra/llcommon/tests/reflection_test.cpp b/indra/llcommon/tests/reflection_test.cpp index 8980ebb1f1..8980ebb1f1 100644..100755 --- a/indra/llcommon/tests/reflection_test.cpp +++ b/indra/llcommon/tests/reflection_test.cpp diff --git a/indra/llcommon/tests/stringize_test.cpp b/indra/llcommon/tests/stringize_test.cpp index 3d34f23998..3d34f23998 100644..100755 --- a/indra/llcommon/tests/stringize_test.cpp +++ b/indra/llcommon/tests/stringize_test.cpp diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index a4d3a4e026..a4d3a4e026 100644..100755 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h diff --git a/indra/llcommon/timer.h b/indra/llcommon/timer.h index 82d19c2d32..82d19c2d32 100644..100755 --- a/indra/llcommon/timer.h +++ b/indra/llcommon/timer.h diff --git a/indra/llcommon/timing.cpp b/indra/llcommon/timing.cpp index c2dc695ef3..c2dc695ef3 100644..100755 --- a/indra/llcommon/timing.cpp +++ b/indra/llcommon/timing.cpp diff --git a/indra/llcommon/timing.h b/indra/llcommon/timing.h index c408d4c446..c408d4c446 100644..100755 --- a/indra/llcommon/timing.h +++ b/indra/llcommon/timing.h diff --git a/indra/llcommon/u64.cpp b/indra/llcommon/u64.cpp index eea16c5036..eea16c5036 100644..100755 --- a/indra/llcommon/u64.cpp +++ b/indra/llcommon/u64.cpp diff --git a/indra/llcommon/u64.h b/indra/llcommon/u64.h index 75c8a59136..75c8a59136 100644..100755 --- a/indra/llcommon/u64.h +++ b/indra/llcommon/u64.h  | 
