summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/CMakeLists.txt5
-rw-r--r--indra/llcommon/llallocator.cpp33
-rw-r--r--indra/llcommon/llallocator.h6
-rw-r--r--indra/llcommon/llassettype.cpp1
-rw-r--r--indra/llcommon/llassettype.h3
-rw-r--r--indra/llcommon/llavatarname.cpp128
-rw-r--r--indra/llcommon/llavatarname.h65
-rw-r--r--indra/llcommon/llfasttimer.cpp (renamed from indra/llcommon/llfasttimer_class.cpp)349
-rw-r--r--indra/llcommon/llfasttimer.h362
-rw-r--r--indra/llcommon/llfasttimer_class.h276
-rwxr-xr-x[-rw-r--r--]indra/llcommon/llfoldertype.h0
-rw-r--r--indra/llcommon/llhandle.h13
-rw-r--r--indra/llcommon/llinitparam.cpp82
-rw-r--r--indra/llcommon/llinitparam.h1741
-rw-r--r--indra/llcommon/llinstancetracker.h5
-rw-r--r--indra/llcommon/llmemory.h4
-rw-r--r--indra/llcommon/llmemtype.cpp232
-rw-r--r--indra/llcommon/llmemtype.h242
-rw-r--r--indra/llcommon/llrefcount.h19
-rw-r--r--indra/llcommon/llregistry.h4
-rw-r--r--indra/llcommon/llsdparam.cpp51
-rw-r--r--indra/llcommon/llstat.cpp1031
-rw-r--r--indra/llcommon/llstat.h283
-rw-r--r--indra/llcommon/llthread.h17
-rw-r--r--indra/llcommon/lluuid.cpp37
-rw-r--r--indra/llcommon/lluuid.h3
-rw-r--r--indra/llcommon/llversionviewer.h4
-rw-r--r--indra/llcommon/stdenums.h3
28 files changed, 1889 insertions, 3110 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 66e2bc9095..5cce8ff2c4 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -53,7 +53,7 @@ set(llcommon_SOURCE_FILES
lleventfilter.cpp
llevents.cpp
lleventtimer.cpp
- llfasttimer_class.cpp
+ llfasttimer.cpp
llfile.cpp
llfindlocale.cpp
llfixedbuffer.cpp
@@ -71,7 +71,6 @@ set(llcommon_SOURCE_FILES
llmd5.cpp
llmemory.cpp
llmemorystream.cpp
- llmemtype.cpp
llmetrics.cpp
llmetricperformancetester.cpp
llmortician.cpp
@@ -168,7 +167,6 @@ set(llcommon_HEADER_FILES
lleventemitter.h
llextendedstatus.h
llfasttimer.h
- llfasttimer_class.h
llfile.h
llfindlocale.h
llfixedbuffer.h
@@ -197,7 +195,6 @@ set(llcommon_HEADER_FILES
llmd5.h
llmemory.h
llmemorystream.h
- llmemtype.h
llmetrics.h
llmetricperformancetester.h
llmortician.h
diff --git a/indra/llcommon/llallocator.cpp b/indra/llcommon/llallocator.cpp
index 87654b5b97..34fc28d8cc 100644
--- 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
--- 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/llassettype.cpp b/indra/llcommon/llassettype.cpp
index 5e566d6c7c..5ae2df3994 100644
--- 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
--- 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/llavatarname.cpp b/indra/llcommon/llavatarname.cpp
index 3206843bf4..95ecce509b 100644
--- 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,36 +105,120 @@ 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;
}
-std::string LLAvatarName::getLegacyName() const
+std::string LLAvatarName::getDisplayName() const
{
- if (mLegacyFirstName.empty() && mLegacyLastName.empty()) // display names disabled?
+ if (sUseDisplayNames)
{
return mDisplayName;
}
+ else
+ {
+ return getUserName();
+ }
+}
+std::string LLAvatarName::getUserName() const
+{
std::string name;
- name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() );
- name = mLegacyFirstName;
- name += " ";
- name += mLegacyLastName;
+ 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..4827353018 100644
--- a/indra/llcommon/llavatarname.h
+++ b/indra/llcommon/llavatarname.h
@@ -39,23 +39,62 @@ 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;
+
+ // "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; }
- // 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;
-
+ // 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 +120,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/llfasttimer_class.cpp b/indra/llcommon/llfasttimer.cpp
index 463f558c2c..6970c29092 100644
--- 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))
-{
- mFrameState = &mTimer.getFrameState();
- update_cached_pointers_if_changed();
-}
-
-// static
-void LLFastTimer::DeclareTimer::updateCachedPointers()
+: mTimer(NamedTimerFactory::instance().createNamedTimer(name, &mFrameState))
{
- // 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()
@@ -777,145 +654,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..e42e549df5 100644
--- 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,363 @@
#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;
+
+ 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/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/llhandle.h b/indra/llcommon/llhandle.h
index 6af5e198d6..401e4d759a 100644
--- 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/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index db72aa19b9..89c831d296 100644
--- 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
--- 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*)&param);
- }
- 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*)&param);
+ }
+
+ 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*)&param);
+ }
+ 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*)&param, 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*)&param, 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.h b/indra/llcommon/llinstancetracker.h
index 403df08990..1eab270e3c 100644
--- 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/llmemory.h b/indra/llcommon/llmemory.h
index 10013e0f92..e725bdd9fa 100644
--- 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/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/llrefcount.h b/indra/llcommon/llrefcount.h
index 8eb5d53f3f..32ae15435a 100644
--- 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
--- 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/llsdparam.cpp b/indra/llcommon/llsdparam.cpp
index 0e29873bb0..9f4460a988 100644
--- a/indra/llcommon/llsdparam.cpp
+++ b/indra/llcommon/llsdparam.cpp
@@ -223,10 +223,14 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser:
{
bool new_traversal = it->second;
- LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first];
-
- if (child_sd->isArray())
+ LLSD* child_sd;
+ if (it->first.empty())
{
+ child_sd = sd_to_write;
+ if (child_sd->isUndefined())
+ {
+ *child_sd = LLSD::emptyArray();
+ }
if (new_traversal)
{
// write to new element at end
@@ -240,22 +244,7 @@ LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser:
}
else
{
- if (new_traversal
- && child_sd->isDefined()
- && !child_sd->isArray())
- {
- // copy child contents into first element of an array
- LLSD new_array = LLSD::emptyArray();
- new_array.append(*child_sd);
- // assign array to slot that previously held the single value
- *child_sd = new_array;
- // return next element in that array
- sd_to_write = &((*child_sd)[1]);
- }
- else
- {
- sd_to_write = child_sd;
- }
+ sd_to_write = &(*sd_to_write)[it->first];
}
it->second = false;
}
@@ -283,8 +272,9 @@ void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLI
it != sd.endArray();
++it)
{
- stack.back().second = true;
+ stack.push_back(make_pair(std::string(), true));
readSDValues(cb, *it, stack);
+ stack.pop_back();
}
}
else if (sd.isUndefined())
@@ -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/llstat.cpp b/indra/llcommon/llstat.cpp
index b82d52797e..3678c8e1c1 100644
--- 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
--- 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/llthread.h b/indra/llcommon/llthread.h
index 5c8bbca2ca..0fb89c5613 100644
--- 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/lluuid.cpp b/indra/llcommon/lluuid.cpp
index db8c9c85ab..0aaa50d231 100644
--- 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(&timestamp);
+ U16 our_clock_seq = clock_seq;
- // if clock went backward change clockseq
- if (cmpTime(&timestamp, &time_last) == -1) {
+ // if clock hasn't changed or went backward, change clockseq
+ if (cmpTime(&timestamp, &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
--- 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/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 8585af0a29..0b0c74b3d3 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -28,8 +28,8 @@
#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_MINOR = 5;
+const S32 LL_VERSION_PATCH = 1;
const S32 LL_VERSION_BUILD = 0;
const char * const LL_CHANNEL = "Second Life Developer";
diff --git a/indra/llcommon/stdenums.h b/indra/llcommon/stdenums.h
index 40b3364b36..efcbe76795 100644
--- 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.