summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorMonty Brandenberg <monty@lindenlab.com>2014-05-22 22:08:54 +0000
committerMonty Brandenberg <monty@lindenlab.com>2014-05-22 22:08:54 +0000
commit060c728970dc78d30f2cebdbeda7e56ea8de46e2 (patch)
tree8f00ce1b3bd564bc6cb81a2bc39a081eb3deca35 /indra/llcommon
parentf8874d04b8ca238ee99dc464055295cff417a9b2 (diff)
parent644ca6a0f8a7759119814f88df93b8e838321a12 (diff)
Merge. Pull in viewer-release after release of 3.7.8
Diffstat (limited to 'indra/llcommon')
-rwxr-xr-xindra/llcommon/CMakeLists.txt87
-rwxr-xr-xindra/llcommon/doublelinkedlist.h1397
-rwxr-xr-xindra/llcommon/imageids.cpp73
-rwxr-xr-xindra/llcommon/imageids.h70
-rwxr-xr-xindra/llcommon/indra_constants.cpp31
-rwxr-xr-xindra/llcommon/indra_constants.h356
-rwxr-xr-xindra/llcommon/linked_lists.h937
-rwxr-xr-xindra/llcommon/ll_template_cast.h177
-rwxr-xr-xindra/llcommon/llaccountingcost.h86
-rwxr-xr-xindra/llcommon/llagentconstants.h159
-rw-r--r--indra/llcommon/llalignedarray.h10
-rwxr-xr-xindra/llcommon/llallocator_heap_profile.cpp2
-rwxr-xr-xindra/llcommon/llapp.cpp304
-rwxr-xr-xindra/llcommon/llapp.h57
-rwxr-xr-xindra/llcommon/llapr.cpp25
-rwxr-xr-xindra/llcommon/llapr.h40
-rwxr-xr-xindra/llcommon/llassettype.h2
-rwxr-xr-xindra/llcommon/llassoclist.h296
-rwxr-xr-xindra/llcommon/llavatarconstants.h55
-rwxr-xr-xindra/llcommon/llavatarname.cpp254
-rwxr-xr-xindra/llcommon/llavatarname.h139
-rwxr-xr-xindra/llcommon/llbase32.cpp4
-rwxr-xr-xindra/llcommon/llbitpack.cpp (renamed from indra/llcommon/bitpack.cpp)2
-rwxr-xr-xindra/llcommon/llbitpack.h (renamed from indra/llcommon/bitpack.h)12
-rwxr-xr-xindra/llcommon/llchat.h109
-rw-r--r--[-rwxr-xr-x]indra/llcommon/llclickaction.h11
-rwxr-xr-xindra/llcommon/llcommon.cpp16
-rwxr-xr-xindra/llcommon/llcommonutils.h2
-rwxr-xr-xindra/llcommon/llcrc.cpp4
-rwxr-xr-xindra/llcommon/llcrc.h2
-rwxr-xr-xindra/llcommon/llcriticaldamp.cpp77
-rwxr-xr-xindra/llcommon/llcriticaldamp.h32
-rwxr-xr-xindra/llcommon/llcursortypes.cpp91
-rwxr-xr-xindra/llcommon/llcursortypes.h79
-rwxr-xr-xindra/llcommon/lldarray.h223
-rwxr-xr-xindra/llcommon/lldate.cpp24
-rwxr-xr-xindra/llcommon/lldate.h5
-rw-r--r--indra/llcommon/lldeadmantimer.cpp6
-rwxr-xr-xindra/llcommon/lldeleteutils.h47
-rwxr-xr-xindra/llcommon/lldepthstack.h39
-rwxr-xr-xindra/llcommon/lldictionary.h2
-rwxr-xr-xindra/llcommon/lldlinked.h93
-rwxr-xr-xindra/llcommon/lldqueueptr.h352
-rwxr-xr-xindra/llcommon/llenum.h78
-rwxr-xr-xindra/llcommon/llerror.cpp483
-rwxr-xr-xindra/llcommon/llerror.h248
-rwxr-xr-xindra/llcommon/llerrorcontrol.h16
-rwxr-xr-xindra/llcommon/llerrorlegacy.h86
-rwxr-xr-xindra/llcommon/llerrorthread.cpp89
-rwxr-xr-xindra/llcommon/llevent.h2
-rwxr-xr-xindra/llcommon/llevents.cpp1
-rwxr-xr-xindra/llcommon/llevents.h2
-rwxr-xr-xindra/llcommon/llextendedstatus.h67
-rwxr-xr-xindra/llcommon/llfasttimer.cpp662
-rwxr-xr-xindra/llcommon/llfasttimer.h380
-rwxr-xr-xindra/llcommon/llfile.cpp57
-rwxr-xr-xindra/llcommon/llfile.h2
-rwxr-xr-xindra/llcommon/llfindlocale.cpp2
-rwxr-xr-xindra/llcommon/llfoldertype.cpp168
-rw-r--r--indra/llcommon/llfoldertype.h111
-rwxr-xr-xindra/llcommon/llformat.h2
-rwxr-xr-xindra/llcommon/llframetimer.cpp8
-rwxr-xr-xindra/llcommon/llframetimer.h5
-rwxr-xr-xindra/llcommon/llheartbeat.cpp8
-rwxr-xr-xindra/llcommon/llindexedqueue.h155
-rwxr-xr-xindra/llcommon/llindexedvector.h100
-rwxr-xr-xindra/llcommon/llinitparam.cpp46
-rwxr-xr-xindra/llcommon/llinitparam.h447
-rwxr-xr-xindra/llcommon/llinstancetracker.cpp18
-rwxr-xr-xindra/llcommon/llinstancetracker.h109
-rwxr-xr-xindra/llcommon/lllazy.cpp40
-rwxr-xr-xindra/llcommon/lllazy.h399
-rwxr-xr-xindra/llcommon/llleap.cpp2
-rwxr-xr-xindra/llcommon/lllinkedqueue.h309
-rwxr-xr-xindra/llcommon/llliveappconfig.cpp10
-rwxr-xr-xindra/llcommon/lllocalidhashmap.h895
-rwxr-xr-xindra/llcommon/lllog.cpp111
-rwxr-xr-xindra/llcommon/lllog.h52
-rwxr-xr-xindra/llcommon/lllslconstants.h242
-rwxr-xr-xindra/llcommon/llmap.h245
-rwxr-xr-xindra/llcommon/llmd5.cpp1
-rwxr-xr-xindra/llcommon/llmemory.cpp283
-rwxr-xr-xindra/llcommon/llmemory.h136
-rwxr-xr-xindra/llcommon/llmemorystream.cpp2
-rwxr-xr-xindra/llcommon/llmetricperformancetester.cpp17
-rwxr-xr-xindra/llcommon/llmetrics.cpp4
-rwxr-xr-xindra/llcommon/llmetrics.h2
-rwxr-xr-xindra/llcommon/llmortician.h1
-rw-r--r--indra/llcommon/llmutex.cpp205
-rw-r--r--indra/llcommon/llmutex.h141
-rw-r--r--[-rwxr-xr-x]indra/llcommon/llnametable.h0
-rwxr-xr-xindra/llcommon/lloptioninterface.cpp33
-rwxr-xr-xindra/llcommon/llpointer.h87
-rw-r--r--[-rwxr-xr-x]indra/llcommon/llpredicate.cpp (renamed from indra/llcommon/lloptioninterface.h)29
-rw-r--r--indra/llcommon/llpredicate.h210
-rwxr-xr-xindra/llcommon/llpreprocessor.h21
-rwxr-xr-xindra/llcommon/llpriqueuemap.h6
-rwxr-xr-xindra/llcommon/llprocess.h4
-rwxr-xr-xindra/llcommon/llprocessor.cpp8
-rwxr-xr-xindra/llcommon/llprocessor.h4
-rwxr-xr-xindra/llcommon/llptrskiplist.h724
-rwxr-xr-xindra/llcommon/llptrskipmap.h1239
-rwxr-xr-xindra/llcommon/llptrto.h1
-rwxr-xr-xindra/llcommon/llqueuedthread.cpp33
-rwxr-xr-xindra/llcommon/llrefcount.cpp10
-rwxr-xr-xindra/llcommon/llrefcount.h79
-rwxr-xr-xindra/llcommon/llregistry.h16
-rwxr-xr-xindra/llcommon/llsafehandle.h2
-rwxr-xr-xindra/llcommon/llsdparam.cpp15
-rwxr-xr-xindra/llcommon/llsdparam.h24
-rwxr-xr-xindra/llcommon/llsdserialize.cpp68
-rwxr-xr-xindra/llcommon/llsdserialize_xml.cpp6
-rwxr-xr-xindra/llcommon/llsdutil.h2
-rwxr-xr-xindra/llcommon/llsecondlifeurls.cpp84
-rwxr-xr-xindra/llcommon/llsecondlifeurls.h76
-rwxr-xr-xindra/llcommon/llsingleton.h16
-rwxr-xr-xindra/llcommon/llskiplist.h517
-rwxr-xr-xindra/llcommon/llskipmap.h1022
-rwxr-xr-xindra/llcommon/llsortedvector.h152
-rwxr-xr-xindra/llcommon/llstack.h48
-rwxr-xr-xindra/llcommon/llstacktrace.cpp2
-rwxr-xr-xindra/llcommon/llstat.cpp404
-rwxr-xr-xindra/llcommon/llstat.h116
-rw-r--r--[-rwxr-xr-x]indra/llcommon/llstatenums.h44
-rwxr-xr-xindra/llcommon/llstl.h200
-rwxr-xr-xindra/llcommon/llstring.cpp16
-rwxr-xr-xindra/llcommon/llstring.h14
-rwxr-xr-xindra/llcommon/llstringtable.cpp4
-rwxr-xr-xindra/llcommon/llsys.cpp70
-rwxr-xr-xindra/llcommon/llsys.h10
-rwxr-xr-xindra/llcommon/llthread.cpp274
-rwxr-xr-xindra/llcommon/llthread.h202
-rw-r--r--indra/llcommon/llthreadlocalstorage.cpp119
-rw-r--r--indra/llcommon/llthreadlocalstorage.h185
-rwxr-xr-xindra/llcommon/llthreadsafequeue.cpp2
-rwxr-xr-xindra/llcommon/lltimer.cpp124
-rwxr-xr-xindra/llcommon/lltimer.h63
-rw-r--r--indra/llcommon/lltrace.cpp86
-rw-r--r--indra/llcommon/lltrace.h492
-rw-r--r--indra/llcommon/lltraceaccumulators.cpp302
-rw-r--r--indra/llcommon/lltraceaccumulators.h590
-rw-r--r--indra/llcommon/lltracerecording.cpp1251
-rw-r--r--indra/llcommon/lltracerecording.h670
-rw-r--r--indra/llcommon/lltracethreadrecorder.cpp329
-rw-r--r--indra/llcommon/lltracethreadrecorder.h102
-rwxr-xr-xindra/llcommon/lltypeinfolookup.h117
-rw-r--r--indra/llcommon/llunits.h129
-rw-r--r--indra/llcommon/llunittype.h836
-rwxr-xr-xindra/llcommon/lluri.cpp12
-rwxr-xr-xindra/llcommon/lluuid.cpp12
-rwxr-xr-xindra/llcommon/lluuid.h1
-rwxr-xr-xindra/llcommon/lluuidhashmap.h583
-rw-r--r--[-rwxr-xr-x]indra/llcommon/llwin32headers.h (renamed from indra/llcommon/llversionserver.h)28
-rw-r--r--[-rwxr-xr-x]indra/llcommon/llwin32headerslean.h (renamed from indra/llcommon/lldarrayptr.h)24
-rwxr-xr-xindra/llcommon/llworkerthread.cpp24
-rwxr-xr-xindra/llcommon/llworkerthread.h5
-rwxr-xr-xindra/llcommon/metaclass.cpp81
-rwxr-xr-xindra/llcommon/metaclass.h82
-rwxr-xr-xindra/llcommon/metaclasst.h60
-rwxr-xr-xindra/llcommon/metaproperty.cpp56
-rwxr-xr-xindra/llcommon/metaproperty.h73
-rwxr-xr-xindra/llcommon/metapropertyt.h183
-rwxr-xr-xindra/llcommon/reflective.cpp40
-rwxr-xr-xindra/llcommon/reflective.h42
-rwxr-xr-xindra/llcommon/reflectivet.h48
-rwxr-xr-xindra/llcommon/roles_constants.h192
-rwxr-xr-xindra/llcommon/stdenums.h137
-rw-r--r--[-rwxr-xr-x]indra/llcommon/string_table.h0
-rwxr-xr-xindra/llcommon/stringize.h51
-rwxr-xr-xindra/llcommon/tests/bitpack_test.cpp2
-rwxr-xr-xindra/llcommon/tests/commonmisc_test.cpp10
-rw-r--r--indra/llcommon/tests/lldeadmantimer_test.cpp6
-rwxr-xr-xindra/llcommon/tests/llerror_test.cpp90
-rwxr-xr-xindra/llcommon/tests/lleventcoro_test.cpp8
-rwxr-xr-xindra/llcommon/tests/lleventdispatcher_test.cpp2
-rwxr-xr-xindra/llcommon/tests/lleventfilter_test.cpp4
-rwxr-xr-xindra/llcommon/tests/llinstancetracker_test.cpp16
-rwxr-xr-xindra/llcommon/tests/llleap_test.cpp3
-rwxr-xr-xindra/llcommon/tests/llprocess_test.cpp13
-rwxr-xr-xindra/llcommon/tests/llsdserialize_test.cpp6
-rw-r--r--indra/llcommon/tests/lltrace_test.cpp142
-rw-r--r--indra/llcommon/tests/llunits_test.cpp388
-rwxr-xr-xindra/llcommon/tests/reflection_test.cpp220
-rwxr-xr-xindra/llcommon/tests/stringize_test.cpp20
-rwxr-xr-xindra/llcommon/tests/wrapllerrs.h8
-rwxr-xr-xindra/llcommon/timing.h42
-rwxr-xr-xindra/llcommon/u64.cpp2
187 files changed, 9295 insertions, 16948 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index e4b27c15af..81ccb756e0 100755
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -26,22 +26,20 @@ include_directories(
# ${LLCOMMON_LIBRARIES})
set(llcommon_SOURCE_FILES
- imageids.cpp
indra_constants.cpp
llallocator.cpp
llallocator_heap_profile.cpp
llapp.cpp
llapr.cpp
llassettype.cpp
- llavatarname.cpp
llbase32.cpp
llbase64.cpp
+ llbitpack.cpp
llcommon.cpp
llcommonutils.cpp
llcoros.cpp
llcrc.cpp
llcriticaldamp.cpp
- llcursortypes.cpp
lldate.cpp
lldeadmantimer.cpp
lldependencies.cpp
@@ -59,7 +57,6 @@ set(llcommon_SOURCE_FILES
llfile.cpp
llfindlocale.cpp
llfixedbuffer.cpp
- llfoldertype.cpp
llformat.cpp
llframetimer.cpp
llheartbeat.cpp
@@ -69,15 +66,15 @@ set(llcommon_SOURCE_FILES
llleaplistener.cpp
llliveappconfig.cpp
lllivefile.cpp
- lllog.cpp
llmd5.cpp
llmemory.cpp
llmemorystream.cpp
llmetrics.cpp
llmetricperformancetester.cpp
llmortician.cpp
- lloptioninterface.cpp
+ llmutex.cpp
llptrto.cpp
+ llpredicate.cpp
llprocess.cpp
llprocessor.cpp
llprocinfo.cpp
@@ -90,9 +87,7 @@ set(llcommon_SOURCE_FILES
llsdserialize.cpp
llsdserialize_xml.cpp
llsdutil.cpp
- llsecondlifeurls.cpp
llsingleton.cpp
- llstat.cpp
llstacktrace.cpp
llstreamqueue.cpp
llstreamtools.cpp
@@ -100,14 +95,16 @@ set(llcommon_SOURCE_FILES
llstringtable.cpp
llsys.cpp
llthread.cpp
+ llthreadlocalstorage.cpp
llthreadsafequeue.cpp
lltimer.cpp
+ lltrace.cpp
+ lltraceaccumulators.cpp
+ lltracerecording.cpp
+ lltracethreadrecorder.cpp
lluri.cpp
lluuid.cpp
llworkerthread.cpp
- metaclass.cpp
- metaproperty.cpp
- reflective.cpp
timing.cpp
u64.cpp
)
@@ -115,53 +112,35 @@ set(llcommon_SOURCE_FILES
set(llcommon_HEADER_FILES
CMakeLists.txt
- bitpack.h
ctype_workaround.h
- doublelinkedlist.h
fix_macros.h
- imageids.h
indra_constants.h
linden_common.h
- linked_lists.h
- llaccountingcost.h
llalignedarray.h
llallocator.h
llallocator_heap_profile.h
- llagentconstants.h
- llavatarname.h
llapp.h
llapr.h
llassettype.h
- llassoclist.h
- llavatarconstants.h
llbase32.h
llbase64.h
+ llbitpack.h
llboost.h
- llchat.h
- llclickaction.h
llcommon.h
llcommonutils.h
llcoros.h
llcrc.h
llcriticaldamp.h
- llcursortypes.h
- lldarray.h
- lldarrayptr.h
lldate.h
lldeadmantimer.h
lldefs.h
lldependencies.h
- lldeleteutils.h
lldepthstack.h
lldictionary.h
- lldlinked.h
lldoubledispatch.h
- lldqueueptr.h
llendianswizzle.h
- llenum.h
llerror.h
llerrorcontrol.h
- llerrorlegacy.h
llerrorthread.h
llevent.h
lleventapi.h
@@ -170,33 +149,25 @@ set(llcommon_HEADER_FILES
lleventfilter.h
llevents.h
lleventemitter.h
- llextendedstatus.h
llfasttimer.h
llfile.h
llfindlocale.h
llfixedbuffer.h
- llfoldertype.h
llformat.h
llframetimer.h
llhandle.h
llhash.h
llheartbeat.h
llhttpstatuscodes.h
- llindexedqueue.h
+ llindexedvector.h
llinitparam.h
llinstancetracker.h
llkeythrottle.h
- lllazy.h
llleap.h
llleaplistener.h
lllistenerwrapper.h
- lllinkedqueue.h
llliveappconfig.h
lllivefile.h
- lllocalidhashmap.h
- lllog.h
- lllslconstants.h
- llmap.h
llmd5.h
llmemory.h
llmemorystream.h
@@ -204,15 +175,13 @@ set(llcommon_HEADER_FILES
llmetricperformancetester.h
llmortician.h
llnametable.h
- lloptioninterface.h
llpointer.h
+ llpredicate.h
llpreprocessor.h
llpriqueuemap.h
llprocess.h
llprocessor.h
llprocinfo.h
- llptrskiplist.h
- llptrskipmap.h
llptrto.h
llqueuedthread.h
llrand.h
@@ -226,16 +195,9 @@ set(llcommon_HEADER_FILES
llsdserialize.h
llsdserialize_xml.h
llsdutil.h
- llsecondlifeurls.h
llsimplehash.h
llsingleton.h
- llskiplist.h
- llskipmap.h
- llsortedvector.h
- llstack.h
llstacktrace.h
- llstat.h
- llstatenums.h
llstl.h
llstreamqueue.h
llstreamtools.h
@@ -245,29 +207,24 @@ set(llcommon_HEADER_FILES
llstaticstringtable.h
llsys.h
llthread.h
+ llthreadlocalstorage.h
llthreadsafequeue.h
lltimer.h
+ lltrace.h
+ lltraceaccumulators.h
+ lltracerecording.h
+ lltracethreadrecorder.h
lltreeiterators.h
- lltypeinfolookup.h
+ llunits.h
+ llunittype.h
lluri.h
lluuid.h
- lluuidhashmap.h
- llversionserver.h
+ llwin32headers.h
+ llwin32headerslean.h
llworkerthread.h
- ll_template_cast.h
- metaclass.h
- metaclasst.h
- metaproperty.h
- metapropertyt.h
- reflective.h
- reflectivet.h
- roles_constants.h
- stdenums.h
stdtypes.h
- string_table.h
stringize.h
timer.h
- timing.h
u64.h
)
@@ -333,16 +290,16 @@ if (LL_TESTS)
LL_ADD_INTEGRATION_TEST(llerror "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llinstancetracker "" "${test_libs}")
- LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llprocessor "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llprocinfo "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(lltrace "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}")
- LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}")
+ LL_ADD_INTEGRATION_TEST(llunits "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(lleventcoro "" "${test_libs};${BOOST_CONTEXT_LIBRARY};${BOOST_COROUTINE_LIBRARY};${BOOST_SYSTEM_LIBRARY}")
diff --git a/indra/llcommon/doublelinkedlist.h b/indra/llcommon/doublelinkedlist.h
deleted file mode 100755
index 0aeaa69df3..0000000000
--- a/indra/llcommon/doublelinkedlist.h
+++ /dev/null
@@ -1,1397 +0,0 @@
-/**
- * @file doublelinkedlist.h
- * @brief Provides a standard doubly linked list for fun and profit.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_DOUBLELINKEDLIST_H
-#define LL_DOUBLELINKEDLIST_H
-
-#include "llerror.h"
-#include "llrand.h"
-
-// node that actually contains the data
-template <class DATA_TYPE> class LLDoubleLinkedNode
-{
-public:
- DATA_TYPE *mDatap;
- LLDoubleLinkedNode *mNextp;
- LLDoubleLinkedNode *mPrevp;
-
-
-public:
- // assign the mDatap pointer
- LLDoubleLinkedNode(DATA_TYPE *data);
-
- // destructor does not, by default, destroy associated data
- // however, the mDatap must be NULL to ensure that we aren't causing memory leaks
- ~LLDoubleLinkedNode();
-
- // delete associated data and NULL out pointer
- void deleteData();
-
- // remove associated data and NULL out pointer
- void removeData();
-};
-
-
-const U32 LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH = 4;
-
-template <class DATA_TYPE> class LLDoubleLinkedList
-{
-private:
- LLDoubleLinkedNode<DATA_TYPE> mHead; // head node
- LLDoubleLinkedNode<DATA_TYPE> mTail; // tail node
- LLDoubleLinkedNode<DATA_TYPE> *mQueuep; // The node in the batter's box
- LLDoubleLinkedNode<DATA_TYPE> *mCurrentp; // The node we're talking about
-
- // The state stack allows nested exploration of the LLDoubleLinkedList
- // but should be used with great care
- LLDoubleLinkedNode<DATA_TYPE> *mQueuepStack[LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH];
- LLDoubleLinkedNode<DATA_TYPE> *mCurrentpStack[LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH];
- U32 mStateStackDepth;
- U32 mCount;
-
- // mInsertBefore is a pointer to a user-set function that returns
- // TRUE if "first" should be located before "second"
- // NOTE: mInsertBefore() should never return TRUE when ("first" == "second")
- // or never-ending loops can occur
- BOOL (*mInsertBefore)(DATA_TYPE *first, DATA_TYPE *second);
-
-public:
- LLDoubleLinkedList();
-
- // destructor destroys list and nodes, but not data in nodes
- ~LLDoubleLinkedList();
-
- // put data into a node and stick it at the front of the list
- // set mCurrentp to mQueuep
- void addData(DATA_TYPE *data);
-
- // put data into a node and stick it at the end of the list
- // set mCurrentp to mQueuep
- void addDataAtEnd(DATA_TYPE *data);
-
- S32 getLength() const;
- // search the list starting at mHead.mNextp and remove the link with mDatap == data
- // set mCurrentp to mQueuep
- // return TRUE if found, FALSE if not found
- BOOL removeData(const DATA_TYPE *data);
-
- // search the list starting at mHead.mNextp and delete the link with mDatap == data
- // set mCurrentp to mQueuep
- // return TRUE if found, FALSE if not found
- BOOL deleteData(DATA_TYPE *data);
-
- // remove all nodes from the list and delete the associated data
- void deleteAllData();
-
- // remove all nodes from the list but do not delete data
- void removeAllNodes();
-
- BOOL isEmpty();
-
- // check to see if data is in list
- // set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
- // return TRUE if found, FALSE if not found
- BOOL checkData(const DATA_TYPE *data);
-
- // NOTE: This next two funtions are only included here
- // for those too familiar with the LLLinkedList template class.
- // They are depreciated. resetList() is unecessary while
- // getCurrentData() is identical to getNextData() and has
- // a misleading name.
- //
- // The recommended way to loop through a list is as follows:
- //
- // datap = list.getFirstData();
- // while (datap)
- // {
- // /* do stuff */
- // datap = list.getNextData();
- // }
-
- // place mQueuep on mHead node
- void resetList();
-
- // return the data currently pointed to,
- // set mCurrentp to that node and bump mQueuep down the list
- // NOTE: this function is identical to getNextData()
- DATA_TYPE *getCurrentData();
-
-
- // reset the list and return the data currently pointed to,
- // set mCurrentp to that node and bump mQueuep down the list
- DATA_TYPE *getFirstData();
-
-
- // reset the list and return the data at position n, set mCurentp
- // to that node and bump mQueuep down the list
- // Note: n=0 will behave like getFirstData()
- DATA_TYPE *getNthData(U32 n);
-
- // reset the list and return the last data in it,
- // set mCurrentp to that node and bump mQueuep up the list
- DATA_TYPE *getLastData();
-
- // return data in mQueuep,
- // set mCurrentp mQueuep and bump mQueuep down the list
- DATA_TYPE *getNextData();
-
- // return the data in mQueuep,
- // set mCurrentp to mQueuep and bump mQueuep up the list
- DATA_TYPE *getPreviousData();
-
- // remove the Node at mCurrentp
- // set mCurrentp to mQueuep
- void removeCurrentData();
-
- // delete the Node at mCurrentp
- // set mCurrentp to mQueuep
- void deleteCurrentData();
-
- // remove the Node at mCurrentp and insert it into newlist
- // set mCurrentp to mQueuep
- void moveCurrentData(LLDoubleLinkedList<DATA_TYPE> *newlist);
-
- // insert the node in front of mCurrentp
- // set mCurrentp to mQueuep
- void insertNode(LLDoubleLinkedNode<DATA_TYPE> *node);
-
- // insert the data in front of mCurrentp
- // set mCurrentp to mQueuep
- void insertData(DATA_TYPE *data);
-
- // if mCurrentp has a previous node then :
- // * swaps mCurrentp with its previous
- // * set mCurrentp to mQueuep
- // (convenient for forward bubble-sort)
- // otherwise does nothing
- void swapCurrentWithPrevious();
-
- // if mCurrentp has a next node then :
- // * swaps mCurrentp with its next
- // * set mCurrentp to mQueuep
- // (convenient for backwards bubble-sort)
- // otherwise does nothing
- void swapCurrentWithNext();
-
- // move mCurrentp to the front of the list
- // set mCurrentp to mQueuep
- void moveCurrentToFront();
-
- // move mCurrentp to the end of the list
- // set mCurrentp to mQueuep
- void moveCurrentToEnd();
-
- // set mInsertBefore
- void setInsertBefore(BOOL (*insert_before)(DATA_TYPE *first, DATA_TYPE *second));
-
- // add data in front of first node for which mInsertBefore(datap, node->mDatap) returns TRUE
- // set mCurrentp to mQueuep
- BOOL addDataSorted(DATA_TYPE *datap);
-
- // sort the list using bubble-sort
- // Yes, this is a different name than the same function in LLLinkedList.
- // When it comes time for a name consolidation hopefully this one will win.
- BOOL bubbleSort();
-
- // does a single bubble sort pass on the list
- BOOL lazyBubbleSort();
-
- // returns TRUE if state successfully pushed (state stack not full)
- BOOL pushState();
-
- // returns TRUE if state successfully popped (state stack not empty)
- BOOL popState();
-
- // empties the state stack
- void clearStateStack();
-
- // randomly move the the links in the list for debug or (Discordian) purposes
- // sets mCurrentp and mQueuep to top of list
- void scramble();
-
-private:
- // add node to beginning of list
- // set mCurrentp to mQueuep
- void addNode(LLDoubleLinkedNode<DATA_TYPE> *node);
-
- // add node to end of list
- // set mCurrentp to mQueuep
- void addNodeAtEnd(LLDoubleLinkedNode<DATA_TYPE> *node);
-};
-
-//#endif
-
-////////////////////////////////////////////////////////////////////////////////////////////
-
-// doublelinkedlist.cpp
-// LLDoubleLinkedList template class implementation file.
-// Provides a standard doubly linked list for fun and profit.
-//
-// Copyright 2001, Linden Research, Inc.
-
-//#include "llerror.h"
-//#include "doublelinkedlist.h"
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// LLDoubleLinkedNode
-//////////////////////////////////////////////////////////////////////////////////////////
-
-
-// assign the mDatap pointer
-template <class DATA_TYPE>
-LLDoubleLinkedNode<DATA_TYPE>::LLDoubleLinkedNode(DATA_TYPE *data) :
- mDatap(data), mNextp(NULL), mPrevp(NULL)
-{
-}
-
-
-// destructor does not, by default, destroy associated data
-// however, the mDatap must be NULL to ensure that we aren't causing memory leaks
-template <class DATA_TYPE>
-LLDoubleLinkedNode<DATA_TYPE>::~LLDoubleLinkedNode()
-{
- if (mDatap)
- {
- llerror("Attempting to call LLDoubleLinkedNode destructor with a non-null mDatap!", 1);
- }
-}
-
-
-// delete associated data and NULL out pointer
-template <class DATA_TYPE>
-void LLDoubleLinkedNode<DATA_TYPE>::deleteData()
-{
- delete mDatap;
- mDatap = NULL;
-}
-
-
-template <class DATA_TYPE>
-void LLDoubleLinkedNode<DATA_TYPE>::removeData()
-{
- mDatap = NULL;
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////////
-// LLDoubleLinkedList
-//////////////////////////////////////////////////////////////////////////////////////
-
-// <------- up -------
-//
-// mCurrentp
-// mQueuep |
-// | |
-// | |
-// .------. .------. .------. .------.
-// | |---->| |---->| |----->| |-----> NULL
-// NULL <-----| |<----| |<----| |<-----| |
-// _'------' '------' '------' '------:_
-// .------. /| | | |\ .------.
-// NULL <-----|mHead |/ | mQueuep \|mTail |-----> NULL
-// | | mCurrentp | |
-// '------' '------'
-// -------- down --------->
-
-template <class DATA_TYPE>
-LLDoubleLinkedList<DATA_TYPE>::LLDoubleLinkedList()
-: mHead(NULL), mTail(NULL), mQueuep(NULL)
-{
- mCurrentp = mHead.mNextp;
- mQueuep = mHead.mNextp;
- mStateStackDepth = 0;
- mCount = 0;
- mInsertBefore = NULL;
-}
-
-
-// destructor destroys list and nodes, but not data in nodes
-template <class DATA_TYPE>
-LLDoubleLinkedList<DATA_TYPE>::~LLDoubleLinkedList()
-{
- removeAllNodes();
-}
-
-
-// put data into a node and stick it at the front of the list
-// doesn't change mCurrentp nor mQueuep
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::addData(DATA_TYPE *data)
-{
- // don't allow NULL to be passed to addData
- if (!data)
- {
- llerror("NULL pointer passed to LLDoubleLinkedList::addData()", 0);
- }
-
- // make the new node
- LLDoubleLinkedNode<DATA_TYPE> *temp = new LLDoubleLinkedNode<DATA_TYPE> (data);
-
- // add the node to the front of the list
- temp->mPrevp = NULL;
- temp->mNextp = mHead.mNextp;
- mHead.mNextp = temp;
-
- // if there's something in the list, fix its back pointer
- if (temp->mNextp)
- {
- temp->mNextp->mPrevp = temp;
- }
- // otherwise, fix the tail of the list
- else
- {
- mTail.mPrevp = temp;
- }
-
- mCount++;
-}
-
-
-// put data into a node and stick it at the end of the list
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::addDataAtEnd(DATA_TYPE *data)
-{
- // don't allow NULL to be passed to addData
- if (!data)
- {
- llerror("NULL pointer passed to LLDoubleLinkedList::addData()", 0);
- }
-
- // make the new node
- LLDoubleLinkedNode<DATA_TYPE> *nodep = new LLDoubleLinkedNode<DATA_TYPE>(data);
-
- addNodeAtEnd(nodep);
- mCount++;
-}
-
-
-// search the list starting at mHead.mNextp and remove the link with mDatap == data
-// set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::removeData(const DATA_TYPE *data)
-{
- BOOL b_found = FALSE;
- // don't allow NULL to be passed to addData
- if (!data)
- {
- llerror("NULL pointer passed to LLDoubleLinkedList::removeData()", 0);
- }
-
- mCurrentp = mHead.mNextp;
-
- while (mCurrentp)
- {
- if (mCurrentp->mDatap == data)
- {
- b_found = TRUE;
-
- // if there is a next one, fix it
- if (mCurrentp->mNextp)
- {
- mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
- }
- else // we are at end of list
- {
- mTail.mPrevp = mCurrentp->mPrevp;
- }
-
- // if there is a previous one, fix it
- if (mCurrentp->mPrevp)
- {
- mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
- }
- else // we are at beginning of list
- {
- mHead.mNextp = mCurrentp->mNextp;
- }
-
- // remove the node
- mCurrentp->removeData();
- delete mCurrentp;
- mCount--;
- break;
- }
- mCurrentp = mCurrentp->mNextp;
- }
-
- // reset the list back to where it was
- if (mCurrentp == mQueuep)
- {
- mCurrentp = mQueuep = NULL;
- }
- else
- {
- mCurrentp = mQueuep;
- }
-
- return b_found;
-}
-
-
-// search the list starting at mHead.mNextp and delete the link with mDatap == data
-// set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::deleteData(DATA_TYPE *data)
-{
- BOOL b_found = FALSE;
- // don't allow NULL to be passed to addData
- if (!data)
- {
- llerror("NULL pointer passed to LLDoubleLinkedList::deleteData()", 0);
- }
-
- mCurrentp = mHead.mNextp;
-
- while (mCurrentp)
- {
- if (mCurrentp->mDatap == data)
- {
- b_found = TRUE;
-
- // if there is a next one, fix it
- if (mCurrentp->mNextp)
- {
- mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
- }
- else // we are at end of list
- {
- mTail.mPrevp = mCurrentp->mPrevp;
- }
-
- // if there is a previous one, fix it
- if (mCurrentp->mPrevp)
- {
- mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
- }
- else // we are at beginning of list
- {
- mHead.mNextp = mCurrentp->mNextp;
- }
-
- // remove the node
- mCurrentp->deleteData();
- delete mCurrentp;
- mCount--;
- break;
- }
- mCurrentp = mCurrentp->mNextp;
- }
-
- // reset the list back to where it was
- if (mCurrentp == mQueuep)
- {
- mCurrentp = mQueuep = NULL;
- }
- else
- {
- mCurrentp = mQueuep;
- }
-
- return b_found;
-}
-
-
-// remove all nodes from the list and delete the associated data
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::deleteAllData()
-{
- mCurrentp = mHead.mNextp;
-
- while (mCurrentp)
- {
- mQueuep = mCurrentp->mNextp;
- mCurrentp->deleteData();
- delete mCurrentp;
- mCurrentp = mQueuep;
- }
-
- // reset mHead and mQueuep
- mHead.mNextp = NULL;
- mTail.mPrevp = NULL;
- mCurrentp = mHead.mNextp;
- mQueuep = mHead.mNextp;
- mStateStackDepth = 0;
- mCount = 0;
-}
-
-
-// remove all nodes from the list but do not delete associated data
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::removeAllNodes()
-{
- mCurrentp = mHead.mNextp;
-
- while (mCurrentp)
- {
- mQueuep = mCurrentp->mNextp;
- mCurrentp->removeData();
- delete mCurrentp;
- mCurrentp = mQueuep;
- }
-
- // reset mHead and mCurrentp
- mHead.mNextp = NULL;
- mTail.mPrevp = NULL;
- mCurrentp = mHead.mNextp;
- mQueuep = mHead.mNextp;
- mStateStackDepth = 0;
- mCount = 0;
-}
-
-template <class DATA_TYPE>
-S32 LLDoubleLinkedList<DATA_TYPE>::getLength() const
-{
-// U32 length = 0;
-// for (LLDoubleLinkedNode<DATA_TYPE>* temp = mHead.mNextp; temp != NULL; temp = temp->mNextp)
-// {
-// length++;
-// }
- return mCount;
-}
-
-// check to see if data is in list
-// set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::checkData(const DATA_TYPE *data)
-{
- mCurrentp = mHead.mNextp;
-
- while (mCurrentp)
- {
- if (mCurrentp->mDatap == data)
- {
- mQueuep = mCurrentp;
- return TRUE;
- }
- mCurrentp = mCurrentp->mNextp;
- }
-
- mCurrentp = mQueuep;
- return FALSE;
-}
-
-// NOTE: This next two funtions are only included here
-// for those too familiar with the LLLinkedList template class.
-// They are depreciated. resetList() is unecessary while
-// getCurrentData() is identical to getNextData() and has
-// a misleading name.
-//
-// The recommended way to loop through a list is as follows:
-//
-// datap = list.getFirstData();
-// while (datap)
-// {
-// /* do stuff */
-// datap = list.getNextData();
-// }
-
- // place mCurrentp and mQueuep on first node
- template <class DATA_TYPE>
- void LLDoubleLinkedList<DATA_TYPE>::resetList()
- {
- mCurrentp = mHead.mNextp;
- mQueuep = mHead.mNextp;
- mStateStackDepth = 0;
- }
-
-
- // return the data currently pointed to,
- // set mCurrentp to that node and bump mQueuep down the list
- template <class DATA_TYPE>
- DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getCurrentData()
- {
- if (mQueuep)
- {
- mCurrentp = mQueuep;
- mQueuep = mQueuep->mNextp;
- return mCurrentp->mDatap;
- }
- else
- {
- return NULL;
- }
- }
-
-
-// reset the list and return the data currently pointed to,
-// set mCurrentp to that node and bump mQueuep down the list
-template <class DATA_TYPE>
-DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getFirstData()
-{
- mQueuep = mHead.mNextp;
- mCurrentp = mQueuep;
- if (mQueuep)
- {
- mQueuep = mQueuep->mNextp;
- return mCurrentp->mDatap;
- }
- else
- {
- return NULL;
- }
-}
-
-
-// reset the list and return the data at position n, set mCurentp
-// to that node and bump mQueuep down the list
-// Note: n=0 will behave like getFirstData()
-template <class DATA_TYPE>
-DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getNthData(U32 n)
-{
- mCurrentp = mHead.mNextp;
-
- if (mCurrentp)
- {
- for (U32 i=0; i<n; i++)
- {
- mCurrentp = mCurrentp->mNextp;
- if (!mCurrentp)
- {
- break;
- }
- }
- }
-
- if (mCurrentp)
- {
- // bump mQueuep down the list
- mQueuep = mCurrentp->mNextp;
- return mCurrentp->mDatap;
- }
- else
- {
- mQueuep = NULL;
- return NULL;
- }
-}
-
-
-// reset the list and return the last data in it,
-// set mCurrentp to that node and bump mQueuep up the list
-template <class DATA_TYPE>
-DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getLastData()
-{
- mQueuep = mTail.mPrevp;
- mCurrentp = mQueuep;
- if (mQueuep)
- {
- mQueuep = mQueuep->mPrevp;
- return mCurrentp->mDatap;
- }
- else
- {
- return NULL;
- }
-}
-
-
-// return the data in mQueuep,
-// set mCurrentp to mQueuep and bump mQueuep down the list
-template <class DATA_TYPE>
-DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getNextData()
-{
- if (mQueuep)
- {
- mCurrentp = mQueuep;
- mQueuep = mQueuep->mNextp;
- return mCurrentp->mDatap;
- }
- else
- {
- return NULL;
- }
-}
-
-
-// return the data in mQueuep,
-// set mCurrentp to mQueuep and bump mQueuep up the list
-template <class DATA_TYPE>
-DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getPreviousData()
-{
- if (mQueuep)
- {
- mCurrentp = mQueuep;
- mQueuep = mQueuep->mPrevp;
- return mCurrentp->mDatap;
- }
- else
- {
- return NULL;
- }
-}
-
-
-// remove the Node at mCurrentp
-// set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep)
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::removeCurrentData()
-{
- if (mCurrentp)
- {
- // if there is a next one, fix it
- if (mCurrentp->mNextp)
- {
- mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
- }
- else // otherwise we are at end of list
- {
- mTail.mPrevp = mCurrentp->mPrevp;
- }
-
- // if there is a previous one, fix it
- if (mCurrentp->mPrevp)
- {
- mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
- }
- else // otherwise we are at beginning of list
- {
- mHead.mNextp = mCurrentp->mNextp;
- }
-
- // remove the node
- mCurrentp->removeData();
- delete mCurrentp;
- mCount--;
-
- // check for redundant pointing
- if (mCurrentp == mQueuep)
- {
- mCurrentp = mQueuep = NULL;
- }
- else
- {
- mCurrentp = mQueuep;
- }
- }
-}
-
-
-// delete the Node at mCurrentp
-// set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep)
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::deleteCurrentData()
-{
- if (mCurrentp)
- {
- // remove the node
- // if there is a next one, fix it
- if (mCurrentp->mNextp)
- {
- mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
- }
- else // otherwise we are at end of list
- {
- mTail.mPrevp = mCurrentp->mPrevp;
- }
-
- // if there is a previous one, fix it
- if (mCurrentp->mPrevp)
- {
- mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
- }
- else // otherwise we are at beginning of list
- {
- mHead.mNextp = mCurrentp->mNextp;
- }
-
- // remove the LLDoubleLinkedNode
- mCurrentp->deleteData();
- delete mCurrentp;
- mCount--;
-
- // check for redundant pointing
- if (mCurrentp == mQueuep)
- {
- mCurrentp = mQueuep = NULL;
- }
- else
- {
- mCurrentp = mQueuep;
- }
- }
-}
-
-
-// remove the Node at mCurrentp and insert it into newlist
-// set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep)
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::moveCurrentData(LLDoubleLinkedList<DATA_TYPE> *newlist)
-{
- if (mCurrentp)
- {
- // remove the node
- // if there is a next one, fix it
- if (mCurrentp->mNextp)
- {
- mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
- }
- else // otherwise we are at end of list
- {
- mTail.mPrevp = mCurrentp->mPrevp;
- }
-
- // if there is a previous one, fix it
- if (mCurrentp->mPrevp)
- {
- mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
- }
- else // otherwise we are at beginning of list
- {
- mHead.mNextp = mCurrentp->mNextp;
- }
-
- // move the node to the new list
- newlist->addNode(mCurrentp);
-
- // check for redundant pointing
- if (mCurrentp == mQueuep)
- {
- mCurrentp = mQueuep = NULL;
- }
- else
- {
- mCurrentp = mQueuep;
- }
- }
-}
-
-
-// Inserts the node previous to mCurrentp
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::insertNode(LLDoubleLinkedNode<DATA_TYPE> *nodep)
-{
- // don't allow pointer to NULL to be passed
- if (!nodep)
- {
- llerror("NULL pointer passed to LLDoubleLinkedList::insertNode()", 0);
- }
- if (!nodep->mDatap)
- {
- llerror("NULL data pointer passed to LLDoubleLinkedList::insertNode()", 0);
- }
-
- if (mCurrentp)
- {
- if (mCurrentp->mPrevp)
- {
- nodep->mPrevp = mCurrentp->mPrevp;
- nodep->mNextp = mCurrentp;
- mCurrentp->mPrevp->mNextp = nodep;
- mCurrentp->mPrevp = nodep;
- }
- else // at beginning of list
- {
- nodep->mPrevp = NULL;
- nodep->mNextp = mCurrentp;
- mHead.mNextp = nodep;
- mCurrentp->mPrevp = nodep;
- }
- mCurrentp = mQueuep;
- }
- else // add to front of list
- {
- addNode(nodep);
- }
-}
-
-
-// insert the data in front of mCurrentp
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::insertData(DATA_TYPE *data)
-{
- if (!data)
- {
- llerror("NULL data pointer passed to LLDoubleLinkedList::insertNode()", 0);
- }
- LLDoubleLinkedNode<DATA_TYPE> *node = new LLDoubleLinkedNode<DATA_TYPE>(data);
- insertNode(node);
- mCount++;
-}
-
-
-// if mCurrentp has a previous node then :
-// * swaps mCurrentp with its previous
-// * set mCurrentp to mQueuep
-// otherwise does nothing
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::swapCurrentWithPrevious()
-{
- if (mCurrentp)
- {
- if (mCurrentp->mPrevp)
- {
- // Pull mCurrentp out of list
- mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
- if (mCurrentp->mNextp)
- {
- mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
- }
- else // mCurrentp was at end of list
- {
- mTail.mPrevp = mCurrentp->mPrevp;
- }
-
- // Fix mCurrentp's pointers
- mCurrentp->mNextp = mCurrentp->mPrevp;
- mCurrentp->mPrevp = mCurrentp->mNextp->mPrevp;
- mCurrentp->mNextp->mPrevp = mCurrentp;
-
- if (mCurrentp->mPrevp)
- {
- // Fix the backward pointer of mCurrentp's new previous
- mCurrentp->mPrevp->mNextp = mCurrentp;
- }
- else // mCurrentp is now at beginning of list
- {
- mHead.mNextp = mCurrentp;
- }
-
- // Set the list back to the way it was
- mCurrentp = mQueuep;
- }
- }
-}
-
-
-// if mCurrentp has a next node then :
-// * swaps mCurrentp with its next
-// * set mCurrentp to mQueuep
-// otherwise does nothing
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::swapCurrentWithNext()
-{
- if (mCurrentp)
- {
- if (mCurrentp->mNextp)
- {
- // Pull mCurrentp out of list
- mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
- if (mCurrentp->mPrevp)
- {
- mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
- }
- else // mCurrentp was at beginning of list
- {
- mHead.mNextp = mCurrentp->mNextp;
- }
-
- // Fix mCurrentp's pointers
- mCurrentp->mPrevp = mCurrentp->mNextp;
- mCurrentp->mNextp = mCurrentp->mPrevp->mNextp;
- mCurrentp->mPrevp->mNextp = mCurrentp;
-
- if (mCurrentp->mNextp)
- {
- // Fix the back pointer of mCurrentp's new next
- mCurrentp->mNextp->mPrevp = mCurrentp;
- }
- else // mCurrentp is now at end of list
- {
- mTail.mPrevp = mCurrentp;
- }
-
- // Set the list back to the way it was
- mCurrentp = mQueuep;
- }
- }
-}
-
-// move mCurrentp to the front of the list
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::moveCurrentToFront()
-{
- if (mCurrentp)
- {
- // if there is a previous one, fix it
- if (mCurrentp->mPrevp)
- {
- mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
- }
- else // otherwise we are at beginning of list
- {
- // check for redundant pointing
- if (mCurrentp == mQueuep)
- {
- mCurrentp = mQueuep = NULL;
- }
- else
- {
- mCurrentp = mQueuep;
- }
- return;
- }
-
- // if there is a next one, fix it
- if (mCurrentp->mNextp)
- {
- mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
- }
- else // otherwise we are at end of list
- {
- mTail.mPrevp = mCurrentp->mPrevp;
- }
-
- // add mCurrentp to beginning of list
- mCurrentp->mNextp = mHead.mNextp;
- mHead.mNextp->mPrevp = mCurrentp; // mHead.mNextp MUST be valid,
- // or the list had only one node
- // and we would have returned already
- mCurrentp->mPrevp = NULL;
- mHead.mNextp = mCurrentp;
-
- // check for redundant pointing
- if (mCurrentp == mQueuep)
- {
- mCurrentp = mQueuep = NULL;
- }
- else
- {
- mCurrentp = mQueuep;
- }
- }
-
-}
-
-// move mCurrentp to the end of the list
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::moveCurrentToEnd()
-{
- if (mCurrentp)
- {
- // if there is a next one, fix it
- if (mCurrentp->mNextp)
- {
- mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp;
- }
- else // otherwise we are at end of list and we're done
- {
- // check for redundant pointing
- if (mCurrentp == mQueuep)
- {
- mCurrentp = mQueuep = NULL;
- }
- else
- {
- mCurrentp = mQueuep;
- }
- return;
- }
-
- // if there is a previous one, fix it
- if (mCurrentp->mPrevp)
- {
- mCurrentp->mPrevp->mNextp = mCurrentp->mNextp;
- }
- else // otherwise we are at beginning of list
- {
- mHead.mNextp = mCurrentp->mNextp;
- }
-
- // add mCurrentp to end of list
- mCurrentp->mPrevp = mTail.mPrevp;
- mTail.mPrevp->mNextp = mCurrentp; // mTail.mPrevp MUST be valid,
- // or the list had only one node
- // and we would have returned already
- mCurrentp->mNextp = NULL;
- mTail.mPrevp = mCurrentp;
-
- // check for redundant pointing
- if (mCurrentp == mQueuep)
- {
- mCurrentp = mQueuep = NULL;
- }
- else
- {
- mCurrentp = mQueuep;
- }
- }
-}
-
-
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::setInsertBefore(BOOL (*insert_before)(DATA_TYPE *first, DATA_TYPE *second) )
-{
- mInsertBefore = insert_before;
-}
-
-
-// add data in front of the first node for which mInsertBefore(datap, node->mDatap) returns TRUE
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::addDataSorted(DATA_TYPE *datap)
-{
- // don't allow NULL to be passed to addData()
- if (!datap)
- {
- llerror("NULL pointer passed to LLDoubleLinkedList::addDataSorted()", 0);
- }
-
- // has mInsertBefore not been set?
- if (!mInsertBefore)
- {
- addData(datap);
- return FALSE;
- }
-
- // is the list empty?
- if (!mHead.mNextp)
- {
- addData(datap);
- return TRUE;
- }
-
- // Note: this step has been added so that the behavior of LLDoubleLinkedList
- // is as rigorous as the LLLinkedList class about adding duplicate nodes.
- // Duplicate nodes can cause a problem when sorting if mInsertBefore(foo, foo)
- // returns TRUE. However, if mInsertBefore(foo, foo) returns FALSE, then there
- // shouldn't be any reason to exclude duplicate nodes (as we do here).
- if (checkData(datap))
- {
- return FALSE;
- }
-
- mCurrentp = mHead.mNextp;
- while (mCurrentp)
- {
- // check to see if datap is already in the list
- if (datap == mCurrentp->mDatap)
- {
- return FALSE;
- }
- else if (mInsertBefore(datap, mCurrentp->mDatap))
- {
- insertData(datap);
- return TRUE;
- }
- mCurrentp = mCurrentp->mNextp;
- }
-
- addDataAtEnd(datap);
- return TRUE;
-}
-
-
-// bubble-sort until sorted and return TRUE if anything was sorted
-// leaves mQueuep pointing at last node that was swapped with its mNextp
-//
-// NOTE: if you find this function looping for really long times, then you
-// probably need to check your implementation of mInsertBefore(a,b) and make
-// sure it does not return TRUE when (a == b)!
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::bubbleSort()
-{
- BOOL b_swapped = FALSE;
- U32 count = 0;
- while (lazyBubbleSort())
- {
- b_swapped = TRUE;
- if (count++ > 0x7FFFFFFF)
- {
- llwarning("LLDoubleLinkedList::bubbleSort() : too many passes...", 1);
- llwarning(" make sure the mInsertBefore(a, b) does not return TRUE for a == b", 1);
- break;
- }
- }
- return b_swapped;
-}
-
-
-// do a single bubble-sort pass and return TRUE if anything was sorted
-// leaves mQueuep pointing at last node that was swapped with its mNextp
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::lazyBubbleSort()
-{
- // has mInsertBefore been set?
- if (!mInsertBefore)
- {
- return FALSE;
- }
-
- // is list empty?
- mCurrentp = mHead.mNextp;
- if (!mCurrentp)
- {
- return FALSE;
- }
-
- BOOL b_swapped = FALSE;
-
- // the sort will exit after 0x7FFFFFFF nodes or the end of the list, whichever is first
- S32 length = 0x7FFFFFFF;
- S32 count = 0;
-
- while (mCurrentp && mCurrentp->mNextp && count<length)
- {
- if (mInsertBefore(mCurrentp->mNextp->mDatap, mCurrentp->mDatap))
- {
- b_swapped = TRUE;
- mQueuep = mCurrentp;
- swapCurrentWithNext(); // sets mCurrentp to mQueuep
- }
- count++;
- mCurrentp = mCurrentp->mNextp;
- }
-
- return b_swapped;
-}
-
-
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::pushState()
-{
- if (mStateStackDepth < LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH)
- {
- *(mQueuepStack + mStateStackDepth) = mQueuep;
- *(mCurrentpStack + mStateStackDepth) = mCurrentp;
- mStateStackDepth++;
- return TRUE;
- }
- return FALSE;
-}
-
-
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::popState()
-{
- if (mStateStackDepth > 0)
- {
- mStateStackDepth--;
- mQueuep = *(mQueuepStack + mStateStackDepth);
- mCurrentp = *(mCurrentpStack + mStateStackDepth);
- return TRUE;
- }
- return FALSE;
-}
-
-
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::clearStateStack()
-{
- mStateStackDepth = 0;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// private members
-//////////////////////////////////////////////////////////////////////////////////////////
-
-// add node to beginning of list
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::addNode(LLDoubleLinkedNode<DATA_TYPE> *nodep)
-{
- // add the node to the front of the list
- nodep->mPrevp = NULL;
- nodep->mNextp = mHead.mNextp;
- mHead.mNextp = nodep;
-
- // if there's something in the list, fix its back pointer
- if (nodep->mNextp)
- {
- nodep->mNextp->mPrevp = nodep;
- }
- else // otherwise fix the tail node
- {
- mTail.mPrevp = nodep;
- }
-
- mCurrentp = mQueuep;
-}
-
-
-// add node to end of list
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::addNodeAtEnd(LLDoubleLinkedNode<DATA_TYPE> *node)
-{
- // add the node to the end of the list
- node->mNextp = NULL;
- node->mPrevp = mTail.mPrevp;
- mTail.mPrevp = node;
-
- // if there's something in the list, fix its back pointer
- if (node->mPrevp)
- {
- node->mPrevp->mNextp = node;
- }
- else // otherwise fix the head node
- {
- mHead.mNextp = node;
- }
-
- mCurrentp = mQueuep;
-}
-
-
-// randomly move nodes in the list for DEBUG (or Discordian) purposes
-// sets mCurrentp and mQueuep to top of list
-template <class DATA_TYPE>
-void LLDoubleLinkedList<DATA_TYPE>::scramble()
-{
- S32 random_number;
- DATA_TYPE *datap = getFirstData();
- while(datap)
- {
- random_number = ll_rand(5);
-
- if (0 == random_number)
- {
- removeCurrentData();
- addData(datap);
- }
- else if (1 == random_number)
- {
- removeCurrentData();
- addDataAtEnd(datap);
- }
- else if (2 == random_number)
- {
- swapCurrentWithPrevious();
- }
- else if (3 == random_number)
- {
- swapCurrentWithNext();
- }
- datap = getNextData();
- }
- mQueuep = mHead.mNextp;
- mCurrentp = mQueuep;
-}
-
-template <class DATA_TYPE>
-BOOL LLDoubleLinkedList<DATA_TYPE>::isEmpty()
-{
- return (mCount == 0);
-}
-
-
-#endif
diff --git a/indra/llcommon/imageids.cpp b/indra/llcommon/imageids.cpp
deleted file mode 100755
index 7d647e5c36..0000000000
--- a/indra/llcommon/imageids.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * @file imageids.cpp
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "imageids.h"
-
-#include "lluuid.h"
-
-//
-// USE OF THIS FILE IS DEPRECATED
-//
-// Please use viewerart.ini and the standard
-// art import path. // indicates if file is only
- // on dataserver, or also
- // pre-cached on viewer
-
-// Grass Images
-const LLUUID IMG_SMOKE ("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); // VIEWER
-
-const LLUUID IMG_DEFAULT ("d2114404-dd59-4a4d-8e6c-49359e91bbf0"); // VIEWER
-
-const LLUUID IMG_SUN ("cce0f112-878f-4586-a2e2-a8f104bba271"); // dataserver
-const LLUUID IMG_MOON ("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver
-const LLUUID IMG_CLOUD_POOF ("fc4b9f0b-d008-45c6-96a4-01dd947ac621"); // dataserver
-const LLUUID IMG_SHOT ("35f217a3-f618-49cf-bbca-c86d486551a9"); // dataserver
-const LLUUID IMG_SPARK ("d2e75ac1-d0fb-4532-820e-a20034ac814d"); // dataserver
-const LLUUID IMG_FIRE ("aca40aa8-44cf-44ca-a0fa-93e1a2986f82"); // dataserver
-const LLUUID IMG_FACE_SELECT ("a85ac674-cb75-4af6-9499-df7c5aaf7a28"); // face selector
-const LLUUID IMG_DEFAULT_AVATAR ("c228d1cf-4b5d-4ba8-84f4-899a0796aa97"); // dataserver
-const LLUUID IMG_INVISIBLE ("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"); // dataserver
-
-const LLUUID IMG_EXPLOSION ("68edcf47-ccd7-45b8-9f90-1649d7f12806"); // On dataserver
-const LLUUID IMG_EXPLOSION_2 ("21ce046c-83fe-430a-b629-c7660ac78d7c"); // On dataserver
-const LLUUID IMG_EXPLOSION_3 ("fedea30a-1be8-47a6-bc06-337a04a39c4b"); // On dataserver
-const LLUUID IMG_EXPLOSION_4 ("abf0d56b-82e5-47a2-a8ad-74741bb2c29e"); // On dataserver
-const LLUUID IMG_SMOKE_POOF ("1e63e323-5fe0-452e-92f8-b98bd0f764e3"); // On dataserver
-
-const LLUUID IMG_BIG_EXPLOSION_1 ("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); // On dataserver
-const LLUUID IMG_BIG_EXPLOSION_2 ("9c8eca51-53d5-42a7-bb58-cef070395db8"); // On dataserver
-
-const LLUUID IMG_BLOOM1 ("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"); // VIEWER
-const LLUUID TERRAIN_DIRT_DETAIL ("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER
-const LLUUID TERRAIN_GRASS_DETAIL ("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER
-const LLUUID TERRAIN_MOUNTAIN_DETAIL ("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER
-const LLUUID TERRAIN_ROCK_DETAIL ("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER
-
-const LLUUID DEFAULT_WATER_NORMAL ("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER
-
-const LLUUID IMG_CHECKERBOARD_RGBA ("2585a0f3-4163-6dd1-0f34-ad48cb909e25"); // dataserver
-
diff --git a/indra/llcommon/imageids.h b/indra/llcommon/imageids.h
deleted file mode 100755
index 18c8ecb074..0000000000
--- a/indra/llcommon/imageids.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * @file imageids.h
- * @brief Temporary holder for image IDs
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_IMAGEIDS_H
-#define LL_IMAGEIDS_H
-
-//
-// USE OF THIS FILE IS DEPRECATED
-//
-// Please use viewerart.ini and the standard
-// art import path.
-
-class LLUUID;
-
-LL_COMMON_API extern const LLUUID IMG_SMOKE;
-
-LL_COMMON_API extern const LLUUID IMG_DEFAULT;
-
-LL_COMMON_API extern const LLUUID IMG_SUN;
-LL_COMMON_API extern const LLUUID IMG_MOON;
-LL_COMMON_API extern const LLUUID IMG_CLOUD_POOF;
-LL_COMMON_API extern const LLUUID IMG_SHOT;
-LL_COMMON_API extern const LLUUID IMG_SPARK;
-LL_COMMON_API extern const LLUUID IMG_FIRE;
-LL_COMMON_API extern const LLUUID IMG_FACE_SELECT;
-LL_COMMON_API extern const LLUUID IMG_DEFAULT_AVATAR;
-LL_COMMON_API extern const LLUUID IMG_INVISIBLE;
-
-LL_COMMON_API extern const LLUUID IMG_EXPLOSION;
-LL_COMMON_API extern const LLUUID IMG_EXPLOSION_2;
-LL_COMMON_API extern const LLUUID IMG_EXPLOSION_3;
-LL_COMMON_API extern const LLUUID IMG_EXPLOSION_4;
-LL_COMMON_API extern const LLUUID IMG_SMOKE_POOF;
-
-LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_1;
-LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_2;
-
-LL_COMMON_API extern const LLUUID IMG_BLOOM1;
-LL_COMMON_API extern const LLUUID TERRAIN_DIRT_DETAIL;
-LL_COMMON_API extern const LLUUID TERRAIN_GRASS_DETAIL;
-LL_COMMON_API extern const LLUUID TERRAIN_MOUNTAIN_DETAIL;
-LL_COMMON_API extern const LLUUID TERRAIN_ROCK_DETAIL;
-
-LL_COMMON_API extern const LLUUID DEFAULT_WATER_NORMAL;
-
-LL_COMMON_API extern const LLUUID IMG_CHECKERBOARD_RGBA;
-#endif
diff --git a/indra/llcommon/indra_constants.cpp b/indra/llcommon/indra_constants.cpp
index d32ae6c041..f3989ee1d0 100755
--- a/indra/llcommon/indra_constants.cpp
+++ b/indra/llcommon/indra_constants.cpp
@@ -35,6 +35,35 @@ const LLUUID LL_UUID_ALL_AGENTS("44e87126-e794-4ded-05b3-7c42da3d5cdb");
// Governor Linden's agent id.
const LLUUID ALEXANDRIA_LINDEN_ID("ba2a564a-f0f1-4b82-9c61-b7520bfcd09f");
const LLUUID GOVERNOR_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1");
-const LLUUID REALESTATE_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1");
// Maintenance's group id.
const LLUUID MAINTENANCE_GROUP_ID("dc7b21cd-3c89-fcaa-31c8-25f9ffd224cd");
+// Grass Images
+const LLUUID IMG_SMOKE ("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); // VIEWER
+
+const LLUUID IMG_DEFAULT ("d2114404-dd59-4a4d-8e6c-49359e91bbf0"); // VIEWER
+
+const LLUUID IMG_SUN ("cce0f112-878f-4586-a2e2-a8f104bba271"); // dataserver
+const LLUUID IMG_MOON ("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver
+const LLUUID IMG_SHOT ("35f217a3-f618-49cf-bbca-c86d486551a9"); // dataserver
+const LLUUID IMG_SPARK ("d2e75ac1-d0fb-4532-820e-a20034ac814d"); // dataserver
+const LLUUID IMG_FIRE ("aca40aa8-44cf-44ca-a0fa-93e1a2986f82"); // dataserver
+const LLUUID IMG_FACE_SELECT ("a85ac674-cb75-4af6-9499-df7c5aaf7a28"); // face selector
+const LLUUID IMG_DEFAULT_AVATAR ("c228d1cf-4b5d-4ba8-84f4-899a0796aa97"); // dataserver
+const LLUUID IMG_INVISIBLE ("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"); // dataserver
+
+const LLUUID IMG_EXPLOSION ("68edcf47-ccd7-45b8-9f90-1649d7f12806"); // On dataserver
+const LLUUID IMG_EXPLOSION_2 ("21ce046c-83fe-430a-b629-c7660ac78d7c"); // On dataserver
+const LLUUID IMG_EXPLOSION_3 ("fedea30a-1be8-47a6-bc06-337a04a39c4b"); // On dataserver
+const LLUUID IMG_EXPLOSION_4 ("abf0d56b-82e5-47a2-a8ad-74741bb2c29e"); // On dataserver
+const LLUUID IMG_SMOKE_POOF ("1e63e323-5fe0-452e-92f8-b98bd0f764e3"); // On dataserver
+
+const LLUUID IMG_BIG_EXPLOSION_1 ("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); // On dataserver
+const LLUUID IMG_BIG_EXPLOSION_2 ("9c8eca51-53d5-42a7-bb58-cef070395db8"); // On dataserver
+
+const LLUUID IMG_BLOOM1 ("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"); // VIEWER
+const LLUUID TERRAIN_DIRT_DETAIL ("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER
+const LLUUID TERRAIN_GRASS_DETAIL ("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER
+const LLUUID TERRAIN_MOUNTAIN_DETAIL ("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER
+const LLUUID TERRAIN_ROCK_DETAIL ("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER
+
+const LLUUID DEFAULT_WATER_NORMAL ("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index 0da83720bd..02f063f5e8 100755
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -31,122 +31,28 @@
class LLUUID;
-// At 45 Hz collisions seem stable and objects seem
-// to settle down at a reasonable rate.
-// JC 3/18/2003
-
-// const F32 PHYSICS_TIMESTEP = 1.f / 45.f;
-// This must be a #define due to anal retentive restrictions on const expressions
-// CG 2008-06-05
-#define PHYSICS_TIMESTEP (1.f / 45.f)
-
-const F32 COLLISION_TOLERANCE = 0.1f;
-const F32 HALF_COLLISION_TOLERANCE = 0.05f;
-
-// Time constants
-const U32 HOURS_PER_LINDEN_DAY = 4;
-const U32 DAYS_PER_LINDEN_YEAR = 11;
-
-const U32 SEC_PER_LINDEN_DAY = HOURS_PER_LINDEN_DAY * 60 * 60;
-const U32 SEC_PER_LINDEN_YEAR = DAYS_PER_LINDEN_YEAR * SEC_PER_LINDEN_DAY;
-
static const F32 REGION_WIDTH_METERS = 256.f;
static const S32 REGION_WIDTH_UNITS = 256;
static const U32 REGION_WIDTH_U32 = 256;
const F32 REGION_HEIGHT_METERS = 4096.f;
-// Bits for simulator performance query flags
-enum LAND_STAT_FLAGS
-{
- STAT_FILTER_BY_PARCEL = 0x00000001,
- STAT_FILTER_BY_OWNER = 0x00000002,
- STAT_FILTER_BY_OBJECT = 0x00000004,
- STAT_FILTER_BY_PARCEL_NAME = 0x00000008,
- STAT_REQUEST_LAST_ENTRY = 0x80000000,
-};
-
-enum LAND_STAT_REPORT_TYPE
-{
- STAT_REPORT_TOP_SCRIPTS = 0,
- STAT_REPORT_TOP_COLLIDERS
-};
-
-const U32 STAT_FILTER_MASK = 0x1FFFFFFF;
-
-// Region absolute limits
-static const S32 REGION_AGENT_COUNT_MIN = 1;
-static const S32 REGION_AGENT_COUNT_MAX = 200; // Must fit in U8 for the moment (RegionInfo msg)
-static const S32 REGION_PRIM_COUNT_MIN = 0;
-static const S32 REGION_PRIM_COUNT_MAX = 40000;
-static const F32 REGION_PRIM_BONUS_MIN = 1.0;
-static const F32 REGION_PRIM_BONUS_MAX = 10.0;
-
-// Default maximum number of tasks/prims per region.
-const U32 DEFAULT_MAX_REGION_WIDE_PRIM_COUNT = 15000;
-
-const F32 MIN_AGENT_DEPTH = 0.30f;
const F32 DEFAULT_AGENT_DEPTH = 0.45f;
-const F32 MAX_AGENT_DEPTH = 0.60f;
-
-const F32 MIN_AGENT_WIDTH = 0.40f;
const F32 DEFAULT_AGENT_WIDTH = 0.60f;
-const F32 MAX_AGENT_WIDTH = 0.80f;
-
-const F32 MIN_AGENT_HEIGHT = 1.1f;
const F32 DEFAULT_AGENT_HEIGHT = 1.9f;
-const F32 MAX_AGENT_HEIGHT = 2.45f;
-
-// For linked sets
-const S32 MAX_CHILDREN_PER_TASK = 255;
-const S32 MAX_CHILDREN_PER_PHYSICAL_TASK = 32;
-
-const S32 MAX_JOINTS_PER_OBJECT = 1; // limiting to 1 until Havok 2.x
-
-const char* const DEFAULT_DMZ_SPACE_SERVER = "192.168.0.140";
-const char* const DEFAULT_DMZ_USER_SERVER = "192.168.0.140";
-const char* const DEFAULT_DMZ_DATA_SERVER = "192.168.0.140";
-const char* const DEFAULT_DMZ_ASSET_SERVER = "http://asset.dmz.lindenlab.com:80";
-
-const char* const DEFAULT_AGNI_SPACE_SERVER = "63.211.139.100";
-const char* const DEFAULT_AGNI_USER_SERVER = "63.211.139.100";
-const char* const DEFAULT_AGNI_DATA_SERVER = "63.211.139.100";
-const char* const DEFAULT_AGNI_ASSET_SERVER = "http://asset.agni.lindenlab.com:80";
-
-// Information about what ports are for what services is in the wiki Name Space Ports page
-// https://wiki.lindenlab.com/wiki/Name_Space_Ports
-const char* const DEFAULT_LOCAL_ASSET_SERVER = "http://localhost:12041/asset/tmp";
-const char* const LOCAL_ASSET_URL_FORMAT = "http://%s:12041/asset";
-
-const U32 DEFAULT_LAUNCHER_PORT = 12029;
-//const U32 DEFAULT_BIGBOARD_PORT = 12030; // Deprecated
-//const U32 DEFAULT_QUERYSIM_PORT = 12031; // Deprecated
-const U32 DEFAULT_DATA_SERVER_PORT = 12032;
-const U32 DEFAULT_SPACE_SERVER_PORT = 12033;
-const U32 DEFAULT_VIEWER_PORT = 12034;
-const U32 DEFAULT_SIMULATOR_PORT = 12035;
-const U32 DEFAULT_USER_SERVER_PORT = 12036;
-const U32 DEFAULT_RPC_SERVER_PORT = 12037;
-const U32 DEFAULT_LOG_DATA_SERVER_PORT = 12039;
-const U32 DEFAULT_BACKBONE_PORT = 12040;
-const U32 DEFAULT_LOCAL_ASSET_PORT = 12041;
-//const U32 DEFAULT_BACKBONE_CAP_PORT = 12042; // Deprecated
-const U32 DEFAULT_CAP_PROXY_PORT = 12043;
-const U32 DEFAULT_INV_DATA_SERVER_PORT = 12044;
-const U32 DEFAULT_CGI_SERVICES_PORT = 12045;
-
-// Mapserver uses ports 12124 - 12139 to allow multiple mapservers to run
-// on a single host for map tile generation. JC
-const U32 DEFAULT_MAPSERVER_PORT = 12124;
-
-// For automatic port discovery when running multiple viewers on one host
-const U32 PORT_DISCOVERY_RANGE_MIN = 13000;
-const U32 PORT_DISCOVERY_RANGE_MAX = PORT_DISCOVERY_RANGE_MIN + 50;
-
-const char LAND_LAYER_CODE = 'L';
-const char WATER_LAYER_CODE = 'W';
-const char WIND_LAYER_CODE = '7';
-const char CLOUD_LAYER_CODE = '8';
+
+enum ETerrainBrushType
+{
+ // the valid brush numbers cannot be reordered, because they
+ // are used in the binary LSL format as arguments to llModifyLand()
+ E_LANDBRUSH_LEVEL = 0,
+ E_LANDBRUSH_RAISE = 1,
+ E_LANDBRUSH_LOWER = 2,
+ E_LANDBRUSH_SMOOTH = 3,
+ E_LANDBRUSH_NOISE = 4,
+ E_LANDBRUSH_REVERT = 5,
+ E_LANDBRUSH_INVALID = 6
+};
// keys
// Bit masks for various keyboard modifier keys.
@@ -265,89 +171,43 @@ LL_COMMON_API extern const LLUUID LL_UUID_ALL_AGENTS;
LL_COMMON_API extern const LLUUID ALEXANDRIA_LINDEN_ID;
LL_COMMON_API extern const LLUUID GOVERNOR_LINDEN_ID;
-LL_COMMON_API extern const LLUUID REALESTATE_LINDEN_ID;
// Maintenance's group id.
LL_COMMON_API extern const LLUUID MAINTENANCE_GROUP_ID;
-// Flags for kick message
-const U32 KICK_FLAGS_DEFAULT = 0x0;
-const U32 KICK_FLAGS_FREEZE = 1 << 0;
-const U32 KICK_FLAGS_UNFREEZE = 1 << 1;
-
-const U8 UPD_NONE = 0x00;
-const U8 UPD_POSITION = 0x01;
-const U8 UPD_ROTATION = 0x02;
-const U8 UPD_SCALE = 0x04;
-const U8 UPD_LINKED_SETS = 0x08;
-const U8 UPD_UNIFORM = 0x10; // used with UPD_SCALE
-
-// Agent Update Flags (U8)
-const U8 AU_FLAGS_NONE = 0x00;
-const U8 AU_FLAGS_HIDETITLE = 0x01;
-const U8 AU_FLAGS_CLIENT_AUTOPILOT = 0x02;
-
-// start location constants
-const U32 START_LOCATION_ID_LAST = 0;
-const U32 START_LOCATION_ID_HOME = 1;
-const U32 START_LOCATION_ID_DIRECT = 2; // for direct teleport
-const U32 START_LOCATION_ID_PARCEL = 3; // for teleports to a parcel
-const U32 START_LOCATION_ID_TELEHUB = 4; // for teleports to a spawnpoint
-const U32 START_LOCATION_ID_URL = 5;
-const U32 START_LOCATION_ID_COUNT = 6;
-
-// group constants
-const U32 GROUP_MIN_SIZE = 2;
-
-// gMaxAgentGroups is now sent by login.cgi, which
-// looks it up from globals.xml.
-//
-// For now we need an old default value however,
-// so the viewer can be deployed ahead of login.cgi.
-//
-const S32 DEFAULT_MAX_AGENT_GROUPS = 25;
+// image ids
+LL_COMMON_API extern const LLUUID IMG_SMOKE;
-// radius within which a chat message is fully audible
-const F32 CHAT_WHISPER_RADIUS = 10.f;
-const F32 CHAT_NORMAL_RADIUS = 20.f;
-const F32 CHAT_SHOUT_RADIUS = 100.f;
-const F32 CHAT_MAX_RADIUS = CHAT_SHOUT_RADIUS;
-const F32 CHAT_MAX_RADIUS_BY_TWO = CHAT_MAX_RADIUS / 2.f;
+LL_COMMON_API extern const LLUUID IMG_DEFAULT;
-// squared editions of the above for distance checks
-const F32 CHAT_WHISPER_RADIUS_SQUARED = CHAT_WHISPER_RADIUS * CHAT_WHISPER_RADIUS;
-const F32 CHAT_NORMAL_RADIUS_SQUARED = CHAT_NORMAL_RADIUS * CHAT_NORMAL_RADIUS;
-const F32 CHAT_SHOUT_RADIUS_SQUARED = CHAT_SHOUT_RADIUS * CHAT_SHOUT_RADIUS;
-const F32 CHAT_MAX_RADIUS_SQUARED = CHAT_SHOUT_RADIUS_SQUARED;
-const F32 CHAT_MAX_RADIUS_BY_TWO_SQUARED = CHAT_MAX_RADIUS_BY_TWO * CHAT_MAX_RADIUS_BY_TWO;
+LL_COMMON_API extern const LLUUID IMG_SUN;
+LL_COMMON_API extern const LLUUID IMG_MOON;
+LL_COMMON_API extern const LLUUID IMG_SHOT;
+LL_COMMON_API extern const LLUUID IMG_SPARK;
+LL_COMMON_API extern const LLUUID IMG_FIRE;
+LL_COMMON_API extern const LLUUID IMG_FACE_SELECT;
+LL_COMMON_API extern const LLUUID IMG_DEFAULT_AVATAR;
+LL_COMMON_API extern const LLUUID IMG_INVISIBLE;
+LL_COMMON_API extern const LLUUID IMG_EXPLOSION;
+LL_COMMON_API extern const LLUUID IMG_EXPLOSION_2;
+LL_COMMON_API extern const LLUUID IMG_EXPLOSION_3;
+LL_COMMON_API extern const LLUUID IMG_EXPLOSION_4;
+LL_COMMON_API extern const LLUUID IMG_SMOKE_POOF;
-// this times above gives barely audible radius
-const F32 CHAT_BARELY_AUDIBLE_FACTOR = 2.0f;
+LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_1;
+LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_2;
-// distance in front of speaking agent the sphere is centered
-const F32 CHAT_WHISPER_OFFSET = 5.f;
-const F32 CHAT_NORMAL_OFFSET = 10.f;
-const F32 CHAT_SHOUT_OFFSET = 50.f;
+LL_COMMON_API extern const LLUUID IMG_BLOOM1;
+LL_COMMON_API extern const LLUUID TERRAIN_DIRT_DETAIL;
+LL_COMMON_API extern const LLUUID TERRAIN_GRASS_DETAIL;
+LL_COMMON_API extern const LLUUID TERRAIN_MOUNTAIN_DETAIL;
+LL_COMMON_API extern const LLUUID TERRAIN_ROCK_DETAIL;
-// first clean starts at 3 AM
-const S32 SANDBOX_FIRST_CLEAN_HOUR = 3;
-// clean every <n> hours
-const S32 SANDBOX_CLEAN_FREQ = 12;
+LL_COMMON_API extern const LLUUID DEFAULT_WATER_NORMAL;
-const F32 WIND_SCALE_HACK = 2.0f; // hack to make wind speeds more realistic
-enum ETerrainBrushType
-{
- // the valid brush numbers cannot be reordered, because they
- // are used in the binary LSL format as arguments to llModifyLand()
- E_LANDBRUSH_LEVEL = 0,
- E_LANDBRUSH_RAISE = 1,
- E_LANDBRUSH_LOWER = 2,
- E_LANDBRUSH_SMOOTH = 3,
- E_LANDBRUSH_NOISE = 4,
- E_LANDBRUSH_REVERT = 5,
- E_LANDBRUSH_INVALID = 6
-};
+// radius within which a chat message is fully audible
+const F32 CHAT_NORMAL_RADIUS = 20.f;
// media commands
const U32 PARCEL_MEDIA_COMMAND_STOP = 0;
@@ -365,51 +225,101 @@ const U32 PARCEL_MEDIA_COMMAND_SIZE = 11;
const U32 PARCEL_MEDIA_COMMAND_DESC = 12;
const U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13;
-// map item types
-const U32 MAP_ITEM_TELEHUB = 0x01;
-const U32 MAP_ITEM_PG_EVENT = 0x02;
-const U32 MAP_ITEM_MATURE_EVENT = 0x03;
-//const U32 MAP_ITEM_POPULAR = 0x04; // No longer supported, 2009-03-02 KLW
-//const U32 MAP_ITEM_AGENT_COUNT = 0x05;
-const U32 MAP_ITEM_AGENT_LOCATIONS = 0x06;
-const U32 MAP_ITEM_LAND_FOR_SALE = 0x07;
-const U32 MAP_ITEM_CLASSIFIED = 0x08;
-const U32 MAP_ITEM_ADULT_EVENT = 0x09;
-const U32 MAP_ITEM_LAND_FOR_SALE_ADULT = 0x0a;
-
-// Region map layer numbers
-const S32 MAP_SIM_OBJECTS = 0;
-const S32 MAP_SIM_TERRAIN = 1;
-const S32 MAP_SIM_LAND_FOR_SALE = 2; // Transparent alpha overlay of land for sale
-const S32 MAP_SIM_IMAGE_TYPES = 3; // Number of map layers
-const S32 MAP_SIM_INFO_MASK = 0x00FFFFFF; // Agent access may be stuffed into upper byte
-const S32 MAP_SIM_LAYER_MASK = 0x0000FFFF; // Layer info is in lower 16 bits
-const S32 MAP_SIM_RETURN_NULL_SIMS = 0x00010000;
-const S32 MAP_SIM_PRELUDE = 0x00020000;
-
-// Crash reporter behavior
-const S32 CRASH_BEHAVIOR_ASK = 0;
-const S32 CRASH_BEHAVIOR_ALWAYS_SEND = 1;
-const S32 CRASH_BEHAVIOR_NEVER_SEND = 2;
-
-// Export/Import return values
-const S32 EXPORT_SUCCESS = 0;
-const S32 EXPORT_ERROR_PERMISSIONS = -1;
-const S32 EXPORT_ERROR_UNKNOWN = -2;
-
-// This is how long the sim will try to teleport you before giving up.
-const F32 TELEPORT_EXPIRY = 15.0f;
-// Additional time (in seconds) to wait per attachment
-const F32 TELEPORT_EXPIRY_PER_ATTACHMENT = 3.f;
-
-// The maximum size of an object extra parameters binary (packed) block
-#define MAX_OBJECT_PARAMS_SIZE 1024
-
const S32 CHAT_CHANNEL_DEBUG = S32_MAX;
-// PLEASE don't add constants here. Every dev will have to do
-// a complete rebuild. Try to find another shared header file,
-// like llregionflags.h, lllslconstants.h, llagentconstants.h,
-// or create a new one. JC
+// agent constants
+const U32 CONTROL_AT_POS_INDEX = 0;
+const U32 CONTROL_AT_NEG_INDEX = 1;
+const U32 CONTROL_LEFT_POS_INDEX = 2;
+const U32 CONTROL_LEFT_NEG_INDEX = 3;
+const U32 CONTROL_UP_POS_INDEX = 4;
+const U32 CONTROL_UP_NEG_INDEX = 5;
+const U32 CONTROL_PITCH_POS_INDEX = 6;
+const U32 CONTROL_PITCH_NEG_INDEX = 7;
+const U32 CONTROL_YAW_POS_INDEX = 8;
+const U32 CONTROL_YAW_NEG_INDEX = 9;
+const U32 CONTROL_FAST_AT_INDEX = 10;
+const U32 CONTROL_FAST_LEFT_INDEX = 11;
+const U32 CONTROL_FAST_UP_INDEX = 12;
+const U32 CONTROL_FLY_INDEX = 13;
+const U32 CONTROL_STOP_INDEX = 14;
+const U32 CONTROL_FINISH_ANIM_INDEX = 15;
+const U32 CONTROL_STAND_UP_INDEX = 16;
+const U32 CONTROL_SIT_ON_GROUND_INDEX = 17;
+const U32 CONTROL_MOUSELOOK_INDEX = 18;
+const U32 CONTROL_NUDGE_AT_POS_INDEX = 19;
+const U32 CONTROL_NUDGE_AT_NEG_INDEX = 20;
+const U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21;
+const U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22;
+const U32 CONTROL_NUDGE_UP_POS_INDEX = 23;
+const U32 CONTROL_NUDGE_UP_NEG_INDEX = 24;
+const U32 CONTROL_TURN_LEFT_INDEX = 25;
+const U32 CONTROL_TURN_RIGHT_INDEX = 26;
+const U32 CONTROL_AWAY_INDEX = 27;
+const U32 CONTROL_LBUTTON_DOWN_INDEX = 28;
+const U32 CONTROL_LBUTTON_UP_INDEX = 29;
+const U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30;
+const U32 CONTROL_ML_LBUTTON_UP_INDEX = 31;
+const U32 TOTAL_CONTROLS = 32;
+
+const U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001
+const U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002
+const U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004
+const U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008
+const U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010
+const U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020
+const U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040
+const U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080
+const U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100
+const U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200
+
+const U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400
+const U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800
+const U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000
+
+const U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000
+const U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000
+const U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000
+const U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000
+const U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000
+const U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000
+
+const U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000
+const U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000
+const U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000
+const U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000
+const U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000
+const U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000
+const U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000
+const U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000
+
+const U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000
+
+const U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000
+const U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000
+const U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000
+const U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000
+
+// move these up so that we can hide them in "State" for object updates
+// (for now)
+const U32 AGENT_ATTACH_OFFSET = 4;
+const U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET;
+
+// RN: this method swaps the upper and lower nibbles to maintain backward
+// compatibility with old objects that only used the upper nibble
+#define ATTACHMENT_ID_FROM_STATE(state) ((S32)((((U8)state & AGENT_ATTACH_MASK) >> 4) | (((U8)state & ~AGENT_ATTACH_MASK) << 4)))
+
+// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
+const U8 CLICK_ACTION_NONE = 0;
+const U8 CLICK_ACTION_TOUCH = 0;
+const U8 CLICK_ACTION_SIT = 1;
+const U8 CLICK_ACTION_BUY = 2;
+const U8 CLICK_ACTION_PAY = 3;
+const U8 CLICK_ACTION_OPEN = 4;
+const U8 CLICK_ACTION_PLAY = 5;
+const U8 CLICK_ACTION_OPEN_MEDIA = 6;
+const U8 CLICK_ACTION_ZOOM = 7;
+// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
+
#endif
diff --git a/indra/llcommon/linked_lists.h b/indra/llcommon/linked_lists.h
deleted file mode 100755
index 6b25295b7b..0000000000
--- a/indra/llcommon/linked_lists.h
+++ /dev/null
@@ -1,937 +0,0 @@
-/**
- * @file linked_lists.h
- * @brief LLLinkedList class header amd implementation file.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LINKED_LISTS_H
-#define LL_LINKED_LISTS_H
-
-/**
- * Provides a standard doubly linked list for fun and profit
- * Utilizes a neat trick off of Flipcode where the back pointer is a
- * pointer to a pointer, allowing easier transfer of nodes between lists, &c
- * And a template class, of course
- */
-
-#include "llerror.h"
-
-
-template <class DATA_TYPE> class LLLinkedList
-{
-public:
- friend class LLLinkNode;
- // External interface
-
- // basic constructor
- LLLinkedList() : mHead(NULL), mCurrentp(NULL), mInsertBefore(NULL)
- {
- mCurrentp = mHead.mNextp;
- mCurrentOperatingp = mHead.mNextp;
- mCount = 0;
- }
-
- // basic constructor
- LLLinkedList(BOOL (*insert_before)(DATA_TYPE *data_new, DATA_TYPE *data_tested)) : mHead(NULL), mCurrentp(NULL), mInsertBefore(insert_before)
- {
- mCurrentp = mHead.mNextp;
- mCurrentOperatingp = mHead.mNextp;
- mCount = 0;
- }
-
- // destructor destroys list and nodes, but not data in nodes
- ~LLLinkedList()
- {
- removeAllNodes();
- }
-
- // set mInsertBefore
- void setInsertBefore(BOOL (*insert_before)(DATA_TYPE *data_new, DATA_TYPE *data_tested))
- {
- mInsertBefore = insert_before;
- }
-
- //
- // WARNING!!!!!!!
- // addData and addDataSorted are NOT O(1) operations, but O(n) because they check
- // for existence of the data in the linked list first. Why, I don't know - djs
- // If you don't care about dupes, use addDataNoCheck
- //
-
- // put data into a node and stick it at the front of the list
- inline BOOL addData(DATA_TYPE *data);
-
- // put data into a node and sort into list by mInsertBefore()
- // calls normal add if mInsertBefore isn't set
- inline BOOL addDataSorted(DATA_TYPE *data);
-
- inline BOOL addDataNoCheck(DATA_TYPE *data);
-
- // bubbleSortList
- // does an improved bubble sort of the list . . . works best with almost sorted data
- // does nothing if mInsertBefore isn't set
- // Nota Bene: Swaps are accomplished by swapping data pointers
- inline void bubbleSortList();
-
- // put data into a node and stick it at the end of the list
- inline BOOL addDataAtEnd(DATA_TYPE *data);
-
- // returns number of items in the list
- inline S32 getLength() const;
-
- inline BOOL isEmpty();
-
- // search the list starting at mHead.mNextp and remove the link with mDatap == data
- // leave mCurrentp and mCurrentOperatingp on the next entry
- // return TRUE if found, FALSE if not found
- inline BOOL removeData(DATA_TYPE *data);
-
- // search the list starting at mHead.mNextp and delete the link with mDatap == data
- // leave mCurrentp and mCurrentOperatingp on the next entry
- // return TRUE if found, FALSE if not found
- inline BOOL deleteData(DATA_TYPE *data);
-
- // remove all nodes from the list and delete the associated data
- inline void deleteAllData();
-
- // remove all nodes from the list but do not delete data
- inline void removeAllNodes();
-
- // check to see if data is in list
- // if TRUE then mCurrentp and mCurrentOperatingp point to data
- inline BOOL checkData(DATA_TYPE *data);
-
- // place mCurrentp on first node
- inline void resetList();
-
- // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
- inline DATA_TYPE *getCurrentData();
-
- // same as getCurrentData() but a more intuitive name for the operation
- inline DATA_TYPE *getNextData();
-
- // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
- inline DATA_TYPE *getFirstData();
-
- // reset the list and return the data at position n, set mCurentOperatingp to that node and bump mCurrentp
- // Note: n is zero-based
- inline DATA_TYPE *getNthData( U32 n);
-
- // reset the list and return the last data in it, set mCurentOperatingp to that node and bump mCurrentp
- inline DATA_TYPE *getLastData();
-
- // remove the Node at mCurentOperatingp
- // leave mCurrentp and mCurentOperatingp on the next entry
- inline void removeCurrentData();
-
- // remove the Node at mCurentOperatingp and add it to newlist
- // leave mCurrentp and mCurentOperatingp on the next entry
- void moveCurrentData(LLLinkedList *newlist, BOOL b_sort);
-
- BOOL moveData(DATA_TYPE *data, LLLinkedList *newlist, BOOL b_sort);
-
- // delete the Node at mCurentOperatingp
- // leave mCurrentp anf mCurentOperatingp on the next entry
- void deleteCurrentData();
-
-private:
- // node that actually contains the data
- class LLLinkNode
- {
- public:
- // assign the mDatap pointer
- LLLinkNode(DATA_TYPE *data) : mDatap(data), mNextp(NULL), mPrevpp(NULL)
- {
- }
-
- // destructor does not, by default, destroy associated data
- // however, the mDatap must be NULL to ensure that we aren't causing memory leaks
- ~LLLinkNode()
- {
- if (mDatap)
- {
- llerror("Attempting to call LLLinkNode destructor with a non-null mDatap!", 1);
- }
- }
-
- // delete associated data and NULL out pointer
- void deleteData()
- {
- delete mDatap;
- mDatap = NULL;
- }
-
- // NULL out pointer
- void removeData()
- {
- mDatap = NULL;
- }
-
- DATA_TYPE *mDatap;
- LLLinkNode *mNextp;
- LLLinkNode **mPrevpp;
- };
-
- // add a node at the front of the list
- void addData(LLLinkNode *node)
- {
- // don't allow NULL to be passed to addData
- if (!node)
- {
- llerror("NULL pointer passed to LLLinkedList::addData", 0);
- }
-
- // add the node to the front of the list
- node->mPrevpp = &mHead.mNextp;
- node->mNextp = mHead.mNextp;
-
- // if there's something in the list, fix its back pointer
- if (node->mNextp)
- {
- node->mNextp->mPrevpp = &node->mNextp;
- }
-
- mHead.mNextp = node;
- }
-
- LLLinkNode mHead; // fake head node. . . makes pointer operations faster and easier
- LLLinkNode *mCurrentp; // mCurrentp is the Node that getCurrentData returns
- LLLinkNode *mCurrentOperatingp; // this is the node that the various mumbleCurrentData functions act on
- BOOL (*mInsertBefore)(DATA_TYPE *data_new, DATA_TYPE *data_tested); // user function set to allow sorted lists
- U32 mCount;
-};
-
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::addData(DATA_TYPE *data)
-{
- // don't allow NULL to be passed to addData
- if (!data)
- {
- llerror("NULL pointer passed to LLLinkedList::addData", 0);
- }
-
- LLLinkNode *tcurr = mCurrentp;
- LLLinkNode *tcurrop = mCurrentOperatingp;
-
- if ( checkData(data))
- {
- mCurrentp = tcurr;
- mCurrentOperatingp = tcurrop;
- return FALSE;
- }
-
- // make the new node
- LLLinkNode *temp = new LLLinkNode(data);
-
- // add the node to the front of the list
- temp->mPrevpp = &mHead.mNextp;
- temp->mNextp = mHead.mNextp;
-
- // if there's something in the list, fix its back pointer
- if (temp->mNextp)
- {
- temp->mNextp->mPrevpp = &temp->mNextp;
- }
-
- mHead.mNextp = temp;
- mCurrentp = tcurr;
- mCurrentOperatingp = tcurrop;
- mCount++;
- return TRUE;
-}
-
-
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::addDataNoCheck(DATA_TYPE *data)
-{
- // don't allow NULL to be passed to addData
- if (!data)
- {
- llerror("NULL pointer passed to LLLinkedList::addData", 0);
- }
-
- LLLinkNode *tcurr = mCurrentp;
- LLLinkNode *tcurrop = mCurrentOperatingp;
-
- // make the new node
- LLLinkNode *temp = new LLLinkNode(data);
-
- // add the node to the front of the list
- temp->mPrevpp = &mHead.mNextp;
- temp->mNextp = mHead.mNextp;
-
- // if there's something in the list, fix its back pointer
- if (temp->mNextp)
- {
- temp->mNextp->mPrevpp = &temp->mNextp;
- }
-
- mHead.mNextp = temp;
- mCurrentp = tcurr;
- mCurrentOperatingp = tcurrop;
- mCount++;
- return TRUE;
-}
-
-
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::addDataSorted(DATA_TYPE *data)
-{
- LLLinkNode *tcurr = mCurrentp;
- LLLinkNode *tcurrop = mCurrentOperatingp;
- // don't allow NULL to be passed to addData
- if (!data)
- {
- llerror("NULL pointer passed to LLLinkedList::addDataSorted", 0);
- }
-
- if (checkData(data))
- {
- // restore
- mCurrentp = tcurr;
- mCurrentOperatingp = tcurrop;
- return FALSE;
- }
-
- // mInsertBefore not set?
- if (!mInsertBefore)
- {
- addData(data);
- // restore
- mCurrentp = tcurr;
- mCurrentOperatingp = tcurrop;
- return FALSE;
- }
-
- // empty list?
- if (!mHead.mNextp)
- {
- addData(data);
- // restore
- mCurrentp = tcurr;
- mCurrentOperatingp = tcurrop;
- return TRUE;
- }
-
- // make the new node
- LLLinkNode *temp = new LLLinkNode(data);
-
- // walk the list until mInsertBefore returns true
- mCurrentp = mHead.mNextp;
- while (mCurrentp->mNextp)
- {
- if (mInsertBefore(data, mCurrentp->mDatap))
- {
- // insert before the current one
- temp->mPrevpp = mCurrentp->mPrevpp;
- temp->mNextp = mCurrentp;
- *(temp->mPrevpp) = temp;
- mCurrentp->mPrevpp = &temp->mNextp;
- // restore
- mCurrentp = tcurr;
- mCurrentOperatingp = tcurrop;
- mCount++;
- return TRUE;
- }
- else
- {
- mCurrentp = mCurrentp->mNextp;
- }
- }
-
- // on the last element, add before?
- if (mInsertBefore(data, mCurrentp->mDatap))
- {
- // insert before the current one
- temp->mPrevpp = mCurrentp->mPrevpp;
- temp->mNextp = mCurrentp;
- *(temp->mPrevpp) = temp;
- mCurrentp->mPrevpp = &temp->mNextp;
- // restore
- mCurrentp = tcurr;
- mCurrentOperatingp = tcurrop;
- }
- else // insert after
- {
- temp->mPrevpp = &mCurrentp->mNextp;
- temp->mNextp = NULL;
- mCurrentp->mNextp = temp;
-
- // restore
- mCurrentp = tcurr;
- mCurrentOperatingp = tcurrop;
- }
- mCount++;
- return TRUE;
-}
-
-template <class DATA_TYPE>
-void LLLinkedList<DATA_TYPE>::bubbleSortList()
-{
- // mInsertBefore not set
- if (!mInsertBefore)
- {
- return;
- }
-
- LLLinkNode *tcurr = mCurrentp;
- LLLinkNode *tcurrop = mCurrentOperatingp;
-
- BOOL b_swapped = FALSE;
- DATA_TYPE *temp;
-
- // Nota Bene: This will break if more than 0x7FFFFFFF members in list!
- S32 length = 0x7FFFFFFF;
- S32 count = 0;
- do
- {
- b_swapped = FALSE;
- mCurrentp = mHead.mNextp;
- count = 0;
- while ( (count + 1 < length)
- &&(mCurrentp))
- {
- if (mCurrentp->mNextp)
- {
- if (!mInsertBefore(mCurrentp->mDatap, mCurrentp->mNextp->mDatap))
- {
- // swap data pointers!
- temp = mCurrentp->mDatap;
- mCurrentp->mDatap = mCurrentp->mNextp->mDatap;
- mCurrentp->mNextp->mDatap = temp;
- b_swapped = TRUE;
- }
- }
- else
- {
- break;
- }
- count++;
- mCurrentp = mCurrentp->mNextp;
- }
- length = count;
- } while (b_swapped);
-
- // restore
- mCurrentp = tcurr;
- mCurrentOperatingp = tcurrop;
-}
-
-
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::addDataAtEnd(DATA_TYPE *data)
-{
- LLLinkNode *tcurr = mCurrentp;
- LLLinkNode *tcurrop = mCurrentOperatingp;
-
- // don't allow NULL to be passed to addData
- if (!data)
- {
- llerror("NULL pointer passed to LLLinkedList::addData", 0);
- }
-
- if (checkData(data))
- {
- mCurrentp = tcurr;
- mCurrentOperatingp = tcurrop;
- return FALSE;
- }
-
- // make the new node
- LLLinkNode *temp = new LLLinkNode(data);
-
- // add the node to the end of the list
-
- // if empty, add to the front and be done with it
- if (!mHead.mNextp)
- {
- temp->mPrevpp = &mHead.mNextp;
- temp->mNextp = NULL;
- mHead.mNextp = temp;
- }
- else
- {
- // otherwise, walk to the end of the list
- mCurrentp = mHead.mNextp;
- while (mCurrentp->mNextp)
- {
- mCurrentp = mCurrentp->mNextp;
- }
- temp->mPrevpp = &mCurrentp->mNextp;
- temp->mNextp = NULL;
- mCurrentp->mNextp = temp;
- }
-
- // restore
- mCurrentp = tcurr;
- mCurrentOperatingp = tcurrop;
- mCount++;
- return TRUE;
-}
-
-
-// returns number of items in the list
-template <class DATA_TYPE>
-S32 LLLinkedList<DATA_TYPE>::getLength() const
-{
-// S32 length = 0;
-// for (LLLinkNode* temp = mHead.mNextp; temp != NULL; temp = temp->mNextp)
-// {
-// length++;
-// }
- return mCount;
-}
-
-
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::isEmpty()
-{
- return (mCount == 0);
-}
-
-
-// search the list starting at mHead.mNextp and remove the link with mDatap == data
-// leave mCurrentp and mCurrentOperatingp on the next entry
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::removeData(DATA_TYPE *data)
-{
- BOOL b_found = FALSE;
- // don't allow NULL to be passed to addData
- if (!data)
- {
- llerror("NULL pointer passed to LLLinkedList::removeData", 0);
- }
-
- LLLinkNode *tcurr = mCurrentp;
- LLLinkNode *tcurrop = mCurrentOperatingp;
-
- mCurrentp = mHead.mNextp;
- mCurrentOperatingp = mHead.mNextp;
-
- while (mCurrentOperatingp)
- {
- if (mCurrentOperatingp->mDatap == data)
- {
- b_found = TRUE;
-
- // remove the node
-
- // if there is a next one, fix it
- if (mCurrentOperatingp->mNextp)
- {
- mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
- }
- *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
-
- // remove the LLLinkNode
-
- // if we were on the one we want to delete, bump the cached copies
- if (mCurrentOperatingp == tcurrop)
- {
- tcurrop = tcurr = mCurrentOperatingp->mNextp;
- }
- else if (mCurrentOperatingp == tcurr)
- {
- tcurrop = tcurr = mCurrentOperatingp->mNextp;
- }
-
- mCurrentp = mCurrentOperatingp->mNextp;
-
- mCurrentOperatingp->removeData();
- delete mCurrentOperatingp;
- mCurrentOperatingp = mCurrentp;
- mCount--;
- break;
- }
- mCurrentOperatingp = mCurrentOperatingp->mNextp;
- }
- // restore
- mCurrentp = tcurr;
- mCurrentOperatingp = tcurrop;
- return b_found;
-}
-
-// search the list starting at mHead.mNextp and delete the link with mDatap == data
-// leave mCurrentp and mCurrentOperatingp on the next entry
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::deleteData(DATA_TYPE *data)
-{
- BOOL b_found = FALSE;
- // don't allow NULL to be passed to addData
- if (!data)
- {
- llerror("NULL pointer passed to LLLinkedList::removeData", 0);
- }
-
- LLLinkNode *tcurr = mCurrentp;
- LLLinkNode *tcurrop = mCurrentOperatingp;
-
- mCurrentp = mHead.mNextp;
- mCurrentOperatingp = mHead.mNextp;
-
- while (mCurrentOperatingp)
- {
- if (mCurrentOperatingp->mDatap == data)
- {
- b_found = TRUE;
-
- // remove the node
- // if there is a next one, fix it
- if (mCurrentOperatingp->mNextp)
- {
- mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
- }
- *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
-
- // delete the LLLinkNode
- // if we were on the one we want to delete, bump the cached copies
- if (mCurrentOperatingp == tcurrop)
- {
- tcurrop = tcurr = mCurrentOperatingp->mNextp;
- }
-
- // and delete the associated data
- llassert(mCurrentOperatingp);
- mCurrentp = mCurrentOperatingp->mNextp;
- mCurrentOperatingp->deleteData();
- delete mCurrentOperatingp;
- mCurrentOperatingp = mCurrentp;
- mCount--;
- break;
- }
- mCurrentOperatingp = mCurrentOperatingp->mNextp;
- }
- // restore
- mCurrentp = tcurr;
- mCurrentOperatingp = tcurrop;
- return b_found;
-}
-
- // remove all nodes from the list and delete the associated data
-template <class DATA_TYPE>
-void LLLinkedList<DATA_TYPE>::deleteAllData()
-{
- LLLinkNode *temp;
- // reset mCurrentp
- mCurrentp = mHead.mNextp;
-
- while (mCurrentp)
- {
- temp = mCurrentp->mNextp;
- mCurrentp->deleteData();
- delete mCurrentp;
- mCurrentp = temp;
- }
-
- // reset mHead and mCurrentp
- mHead.mNextp = NULL;
- mCurrentp = mHead.mNextp;
- mCurrentOperatingp = mHead.mNextp;
- mCount = 0;
-}
-
-// remove all nodes from the list but do not delete data
-template <class DATA_TYPE>
-void LLLinkedList<DATA_TYPE>::removeAllNodes()
-{
- LLLinkNode *temp;
- // reset mCurrentp
- mCurrentp = mHead.mNextp;
-
- while (mCurrentp)
- {
- temp = mCurrentp->mNextp;
- mCurrentp->removeData();
- delete mCurrentp;
- mCurrentp = temp;
- }
-
- // reset mHead and mCurrentp
- mHead.mNextp = NULL;
- mCurrentp = mHead.mNextp;
- mCurrentOperatingp = mHead.mNextp;
- mCount = 0;
-}
-
-// check to see if data is in list
-// if TRUE then mCurrentp and mCurrentOperatingp point to data
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::checkData(DATA_TYPE *data)
-{
- // reset mCurrentp
- mCurrentp = mHead.mNextp;
-
- while (mCurrentp)
- {
- if (mCurrentp->mDatap == data)
- {
- mCurrentOperatingp = mCurrentp;
- return TRUE;
- }
- mCurrentp = mCurrentp->mNextp;
- }
- mCurrentOperatingp = mCurrentp;
- return FALSE;
-}
-
-// place mCurrentp on first node
-template <class DATA_TYPE>
-void LLLinkedList<DATA_TYPE>::resetList()
-{
- mCurrentp = mHead.mNextp;
- mCurrentOperatingp = mHead.mNextp;
-}
-
-// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class DATA_TYPE>
-DATA_TYPE *LLLinkedList<DATA_TYPE>::getCurrentData()
-{
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mNextp;
- return mCurrentOperatingp->mDatap;
- }
- else
- {
- return NULL;
- }
-}
-
-// same as getCurrentData() but a more intuitive name for the operation
-template <class DATA_TYPE>
-DATA_TYPE *LLLinkedList<DATA_TYPE>::getNextData()
-{
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mNextp;
- return mCurrentOperatingp->mDatap;
- }
- else
- {
- return NULL;
- }
-}
-
-// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class DATA_TYPE>
-DATA_TYPE *LLLinkedList<DATA_TYPE>::getFirstData()
-{
- mCurrentp = mHead.mNextp;
- mCurrentOperatingp = mHead.mNextp;
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mNextp;
- return mCurrentOperatingp->mDatap;
- }
- else
- {
- return NULL;
- }
-}
-
-// Note: n is zero-based
-template <class DATA_TYPE>
-DATA_TYPE *LLLinkedList<DATA_TYPE>::getNthData( U32 n )
-{
- mCurrentOperatingp = mHead.mNextp;
-
- // if empty, return NULL
- if (!mCurrentOperatingp)
- {
- return NULL;
- }
-
- for( U32 i = 0; i < n; i++ )
- {
- mCurrentOperatingp = mCurrentOperatingp->mNextp;
- if( !mCurrentOperatingp )
- {
- return NULL;
- }
- }
-
- mCurrentp = mCurrentOperatingp->mNextp;
- return mCurrentOperatingp->mDatap;
-}
-
-
-// reset the list and return the last data in it, set mCurentOperatingp to that node and bump mCurrentp
-template <class DATA_TYPE>
-DATA_TYPE *LLLinkedList<DATA_TYPE>::getLastData()
-{
- mCurrentOperatingp = mHead.mNextp;
-
- // if empty, return NULL
- if (!mCurrentOperatingp)
- return NULL;
-
- // walk until we're pointing at the last entry
- while (mCurrentOperatingp->mNextp)
- {
- mCurrentOperatingp = mCurrentOperatingp->mNextp;
- }
- mCurrentp = mCurrentOperatingp->mNextp;
- return mCurrentOperatingp->mDatap;
-}
-
-// remove the Node at mCurentOperatingp
-// leave mCurrentp and mCurentOperatingp on the next entry
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-void LLLinkedList<DATA_TYPE>::removeCurrentData()
-{
- if (mCurrentOperatingp)
- {
- // remove the node
- // if there is a next one, fix it
- if (mCurrentOperatingp->mNextp)
- {
- mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
- }
- *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
-
- // remove the LLLinkNode
- mCurrentp = mCurrentOperatingp->mNextp;
-
- mCurrentOperatingp->removeData();
- delete mCurrentOperatingp;
- mCount--;
- mCurrentOperatingp = mCurrentp;
- }
-}
-
-// remove the Node at mCurentOperatingp and add it to newlist
-// leave mCurrentp and mCurentOperatingp on the next entry
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-void LLLinkedList<DATA_TYPE>::moveCurrentData(LLLinkedList *newlist, BOOL b_sort)
-{
- if (mCurrentOperatingp)
- {
- // remove the node
- // if there is a next one, fix it
- if (mCurrentOperatingp->mNextp)
- {
- mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
- }
- *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
-
- // remove the LLLinkNode
- mCurrentp = mCurrentOperatingp->mNextp;
- // move the node to the new list
- newlist->addData(mCurrentOperatingp);
- if (b_sort)
- bubbleSortList();
- mCurrentOperatingp = mCurrentp;
- }
-}
-
-template <class DATA_TYPE>
-BOOL LLLinkedList<DATA_TYPE>::moveData(DATA_TYPE *data, LLLinkedList *newlist, BOOL b_sort)
-{
- BOOL b_found = FALSE;
- // don't allow NULL to be passed to addData
- if (!data)
- {
- llerror("NULL pointer passed to LLLinkedList::removeData", 0);
- }
-
- LLLinkNode *tcurr = mCurrentp;
- LLLinkNode *tcurrop = mCurrentOperatingp;
-
- mCurrentp = mHead.mNextp;
- mCurrentOperatingp = mHead.mNextp;
-
- while (mCurrentOperatingp)
- {
- if (mCurrentOperatingp->mDatap == data)
- {
- b_found = TRUE;
-
- // remove the node
-
- // if there is a next one, fix it
- if (mCurrentOperatingp->mNextp)
- {
- mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
- }
- *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
-
- // if we were on the one we want to delete, bump the cached copies
- if ( (mCurrentOperatingp == tcurrop)
- ||(mCurrentOperatingp == tcurr))
- {
- tcurrop = tcurr = mCurrentOperatingp->mNextp;
- }
-
- // remove the LLLinkNode
- mCurrentp = mCurrentOperatingp->mNextp;
- // move the node to the new list
- newlist->addData(mCurrentOperatingp);
- if (b_sort)
- newlist->bubbleSortList();
- mCurrentOperatingp = mCurrentp;
- break;
- }
- mCurrentOperatingp = mCurrentOperatingp->mNextp;
- }
- // restore
- mCurrentp = tcurr;
- mCurrentOperatingp = tcurrop;
- return b_found;
-}
-
-// delete the Node at mCurentOperatingp
-// leave mCurrentp anf mCurentOperatingp on the next entry
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-void LLLinkedList<DATA_TYPE>::deleteCurrentData()
-{
- if (mCurrentOperatingp)
- {
- // remove the node
- // if there is a next one, fix it
- if (mCurrentOperatingp->mNextp)
- {
- mCurrentOperatingp->mNextp->mPrevpp = mCurrentOperatingp->mPrevpp;
- }
- *(mCurrentOperatingp->mPrevpp) = mCurrentOperatingp->mNextp;
-
- // remove the LLLinkNode
- mCurrentp = mCurrentOperatingp->mNextp;
-
- mCurrentOperatingp->deleteData();
- if (mCurrentOperatingp->mDatap)
- llerror("This is impossible!", 0);
- delete mCurrentOperatingp;
- mCurrentOperatingp = mCurrentp;
- mCount--;
- }
-}
-
-#endif
diff --git a/indra/llcommon/ll_template_cast.h b/indra/llcommon/ll_template_cast.h
deleted file mode 100755
index c8f9a2f7eb..0000000000
--- a/indra/llcommon/ll_template_cast.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/**
- * @file ll_template_cast.h
- * @author Nat Goodspeed
- * @date 2009-11-21
- * @brief Define ll_template_cast function
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LL_TEMPLATE_CAST_H)
-#define LL_LL_TEMPLATE_CAST_H
-
-/**
- * Implementation for ll_template_cast() (q.v.).
- *
- * Default implementation: trying to cast two completely unrelated types
- * returns 0. Typically you'd specify T and U as pointer types, but in fact T
- * can be any type that can be initialized with 0.
- */
-template <typename T, typename U>
-struct ll_template_cast_impl
-{
- T operator()(U)
- {
- return 0;
- }
-};
-
-/**
- * ll_template_cast<T>(some_value) is for use in a template function when
- * some_value might be of arbitrary type, but you want to recognize type T
- * specially.
- *
- * It's designed for use with pointer types. Example:
- * @code
- * struct SpecialClass
- * {
- * void someMethod(const std::string&) const;
- * };
- *
- * template <class REALCLASS>
- * void somefunc(const REALCLASS& instance)
- * {
- * const SpecialClass* ptr = ll_template_cast<const SpecialClass*>(&instance);
- * if (ptr)
- * {
- * ptr->someMethod("Call method only available on SpecialClass");
- * }
- * }
- * @endcode
- *
- * Why is this better than dynamic_cast<>? Because unless OtherClass is
- * polymorphic, the following won't even compile (gcc 4.0.1):
- * @code
- * OtherClass other;
- * SpecialClass* ptr = dynamic_cast<SpecialClass*>(&other);
- * @endcode
- * to say nothing of this:
- * @code
- * void function(int);
- * SpecialClass* ptr = dynamic_cast<SpecialClass*>(&function);
- * @endcode
- * ll_template_cast handles these kinds of cases by returning 0.
- */
-template <typename T, typename U>
-T ll_template_cast(U value)
-{
- return ll_template_cast_impl<T, U>()(value);
-}
-
-/**
- * Implementation for ll_template_cast() (q.v.).
- *
- * Implementation for identical types: return same value.
- */
-template <typename T>
-struct ll_template_cast_impl<T, T>
-{
- T operator()(T value)
- {
- return value;
- }
-};
-
-/**
- * LL_TEMPLATE_CONVERTIBLE(dest, source) asserts that, for a value @c s of
- * type @c source, <tt>ll_template_cast<dest>(s)</tt> will return @c s --
- * presuming that @c source can be converted to @c dest by the normal rules of
- * C++.
- *
- * By default, <tt>ll_template_cast<dest>(s)</tt> will return 0 unless @c s's
- * type is literally identical to @c dest. (This is because of the
- * straightforward application of template specialization rules.) That can
- * lead to surprising results, e.g.:
- *
- * @code
- * Foo myFoo;
- * const Foo* fooptr = ll_template_cast<const Foo*>(&myFoo);
- * @endcode
- *
- * Here @c fooptr will be 0 because <tt>&myFoo</tt> is of type <tt>Foo*</tt>
- * -- @em not <tt>const Foo*</tt>. (Declaring <tt>const Foo myFoo;</tt> would
- * force the compiler to do the right thing.)
- *
- * More disappointingly:
- * @code
- * struct Base {};
- * struct Subclass: public Base {};
- * Subclass object;
- * Base* ptr = ll_template_cast<Base*>(&object);
- * @endcode
- *
- * Here @c ptr will be 0 because <tt>&object</tt> is of type
- * <tt>Subclass*</tt> rather than <tt>Base*</tt>. We @em want this cast to
- * succeed, but without our help ll_template_cast can't recognize it.
- *
- * The following would suffice:
- * @code
- * LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
- * ...
- * Base* ptr = ll_template_cast<Base*>(&object);
- * @endcode
- *
- * However, as noted earlier, this is easily fooled:
- * @code
- * const Base* ptr = ll_template_cast<const Base*>(&object);
- * @endcode
- * would still produce 0 because we haven't yet seen:
- * @code
- * LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
- * @endcode
- *
- * @TODO
- * This macro should use Boost type_traits facilities for stripping and
- * re-adding @c const and @c volatile qualifiers so that invoking
- * LL_TEMPLATE_CONVERTIBLE(dest, source) will automatically generate all
- * permitted permutations. It's really not fair to the coder to require
- * separate:
- * @code
- * LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
- * LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
- * LL_TEMPLATE_CONVERTIBLE(const Base*, const Subclass*);
- * @endcode
- *
- * (Naturally we omit <tt>LL_TEMPLATE_CONVERTIBLE(Base*, const Subclass*)</tt>
- * because that's not permitted by normal C++ assignment anyway.)
- */
-#define LL_TEMPLATE_CONVERTIBLE(DEST, SOURCE) \
-template <> \
-struct ll_template_cast_impl<DEST, SOURCE> \
-{ \
- DEST operator()(SOURCE wrapper) \
- { \
- return wrapper; \
- } \
-}
-
-#endif /* ! defined(LL_LL_TEMPLATE_CAST_H) */
diff --git a/indra/llcommon/llaccountingcost.h b/indra/llcommon/llaccountingcost.h
deleted file mode 100755
index 0ef3b50c6d..0000000000
--- a/indra/llcommon/llaccountingcost.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * @file llaccountingcost.h
- * @
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2011, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_ACCOUNTINGQUOTA_H
-#define LL_ACCOUNTINGQUOTA_H
-
-struct ParcelQuota
-{
- ParcelQuota( F32 ownerRenderCost, F32 ownerPhysicsCost, F32 ownerNetworkCost, F32 ownerSimulationCost,
- F32 groupRenderCost, F32 groupPhysicsCost, F32 groupNetworkCost, F32 groupSimulationCost,
- F32 otherRenderCost, F32 otherPhysicsCost, F32 otherNetworkCost, F32 otherSimulationCost,
- F32 tempRenderCost, F32 tempPhysicsCost, F32 tempNetworkCost, F32 tempSimulationCost,
- F32 selectedRenderCost, F32 selectedPhysicsCost, F32 selectedNetworkCost, F32 selectedSimulationCost,
- F32 parcelCapacity )
- : mOwnerRenderCost( ownerRenderCost ), mOwnerPhysicsCost( ownerPhysicsCost )
- , mOwnerNetworkCost( ownerNetworkCost ), mOwnerSimulationCost( ownerSimulationCost )
- , mGroupRenderCost( groupRenderCost ), mGroupPhysicsCost( groupPhysicsCost )
- , mGroupNetworkCost( groupNetworkCost ), mGroupSimulationCost( groupSimulationCost )
- , mOtherRenderCost( otherRenderCost ), mOtherPhysicsCost( otherPhysicsCost )
- , mOtherNetworkCost( otherNetworkCost ), mOtherSimulationCost( otherSimulationCost )
- , mTempRenderCost( tempRenderCost ), mTempPhysicsCost( tempPhysicsCost )
- , mTempNetworkCost( tempNetworkCost ), mTempSimulationCost( tempSimulationCost )
- , mSelectedRenderCost( tempRenderCost ), mSelectedPhysicsCost( tempPhysicsCost )
- , mSelectedNetworkCost( tempNetworkCost ), mSelectedSimulationCost( selectedSimulationCost )
- , mParcelCapacity( parcelCapacity )
- {
- }
-
- ParcelQuota(){}
- F32 mOwnerRenderCost, mOwnerPhysicsCost, mOwnerNetworkCost, mOwnerSimulationCost;
- F32 mGroupRenderCost, mGroupPhysicsCost, mGroupNetworkCost, mGroupSimulationCost;
- F32 mOtherRenderCost, mOtherPhysicsCost, mOtherNetworkCost, mOtherSimulationCost;
- F32 mTempRenderCost, mTempPhysicsCost, mTempNetworkCost, mTempSimulationCost;
- F32 mSelectedRenderCost, mSelectedPhysicsCost, mSelectedNetworkCost, mSelectedSimulationCost;
- F32 mParcelCapacity;
-};
-
-//SelectionQuota atm does not require a id
-struct SelectionCost
-{
- SelectionCost( /*LLTransactionID transactionId, */ F32 physicsCost, F32 networkCost, F32 simulationCost )
- //: mTransactionId( transactionId)
- : mPhysicsCost( physicsCost )
- , mNetworkCost( networkCost )
- , mSimulationCost( simulationCost )
- {
- }
- SelectionCost()
- : mPhysicsCost( 0.0f )
- , mNetworkCost( 0.0f )
- , mSimulationCost( 0.0f )
- {}
-
- F32 mPhysicsCost, mNetworkCost, mSimulationCost;
- //LLTransactionID mTransactionId;
-};
-
-typedef enum { Roots = 0 , Prims } eSelectionType;
-
-#endif
-
-
-
diff --git a/indra/llcommon/llagentconstants.h b/indra/llcommon/llagentconstants.h
deleted file mode 100755
index cd237da4eb..0000000000
--- a/indra/llcommon/llagentconstants.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/**
- * @file llagentconstants.h
- * @author James Cook, Andrew Meadows, Richard Nelson
- * @brief Shared constants through the system for agents.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLAGENTCONSTANTS_H
-#define LL_LLAGENTCONSTANTS_H
-
-const U32 CONTROL_AT_POS_INDEX = 0;
-const U32 CONTROL_AT_NEG_INDEX = 1;
-const U32 CONTROL_LEFT_POS_INDEX = 2;
-const U32 CONTROL_LEFT_NEG_INDEX = 3;
-const U32 CONTROL_UP_POS_INDEX = 4;
-const U32 CONTROL_UP_NEG_INDEX = 5;
-const U32 CONTROL_PITCH_POS_INDEX = 6;
-const U32 CONTROL_PITCH_NEG_INDEX = 7;
-const U32 CONTROL_YAW_POS_INDEX = 8;
-const U32 CONTROL_YAW_NEG_INDEX = 9;
-const U32 CONTROL_FAST_AT_INDEX = 10;
-const U32 CONTROL_FAST_LEFT_INDEX = 11;
-const U32 CONTROL_FAST_UP_INDEX = 12;
-const U32 CONTROL_FLY_INDEX = 13;
-const U32 CONTROL_STOP_INDEX = 14;
-const U32 CONTROL_FINISH_ANIM_INDEX = 15;
-const U32 CONTROL_STAND_UP_INDEX = 16;
-const U32 CONTROL_SIT_ON_GROUND_INDEX = 17;
-const U32 CONTROL_MOUSELOOK_INDEX = 18;
-const U32 CONTROL_NUDGE_AT_POS_INDEX = 19;
-const U32 CONTROL_NUDGE_AT_NEG_INDEX = 20;
-const U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21;
-const U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22;
-const U32 CONTROL_NUDGE_UP_POS_INDEX = 23;
-const U32 CONTROL_NUDGE_UP_NEG_INDEX = 24;
-const U32 CONTROL_TURN_LEFT_INDEX = 25;
-const U32 CONTROL_TURN_RIGHT_INDEX = 26;
-const U32 CONTROL_AWAY_INDEX = 27;
-const U32 CONTROL_LBUTTON_DOWN_INDEX = 28;
-const U32 CONTROL_LBUTTON_UP_INDEX = 29;
-const U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30;
-const U32 CONTROL_ML_LBUTTON_UP_INDEX = 31;
-const U32 TOTAL_CONTROLS = 32;
-
-const U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001
-const U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002
-const U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004
-const U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008
-const U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010
-const U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020
-const U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040
-const U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080
-const U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100
-const U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200
-
-const U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400
-const U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800
-const U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000
-
-const U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000
-const U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000
-const U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000
-const U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000
-const U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000
-const U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000
-
-const U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000
-const U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000
-const U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000
-const U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000
-const U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000
-const U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000
-const U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000
-const U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000
-
-const U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000
-
-const U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000
-const U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000
-const U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000
-const U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000
-
-const U32 AGENT_CONTROL_AT = AGENT_CONTROL_AT_POS
- | AGENT_CONTROL_AT_NEG
- | AGENT_CONTROL_NUDGE_AT_POS
- | AGENT_CONTROL_NUDGE_AT_NEG;
-
-const U32 AGENT_CONTROL_LEFT = AGENT_CONTROL_LEFT_POS
- | AGENT_CONTROL_LEFT_NEG
- | AGENT_CONTROL_NUDGE_LEFT_POS
- | AGENT_CONTROL_NUDGE_LEFT_NEG;
-
-const U32 AGENT_CONTROL_UP = AGENT_CONTROL_UP_POS
- | AGENT_CONTROL_UP_NEG
- | AGENT_CONTROL_NUDGE_UP_POS
- | AGENT_CONTROL_NUDGE_UP_NEG;
-
-const U32 AGENT_CONTROL_HORIZONTAL = AGENT_CONTROL_AT
- | AGENT_CONTROL_LEFT;
-
-const U32 AGENT_CONTROL_NOT_USED_BY_LSL = AGENT_CONTROL_FLY
- | AGENT_CONTROL_STOP
- | AGENT_CONTROL_FINISH_ANIM
- | AGENT_CONTROL_STAND_UP
- | AGENT_CONTROL_SIT_ON_GROUND
- | AGENT_CONTROL_MOUSELOOK
- | AGENT_CONTROL_AWAY;
-
-const U32 AGENT_CONTROL_MOVEMENT = AGENT_CONTROL_AT
- | AGENT_CONTROL_LEFT
- | AGENT_CONTROL_UP;
-
-const U32 AGENT_CONTROL_ROTATION = AGENT_CONTROL_PITCH_POS
- | AGENT_CONTROL_PITCH_NEG
- | AGENT_CONTROL_YAW_POS
- | AGENT_CONTROL_YAW_NEG;
-
-const U32 AGENT_CONTROL_NUDGE = AGENT_CONTROL_NUDGE_AT_POS
- | AGENT_CONTROL_NUDGE_AT_NEG
- | AGENT_CONTROL_NUDGE_LEFT_POS
- | AGENT_CONTROL_NUDGE_LEFT_NEG;
-
-
-// move these up so that we can hide them in "State" for object updates
-// (for now)
-const U32 AGENT_ATTACH_OFFSET = 4;
-const U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET;
-const U32 AGENT_ATTACH_CLEAR = 0x00;
-
-// RN: this method swaps the upper and lower nibbles to maintain backward
-// compatibility with old objects that only used the upper nibble
-#define ATTACHMENT_ID_FROM_STATE(state) ((S32)((((U8)state & AGENT_ATTACH_MASK) >> 4) | (((U8)state & ~AGENT_ATTACH_MASK) << 4)))
-
-// test state for use in testing grabbing the camera
-const U32 AGENT_CAMERA_OBJECT = 0x1 << 3;
-
-const F32 MAX_ATTACHMENT_DIST = 3.5f; // meters?
-
-#endif
diff --git a/indra/llcommon/llalignedarray.h b/indra/llcommon/llalignedarray.h
index ed8fd31205..b68e9e0f82 100644
--- a/indra/llcommon/llalignedarray.h
+++ b/indra/llcommon/llalignedarray.h
@@ -60,7 +60,7 @@ LLAlignedArray<T, alignment>::LLAlignedArray()
template <class T, U32 alignment>
LLAlignedArray<T, alignment>::~LLAlignedArray()
{
- ll_aligned_free(mArray);
+ ll_aligned_free<alignment>(mArray);
mArray = NULL;
mElementCount = 0;
mCapacity = 0;
@@ -74,7 +74,7 @@ void LLAlignedArray<T, alignment>::push_back(const T& elem)
{
mCapacity++;
mCapacity *= 2;
- T* new_buf = (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment);
+ T* new_buf = (T*) ll_aligned_malloc<alignment>(mCapacity*sizeof(T));
if (mArray)
{
ll_memcpy_nonaliased_aligned_16((char*)new_buf, (char*)mArray, sizeof(T)*mElementCount);
@@ -86,7 +86,7 @@ void LLAlignedArray<T, alignment>::push_back(const T& elem)
mArray[mElementCount++] = elem;
//delete old array here to prevent error on a.push_back(a[0])
- ll_aligned_free(old_buf);
+ ll_aligned_free<alignment>(old_buf);
}
template <class T, U32 alignment>
@@ -95,11 +95,11 @@ void LLAlignedArray<T, alignment>::resize(U32 size)
if (mCapacity < size)
{
mCapacity = size+mCapacity*2;
- T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment) : NULL;
+ T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc<alignment>(mCapacity*sizeof(T)) : NULL;
if (mArray)
{
ll_memcpy_nonaliased_aligned_16((char*) new_buf, (char*) mArray, sizeof(T)*mElementCount);
- ll_aligned_free(mArray);
+ ll_aligned_free<alignment>(mArray);
}
/*for (U32 i = mElementCount; i < mCapacity; ++i)
diff --git a/indra/llcommon/llallocator_heap_profile.cpp b/indra/llcommon/llallocator_heap_profile.cpp
index b574ef668b..b2eafde1aa 100755
--- a/indra/llcommon/llallocator_heap_profile.cpp
+++ b/indra/llcommon/llallocator_heap_profile.cpp
@@ -59,7 +59,7 @@ void LLAllocatorHeapProfile::parse(std::string const & prof_text)
{
// *TODO - determine if there should be some better error state than
// mLines being empty. -brad
- llwarns << "invalid heap profile data passed into parser." << llendl;
+ LL_WARNS() << "invalid heap profile data passed into parser." << LL_ENDL;
return;
}
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 67a98d5fb8..5a40845e7d 100755
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -46,8 +46,8 @@
#include "llstl.h" // for DeletePointer()
#include "llstring.h"
#include "lleventtimer.h"
-
#include "google_breakpad/exception_handler.h"
+#include "stringize.h"
//
// Signal handling
@@ -55,6 +55,8 @@
// Windows uses structured exceptions, so it's handled a bit differently.
//
#if LL_WINDOWS
+#include "windows.h"
+
LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop);
BOOL ConsoleCtrlHandler(DWORD fdwCtrlType);
bool windows_post_minidump_callback(const wchar_t* dump_path,
@@ -71,7 +73,9 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *);
#if LL_LINUX
#include "google_breakpad/minidump_descriptor.h"
-bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc, void* context, bool succeeded);
+static bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_desc,
+ void* context,
+ bool succeeded);
#else
// Called by breakpad exception handler after the minidump has been generated.
bool unix_post_minidump_callback(const char *dump_dir,
@@ -109,11 +113,6 @@ BOOL LLApp::sLogInSignal = FALSE;
LLApp::EAppStatus LLApp::sStatus = LLApp::APP_STATUS_STOPPED; // Keeps track of application status
LLAppErrorHandler LLApp::sErrorHandler = NULL;
BOOL LLApp::sErrorThreadRunning = FALSE;
-#if !LL_WINDOWS
-LLApp::child_map LLApp::sChildMap;
-LLAtomicU32* LLApp::sSigChildCount = NULL;
-LLAppChildCallback LLApp::sDefaultChildCallback = NULL;
-#endif
LLApp::LLApp() : mThreadErrorp(NULL)
@@ -128,11 +127,6 @@ void LLApp::commonCtor()
LLCommon::initClass();
-#if !LL_WINDOWS
- // This must be initialized before the error handler.
- sSigChildCount = new LLAtomicU32(0);
-#endif
-
// initialize the options structure. We need to make this an array
// because the structured data will not auto-allocate if we
// reference an invalid location with the [] operator.
@@ -149,12 +143,13 @@ void LLApp::commonCtor()
// Set the application to this instance.
sApplication = this;
-
+
mExceptionHandler = 0;
// initialize the buffer to write the minidump filename to
// (this is used to avoid allocating memory in the crash handler)
- memset(minidump_path, 0, MAX_MINDUMP_PATH_LENGTH);
+ memset(mMinidumpPath, 0, MAX_MINDUMP_PATH_LENGTH);
+ mCrashReportPipeStr = L"\\\\.\\pipe\\LLCrashReporterPipe";
}
LLApp::LLApp(LLErrorThread *error_thread) :
@@ -166,10 +161,6 @@ LLApp::LLApp(LLErrorThread *error_thread) :
LLApp::~LLApp()
{
-#if !LL_WINDOWS
- delete sSigChildCount;
- sSigChildCount = NULL;
-#endif
// reclaim live file memory
std::for_each(mLiveFiles.begin(), mLiveFiles.end(), DeletePointer());
@@ -218,8 +209,8 @@ bool LLApp::parseCommandOptions(int argc, char** argv)
{
if(argv[ii][0] != '-')
{
- llinfos << "Did not find option identifier while parsing token: "
- << argv[ii] << llendl;
+ LL_INFOS() << "Did not find option identifier while parsing token: "
+ << argv[ii] << LL_ENDL;
return false;
}
int offset = 1;
@@ -244,6 +235,20 @@ bool LLApp::parseCommandOptions(int argc, char** argv)
}
++ii;
value.assign(argv[ii]);
+
+#if LL_WINDOWS
+ //Windows changed command line parsing. Deal with it.
+ S32 slen = value.length() - 1;
+ S32 start = 0;
+ S32 end = slen;
+ if (argv[ii][start]=='"')start++;
+ if (argv[ii][end]=='"')end--;
+ if (start!=0 || end!=slen)
+ {
+ value = value.substr (start,end);
+ }
+#endif
+
commands[name] = value;
}
setOptionData(PRIORITY_COMMAND_LINE, commands);
@@ -288,14 +293,43 @@ void LLApp::stepFrame()
mRunner.run();
}
+#if LL_WINDOWS
+//The following code is needed for 32-bit apps on 64-bit windows to keep it from eating
+//crashes. It is a lovely undocumented 'feature' in SP1 of Windows 7. An excellent
+//in-depth article on the issue may be found here: http://randomascii.wordpress.com/2012/07/05/when-even-crashing-doesn-work/
+void EnableCrashingOnCrashes()
+{
+ typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags);
+ typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags);
+ const DWORD EXCEPTION_SWALLOWING = 0x1;
+
+ HMODULE kernel32 = LoadLibraryA("kernel32.dll");
+ tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32,
+ "GetProcessUserModeExceptionPolicy");
+ tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32,
+ "SetProcessUserModeExceptionPolicy");
+ if (pGetPolicy && pSetPolicy)
+ {
+ DWORD dwFlags;
+ if (pGetPolicy(&dwFlags))
+ {
+ // Turn off the filter
+ pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING);
+ }
+ }
+}
+#endif
-void LLApp::setupErrorHandling()
+void LLApp::setupErrorHandling(bool second_instance)
{
// Error handling is done by starting up an error handling thread, which just sleeps and
// occasionally checks to see if the app is in an error state, and sees if it needs to be run.
#if LL_WINDOWS
+
#if LL_SEND_CRASH_REPORTS
+ EnableCrashingOnCrashes();
+
// This sets a callback to handle w32 signals to the console window.
// The viewer shouldn't be affected, sicne its a windowed app.
SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ConsoleCtrlHandler, TRUE);
@@ -303,9 +337,57 @@ void LLApp::setupErrorHandling()
// Install the Google Breakpad crash handler for Windows
if(mExceptionHandler == 0)
{
- llwarns << "adding breakpad exception handler" << llendl;
- mExceptionHandler = new google_breakpad::ExceptionHandler(
- L"C:\\Temp\\", 0, windows_post_minidump_callback, 0, google_breakpad::ExceptionHandler::HANDLER_ALL);
+ if ( second_instance ) //BUG-5707 Firing teleport from a web browser causes second
+ {
+ mExceptionHandler = new google_breakpad::ExceptionHandler(
+ L"C:\\Temp\\",
+ 0, //No filter
+ windows_post_minidump_callback,
+ 0,
+ google_breakpad::ExceptionHandler::HANDLER_ALL); //No custom client info.
+ }
+ else
+ {
+ LL_WARNS() << "adding breakpad exception handler" << LL_ENDL;
+
+ std::wstring wpipe_name;
+ wpipe_name = mCrashReportPipeStr + wstringize(getPid());
+
+ const std::wstring wdump_path(wstringize(mDumpPath));
+
+ int retries = 30;
+ for (; retries > 0; --retries)
+ {
+ if (mExceptionHandler != 0) delete mExceptionHandler;
+
+ mExceptionHandler = new google_breakpad::ExceptionHandler(
+ wdump_path,
+ NULL, //No filter
+ windows_post_minidump_callback,
+ 0,
+ google_breakpad::ExceptionHandler::HANDLER_ALL,
+ MiniDumpNormal, //Generate a 'normal' minidump.
+ wpipe_name.c_str(),
+ NULL); //No custom client info.
+ if (mExceptionHandler->IsOutOfProcess())
+ {
+ LL_INFOS("CRASHREPORT") << "Successfully attached to Out of Process exception handler." << LL_ENDL;
+ break;
+ }
+ else
+ {
+ LL_WARNS("CRASHREPORT") << "Unable to attach to Out of Process exception handler. " << retries << " retries remaining." << LL_ENDL;
+ ::Sleep(100); //Wait a tick and try again.
+ }
+ }
+
+ if (retries == 0) LL_WARNS("CRASHREPORT") << "Unable to attach to Out of Process exception handler." << LL_ENDL;
+ }
+
+ if (mExceptionHandler)
+ {
+ mExceptionHandler->set_handle_debug_exceptions(true);
+ }
}
#endif
#else
@@ -355,14 +437,17 @@ void LLApp::setupErrorHandling()
if(installHandler && (mExceptionHandler == 0))
{
- std::string dumpPath = "/tmp/";
- mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, 0, &unix_post_minidump_callback, 0, true, 0);
+ mExceptionHandler = new google_breakpad::ExceptionHandler(mDumpPath, 0, &unix_post_minidump_callback, 0, true, 0);
}
#elif LL_LINUX
if(installHandler && (mExceptionHandler == 0))
{
- google_breakpad::MinidumpDescriptor desc("/tmp");
- new google_breakpad::ExceptionHandler(desc, 0, &unix_minidump_callback, 0, true, 0);
+ if (mDumpPath.empty())
+ {
+ mDumpPath = "/tmp";
+ }
+ google_breakpad::MinidumpDescriptor desc(mDumpPath);
+ mExceptionHandler = new google_breakpad::ExceptionHandler(desc, NULL, unix_minidump_callback, NULL, true, -1);
}
#endif
@@ -378,7 +463,7 @@ void LLApp::startErrorThread()
//
if(!mThreadErrorp)
{
- llinfos << "Starting error thread" << llendl;
+ LL_INFOS() << "Starting error thread" << LL_ENDL;
mThreadErrorp = new LLErrorThread();
mThreadErrorp->setUserData((void *) this);
mThreadErrorp->start();
@@ -398,7 +483,7 @@ void LLApp::runErrorHandler()
LLApp::sErrorHandler();
}
- //llinfos << "App status now STOPPED" << llendl;
+ //LL_INFOS() << "App status now STOPPED" << LL_ENDL;
LLApp::setStopped();
}
@@ -418,19 +503,35 @@ void LLApp::setError()
void LLApp::setMiniDumpDir(const std::string &path)
{
+ if (path.empty())
+ {
+ mDumpPath = "/tmp";
+ }
+ else
+ {
+ mDumpPath = path;
+ }
+
if(mExceptionHandler == 0) return;
#ifdef LL_WINDOWS
wchar_t buffer[MAX_MINDUMP_PATH_LENGTH];
- mbstowcs(buffer, path.c_str(), MAX_MINDUMP_PATH_LENGTH);
+ mbstowcs(buffer, mDumpPath.c_str(), MAX_MINDUMP_PATH_LENGTH);
mExceptionHandler->set_dump_path(std::wstring(buffer));
#elif LL_LINUX
- google_breakpad::MinidumpDescriptor desc(path);
+ //google_breakpad::MinidumpDescriptor desc("/tmp"); //path works in debug fails in production inside breakpad lib so linux gets a little less stack reporting until it is patched.
+ google_breakpad::MinidumpDescriptor desc(mDumpPath); //path works in debug fails in production inside breakpad lib so linux gets a little less stack reporting until it is patched.
mExceptionHandler->set_minidump_descriptor(desc);
#else
- mExceptionHandler->set_dump_path(path);
+ mExceptionHandler->set_dump_path(mDumpPath);
#endif
}
+void LLApp::setDebugFileNames(const std::string &path)
+{
+ mStaticDebugFileName = path + "static_debug_info.log";
+ mDynamicDebugFileName = path + "dynamic_debug_info.log";
+}
+
void LLApp::writeMiniDump()
{
if(mExceptionHandler == 0) return;
@@ -443,7 +544,7 @@ void LLApp::setQuitting()
if (!isExiting())
{
// If we're already exiting, we don't want to reset our state back to quitting.
- llinfos << "Setting app state to QUITTING" << llendl;
+ LL_INFOS() << "Setting app state to QUITTING" << LL_ENDL;
setStatus(APP_STATUS_QUITTING);
}
}
@@ -507,34 +608,11 @@ bool LLApp::isCrashloggerDisabled()
return (sDisableCrashlogger == TRUE);
}
-#if !LL_WINDOWS
-// static
-U32 LLApp::getSigChildCount()
-{
- if (sSigChildCount)
- {
- return U32(*sSigChildCount);
- }
- return 0;
-}
-
-// static
-void LLApp::incSigChildCount()
-{
- if (sSigChildCount)
- {
- (*sSigChildCount)++;
- }
-}
-
-#endif
-
-
// static
int LLApp::getPid()
{
#if LL_WINDOWS
- return 0;
+ return GetCurrentProcessId();
#else
return getpid();
#endif
@@ -551,7 +629,7 @@ LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *except
if (LLApp::isError())
{
- llwarns << "Got another fatal signal while in the error handler, die now!" << llendl;
+ LL_WARNS() << "Got another fatal signal while in the error handler, die now!" << LL_ENDL;
retval = EXCEPTION_EXECUTE_HANDLER;
return retval;
}
@@ -597,7 +675,7 @@ BOOL ConsoleCtrlHandler(DWORD fdwCtrlType)
// We're already trying to die, just ignore this signal
if (LLApp::sLogInSignal)
{
- llinfos << "Signal handler - Already trying to quit, ignoring signal!" << llendl;
+ LL_INFOS() << "Signal handler - Already trying to quit, ignoring signal!" << LL_ENDL;
}
return TRUE;
}
@@ -610,43 +688,6 @@ BOOL ConsoleCtrlHandler(DWORD fdwCtrlType)
}
#else //!LL_WINDOWS
-void LLApp::setChildCallback(pid_t pid, LLAppChildCallback callback)
-{
- LLChildInfo child_info;
- child_info.mCallback = callback;
- LLApp::sChildMap[pid] = child_info;
-}
-
-void LLApp::setDefaultChildCallback(LLAppChildCallback callback)
-{
- LLApp::sDefaultChildCallback = callback;
-}
-
-pid_t LLApp::fork()
-{
- fflush(NULL); // flush all buffers before the child inherits them
- pid_t pid = ::fork();
- if( pid < 0 )
- {
- int system_error = errno;
- llwarns << "Unable to fork! Operating system error code: "
- << system_error << llendl;
- }
- else if (pid == 0)
- {
- // Sleep a bit to allow the parent to set up child callbacks.
- ms_sleep(10);
-
- // We need to disable signal handling, because we don't have a
- // signal handling thread anymore.
- setupErrorHandling();
- }
- else
- {
- llinfos << "Forked child process " << pid << llendl;
- }
- return pid;
-}
void setup_signals()
{
@@ -735,7 +776,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
if (LLApp::sLogInSignal)
{
- llinfos << "Signal handler - Got signal " << signum << " - " << apr_signal_description_get(signum) << llendl;
+ LL_INFOS() << "Signal handler - Got signal " << signum << " - " << apr_signal_description_get(signum) << LL_ENDL;
}
@@ -744,28 +785,15 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
case SIGCHLD:
if (LLApp::sLogInSignal)
{
- llinfos << "Signal handler - Got SIGCHLD from " << info->si_pid << llendl;
- }
-
- // Check result code for all child procs for which we've
- // registered callbacks THIS WILL NOT WORK IF SIGCHLD IS SENT
- // w/o killing the child (Go, launcher!)
- // TODO: Now that we're using SIGACTION, we can actually
- // implement the launcher behavior to determine who sent the
- // SIGCHLD even if it doesn't result in child termination
- if (LLApp::sChildMap.count(info->si_pid))
- {
- LLApp::sChildMap[info->si_pid].mGotSigChild = TRUE;
+ LL_INFOS() << "Signal handler - Got SIGCHLD from " << info->si_pid << LL_ENDL;
}
-
- LLApp::incSigChildCount();
return;
case SIGABRT:
// Abort just results in termination of the app, no funky error handling.
if (LLApp::sLogInSignal)
{
- llwarns << "Signal handler - Got SIGABRT, terminating" << llendl;
+ LL_WARNS() << "Signal handler - Got SIGABRT, terminating" << LL_ENDL;
}
clear_signals();
raise(signum);
@@ -775,7 +803,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
case SIGTERM:
if (LLApp::sLogInSignal)
{
- llwarns << "Signal handler - Got SIGINT, HUP, or TERM, exiting gracefully" << llendl;
+ LL_WARNS() << "Signal handler - Got SIGINT, HUP, or TERM, exiting gracefully" << LL_ENDL;
}
// Graceful exit
// Just set our state to quitting, not error
@@ -784,7 +812,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
// We're already trying to die, just ignore this signal
if (LLApp::sLogInSignal)
{
- llinfos << "Signal handler - Already trying to quit, ignoring signal!" << llendl;
+ LL_INFOS() << "Signal handler - Already trying to quit, ignoring signal!" << LL_ENDL;
}
return;
}
@@ -806,7 +834,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
// Smackdown treated just like any other app termination, for now
if (LLApp::sLogInSignal)
{
- llwarns << "Signal handler - Handling smackdown signal!" << llendl;
+ LL_WARNS() << "Signal handler - Handling smackdown signal!" << LL_ENDL;
}
else
{
@@ -820,7 +848,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
if (LLApp::sLogInSignal)
{
- llwarns << "Signal handler - Handling fatal signal!" << llendl;
+ LL_WARNS() << "Signal handler - Handling fatal signal!" << LL_ENDL;
}
if (LLApp::isError())
{
@@ -830,7 +858,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
if (LLApp::sLogInSignal)
{
- llwarns << "Signal handler - Got another fatal signal while in the error handler, die now!" << llendl;
+ LL_WARNS() << "Signal handler - Got another fatal signal while in the error handler, die now!" << LL_ENDL;
}
raise(signum);
return;
@@ -838,13 +866,13 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
if (LLApp::sLogInSignal)
{
- llwarns << "Signal handler - Flagging error status and waiting for shutdown" << llendl;
+ LL_WARNS() << "Signal handler - Flagging error status and waiting for shutdown" << LL_ENDL;
}
if (LLApp::isCrashloggerDisabled()) // Don't gracefully handle any signal, crash and core for a gdb post mortem
{
clear_signals();
- llwarns << "Fatal signal received, not handling the crash here, passing back to operating system" << llendl;
+ LL_WARNS() << "Fatal signal received, not handling the crash here, passing back to operating system" << LL_ENDL;
raise(signum);
return;
}
@@ -859,7 +887,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
if (LLApp::sLogInSignal)
{
- llwarns << "Signal handler - App is stopped, reraising signal" << llendl;
+ LL_WARNS() << "Signal handler - App is stopped, reraising signal" << LL_ENDL;
}
clear_signals();
raise(signum);
@@ -867,7 +895,7 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
} else {
if (LLApp::sLogInSignal)
{
- llinfos << "Signal handler - Unhandled signal " << signum << ", ignoring!" << llendl;
+ LL_INFOS() << "Signal handler - Unhandled signal " << signum << ", ignoring!" << LL_ENDL;
}
}
}
@@ -880,23 +908,28 @@ bool unix_minidump_callback(const google_breakpad::MinidumpDescriptor& minidump_
// heap allocations in a crash handler.
// path format: <dump_dir>/<minidump_id>.dmp
- int dirPathLength = strlen(minidump_desc.path());
+
+ //HACK: *path points to the buffer in getMiniDumpFilename which has already allocated space
+ //to avoid doing allocation during crash.
+ char * path = LLApp::instance()->getMiniDumpFilename();
+ int dir_path_len = strlen(path);
// The path must not be truncated.
- llassert((dirPathLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH);
+ S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH - dir_path_len;
+
+ llassert( (remaining - strlen(minidump_desc.path())) > 5);
- char * path = LLApp::instance()->getMiniDumpFilename();
- S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH;
- strncpy(path, minidump_desc.path(), remaining);
- remaining -= dirPathLength;
- path += dirPathLength;
- if (remaining > 0 && dirPathLength > 0 && path[-1] != '/')
+ path += dir_path_len;
+
+ if (dir_path_len > 0 && path[-1] != '/')
{
*path++ = '/';
--remaining;
}
+
+ strncpy(path, minidump_desc.path(), remaining);
- llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl;
+ LL_INFOS() << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL;
LLApp::runErrorHandler();
#ifndef LL_RELEASE_FOR_DOWNLOAD
@@ -942,7 +975,7 @@ bool unix_post_minidump_callback(const char *dump_dir,
strncpy(path, ".dmp", remaining);
}
- llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl;
+ LL_INFOS() << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL;
LLApp::runErrorHandler();
#ifndef LL_RELEASE_FOR_DOWNLOAD
@@ -966,6 +999,7 @@ bool windows_post_minidump_callback(const wchar_t* dump_path,
S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH;
size_t bytesUsed;
+ LL_INFOS("MINIDUMPCALLBACK") << "Dump file was generated." << LL_ENDL;
bytesUsed = wcstombs(path, dump_path, static_cast<size_t>(remaining));
remaining -= bytesUsed;
path += bytesUsed;
@@ -985,16 +1019,16 @@ bool windows_post_minidump_callback(const wchar_t* dump_path,
strncpy(path, ".dmp", remaining);
}
- llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl;
+ LL_INFOS() << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << LL_ENDL;
// *NOTE:Mani - this code is stolen from LLApp, where its never actually used.
//OSMessageBox("Attach Debugger Now", "Error", OSMB_OK);
// *TODO: Translate the signals/exceptions into cross-platform stuff
// Windows implementation
- llinfos << "Entering Windows Exception Handler..." << llendl;
+ LL_INFOS() << "Entering Windows Exception Handler..." << LL_ENDL;
if (LLApp::isError())
{
- llwarns << "Got another fatal signal while in the error handler, die now!" << llendl;
+ LL_WARNS() << "Got another fatal signal while in the error handler, die now!" << LL_ENDL;
}
// Flag status to error, so thread_error starts its work
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index afa06df23e..d9933b3d36 100755
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -30,8 +30,6 @@
#include <map>
#include "llrun.h"
#include "llsd.h"
-#include "lloptioninterface.h"
-
// Forward declarations
template <typename Type> class LLAtomic32;
typedef LLAtomic32<U32> LLAtomicU32;
@@ -42,7 +40,6 @@ class LLLiveFile;
#endif
typedef void (*LLAppErrorHandler)();
-typedef void (*LLAppChildCallback)(int pid, bool exited, int status);
#if !LL_WINDOWS
extern S32 LL_SMACKDOWN_SIGNAL;
@@ -51,20 +48,13 @@ extern S32 LL_HEARTBEAT_SIGNAL;
// Clear all of the signal handlers (which we want to do for the child process when we fork
void clear_signals();
-class LLChildInfo
-{
-public:
- LLChildInfo() : mGotSigChild(FALSE), mCallback(NULL) {}
- BOOL mGotSigChild;
- LLAppChildCallback mCallback;
-};
#endif
namespace google_breakpad {
class ExceptionHandler; // See exception_handler.h
}
-class LL_COMMON_API LLApp : public LLOptionInterface
+class LL_COMMON_API LLApp
{
friend class LLErrorThread;
public:
@@ -113,7 +103,7 @@ public:
* @param name The name of the option.
* @return Returns the option data.
*/
- virtual LLSD getOption(const std::string& name) const;
+ LLSD getOption(const std::string& name) const;
/**
* @brief Parse command line options and insert them into
@@ -206,10 +196,6 @@ public:
static bool isQuitting();
static bool isError();
static bool isExiting(); // Either quitting or error (app is exiting, cleanly or not)
-#if !LL_WINDOWS
- static U32 getSigChildCount();
- static void incSigChildCount();
-#endif
static int getPid();
/** @name Error handling methods */
@@ -227,7 +213,7 @@ public:
* DO NOT call this method if your application has specialized
* error handling code.
*/
- void setupErrorHandling();
+ void setupErrorHandling(bool mSecondInstance=false);
void setErrorHandler(LLAppErrorHandler handler);
static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred.
@@ -238,32 +224,16 @@ public:
// change the directory where Breakpad minidump files are written to
void setMiniDumpDir(const std::string &path);
+ void setDebugFileNames(const std::string &path);
// Return the Google Breakpad minidump filename after a crash.
- char *getMiniDumpFilename() { return minidump_path; }
+ char *getMiniDumpFilename() { return mMinidumpPath; }
+ std::string* getStaticDebugFile() { return &mStaticDebugFileName; }
+ std::string* getDynamicDebugFile() { return &mDynamicDebugFileName; }
// Write out a Google Breakpad minidump file.
void writeMiniDump();
-#if !LL_WINDOWS
- //
- // Child process handling (Unix only for now)
- //
- // Set a callback to be run on exit of a child process
- // WARNING! This callback is run from the signal handler due to
- // Linux threading requiring waitpid() to be called from the thread that spawned the process.
- // At some point I will make this more behaved, but I'm not going to fix this right now - djs
- void setChildCallback(pid_t pid, LLAppChildCallback callback);
-
- // The child callback to run if no specific handler is set
- void setDefaultChildCallback(LLAppChildCallback callback);
-
- // Fork and do the proper signal handling/error handling mojo
- // *NOTE: You need to make sure your signal handling callback is
- // correct after you fork, because not all threads are duplicated
- // when you fork!
- pid_t fork();
-#endif
/**
* @brief Get a reference to the application runner
@@ -286,13 +256,9 @@ protected:
static EAppStatus sStatus; // Reflects current application status
static BOOL sErrorThreadRunning; // Set while the error thread is running
static BOOL sDisableCrashlogger; // Let the OS handle crashes for us.
+ std::wstring mCrashReportPipeStr; //Name of pipe to use for crash reporting.
-#if !LL_WINDOWS
- static LLAtomicU32* sSigChildCount; // Number of SIGCHLDs received.
- typedef std::map<pid_t, LLChildInfo> child_map; // Map key is a PID
- static child_map sChildMap;
- static LLAppChildCallback sDefaultChildCallback;
-#endif
+ std::string mDumpPath; //output path for google breakpad. Dependency workaround.
/**
* @brief This method is called once a frame to do once a frame tasks.
@@ -303,7 +269,10 @@ private:
void startErrorThread();
// Contains the filename of the minidump file after a crash.
- char minidump_path[MAX_MINDUMP_PATH_LENGTH];
+ char mMinidumpPath[MAX_MINDUMP_PATH_LENGTH];
+
+ std::string mStaticDebugFileName;
+ std::string mDynamicDebugFileName;
// *NOTE: On Windows, we need a routine to reset the structured
// exception handler when some evil driver has taken it over for
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp
index b7815b0e35..a548c96002 100755
--- a/indra/llcommon/llapr.cpp
+++ b/indra/llcommon/llapr.cpp
@@ -29,6 +29,7 @@
#include "linden_common.h"
#include "llapr.h"
#include "apr_dso.h"
+#include "llthreadlocalstorage.h"
apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool.
@@ -37,12 +38,15 @@ apr_thread_mutex_t *gCallStacksLogMutexp = NULL;
const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool
+bool gAPRInitialized = false;
+
void ll_init_apr()
{
+ // Initialize APR and create the global pool
+ apr_initialize();
+
if (!gAPRPoolp)
{
- // Initialize APR and create the global pool
- apr_initialize();
apr_pool_create(&gAPRPoolp, NULL);
// Initialize the logging mutex
@@ -54,11 +58,21 @@ void ll_init_apr()
{
LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;
}
+
+ LLThreadLocalPointerBase::initAllThreadLocalStorage();
+ gAPRInitialized = true;
}
+bool ll_apr_is_initialized()
+{
+ return gAPRInitialized;
+}
+
void ll_cleanup_apr()
{
+ gAPRInitialized = false;
+
LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
if (gLogMutexp)
@@ -77,6 +91,9 @@ void ll_cleanup_apr()
apr_thread_mutex_destroy(gCallStacksLogMutexp);
gCallStacksLogMutexp = NULL;
}
+
+ LLThreadLocalPointerBase::destroyAllThreadLocalStorage();
+
if (gAPRPoolp)
{
apr_pool_destroy(gAPRPoolp);
@@ -429,7 +446,7 @@ S32 LLAPRFile::read(void *buf, S32 nbytes)
{
if(!mFile)
{
- llwarns << "apr mFile is removed by somebody else. Can not read." << llendl ;
+ LL_WARNS() << "apr mFile is removed by somebody else. Can not read." << LL_ENDL ;
return 0;
}
@@ -451,7 +468,7 @@ S32 LLAPRFile::write(const void *buf, S32 nbytes)
{
if(!mFile)
{
- llwarns << "apr mFile is removed by somebody else. Can not write." << llendl ;
+ LL_WARNS() << "apr mFile is removed by somebody else. Can not write." << LL_ENDL ;
return 0;
}
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 1fe7d98472..b1b0fc4718 100755
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -32,28 +32,34 @@
#if LL_LINUX || LL_SOLARIS
#include <sys/param.h> // Need PATH_MAX in APR headers...
#endif
-#if LL_WINDOWS
- // Limit Windows API to small and manageable set.
- // If you get undefined symbols, find the appropriate
- // Windows header file and include that in your .cpp file.
- #define WIN32_LEAN_AND_MEAN
- #include <winsock2.h>
- #include <windows.h>
-#endif
#include <boost/noncopyable.hpp>
-
+#include "llwin32headerslean.h"
#include "apr_thread_proc.h"
#include "apr_thread_mutex.h"
#include "apr_getopt.h"
#include "apr_signal.h"
#include "apr_atomic.h"
+
#include "llstring.h"
extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
extern apr_thread_mutex_t* gCallStacksLogMutexp;
struct apr_dso_handle_t;
+/**
+ * @brief Function which appropriately logs error or remains quiet on
+ * APR_SUCCESS.
+ * @return Returns <code>true</code> if status is an error condition.
+ */
+bool LL_COMMON_API ll_apr_warn_status(apr_status_t status);
+/// There's a whole other APR error-message function if you pass a DSO handle.
+bool LL_COMMON_API ll_apr_warn_status(apr_status_t status, apr_dso_handle_t* handle);
+
+void LL_COMMON_API ll_apr_assert_status(apr_status_t status);
+void LL_COMMON_API ll_apr_assert_status(apr_status_t status, apr_dso_handle_t* handle);
+
+extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool
/**
* @brief initialize the common apr constructs -- apr itself, the
@@ -66,6 +72,9 @@ void LL_COMMON_API ll_init_apr();
*/
void LL_COMMON_API ll_cleanup_apr();
+bool LL_COMMON_API ll_apr_is_initialized();
+
+
//
//LL apr_pool
//manage apr_pool_t, destroy allocated apr_pool in the destruction function.
@@ -263,18 +272,5 @@ public:
//*******************************************************************************************************************************
};
-/**
- * @brief Function which appropriately logs error or remains quiet on
- * APR_SUCCESS.
- * @return Returns <code>true</code> if status is an error condition.
- */
-bool LL_COMMON_API ll_apr_warn_status(apr_status_t status);
-/// There's a whole other APR error-message function if you pass a DSO handle.
-bool LL_COMMON_API ll_apr_warn_status(apr_status_t status, apr_dso_handle_t* handle);
-
-void LL_COMMON_API ll_apr_assert_status(apr_status_t status);
-void LL_COMMON_API ll_apr_assert_status(apr_status_t status, apr_dso_handle_t* handle);
-
-extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool
#endif // LL_LLAPR_H
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 69b01731e5..5a95a58d93 100755
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -29,8 +29,6 @@
#include <string>
-#include "stdenums.h" // for EDragAndDropType
-
class LL_COMMON_API LLAssetType
{
public:
diff --git a/indra/llcommon/llassoclist.h b/indra/llcommon/llassoclist.h
deleted file mode 100755
index 2950504155..0000000000
--- a/indra/llcommon/llassoclist.h
+++ /dev/null
@@ -1,296 +0,0 @@
-/**
- * @file llassoclist.h
- * @brief LLAssocList class header file
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLASSOCLIST_H
-#define LL_LLASSOCLIST_H
-
-//------------------------------------------------------------------------
-// LLAssocList is an associative list container class.
-//
-// The implementation is a single linked list.
-// Both index and value objects are stored by value (not reference).
-// If pointer values are specified for index and/or value, this
-// container does NOT assume ownership of the referenced objects,
-// and does NOT delete() them on removal or destruction of the container.
-//
-// Note that operations are generally not optimized, and may of them
-// are O(n) complexity.
-//------------------------------------------------------------------------
-
-#include <iostream>
-
-template<class INDEX_TYPE, class VALUE_TYPE>
-class LLAssocList
-{
-private:
- // internal list node type
- class Node
- {
- public:
- Node(const INDEX_TYPE &index, const VALUE_TYPE &value, Node *next)
- {
- mIndex = index;
- mValue = value;
- mNext = next;
- }
- ~Node() { }
- INDEX_TYPE mIndex;
- VALUE_TYPE mValue;
- Node *mNext;
- };
-
- // head of the linked list
- Node *mHead;
-
-public:
- // Constructor
- LLAssocList()
- {
- mHead = NULL;
- }
-
- // Destructor
- ~LLAssocList()
- {
- removeAll();
- }
-
- // Returns TRUE if list is empty.
- BOOL isEmpty()
- {
- return (mHead == NULL);
- }
-
- // Returns the number of items in the list.
- U32 length()
- {
- U32 count = 0;
- for ( Node *node = mHead;
- node;
- node = node->mNext )
- {
- count++;
- }
- return count;
- }
-
- // Removes item with the specified index.
- BOOL remove( const INDEX_TYPE &index )
- {
- if (!mHead)
- return FALSE;
-
- if (mHead->mIndex == index)
- {
- Node *node = mHead;
- mHead = mHead->mNext;
- delete node;
- return TRUE;
- }
-
- for ( Node *prev = mHead;
- prev->mNext;
- prev = prev->mNext )
- {
- if (prev->mNext->mIndex == index)
- {
- Node *node = prev->mNext;
- prev->mNext = prev->mNext->mNext;
- delete node;
- return TRUE;
- }
- }
- return FALSE;
- }
-
- // Removes all items from the list.
- void removeAll()
- {
- while ( mHead )
- {
- Node *node = mHead;
- mHead = mHead->mNext;
- delete node;
- }
- }
-
- // Adds a new item to the head of the list,
- // removing any existing item with same index.
- void addToHead( const INDEX_TYPE &index, const VALUE_TYPE &value )
- {
- remove(index);
- Node *node = new Node(index, value, mHead);
- mHead = node;
- }
-
- // Adds a new item to the end of the list,
- // removing any existing item with the same index.
- void addToTail( const INDEX_TYPE &index, const VALUE_TYPE &value )
- {
- remove(index);
- Node *node = new Node(index, value, NULL);
- if (!mHead)
- {
- mHead = node;
- return;
- }
- for ( Node *prev=mHead;
- prev;
- prev=prev->mNext )
- {
- if (!prev->mNext)
- {
- prev->mNext=node;
- return;
- }
- }
- }
-
- // Sets the value of a specified index.
- // If index does not exist, a new value will be added only if
- // 'addIfNotFound' is set to TRUE.
- // Returns TRUE if successful.
- BOOL setValue( const INDEX_TYPE &index, const VALUE_TYPE &value, BOOL addIfNotFound=FALSE )
- {
- VALUE_TYPE *valueP = getValue(index);
- if (valueP)
- {
- *valueP = value;
- return TRUE;
- }
- if (!addIfNotFound)
- return FALSE;
- addToTail(index, value);
- return TRUE;
- }
-
- // Sets the ith value in the list.
- // A new value will NOT be addded, if the ith value does not exist.
- // Returns TRUE if successful.
- BOOL setValueAt( U32 i, const VALUE_TYPE &value )
- {
- VALUE_TYPE *valueP = getValueAt(i);
- if (valueP)
- {
- *valueP = value;
- return TRUE;
- }
- return FALSE;
- }
-
- // Returns a pointer to the value for the specified index,
- // or NULL if no item found.
- VALUE_TYPE *getValue( const INDEX_TYPE &index )
- {
- for ( Node *node = mHead;
- node;
- node = node->mNext )
- {
- if (node->mIndex == index)
- return &node->mValue;
- }
- return NULL;
- }
-
- // Returns a pointer to the ith value in the list, or
- // NULL if i is not valid.
- VALUE_TYPE *getValueAt( U32 i )
- {
- U32 count = 0;
- for ( Node *node = mHead;
- node;
- node = node->mNext )
- {
- if (count == i)
- return &node->mValue;
- count++;
- }
- return NULL;
- }
-
- // Returns a pointer to the index for the specified index,
- // or NULL if no item found.
- INDEX_TYPE *getIndex( const INDEX_TYPE &index )
- {
- for ( Node *node = mHead;
- node;
- node = node->mNext )
- {
- if (node->mIndex == index)
- return &node->mIndex;
- }
- return NULL;
- }
-
- // Returns a pointer to the ith index in the list, or
- // NULL if i is not valid.
- INDEX_TYPE *getIndexAt( U32 i )
- {
- U32 count = 0;
- for ( Node *node = mHead;
- node;
- node = node->mNext )
- {
- if (count == i)
- return &node->mIndex;
- count++;
- }
- return NULL;
- }
-
- // Returns a pointer to the value for the specified index,
- // or NULL if no item found.
- VALUE_TYPE *operator[](const INDEX_TYPE &index)
- {
- return getValue(index);
- }
-
- // Returns a pointer to the ith value in the list, or
- // NULL if i is not valid.
- VALUE_TYPE *operator[](U32 i)
- {
- return getValueAt(i);
- }
-
- // Prints the list contents to the specified stream.
- friend std::ostream &operator<<( std::ostream &os, LLAssocList &map )
- {
- os << "{";
- for ( Node *node = map.mHead;
- node;
- node = node->mNext )
- {
- os << "<" << node->mIndex << ", " << node->mValue << ">";
- if (node->mNext)
- os << ", ";
- }
- os << "}";
-
- return os;
- }
-};
-
-#endif // LL_LLASSOCLIST_H
diff --git a/indra/llcommon/llavatarconstants.h b/indra/llcommon/llavatarconstants.h
deleted file mode 100755
index f47f447b45..0000000000
--- a/indra/llcommon/llavatarconstants.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * @file llavatarconstants.h
- * @brief some useful short term constants for Indra
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_AVATAR_CONSTANTS_H
-#define LL_AVATAR_CONSTANTS_H
-
-// If this string is passed to dataserver in AvatarPropertiesUpdate
-// then no change is made to user.profile_web
-const char* const BLACKLIST_PROFILE_WEB_STR = "featureWebProfilesDisabled";
-
-// If profile web pages are feature blacklisted then this URL is
-// shown in the profile instead of the user's set URL
-const char* const BLACKLIST_PROFILE_WEB_URL = "http://secondlife.com/app/webdisabled";
-
-// Maximum number of avatar picks
-const S32 MAX_AVATAR_PICKS = 10;
-
-// For Flags in AvatarPropertiesReply
-const U32 AVATAR_ALLOW_PUBLISH = 0x1 << 0; // whether profile is externally visible or not
-const U32 AVATAR_MATURE_PUBLISH = 0x1 << 1; // profile is "mature"
-const U32 AVATAR_IDENTIFIED = 0x1 << 2; // whether avatar has provided payment info
-const U32 AVATAR_TRANSACTED = 0x1 << 3; // whether avatar has actively used payment info
-const U32 AVATAR_ONLINE = 0x1 << 4; // the online status of this avatar, if known.
-const U32 AVATAR_AGEVERIFIED = 0x1 << 5; // whether avatar has been age-verified
-
-char const* const VISIBILITY_DEFAULT = "default";
-char const* const VISIBILITY_HIDDEN = "hidden";
-char const* const VISIBILITY_VISIBLE = "visible";
-char const* const VISIBILITY_INVISIBLE = "invisible";
-
-#endif
-
diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp
deleted file mode 100755
index d12f157910..0000000000
--- a/indra/llcommon/llavatarname.cpp
+++ /dev/null
@@ -1,254 +0,0 @@
-/**
- * @file llavatarname.cpp
- * @brief Represents name-related data for an avatar, such as the
- * username/SLID ("bobsmith123" or "james.linden") and the display
- * name ("James Cook")
- *
- * $LicenseInfo:firstyear=2010&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-#include "linden_common.h"
-
-#include "llavatarname.h"
-
-#include "lldate.h"
-#include "llframetimer.h"
-#include "llsd.h"
-
-// Store these in pre-built std::strings to avoid memory allocations in
-// LLSD map lookups
-static const std::string USERNAME("username");
-static const std::string DISPLAY_NAME("display_name");
-static const std::string LEGACY_FIRST_NAME("legacy_first_name");
-static const std::string LEGACY_LAST_NAME("legacy_last_name");
-static const std::string IS_DISPLAY_NAME_DEFAULT("is_display_name_default");
-static const std::string DISPLAY_NAME_EXPIRES("display_name_expires");
-static const std::string DISPLAY_NAME_NEXT_UPDATE("display_name_next_update");
-
-bool LLAvatarName::sUseDisplayNames = true;
-bool LLAvatarName::sUseUsernames = true;
-
-// Minimum time-to-live (in seconds) for a name entry.
-// Avatar name should always guarantee to expire reasonably soon by default
-// so if the failure to get a valid expiration time was due to something temporary
-// we will eventually request and get the right data.
-const F64 MIN_ENTRY_LIFETIME = 60.0;
-
-LLAvatarName::LLAvatarName()
-: mUsername(),
- mDisplayName(),
- mLegacyFirstName(),
- mLegacyLastName(),
- mIsDisplayNameDefault(false),
- mIsTemporaryName(false),
- mExpires(F64_MAX),
- mNextUpdate(0.0)
-{ }
-
-bool LLAvatarName::operator<(const LLAvatarName& rhs) const
-{
- if (mUsername == rhs.mUsername)
- return mDisplayName < rhs.mDisplayName;
- else
- return mUsername < rhs.mUsername;
-}
-
-//static
-void LLAvatarName::setUseDisplayNames(bool use)
-{
- sUseDisplayNames = use;
-}
-//static
-bool LLAvatarName::useDisplayNames()
-{
- return sUseDisplayNames;
-}
-
-void LLAvatarName::setUseUsernames(bool use)
-{
- sUseUsernames = use;
-}
-
-bool LLAvatarName::useUsernames()
-{
- return sUseUsernames;
-}
-
-LLSD LLAvatarName::asLLSD() const
-{
- LLSD sd;
- sd[USERNAME] = mUsername;
- sd[DISPLAY_NAME] = mDisplayName;
- sd[LEGACY_FIRST_NAME] = mLegacyFirstName;
- sd[LEGACY_LAST_NAME] = mLegacyLastName;
- sd[IS_DISPLAY_NAME_DEFAULT] = mIsDisplayNameDefault;
- sd[DISPLAY_NAME_EXPIRES] = LLDate(mExpires);
- sd[DISPLAY_NAME_NEXT_UPDATE] = LLDate(mNextUpdate);
- return sd;
-}
-
-void LLAvatarName::fromLLSD(const LLSD& sd)
-{
- mUsername = sd[USERNAME].asString();
- mDisplayName = sd[DISPLAY_NAME].asString();
- mLegacyFirstName = sd[LEGACY_FIRST_NAME].asString();
- mLegacyLastName = sd[LEGACY_LAST_NAME].asString();
- mIsDisplayNameDefault = sd[IS_DISPLAY_NAME_DEFAULT].asBoolean();
- LLDate expires = sd[DISPLAY_NAME_EXPIRES];
- mExpires = expires.secondsSinceEpoch();
- LLDate next_update = sd[DISPLAY_NAME_NEXT_UPDATE];
- mNextUpdate = next_update.secondsSinceEpoch();
-
- // Some avatars don't have explicit display names set. Force a legible display name here.
- if (mDisplayName.empty())
- {
- mDisplayName = mUsername;
- }
-}
-
-// Transform a string (typically provided by the legacy service) into a decent
-// avatar name instance.
-void LLAvatarName::fromString(const std::string& full_name)
-{
- mDisplayName = full_name;
- std::string::size_type index = full_name.find(' ');
- if (index != std::string::npos)
- {
- // The name is in 2 parts (first last)
- mLegacyFirstName = full_name.substr(0, index);
- mLegacyLastName = full_name.substr(index+1);
- if (mLegacyLastName != "Resident")
- {
- mUsername = mLegacyFirstName + "." + mLegacyLastName;
- mDisplayName = full_name;
- LLStringUtil::toLower(mUsername);
- }
- else
- {
- // Very old names do have a dummy "Resident" last name
- // that we choose to hide from users.
- mUsername = mLegacyFirstName;
- mDisplayName = mLegacyFirstName;
- }
- }
- else
- {
- mLegacyFirstName = full_name;
- mLegacyLastName = "";
- mUsername = full_name;
- mDisplayName = full_name;
- }
- mIsDisplayNameDefault = true;
- mIsTemporaryName = true;
- setExpires(MIN_ENTRY_LIFETIME);
-}
-
-void LLAvatarName::setExpires(F64 expires)
-{
- mExpires = LLFrameTimer::getTotalSeconds() + expires;
-}
-
-std::string LLAvatarName::getCompleteName() const
-{
- std::string name;
- if (sUseDisplayNames)
- {
- if (mUsername.empty() || mIsDisplayNameDefault)
- {
- // If this particular display name is defaulted (i.e. based on user name),
- // then display only the easier to read instance of the person's name.
- name = mDisplayName;
- }
- else
- {
- name = mDisplayName;
- if(sUseUsernames)
- {
- name += " (" + mUsername + ")";
- }
- }
- }
- else
- {
- name = getUserName();
- }
- return name;
-}
-
-std::string LLAvatarName::getLegacyName() const
-{
- if (mLegacyFirstName.empty() && mLegacyLastName.empty()) // display names disabled?
- {
- return mDisplayName;
- }
-
- std::string name;
- name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() );
- name = mLegacyFirstName;
- name += " ";
- name += mLegacyLastName;
- return name;
-}
-
-std::string LLAvatarName::getDisplayName() const
-{
- if (sUseDisplayNames)
- {
- return mDisplayName;
- }
- else
- {
- return getUserName();
- }
-}
-
-std::string LLAvatarName::getUserName() const
-{
- std::string name;
- if (mLegacyLastName.empty() || (mLegacyLastName == "Resident"))
- {
- if (mLegacyFirstName.empty())
- {
- // If we cannot create a user name from the legacy strings, use the display name
- name = mDisplayName;
- }
- else
- {
- // The last name might be empty if it defaulted to "Resident"
- name = mLegacyFirstName;
- }
- }
- else
- {
- name = mLegacyFirstName + " " + mLegacyLastName;
- }
- return name;
-}
-
-void LLAvatarName::dump() const
-{
- LL_DEBUGS("AvNameCache") << "LLAvatarName: "
- << "user '" << mUsername << "' "
- << "display '" << mDisplayName << "' "
- << "expires in " << mExpires - LLFrameTimer::getTotalSeconds() << " seconds"
- << LL_ENDL;
-}
-
diff --git a/indra/llcommon/llavatarname.h b/indra/llcommon/llavatarname.h
deleted file mode 100755
index 1cb3ae421f..0000000000
--- a/indra/llcommon/llavatarname.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/**
- * @file llavatarname.h
- * @brief Represents name-related data for an avatar, such as the
- * username/SLID ("bobsmith123" or "james.linden") and the display
- * name ("James Cook")
- *
- * $LicenseInfo:firstyear=2010&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-#ifndef LLAVATARNAME_H
-#define LLAVATARNAME_H
-
-#include <string>
-
-class LLSD;
-
-class LL_COMMON_API LLAvatarName
-{
-public:
- LLAvatarName();
-
- bool operator<(const LLAvatarName& rhs) const;
-
- // Conversion to and from LLSD (cache file or server response)
- LLSD asLLSD() const;
- void fromLLSD(const LLSD& sd);
-
- // Used only in legacy mode when the display name capability is not provided server side
- // or to otherwise create a temporary valid item.
- void fromString(const std::string& full_name);
-
- // Set the name object to become invalid in "expires" seconds from now
- void setExpires(F64 expires);
-
- // Set and get the display name flag set by the user in preferences.
- static void setUseDisplayNames(bool use);
- static bool useDisplayNames();
-
- static void setUseUsernames(bool use);
- static bool useUsernames();
-
- // A name object is valid if not temporary and not yet expired (default is expiration not checked)
- bool isValidName(F64 max_unrefreshed = 0.0f) const { return !mIsTemporaryName && (mExpires >= max_unrefreshed); }
-
- // Return true if the name is made up from legacy or temporary data
- bool isDisplayNameDefault() const { return mIsDisplayNameDefault; }
-
- // For normal names, returns "James Linden (james.linden)"
- // When display names are disabled returns just "James Linden"
- std::string getCompleteName() const;
-
- // Returns "James Linden" or "bobsmith123 Resident" for backwards
- // compatibility with systems like voice and muting
- // *TODO: Eliminate this in favor of username only
- std::string getLegacyName() const;
-
- // "José Sanchez" or "James Linden", UTF-8 encoded Unicode
- // Takes the display name preference into account. This is truly the name that should
- // be used for all UI where an avatar name has to be used unless we truly want something else (rare)
- std::string getDisplayName() const;
-
- // Returns "James Linden" or "bobsmith123 Resident"
- // Used where we explicitely prefer or need a non UTF-8 legacy (ASCII) name
- // Also used for backwards compatibility with systems like voice and muting
- std::string getUserName() const;
-
- // Returns "james.linden" or the legacy name for very old names
- std::string getAccountName() const { return mUsername; }
-
- // Debug print of the object
- void dump() const;
-
- // Names can change, so need to keep track of when name was
- // last checked.
- // Unix time-from-epoch seconds for efficiency
- F64 mExpires;
-
- // You can only change your name every N hours, so record
- // when the next update is allowed
- // Unix time-from-epoch seconds
- F64 mNextUpdate;
-
-private:
- // "bobsmith123" or "james.linden", US-ASCII only
- std::string mUsername;
-
- // "José Sanchez" or "James Linden", UTF-8 encoded Unicode
- // Contains data whether or not user has explicitly set
- // a display name; may duplicate their username.
- std::string mDisplayName;
-
- // For "James Linden", "James"
- // For "bobsmith123", "bobsmith123"
- // Used to communicate with legacy systems like voice and muting which
- // rely on old-style names.
- // *TODO: Eliminate this in favor of username only
- std::string mLegacyFirstName;
-
- // For "James Linden", "Linden"
- // For "bobsmith123", "Resident"
- // see above for rationale
- std::string mLegacyLastName;
-
- // If true, both display name and SLID were generated from
- // a legacy first and last name, like "James Linden (james.linden)"
- bool mIsDisplayNameDefault;
-
- // Under error conditions, we may insert "dummy" records with
- // names like "???" into caches as placeholders. These can be
- // shown in UI, but are not serialized.
- bool mIsTemporaryName;
-
- // Global flag indicating if display name should be used or not
- // This will affect the output of the high level "get" methods
- static bool sUseDisplayNames;
-
- // Flag indicating if username should be shown after display name or not
- static bool sUseUsernames;
-};
-
-#endif
diff --git a/indra/llcommon/llbase32.cpp b/indra/llcommon/llbase32.cpp
index 053ac0d32f..349567c90b 100755
--- a/indra/llcommon/llbase32.cpp
+++ b/indra/llcommon/llbase32.cpp
@@ -231,8 +231,8 @@ std::string LLBase32::encode(const U8* input, size_t input_size)
size_t encoded = base32_encode(&output[0], output_size, input, input_size);
- llinfos << "encoded " << encoded << " into buffer of size "
- << output_size << llendl;
+ LL_INFOS() << "encoded " << encoded << " into buffer of size "
+ << output_size << LL_ENDL;
}
return output;
}
diff --git a/indra/llcommon/bitpack.cpp b/indra/llcommon/llbitpack.cpp
index cdcaba0765..622a099945 100755
--- a/indra/llcommon/bitpack.cpp
+++ b/indra/llcommon/llbitpack.cpp
@@ -27,4 +27,4 @@
#include "linden_common.h"
// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes.
-#include "bitpack.h"
+#include "llbitpack.h"
diff --git a/indra/llcommon/bitpack.h b/indra/llcommon/llbitpack.h
index 037300dd14..f99a354cd4 100755
--- a/indra/llcommon/bitpack.h
+++ b/indra/llcommon/llbitpack.h
@@ -1,5 +1,5 @@
/**
- * @file bitpack.h
+ * @file llbitpack.h
* @brief Convert data to packed bit stream
*
* $LicenseInfo:firstyear=2000&license=viewerlgpl$
@@ -79,7 +79,7 @@ public:
*(mBuffer + mBufferSize++) = mLoad;
if (mBufferSize > mMaxSize)
{
- llerror("mBufferSize exceeding mMaxSize!", 0);
+ LL_ERRS() << "mBufferSize exceeding mMaxSize!" << LL_ENDL;
}
mLoadSize = 0;
mLoad = 0x00;
@@ -122,7 +122,7 @@ public:
*(mBuffer + mBufferSize++) = mLoad;
if (mBufferSize > mMaxSize)
{
- llerror("mBufferSize exceeding mMaxSize!", 0);
+ LL_ERRS() << "mBufferSize exceeding mMaxSize!" << LL_ENDL;
}
mLoadSize = 0;
mLoad = 0x00;
@@ -165,8 +165,8 @@ public:
#ifdef _DEBUG
if (mBufferSize > mMaxSize)
{
- llerrs << "mBufferSize exceeding mMaxSize" << llendl;
- llerrs << mBufferSize << " > " << mMaxSize << llendl;
+ LL_ERRS() << "mBufferSize exceeding mMaxSize" << LL_ENDL;
+ LL_ERRS() << mBufferSize << " > " << mMaxSize << LL_ENDL;
}
#endif
mLoad = *(mBuffer + mBufferSize++);
@@ -190,7 +190,7 @@ public:
*(mBuffer + mBufferSize++) = mLoad;
if (mBufferSize > mMaxSize)
{
- llerror("mBufferSize exceeding mMaxSize!", 0);
+ LL_ERRS() << "mBufferSize exceeding mMaxSize!" << LL_ENDL;
}
mLoadSize = 0;
}
diff --git a/indra/llcommon/llchat.h b/indra/llcommon/llchat.h
deleted file mode 100755
index f5b242fdfc..0000000000
--- a/indra/llcommon/llchat.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/**
- * @file llchat.h
- * @author James Cook
- * @brief Chat constants and data structures.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLCHAT_H
-#define LL_LLCHAT_H
-
-#include "lluuid.h"
-#include "v3math.h"
-
-// enumerations used by the chat system
-typedef enum e_chat_source_type
-{
- CHAT_SOURCE_SYSTEM = 0,
- CHAT_SOURCE_AGENT = 1,
- CHAT_SOURCE_OBJECT = 2,
- CHAT_SOURCE_UNKNOWN = 3
-} EChatSourceType;
-
-typedef enum e_chat_type
-{
- CHAT_TYPE_WHISPER = 0,
- CHAT_TYPE_NORMAL = 1,
- CHAT_TYPE_SHOUT = 2,
- CHAT_TYPE_START = 4,
- CHAT_TYPE_STOP = 5,
- CHAT_TYPE_DEBUG_MSG = 6,
- CHAT_TYPE_REGION = 7,
- CHAT_TYPE_OWNER = 8,
- CHAT_TYPE_DIRECT = 9 // From llRegionSayTo()
-} EChatType;
-
-typedef enum e_chat_audible_level
-{
- CHAT_AUDIBLE_NOT = -1,
- CHAT_AUDIBLE_BARELY = 0,
- CHAT_AUDIBLE_FULLY = 1
-} EChatAudible;
-
-typedef enum e_chat_style
-{
- CHAT_STYLE_NORMAL,
- CHAT_STYLE_IRC,
- CHAT_STYLE_HISTORY
-}EChatStyle;
-
-// A piece of chat
-class LLChat
-{
-public:
- LLChat(const std::string& text = std::string())
- : mText(text),
- mFromName(),
- mFromID(),
- mNotifId(),
- mOwnerID(),
- mSourceType(CHAT_SOURCE_AGENT),
- mChatType(CHAT_TYPE_NORMAL),
- mAudible(CHAT_AUDIBLE_FULLY),
- mMuted(FALSE),
- mTime(0.0),
- mTimeStr(),
- mPosAgent(),
- mURL(),
- mChatStyle(CHAT_STYLE_NORMAL),
- mSessionID()
- { }
-
- std::string mText; // UTF-8 line of text
- std::string mFromName; // agent or object name
- LLUUID mFromID; // agent id or object id
- LLUUID mNotifId;
- LLUUID mOwnerID;
- EChatSourceType mSourceType;
- EChatType mChatType;
- EChatAudible mAudible;
- BOOL mMuted; // pass muted chat to maintain list of chatters
- F64 mTime; // viewer only, seconds from viewer start
- std::string mTimeStr;
- LLVector3 mPosAgent;
- std::string mURL;
- EChatStyle mChatStyle;
- LLUUID mSessionID;
-};
-
-#endif
diff --git a/indra/llcommon/llclickaction.h b/indra/llcommon/llclickaction.h
index 1f87d8eec3..2f83113af9 100755..100644
--- a/indra/llcommon/llclickaction.h
+++ b/indra/llcommon/llclickaction.h
@@ -27,15 +27,4 @@
#ifndef LL_LLCLICKACTION_H
#define LL_LLCLICKACTION_H
-// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
-const U8 CLICK_ACTION_NONE = 0;
-const U8 CLICK_ACTION_TOUCH = 0;
-const U8 CLICK_ACTION_SIT = 1;
-const U8 CLICK_ACTION_BUY = 2;
-const U8 CLICK_ACTION_PAY = 3;
-const U8 CLICK_ACTION_OPEN = 4;
-const U8 CLICK_ACTION_PLAY = 5;
-const U8 CLICK_ACTION_OPEN_MEDIA = 6;
-const U8 CLICK_ACTION_ZOOM = 7;
-// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
#endif
diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index b938b0e65a..19642b0982 100755
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -29,10 +29,14 @@
#include "llmemory.h"
#include "llthread.h"
+#include "lltrace.h"
+#include "lltracethreadrecorder.h"
//static
BOOL LLCommon::sAprInitialized = FALSE;
+static LLTrace::ThreadRecorder* sMasterThreadRecorder = NULL;
+
//static
void LLCommon::initClass()
{
@@ -45,15 +49,19 @@ void LLCommon::initClass()
LLTimer::initClass();
LLThreadSafeRefCount::initThreadSafeRefCount();
assert_main_thread(); // Make sure we record the main thread
-// LLWorkerThread::initClass();
-// LLFrameCallbackManager::initClass();
+ if (!sMasterThreadRecorder)
+ {
+ sMasterThreadRecorder = new LLTrace::ThreadRecorder();
+ LLTrace::set_master_thread_recorder(sMasterThreadRecorder);
+ }
}
//static
void LLCommon::cleanupClass()
{
-// LLFrameCallbackManager::cleanupClass();
-// LLWorkerThread::cleanupClass();
+ delete sMasterThreadRecorder;
+ sMasterThreadRecorder = NULL;
+ LLTrace::set_master_thread_recorder(NULL);
LLThreadSafeRefCount::cleanupThreadSafeRefCount();
LLTimer::cleanupClass();
if (sAprInitialized)
diff --git a/indra/llcommon/llcommonutils.h b/indra/llcommon/llcommonutils.h
index 755dc41fb4..20ada27830 100755
--- a/indra/llcommon/llcommonutils.h
+++ b/indra/llcommon/llcommonutils.h
@@ -27,6 +27,8 @@
#ifndef LL_LLCOMMONUTILS_H
#define LL_LLCOMMONUTILS_H
+#include "lluuid.h"
+
namespace LLCommonUtils
{
/**
diff --git a/indra/llcommon/llcrc.cpp b/indra/llcommon/llcrc.cpp
index e80da0bb0d..626bb1e564 100755
--- a/indra/llcommon/llcrc.cpp
+++ b/indra/llcommon/llcrc.cpp
@@ -162,7 +162,7 @@ void LLCRC::update(const std::string& filename)
{
if (filename.empty())
{
- llerrs << "No filename specified" << llendl;
+ LL_ERRS() << "No filename specified" << LL_ENDL;
return;
}
@@ -185,7 +185,7 @@ void LLCRC::update(const std::string& filename)
if (nread < (size_t) size)
{
- llwarns << "Short read on " << filename << llendl;
+ LL_WARNS() << "Short read on " << filename << LL_ENDL;
}
update(data, nread);
diff --git a/indra/llcommon/llcrc.h b/indra/llcommon/llcrc.h
index 2d291d92a1..3f41b28ffa 100755
--- a/indra/llcommon/llcrc.h
+++ b/indra/llcommon/llcrc.h
@@ -41,7 +41,7 @@
// crc.update(fgetc(fp));
// }
// fclose(fp);
-// llinfos << "File crc: " << crc.getCRC() << llendl;
+// LL_INFOS() << "File crc: " << crc.getCRC() << LL_ENDL;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LL_COMMON_API LLCRC
diff --git a/indra/llcommon/llcriticaldamp.cpp b/indra/llcommon/llcriticaldamp.cpp
index 49aac9ce75..54be855f67 100755
--- a/indra/llcommon/llcriticaldamp.cpp
+++ b/indra/llcommon/llcriticaldamp.cpp
@@ -27,18 +27,38 @@
#include "linden_common.h"
#include "llcriticaldamp.h"
+#include <algorithm>
//-----------------------------------------------------------------------------
// static members
//-----------------------------------------------------------------------------
-LLFrameTimer LLCriticalDamp::sInternalTimer;
-std::map<F32, F32> LLCriticalDamp::sInterpolants;
-F32 LLCriticalDamp::sTimeDelta;
+LLFrameTimer LLSmoothInterpolation::sInternalTimer;
+std::vector<LLSmoothInterpolation::Interpolant> LLSmoothInterpolation::sInterpolants;
+F32 LLSmoothInterpolation::sTimeDelta;
+
+// helper functors
+struct LLSmoothInterpolation::CompareTimeConstants
+{
+ bool operator()(const F32& a, const LLSmoothInterpolation::Interpolant& b) const
+ {
+ return a < b.mTimeScale;
+ }
+
+ bool operator()(const LLSmoothInterpolation::Interpolant& a, const F32& b) const
+ {
+ return a.mTimeScale < b; // bottom of a is higher than bottom of b
+ }
+
+ bool operator()(const LLSmoothInterpolation::Interpolant& a, const LLSmoothInterpolation::Interpolant& b) const
+ {
+ return a.mTimeScale < b.mTimeScale; // bottom of a is higher than bottom of b
+ }
+};
//-----------------------------------------------------------------------------
-// LLCriticalDamp()
+// LLSmoothInterpolation()
//-----------------------------------------------------------------------------
-LLCriticalDamp::LLCriticalDamp()
+LLSmoothInterpolation::LLSmoothInterpolation()
{
sTimeDelta = 0.f;
}
@@ -47,44 +67,55 @@ LLCriticalDamp::LLCriticalDamp()
//-----------------------------------------------------------------------------
// updateInterpolants()
//-----------------------------------------------------------------------------
-void LLCriticalDamp::updateInterpolants()
+void LLSmoothInterpolation::updateInterpolants()
{
sTimeDelta = sInternalTimer.getElapsedTimeAndResetF32();
- F32 time_constant;
-
- for (std::map<F32, F32>::iterator iter = sInterpolants.begin();
- iter != sInterpolants.end(); iter++)
+ for (S32 i = 0; i < sInterpolants.size(); i++)
{
- time_constant = iter->first;
- F32 new_interpolant = 1.f - pow(2.f, -sTimeDelta / time_constant);
- new_interpolant = llclamp(new_interpolant, 0.f, 1.f);
- sInterpolants[time_constant] = new_interpolant;
+ Interpolant& interp = sInterpolants[i];
+ interp.mInterpolant = calcInterpolant(interp.mTimeScale);
}
}
//-----------------------------------------------------------------------------
// getInterpolant()
//-----------------------------------------------------------------------------
-F32 LLCriticalDamp::getInterpolant(const F32 time_constant, BOOL use_cache)
+F32 LLSmoothInterpolation::getInterpolant(F32SecondsImplicit time_constant, bool use_cache)
{
if (time_constant == 0.f)
{
return 1.f;
}
- if (use_cache && sInterpolants.count(time_constant))
+ if (use_cache)
{
- return sInterpolants[time_constant];
+ interpolant_vec_t::iterator find_it = std::lower_bound(sInterpolants.begin(), sInterpolants.end(), time_constant.value(), CompareTimeConstants());
+ if (find_it != sInterpolants.end() && find_it->mTimeScale == time_constant)
+ {
+ return find_it->mInterpolant;
+ }
+ else
+ {
+ Interpolant interp;
+ interp.mTimeScale = time_constant.value();
+ interp.mInterpolant = calcInterpolant(time_constant.value());
+ sInterpolants.insert(find_it, interp);
+ return interp.mInterpolant;
+ }
}
-
- F32 interpolant = 1.f - pow(2.f, -sTimeDelta / time_constant);
- interpolant = llclamp(interpolant, 0.f, 1.f);
- if (use_cache)
+ else
{
- sInterpolants[time_constant] = interpolant;
+ return calcInterpolant(time_constant.value());
+
}
+}
- return interpolant;
+//-----------------------------------------------------------------------------
+// calcInterpolant()
+//-----------------------------------------------------------------------------
+F32 LLSmoothInterpolation::calcInterpolant(F32 time_constant)
+{
+ return llclamp(1.f - powf(2.f, -sTimeDelta / time_constant), 0.f, 1.f);
}
diff --git a/indra/llcommon/llcriticaldamp.h b/indra/llcommon/llcriticaldamp.h
index 52f052ae25..1fb6a1af29 100755
--- a/indra/llcommon/llcriticaldamp.h
+++ b/indra/llcommon/llcriticaldamp.h
@@ -28,26 +28,46 @@
#ifndef LL_LLCRITICALDAMP_H
#define LL_LLCRITICALDAMP_H
-#include <map>
+#include <vector>
#include "llframetimer.h"
+#include "llunits.h"
-class LL_COMMON_API LLCriticalDamp
+class LL_COMMON_API LLSmoothInterpolation
{
public:
- LLCriticalDamp();
+ LLSmoothInterpolation();
// MANIPULATORS
static void updateInterpolants();
// ACCESSORS
- static F32 getInterpolant(const F32 time_constant, BOOL use_cache = TRUE);
+ static F32 getInterpolant(F32SecondsImplicit time_constant, bool use_cache = true);
-protected:
+ template<typename T>
+ static T lerp(T a, T b, F32SecondsImplicit time_constant, bool use_cache = true)
+ {
+ F32 interpolant = getInterpolant(time_constant, use_cache);
+ return ((a * (1.f - interpolant))
+ + (b * interpolant));
+ }
+
+protected:
+ static F32 calcInterpolant(F32 time_constant);
+
+ struct CompareTimeConstants;
static LLFrameTimer sInternalTimer; // frame timer for calculating deltas
- static std::map<F32, F32> sInterpolants;
+ struct Interpolant
+ {
+ F32 mTimeScale;
+ F32 mInterpolant;
+ };
+ typedef std::vector<Interpolant> interpolant_vec_t;
+ static interpolant_vec_t sInterpolants;
static F32 sTimeDelta;
};
+typedef LLSmoothInterpolation LLCriticalDamp;
+
#endif // LL_LLCRITICALDAMP_H
diff --git a/indra/llcommon/llcursortypes.cpp b/indra/llcommon/llcursortypes.cpp
deleted file mode 100755
index ec60097195..0000000000
--- a/indra/llcommon/llcursortypes.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * @file llcursortypes.cpp
- * @brief Cursor types and lookup of types from a string
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llcursortypes.h"
-
-ECursorType getCursorFromString(const std::string& cursor_string)
-{
- static std::map<std::string,U32> cursor_string_table;
- if (cursor_string_table.empty())
- {
- cursor_string_table["UI_CURSOR_ARROW"] = UI_CURSOR_ARROW;
- cursor_string_table["UI_CURSOR_WAIT"] = UI_CURSOR_WAIT;
- cursor_string_table["UI_CURSOR_HAND"] = UI_CURSOR_HAND;
- cursor_string_table["UI_CURSOR_IBEAM"] = UI_CURSOR_IBEAM;
- cursor_string_table["UI_CURSOR_CROSS"] = UI_CURSOR_CROSS;
- cursor_string_table["UI_CURSOR_SIZENWSE"] = UI_CURSOR_SIZENWSE;
- cursor_string_table["UI_CURSOR_SIZENESW"] = UI_CURSOR_SIZENESW;
- cursor_string_table["UI_CURSOR_SIZEWE"] = UI_CURSOR_SIZEWE;
- cursor_string_table["UI_CURSOR_SIZENS"] = UI_CURSOR_SIZENS;
- cursor_string_table["UI_CURSOR_NO"] = UI_CURSOR_NO;
- cursor_string_table["UI_CURSOR_WORKING"] = UI_CURSOR_WORKING;
- cursor_string_table["UI_CURSOR_TOOLGRAB"] = UI_CURSOR_TOOLGRAB;
- cursor_string_table["UI_CURSOR_TOOLLAND"] = UI_CURSOR_TOOLLAND;
- cursor_string_table["UI_CURSOR_TOOLFOCUS"] = UI_CURSOR_TOOLFOCUS;
- cursor_string_table["UI_CURSOR_TOOLCREATE"] = UI_CURSOR_TOOLCREATE;
- cursor_string_table["UI_CURSOR_ARROWDRAG"] = UI_CURSOR_ARROWDRAG;
- cursor_string_table["UI_CURSOR_ARROWCOPY"] = UI_CURSOR_ARROWCOPY;
- cursor_string_table["UI_CURSOR_ARROWDRAGMULTI"] = UI_CURSOR_ARROWDRAGMULTI;
- cursor_string_table["UI_CURSOR_ARROWCOPYMULTI"] = UI_CURSOR_ARROWCOPYMULTI;
- cursor_string_table["UI_CURSOR_NOLOCKED"] = UI_CURSOR_NOLOCKED;
- cursor_string_table["UI_CURSOR_ARROWLOCKED"] = UI_CURSOR_ARROWLOCKED;
- cursor_string_table["UI_CURSOR_GRABLOCKED"] = UI_CURSOR_GRABLOCKED;
- cursor_string_table["UI_CURSOR_TOOLTRANSLATE"] = UI_CURSOR_TOOLTRANSLATE;
- cursor_string_table["UI_CURSOR_TOOLROTATE"] = UI_CURSOR_TOOLROTATE;
- cursor_string_table["UI_CURSOR_TOOLSCALE"] = UI_CURSOR_TOOLSCALE;
- cursor_string_table["UI_CURSOR_TOOLCAMERA"] = UI_CURSOR_TOOLCAMERA;
- cursor_string_table["UI_CURSOR_TOOLPAN"] = UI_CURSOR_TOOLPAN;
- cursor_string_table["UI_CURSOR_TOOLZOOMIN"] = UI_CURSOR_TOOLZOOMIN;
- cursor_string_table["UI_CURSOR_TOOLPICKOBJECT3"] = UI_CURSOR_TOOLPICKOBJECT3;
- cursor_string_table["UI_CURSOR_TOOLPLAY"] = UI_CURSOR_TOOLPLAY;
- cursor_string_table["UI_CURSOR_TOOLPAUSE"] = UI_CURSOR_TOOLPAUSE;
- cursor_string_table["UI_CURSOR_TOOLMEDIAOPEN"] = UI_CURSOR_TOOLMEDIAOPEN;
- cursor_string_table["UI_CURSOR_PIPETTE"] = UI_CURSOR_PIPETTE;
- cursor_string_table["UI_CURSOR_TOOLSIT"] = UI_CURSOR_TOOLSIT;
- cursor_string_table["UI_CURSOR_TOOLBUY"] = UI_CURSOR_TOOLBUY;
- cursor_string_table["UI_CURSOR_TOOLOPEN"] = UI_CURSOR_TOOLOPEN;
- cursor_string_table["UI_CURSOR_TOOLPATHFINDING"] = UI_CURSOR_TOOLPATHFINDING;
- cursor_string_table["UI_CURSOR_TOOLPATHFINDINGPATHSTART"] = UI_CURSOR_TOOLPATHFINDING_PATH_START;
- cursor_string_table["UI_CURSOR_TOOLPATHFINDINGPATHSTARTADD"] = UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD;
- cursor_string_table["UI_CURSOR_TOOLPATHFINDINGPATHEND"] = UI_CURSOR_TOOLPATHFINDING_PATH_END;
- cursor_string_table["UI_CURSOR_TOOLPATHFINDINGPATHENDADD"] = UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD;
- cursor_string_table["UI_CURSOR_TOOLNO"] = UI_CURSOR_TOOLNO;
- }
-
- std::map<std::string,U32>::const_iterator iter = cursor_string_table.find(cursor_string);
-
- if (iter != cursor_string_table.end())
- {
- return (ECursorType)iter->second;
- }
-
- return UI_CURSOR_ARROW;
-}
-
-
-
diff --git a/indra/llcommon/llcursortypes.h b/indra/llcommon/llcursortypes.h
deleted file mode 100755
index cb6d6636a0..0000000000
--- a/indra/llcommon/llcursortypes.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/**
- * @file llcursortypes.h
- * @brief Cursor types
- *
- * $LicenseInfo:firstyear=2008&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLCURSORTYPES_H
-#define LL_LLCURSORTYPES_H
-
-// If you add types here, add them in LLCursor::getCursorFromString
-enum ECursorType {
- UI_CURSOR_ARROW,
- UI_CURSOR_WAIT,
- UI_CURSOR_HAND,
- UI_CURSOR_IBEAM,
- UI_CURSOR_CROSS,
- UI_CURSOR_SIZENWSE,
- UI_CURSOR_SIZENESW,
- UI_CURSOR_SIZEWE,
- UI_CURSOR_SIZENS,
- UI_CURSOR_NO,
- UI_CURSOR_WORKING,
- UI_CURSOR_TOOLGRAB,
- UI_CURSOR_TOOLLAND,
- UI_CURSOR_TOOLFOCUS,
- UI_CURSOR_TOOLCREATE,
- UI_CURSOR_ARROWDRAG,
- UI_CURSOR_ARROWCOPY, // drag with copy
- UI_CURSOR_ARROWDRAGMULTI,
- UI_CURSOR_ARROWCOPYMULTI, // drag with copy
- UI_CURSOR_NOLOCKED,
- UI_CURSOR_ARROWLOCKED,
- UI_CURSOR_GRABLOCKED,
- UI_CURSOR_TOOLTRANSLATE,
- UI_CURSOR_TOOLROTATE,
- UI_CURSOR_TOOLSCALE,
- UI_CURSOR_TOOLCAMERA,
- UI_CURSOR_TOOLPAN,
- UI_CURSOR_TOOLZOOMIN,
- UI_CURSOR_TOOLPICKOBJECT3,
- UI_CURSOR_TOOLPLAY,
- UI_CURSOR_TOOLPAUSE,
- UI_CURSOR_TOOLMEDIAOPEN,
- UI_CURSOR_PIPETTE,
- UI_CURSOR_TOOLSIT,
- UI_CURSOR_TOOLBUY,
- UI_CURSOR_TOOLOPEN,
- UI_CURSOR_TOOLPATHFINDING,
- UI_CURSOR_TOOLPATHFINDING_PATH_START,
- UI_CURSOR_TOOLPATHFINDING_PATH_START_ADD,
- UI_CURSOR_TOOLPATHFINDING_PATH_END,
- UI_CURSOR_TOOLPATHFINDING_PATH_END_ADD,
- UI_CURSOR_TOOLNO,
- UI_CURSOR_COUNT // Number of elements in this enum (NOT a cursor)
-};
-
-LL_COMMON_API ECursorType getCursorFromString(const std::string& cursor_string);
-
-#endif // LL_LLCURSORTYPES_H
diff --git a/indra/llcommon/lldarray.h b/indra/llcommon/lldarray.h
deleted file mode 100755
index 131b819c99..0000000000
--- a/indra/llcommon/lldarray.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/**
- * @file lldarray.h
- * @brief Wrapped std::vector for backward compatibility.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLDARRAY_H
-#define LL_LLDARRAY_H
-
-#include "llerror.h"
-
-#include <vector>
-#include <map>
-
-// class LLDynamicArray<>; // = std::vector + reserves <BlockSize> elements
-// class LLDynamicArrayIndexed<>; // = std::vector + std::map if indices, only supports operator[] and begin(),end()
-
-//--------------------------------------------------------
-// LLDynamicArray declaration
-//--------------------------------------------------------
-// NOTE: BlockSize is used to reserve a minimal initial amount
-template <typename Type, int BlockSize = 32>
-class LLDynamicArray : public std::vector<Type>
-{
-public:
- enum
- {
- OKAY = 0,
- FAIL = -1
- };
-
- LLDynamicArray(S32 size=0) : std::vector<Type>(size) { if (size < BlockSize) std::vector<Type>::reserve(BlockSize); }
-
- void reset() { std::vector<Type>::clear(); }
-
- // ACCESSORS
- const Type& get(S32 index) const { return std::vector<Type>::operator[](index); }
- Type& get(S32 index) { return std::vector<Type>::operator[](index); }
- S32 find(const Type &obj) const;
-
- S32 count() const { return std::vector<Type>::size(); }
- S32 getLength() const { return std::vector<Type>::size(); }
- S32 getMax() const { return std::vector<Type>::capacity(); }
-
- // MANIPULATE
- S32 put(const Type &obj); // add to end of array, returns index
-// Type* reserve(S32 num); // reserve a block of indices in advance
- Type* reserve_block(U32 num); // reserve a block of indices in advance
-
- S32 remove(S32 index); // remove by index, no bounds checking
- S32 removeObj(const Type &obj); // remove by object
- S32 removeLast();
-
- void operator+=(const LLDynamicArray<Type,BlockSize> &other);
-};
-
-//--------------------------------------------------------
-// LLDynamicArray implementation
-//--------------------------------------------------------
-
-template <typename Type,int BlockSize>
-inline S32 LLDynamicArray<Type,BlockSize>::find(const Type &obj) const
-{
- typename std::vector<Type>::const_iterator iter = std::find(this->begin(), this->end(), obj);
- if (iter != this->end())
- {
- return iter - this->begin();
- }
- return FAIL;
-}
-
-
-template <typename Type,int BlockSize>
-inline S32 LLDynamicArray<Type,BlockSize>::remove(S32 i)
-{
- // This is a fast removal by swapping with the last element
- S32 sz = this->size();
- if (i < 0 || i >= sz)
- {
- return FAIL;
- }
- if (i < sz-1)
- {
- this->operator[](i) = this->back();
- }
- this->pop_back();
- return i;
-}
-
-template <typename Type,int BlockSize>
-inline S32 LLDynamicArray<Type,BlockSize>::removeObj(const Type& obj)
-{
- typename std::vector<Type>::iterator iter = std::find(this->begin(), this->end(), obj);
- if (iter != this->end())
- {
- S32 res = iter - this->begin();
- typename std::vector<Type>::iterator last = this->end();
- --last;
- *iter = *last;
- this->pop_back();
- return res;
- }
- return FAIL;
-}
-
-template <typename Type,int BlockSize>
-inline S32 LLDynamicArray<Type,BlockSize>::removeLast()
-{
- if (!this->empty())
- {
- this->pop_back();
- return OKAY;
- }
- return FAIL;
-}
-
-template <typename Type,int BlockSize>
-inline Type* LLDynamicArray<Type,BlockSize>::reserve_block(U32 num)
-{
- U32 sz = this->size();
- this->resize(sz+num);
- return &(this->operator[](sz));
-}
-
-template <typename Type,int BlockSize>
-inline S32 LLDynamicArray<Type,BlockSize>::put(const Type &obj)
-{
- this->push_back(obj);
- return this->size() - 1;
-}
-
-template <typename Type,int BlockSize>
-inline void LLDynamicArray<Type,BlockSize>::operator+=(const LLDynamicArray<Type,BlockSize> &other)
-{
- insert(this->end(), other.begin(), other.end());
-}
-
-//--------------------------------------------------------
-// LLDynamicArrayIndexed declaration
-//--------------------------------------------------------
-
-template <typename Type, typename Key, int BlockSize = 32>
-class LLDynamicArrayIndexed
-{
-public:
- typedef typename std::vector<Type>::iterator iterator;
- typedef typename std::vector<Type>::const_iterator const_iterator;
- typedef typename std::vector<Type>::reverse_iterator reverse_iterator;
- typedef typename std::vector<Type>::const_reverse_iterator const_reverse_iterator;
- typedef typename std::vector<Type>::size_type size_type;
-protected:
- std::vector<Type> mVector;
- std::map<Key, U32> mIndexMap;
-
-public:
- LLDynamicArrayIndexed() { mVector.reserve(BlockSize); }
-
- iterator begin() { return mVector.begin(); }
- const_iterator begin() const { return mVector.begin(); }
- iterator end() { return mVector.end(); }
- const_iterator end() const { return mVector.end(); }
-
- reverse_iterator rbegin() { return mVector.rbegin(); }
- const_reverse_iterator rbegin() const { return mVector.rbegin(); }
- reverse_iterator rend() { return mVector.rend(); }
- const_reverse_iterator rend() const { return mVector.rend(); }
-
- void reset() { mVector.resize(0); mIndexMap.resize(0); }
- bool empty() const { return mVector.empty(); }
- size_type size() const { return mVector.size(); }
-
- Type& operator[](const Key& k)
- {
- typename std::map<Key, U32>::const_iterator iter = mIndexMap.find(k);
- if (iter == mIndexMap.end())
- {
- U32 n = mVector.size();
- mIndexMap[k] = n;
- mVector.push_back(Type());
- llassert(mVector.size() == mIndexMap.size());
- return mVector[n];
- }
- else
- {
- return mVector[iter->second];
- }
- }
-
- const_iterator find(const Key& k) const
- {
- typename std::map<Key, U32>::const_iterator iter = mIndexMap.find(k);
- if(iter == mIndexMap.end())
- {
- return mVector.end();
- }
- else
- {
- return mVector.begin() + iter->second;
- }
- }
-};
-
-#endif
diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp
index 030ef6a3c7..7a2a0869f4 100755
--- a/indra/llcommon/lldate.cpp
+++ b/indra/llcommon/lldate.cpp
@@ -39,6 +39,7 @@
#include "lltimer.h"
#include "llstring.h"
+#include "llfasttimer.h"
static const F64 DATE_EPOCH = 0.0;
@@ -48,25 +49,22 @@ static const F64 LL_APR_USEC_PER_SEC = 1000000.0;
LLDate::LLDate() : mSecondsSinceEpoch(DATE_EPOCH)
-{
-}
+{}
LLDate::LLDate(const LLDate& date) :
mSecondsSinceEpoch(date.mSecondsSinceEpoch)
-{
-}
+{}
-LLDate::LLDate(F64 seconds_since_epoch) :
- mSecondsSinceEpoch(seconds_since_epoch)
-{
-}
+LLDate::LLDate(F64SecondsImplicit seconds_since_epoch) :
+ mSecondsSinceEpoch(seconds_since_epoch.value())
+{}
LLDate::LLDate(const std::string& iso8601_date)
{
if(!fromString(iso8601_date))
{
- llwarns << "date " << iso8601_date << " failed to parse; "
- << "ZEROING IT OUT" << llendl;
+ LL_WARNS() << "date " << iso8601_date << " failed to parse; "
+ << "ZEROING IT OUT" << LL_ENDL;
mSecondsSinceEpoch = DATE_EPOCH;
}
}
@@ -88,11 +86,11 @@ std::string LLDate::asRFC1123() const
return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT"));
}
-LLFastTimer::DeclareTimer FT_DATE_FORMAT("Date Format");
+LLTrace::BlockTimerStatHandle FT_DATE_FORMAT("Date Format");
std::string LLDate::toHTTPDateString (std::string fmt) const
{
- LLFastTimer ft1(FT_DATE_FORMAT);
+ LL_RECORD_BLOCK_TIME(FT_DATE_FORMAT);
time_t locSeconds = (time_t) mSecondsSinceEpoch;
struct tm * gmt = gmtime (&locSeconds);
@@ -101,7 +99,7 @@ std::string LLDate::toHTTPDateString (std::string fmt) const
std::string LLDate::toHTTPDateString (tm * gmt, std::string fmt)
{
- LLFastTimer ft1(FT_DATE_FORMAT);
+ LL_RECORD_BLOCK_TIME(FT_DATE_FORMAT);
// avoid calling setlocale() unnecessarily - it's expensive.
static std::string prev_locale = "";
diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h
index 7ff8b550ad..be2cd2d051 100755
--- a/indra/llcommon/lldate.h
+++ b/indra/llcommon/lldate.h
@@ -33,6 +33,7 @@
#include <string>
#include "stdtypes.h"
+#include "llunits.h"
/**
* @class LLDate
@@ -56,9 +57,9 @@ public:
/**
* @brief Construct a date from a seconds since epoch value.
*
- * @pararm seconds_since_epoch The number of seconds since UTC epoch.
+ * @param seconds_since_epoch The number of seconds since UTC epoch.
*/
- LLDate(F64 seconds_since_epoch);
+ LLDate(F64SecondsImplicit seconds_since_epoch);
/**
* @brief Construct a date from a string representation
diff --git a/indra/llcommon/lldeadmantimer.cpp b/indra/llcommon/lldeadmantimer.cpp
index 7d9097e344..830443b956 100644
--- a/indra/llcommon/lldeadmantimer.cpp
+++ b/indra/llcommon/lldeadmantimer.cpp
@@ -43,7 +43,7 @@
// true true Not allowed
//
LLDeadmanTimer::LLDeadmanTimer(F64 horizon, bool inc_cpu)
- : mHorizon(time_type(llmax(horizon, F64(0.0)) * gClockFrequency)),
+ : mHorizon(time_type(llmax(horizon, F64(0.0)) * get_timer_info().mClockFrequency)),
mActive(false), // If true, a timer is running.
mDone(false), // If true, timer has completed and can be read (once)
mStarted(U64L(0)),
@@ -144,8 +144,8 @@ bool LLDeadmanTimer::isExpired(time_type now, F64 & started, F64 & stopped, U64
return false;
}
- started = mStarted * gClockFrequencyInv;
- stopped = mStopped * gClockFrequencyInv;
+ started = mStarted * get_timer_info().mClockFrequencyInv;
+ stopped = mStopped * get_timer_info().mClockFrequencyInv;
count = mCount;
mDone = false;
diff --git a/indra/llcommon/lldeleteutils.h b/indra/llcommon/lldeleteutils.h
deleted file mode 100755
index f250dc3028..0000000000
--- a/indra/llcommon/lldeleteutils.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * @file lldeleteutils.h
- * @brief Utility functions to simplify some common pointer-munging idioms.
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-#ifndef LL_DELETE_UTILS_H
-#define LL_DELETE_UTILS_H
-
-// Simple utility functions to eventually replace the common 2-line
-// idiom scattered throughout the viewer codebase. Note that where
-// possible we would rather be using smart pointers of some sort.
-
-template <class T>
-inline void deleteAndClear(T*& ptr)
-{
- delete ptr;
- ptr = NULL;
-}
-
-template <class T>
-inline void deleteAndClearArray(T*& array_ptr)
-{
- delete[] array_ptr;
- array_ptr = NULL;
-}
-
-#endif
diff --git a/indra/llcommon/lldepthstack.h b/indra/llcommon/lldepthstack.h
index d9db54efc7..b65840d342 100755
--- a/indra/llcommon/lldepthstack.h
+++ b/indra/llcommon/lldepthstack.h
@@ -27,18 +27,19 @@
#ifndef LL_LLDEPTHSTACK_H
#define LL_LLDEPTHSTACK_H
-#include "linked_lists.h"
+#include "llstl.h"
template <class DATA_TYPE> class LLDepthStack
{
private:
- LLLinkedList<DATA_TYPE> mStack;
+ std::deque<DATA_TYPE*> mStack;
U32 mCurrentDepth;
U32 mMaxDepth;
public:
- LLDepthStack() : mCurrentDepth(0), mMaxDepth(0) {}
- ~LLDepthStack() {}
+ LLDepthStack()
+ : mCurrentDepth(0), mMaxDepth(0)
+ {}
void setDepth(U32 depth)
{
@@ -54,24 +55,27 @@ public:
{
if (mCurrentDepth < mMaxDepth)
{
- mStack.addData(data);
+ mStack.push_back(data);
mCurrentDepth++;
}
else
{
// the last item falls off stack and is deleted
- mStack.getLastData();
- mStack.deleteCurrentData();
- mStack.addData(data);
+ if (!mStack.empty())
+ {
+ mStack.pop_front();
+ }
+ mStack.push_back(data);
}
}
DATA_TYPE *pop()
{
- DATA_TYPE *tempp = mStack.getFirstData();
- if (tempp)
+ DATA_TYPE *tempp = NULL;
+ if (!mStack.empty())
{
- mStack.removeCurrentData();
+ tempp = mStack.back();
+ mStack.pop_back();
mCurrentDepth--;
}
return tempp;
@@ -79,20 +83,13 @@ public:
DATA_TYPE *check()
{
- DATA_TYPE *tempp = mStack.getFirstData();
- return tempp;
+ return mStack.empty() ? NULL : mStack.back();
}
-
- void deleteAllData()
- {
- mCurrentDepth = 0;
- mStack.deleteAllData();
- }
-
+
void removeAllNodes()
{
mCurrentDepth = 0;
- mStack.removeAllNodes();
+ mStack.clear();
}
};
diff --git a/indra/llcommon/lldictionary.h b/indra/llcommon/lldictionary.h
index c752859a36..5800ec5e5d 100755
--- a/indra/llcommon/lldictionary.h
+++ b/indra/llcommon/lldictionary.h
@@ -89,7 +89,7 @@ protected:
{
if (lookup(index))
{
- llerrs << "Dictionary entry already added (attempted to add duplicate entry)" << llendl;
+ LL_ERRS() << "Dictionary entry already added (attempted to add duplicate entry)" << LL_ENDL;
}
(*this)[index] = entry;
}
diff --git a/indra/llcommon/lldlinked.h b/indra/llcommon/lldlinked.h
deleted file mode 100755
index 3f7c197be7..0000000000
--- a/indra/llcommon/lldlinked.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * @file lldlinked.h
- * @brief Declaration of the LLDLinked class.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-#ifndef LL_LLDLINKED_H
-#define LL_LLDLINKED_H
-
-template <class Type> class LLDLinked
-{
- LLDLinked* mNextp;
- LLDLinked* mPrevp;
-public:
-
- Type* getNext() { return (Type*)mNextp; }
- Type* getPrev() { return (Type*)mPrevp; }
- Type* getFirst() { return (Type*)mNextp; }
-
- void init()
- {
- mNextp = mPrevp = NULL;
- }
-
- void unlink()
- {
- if (mPrevp) mPrevp->mNextp = mNextp;
- if (mNextp) mNextp->mPrevp = mPrevp;
- }
-
- LLDLinked() { mNextp = mPrevp = NULL; }
- virtual ~LLDLinked() { unlink(); }
-
- virtual void deleteAll()
- {
- Type *curp = getFirst();
- while(curp)
- {
- Type *nextp = curp->getNext();
- curp->unlink();
- delete curp;
- curp = nextp;
- }
- }
-
- void relink(Type &after)
- {
- LLDLinked *afterp = (LLDLinked*)&after;
- afterp->mPrevp = this;
- mNextp = afterp;
- }
-
- virtual void append(Type& after)
- {
- LLDLinked *afterp = (LLDLinked*)&after;
- afterp->mPrevp = this;
- afterp->mNextp = mNextp;
- if (mNextp) mNextp->mPrevp = afterp;
- mNextp = afterp;
- }
-
- virtual void insert(Type& before)
- {
- LLDLinked *beforep = (LLDLinked*)&before;
- beforep->mNextp = this;
- beforep->mPrevp = mPrevp;
- if (mPrevp) mPrevp->mNextp = beforep;
- mPrevp = beforep;
- }
-
- virtual void put(Type& obj) { append(obj); }
-};
-
-#endif
diff --git a/indra/llcommon/lldqueueptr.h b/indra/llcommon/lldqueueptr.h
deleted file mode 100755
index 9fe08191e1..0000000000
--- a/indra/llcommon/lldqueueptr.h
+++ /dev/null
@@ -1,352 +0,0 @@
-/**
- * @file lldqueueptr.h
- * @brief LLDynamicQueuePtr declaration
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-#ifndef LL_LLDQUEUEPTR_H
-#define LL_LLDQUEUEPTR_H
-
-template <class Type>
-class LLDynamicQueuePtr
-{
-public:
- enum
- {
- OKAY = 0,
- FAIL = -1
- };
-
- LLDynamicQueuePtr(const S32 size=8);
- ~LLDynamicQueuePtr();
-
- void init();
- void destroy();
- void reset();
- void reallocate(U32 newsize);
-
- // ACCESSORS
- const Type& get(const S32 index) const; // no bounds checking
- Type& get(const S32 index); // no bounds checking
- const Type& operator [] (const S32 index) const { return get(index); }
- Type& operator [] (const S32 index) { return get(index); }
- S32 find(const Type &obj) const;
-
- S32 count() const { return (mLastObj >= mFirstObj ? mLastObj - mFirstObj : mLastObj + mMaxObj - mFirstObj); }
- S32 getMax() const { return mMaxObj; }
- S32 getFirst() const { return mFirstObj; }
- S32 getLast () const { return mLastObj; }
-
- // MANIPULATE
- S32 push(const Type &obj); // add to end of Queue, returns index from start
- S32 pull( Type &obj); // pull from Queue, returns index from start
-
- S32 remove (S32 index); // remove by index
- S32 removeObj(const Type &obj); // remove by object
-
-protected:
- S32 mFirstObj, mLastObj, mMaxObj;
- Type* mMemory;
-
-public:
-
- void print()
- {
- /*
- Convert this to llinfos if it's intended to be used - djs 08/30/02
-
- printf("Printing from %d to %d (of %d): ",mFirstObj, mLastObj, mMaxObj);
-
- if (mFirstObj <= mLastObj)
- {
- for (S32 i=mFirstObj;i<mLastObj;i++)
- {
- printf("%d ",mMemory[i]);
- }
- }
- else
- {
- for (S32 i=mFirstObj;i<mMaxObj;i++)
- {
- printf("%d ",mMemory[i]);
- }
- for (i=0;i<mLastObj;i++)
- {
- printf("%d ",mMemory[i]);
- }
- }
- printf("\n");
- */
- }
-
-};
-
-
-//--------------------------------------------------------
-// LLDynamicQueuePtrPtr implementation
-//--------------------------------------------------------
-
-
-template <class Type>
-inline LLDynamicQueuePtr<Type>::LLDynamicQueuePtr(const S32 size)
-{
- init();
- reallocate(size);
-}
-
-template <class Type>
-inline LLDynamicQueuePtr<Type>::~LLDynamicQueuePtr()
-{
- destroy();
-}
-
-template <class Type>
-inline void LLDynamicQueuePtr<Type>::init()
-{
- mFirstObj = 0;
- mLastObj = 0;
- mMaxObj = 0;
- mMemory = NULL;
-}
-
-template <class Type>
-inline void LLDynamicQueuePtr<Type>::reallocate(U32 newsize)
-{
- if (newsize)
- {
- if (mFirstObj > mLastObj && newsize > mMaxObj)
- {
- Type* new_memory = new Type[newsize];
-
- llassert(new_memory);
-
- S32 _count = count();
- S32 i, m = 0;
- for (i=mFirstObj; i < mMaxObj; i++)
- {
- new_memory[m++] = mMemory[i];
- }
- for (i=0; i <=mLastObj; i++)
- {
- new_memory[m++] = mMemory[i];
- }
-
- delete[] mMemory;
- mMemory = new_memory;
-
- mFirstObj = 0;
- mLastObj = _count;
- }
- else
- {
- Type* new_memory = new Type[newsize];
-
- llassert(new_memory);
-
- S32 i, m = 0;
- for (i=0; i < mLastObj; i++)
- {
- new_memory[m++] = mMemory[i];
- }
- delete[] mMemory;
- mMemory = new_memory;
- }
- }
- else if (mMemory)
- {
- delete[] mMemory;
- mMemory = NULL;
- }
-
- mMaxObj = newsize;
-}
-
-template <class Type>
-inline void LLDynamicQueuePtr<Type>::destroy()
-{
- reset();
- delete[] mMemory;
- mMemory = NULL;
-}
-
-
-template <class Type>
-void LLDynamicQueuePtr<Type>::reset()
-{
- for (S32 i=0; i < mMaxObj; i++)
- {
- get(i) = NULL; // unrefs for pointers
- }
-
- mFirstObj = 0;
- mLastObj = 0;
-}
-
-
-template <class Type>
-inline S32 LLDynamicQueuePtr<Type>::find(const Type &obj) const
-{
- S32 i;
- if (mFirstObj <= mLastObj)
- {
- for ( i = mFirstObj; i < mLastObj; i++ )
- {
- if (mMemory[i] == obj)
- {
- return i;
- }
- }
- }
- else
- {
- for ( i = mFirstObj; i < mMaxObj; i++ )
- {
- if (mMemory[i] == obj)
- {
- return i;
- }
- }
- for ( i = 0; i < mLastObj; i++ )
- {
- if (mMemory[i] == obj)
- {
- return i;
- }
- }
- }
-
- return FAIL;
-}
-
-template <class Type>
-inline S32 LLDynamicQueuePtr<Type>::remove(S32 i)
-{
- if (mFirstObj > mLastObj)
- {
- if (i >= mFirstObj && i < mMaxObj)
- {
- while( i > mFirstObj)
- {
- mMemory[i] = mMemory[i-1];
- i--;
- }
- mMemory[mFirstObj] = NULL;
- mFirstObj++;
- if (mFirstObj >= mMaxObj) mFirstObj = 0;
-
- return count();
- }
- else if (i < mLastObj && i >= 0)
- {
- while(i < mLastObj)
- {
- mMemory[i] = mMemory[i+1];
- i++;
- }
- mMemory[mLastObj] = NULL;
- mLastObj--;
- if (mLastObj < 0) mLastObj = mMaxObj-1;
-
- return count();
- }
- }
- else if (i <= mLastObj && i >= mFirstObj)
- {
- while(i < mLastObj)
- {
- mMemory[i] = mMemory[i+1];
- i++;
- }
- mMemory[mLastObj] = NULL;
- mLastObj--;
- if (mLastObj < 0) mLastObj = mMaxObj-1;
-
- return count();
- }
-
-
- return FAIL;
-}
-
-template <class Type>
-inline S32 LLDynamicQueuePtr<Type>::removeObj(const Type& obj)
-{
- S32 ind = find(obj);
- if (ind >= 0)
- {
- return remove(ind);
- }
- return FAIL;
-}
-
-template <class Type>
-inline S32 LLDynamicQueuePtr<Type>::push(const Type &obj)
-{
- if (mMaxObj - count() <= 1)
- {
- reallocate(mMaxObj * 2);
- }
-
- mMemory[mLastObj++] = obj;
-
- if (mLastObj >= mMaxObj)
- {
- mLastObj = 0;
- }
-
- return count();
-}
-
-template <class Type>
-inline S32 LLDynamicQueuePtr<Type>::pull(Type &obj)
-{
- obj = NULL;
-
- if (count() < 1) return -1;
-
- obj = mMemory[mFirstObj];
- mMemory[mFirstObj] = NULL;
-
- mFirstObj++;
-
- if (mFirstObj >= mMaxObj)
- {
- mFirstObj = 0;
- }
-
- return count();
-}
-
-template <class Type>
-inline const Type& LLDynamicQueuePtr<Type>::get(const S32 i) const
-{
- return mMemory[i];
-}
-
-template <class Type>
-inline Type& LLDynamicQueuePtr<Type>::get(const S32 i)
-{
- return mMemory[i];
-}
-
-
-#endif // LL_LLDQUEUEPTR_H
diff --git a/indra/llcommon/llenum.h b/indra/llcommon/llenum.h
deleted file mode 100755
index f57b2bc0b5..0000000000
--- a/indra/llcommon/llenum.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/**
- * @file llenum.h
- * @author Tom Yedwab
- * @brief Utility class for storing enum value <-> string lookup.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLENUM_H
-#define LL_LLENUM_H
-
-class LLEnum
-{
-public:
- typedef std::pair<const std::string, const U32> enum_t;
- enum
- {
- UNDEFINED = 0xffffffff,
- };
-
- LLEnum(const enum_t values_array[], const U32 length)
- {
- for (U32 i=0; i<length; ++i)
- {
- mEnumMap.insert(values_array[i]);
- if (values_array[i].second >= mEnumArray.size())
- {
- mEnumArray.resize(values_array[i].second+1);
- }
- mEnumArray[values_array[i].second] = values_array[i].first;
- }
- }
-
- U32 operator[](std::string str)
- {
- std::map<const std::string, const U32>::iterator itor;
- itor = mEnumMap.find(str);
- if (itor != mEnumMap.end())
- {
- return itor->second;
- }
- return UNDEFINED;
- }
-
- const std::string operator[](U32 index)
- {
- if (index < mEnumArray.size())
- {
- return mEnumArray[index];
- }
- return "";
- }
-
-private:
- std::map<const std::string, const U32> mEnumMap;
- std::vector<std::string> mEnumArray;
-};
-
-#endif // LL_LLENUM_H
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 853f279c95..a7963174ad 100755
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -51,7 +51,26 @@
#include "lltimer.h"
namespace {
-#if !LL_WINDOWS
+#if LL_WINDOWS
+ void debugger_print(const std::string& s)
+ {
+ // Be careful when calling OutputDebugString as it throws DBG_PRINTEXCEPTION_C
+ // which works just fine under the windows debugger, but can cause users who
+ // have enabled SEHOP exception chain validation to crash due to interactions
+ // between the Win 32-bit exception handling and boost coroutine fiber stacks. BUG-2707
+ //
+ if (IsDebuggerPresent())
+ {
+ // Need UTF16 for Unicode OutputDebugString
+ //
+ if (s.size())
+ {
+ OutputDebugString(utf8str_to_utf16str(s).c_str());
+ OutputDebugString(TEXT("\n"));
+ }
+ }
+ }
+#else
class RecordToSyslog : public LLError::Recorder
{
public:
@@ -96,8 +115,9 @@ namespace {
mFile.open(filename, llofstream::out | llofstream::app);
if (!mFile)
{
- llinfos << "Error setting log file to " << filename << llendl;
+ LL_INFOS() << "Error setting log file to " << filename << LL_ENDL;
}
+ mWantsTime = true;
}
~RecordToFile()
@@ -107,14 +127,10 @@ namespace {
bool okay() { return mFile; }
- virtual bool wantsTime() { return true; }
-
virtual void recordMessage(LLError::ELevel level,
const std::string& message)
{
mFile << message << std::endl;
- // mFile.flush();
- // *FIX: should we do this?
}
private:
@@ -125,9 +141,10 @@ namespace {
class RecordToStderr : public LLError::Recorder
{
public:
- RecordToStderr(bool timestamp) : mTimestamp(timestamp), mUseANSI(ANSI_PROBE) { }
-
- virtual bool wantsTime() { return mTimestamp; }
+ RecordToStderr(bool timestamp) : mUseANSI(ANSI_PROBE)
+ {
+ mWantsTime = timestamp;
+ }
virtual void recordMessage(LLError::ELevel level,
const std::string& message)
@@ -158,14 +175,19 @@ namespace {
}
private:
- bool mTimestamp;
- enum ANSIState {ANSI_PROBE, ANSI_YES, ANSI_NO};
- ANSIState mUseANSI;
+ enum ANSIState
+ {
+ ANSI_PROBE,
+ ANSI_YES,
+ ANSI_NO
+ } mUseANSI;
+
void colorANSI(const std::string color)
{
// ANSI color code escape sequence
fprintf(stderr, "\033[%sm", color.c_str() );
};
+
bool checkANSI(void)
{
#if LL_LINUX || LL_DARWIN
@@ -198,10 +220,13 @@ namespace {
class RecordToWinDebug: public LLError::Recorder
{
public:
+ RecordToWinDebug()
+ {}
+
virtual void recordMessage(LLError::ELevel level,
const std::string& message)
{
- LL_WINDOWS_OUTPUT_DEBUG(message);
+ debugger_print(message);
}
};
#endif
@@ -213,7 +238,7 @@ namespace
std::string className(const std::type_info& type)
{
#ifdef __GNUC__
- // GCC: type_info::name() returns a mangled class name, must demangle
+ // GCC: type_info::name() returns a mangled class name,st demangle
static size_t abi_name_len = 100;
static char* abi_name_buf = (char*)malloc(abi_name_len);
@@ -317,15 +342,15 @@ namespace
if (configuration.isUndefined())
{
- llwarns << filename() << " missing, ill-formed,"
+ LL_WARNS() << filename() << " missing, ill-formed,"
" or simply undefined; not changing configuration"
- << llendl;
+ << LL_ENDL;
return false;
}
}
LLError::configure(configuration);
- llinfos << "logging reconfigured from " << filename() << llendl;
+ LL_INFOS() << "logging reconfigured from " << filename() << LL_ENDL;
return true;
}
@@ -390,25 +415,25 @@ namespace LLError
class Settings
{
public:
- bool printLocation;
+ bool mPrintLocation;
- LLError::ELevel defaultLevel;
+ LLError::ELevel mDefaultLevel;
- LevelMap functionLevelMap;
- LevelMap classLevelMap;
- LevelMap fileLevelMap;
- LevelMap tagLevelMap;
- std::map<std::string, unsigned int> uniqueLogMessages;
+ LevelMap mFunctionLevelMap;
+ LevelMap mClassLevelMap;
+ LevelMap mFileLevelMap;
+ LevelMap mTagLevelMap;
+ std::map<std::string, unsigned int> mUniqueLogMessages;
- LLError::FatalFunction crashFunction;
- LLError::TimeFunction timeFunction;
+ LLError::FatalFunction mCrashFunction;
+ LLError::TimeFunction mTimeFunction;
- Recorders recorders;
- Recorder* fileRecorder;
- Recorder* fixedBufferRecorder;
- std::string fileRecorderFileName;
+ Recorders mRecorders;
+ Recorder* mFileRecorder;
+ Recorder* mFixedBufferRecorder;
+ std::string mFileRecorderFileName;
- int shouldLogCallCounter;
+ int mShouldLogCallCounter;
static Settings& get();
@@ -418,19 +443,19 @@ namespace LLError
private:
Settings()
- : printLocation(false),
- defaultLevel(LLError::LEVEL_DEBUG),
- crashFunction(),
- timeFunction(NULL),
- fileRecorder(NULL),
- fixedBufferRecorder(NULL),
- shouldLogCallCounter(0)
+ : mPrintLocation(false),
+ mDefaultLevel(LLError::LEVEL_DEBUG),
+ mCrashFunction(),
+ mTimeFunction(NULL),
+ mFileRecorder(NULL),
+ mFixedBufferRecorder(NULL),
+ mShouldLogCallCounter(0)
{ }
~Settings()
{
- for_each(recorders.begin(), recorders.end(), DeletePointer());
- recorders.clear();
+ for_each(mRecorders.begin(), mRecorders.end(), DeletePointer());
+ mRecorders.clear();
}
static Settings*& getPtr();
@@ -489,18 +514,64 @@ namespace LLError
int line,
const std::type_info& class_info,
const char* function,
- const char* broadTag,
- const char* narrowTag,
- bool printOnce)
- : mLevel(level), mFile(file), mLine(line),
- mClassInfo(class_info), mFunction(function),
- mCached(false), mShouldLog(false),
- mBroadTag(broadTag), mNarrowTag(narrowTag), mPrintOnce(printOnce)
- { }
+ bool printOnce,
+ const char** tags,
+ size_t tag_count)
+ : mLevel(level),
+ mFile(file),
+ mLine(line),
+ mClassInfo(class_info),
+ mFunction(function),
+ mCached(false),
+ mShouldLog(false),
+ mPrintOnce(printOnce),
+ mTags(new const char* [tag_count]),
+ mTagCount(tag_count)
+ {
+ for (int i = 0; i < tag_count; i++)
+ {
+ mTags[i] = tags[i];
+ }
+
+ switch (mLevel)
+ {
+ case LEVEL_DEBUG: mLevelString = "DEBUG:"; break;
+ case LEVEL_INFO: mLevelString = "INFO:"; break;
+ case LEVEL_WARN: mLevelString = "WARNING:"; break;
+ case LEVEL_ERROR: mLevelString = "ERROR:"; break;
+ default: mLevelString = "XXX:"; break;
+ };
+ mLocationString = llformat("%s(%d) :", abbreviateFile(mFile).c_str(), mLine);
+#if LL_WINDOWS
+ // DevStudio: __FUNCTION__ already includes the full class name
+#else
+#if LL_LINUX
+ // gross, but typeid comparison seems to always fail here with gcc4.1
+ if (0 != strcmp(mClassInfo.name(), typeid(NoClassInfo).name()))
+#else
+ if (mClassInfo != typeid(NoClassInfo))
+#endif // LL_LINUX
+ {
+ mFunctionString = className(mClassInfo) + "::";
+ }
+#endif
+ mFunctionString += std::string(mFunction) + ":";
+ for (size_t i = 0; i < mTagCount; i++)
+ {
+ mTagString += std::string("#") + mTags[i] + ((i == mTagCount - 1) ? "" : " ");
+ }
+ }
+
+ CallSite::~CallSite()
+ {
+ delete []mTags;
+ }
void CallSite::invalidate()
- { mCached = false; }
+ {
+ mCached = false;
+ }
}
namespace
@@ -586,25 +657,25 @@ namespace LLError
void setPrintLocation(bool print)
{
Settings& s = Settings::get();
- s.printLocation = print;
+ s.mPrintLocation = print;
}
void setFatalFunction(const FatalFunction& f)
{
Settings& s = Settings::get();
- s.crashFunction = f;
+ s.mCrashFunction = f;
}
FatalFunction getFatalFunction()
{
Settings& s = Settings::get();
- return s.crashFunction;
+ return s.mCrashFunction;
}
void setTimeFunction(TimeFunction f)
{
Settings& s = Settings::get();
- s.timeFunction = f;
+ s.mTimeFunction = f;
}
void setDefaultLevel(ELevel level)
@@ -612,13 +683,13 @@ namespace LLError
Globals& g = Globals::get();
Settings& s = Settings::get();
g.invalidateCallSites();
- s.defaultLevel = level;
+ s.mDefaultLevel = level;
}
ELevel getDefaultLevel()
{
Settings& s = Settings::get();
- return s.defaultLevel;
+ return s.mDefaultLevel;
}
void setFunctionLevel(const std::string& function_name, ELevel level)
@@ -626,7 +697,7 @@ namespace LLError
Globals& g = Globals::get();
Settings& s = Settings::get();
g.invalidateCallSites();
- s.functionLevelMap[function_name] = level;
+ s.mFunctionLevelMap[function_name] = level;
}
void setClassLevel(const std::string& class_name, ELevel level)
@@ -634,7 +705,7 @@ namespace LLError
Globals& g = Globals::get();
Settings& s = Settings::get();
g.invalidateCallSites();
- s.classLevelMap[class_name] = level;
+ s.mClassLevelMap[class_name] = level;
}
void setFileLevel(const std::string& file_name, ELevel level)
@@ -642,7 +713,7 @@ namespace LLError
Globals& g = Globals::get();
Settings& s = Settings::get();
g.invalidateCallSites();
- s.fileLevelMap[file_name] = level;
+ s.mFileLevelMap[file_name] = level;
}
void setTagLevel(const std::string& tag_name, ELevel level)
@@ -650,7 +721,7 @@ namespace LLError
Globals& g = Globals::get();
Settings& s = Settings::get();
g.invalidateCallSites();
- s.tagLevelMap[tag_name] = level;
+ s.mTagLevelMap[tag_name] = level;
}
LLError::ELevel decodeLevel(std::string name)
@@ -671,7 +742,7 @@ namespace LLError
LevelMap::const_iterator i = level_names.find(name);
if (i == level_names.end())
{
- llwarns << "unrecognized logging level: '" << name << "'" << llendl;
+ LL_WARNS() << "unrecognized logging level: '" << name << "'" << LL_ENDL;
return LLError::LEVEL_INFO;
}
@@ -698,11 +769,11 @@ namespace LLError
Settings& s = Settings::get();
g.invalidateCallSites();
- s.functionLevelMap.clear();
- s.classLevelMap.clear();
- s.fileLevelMap.clear();
- s.tagLevelMap.clear();
- s.uniqueLogMessages.clear();
+ s.mFunctionLevelMap.clear();
+ s.mClassLevelMap.clear();
+ s.mFileLevelMap.clear();
+ s.mTagLevelMap.clear();
+ s.mUniqueLogMessages.clear();
setPrintLocation(config["print-location"]);
setDefaultLevel(decodeLevel(config["default-level"]));
@@ -715,10 +786,10 @@ namespace LLError
ELevel level = decodeLevel(entry["level"]);
- setLevels(s.functionLevelMap, entry["functions"], level);
- setLevels(s.classLevelMap, entry["classes"], level);
- setLevels(s.fileLevelMap, entry["files"], level);
- setLevels(s.tagLevelMap, entry["tags"], level);
+ setLevels(s.mFunctionLevelMap, entry["functions"], level);
+ setLevels(s.mClassLevelMap, entry["classes"], level);
+ setLevels(s.mFileLevelMap, entry["files"], level);
+ setLevels(s.mTagLevelMap, entry["tags"], level);
}
}
}
@@ -726,14 +797,45 @@ namespace LLError
namespace LLError
{
+ Recorder::Recorder()
+ : mWantsTime(false),
+ mWantsTags(false),
+ mWantsLevel(true),
+ mWantsLocation(false),
+ mWantsFunctionName(true)
+ {}
+
Recorder::~Recorder()
{ }
- // virtual
bool Recorder::wantsTime()
- { return false; }
+ {
+ return mWantsTime;
+ }
+ // virtual
+ bool Recorder::wantsTags()
+ {
+ return mWantsTags;
+ }
+ // virtual
+ bool Recorder::wantsLevel()
+ {
+ return mWantsLevel;
+ }
+
+ // virtual
+ bool Recorder::wantsLocation()
+ {
+ return mWantsLocation;
+ }
+
+ // virtual
+ bool Recorder::wantsFunctionName()
+ {
+ return mWantsFunctionName;
+ }
void addRecorder(Recorder* recorder)
{
@@ -742,7 +844,7 @@ namespace LLError
return;
}
Settings& s = Settings::get();
- s.recorders.push_back(recorder);
+ s.mRecorders.push_back(recorder);
}
void removeRecorder(Recorder* recorder)
@@ -752,9 +854,8 @@ namespace LLError
return;
}
Settings& s = Settings::get();
- s.recorders.erase(
- std::remove(s.recorders.begin(), s.recorders.end(), recorder),
- s.recorders.end());
+ s.mRecorders.erase(std::remove(s.mRecorders.begin(), s.mRecorders.end(), recorder),
+ s.mRecorders.end());
}
}
@@ -764,10 +865,10 @@ namespace LLError
{
LLError::Settings& s = LLError::Settings::get();
- removeRecorder(s.fileRecorder);
- delete s.fileRecorder;
- s.fileRecorder = NULL;
- s.fileRecorderFileName.clear();
+ removeRecorder(s.mFileRecorder);
+ delete s.mFileRecorder;
+ s.mFileRecorder = NULL;
+ s.mFileRecorderFileName.clear();
if (file_name.empty())
{
@@ -781,8 +882,8 @@ namespace LLError
return;
}
- s.fileRecorderFileName = file_name;
- s.fileRecorder = f;
+ s.mFileRecorderFileName = file_name;
+ s.mFileRecorder = f;
addRecorder(f);
}
@@ -790,98 +891,112 @@ namespace LLError
{
LLError::Settings& s = LLError::Settings::get();
- removeRecorder(s.fixedBufferRecorder);
- delete s.fixedBufferRecorder;
- s.fixedBufferRecorder = NULL;
+ removeRecorder(s.mFixedBufferRecorder);
+ delete s.mFixedBufferRecorder;
+ s.mFixedBufferRecorder = NULL;
if (!fixedBuffer)
{
return;
}
- s.fixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
- addRecorder(s.fixedBufferRecorder);
+ s.mFixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
+ addRecorder(s.mFixedBufferRecorder);
}
std::string logFileName()
{
LLError::Settings& s = LLError::Settings::get();
- return s.fileRecorderFileName;
+ return s.mFileRecorderFileName;
}
}
namespace
{
- void writeToRecorders(LLError::ELevel level, const std::string& message)
+ void writeToRecorders(const LLError::CallSite& site, const std::string& message, bool show_location = true, bool show_time = true, bool show_tags = true, bool show_level = true, bool show_function = true)
{
+ LLError::ELevel level = site.mLevel;
LLError::Settings& s = LLError::Settings::get();
- std::string messageWithTime;
-
- for (Recorders::const_iterator i = s.recorders.begin();
- i != s.recorders.end();
+ for (Recorders::const_iterator i = s.mRecorders.begin();
+ i != s.mRecorders.end();
++i)
{
LLError::Recorder* r = *i;
- if (r->wantsTime() && s.timeFunction != NULL)
+ std::ostringstream message_stream;
+
+ if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s.mPrintLocation))
+ {
+ message_stream << site.mLocationString << " ";
+ }
+
+ if (show_time && r->wantsTime() && s.mTimeFunction != NULL)
{
- if (messageWithTime.empty())
+ message_stream << s.mTimeFunction() << " ";
+ }
+
+ if (show_level && r->wantsLevel())
{
- messageWithTime = s.timeFunction() + " " + message;
+ message_stream << site.mLevelString << " ";
}
- r->recordMessage(level, messageWithTime);
+ if (show_tags && r->wantsTags())
+ {
+ message_stream << site.mTagString << " ";
}
- else
+
+ if (show_function && r->wantsFunctionName())
{
- r->recordMessage(level, message);
+ message_stream << site.mFunctionString << " ";
}
+
+ message_stream << message;
+
+ r->recordMessage(level, message_stream.str());
}
}
}
-
-/*
-Recorder formats:
-
-$type = "ERROR" | "WARNING" | "ALERT" | "INFO" | "DEBUG"
-$loc = "$file($line)"
-$msg = "$loc : " if FATAL or printing loc
- "" otherwise
-$msg += "$type: "
-$msg += contents of stringstream
-
-$time = "%Y-%m-%dT%H:%M:%SZ" if UTC
- or "%Y-%m-%dT%H:%M:%S %Z" if local
-
-syslog: "$msg"
-file: "$time $msg\n"
-stderr: "$time $msg\n" except on windows, "$msg\n"
-fixedbuf: "$msg"
-winddebug: "$msg\n"
-
-Note: if FATAL, an additional line gets logged first, with $msg set to
- "$loc : error"
-
-You get:
- llfoo.cpp(42) : error
- llfoo.cpp(42) : ERROR: something
-
-*/
-
namespace {
bool checkLevelMap(const LevelMap& map, const std::string& key,
LLError::ELevel& level)
{
+ bool stop_checking;
LevelMap::const_iterator i = map.find(key);
if (i == map.end())
{
- return false;
+ return stop_checking = false;
}
level = i->second;
- return true;
+ return stop_checking = true;
+ }
+
+ bool checkLevelMap( const LevelMap& map,
+ const char *const * keys,
+ size_t count,
+ LLError::ELevel& level)
+ {
+ bool found_level = false;
+
+ LLError::ELevel tag_level = LLError::LEVEL_NONE;
+
+ for (size_t i = 0; i < count; i++)
+ {
+ LevelMap::const_iterator it = map.find(keys[i]);
+ if (it != map.end())
+ {
+ found_level = true;
+ tag_level = llmin(tag_level, it->second);
+ }
+ }
+
+ if (found_level)
+ {
+ level = tag_level;
+ }
+ return found_level;
}
class LogLock
@@ -948,9 +1063,9 @@ namespace LLError
Globals& g = Globals::get();
Settings& s = Settings::get();
- s.shouldLogCallCounter += 1;
+ s.mShouldLogCallCounter++;
- std::string class_name = className(site.mClassInfo);
+ const std::string& class_name = className(site.mClassInfo);
std::string function_name = functionName(site.mFunction);
#if LL_LINUX
// gross, but typeid comparison seems to always fail here with gcc4.1
@@ -962,17 +1077,18 @@ namespace LLError
function_name = class_name + "::" + function_name;
}
- ELevel compareLevel = s.defaultLevel;
+ ELevel compareLevel = s.mDefaultLevel;
// The most specific match found will be used as the log level,
// since the computation short circuits.
// So, in increasing order of importance:
- // Default < Broad Tag < File < Class < Function < Narrow Tag
- ((site.mNarrowTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mNarrowTag, compareLevel) : false)
- || checkLevelMap(s.functionLevelMap, function_name, compareLevel)
- || checkLevelMap(s.classLevelMap, class_name, compareLevel)
- || checkLevelMap(s.fileLevelMap, abbreviateFile(site.mFile), compareLevel)
- || ((site.mBroadTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mBroadTag, compareLevel) : false);
+ // Default < Tags < File < Class < Function
+ checkLevelMap(s.mFunctionLevelMap, function_name, compareLevel)
+ || checkLevelMap(s.mClassLevelMap, class_name, compareLevel)
+ || checkLevelMap(s.mFileLevelMap, abbreviateFile(site.mFile), compareLevel)
+ || (site.mTagCount > 0
+ ? checkLevelMap(s.mTagLevelMap, site.mTags, site.mTagCount, compareLevel)
+ : false);
site.mCached = true;
g.addCallSite(site);
@@ -1016,6 +1132,7 @@ namespace LLError
}
Globals& g = Globals::get();
+
if (out == &g.messageStream)
{
g.messageStream.clear();
@@ -1054,56 +1171,21 @@ namespace LLError
if (site.mLevel == LEVEL_ERROR)
{
- std::ostringstream fatalMessage;
- fatalMessage << abbreviateFile(site.mFile)
- << "(" << site.mLine << ") : error";
-
- writeToRecorders(site.mLevel, fatalMessage.str());
- }
-
-
- std::ostringstream prefix;
-
- switch (site.mLevel)
- {
- case LEVEL_DEBUG: prefix << "DEBUG: "; break;
- case LEVEL_INFO: prefix << "INFO: "; break;
- case LEVEL_WARN: prefix << "WARNING: "; break;
- case LEVEL_ERROR: prefix << "ERROR: "; break;
- default: prefix << "XXX: "; break;
- };
-
- if (s.printLocation)
- {
- prefix << abbreviateFile(site.mFile)
- << "(" << site.mLine << ") : ";
+ writeToRecorders(site, "error", true, true, true, false, false);
}
- #if LL_WINDOWS
- // DevStudio: __FUNCTION__ already includes the full class name
- #else
- #if LL_LINUX
- // gross, but typeid comparison seems to always fail here with gcc4.1
- if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name()))
- #else
- if (site.mClassInfo != typeid(NoClassInfo))
- #endif // LL_LINUX
- {
- prefix << className(site.mClassInfo) << "::";
- }
- #endif
- prefix << site.mFunction << ": ";
+ std::ostringstream message_stream;
if (site.mPrintOnce)
{
- std::map<std::string, unsigned int>::iterator messageIter = s.uniqueLogMessages.find(message);
- if (messageIter != s.uniqueLogMessages.end())
+ std::map<std::string, unsigned int>::iterator messageIter = s.mUniqueLogMessages.find(message);
+ if (messageIter != s.mUniqueLogMessages.end())
{
messageIter->second++;
unsigned int num_messages = messageIter->second;
if (num_messages == 10 || num_messages == 50 || (num_messages % 100) == 0)
{
- prefix << "ONCE (" << num_messages << "th time seen): ";
+ message_stream << "ONCE (" << num_messages << "th time seen): ";
}
else
{
@@ -1112,26 +1194,22 @@ namespace LLError
}
else
{
- prefix << "ONCE: ";
- s.uniqueLogMessages[message] = 1;
+ message_stream << "ONCE: ";
+ s.mUniqueLogMessages[message] = 1;
}
}
- prefix << message;
- message = prefix.str();
+ message_stream << message;
- writeToRecorders(site.mLevel, message);
+ writeToRecorders(site, message_stream.str());
- if (site.mLevel == LEVEL_ERROR && s.crashFunction)
+ if (site.mLevel == LEVEL_ERROR && s.mCrashFunction)
{
- s.crashFunction(message);
+ s.mCrashFunction(message_stream.str());
}
}
}
-
-
-
namespace LLError
{
Settings* saveAndResetSettings()
@@ -1188,7 +1266,7 @@ namespace LLError
int shouldLogCallCount()
{
Settings& s = Settings::get();
- return s.shouldLogCallCounter;
+ return s.mShouldLogCallCounter;
}
#if LL_WINDOWS
@@ -1376,13 +1454,13 @@ namespace LLError
if(sIndex > 0)
{
- llinfos << " ************* PRINT OUT LL CALL STACKS ************* " << llendl ;
+ LL_INFOS() << " ************* PRINT OUT LL CALL STACKS ************* " << LL_ENDL;
while(sIndex > 0)
{
sIndex-- ;
- llinfos << sBuffer[sIndex] << llendl ;
+ LL_INFOS() << sBuffer[sIndex] << LL_ENDL;
}
- llinfos << " *************** END OF LL CALL STACKS *************** " << llendl ;
+ LL_INFOS() << " *************** END OF LL CALL STACKS *************** " << LL_ENDL;
}
if(sBuffer)
@@ -1399,26 +1477,5 @@ namespace LLError
sIndex = 0 ;
}
-#if LL_WINDOWS
- void LLOutputDebugUTF8(const std::string& s)
- {
- // Be careful when calling OutputDebugString as it throws DBG_PRINTEXCEPTION_C
- // which works just fine under the windows debugger, but can cause users who
- // have enabled SEHOP exception chain validation to crash due to interactions
- // between the Win 32-bit exception handling and boost coroutine fiber stacks. BUG-2707
- //
- if (IsDebuggerPresent())
- {
- // Need UTF16 for Unicode OutputDebugString
- //
- if (s.size())
- {
- OutputDebugString(utf8str_to_utf16str(s).c_str());
- OutputDebugString(TEXT("\n"));
- }
- }
- }
-#endif
-
}
diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h
index 0b723aeb5d..bc80e64423 100755
--- a/indra/llcommon/llerror.h
+++ b/indra/llcommon/llerror.h
@@ -31,9 +31,68 @@
#include <sstream>
#include <typeinfo>
-#include "llerrorlegacy.h"
#include "stdtypes.h"
+#include "llpreprocessor.h"
+#include <boost/static_assert.hpp>
+
+const int LL_ERR_NOERR = 0;
+
+// Define one of these for different error levels in release...
+// #define RELEASE_SHOW_DEBUG // Define this if you want your release builds to show lldebug output.
+#define RELEASE_SHOW_INFO // Define this if you want your release builds to show llinfo output
+#define RELEASE_SHOW_WARN // Define this if you want your release builds to show llwarn output.
+
+#ifdef _DEBUG
+#define SHOW_DEBUG
+#define SHOW_WARN
+#define SHOW_INFO
+#define SHOW_ASSERT
+#else // _DEBUG
+
+#ifdef LL_RELEASE_WITH_DEBUG_INFO
+#define SHOW_ASSERT
+#endif // LL_RELEASE_WITH_DEBUG_INFO
+
+#ifdef RELEASE_SHOW_DEBUG
+#define SHOW_DEBUG
+#endif
+
+#ifdef RELEASE_SHOW_WARN
+#define SHOW_WARN
+#endif
+
+#ifdef RELEASE_SHOW_INFO
+#define SHOW_INFO
+#endif
+
+#ifdef RELEASE_SHOW_ASSERT
+#define SHOW_ASSERT
+#endif
+
+#endif // !_DEBUG
+
+#define llassert_always_msg(func, msg) if (LL_UNLIKELY(!(func))) LL_ERRS() << "ASSERT (" << msg << ")" << LL_ENDL
+
+#define llassert_always(func) llassert_always_msg(func, #func)
+
+#ifdef SHOW_ASSERT
+#define llassert(func) llassert_always_msg(func, #func)
+#define llverify(func) llassert_always_msg(func, #func)
+#else
+#define llassert(func)
+#define llverify(func) do {if (func) {}} while(0)
+#endif
+
+#ifdef LL_WINDOWS
+#define LL_STATIC_ASSERT(func, msg) static_assert(func, msg)
+#define LL_BAD_TEMPLATE_INSTANTIATION(type, msg) static_assert(false, msg)
+#else
+#define LL_STATIC_ASSERT(func, msg) BOOST_STATIC_ASSERT(func)
+#define LL_BAD_TEMPLATE_INSTANTIATION(type, msg) BOOST_STATIC_ASSERT(sizeof(type) != 0 && false);
+#endif
+
+
/** Error Logging Facility
Information for most users:
@@ -121,50 +180,62 @@ namespace LLError
They are not intended for general use.
*/
- class CallSite;
+ struct CallSite;
class LL_COMMON_API Log
{
public:
static bool shouldLog(CallSite&);
static std::ostringstream* out();
- static void flush(std::ostringstream* out, char* message) ;
+ static void flush(std::ostringstream* out, char* message);
static void flush(std::ostringstream*, const CallSite&);
};
- class LL_COMMON_API CallSite
+ struct LL_COMMON_API CallSite
{
// Represents a specific place in the code where a message is logged
// This is public because it is used by the macros below. It is not
// intended for public use.
- public:
- CallSite(ELevel, const char* file, int line,
- const std::type_info& class_info, const char* function, const char* broadTag, const char* narrowTag, bool printOnce);
-
+ CallSite(ELevel level,
+ const char* file,
+ int line,
+ const std::type_info& class_info,
+ const char* function,
+ bool print_once,
+ const char** tags,
+ size_t tag_count);
+
+ ~CallSite();
+
#ifdef LL_LIBRARY_INCLUDE
bool shouldLog();
#else // LL_LIBRARY_INCLUDE
bool shouldLog()
- { return mCached ? mShouldLog : Log::shouldLog(*this); }
+ {
+ return mCached
+ ? mShouldLog
+ : Log::shouldLog(*this);
+ }
// this member function needs to be in-line for efficiency
#endif // LL_LIBRARY_INCLUDE
void invalidate();
- private:
// these describe the call site and never change
const ELevel mLevel;
const char* const mFile;
- const int mLine;
- const std::type_info& mClassInfo;
+ const int mLine;
+ const std::type_info& mClassInfo;
const char* const mFunction;
- const char* const mBroadTag;
- const char* const mNarrowTag;
- const bool mPrintOnce;
-
- // these implement a cache of the call to shouldLog()
- bool mCached;
- bool mShouldLog;
+ const char** mTags;
+ size_t mTagCount;
+ const bool mPrintOnce;
+ const char* mLevelString;
+ std::string mLocationString,
+ mFunctionString,
+ mTagString;
+ bool mCached,
+ mShouldLog;
friend class Log;
};
@@ -198,32 +269,23 @@ namespace LLError
static void clear() ;
static void end(std::ostringstream* _out) ;
};
-
-#if LL_WINDOWS
- void LLOutputDebugUTF8(const std::string& s);
-#endif
-
}
-#if LL_WINDOWS
- // Macro accepting a std::string for display in windows debugging console
- #define LL_WINDOWS_OUTPUT_DEBUG(a) LLError::LLOutputDebugUTF8(a)
-#else
- #define LL_WINDOWS_OUTPUT_DEBUG(a)
-#endif
-
//this is cheaper than llcallstacks if no need to output other variables to call stacks.
-#define llpushcallstacks LLError::LLCallStacks::push(__FUNCTION__, __LINE__)
-#define llcallstacks \
- {\
+#define LL_PUSH_CALLSTACKS() LLError::LLCallStacks::push(__FUNCTION__, __LINE__)
+
+#define llcallstacks \
+ { \
std::ostringstream* _out = LLError::LLCallStacks::insert(__FUNCTION__, __LINE__) ; \
(*_out)
-#define llcallstacksendl \
- LLError::End(); \
+
+#define llcallstacksendl \
+ LLError::End(); \
LLError::LLCallStacks::end(_out) ; \
}
-#define llclearcallstacks LLError::LLCallStacks::clear()
-#define llprintcallstacks LLError::LLCallStacks::print()
+
+#define LL_CLEAR_CALLSTACKS() LLError::LLCallStacks::clear()
+#define LL_PRINT_CALLSTACKS() LLError::LLCallStacks::print()
/*
Class type information for logging
@@ -237,78 +299,72 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
// Outside a class declaration, or in class without LOG_CLASS(), this
// typedef causes the messages to not be associated with any class.
+/////////////////////////////////
+// Error Logging Macros
+// See top of file for common usage.
+/////////////////////////////////
+// this macro uses a one-shot do statement to avoid parsing errors when writing control flow statements
+// without braces:
+// if (condition) LL_INFOS() << "True" << LL_ENDL; else LL_INFOS()() << "False" << LL_ENDL
+#define lllog(level, once, ...) \
+ do { \
+ const char* tags[] = {"", ##__VA_ARGS__}; \
+ ::size_t tag_count = LL_ARRAY_SIZE(tags) - 1; \
+ static LLError::CallSite _site( \
+ level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, once, &tags[1], tag_count);\
+ if (LL_UNLIKELY(_site.shouldLog())) \
+ { \
+ std::ostringstream* _out = LLError::Log::out(); \
+ (*_out)
+//Use this construct if you need to do computation in the middle of a
+//message:
+//
+// LL_INFOS("AgentGesture") << "the agent " << agend_id;
+// switch (f)
+// {
+// case FOP_SHRUGS: LL_CONT << "shrugs"; break;
+// case FOP_TAPS: LL_CONT << "points at " << who; break;
+// case FOP_SAYS: LL_CONT << "says " << message; break;
+// }
+// LL_CONT << " for " << t << " seconds" << LL_ENDL;
+//
+//Such computation is done iff the message will be logged.
+#define LL_CONT (*_out)
-/*
- Error Logging Macros
- See top of file for common usage.
-*/
-
-#define lllog(level, broadTag, narrowTag, once) \
- do { \
- static LLError::CallSite _site( \
- level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, broadTag, narrowTag, once);\
- if (LL_UNLIKELY(_site.shouldLog())) \
- { \
- std::ostringstream* _out = LLError::Log::out(); \
- (*_out)
+#define LL_NEWLINE '\n'
-// DEPRECATED: Don't call directly, use LL_ENDL instead, which actually looks like a macro
-#define llendl \
- LLError::End(); \
+#define LL_ENDL \
+ LLError::End(); \
LLError::Log::flush(_out, _site); \
- } \
+ } \
} while(0)
-// DEPRECATED: Use the new macros that allow tags and *look* like macros.
-#define lldebugs lllog(LLError::LEVEL_DEBUG, NULL, NULL, false)
-#define llinfos lllog(LLError::LEVEL_INFO, NULL, NULL, false)
-#define llwarns lllog(LLError::LEVEL_WARN, NULL, NULL, false)
-#define llerrs lllog(LLError::LEVEL_ERROR, NULL, NULL, false)
-#define llcont (*_out)
-
// NEW Macros for debugging, allow the passing of a string tag
-// One Tag
-#define LL_DEBUGS(broadTag) lllog(LLError::LEVEL_DEBUG, broadTag, NULL, false)
-#define LL_INFOS(broadTag) lllog(LLError::LEVEL_INFO, broadTag, NULL, false)
-#define LL_WARNS(broadTag) lllog(LLError::LEVEL_WARN, broadTag, NULL, false)
-#define LL_ERRS(broadTag) lllog(LLError::LEVEL_ERROR, broadTag, NULL, false)
-// Two Tags
-#define LL_DEBUGS2(broadTag, narrowTag) lllog(LLError::LEVEL_DEBUG, broadTag, narrowTag, false)
-#define LL_INFOS2(broadTag, narrowTag) lllog(LLError::LEVEL_INFO, broadTag, narrowTag, false)
-#define LL_WARNS2(broadTag, narrowTag) lllog(LLError::LEVEL_WARN, broadTag, narrowTag, false)
-#define LL_ERRS2(broadTag, narrowTag) lllog(LLError::LEVEL_ERROR, broadTag, narrowTag, false)
+// Pass comma separated list of tags (currently only supports up to 0, 1, or 2)
+#define LL_DEBUGS(...) lllog(LLError::LEVEL_DEBUG, false, ##__VA_ARGS__)
+#define LL_INFOS(...) lllog(LLError::LEVEL_INFO, false, ##__VA_ARGS__)
+#define LL_WARNS(...) lllog(LLError::LEVEL_WARN, false, ##__VA_ARGS__)
+#define LL_ERRS(...) lllog(LLError::LEVEL_ERROR, false, ##__VA_ARGS__)
+// alternative to llassert_always that prints explanatory message
+#define LL_ERRS_IF(exp, ...) if (exp) LL_ERRS(##__VA_ARGS__) << "(" #exp ")"
// Only print the log message once (good for warnings or infos that would otherwise
// spam the log file over and over, such as tighter loops).
-#define LL_DEBUGS_ONCE(broadTag) lllog(LLError::LEVEL_DEBUG, broadTag, NULL, true)
-#define LL_INFOS_ONCE(broadTag) lllog(LLError::LEVEL_INFO, broadTag, NULL, true)
-#define LL_WARNS_ONCE(broadTag) lllog(LLError::LEVEL_WARN, broadTag, NULL, true)
-#define LL_DEBUGS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_DEBUG, broadTag, narrowTag, true)
-#define LL_INFOS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_INFO, broadTag, narrowTag, true)
-#define LL_WARNS2_ONCE(broadTag, narrowTag) lllog(LLError::LEVEL_WARN, broadTag, narrowTag, true)
-
-#define LL_ENDL llendl
-#define LL_CONT (*_out)
+#define LL_DEBUGS_ONCE(...) lllog(LLError::LEVEL_DEBUG, true, ##__VA_ARGS__)
+#define LL_INFOS_ONCE(...) lllog(LLError::LEVEL_INFO, true, ##__VA_ARGS__)
+#define LL_WARNS_ONCE(...) lllog(LLError::LEVEL_WARN, true, ##__VA_ARGS__)
- /*
- Use this construct if you need to do computation in the middle of a
- message:
-
- LL_INFOS("AgentGesture") << "the agent " << agend_id;
- switch (f)
- {
- case FOP_SHRUGS: LL_CONT << "shrugs"; break;
- case FOP_TAPS: LL_CONT << "points at " << who; break;
- case FOP_SAYS: LL_CONT << "says " << message; break;
- }
- LL_CONT << " for " << t << " seconds" << LL_ENDL;
-
- Such computation is done iff the message will be logged.
- */
+// DEPRECATED: Use the new macros that allow tags and *look* like macros.
+#define lldebugs LL_COMPILE_TIME_MESSAGE("Warning: lldebugs deprecated, use LL_DEBUGS() instead") LL_DEBUGS()
+#define llinfos LL_COMPILE_TIME_MESSAGE("Warning: llinfos deprecated, use LL_INFOS() instead") LL_INFOS()
+#define llwarns LL_COMPILE_TIME_MESSAGE("Warning: llwarns deprecated, use LL_WARNS() instead") LL_WARNS()
+#define llerrs LL_COMPILE_TIME_MESSAGE("Warning: llerrs deprecated, use LL_ERRS() instead") LL_ERRS()
+#define llcont LL_COMPILE_TIME_MESSAGE("Warning: llcont deprecated, use LL_CONT instead") LL_CONT
+#define llendl LL_COMPILE_TIME_MESSAGE("Warning: llendl deprecated, use LL_ENDL instead") LL_ENDL
#endif // LL_LLERROR_H
diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h
index 480654b1a2..aab695094c 100755
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -136,14 +136,24 @@ namespace LLError
{
// An object that handles the actual output or error messages.
public:
+ Recorder();
virtual ~Recorder();
virtual void recordMessage(LLError::ELevel, const std::string& message) = 0;
// use the level for better display, not for filtering
- virtual bool wantsTime(); // default returns false
- // override and return true if the recorder wants the time string
- // included in the text of the message
+ bool wantsTime();
+ bool wantsTags();
+ bool wantsLevel();
+ bool wantsLocation();
+ bool wantsFunctionName();
+
+ protected:
+ bool mWantsTime,
+ mWantsTags,
+ mWantsLevel,
+ mWantsLocation,
+ mWantsFunctionName;
};
/**
diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h
index 37cee579cd..31dd207008 100755
--- a/indra/llcommon/llerrorlegacy.h
+++ b/indra/llcommon/llerrorlegacy.h
@@ -28,91 +28,5 @@
#ifndef LL_LLERRORLEGACY_H
#define LL_LLERRORLEGACY_H
-#include "llpreprocessor.h"
-
-/*
- LEGACY -- DO NOT USE THIS STUFF ANYMORE
-*/
-
-// Specific error codes
-const int LL_ERR_NOERR = 0;
-const int LL_ERR_ASSET_REQUEST_FAILED = -1;
-//const int LL_ERR_ASSET_REQUEST_INVALID = -2;
-const int LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3;
-const int LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4;
-const int LL_ERR_INSUFFICIENT_PERMISSIONS = -5;
-const int LL_ERR_EOF = -39;
-const int LL_ERR_CANNOT_OPEN_FILE = -42;
-const int LL_ERR_FILE_NOT_FOUND = -43;
-const int LL_ERR_FILE_EMPTY = -44;
-const int LL_ERR_TCP_TIMEOUT = -23016;
-const int LL_ERR_CIRCUIT_GONE = -23017;
-const int LL_ERR_PRICE_MISMATCH = -23018;
-
-
-
-// Define one of these for different error levels in release...
-// #define RELEASE_SHOW_DEBUG // Define this if you want your release builds to show lldebug output.
-#define RELEASE_SHOW_INFO // Define this if you want your release builds to show llinfo output
-#define RELEASE_SHOW_WARN // Define this if you want your release builds to show llwarn output.
-
-
-//////////////////////////////////////////
-//
-// Implementation - ignore
-//
-//
-#ifdef _DEBUG
-#define SHOW_DEBUG
-#define SHOW_WARN
-#define SHOW_INFO
-#define SHOW_ASSERT
-#else // _DEBUG
-
-#ifdef LL_RELEASE_WITH_DEBUG_INFO
-#define SHOW_ASSERT
-#endif // LL_RELEASE_WITH_DEBUG_INFO
-
-#ifdef RELEASE_SHOW_DEBUG
-#define SHOW_DEBUG
-#endif
-
-#ifdef RELEASE_SHOW_WARN
-#define SHOW_WARN
-#endif
-
-#ifdef RELEASE_SHOW_INFO
-#define SHOW_INFO
-#endif
-
-#ifdef RELEASE_SHOW_ASSERT
-#define SHOW_ASSERT
-#endif
-
-#endif // _DEBUG
-
-
-
-#define lldebugst(type) lldebugs
-#define llendflush llendl
-
-
-#define llerror(msg, num) llerrs << "Error # " << num << ": " << msg << llendl;
-
-#define llwarning(msg, num) llwarns << "Warning # " << num << ": " << msg << llendl;
-
-#define llassert_always(func) if (LL_UNLIKELY(!(func))) llerrs << "ASSERT (" << #func << ")" << llendl;
-
-#ifdef SHOW_ASSERT
-#define llassert(func) llassert_always(func)
-#define llverify(func) llassert_always(func)
-#else
-#define llassert(func)
-#define llverify(func) do {if (func) {}} while(0)
-#endif
-
-// handy compile-time assert - enforce those template parameters!
-#define cassert(expn) typedef char __C_ASSERT__[(expn)?1:-1] /* Flawfinder: ignore */
- //XXX: used in two places in llcommon/llskipmap.h
#endif // LL_LLERRORLEGACY_H
diff --git a/indra/llcommon/llerrorthread.cpp b/indra/llcommon/llerrorthread.cpp
index 950fcd6e83..f6bc68b5c1 100755
--- a/indra/llcommon/llerrorthread.cpp
+++ b/indra/llcommon/llerrorthread.cpp
@@ -65,7 +65,7 @@ void get_child_status(const int waitpid_status, int &process_status, bool &exite
exited = true;
if (do_logging)
{
- llinfos << "get_child_status - Child exited cleanly with return of " << process_status << llendl;
+ LL_INFOS() << "get_child_status - Child exited cleanly with return of " << process_status << LL_ENDL;
}
return;
}
@@ -75,15 +75,15 @@ void get_child_status(const int waitpid_status, int &process_status, bool &exite
exited = true;
if (do_logging)
{
- llinfos << "get_child_status - Child died because of uncaught signal " << process_status << llendl;
+ LL_INFOS() << "get_child_status - Child died because of uncaught signal " << process_status << LL_ENDL;
#ifdef WCOREDUMP
if (WCOREDUMP(waitpid_status))
{
- llinfos << "get_child_status - Child dumped core" << llendl;
+ LL_INFOS() << "get_child_status - Child dumped core" << LL_ENDL;
}
else
{
- llinfos << "get_child_status - Child didn't dump core" << llendl;
+ LL_INFOS() << "get_child_status - Child didn't dump core" << LL_ENDL;
}
#endif
}
@@ -93,7 +93,7 @@ void get_child_status(const int waitpid_status, int &process_status, bool &exite
{
// This is weird. I just dump the waitpid status into the status code,
// not that there's any way of telling what it is...
- llinfos << "get_child_status - Got SIGCHILD but child didn't exit" << llendl;
+ LL_INFOS() << "get_child_status - Got SIGCHILD but child didn't exit" << LL_ENDL;
process_status = waitpid_status;
}
@@ -106,99 +106,28 @@ void LLErrorThread::run()
// This thread sits and waits for the sole purpose
// of waiting for the signal/exception handlers to flag the
// application state as APP_STATUS_ERROR.
- llinfos << "thread_error - Waiting for an error" << llendl;
+ LL_INFOS() << "thread_error - Waiting for an error" << LL_ENDL;
S32 counter = 0;
-#if !LL_WINDOWS
- U32 last_sig_child_count = 0;
-#endif
while (! (LLApp::isError() || LLApp::isStopped()))
{
-#if !LL_WINDOWS
- // Check whether or not the main thread had a sig child we haven't handled.
- U32 current_sig_child_count = LLApp::getSigChildCount();
- if (last_sig_child_count != current_sig_child_count)
- {
- int status = 0;
- pid_t child_pid = 0;
- last_sig_child_count = current_sig_child_count;
- if (LLApp::sLogInSignal)
- {
- llinfos << "thread_error handling SIGCHLD #" << current_sig_child_count << llendl;
- }
- for (LLApp::child_map::iterator iter = LLApp::sChildMap.begin(); iter != LLApp::sChildMap.end();)
- {
- child_pid = iter->first;
- LLChildInfo &child_info = iter->second;
- // check the status of *all* children, in case we missed a signal
- if (0 != waitpid(child_pid, &status, WNOHANG))
- {
- bool exited = false;
- int exit_status = -1;
- get_child_status(status, exit_status, exited, LLApp::sLogInSignal);
-
- if (child_info.mCallback)
- {
- if (LLApp::sLogInSignal)
- {
- llinfos << "Signal handler - Running child callback" << llendl;
- }
- child_info.mCallback(child_pid, exited, status);
- }
- LLApp::sChildMap.erase(iter++);
- }
- else
- {
- // Child didn't terminate, yet we got a sigchild somewhere...
- if (child_info.mGotSigChild && child_info.mCallback)
- {
- child_info.mCallback(child_pid, false, 0);
- }
- child_info.mGotSigChild = FALSE;
- iter++;
- }
- }
-
- // check the status of *all* children, in case we missed a signal
- // Same as above, but use the default child callback
- while(0 < (child_pid = waitpid( -1, &status, WNOHANG )))
- {
- if (0 != waitpid(child_pid, &status, WNOHANG))
- {
- bool exited = false;
- int exit_status = -1;
- get_child_status(status, exit_status, exited, LLApp::sLogInSignal);
- if (LLApp::sDefaultChildCallback)
- {
- if (LLApp::sLogInSignal)
- {
- llinfos << "Signal handler - Running default child callback" << llendl;
- }
- LLApp::sDefaultChildCallback(child_pid, true, status);
- }
- }
- }
- }
-
-
-#endif
ms_sleep(10);
counter++;
}
if (LLApp::isError())
{
// The app is in an error state, run the application's error handler.
- //llinfos << "thread_error - An error has occurred, running error callback!" << llendl;
+ //LL_INFOS() << "thread_error - An error has occurred, running error callback!" << LL_ENDL;
// Run the error handling callback
LLApp::runErrorHandler();
}
else
{
// Everything is okay, a clean exit.
- //llinfos << "thread_error - Application exited cleanly" << llendl;
+ //LL_INFOS() << "thread_error - Application exited cleanly" << LL_ENDL;
}
- //llinfos << "thread_error - Exiting" << llendl;
+ //LL_INFOS() << "thread_error - Exiting" << LL_ENDL;
LLApp::sErrorThreadRunning = FALSE;
}
diff --git a/indra/llcommon/llevent.h b/indra/llcommon/llevent.h
index 8cd682b8bf..28ce7de102 100755
--- a/indra/llcommon/llevent.h
+++ b/indra/llcommon/llevent.h
@@ -29,8 +29,8 @@
#define LL_EVENT_H
#include "llsd.h"
+#include "llrefcount.h"
#include "llpointer.h"
-#include "llthread.h"
namespace LLOldEvents
{
diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
index 0855180dcd..1c928b3db8 100755
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -41,7 +41,6 @@
#include <algorithm>
// std headers
#include <typeinfo>
-#include <cassert>
#include <cmath>
#include <cctype>
// external library headers
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index 65b0fef354..0cbd1da32d 100755
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -61,7 +61,7 @@
#include "llsd.h"
#include "llsingleton.h"
#include "lldependencies.h"
-#include "ll_template_cast.h"
+#include "llstl.h"
/*==========================================================================*|
// override this to allow binding free functions with more parameters
diff --git a/indra/llcommon/llextendedstatus.h b/indra/llcommon/llextendedstatus.h
deleted file mode 100755
index 8ce173d1ff..0000000000
--- a/indra/llcommon/llextendedstatus.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * @file llextendedstatus.h
- * @date August 2007
- * @brief extended status codes for curl/vfs/resident asset storage and delivery
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLEXTENDEDSTATUS_H
-#define LL_LLEXTENDEDSTATUS_H
-
-
-typedef S32 LLExtStat;
-
-
-// Status provider groups - Top bits indicate which status type it is
-// Zero is common status code (next section)
-const LLExtStat LL_EXSTAT_CURL_RESULT = 1L<<30; // serviced by curl - use 1L if we really implement the below
-const LLExtStat LL_EXSTAT_RES_RESULT = 2L<<30; // serviced by resident copy
-const LLExtStat LL_EXSTAT_VFS_RESULT = 3L<<30; // serviced by vfs
-
-
-// Common Status Codes
-//
-const LLExtStat LL_EXSTAT_NONE = 0x00000; // No extra info here - sorry!
-const LLExtStat LL_EXSTAT_NULL_UUID = 0x10001; // null asset ID
-const LLExtStat LL_EXSTAT_NO_UPSTREAM = 0x10002; // attempt to upload without a valid upstream method/provider
-const LLExtStat LL_EXSTAT_REQUEST_DROPPED = 0x10003; // request was dropped unserviced
-const LLExtStat LL_EXSTAT_NONEXISTENT_FILE = 0x10004; // trying to upload a file that doesn't exist
-const LLExtStat LL_EXSTAT_BLOCKED_FILE = 0x10005; // trying to upload a file that we can't open
-
-
-// curl status codes:
-//
-// Mask off LL_EXSTAT_CURL_RESULT for original result and
-// see: libraries/include/curl/curl.h
-
-
-// Memory-Resident status codes:
-// None at present
-
-
-// VFS status codes:
-const LLExtStat LL_EXSTAT_VFS_CACHED = LL_EXSTAT_VFS_RESULT | 0x0001;
-const LLExtStat LL_EXSTAT_VFS_CORRUPT = LL_EXSTAT_VFS_RESULT | 0x0002;
-
-
-#endif // LL_LLEXTENDEDSTATUS_H
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 58db7d0d17..3d28cd15b0 100755
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -32,8 +32,13 @@
#include "llsingleton.h"
#include "lltreeiterators.h"
#include "llsdserialize.h"
+#include "llunits.h"
+#include "llsd.h"
+#include "lltracerecording.h"
+#include "lltracethreadrecorder.h"
#include <boost/bind.hpp>
+#include <queue>
#if LL_WINDOWS
@@ -49,140 +54,115 @@
#error "architecture not supported"
#endif
+namespace LLTrace
+{
+
//////////////////////////////////////////////////////////////////////////////
// statics
-S32 LLFastTimer::sCurFrameIndex = -1;
-S32 LLFastTimer::sLastFrameIndex = -1;
-U64 LLFastTimer::sLastFrameTime = LLFastTimer::getCPUClockCount64();
-bool LLFastTimer::sPauseHistory = 0;
-bool LLFastTimer::sResetHistory = 0;
-LLFastTimer::CurTimerData LLFastTimer::sCurTimerData;
-BOOL LLFastTimer::sLog = FALSE;
-std::string LLFastTimer::sLogName = "";
-BOOL LLFastTimer::sMetricLog = FALSE;
-LLMutex* LLFastTimer::sLogLock = NULL;
-std::queue<LLSD> LLFastTimer::sLogQueue;
+bool BlockTimer::sLog = false;
+std::string BlockTimer::sLogName = "";
+bool BlockTimer::sMetricLog = false;
#if LL_LINUX || LL_SOLARIS
-U64 LLFastTimer::sClockResolution = 1000000000; // Nanosecond resolution
+U64 BlockTimer::sClockResolution = 1000000000; // Nanosecond resolution
#else
-U64 LLFastTimer::sClockResolution = 1000000; // Microsecond resolution
+U64 BlockTimer::sClockResolution = 1000000; // Microsecond resolution
#endif
-// FIXME: move these declarations to the relevant modules
-
-// helper functions
-typedef LLTreeDFSPostIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_bottom_up_iterator_t;
+static LLMutex* sLogLock = NULL;
+static std::queue<LLSD> sLogQueue;
-static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(LLFastTimer::NamedTimer& id)
+block_timer_tree_df_iterator_t begin_block_timer_tree_df(BlockTimerStatHandle& id)
{
- return timer_tree_bottom_up_iterator_t(&id,
- boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1),
- boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1));
+ return block_timer_tree_df_iterator_t(&id,
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1),
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
}
-static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up()
+block_timer_tree_df_iterator_t end_block_timer_tree_df()
{
- return timer_tree_bottom_up_iterator_t();
+ return block_timer_tree_df_iterator_t();
}
-typedef LLTreeDFSIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_dfs_iterator_t;
-
+block_timer_tree_df_post_iterator_t begin_block_timer_tree_df_post(BlockTimerStatHandle& id)
+{
+ return block_timer_tree_df_post_iterator_t(&id,
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1),
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
+}
-static timer_tree_dfs_iterator_t begin_timer_tree(LLFastTimer::NamedTimer& id)
+block_timer_tree_df_post_iterator_t end_block_timer_tree_df_post()
{
- return timer_tree_dfs_iterator_t(&id,
- boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1),
- boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1));
+ return block_timer_tree_df_post_iterator_t();
}
-static timer_tree_dfs_iterator_t end_timer_tree()
+block_timer_tree_bf_iterator_t begin_block_timer_tree_bf(BlockTimerStatHandle& id)
{
- return timer_tree_dfs_iterator_t();
+ return block_timer_tree_bf_iterator_t(&id,
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1),
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
}
-// factory class that creates NamedTimers via static DeclareTimer objects
-class NamedTimerFactory : public LLSingleton<NamedTimerFactory>
-{
-public:
- NamedTimerFactory()
- : mTimerRoot(new LLFastTimer::NamedTimer("root"))
+block_timer_tree_bf_iterator_t end_block_timer_tree_bf()
{
- mRootFrameState.setNamedTimer(mTimerRoot);
- mTimerRoot->setFrameState(&mRootFrameState);
- mTimerRoot->mParent = mTimerRoot;
- mTimerRoot->setCollapsed(false);
- mRootFrameState.mParent = &mRootFrameState;
+ return block_timer_tree_bf_iterator_t();
}
- ~NamedTimerFactory()
+block_timer_tree_df_iterator_t begin_timer_tree(BlockTimerStatHandle& id)
{
- std::for_each(mTimers.begin(), mTimers.end(), DeletePairedPointer());
- mTimers.clear();
-
- delete mTimerRoot;
+ return block_timer_tree_df_iterator_t(&id,
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::beginChildren), _1),
+ boost::bind(boost::mem_fn(&BlockTimerStatHandle::endChildren), _1));
}
- LLFastTimer::NamedTimer& createNamedTimer(const std::string& name, LLFastTimer::FrameState* state)
+block_timer_tree_df_iterator_t end_timer_tree()
{
- LLFastTimer::NamedTimer* timer = new LLFastTimer::NamedTimer(name);
- timer->setFrameState(state);
- timer->setParent(mTimerRoot);
- mTimers.insert(std::make_pair(name, timer));
+ return block_timer_tree_df_iterator_t();
+}
- return *timer;
- }
- LLFastTimer::NamedTimer* getTimerByName(const std::string& name)
+// sort child timers by name
+struct SortTimerByName
{
- timer_map_t::iterator found_it = mTimers.find(name);
- if (found_it != mTimers.end())
+ bool operator()(const BlockTimerStatHandle* i1, const BlockTimerStatHandle* i2)
{
- return found_it->second;
+ return i1->getName() < i2->getName();
}
- return NULL;
- }
-
- LLFastTimer::NamedTimer* getRootTimer() { return mTimerRoot; }
-
- typedef std::multimap<std::string, LLFastTimer::NamedTimer*> timer_map_t;
- timer_map_t::iterator beginTimers() { return mTimers.begin(); }
- timer_map_t::iterator endTimers() { return mTimers.end(); }
- S32 timerCount() { return mTimers.size(); }
-
-private:
- timer_map_t mTimers;
-
- LLFastTimer::NamedTimer* mTimerRoot;
- LLFastTimer::FrameState mRootFrameState;
};
-LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name, bool open )
-: mTimer(NamedTimerFactory::instance().createNamedTimer(name, &mFrameState))
+static BlockTimerStatHandle sRootTimer("root", NULL);
+BlockTimerStatHandle& BlockTimer::getRootTimeBlock()
{
- mTimer.setCollapsed(!open);
+ return sRootTimer;
+ }
+
+void BlockTimer::pushLog(LLSD log)
+{
+ LLMutexLock lock(sLogLock);
+
+ sLogQueue.push(log);
}
-LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name)
-: mTimer(NamedTimerFactory::instance().createNamedTimer(name, &mFrameState))
+void BlockTimer::setLogLock(LLMutex* lock)
{
+ sLogLock = lock;
}
+
//static
#if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
-U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
+U64 BlockTimer::countsPerSecond()
{
- return sClockResolution >> 8;
+ return sClockResolution;
}
#else // windows or x86-mac or x86-linux or x86-solaris
-U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
+U64 BlockTimer::countsPerSecond()
{
#if LL_FASTTIMER_USE_RDTSC || !LL_WINDOWS
//getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz
- static U64 sCPUClockFrequency = U64(LLProcessorInfo().getCPUFrequency()*1000000.0);
-
- // we drop the low-order byte in our timers, so report a lower frequency
+ static LLUnit<U64, LLUnits::Hertz> sCPUClockFrequency = LLProcessorInfo().getCPUFrequency();
+ return sCPUClockFrequency.value();
#else
// If we're not using RDTSC, each fasttimer tick is just a performance counter tick.
// Not redefining the clock frequency itself (in llprocessor.cpp/calculate_cpu_frequency())
@@ -194,270 +174,211 @@ U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
QueryPerformanceFrequency((LARGE_INTEGER*)&sCPUClockFrequency);
firstcall = false;
}
+ return sCPUClockFrequency.value();
#endif
- return sCPUClockFrequency >> 8;
}
#endif
-LLFastTimer::FrameState::FrameState()
-: mActiveCount(0),
- mCalls(0),
- mSelfTimeCounter(0),
- mParent(NULL),
- mLastCaller(NULL),
- mMoveUpTree(false)
+BlockTimerStatHandle::BlockTimerStatHandle(const char* name, const char* description)
+: StatType<TimeBlockAccumulator>(name, description)
{}
-
-LLFastTimer::NamedTimer::NamedTimer(const std::string& name)
-: mName(name),
- mCollapsed(true),
- mParent(NULL),
- mTotalTimeCounter(0),
- mCountAverage(0),
- mCallAverage(0),
- mNeedsSorting(false),
- mFrameState(NULL)
+TimeBlockTreeNode& BlockTimerStatHandle::getTreeNode() const
{
- mCountHistory = new U32[HISTORY_NUM];
- memset(mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
- mCallHistory = new U32[HISTORY_NUM];
- memset(mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
+ TimeBlockTreeNode* nodep = LLTrace::get_thread_recorder()->getTimeBlockTreeNode(getIndex());
+ llassert(nodep);
+ return *nodep;
}
-LLFastTimer::NamedTimer::~NamedTimer()
-{
- delete[] mCountHistory;
- delete[] mCallHistory;
-}
-std::string LLFastTimer::NamedTimer::getToolTip(S32 history_idx)
+void BlockTimer::bootstrapTimerTree()
{
- F64 ms_multiplier = 1000.0 / (F64)LLFastTimer::countsPerSecond();
- if (history_idx < 0)
- {
- // by default, show average number of call
- return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getCountAverage() * ms_multiplier), (S32)getCallAverage());
- }
- else
+ for (BlockTimerStatHandle::instance_tracker_t::instance_iter it = BlockTimerStatHandle::instance_tracker_t::beginInstances(), end_it = BlockTimerStatHandle::instance_tracker_t::endInstances();
+ it != end_it;
+ ++it)
{
- return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getHistoricalCount(history_idx) * ms_multiplier), (S32)getHistoricalCalls(history_idx));
- }
-}
+ BlockTimerStatHandle& timer = static_cast<BlockTimerStatHandle&>(*it);
+ if (&timer == &BlockTimer::getRootTimeBlock()) continue;
-void LLFastTimer::NamedTimer::setParent(NamedTimer* parent)
+ // bootstrap tree construction by attaching to last timer to be on stack
+ // when this timer was called
+ if (timer.getParent() == &BlockTimer::getRootTimeBlock())
{
- llassert_always(parent != this);
- llassert_always(parent != NULL);
+ TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
- if (mParent)
+ if (accumulator.mLastCaller)
{
- // subtract our accumulated from previous parent
- for (S32 i = 0; i < HISTORY_NUM; i++)
- {
- mParent->mCountHistory[i] -= mCountHistory[i];
- }
-
- // subtract average timing from previous parent
- mParent->mCountAverage -= mCountAverage;
-
- std::vector<NamedTimer*>& children = mParent->getChildren();
- std::vector<NamedTimer*>::iterator found_it = std::find(children.begin(), children.end(), this);
- if (found_it != children.end())
- {
- children.erase(found_it);
+ timer.setParent(accumulator.mLastCaller);
+ accumulator.mParent = accumulator.mLastCaller;
}
+ // no need to push up tree on first use, flag can be set spuriously
+ accumulator.mMoveUpTree = false;
}
-
- mParent = parent;
- if (parent)
- {
- getFrameState().mParent = &parent->getFrameState();
- parent->getChildren().push_back(this);
- parent->mNeedsSorting = true;
}
}
-S32 LLFastTimer::NamedTimer::getDepth()
+// bump timers up tree if they have been flagged as being in the wrong place
+// do this in a bottom up order to promote descendants first before promoting ancestors
+// this preserves partial order derived from current frame's observations
+void BlockTimer::incrementalUpdateTimerTree()
{
- S32 depth = 0;
- NamedTimer* timerp = mParent;
- while(timerp)
+ for(block_timer_tree_df_post_iterator_t it = begin_block_timer_tree_df_post(BlockTimer::getRootTimeBlock());
+ it != end_block_timer_tree_df_post();
+ ++it)
{
- depth++;
- if (timerp->getParent() == timerp) break;
- timerp = timerp->mParent;
- }
- return depth;
-}
+ BlockTimerStatHandle* timerp = *it;
-// static
-void LLFastTimer::NamedTimer::processTimes()
+ // sort timers by time last called, so call graph makes sense
+ TimeBlockTreeNode& tree_node = timerp->getTreeNode();
+ if (tree_node.mNeedsSorting)
{
- if (sCurFrameIndex < 0) return;
-
- buildHierarchy();
- accumulateTimings();
+ std::sort(tree_node.mChildren.begin(), tree_node.mChildren.end(), SortTimerByName());
}
-// sort child timers by name
-struct SortTimerByName
+ // skip root timer
+ if (timerp != &BlockTimer::getRootTimeBlock())
{
- bool operator()(const LLFastTimer::NamedTimer* i1, const LLFastTimer::NamedTimer* i2)
- {
- return i1->getName() < i2->getName();
- }
-};
+ TimeBlockAccumulator& accumulator = timerp->getCurrentAccumulator();
-//static
-void LLFastTimer::NamedTimer::buildHierarchy()
+ if (accumulator.mMoveUpTree)
{
- if (sCurFrameIndex < 0 ) return;
-
- // set up initial tree
- {
- for (instance_iter it = beginInstances(); it != endInstances(); ++it)
- {
- NamedTimer& timer = *it;
- if (&timer == NamedTimerFactory::instance().getRootTimer()) continue;
-
- // bootstrap tree construction by attaching to last timer to be on stack
- // when this timer was called
- if (timer.getFrameState().mLastCaller && timer.mParent == NamedTimerFactory::instance().getRootTimer())
- {
- timer.setParent(timer.getFrameState().mLastCaller->mTimer);
- // no need to push up tree on first use, flag can be set spuriously
- timer.getFrameState().mMoveUpTree = false;
- }
- }
- }
-
- // bump timers up tree if they've been flagged as being in the wrong place
- // do this in a bottom up order to promote descendants first before promoting ancestors
- // this preserves partial order derived from current frame's observations
- for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getRootTimer());
- it != end_timer_tree_bottom_up();
- ++it)
- {
- NamedTimer* timerp = *it;
- // skip root timer
- if (timerp == NamedTimerFactory::instance().getRootTimer()) continue;
-
- if (timerp->getFrameState().mMoveUpTree)
- {
- // since ancestors have already been visited, reparenting won't affect tree traversal
+ // since ancestors have already been visited, re-parenting won't affect tree traversal
//step up tree, bringing our descendants with us
LL_DEBUGS("FastTimers") << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() <<
" to child of " << timerp->getParent()->getParent()->getName() << LL_ENDL;
timerp->setParent(timerp->getParent()->getParent());
- timerp->getFrameState().mMoveUpTree = false;
+ accumulator.mParent = timerp->getParent();
+ accumulator.mMoveUpTree = false;
// don't bubble up any ancestors until descendants are done bubbling up
+ // as ancestors may call this timer only on certain paths, so we want to resolve
+ // child-most block locations before their parents
it.skipAncestors();
}
}
+ }
+}
- // sort timers by time last called, so call graph makes sense
- for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer());
- it != end_timer_tree();
- ++it)
+
+void BlockTimer::updateTimes()
{
- NamedTimer* timerp = (*it);
- if (timerp->mNeedsSorting)
+ // walk up stack of active timers and accumulate current time while leaving timing structures active
+ BlockTimerStackRecord* stack_record = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
+ if (!stack_record) return;
+
+ U64 cur_time = getCPUClockCount64();
+ BlockTimer* cur_timer = stack_record->mActiveTimer;
+ TimeBlockAccumulator* accumulator = &stack_record->mTimeBlock->getCurrentAccumulator();
+
+ while(cur_timer
+ && cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self
{
- std::sort(timerp->getChildren().begin(), timerp->getChildren().end(), SortTimerByName());
- }
- timerp->mNeedsSorting = false;
+ U64 cumulative_time_delta = cur_time - cur_timer->mStartTime;
+ cur_timer->mStartTime = cur_time;
+
+ accumulator->mTotalTimeCounter += cumulative_time_delta;
+ accumulator->mSelfTimeCounter += cumulative_time_delta - stack_record->mChildTime;
+ stack_record->mChildTime = 0;
+
+ stack_record = &cur_timer->mParentTimerData;
+ accumulator = &stack_record->mTimeBlock->getCurrentAccumulator();
+ cur_timer = stack_record->mActiveTimer;
+
+ stack_record->mChildTime += cumulative_time_delta;
}
}
+static LLTrace::BlockTimerStatHandle FTM_PROCESS_TIMES("Process FastTimer Times");
+
+// not thread safe, so only call on main thread
//static
-void LLFastTimer::NamedTimer::accumulateTimings()
+void BlockTimer::processTimes()
{
- U32 cur_time = getCPUClockCount32();
+#if LL_TRACE_ENABLED
+ LL_RECORD_BLOCK_TIME(FTM_PROCESS_TIMES);
+ get_clock_count(); // good place to calculate clock frequency
- // walk up stack of active timers and accumulate current time while leaving timing structures active
- LLFastTimer* cur_timer = sCurTimerData.mCurTimer;
- // root defined by parent pointing to self
- CurTimerData* cur_data = &sCurTimerData;
- while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
- {
- U32 cumulative_time_delta = cur_time - cur_timer->mStartTime;
- U32 self_time_delta = cumulative_time_delta - cur_data->mChildTime;
- cur_data->mChildTime = 0;
- cur_timer->mFrameState->mSelfTimeCounter += self_time_delta;
- cur_timer->mStartTime = cur_time;
+ // set up initial tree
+ bootstrapTimerTree();
- cur_data = &cur_timer->mLastTimerData;
- cur_data->mChildTime += cumulative_time_delta;
+ incrementalUpdateTimerTree();
- cur_timer = cur_timer->mLastTimerData.mCurTimer;
- }
+ updateTimes();
- // traverse tree in DFS post order, or bottom up
- for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getRootTimer());
- it != end_timer_tree_bottom_up();
+ // reset for next frame
+ for (BlockTimerStatHandle::instance_tracker_t::instance_iter it = BlockTimerStatHandle::instance_tracker_t::beginInstances(),
+ end_it = BlockTimerStatHandle::instance_tracker_t::endInstances();
+ it != end_it;
++it)
{
- NamedTimer* timerp = (*it);
- timerp->mTotalTimeCounter = timerp->getFrameState().mSelfTimeCounter;
- for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it)
+ BlockTimerStatHandle& timer = static_cast<BlockTimerStatHandle&>(*it);
+ TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
+
+ accumulator.mLastCaller = NULL;
+ accumulator.mMoveUpTree = false;
+ }
+#endif
+}
+
+std::vector<BlockTimerStatHandle*>::iterator BlockTimerStatHandle::beginChildren()
{
- timerp->mTotalTimeCounter += (*child_it)->mTotalTimeCounter;
+ return getTreeNode().mChildren.begin();
}
- S32 cur_frame = sCurFrameIndex;
- if (cur_frame >= 0)
+std::vector<BlockTimerStatHandle*>::iterator BlockTimerStatHandle::endChildren()
{
- // update timer history
- int hidx = cur_frame % HISTORY_NUM;
+ return getTreeNode().mChildren.end();
+}
- timerp->mCountHistory[hidx] = timerp->mTotalTimeCounter;
- timerp->mCountAverage = ((U64)timerp->mCountAverage * cur_frame + timerp->mTotalTimeCounter) / (cur_frame+1);
- timerp->mCallHistory[hidx] = timerp->getFrameState().mCalls;
- timerp->mCallAverage = ((U64)timerp->mCallAverage * cur_frame + timerp->getFrameState().mCalls) / (cur_frame+1);
- }
+std::vector<BlockTimerStatHandle*>& BlockTimerStatHandle::getChildren()
+{
+ return getTreeNode().mChildren;
}
+
+bool BlockTimerStatHandle::hasChildren()
+{
+ return ! getTreeNode().mChildren.empty();
}
// static
-void LLFastTimer::NamedTimer::resetFrame()
+void BlockTimer::logStats()
{
+ // get ready for next frame
if (sLog)
{ //output current frame counts to performance log
static S32 call_count = 0;
if (call_count % 100 == 0)
{
- LL_DEBUGS("FastTimers") << "countsPerSecond (32 bit): " << countsPerSecond() << LL_ENDL;
- LL_DEBUGS("FastTimers") << "get_clock_count (64 bit): " << get_clock_count() << llendl;
+ LL_DEBUGS("FastTimers") << "countsPerSecond: " << countsPerSecond() << LL_ENDL;
LL_DEBUGS("FastTimers") << "LLProcessorInfo().getCPUFrequency() " << LLProcessorInfo().getCPUFrequency() << LL_ENDL;
LL_DEBUGS("FastTimers") << "getCPUClockCount32() " << getCPUClockCount32() << LL_ENDL;
LL_DEBUGS("FastTimers") << "getCPUClockCount64() " << getCPUClockCount64() << LL_ENDL;
- LL_DEBUGS("FastTimers") << "elapsed sec " << ((F64)getCPUClockCount64())/((F64)LLProcessorInfo().getCPUFrequency()*1000000.0) << LL_ENDL;
+ LL_DEBUGS("FastTimers") << "elapsed sec " << ((F64)getCPUClockCount64() / (F64HertzImplicit)LLProcessorInfo().getCPUFrequency()) << LL_ENDL;
}
call_count++;
- F64 iclock_freq = 1000.0 / countsPerSecond(); // good place to calculate clock frequency
-
- F64 total_time = 0;
+ F64Seconds total_time(0);
LLSD sd;
{
- for (instance_iter it = beginInstances(); it != endInstances(); ++it)
+ for (BlockTimerStatHandle::instance_tracker_t::instance_iter it = BlockTimerStatHandle::instance_tracker_t::beginInstances(),
+ end_it = BlockTimerStatHandle::instance_tracker_t::endInstances();
+ it != end_it;
+ ++it)
{
- NamedTimer& timer = *it;
- FrameState& info = timer.getFrameState();
- sd[timer.getName()]["Time"] = (LLSD::Real) (info.mSelfTimeCounter*iclock_freq);
- sd[timer.getName()]["Calls"] = (LLSD::Integer) info.mCalls;
+ BlockTimerStatHandle& timer = static_cast<BlockTimerStatHandle&>(*it);
+ LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
+ sd[timer.getName()]["Time"] = (LLSD::Real) (frame_recording.getLastRecording().getSum(timer).value());
+ sd[timer.getName()]["Calls"] = (LLSD::Integer) (frame_recording.getLastRecording().getSum(timer.callCount()));
// computing total time here because getting the root timer's getCountHistory
// doesn't work correctly on the first frame
- total_time = total_time + info.mSelfTimeCounter * iclock_freq;
+ total_time += frame_recording.getLastRecording().getSum(timer);
}
}
- sd["Total"]["Time"] = (LLSD::Real) total_time;
+ sd["Total"]["Time"] = (LLSD::Real) total_time.value();
sd["Total"]["Calls"] = (LLSD::Integer) 1;
{
@@ -466,168 +387,44 @@ void LLFastTimer::NamedTimer::resetFrame()
}
}
- // reset for next frame
- for (instance_iter it = beginInstances(); it != endInstances(); ++it)
- {
- NamedTimer& timer = *it;
-
- FrameState& info = timer.getFrameState();
- info.mSelfTimeCounter = 0;
- info.mCalls = 0;
- info.mLastCaller = NULL;
- info.mMoveUpTree = false;
- // update parent pointer in timer state struct
- if (timer.mParent)
- {
- info.mParent = &timer.mParent->getFrameState();
- }
- }
-}
-
-//static
-void LLFastTimer::NamedTimer::reset()
-{
- resetFrame(); // reset frame data
-
- // walk up stack of active timers and reset start times to current time
- // effectively zeroing out any accumulated time
- U32 cur_time = getCPUClockCount32();
-
- // root defined by parent pointing to self
- CurTimerData* cur_data = &sCurTimerData;
- LLFastTimer* cur_timer = cur_data->mCurTimer;
- while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer)
- {
- cur_timer->mStartTime = cur_time;
- cur_data->mChildTime = 0;
-
- cur_data = &cur_timer->mLastTimerData;
- cur_timer = cur_data->mCurTimer;
- }
-
- // reset all history
- {
- for (instance_iter it = beginInstances(); it != endInstances(); ++it)
- {
- NamedTimer& timer = *it;
- if (&timer != NamedTimerFactory::instance().getRootTimer())
- {
- timer.setParent(NamedTimerFactory::instance().getRootTimer());
- }
-
- timer.mCountAverage = 0;
- timer.mCallAverage = 0;
- memset(timer.mCountHistory, 0, sizeof(U32) * HISTORY_NUM);
- memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM);
- }
- }
-
- sLastFrameIndex = 0;
- sCurFrameIndex = 0;
-}
-
-U32 LLFastTimer::NamedTimer::getHistoricalCount(S32 history_index) const
-{
- S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM;
- return mCountHistory[history_idx];
-}
-
-U32 LLFastTimer::NamedTimer::getHistoricalCalls(S32 history_index ) const
-{
- S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM;
- return mCallHistory[history_idx];
-}
-
-LLFastTimer::FrameState& LLFastTimer::NamedTimer::getFrameState() const
-{
- return *mFrameState;
-}
-
-std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::beginChildren()
-{
- return mChildren.begin();
-}
-
-std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::endChildren()
-{
- return mChildren.end();
-}
-
-std::vector<LLFastTimer::NamedTimer*>& LLFastTimer::NamedTimer::getChildren()
-{
- return mChildren;
-}
-
-//static
-LLFastTimer::NamedTimer& LLFastTimer::NamedTimer::getRootNamedTimer()
-{
- return *NamedTimerFactory::instance().getRootTimer();
-}
-
-//static
-void LLFastTimer::nextFrame()
-{
- countsPerSecond(); // good place to calculate clock frequency
- U64 frame_time = getCPUClockCount64();
- if ((frame_time - sLastFrameTime) >> 8 > 0xffffffff)
- {
- llinfos << "Slow frame, fast timers inaccurate" << llendl;
- }
-
- if (!sPauseHistory)
- {
- NamedTimer::processTimes();
- sLastFrameIndex = sCurFrameIndex++;
- }
-
- // get ready for next frame
- NamedTimer::resetFrame();
- sLastFrameTime = frame_time;
}
//static
-void LLFastTimer::dumpCurTimes()
+void BlockTimer::dumpCurTimes()
{
- // accumulate timings, etc.
- NamedTimer::processTimes();
-
- F64 clock_freq = (F64)countsPerSecond();
- F64 iclock_freq = 1000.0 / clock_freq; // clock_ticks -> milliseconds
+ LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording();
+ LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording();
// walk over timers in depth order and output timings
- for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer());
+ for(block_timer_tree_df_iterator_t it = begin_timer_tree(BlockTimer::getRootTimeBlock());
it != end_timer_tree();
++it)
{
- NamedTimer* timerp = (*it);
- F64 total_time_ms = ((F64)timerp->getHistoricalCount(0) * iclock_freq);
+ BlockTimerStatHandle* timerp = (*it);
+ F64Seconds total_time = last_frame_recording.getSum(*timerp);
+ U32 num_calls = last_frame_recording.getSum(timerp->callCount());
+
// Don't bother with really brief times, keep output concise
- if (total_time_ms < 0.1) continue;
+ if (total_time < F32Milliseconds(0.1f)) continue;
std::ostringstream out_str;
- for (S32 i = 0; i < timerp->getDepth(); i++)
+ BlockTimerStatHandle* parent_timerp = timerp;
+ while(parent_timerp && parent_timerp != parent_timerp->getParent())
{
out_str << "\t";
+ parent_timerp = parent_timerp->getParent();
}
-
out_str << timerp->getName() << " "
- << std::setprecision(3) << total_time_ms << " ms, "
- << timerp->getHistoricalCalls(0) << " calls";
+ << std::setprecision(3) << total_time.valueInUnits<LLUnits::Milliseconds>() << " ms, "
+ << num_calls << " calls";
- llinfos << out_str.str() << llendl;
- }
+ LL_INFOS() << out_str.str() << LL_ENDL;
}
-
-//static
-void LLFastTimer::reset()
-{
- NamedTimer::reset();
}
-
//static
-void LLFastTimer::writeLog(std::ostream& os)
+void BlockTimer::writeLog(std::ostream& os)
{
while (!sLogQueue.empty())
{
@@ -638,22 +435,57 @@ void LLFastTimer::writeLog(std::ostream& os)
}
}
-//static
-const LLFastTimer::NamedTimer* LLFastTimer::getTimerByName(const std::string& name)
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// TimeBlockAccumulator
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+TimeBlockAccumulator::TimeBlockAccumulator()
+: mTotalTimeCounter(0),
+ mSelfTimeCounter(0),
+ mCalls(0),
+ mLastCaller(NULL),
+ mActiveCount(0),
+ mMoveUpTree(false),
+ mParent(NULL)
+{}
+
+void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other, EBufferAppendType append_type )
{
- return NamedTimerFactory::instance().getTimerByName(name);
+#if LL_TRACE_ENABLED
+ // we can't merge two unrelated time block samples, as that will screw with the nested timings
+ // due to the call hierarchy of each thread
+ llassert(append_type == SEQUENTIAL);
+ mTotalTimeCounter += other.mTotalTimeCounter;
+ mSelfTimeCounter += other.mSelfTimeCounter;
+ mCalls += other.mCalls;
+ mLastCaller = other.mLastCaller;
+ mActiveCount = other.mActiveCount;
+ mMoveUpTree = other.mMoveUpTree;
+ mParent = other.mParent;
+#endif
}
-LLFastTimer::LLFastTimer(LLFastTimer::FrameState* state)
-: mFrameState(state)
+void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other )
+{
+ mCalls = 0;
+ mSelfTimeCounter = 0;
+ mTotalTimeCounter = 0;
+
+ if (other)
{
- U32 start_time = getCPUClockCount32();
- mStartTime = start_time;
- mFrameState->mActiveCount++;
- LLFastTimer::sCurTimerData.mCurTimer = this;
- LLFastTimer::sCurTimerData.mFrameState = mFrameState;
- LLFastTimer::sCurTimerData.mChildTime = 0;
- mLastTimerData = LLFastTimer::sCurTimerData;
+ mLastCaller = other->mLastCaller;
+ mActiveCount = other->mActiveCount;
+ mMoveUpTree = other->mMoveUpTree;
+ mParent = other->mParent;
+ }
+}
+
+F64Seconds BlockTimer::getElapsedTime()
+{
+ U64 total_time = getCPUClockCount64() - mStartTime;
+
+ return F64Seconds((F64)total_time / (F64)BlockTimer::countsPerSecond());
}
+} // namespace LLTrace
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index a99a1d88af..2370253078 100755
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -28,218 +28,30 @@
#define LL_FASTTIMER_H
#include "llinstancetracker.h"
+#include "lltrace.h"
+#include "lltreeiterators.h"
-#define FAST_TIMER_ON 1
-#define DEBUG_FAST_TIMER_THREADS 1
-
-class LLMutex;
-
-#include <queue>
-#include "llsd.h"
-
+#define LL_FAST_TIMER_ON 1
#define LL_FASTTIMER_USE_RDTSC 1
+#define LL_RECORD_BLOCK_TIME(timer_stat) const LLTrace::BlockTimer& LL_GLUE_TOKENS(block_time_recorder, __LINE__)(LLTrace::timeThisBlock(timer_stat)); (void)LL_GLUE_TOKENS(block_time_recorder, __LINE__);
-LL_COMMON_API void assert_main_thread();
-
-class LL_COMMON_API LLFastTimer
+namespace LLTrace
{
-public:
- class NamedTimer;
-
- struct LL_COMMON_API FrameState
- {
- FrameState();
- void setNamedTimer(NamedTimer* timerp) { mTimer = timerp; }
-
- U32 mSelfTimeCounter;
- U32 mCalls;
- FrameState* mParent; // info for caller timer
- FrameState* mLastCaller; // used to bootstrap tree construction
- NamedTimer* mTimer;
- U16 mActiveCount; // number of timers with this ID active on stack
- bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
- };
-
- // stores a "named" timer instance to be reused via multiple LLFastTimer stack instances
- class LL_COMMON_API NamedTimer
- : public LLInstanceTracker<NamedTimer>
- {
- friend class DeclareTimer;
- public:
- ~NamedTimer();
-
- enum { HISTORY_NUM = 300 };
-
- const std::string& getName() const { return mName; }
- NamedTimer* getParent() const { return mParent; }
- void setParent(NamedTimer* parent);
- S32 getDepth();
- std::string getToolTip(S32 history_index = -1);
-
- typedef std::vector<NamedTimer*>::const_iterator child_const_iter;
- child_const_iter beginChildren();
- child_const_iter endChildren();
- std::vector<NamedTimer*>& getChildren();
-
- void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
- bool getCollapsed() const { return mCollapsed; }
-
- U32 getCountAverage() const { return mCountAverage; }
- U32 getCallAverage() const { return mCallAverage; }
-
- U32 getHistoricalCount(S32 history_index = 0) const;
- U32 getHistoricalCalls(S32 history_index = 0) const;
-
- static NamedTimer& getRootNamedTimer();
-
- void setFrameState(FrameState* state) { mFrameState = state; state->setNamedTimer(this); }
- FrameState& getFrameState() const;
-
- private:
- friend class LLFastTimer;
- friend class NamedTimerFactory;
-
- //
- // methods
- //
- NamedTimer(const std::string& name);
- // recursive call to gather total time from children
- static void accumulateTimings();
-
- // updates cumulative times and hierarchy,
- // can be called multiple times in a frame, at any point
- static void processTimes();
-
- static void buildHierarchy();
- static void resetFrame();
- static void reset();
-
- //
- // members
- //
- FrameState* mFrameState;
-
- std::string mName;
-
- U32 mTotalTimeCounter;
-
- U32 mCountAverage;
- U32 mCallAverage;
-
- U32* mCountHistory;
- U32* mCallHistory;
-
- // tree structure
- NamedTimer* mParent; // NamedTimer of caller(parent)
- std::vector<NamedTimer*> mChildren;
- bool mCollapsed; // don't show children
- bool mNeedsSorting; // sort children whenever child added
- };
-
- // used to statically declare a new named timer
- class LL_COMMON_API DeclareTimer
- : public LLInstanceTracker< DeclareTimer >
- {
- friend class LLFastTimer;
- public:
-
- DeclareTimer(const std::string& name, bool open);
- DeclareTimer(const std::string& name);
-
- NamedTimer& getNamedTimer() { return mTimer; }
-
- private:
- FrameState mFrameState;
- NamedTimer& mTimer;
- };
-
-public:
- LLFastTimer(LLFastTimer::FrameState* state);
-
- LL_FORCE_INLINE LLFastTimer(LLFastTimer::DeclareTimer& timer)
- : mFrameState(&timer.mFrameState)
- {
-#if FAST_TIMER_ON
- LLFastTimer::FrameState* frame_state = mFrameState;
- mStartTime = getCPUClockCount32();
-
- frame_state->mActiveCount++;
- frame_state->mCalls++;
- // keep current parent as long as it is active when we are
- frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0);
-
- LLFastTimer::CurTimerData* cur_timer_data = &LLFastTimer::sCurTimerData;
- mLastTimerData = *cur_timer_data;
- cur_timer_data->mCurTimer = this;
- cur_timer_data->mFrameState = frame_state;
- cur_timer_data->mChildTime = 0;
-#endif
-#if DEBUG_FAST_TIMER_THREADS
-#if !LL_RELEASE
- assert_main_thread();
-#endif
-#endif
- }
-
- LL_FORCE_INLINE ~LLFastTimer()
- {
-#if FAST_TIMER_ON
- LLFastTimer::FrameState* frame_state = mFrameState;
- U32 total_time = getCPUClockCount32() - mStartTime;
-
- frame_state->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime;
- frame_state->mActiveCount--;
-
- // store last caller to bootstrap tree creation
- // do this in the destructor in case of recursion to get topmost caller
- frame_state->mLastCaller = mLastTimerData.mFrameState;
-
- // we are only tracking self time, so subtract our total time delta from parents
- mLastTimerData.mChildTime += total_time;
-
- LLFastTimer::sCurTimerData = mLastTimerData;
-#endif
- }
+// use to create blocktimer rvalue to be captured in a reference so that the BlockTimer lives to the end of the block.
+class BlockTimer timeThisBlock(class BlockTimerStatHandle& timer);
+class BlockTimer
+{
public:
- static LLMutex* sLogLock;
- static std::queue<LLSD> sLogQueue;
- static BOOL sLog;
- static BOOL sMetricLog;
- static std::string sLogName;
- static bool sPauseHistory;
- static bool sResetHistory;
-
- // call this once a frame to reset timers
- static void nextFrame();
+ typedef BlockTimer self_t;
+ typedef class BlockTimerStatHandle DeclareTimer;
- // dumps current cumulative frame stats to log
- // call nextFrame() to reset timers
- static void dumpCurTimes();
+ ~BlockTimer();
- // call this to reset timer hierarchy, averages, etc.
- static void reset();
+ F64Seconds getElapsedTime();
- static U64 countsPerSecond();
- static S32 getLastFrameIndex() { return sLastFrameIndex; }
- static S32 getCurFrameIndex() { return sCurFrameIndex; }
-
- static void writeLog(std::ostream& os);
- static const NamedTimer* getTimerByName(const std::string& name);
-
- struct CurTimerData
- {
- LLFastTimer* mCurTimer;
- FrameState* mFrameState;
- U32 mChildTime;
- };
- static CurTimerData sCurTimerData;
-
-private:
-
-
- //////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////
//
// Important note: These implementations must be FAST!
//
@@ -261,14 +73,14 @@ private:
//#undef _interlockedbittestandset
//#undef _interlockedbittestandreset
- //inline U32 LLFastTimer::getCPUClockCount32()
+ //inline U32 getCPUClockCount32()
//{
// U64 time_stamp = __rdtsc();
// return (U32)(time_stamp >> 8);
//}
//
//// return full timer value, *not* shifted by 8 bits
- //inline U64 LLFastTimer::getCPUClockCount64()
+ //inline U64 getCPUClockCount64()
//{
// return __rdtsc();
//}
@@ -308,7 +120,7 @@ private:
}
#else
- //LL_COMMON_API U64 get_clock_count(); // in lltimer.cpp
+ //U64 get_clock_count(); // in lltimer.cpp
// These use QueryPerformanceCounter, which is arguably fine and also works on AMD architectures.
static U32 getCPUClockCount32()
{
@@ -375,18 +187,160 @@ private:
#endif
- static U64 sClockResolution;
+ static BlockTimerStatHandle& getRootTimeBlock();
+ static void pushLog(LLSD sd);
+ static void setLogLock(class LLMutex* mutex);
+ static void writeLog(std::ostream& os);
+ static void updateTimes();
+
+ static U64 countsPerSecond();
+
+ // updates cumulative times and hierarchy,
+ // can be called multiple times in a frame, at any point
+ static void processTimes();
- static S32 sCurFrameIndex;
- static S32 sLastFrameIndex;
- static U64 sLastFrameTime;
+ static void bootstrapTimerTree();
+ static void incrementalUpdateTimerTree();
- U32 mStartTime;
- LLFastTimer::FrameState* mFrameState;
- LLFastTimer::CurTimerData mLastTimerData;
+ // call this once a frame to periodically log timers
+ static void logStats();
+
+ // dumps current cumulative frame stats to log
+ // call nextFrame() to reset timers
+ static void dumpCurTimes();
+
+private:
+ friend class BlockTimerStatHandle;
+ // FIXME: this friendship exists so that each thread can instantiate a root timer,
+ // which could be a derived class with a public constructor instead, possibly
+ friend class ThreadRecorder;
+ friend BlockTimer timeThisBlock(BlockTimerStatHandle&);
+
+ BlockTimer(BlockTimerStatHandle& timer);
+#if !defined(MSC_VER) || MSC_VER < 1700
+ // Visual Studio 2010 has a bug where capturing an object returned by value
+ // into a local reference requires access to the copy constructor at the call site.
+ // This appears to be fixed in 2012.
+public:
+#endif
+ // no-copy
+ BlockTimer(const BlockTimer& other) {};
+
+private:
+ U64 mStartTime;
+ BlockTimerStackRecord mParentTimerData;
+
+public:
+ // statics
+ static std::string sLogName;
+ static bool sMetricLog,
+ sLog;
+ static U64 sClockResolution;
};
-typedef class LLFastTimer LLFastTimer;
+// this dummy function assists in allocating a block timer with stack-based lifetime.
+// this is done by capturing the return value in a stack-allocated const reference variable.
+// (This is most easily done using the macro LL_RECORD_BLOCK_TIME)
+// Otherwise, it would be possible to store a BlockTimer on the heap, resulting in non-nested lifetimes,
+// which would break the invariants of the timing hierarchy logic
+LL_FORCE_INLINE class BlockTimer timeThisBlock(class BlockTimerStatHandle& timer)
+{
+ return BlockTimer(timer);
+}
+
+// stores a "named" timer instance to be reused via multiple BlockTimer stack instances
+class BlockTimerStatHandle
+: public StatType<TimeBlockAccumulator>
+{
+public:
+ BlockTimerStatHandle(const char* name, const char* description = "");
+
+ TimeBlockTreeNode& getTreeNode() const;
+ BlockTimerStatHandle* getParent() const { return getTreeNode().getParent(); }
+ void setParent(BlockTimerStatHandle* parent) { getTreeNode().setParent(parent); }
+
+ typedef std::vector<BlockTimerStatHandle*>::iterator child_iter;
+ typedef std::vector<BlockTimerStatHandle*>::const_iterator child_const_iter;
+ child_iter beginChildren();
+ child_iter endChildren();
+ bool hasChildren();
+ std::vector<BlockTimerStatHandle*>& getChildren();
+
+ StatType<TimeBlockAccumulator::CallCountFacet>& callCount()
+ {
+ return static_cast<StatType<TimeBlockAccumulator::CallCountFacet>&>(*(StatType<TimeBlockAccumulator>*)this);
+ }
+
+ StatType<TimeBlockAccumulator::SelfTimeFacet>& selfTime()
+ {
+ return static_cast<StatType<TimeBlockAccumulator::SelfTimeFacet>&>(*(StatType<TimeBlockAccumulator>*)this);
+ }
+
+ bool mCollapsed; // don't show children
+};
+
+// iterators and helper functions for walking the call hierarchy of block timers in different ways
+typedef LLTreeDFSIter<BlockTimerStatHandle, BlockTimerStatHandle::child_const_iter> block_timer_tree_df_iterator_t;
+typedef LLTreeDFSPostIter<BlockTimerStatHandle, BlockTimerStatHandle::child_const_iter> block_timer_tree_df_post_iterator_t;
+typedef LLTreeBFSIter<BlockTimerStatHandle, BlockTimerStatHandle::child_const_iter> block_timer_tree_bf_iterator_t;
+
+block_timer_tree_df_iterator_t begin_block_timer_tree_df(BlockTimerStatHandle& id);
+block_timer_tree_df_iterator_t end_block_timer_tree_df();
+block_timer_tree_df_post_iterator_t begin_block_timer_tree_df_post(BlockTimerStatHandle& id);
+block_timer_tree_df_post_iterator_t end_block_timer_tree_df_post();
+block_timer_tree_bf_iterator_t begin_block_timer_tree_bf(BlockTimerStatHandle& id);
+block_timer_tree_bf_iterator_t end_block_timer_tree_bf();
+
+LL_FORCE_INLINE BlockTimer::BlockTimer(BlockTimerStatHandle& timer)
+{
+#if LL_FAST_TIMER_ON
+ BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
+ if (!cur_timer_data) return;
+ TimeBlockAccumulator& accumulator = timer.getCurrentAccumulator();
+ accumulator.mActiveCount++;
+ // keep current parent as long as it is active when we are
+ accumulator.mMoveUpTree |= (accumulator.mParent->getCurrentAccumulator().mActiveCount == 0);
+
+ // store top of stack
+ mParentTimerData = *cur_timer_data;
+ // push new information
+ cur_timer_data->mActiveTimer = this;
+ cur_timer_data->mTimeBlock = &timer;
+ cur_timer_data->mChildTime = 0;
+
+ mStartTime = getCPUClockCount64();
+#endif
+}
+
+LL_FORCE_INLINE BlockTimer::~BlockTimer()
+{
+#if LL_FAST_TIMER_ON
+ U64 total_time = getCPUClockCount64() - mStartTime;
+ BlockTimerStackRecord* cur_timer_data = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
+ if (!cur_timer_data) return;
+
+ TimeBlockAccumulator& accumulator = cur_timer_data->mTimeBlock->getCurrentAccumulator();
+
+ accumulator.mCalls++;
+ accumulator.mTotalTimeCounter += total_time;
+ accumulator.mSelfTimeCounter += total_time - cur_timer_data->mChildTime;
+ accumulator.mActiveCount--;
+
+ // store last caller to bootstrap tree creation
+ // do this in the destructor in case of recursion to get topmost caller
+ accumulator.mLastCaller = mParentTimerData.mTimeBlock;
+
+ // we are only tracking self time, so subtract our total time delta from parents
+ mParentTimerData.mChildTime += total_time;
+
+ //pop stack
+ *cur_timer_data = mParentTimerData;
+#endif
+}
+
+}
+
+typedef LLTrace::BlockTimer LLFastTimer;
#endif // LL_LLFASTTIMER_H
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index c3a0f0bfe0..259187c52f 100755
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -28,7 +28,7 @@
*/
#if LL_WINDOWS
-#include <windows.h>
+#include "llwin32headerslean.h"
#include <stdlib.h> // Windows errno
#else
#include <errno.h>
@@ -265,6 +265,37 @@ int LLFile::rename(const std::string& filename, const std::string& newname)
return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc);
}
+bool LLFile::copy(const std::string from, const std::string to)
+{
+ bool copied = false;
+ LLFILE* in = LLFile::fopen(from, "rb"); /* Flawfinder: ignore */
+ if (in)
+ {
+ LLFILE* out = LLFile::fopen(to, "wb"); /* Flawfinder: ignore */
+ if (out)
+ {
+ char buf[16384]; /* Flawfinder: ignore */
+ size_t readbytes;
+ bool write_ok = true;
+ while(write_ok && (readbytes = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */
+ {
+ if (fwrite(buf, 1, readbytes, out) != readbytes)
+ {
+ LL_WARNS("LLFile") << "Short write" << LL_ENDL;
+ write_ok = false;
+ }
+ }
+ if ( write_ok )
+ {
+ copied = true;
+ }
+ fclose(out);
+ }
+ fclose(in);
+ }
+ return copied;
+}
+
int LLFile::stat(const std::string& filename, llstat* filestatus)
{
#if LL_WINDOWS
@@ -438,7 +469,7 @@ llstdio_filebuf::int_type llstdio_filebuf::overflow(llstdio_filebuf::int_type __
_M_set_buffer(0);
__ret = traits_type::not_eof(__c);
}
- }
+ }
else if (_M_buf_size > 1)
{
// Overflow in 'uncommitted' mode: set _M_writing, set
@@ -496,11 +527,11 @@ bool llstdio_filebuf::_convert_to_external(char_type* __ibuf,
if (__r == codecvt_base::ok || __r == codecvt_base::partial)
__blen = __bend - __buf;
else if (__r == codecvt_base::noconv)
- {
+ {
// Same as the always_noconv case above.
__buf = reinterpret_cast<char*>(__ibuf);
__blen = __ilen;
- }
+ }
else
__throw_ios_failure(__N("llstdio_filebuf::_convert_to_external "
"conversion error"));
@@ -643,9 +674,9 @@ llstdio_filebuf::int_type llstdio_filebuf::underflow()
_M_ext_end, _M_ext_next,
this->eback(),
this->eback() + __buflen, __iend);
-}
+ }
if (__r == codecvt_base::noconv)
-{
+ {
size_t __avail = _M_ext_end - _M_ext_buf;
__ilen = std::min(__avail, __buflen);
traits_type::copy(this->eback(),
@@ -806,15 +837,15 @@ std::streamsize llstdio_filebuf::xsputn(char_type* __s, std::streamsize __n)
__ret = fwrite(__buf, 1, __buffill, _M_file.file());
}
if (__ret == __buffill)
- {
+ {
__ret += fwrite(reinterpret_cast<const char*>(__s), 1,
__n, _M_file.file());
- }
+ }
if (__ret == __buffill + __n)
{
_M_set_buffer(0);
_M_writing = true;
-}
+ }
if (__ret > __buffill)
__ret -= __buffill;
else
@@ -848,7 +879,7 @@ llifstream::llifstream() : _M_filebuf(),
#endif
// explicit
-llifstream::llifstream(const std::string& _Filename,
+llifstream::llifstream(const std::string& _Filename,
ios_base::openmode _Mode) : _M_filebuf(),
#if LL_WINDOWS
std::istream(&_M_filebuf)
@@ -877,7 +908,7 @@ llifstream::llifstream(const char* _Filename,
if (_M_filebuf.open(wideName.c_str(), _Mode | ios_base::in) == 0)
{
_Myios::setstate(ios_base::failbit);
-}
+ }
}
#else
std::istream()
@@ -951,8 +982,8 @@ void llifstream::close()
#else
this->setstate(ios_base::failbit);
#endif
- }
}
+}
/************** output file stream ********************************/
@@ -1042,7 +1073,7 @@ void llofstream::open(const char* _Filename, ios_base::openmode _Mode)
#if LL_WINDOWS
llutf16string wideName = utf8str_to_utf16str( _Filename );
if (_M_filebuf.open( wideName.c_str(), _Mode | ios_base::out) == 0)
-{
+ {
_Myios::setstate(ios_base::failbit);
}
else
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index d59e68367e..f56b22bf9a 100755
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -75,6 +75,8 @@ public:
static int rmdir(const std::string& filename);
static int remove(const std::string& filename);
static int rename(const std::string& filename,const std::string& newname);
+ static bool copy(const std::string from, const std::string to);
+
static int stat(const std::string& filename,llstat* file_status);
static bool isdir(const std::string& filename);
static bool isfile(const std::string& filename);
diff --git a/indra/llcommon/llfindlocale.cpp b/indra/llcommon/llfindlocale.cpp
index cd7c0c7c09..f019bd0c64 100755
--- a/indra/llcommon/llfindlocale.cpp
+++ b/indra/llcommon/llfindlocale.cpp
@@ -33,7 +33,7 @@
#include <ctype.h>
#ifdef WIN32
-#include <windows.h>
+#include "llwin32headers.h"
#include <winnt.h>
#endif
diff --git a/indra/llcommon/llfoldertype.cpp b/indra/llcommon/llfoldertype.cpp
deleted file mode 100755
index f6d0f5bce8..0000000000
--- a/indra/llcommon/llfoldertype.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-/**
- * @file llfoldertype.cpp
- * @brief Implementatino of LLFolderType functionality.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llfoldertype.h"
-#include "lldictionary.h"
-#include "llmemory.h"
-#include "llsingleton.h"
-
-///----------------------------------------------------------------------------
-/// Class LLFolderType
-///----------------------------------------------------------------------------
-struct FolderEntry : public LLDictionaryEntry
-{
- FolderEntry(const std::string &type_name, // 8 character limit!
- bool is_protected) // can the viewer change categories of this type?
- :
- LLDictionaryEntry(type_name),
- mIsProtected(is_protected)
- {
- llassert(type_name.length() <= 8);
- }
-
- const bool mIsProtected;
-};
-
-class LLFolderDictionary : public LLSingleton<LLFolderDictionary>,
- public LLDictionary<LLFolderType::EType, FolderEntry>
-{
-public:
- LLFolderDictionary();
-protected:
- virtual LLFolderType::EType notFound() const
- {
- return LLFolderType::FT_NONE;
- }
-};
-
-LLFolderDictionary::LLFolderDictionary()
-{
- // TYPE NAME PROTECTED
- // |-----------|---------|
- addEntry(LLFolderType::FT_TEXTURE, new FolderEntry("texture", TRUE));
- addEntry(LLFolderType::FT_SOUND, new FolderEntry("sound", TRUE));
- addEntry(LLFolderType::FT_CALLINGCARD, new FolderEntry("callcard", TRUE));
- addEntry(LLFolderType::FT_LANDMARK, new FolderEntry("landmark", TRUE));
- addEntry(LLFolderType::FT_CLOTHING, new FolderEntry("clothing", TRUE));
- addEntry(LLFolderType::FT_OBJECT, new FolderEntry("object", TRUE));
- addEntry(LLFolderType::FT_NOTECARD, new FolderEntry("notecard", TRUE));
- addEntry(LLFolderType::FT_ROOT_INVENTORY, new FolderEntry("root_inv", TRUE));
- addEntry(LLFolderType::FT_LSL_TEXT, new FolderEntry("lsltext", TRUE));
- addEntry(LLFolderType::FT_BODYPART, new FolderEntry("bodypart", TRUE));
- addEntry(LLFolderType::FT_TRASH, new FolderEntry("trash", TRUE));
- addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, new FolderEntry("snapshot", TRUE));
- addEntry(LLFolderType::FT_LOST_AND_FOUND, new FolderEntry("lstndfnd", TRUE));
- addEntry(LLFolderType::FT_ANIMATION, new FolderEntry("animatn", TRUE));
- addEntry(LLFolderType::FT_GESTURE, new FolderEntry("gesture", TRUE));
- addEntry(LLFolderType::FT_FAVORITE, new FolderEntry("favorite", TRUE));
-
- for (S32 ensemble_num = S32(LLFolderType::FT_ENSEMBLE_START); ensemble_num <= S32(LLFolderType::FT_ENSEMBLE_END); ensemble_num++)
- {
- addEntry(LLFolderType::EType(ensemble_num), new FolderEntry("ensemble", FALSE));
- }
-
- addEntry(LLFolderType::FT_CURRENT_OUTFIT, new FolderEntry("current", TRUE));
- addEntry(LLFolderType::FT_OUTFIT, new FolderEntry("outfit", FALSE));
- addEntry(LLFolderType::FT_MY_OUTFITS, new FolderEntry("my_otfts", TRUE));
-
- addEntry(LLFolderType::FT_MESH, new FolderEntry("mesh", TRUE));
-
- addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE));
- addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", TRUE));
- addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE));
-
- addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE));
-};
-
-// static
-LLFolderType::EType LLFolderType::lookup(const std::string& name)
-{
- return LLFolderDictionary::getInstance()->lookup(name);
-}
-
-// static
-const std::string &LLFolderType::lookup(LLFolderType::EType folder_type)
-{
- const FolderEntry *entry = LLFolderDictionary::getInstance()->lookup(folder_type);
- if (entry)
- {
- return entry->mName;
- }
- else
- {
- return badLookup();
- }
-}
-
-// static
-// Only ensembles and plain folders aren't protected. "Protected" means
-// you can't change certain properties such as their type.
-bool LLFolderType::lookupIsProtectedType(EType folder_type)
-{
- const LLFolderDictionary *dict = LLFolderDictionary::getInstance();
- const FolderEntry *entry = dict->lookup(folder_type);
- if (entry)
- {
- return entry->mIsProtected;
- }
- return true;
-}
-
-// static
-bool LLFolderType::lookupIsEnsembleType(EType folder_type)
-{
- return (folder_type >= FT_ENSEMBLE_START &&
- folder_type <= FT_ENSEMBLE_END);
-}
-
-// static
-LLAssetType::EType LLFolderType::folderTypeToAssetType(LLFolderType::EType folder_type)
-{
- if (LLAssetType::lookup(LLAssetType::EType(folder_type)) == LLAssetType::badLookup())
- {
- llwarns << "Converting to unknown asset type " << folder_type << llendl;
- }
- return (LLAssetType::EType)folder_type;
-}
-
-// static
-LLFolderType::EType LLFolderType::assetTypeToFolderType(LLAssetType::EType asset_type)
-{
- if (LLFolderType::lookup(LLFolderType::EType(asset_type)) == LLFolderType::badLookup())
- {
- llwarns << "Converting to unknown folder type " << asset_type << llendl;
- }
- return (LLFolderType::EType)asset_type;
-}
-
-// static
-const std::string &LLFolderType::badLookup()
-{
- static const std::string sBadLookup = "llfoldertype_bad_lookup";
- return sBadLookup;
-}
diff --git a/indra/llcommon/llfoldertype.h b/indra/llcommon/llfoldertype.h
deleted file mode 100644
index a0c847914f..0000000000
--- a/indra/llcommon/llfoldertype.h
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * @file llfoldertype.h
- * @brief Declaration of LLFolderType.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLFOLDERTYPE_H
-#define LL_LLFOLDERTYPE_H
-
-#include <string>
-#include "llassettype.h"
-
-// This class handles folder types (similar to assettype, except for folders)
-// and operations on those.
-class LL_COMMON_API LLFolderType
-{
-public:
- // ! BACKWARDS COMPATIBILITY ! Folder type enums must match asset type enums.
- enum EType
- {
- FT_TEXTURE = 0,
-
- FT_SOUND = 1,
-
- FT_CALLINGCARD = 2,
-
- FT_LANDMARK = 3,
-
- FT_CLOTHING = 5,
-
- FT_OBJECT = 6,
-
- FT_NOTECARD = 7,
-
- FT_ROOT_INVENTORY = 8,
- // We'd really like to change this to 9 since AT_CATEGORY is 8,
- // but "My Inventory" has been type 8 for a long time.
-
- FT_LSL_TEXT = 10,
-
- FT_BODYPART = 13,
-
- FT_TRASH = 14,
-
- FT_SNAPSHOT_CATEGORY = 15,
-
- FT_LOST_AND_FOUND = 16,
-
- FT_ANIMATION = 20,
-
- FT_GESTURE = 21,
-
- FT_FAVORITE = 23,
-
- FT_ENSEMBLE_START = 26,
- FT_ENSEMBLE_END = 45,
- // This range is reserved for special clothing folder types.
-
- FT_CURRENT_OUTFIT = 46,
- FT_OUTFIT = 47,
- FT_MY_OUTFITS = 48,
-
- FT_MESH = 49,
-
- FT_INBOX = 50,
- FT_OUTBOX = 51,
-
- FT_BASIC_ROOT = 52,
-
- FT_COUNT,
-
- FT_NONE = -1
- };
-
- static EType lookup(const std::string& type_name);
- static const std::string& lookup(EType folder_type);
-
- static bool lookupIsProtectedType(EType folder_type);
- static bool lookupIsEnsembleType(EType folder_type);
-
- static LLAssetType::EType folderTypeToAssetType(LLFolderType::EType folder_type);
- static LLFolderType::EType assetTypeToFolderType(LLAssetType::EType asset_type);
-
- static const std::string& badLookup(); // error string when a lookup fails
-
-protected:
- LLFolderType() {}
- ~LLFolderType() {}
-};
-
-#endif // LL_LLFOLDERTYPE_H
diff --git a/indra/llcommon/llformat.h b/indra/llcommon/llformat.h
index a4ec5e01de..fb8e7cd045 100755
--- a/indra/llcommon/llformat.h
+++ b/indra/llcommon/llformat.h
@@ -29,7 +29,7 @@
#define LL_LLFORMAT_H
// Use as follows:
-// llinfos << llformat("Test:%d (%.2f %.2f)", idx, x, y) << llendl;
+// LL_INFOS() << llformat("Test:%d (%.2f %.2f)", idx, x, y) << LL_ENDL;
//
// *NOTE: buffer limited to 1024, (but vsnprintf prevents overrun)
// should perhaps be replaced with boost::format.
diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp
index ec64195b21..1af2cb8afd 100755
--- a/indra/llcommon/llframetimer.cpp
+++ b/indra/llcommon/llframetimer.cpp
@@ -115,10 +115,10 @@ F64 LLFrameTimer::expiresAt() const
BOOL LLFrameTimer::checkExpirationAndReset(F32 expiration)
{
- //llinfos << "LLFrameTimer::checkExpirationAndReset()" << llendl;
- //llinfos << " mStartTime:" << mStartTime << llendl;
- //llinfos << " sFrameTime:" << sFrameTime << llendl;
- //llinfos << " mExpiry: " << mExpiry << llendl;
+ //LL_INFOS() << "LLFrameTimer::checkExpirationAndReset()" << LL_ENDL;
+ //LL_INFOS() << " mStartTime:" << mStartTime << LL_ENDL;
+ //LL_INFOS() << " sFrameTime:" << sFrameTime << LL_ENDL;
+ //LL_INFOS() << " mExpiry: " << mExpiry << LL_ENDL;
if(hasExpired())
{
diff --git a/indra/llcommon/llframetimer.h b/indra/llcommon/llframetimer.h
index 45754f3785..81bd5da8a3 100755
--- a/indra/llcommon/llframetimer.h
+++ b/indra/llcommon/llframetimer.h
@@ -35,7 +35,6 @@
*/
#include "lltimer.h"
-#include "timing.h"
class LL_COMMON_API LLFrameTimer
{
@@ -44,7 +43,7 @@ public:
// Return the number of seconds since the start of this
// application instance.
- static F64 getElapsedSeconds()
+ static F64SecondsImplicit getElapsedSeconds()
{
// Loses msec precision after ~4.5 hours...
return sFrameTime;
@@ -53,7 +52,7 @@ public:
// Return a low precision usec since epoch
static U64 getTotalTime()
{
- return sTotalTime ? sTotalTime : totalTime();
+ return sTotalTime ? U64MicrosecondsImplicit(sTotalTime) : totalTime();
}
// Return a low precision seconds since epoch
diff --git a/indra/llcommon/llheartbeat.cpp b/indra/llcommon/llheartbeat.cpp
index 18a0c489bd..19b7452748 100755
--- a/indra/llcommon/llheartbeat.cpp
+++ b/indra/llcommon/llheartbeat.cpp
@@ -98,7 +98,7 @@ LLHeartbeat::rawSendWithTimeout(F32 timeout_sec)
mTimeoutTimer.setTimerExpirySec(timeout_sec);
do {
result = rawSend();
- //llinfos << " HEARTSENDc=" << result << llendl;
+ //LL_INFOS() << " HEARTSENDc=" << result << LL_ENDL;
} while (result==1 && !mTimeoutTimer.hasExpired());
return result;
@@ -118,7 +118,7 @@ LLHeartbeat::send(F32 timeout_sec)
// zero-timeout; we don't care too much whether our
// heartbeat was digested.
result = rawSend();
- //llinfos << " HEARTSENDb=" << result << llendl;
+ //LL_INFOS() << " HEARTSENDb=" << result << LL_ENDL;
}
}
@@ -146,14 +146,14 @@ LLHeartbeat::send(F32 timeout_sec)
// It's been ages since we successfully had a heartbeat
// digested by the watchdog. Sit here and spin a while
// in the hope that we can force it through.
- llwarns << "Unable to deliver heartbeat to launcher for " << mPanicTimer.getElapsedTimeF32() << " seconds. Going to try very hard for up to " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << llendl;
+ LL_WARNS() << "Unable to deliver heartbeat to launcher for " << mPanicTimer.getElapsedTimeF32() << " seconds. Going to try very hard for up to " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << LL_ENDL;
result = rawSendWithTimeout(mAggressiveHeartbeatMaxBlockingSecs);
if (result == 0) {
total_success = true;
} else {
// we couldn't even force it through. That's bad,
// but we'll try again in a while.
- llwarns << "Could not deliver heartbeat to launcher even after trying very hard for " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << llendl;
+ LL_WARNS() << "Could not deliver heartbeat to launcher even after trying very hard for " << mAggressiveHeartbeatMaxBlockingSecs << " seconds." << LL_ENDL;
}
// in any case, reset the panic timer.
diff --git a/indra/llcommon/llindexedqueue.h b/indra/llcommon/llindexedqueue.h
deleted file mode 100755
index aa2675d87d..0000000000
--- a/indra/llcommon/llindexedqueue.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/**
- * @file llindexedqueue.h
- * @brief An indexed FIFO queue, where only one element with each key
- * can be in the queue.
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLINDEXEDQUEUE_H
-#define LL_LLINDEXEDQUEUE_H
-
-// An indexed FIFO queue, where only one element with each key can be in the queue.
-// This is ONLY used in the interest list, you'll probably want to review this code
-// carefully if you want to use it elsewhere - Doug
-
-template <typename Type>
-class LLIndexedQueue
-{
-protected:
- typedef std::deque<Type> type_deque;
- type_deque mQueue;
- std::set<Type> mKeySet;
-
-public:
- LLIndexedQueue() {}
-
- // move_if_there is an O(n) operation
- bool push_back(const Type &value, bool move_if_there = false)
- {
- if (mKeySet.find(value) != mKeySet.end())
- {
- // Already on the queue
- if (move_if_there)
- {
- // Remove the existing entry.
- typename type_deque::iterator it;
- for (it = mQueue.begin(); it != mQueue.end(); ++it)
- {
- if (*it == value)
- {
- break;
- }
- }
-
- // This HAS to succeed, otherwise there's a serious bug in the keyset implementation
- // (although this isn't thread safe, at all)
-
- mQueue.erase(it);
- }
- else
- {
- // We're not moving it, leave it alone
- return false;
- }
- }
- else
- {
- // Doesn't exist, add it to the key set
- mKeySet.insert(value);
- }
-
- mQueue.push_back(value);
-
- // We succeeded in adding the new element.
- return true;
- }
-
- bool push_front(const Type &value, bool move_if_there = false)
- {
- if (mKeySet.find(value) != mKeySet.end())
- {
- // Already on the queue
- if (move_if_there)
- {
- // Remove the existing entry.
- typename type_deque::iterator it;
- for (it = mQueue.begin(); it != mQueue.end(); ++it)
- {
- if (*it == value)
- {
- break;
- }
- }
-
- // This HAS to succeed, otherwise there's a serious bug in the keyset implementation
- // (although this isn't thread safe, at all)
-
- mQueue.erase(it);
- }
- else
- {
- // We're not moving it, leave it alone
- return false;
- }
- }
- else
- {
- // Doesn't exist, add it to the key set
- mKeySet.insert(value);
- }
-
- mQueue.push_front(value);
- return true;
- }
-
- void pop()
- {
- Type value = mQueue.front();
- mKeySet.erase(value);
- mQueue.pop_front();
- }
-
- Type &front()
- {
- return mQueue.front();
- }
-
- S32 size() const
- {
- return mQueue.size();
- }
-
- bool empty() const
- {
- return mQueue.empty();
- }
-
- void clear()
- {
- // Clear out all elements on the queue
- mQueue.clear();
- mKeySet.clear();
- }
-};
-
-#endif // LL_LLINDEXEDQUEUE_H
diff --git a/indra/llcommon/llindexedvector.h b/indra/llcommon/llindexedvector.h
new file mode 100755
index 0000000000..68c3821802
--- /dev/null
+++ b/indra/llcommon/llindexedvector.h
@@ -0,0 +1,100 @@
+/**
+ * @file lldarray.h
+ * @brief Wrapped std::vector for backward compatibility.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLDARRAY_H
+#define LL_LLDARRAY_H
+
+#include "llerror.h"
+
+#include <vector>
+#include <map>
+
+//--------------------------------------------------------
+// LLIndexedVector
+//--------------------------------------------------------
+
+template <typename Type, typename Key, int BlockSize = 32>
+class LLIndexedVector
+{
+public:
+ typedef typename std::vector<Type>::iterator iterator;
+ typedef typename std::vector<Type>::const_iterator const_iterator;
+ typedef typename std::vector<Type>::reverse_iterator reverse_iterator;
+ typedef typename std::vector<Type>::const_reverse_iterator const_reverse_iterator;
+ typedef typename std::vector<Type>::size_type size_type;
+protected:
+ std::vector<Type> mVector;
+ std::map<Key, U32> mIndexMap;
+
+public:
+ LLIndexedVector() { mVector.reserve(BlockSize); }
+
+ iterator begin() { return mVector.begin(); }
+ const_iterator begin() const { return mVector.begin(); }
+ iterator end() { return mVector.end(); }
+ const_iterator end() const { return mVector.end(); }
+
+ reverse_iterator rbegin() { return mVector.rbegin(); }
+ const_reverse_iterator rbegin() const { return mVector.rbegin(); }
+ reverse_iterator rend() { return mVector.rend(); }
+ const_reverse_iterator rend() const { return mVector.rend(); }
+
+ void reset() { mVector.resize(0); mIndexMap.resize(0); }
+ bool empty() const { return mVector.empty(); }
+ size_type size() const { return mVector.size(); }
+
+ Type& operator[](const Key& k)
+ {
+ typename std::map<Key, U32>::const_iterator iter = mIndexMap.find(k);
+ if (iter == mIndexMap.end())
+ {
+ U32 n = mVector.size();
+ mIndexMap[k] = n;
+ mVector.push_back(Type());
+ llassert(mVector.size() == mIndexMap.size());
+ return mVector[n];
+ }
+ else
+ {
+ return mVector[iter->second];
+ }
+ }
+
+ const_iterator find(const Key& k) const
+ {
+ typename std::map<Key, U32>::const_iterator iter = mIndexMap.find(k);
+ if(iter == mIndexMap.end())
+ {
+ return mVector.end();
+ }
+ else
+ {
+ return mVector.begin() + iter->second;
+ }
+ }
+};
+
+#endif
diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index 89c831d296..aa2f4eb289 100755
--- a/indra/llcommon/llinitparam.cpp
+++ b/indra/llcommon/llinitparam.cpp
@@ -28,10 +28,17 @@
#include "linden_common.h"
#include "llinitparam.h"
+#include "llformat.h"
namespace LLInitParam
{
+
+ predicate_rule_t default_parse_rules()
+ {
+ return ll_make_predicate(PROVIDED) && !ll_make_predicate(EMPTY);
+ }
+
//
// Param
//
@@ -93,13 +100,13 @@ namespace LLInitParam
void Parser::parserWarning(const std::string& message)
{
if (mParseSilently) return;
- llwarns << message << llendl;
+ LL_WARNS() << message << LL_ENDL;
}
void Parser::parserError(const std::string& message)
{
if (mParseSilently) return;
- llerrs << message << llendl;
+ LL_ERRS() << message << LL_ENDL;
}
@@ -124,7 +131,7 @@ namespace LLInitParam
std::string name(char_name);
if ((size_t)param->mParamHandle > mMaxParamOffset)
{
- llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;
+ LL_ERRS() << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << LL_ENDL;
}
if (name.empty())
@@ -196,6 +203,9 @@ namespace LLInitParam
bool BaseBlock::validateBlock(bool emit_errors) const
{
+ // only validate block when it hasn't already passed validation with current data
+ if (!mValidated)
+ {
const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it)
{
@@ -204,16 +214,23 @@ namespace LLInitParam
{
if (emit_errors)
{
- llwarns << "Invalid param \"" << getParamName(block_data, param) << "\"" << llendl;
+ LL_WARNS() << "Invalid param \"" << getParamName(block_data, param) << "\"" << LL_ENDL;
}
return false;
}
}
- return true;
+ mValidated = true;
+ }
+ return mValidated;
}
- void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const
+ bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const LLInitParam::BaseBlock* diff_block) const
{
+ bool serialized = false;
+ if (!predicate_rule.check(ll_make_predicate(PROVIDED, isProvided())))
+ {
+ return false;
+ }
// named param is one like LLView::Params::follows
// unnamed param is like LLView::Params::rect - implicit
const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
@@ -225,10 +242,10 @@ namespace LLInitParam
param_handle_t param_handle = (*it)->mParamHandle;
const Param* param = getParamFromHandle(param_handle);
ParamDescriptor::serialize_func_t serialize_func = (*it)->mSerializeFunc;
- if (serialize_func)
+ if (serialize_func && predicate_rule.check(ll_make_predicate(PROVIDED, param->anyProvided())))
{
const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
- serialize_func(*param, parser, name_stack, diff_param);
+ serialized |= serialize_func(*param, parser, name_stack, predicate_rule, diff_param);
}
}
@@ -239,7 +256,7 @@ namespace LLInitParam
param_handle_t param_handle = it->second->mParamHandle;
const Param* param = getParamFromHandle(param_handle);
ParamDescriptor::serialize_func_t serialize_func = it->second->mSerializeFunc;
- if (serialize_func && param->anyProvided())
+ if (serialize_func && predicate_rule.check(ll_make_predicate(PROVIDED, param->anyProvided())))
{
// Ensure this param has not already been serialized
// Prevents <rect> from being serialized as its own tag.
@@ -264,10 +281,17 @@ namespace LLInitParam
name_stack.push_back(std::make_pair(it->first, !duplicate));
const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
- serialize_func(*param, parser, name_stack, diff_param);
+ serialized |= serialize_func(*param, parser, name_stack, predicate_rule, diff_param);
name_stack.pop_back();
}
}
+
+ if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY)))
+ {
+ serialized |= parser.writeValue(Flag(), name_stack);
+ }
+ // was anything serialized in this block?
+ return serialized;
}
bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const
@@ -393,7 +417,7 @@ namespace LLInitParam
// Block<T, Base_Class>
if ((size_t)handle > block_data.mMaxParamOffset)
{
- llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;
+ LL_ERRS() << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << LL_ENDL;
}
ParamDescriptorPtr param_descriptor = findParamDescriptor(param);
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index 03ab0fb67f..2532566319 100755
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -29,14 +29,16 @@
#define LL_LLPARAM_H
#include <vector>
+#include <list>
#include <boost/function.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/unordered_map.hpp>
-#include <boost/shared_ptr.hpp>
#include "llerror.h"
#include "llstl.h"
+#include "llpredicate.h"
+#include "llsd.h"
namespace LLTypeTags
{
@@ -195,6 +197,8 @@ namespace LLInitParam
return mValue;
}
+ bool isValid() const { return true; }
+
protected:
T mValue;
};
@@ -209,13 +213,11 @@ namespace LLInitParam
typedef T value_t;
ParamValue()
- : T(),
- mValidated(false)
+ : T()
{}
ParamValue(const default_value_t& other)
- : T(other),
- mValidated(false)
+ : T(other)
{}
void setValue(const value_t& val)
@@ -232,9 +234,6 @@ namespace LLInitParam
{
return *this;
}
-
- protected:
- mutable bool mValidated; // lazy validation flag
};
@@ -497,25 +496,25 @@ namespace LLInitParam
virtual ~Parser();
template <typename T> bool readValue(T& param, typename boost::disable_if<boost::is_enum<T> >::type* dummy = 0)
- {
+ {
parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
if (found_it != mParserReadFuncs->end())
- {
+ {
return found_it->second(*this, (void*)&param);
- }
-
- return false;
}
-
+
+ return false;
+ }
+
template <typename T> bool readValue(T& param, typename boost::enable_if<boost::is_enum<T> >::type* dummy = 0)
- {
+ {
parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T));
if (found_it != mParserReadFuncs->end())
- {
+ {
return found_it->second(*this, (void*)&param);
- }
+ }
else
- {
+ {
found_it = mParserReadFuncs->find(&typeid(S32));
if (found_it != mParserReadFuncs->end())
{
@@ -523,20 +522,20 @@ namespace LLInitParam
bool parsed = found_it->second(*this, (void*)&int_value);
param = (T)int_value;
return parsed;
- }
}
- return false;
}
+ 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;
}
+ 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)
@@ -579,6 +578,19 @@ namespace LLInitParam
class Param;
+ enum ESerializePredicates
+ {
+ PROVIDED,
+ REQUIRED,
+ VALID,
+ HAS_DEFAULT_VALUE,
+ EMPTY
+ };
+
+ typedef LLPredicate::Rule<ESerializePredicates> predicate_rule_t;
+
+ predicate_rule_t default_parse_rules();
+
// various callbacks and constraints associated with an individual param
struct LL_COMMON_API ParamDescriptor
{
@@ -589,7 +601,7 @@ namespace LLInitParam
typedef bool(*merge_func_t)(Param&, const Param&, bool);
typedef bool(*deserialize_func_t)(Param&, Parser&, Parser::name_stack_range_t&, bool);
- typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param);
+ typedef bool(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const predicate_rule_t rules, const Param* diff_param);
typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count);
typedef bool(*validation_func_t)(const Param*);
@@ -617,7 +629,7 @@ namespace LLInitParam
UserData* mUserData;
};
- typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr;
+ typedef ParamDescriptor* ParamDescriptorPtr;
// each derived Block class keeps a static data structure maintaining offsets to various params
class LL_COMMON_API BlockDescriptor
@@ -829,12 +841,28 @@ namespace LLInitParam
LOG_CLASS(BaseBlock);
friend class Param;
+ BaseBlock()
+ : mValidated(false),
+ mParamProvided(false)
+ {}
+
virtual ~BaseBlock() {}
bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false);
param_handle_t getHandleFromParam(const Param* param) const;
bool validateBlock(bool emit_errors = true) const;
+ bool isProvided() const
+ {
+ return mParamProvided;
+ }
+
+ bool isValid() const
+ {
+ return validateBlock(false);
+ }
+
+
Param* getParamFromHandle(const param_handle_t param_handle)
{
if (param_handle == 0) return NULL;
@@ -852,10 +880,19 @@ namespace LLInitParam
void addSynonym(Param& param, const std::string& synonym);
// Blocks can override this to do custom tracking of changes
- virtual void paramChanged(const Param& changed_param, bool user_provided) {}
+ virtual void paramChanged(const Param& changed_param, bool user_provided)
+ {
+ if (user_provided)
+ {
+ // a child param has been explicitly changed
+ // so *some* aspect of this block is now provided
+ mValidated = false;
+ mParamProvided = true;
+ }
+ }
bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name);
- void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
+ bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t rule, const BaseBlock* diff_block = NULL) const;
bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const;
virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); }
@@ -893,6 +930,9 @@ namespace LLInitParam
return mergeBlock(block_data, source, overwrite);
}
+ mutable bool mValidated; // lazy validation flag
+ bool mParamProvided;
+
private:
const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const;
};
@@ -986,6 +1026,8 @@ namespace LLInitParam
bool isProvided() const { return Param::anyProvided(); }
+ bool isValid() const { return true; }
+
static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
{
self_t& typed_param = static_cast<self_t&>(param);
@@ -1014,10 +1056,23 @@ namespace LLInitParam
return false;
}
- static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+ static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
{
+ bool serialized = false;
const self_t& typed_param = static_cast<const self_t&>(param);
- if (!typed_param.isProvided()) return;
+ const self_t* diff_typed_param = static_cast<const self_t*>(diff_param);
+
+ LLPredicate::Value<ESerializePredicates> predicate;
+ if (diff_typed_param && ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()))
+ {
+ predicate.set(HAS_DEFAULT_VALUE);
+ }
+
+ predicate.set(VALID, typed_param.isValid());
+ predicate.set(PROVIDED, typed_param.anyProvided());
+ predicate.set(EMPTY, false);
+
+ if (!predicate_rule.check(predicate)) return false;
if (!name_stack.empty())
{
@@ -1030,25 +1085,27 @@ namespace LLInitParam
if (!key.empty())
{
- if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))
+ if (!diff_typed_param || !ParamCompare<std::string>::equals(diff_typed_param->getValueName(), key))
{
- parser.writeValue(key, name_stack);
+ serialized = parser.writeValue(key, name_stack);
}
}
// then try to serialize value directly
- else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), static_cast<const self_t*>(diff_param)->getValue()))
+ else if (!diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()))
{
- if (!parser.writeValue(typed_param.getValue(), name_stack))
+ serialized = parser.writeValue(typed_param.getValue(), name_stack);
+ if (!serialized)
{
std::string calculated_key = typed_param.calcValueName(typed_param.getValue());
if (calculated_key.size()
- && (!diff_param
+ && (!diff_typed_param
|| !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key)))
{
- parser.writeValue(calculated_key, name_stack);
+ serialized = parser.writeValue(calculated_key, name_stack);
}
}
}
+ return serialized;
}
static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
@@ -1113,19 +1170,19 @@ namespace LLInitParam
};
// parameter that is a block
- template <typename T, typename NAME_VALUE_LOOKUP>
- class TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK>
+ template <typename BLOCK_T, typename NAME_VALUE_LOOKUP>
+ class TypedParam<BLOCK_T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK>
: public Param,
public NAME_VALUE_LOOKUP::type_value_t
{
protected:
- typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t;
- typedef typename param_value_t::default_value_t default_value_t;
- typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK> self_t;
- typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t;
+ typedef ParamValue<typename LLTypeTags::Sorted<BLOCK_T>::value_t> param_value_t;
+ typedef typename param_value_t::default_value_t default_value_t;
+ typedef TypedParam<BLOCK_T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK> self_t;
+ typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t;
public:
using named_value_t::operator();
- typedef typename param_value_t::value_t value_t;
+ typedef typename param_value_t::value_t value_t;
TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
: Param(block_descriptor.mCurrentBlockPtr),
@@ -1148,11 +1205,11 @@ namespace LLInitParam
if(named_value_t::valueNamesExist()
&& parser.readValue(name)
&& named_value_t::getValueFromName(name, typed_param.getValue()))
- {
- typed_param.setValueName(name);
- typed_param.setProvided();
- return true;
- }
+ {
+ typed_param.setValueName(name);
+ typed_param.setProvided();
+ return true;
+ }
}
if(typed_param.deserializeBlock(parser, name_stack_range, new_name))
@@ -1166,10 +1223,16 @@ namespace LLInitParam
return false;
}
- static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+ static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
{
const self_t& typed_param = static_cast<const self_t&>(param);
- if (!typed_param.isProvided()) return;
+
+ LLPredicate::Value<ESerializePredicates> predicate;
+
+ predicate.set(VALID, typed_param.isValid());
+ predicate.set(PROVIDED, typed_param.anyProvided());
+
+ if (!predicate_rule.check(predicate)) return false;
if (!name_stack.empty())
{
@@ -1182,12 +1245,15 @@ namespace LLInitParam
if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key))
{
parser.writeValue(key, name_stack);
+ return true;
}
}
else
{
- typed_param.serializeBlock(parser, name_stack, static_cast<const self_t*>(diff_param));
+ return typed_param.serializeBlock(parser, name_stack, predicate_rule, static_cast<const self_t*>(diff_param));
}
+
+ return false;
}
static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
@@ -1209,13 +1275,12 @@ namespace LLInitParam
// *and* the block as a whole validates
bool isProvided() const
{
- // only validate block when it hasn't already passed validation with current data
- if (Param::anyProvided() && !param_value_t::mValidated)
- {
- // a sub-block is "provided" when it has been filled in enough to be valid
- param_value_t::mValidated = param_value_t::validateBlock(false);
- }
- return Param::anyProvided() && param_value_t::mValidated;
+ return Param::anyProvided() && isValid();
+ }
+
+ bool isValid() const
+ {
+ return param_value_t::isValid();
}
// assign block contents to this param-that-is-a-block
@@ -1223,9 +1288,6 @@ namespace LLInitParam
{
setValue(val);
named_value_t::clearValueName();
- // force revalidation of block
- // next call to isProvided() will update provision status based on validity
- param_value_t::mValidated = false;
setProvided(flag_as_provided);
}
@@ -1242,9 +1304,6 @@ namespace LLInitParam
if (user_provided)
{
- // a child param has been explicitly changed
- // so *some* aspect of this block is now provided
- param_value_t::mValidated = false;
setProvided();
named_value_t::clearValueName();
}
@@ -1296,13 +1355,13 @@ namespace LLInitParam
};
// list of non-block parameters
- template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
- class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK>
+ template <typename MULTI_VALUE_T, typename NAME_VALUE_LOOKUP>
+ class TypedParam<MULTI_VALUE_T, NAME_VALUE_LOOKUP, true, NOT_BLOCK>
: public Param
{
protected:
- typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> self_t;
- typedef ParamValue<typename LLTypeTags::Sorted<VALUE_TYPE>::value_t> param_value_t;
+ typedef TypedParam<MULTI_VALUE_T, NAME_VALUE_LOOKUP, true, NOT_BLOCK> self_t;
+ typedef ParamValue<typename LLTypeTags::Sorted<MULTI_VALUE_T>::value_t> param_value_t;
typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t;
typedef container_t default_value_t;
typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t;
@@ -1311,7 +1370,9 @@ namespace LLInitParam
typedef typename param_value_t::value_t value_t;
TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
- : Param(block_descriptor.mCurrentBlockPtr)
+ : Param(block_descriptor.mCurrentBlockPtr),
+ mMinCount(min_count),
+ mMaxCount(max_count)
{
std::copy(value.begin(), value.end(), std::back_inserter(mValues));
@@ -1322,7 +1383,13 @@ namespace LLInitParam
}
}
- bool isProvided() const { return Param::anyProvided(); }
+ bool isProvided() const { return Param::anyProvided() && isValid(); }
+
+ bool isValid() const
+ {
+ size_t num_elements = numValidElements();
+ return mMinCount < num_elements && num_elements < mMaxCount;
+ }
static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
{
@@ -1337,7 +1404,7 @@ namespace LLInitParam
}
// no further names in stack, attempt to parse value now
- if (name_stack_range.first == name_stack_range.second)
+ if (new_name_stack_range.first == new_name_stack_range.second)
{
std::string name;
@@ -1359,10 +1426,19 @@ namespace LLInitParam
return false;
}
- static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+ static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
{
+ bool serialized = false;
const self_t& typed_param = static_cast<const self_t&>(param);
- if (!typed_param.isProvided()) return;
+
+ LLPredicate::Value<ESerializePredicates> predicate;
+
+ predicate.set(REQUIRED, typed_param.mMinCount > 0);
+ predicate.set(VALID, typed_param.isValid());
+ predicate.set(PROVIDED, typed_param.anyProvided());
+ predicate.set(EMPTY, typed_param.mValues.empty());
+
+ if (!predicate_rule.check(predicate)) return false;
for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
it != end_it;
@@ -1378,7 +1454,11 @@ namespace LLInitParam
if (!value_written)
{
std::string calculated_key = it->calcValueName(it->getValue());
- if (!parser.writeValue(calculated_key, name_stack))
+ if (parser.writeValue(calculated_key, name_stack))
+ {
+ serialized = true;
+ }
+ else
{
break;
}
@@ -1386,19 +1466,23 @@ namespace LLInitParam
}
else
{
- if(!parser.writeValue(key, name_stack))
+ if(parser.writeValue(key, name_stack))
+ {
+ serialized = true;
+ }
+ else
{
break;
}
}
-
- name_stack.pop_back();
}
+
+ return serialized;
}
static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
{
- parser.inspectValue<VALUE_TYPE>(name_stack, min_count, max_count, NULL);
+ parser.inspectValue<MULTI_VALUE_T>(name_stack, min_count, max_count, NULL);
if (named_value_t::getPossibleValues())
{
parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues());
@@ -1453,7 +1537,7 @@ namespace LLInitParam
bool empty() const { return mValues.empty(); }
size_t size() const { return mValues.size(); }
- U32 numValidElements() const
+ size_t numValidElements() const
{
return mValues.size();
}
@@ -1483,6 +1567,8 @@ namespace LLInitParam
}
container_t mValues;
+ size_t mMinCount,
+ mMaxCount;
private:
void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )
@@ -1500,13 +1586,13 @@ namespace LLInitParam
};
// list of block parameters
- template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
- class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK>
+ template <typename MULTI_BLOCK_T, typename NAME_VALUE_LOOKUP>
+ class TypedParam<MULTI_BLOCK_T, NAME_VALUE_LOOKUP, true, IS_A_BLOCK>
: public Param
{
protected:
- typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK> self_t;
- typedef ParamValue<typename LLTypeTags::Sorted<VALUE_TYPE>::value_t> param_value_t;
+ typedef TypedParam<MULTI_BLOCK_T, NAME_VALUE_LOOKUP, true, IS_A_BLOCK> self_t;
+ typedef ParamValue<typename LLTypeTags::Sorted<MULTI_BLOCK_T>::value_t> param_value_t;
typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t;
typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t;
typedef container_t default_value_t;
@@ -1516,7 +1602,9 @@ namespace LLInitParam
typedef typename param_value_t::value_t value_t;
TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count)
- : Param(block_descriptor.mCurrentBlockPtr)
+ : Param(block_descriptor.mCurrentBlockPtr),
+ mMinCount(min_count),
+ mMaxCount(max_count)
{
std::copy(value.begin(), value.end(), back_inserter(mValues));
@@ -1526,7 +1614,14 @@ namespace LLInitParam
}
}
- bool isProvided() const { return Param::anyProvided(); }
+ bool isProvided() const { return Param::anyProvided() && isValid(); }
+
+ bool isValid() const
+ {
+ size_t num_elements = numValidElements();
+ return mMinCount < num_elements && num_elements < mMaxCount;
+ }
+
static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
{
@@ -1549,7 +1644,7 @@ namespace LLInitParam
}
param_value_t& value = typed_param.mValues.back();
- if (name_stack_range.first == name_stack_range.second)
+ if (new_name_stack_range.first == new_name_stack_range.second)
{ // try to parse a known named value
std::string name;
@@ -1559,6 +1654,10 @@ namespace LLInitParam
{
typed_param.mValues.back().setValueName(name);
typed_param.setProvided();
+ if (new_array_value)
+ {
+ name_stack_range.first->second = false;
+ }
return true;
}
}
@@ -1583,10 +1682,18 @@ namespace LLInitParam
return false;
}
- static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param)
+ static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param)
{
+ bool serialized = false;
const self_t& typed_param = static_cast<const self_t&>(param);
- if (!typed_param.isProvided()) return;
+ LLPredicate::Value<ESerializePredicates> predicate;
+
+ predicate.set(REQUIRED, typed_param.mMinCount > 0);
+ predicate.set(VALID, typed_param.isValid());
+ predicate.set(PROVIDED, typed_param.anyProvided());
+ predicate.set(EMPTY, typed_param.mValues.empty());
+
+ if (!predicate_rule.check(predicate)) return false;
for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
it != end_it;
@@ -1597,17 +1704,24 @@ namespace LLInitParam
std::string key = it->getValueName();
if (!key.empty())
{
- parser.writeValue(key, name_stack);
+ serialized |= parser.writeValue(key, name_stack);
}
// Not parsed via named values, write out value directly
- // NOTE: currently we don't worry about removing default values in Multiple
+ // NOTE: currently we don't do diffing of Multiples
else
{
- it->serializeBlock(parser, name_stack, NULL);
+ serialized = it->serializeBlock(parser, name_stack, predicate_rule, NULL);
}
name_stack.pop_back();
}
+
+ if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY)))
+ {
+ serialized |= parser.writeValue(Flag(), name_stack);
+ }
+
+ return serialized;
}
static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count)
@@ -1670,14 +1784,14 @@ namespace LLInitParam
bool empty() const { return mValues.empty(); }
size_t size() const { return mValues.size(); }
- U32 numValidElements() const
+ size_t numValidElements() const
{
- U32 count = 0;
+ size_t count = 0;
for (const_iterator it = mValues.begin(), end_it = mValues.end();
it != end_it;
++it)
{
- if(it->validateBlock(false)) count++;
+ if(it->isValid()) count++;
}
return count;
}
@@ -1709,6 +1823,8 @@ namespace LLInitParam
}
container_t mValues;
+ size_t mMinCount,
+ mMaxCount;
private:
void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name )
@@ -2015,7 +2131,7 @@ namespace LLInitParam
static bool validate(const Param* paramp)
{
- U32 num_valid = ((super_t*)paramp)->numValidElements();
+ size_t num_valid = ((super_t*)paramp)->numValidElements();
return RANGE::minCount <= num_valid && num_valid <= RANGE::maxCount;
}
};
@@ -2158,13 +2274,11 @@ namespace LLInitParam
typedef T default_value_t;
ParamValue()
- : mValue(),
- mValidated(false)
+ : mValue()
{}
ParamValue(const default_value_t& value)
- : mValue(value),
- mValidated(false)
+ : mValue(value)
{}
void setValue(const value_t& val)
@@ -2191,18 +2305,18 @@ namespace LLInitParam
return mValue.deserializeBlock(p, name_stack_range, new_name);
}
- void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const
+ bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const self_t* diff_block = NULL) const
{
const BaseBlock* base_block = diff_block
? &(diff_block->mValue)
: NULL;
- mValue.serializeBlock(p, name_stack, base_block);
+ return mValue.serializeBlock(p, name_stack, predicate_rule, base_block);
}
bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
- {
+ {
return mValue.inspectBlock(p, name_stack, min_count, max_count);
- }
+ }
bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite)
{
@@ -2212,9 +2326,7 @@ namespace LLInitParam
// clear away what is there and take the new stuff as a whole
resetToDefault();
return mValue.mergeBlock(block_data, source.getValue(), overwrite);
- }
-
-
+ }
return mValue.mergeBlock(block_data, source.getValue(), overwrite);
}
@@ -2223,14 +2335,17 @@ namespace LLInitParam
return mValue.validateBlock(emit_errors);
}
+ bool isValid() const
+ {
+ return validateBlock(false);
+ }
+
static BlockDescriptor& getBlockDescriptor()
{
return value_t::getBlockDescriptor();
}
- mutable bool mValidated; // lazy validation flag
-
private:
void resetToDefault()
{
@@ -2251,15 +2366,13 @@ namespace LLInitParam
typedef T default_value_t;
ParamValue()
- : mValue(),
- mValidated(false)
+ : mValue()
{
mCurParam = getBlockDescriptor().mAllParams.begin();
}
ParamValue(const default_value_t& value)
- : mValue(value),
- mValidated(false)
+ : mValue(value)
{
mCurParam = getBlockDescriptor().mAllParams.begin();
}
@@ -2284,7 +2397,7 @@ namespace LLInitParam
if (new_name)
{
mCurParam = getBlockDescriptor().mAllParams.begin();
- }
+ }
if (name_stack_range.first == name_stack_range.second
&& mCurParam != getBlockDescriptor().mAllParams.end())
{
@@ -2296,7 +2409,7 @@ namespace LLInitParam
if (deserialize_func
&& paramp
&& deserialize_func(*paramp, p, name_stack_range, new_name))
- {
+ {
++mCurParam;
return true;
}
@@ -2304,19 +2417,19 @@ namespace LLInitParam
{
return false;
}
- }
+ }
else
{
return mValue.deserializeBlock(p, name_stack_range, new_name);
}
}
- void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const
+ bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const self_t* diff_block = NULL) const
{
const BaseBlock* base_block = diff_block
? &(diff_block->mValue)
: NULL;
- mValue.serializeBlock(p, name_stack, base_block);
+ return mValue.serializeBlock(p, name_stack, predicate_rule, base_block);
}
bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
@@ -2334,13 +2447,16 @@ namespace LLInitParam
return mValue.validateBlock(emit_errors);
}
+ bool isValid() const
+ {
+ return validateBlock(false);
+ }
+
static BlockDescriptor& getBlockDescriptor()
{
return value_t::getBlockDescriptor();
}
- mutable bool mValidated; // lazy validation flag
-
private:
BlockDescriptor::all_params_list_t::iterator mCurParam;
@@ -2358,16 +2474,14 @@ namespace LLInitParam
typedef T default_value_t;
ParamValue()
- : T(),
- mValidated(false)
+ : T()
{}
ParamValue(const default_value_t& value)
- : T(value.getValue()),
- mValidated(false)
+ : T(value.getValue())
{}
- mutable bool mValidated; // lazy validation flag
+ bool isValid() const { return true; }
};
template<typename T, typename BLOCK_T>
@@ -2380,18 +2494,15 @@ namespace LLInitParam
typedef LazyValue<T> default_value_t;
ParamValue()
- : mValue(),
- mValidated(false)
+ : mValue()
{}
ParamValue(const default_value_t& other)
- : mValue(other),
- mValidated(false)
+ : mValue(other)
{}
ParamValue(const T& value)
- : mValue(value),
- mValidated(false)
+ : mValue(value)
{}
void setValue(const value_t& val)
@@ -2414,14 +2525,14 @@ namespace LLInitParam
return mValue.get().deserializeBlock(p, name_stack_range, new_name);
}
- void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const
+ bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const self_t* diff_block = NULL) const
{
- if (mValue.empty()) return;
+ if (mValue.empty()) return false;
const BaseBlock* base_block = (diff_block && !diff_block->mValue.empty())
? &(diff_block->mValue.get().getValue())
: NULL;
- mValue.get().serializeBlock(p, name_stack, base_block);
+ return mValue.get().serializeBlock(p, name_stack, predicate_rule, base_block);
}
bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
@@ -2433,26 +2544,29 @@ namespace LLInitParam
{
return source.mValue.empty() || mValue.get().mergeBlock(block_data, source.getValue(), overwrite);
}
-
+
bool validateBlock(bool emit_errors = true) const
{
return mValue.empty() || mValue.get().validateBlock(emit_errors);
}
+ bool isValid() const
+ {
+ return validateBlock(false);
+ }
+
static BlockDescriptor& getBlockDescriptor()
{
return value_t::getBlockDescriptor();
}
- mutable bool mValidated; // lazy validation flag
-
private:
LazyValue<T> mValue;
};
template<typename T, typename BLOCK_T>
class ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T>
- {
+ {
typedef ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> self_t;
public:
@@ -2460,18 +2574,15 @@ namespace LLInitParam
typedef LazyValue<T> default_value_t;
ParamValue()
- : mValue(),
- mValidated(false)
+ : mValue()
{}
ParamValue(const default_value_t& other)
- : mValue(other),
- mValidated(false)
+ : mValue(other)
{}
ParamValue(const T& value)
- : mValue(value),
- mValidated(false)
+ : mValue(value)
{}
void setValue(const value_t& val)
@@ -2489,7 +2600,10 @@ namespace LLInitParam
return mValue.get().getValue();
}
- mutable bool mValidated; // lazy validation flag
+ bool isValid() const
+ {
+ return true;
+ }
private:
LazyValue<T> mValue;
@@ -2504,12 +2618,10 @@ namespace LLInitParam
typedef LLSD default_value_t;
ParamValue()
- : mValidated(false)
{}
ParamValue(const default_value_t& other)
- : mValue(other),
- mValidated(false)
+ : mValue(other)
{}
void setValue(const value_t& val) { mValue = val; }
@@ -2519,16 +2631,13 @@ namespace LLInitParam
// block param interface
LL_COMMON_API bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name);
- LL_COMMON_API void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const;
+ LL_COMMON_API bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block = NULL) const;
bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const
{
//TODO: implement LLSD params as schema type Any
return true;
}
- protected:
- mutable bool mValidated; // lazy validation flag
-
private:
static void serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack);
@@ -2547,18 +2656,17 @@ namespace LLInitParam
BLOCK_AUTHORITATIVE // mValue is derived from the block parameters, which are authoritative
} EValueAge;
- typedef ParamValue<T> derived_t;
- typedef CustomParamValue<T> self_t;
- typedef Block<derived_t> block_t;
+ typedef TypeValues<T> derived_t;
+ typedef CustomParamValue<T> self_t;
+ typedef Block<ParamValue<T> > block_t;
typedef T default_value_t;
- typedef T value_t;
+ typedef T value_t;
typedef void baseblock_base_class_t;
CustomParamValue(const default_value_t& value = T())
: mValue(value),
- mValueAge(VALUE_AUTHORITATIVE),
- mValidated(false)
+ mValueAge(VALUE_AUTHORITATIVE)
{}
bool deserializeBlock(Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name)
@@ -2580,16 +2688,30 @@ namespace LLInitParam
return typed_param.BaseBlock::deserializeBlock(parser, name_stack_range, new_name);
}
- void serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const
+ bool serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block = NULL) const
{
const derived_t& typed_param = static_cast<const derived_t&>(*this);
const derived_t* diff_param = static_cast<const derived_t*>(diff_block);
+ //std::string key = typed_param.getValueName();
+
+ //// first try to write out name of name/value pair
+ //if (!key.empty())
+ //{
+ // if (!diff_param || !ParamCompare<std::string>::equals(diff_param->getValueName(), key))
+ // {
+ // return parser.writeValue(key, name_stack);
+ // }
+ //}
// then try to serialize value directly
if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue()))
{
- if (!parser.writeValue(typed_param.getValue(), name_stack))
+ if (parser.writeValue(typed_param.getValue(), name_stack))
+ {
+ return true;
+ }
+ else
{
//RN: *always* serialize provided components of BlockValue (don't pass diff_param on),
// since these tend to be viewed as the constructor arguments for the value T. It seems
@@ -2606,14 +2728,15 @@ namespace LLInitParam
// and serialize those params
derived_t copy(typed_param);
copy.updateBlockFromValue(true);
- copy.block_t::serializeBlock(parser, name_stack, NULL);
+ return copy.block_t::serializeBlock(parser, name_stack, predicate_rule, NULL);
}
else
{
- block_t::serializeBlock(parser, name_stack, NULL);
+ return block_t::serializeBlock(parser, name_stack, predicate_rule, NULL);
}
}
}
+ return false;
}
bool validateBlock(bool emit_errors = true) const
@@ -2705,8 +2828,6 @@ namespace LLInitParam
return block_t::mergeBlock(block_data, source, overwrite);
}
- mutable bool mValidated; // lazy validation flag
-
private:
mutable T mValue;
mutable EValueAge mValueAge;
diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp
index 64a313b5ff..11fc53f8c8 100755
--- a/indra/llcommon/llinstancetracker.cpp
+++ b/indra/llcommon/llinstancetracker.cpp
@@ -27,8 +27,26 @@
#include "linden_common.h"
// associated header
#include "llinstancetracker.h"
+#include "llapr.h"
+
// STL headers
// std headers
// external library headers
// other Linden headers
+void LLInstanceTrackerBase::StaticBase::incrementDepth()
+{
+ apr_atomic_inc32(&sIterationNestDepth);
+}
+
+void LLInstanceTrackerBase::StaticBase::decrementDepth()
+{
+ llassert(sIterationNestDepth);
+ apr_atomic_dec32(&sIterationNestDepth);
+}
+
+U32 LLInstanceTrackerBase::StaticBase::getDepth()
+{
+ apr_uint32_t data = apr_atomic_read32(&sIterationNestDepth);
+ return data;
+}
diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h
index 55187d8325..9783644e66 100755
--- a/indra/llcommon/llinstancetracker.h
+++ b/indra/llcommon/llinstancetracker.h
@@ -31,10 +31,7 @@
#include <map>
#include <typeinfo>
-#include "string_table.h"
-#include <boost/utility.hpp>
-#include <boost/function.hpp>
-#include <boost/bind.hpp>
+#include "llstringtable.h"
#include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator/indirect_iterator.hpp>
@@ -46,8 +43,6 @@
class LL_COMMON_API LLInstanceTrackerBase
{
protected:
-
-
/// It's not essential to derive your STATICDATA (for use with
/// getStatic()) from StaticBase; it's just that both known
/// implementations do.
@@ -56,31 +51,39 @@ protected:
StaticBase():
sIterationNestDepth(0)
{}
- S32 sIterationNestDepth;
+
+ void incrementDepth();
+ void decrementDepth();
+ U32 getDepth();
+ private:
+ U32 sIterationNestDepth;
};
};
LL_COMMON_API void assert_main_thread();
+enum EInstanceTrackerAllowKeyCollisions
+{
+ LLInstanceTrackerErrorOnCollision,
+ LLInstanceTrackerReplaceOnCollision
+};
+
/// This mix-in class adds support for tracking all instances of the specified class parameter T
/// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
/// If KEY is not provided, then instances are stored in a simple set
-/// @NOTE: see explicit specialization below for default KEY==T* case
-template<typename T, typename KEY = T*>
+/// @NOTE: see explicit specialization below for default KEY==void case
+/// @NOTE: this class is not thread-safe unless used as read-only
+template<typename T, typename KEY = void, EInstanceTrackerAllowKeyCollisions KEY_COLLISION_BEHAVIOR = LLInstanceTrackerErrorOnCollision>
class LLInstanceTracker : public LLInstanceTrackerBase
{
typedef LLInstanceTracker<T, KEY> self_t;
- typedef typename std::map<KEY, T*> InstanceMap;
+ typedef typename std::multimap<KEY, T*> InstanceMap;
struct StaticData: public StaticBase
{
InstanceMap sMap;
};
static StaticData& getStatic() { static StaticData sData; return sData;}
- static InstanceMap& getMap_()
- {
- // assert_main_thread(); fwiw this class is not thread safe, and it used by multiple threads. Bad things happen.
- return getStatic().sMap;
- }
+ static InstanceMap& getMap_() { return getStatic().sMap; }
public:
class instance_iter : public boost::iterator_facade<instance_iter, T, boost::forward_traversal_tag>
@@ -91,12 +94,12 @@ public:
instance_iter(const typename InstanceMap::iterator& it)
: mIterator(it)
{
- ++getStatic().sIterationNestDepth;
+ getStatic().incrementDepth();
}
~instance_iter()
{
- --getStatic().sIterationNestDepth;
+ getStatic().decrementDepth();
}
@@ -123,20 +126,20 @@ public:
typedef boost::iterator_facade<key_iter, KEY, boost::forward_traversal_tag> super_t;
key_iter(typename InstanceMap::iterator it)
- : mIterator(it)
+ : mIterator(it)
{
- ++getStatic().sIterationNestDepth;
+ getStatic().incrementDepth();
}
key_iter(const key_iter& other)
- : mIterator(other.mIterator)
+ : mIterator(other.mIterator)
{
- ++getStatic().sIterationNestDepth;
+ getStatic().incrementDepth();
}
~key_iter()
{
- --getStatic().sIterationNestDepth;
+ getStatic().decrementDepth();
}
@@ -174,7 +177,10 @@ public:
return instance_iter(getMap_().end());
}
- static S32 instanceCount() { return getMap_().size(); }
+ static S32 instanceCount()
+ {
+ return getMap_().size();
+ }
static key_iter beginKeys()
{
@@ -186,7 +192,7 @@ public:
}
protected:
- LLInstanceTracker(KEY key)
+ LLInstanceTracker(const KEY& key)
{
// make sure static data outlives all instances
getStatic();
@@ -195,7 +201,7 @@ protected:
virtual ~LLInstanceTracker()
{
// it's unsafe to delete instances of this type while all instances are being iterated over.
- llassert_always(getStatic().sIterationNestDepth == 0);
+ llassert_always(getStatic().getDepth() == 0);
remove_();
}
virtual void setKey(KEY key) { remove_(); add_(key); }
@@ -205,17 +211,44 @@ private:
LLInstanceTracker( const LLInstanceTracker& );
const LLInstanceTracker& operator=( const LLInstanceTracker& );
- void add_(KEY key)
+ void add_(const KEY& key)
{
mInstanceKey = key;
- getMap_()[key] = static_cast<T*>(this);
+ InstanceMap& map = getMap_();
+ typename InstanceMap::iterator insertion_point_it = map.lower_bound(key);
+ if (insertion_point_it != map.end()
+ && insertion_point_it->first == key)
+ { // found existing entry with that key
+ switch(KEY_COLLISION_BEHAVIOR)
+ {
+ case LLInstanceTrackerErrorOnCollision:
+ {
+ // use assert here instead of LL_ERRS(), otherwise the error will be ignored since this call is made during global object initialization
+ llassert_always_msg(false, "Instance with this same key already exists!");
+ break;
+ }
+ case LLInstanceTrackerReplaceOnCollision:
+ {
+ // replace pointer, but leave key (should have compared equal anyway)
+ insertion_point_it->second = static_cast<T*>(this);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else
+ { // new key
+ map.insert(insertion_point_it, std::make_pair(key, static_cast<T*>(this)));
+ }
}
void remove_()
{
- typename InstanceMap::iterator iter = getMap_().find(mInstanceKey);
- if (iter != getMap_().end())
+ InstanceMap& map = getMap_();
+ typename InstanceMap::iterator iter = map.find(mInstanceKey);
+ if (iter != map.end())
{
- getMap_().erase(iter);
+ map.erase(iter);
}
}
@@ -223,12 +256,12 @@ private:
KEY mInstanceKey;
};
-/// explicit specialization for default case where KEY is T*
+/// explicit specialization for default case where KEY is void
/// use a simple std::set<T*>
-template<typename T>
-class LLInstanceTracker<T, T*> : public LLInstanceTrackerBase
+template<typename T, EInstanceTrackerAllowKeyCollisions KEY_COLLISION_BEHAVIOR>
+class LLInstanceTracker<T, void, KEY_COLLISION_BEHAVIOR> : public LLInstanceTrackerBase
{
- typedef LLInstanceTracker<T, T*> self_t;
+ typedef LLInstanceTracker<T, void> self_t;
typedef typename std::set<T*> InstanceSet;
struct StaticData: public StaticBase
{
@@ -261,18 +294,18 @@ public:
instance_iter(const typename InstanceSet::iterator& it)
: mIterator(it)
{
- ++getStatic().sIterationNestDepth;
+ getStatic().incrementDepth();
}
instance_iter(const instance_iter& other)
: mIterator(other.mIterator)
{
- ++getStatic().sIterationNestDepth;
+ getStatic().incrementDepth();
}
~instance_iter()
{
- --getStatic().sIterationNestDepth;
+ getStatic().decrementDepth();
}
private:
@@ -305,7 +338,7 @@ protected:
virtual ~LLInstanceTracker()
{
// it's unsafe to delete instances of this type while all instances are being iterated over.
- llassert_always(getStatic().sIterationNestDepth == 0);
+ llassert_always(getStatic().getDepth() == 0);
getSet_().erase(static_cast<T*>(this));
}
diff --git a/indra/llcommon/lllazy.cpp b/indra/llcommon/lllazy.cpp
deleted file mode 100755
index 29fa040387..0000000000
--- a/indra/llcommon/lllazy.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * @file lllazy.cpp
- * @author Nat Goodspeed
- * @date 2009-01-28
- * @brief Implementation for lllazy.
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-// Precompiled header
-#include "linden_common.h"
-// associated header
-#include "lllazy.h"
-// STL headers
-// std headers
-// external library headers
-// other Linden headers
-
-// lllazy.h is presently header-only. This file exists only because our CMake
-// test macro ADD_BUILD_TEST requires it.
-int dummy = 0;
diff --git a/indra/llcommon/lllazy.h b/indra/llcommon/lllazy.h
deleted file mode 100755
index 5f3bbce79e..0000000000
--- a/indra/llcommon/lllazy.h
+++ /dev/null
@@ -1,399 +0,0 @@
-/**
- * @file lllazy.h
- * @author Nat Goodspeed
- * @date 2009-01-22
- * @brief Lazy instantiation of specified type. Useful in conjunction with
- * Michael Feathers's "Extract and Override Getter" ("Working
- * Effectively with Legacy Code", p. 352).
- *
- * Quoting his synopsis of steps on p.355:
- *
- * 1. Identify the object you need a getter for.
- * 2. Extract all of the logic needed to create the object into a getter.
- * 3. Replace all uses of the object with calls to the getter, and initialize
- * the reference that holds the object to null in all constructors.
- * 4. Add the first-time logic to the getter so that the object is constructed
- * and assigned to the reference whenever the reference is null.
- * 5. Subclass the class and override the getter to provide an alternative
- * object for testing.
- *
- * It's the second half of bullet 3 (3b, as it were) that bothers me. I find
- * it all too easy to imagine adding pointer initializers to all but one
- * constructor... the one not exercised by my tests. That suggested using
- * (e.g.) boost::scoped_ptr<MyObject> so you don't have to worry about
- * destroying it either.
- *
- * However, introducing additional machinery allows us to encapsulate bullet 4
- * as well.
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LLLAZY_H)
-#define LL_LLLAZY_H
-
-#include <boost/function.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/lambda/construct.hpp>
-#include <stdexcept>
-
-/// LLLazyCommon simply factors out of LLLazy<T> things that don't depend on
-/// its template parameter.
-class LLLazyCommon
-{
-public:
- /**
- * This exception is thrown if you try to replace an LLLazy<T>'s factory
- * (or T* instance) after it already has an instance in hand. Since T
- * might well be stateful, we can't know the effect of silently discarding
- * and replacing an existing instance, so we disallow it. This facility is
- * intended for testing, and in a test scenario we can definitely control
- * that.
- */
- struct InstanceChange: public std::runtime_error
- {
- InstanceChange(const std::string& what): std::runtime_error(what) {}
- };
-
-protected:
- /**
- * InstanceChange might be appropriate in a couple of different LLLazy<T>
- * methods. Factor out the common logic.
- */
- template <typename PTR>
- static void ensureNoInstance(const PTR& ptr)
- {
- if (ptr)
- {
- // Too late: we've already instantiated the lazy object. We don't
- // know whether it's stateful or not, so it's not safe to discard
- // the existing instance in favor of a replacement.
- throw InstanceChange("Too late to replace LLLazy instance");
- }
- }
-};
-
-/**
- * LLLazy<T> is useful when you have an outer class Outer that you're trying
- * to bring under unit test, that contains a data member difficult to
- * instantiate in a test harness. Typically the data member's class Inner has
- * many thorny dependencies. Feathers generally advocates "Extract and
- * Override Factory Method" (p. 350). But in C++, you can't call a derived
- * class override of a virtual method from the derived class constructor,
- * which limits applicability of "Extract and Override Factory Method." For
- * such cases Feathers presents "Extract and Override Getter" (p. 352).
- *
- * So we'll assume that your class Outer contains a member like this:
- * @code
- * Inner mInner;
- * @endcode
- *
- * LLLazy<Inner> can be used to replace this member. You can directly declare:
- * @code
- * LLLazy<Inner> mInner;
- * @endcode
- * and change references to mInner accordingly.
- *
- * (Alternatively, you can add a base class of the form
- * <tt>LLLazyBase<Inner></tt>. This is discussed further in the LLLazyBase<T>
- * documentation.)
- *
- * LLLazy<T> binds a <tt>boost::scoped_ptr<T></tt> and a factory functor
- * returning T*. You can either bind that functor explicitly or let it default
- * to the expression <tt>new T()</tt>.
- *
- * As long as LLLazy<T> remains unreferenced, its T remains uninstantiated.
- * The first time you use get(), <tt>operator*()</tt> or <tt>operator->()</tt>
- * it will instantiate its T and thereafter behave like a pointer to it.
- *
- * Thus, any existing reference to <tt>mInner.member</tt> should be replaced
- * with <tt>mInner->member</tt>. Any simple reference to @c mInner should be
- * replaced by <tt>*mInner</tt>.
- *
- * (If the original declaration was a pointer initialized in Outer's
- * constructor, e.g. <tt>Inner* mInner</tt>, so much the better. In that case
- * you should be able to drop in <tt>LLLazy<Inner></tt> without much change.)
- *
- * The support for "Extract and Override Getter" lies in the fact that you can
- * replace the factory functor -- or provide an explicit T*. Presumably this
- * is most useful from a test subclass -- which suggests that your @c mInner
- * member should be @c protected.
- *
- * Note that <tt>boost::lambda::new_ptr<T>()</tt> makes a dandy factory
- * functor, for either the set() method or LLLazy<T>'s constructor. If your T
- * requires constructor arguments, use an expression more like
- * <tt>boost::lambda::bind(boost::lambda::new_ptr<T>(), arg1, arg2, ...)</tt>.
- *
- * Of course the point of replacing the functor is to substitute a class that,
- * though referenced as Inner*, is not an Inner; presumably this is a testing
- * subclass of Inner (e.g. TestInner). Thus your test subclass TestOuter for
- * the containing class Outer will contain something like this:
- * @code
- * class TestOuter: public Outer
- * {
- * public:
- * TestOuter()
- * {
- * // mInner must be 'protected' rather than 'private'
- * mInner.set(boost::lambda::new_ptr<TestInner>());
- * }
- * ...
- * };
- * @endcode
- */
-template <typename T>
-class LLLazy: public LLLazyCommon
-{
-public:
- /// Any nullary functor returning T* will work as a Factory
- typedef boost::function<T* ()> Factory;
-
- /// The default LLLazy constructor uses <tt>new T()</tt> as its Factory
- LLLazy():
- mFactory(boost::lambda::new_ptr<T>())
- {}
-
- /// Bind an explicit Factory functor
- LLLazy(const Factory& factory):
- mFactory(factory)
- {}
-
- /// Reference T, instantiating it if this is the first access
- const T& get() const
- {
- if (! mInstance)
- {
- // use the bound Factory functor
- mInstance.reset(mFactory());
- }
- return *mInstance;
- }
-
- /// non-const get()
- T& get()
- {
- return const_cast<T&>(const_cast<const LLLazy<T>*>(this)->get());
- }
-
- /// operator*() is equivalent to get()
- const T& operator*() const { return get(); }
- /// operator*() is equivalent to get()
- T& operator*() { return get(); }
-
- /**
- * operator->() must return (something resembling) T*. It's tempting to
- * return the underlying boost::scoped_ptr<T>, but that would require
- * breaking out the lazy-instantiation logic from get() into a common
- * private method. Assume the pointer used for operator->() access is very
- * short-lived.
- */
- const T* operator->() const { return &get(); }
- /// non-const operator->()
- T* operator->() { return &get(); }
-
- /// set(Factory). This will throw InstanceChange if mInstance has already
- /// been set.
- void set(const Factory& factory)
- {
- ensureNoInstance(mInstance);
- mFactory = factory;
- }
-
- /// set(T*). This will throw InstanceChange if mInstance has already been
- /// set.
- void set(T* instance)
- {
- ensureNoInstance(mInstance);
- mInstance.reset(instance);
- }
-
-private:
- Factory mFactory;
- // Consider an LLLazy<T> member of a class we're accessing by const
- // reference. We want to allow even const methods to touch the LLLazy<T>
- // member. Hence the actual pointer must be mutable because such access
- // might assign it.
- mutable boost::scoped_ptr<T> mInstance;
-};
-
-#if (! defined(__GNUC__)) || (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)
-// Not gcc at all, or a gcc more recent than gcc 3.3
-#define GCC33 0
-#else
-#define GCC33 1
-#endif
-
-/**
- * LLLazyBase<T> wraps LLLazy<T>, giving you an alternative way to replace
- * <tt>Inner mInner;</tt>. Instead of coding <tt>LLLazy<Inner> mInner</tt>,
- * you can add LLLazyBase<Inner> to your Outer class's bases, e.g.:
- * @code
- * class Outer: public LLLazyBase<Inner>
- * {
- * ...
- * };
- * @endcode
- *
- * This gives you @c public get() and @c protected set() methods without
- * having to make your LLLazy<Inner> member @c protected. The tradeoff is that
- * you must access the wrapped LLLazy<Inner> using get() and set() rather than
- * with <tt>operator*()</tt> or <tt>operator->()</tt>.
- *
- * This mechanism can be used for more than one member, but only if they're of
- * different types. That is, you can replace:
- * @code
- * DifficultClass mDifficult;
- * AwkwardType mAwkward;
- * @endcode
- * with:
- * @code
- * class Outer: public LLLazyBase<DifficultClass>, public LLLazyBase<AwkwardType>
- * {
- * ...
- * };
- * @endcode
- * but for a situation like this:
- * @code
- * DifficultClass mMainDifficult, mAuxDifficult;
- * @endcode
- * you should directly embed LLLazy<DifficultClass> (q.v.).
- *
- * For multiple LLLazyBase bases, e.g. the <tt>LLLazyBase<DifficultClass>,
- * LLLazyBase<AwkwardType></tt> example above, access the relevant get()/set()
- * as (e.g.) <tt>LLLazyBase<DifficultClass>::get()</tt>. (This is why you
- * can't have multiple LLLazyBase<T> of the same T.) For a bit of syntactic
- * sugar, please see getLazy()/setLazy().
- */
-template <typename T>
-class LLLazyBase
-{
-public:
- /// invoke default LLLazy constructor
- LLLazyBase() {}
- /// make wrapped LLLazy bind an explicit Factory
- LLLazyBase(const typename LLLazy<T>::Factory& factory):
- mInstance(factory)
- {}
-
- /// access to LLLazy::get()
- T& get() { return *mInstance; }
- /// access to LLLazy::get()
- const T& get() const { return *mInstance; }
-
-protected:
- // see getLazy()/setLazy()
- #if (! GCC33)
- template <typename T2, class MYCLASS> friend T2& getLazy(MYCLASS* this_);
- template <typename T2, class MYCLASS> friend const T2& getLazy(const MYCLASS* this_);
- #else // gcc 3.3
- template <typename T2, class MYCLASS> friend T2& getLazy(const MYCLASS* this_);
- #endif // gcc 3.3
- template <typename T2, class MYCLASS> friend void setLazy(MYCLASS* this_, T2* instance);
- template <typename T2, class MYCLASS>
- friend void setLazy(MYCLASS* this_, const typename LLLazy<T2>::Factory& factory);
-
- /// access to LLLazy::set(Factory)
- void set(const typename LLLazy<T>::Factory& factory)
- {
- mInstance.set(factory);
- }
-
- /// access to LLLazy::set(T*)
- void set(T* instance)
- {
- mInstance.set(instance);
- }
-
-private:
- LLLazy<T> mInstance;
-};
-
-/**
- * @name getLazy()/setLazy()
- * Suppose you have something like the following:
- * @code
- * class Outer: public LLLazyBase<DifficultClass>, public LLLazyBase<AwkwardType>
- * {
- * ...
- * };
- * @endcode
- *
- * Your methods can reference the @c DifficultClass instance using
- * <tt>LLLazyBase<DifficultClass>::get()</tt>, which is admittedly a bit ugly.
- * Alternatively, you can write <tt>getLazy<DifficultClass>(this)</tt>, which
- * is somewhat more straightforward to read.
- *
- * Similarly,
- * @code
- * LLLazyBase<DifficultClass>::set(new TestDifficultClass());
- * @endcode
- * could instead be written:
- * @code
- * setLazy<DifficultClass>(this, new TestDifficultClass());
- * @endcode
- *
- * @note
- * I wanted to provide getLazy() and setLazy() without explicitly passing @c
- * this. That would imply making them methods on a base class rather than free
- * functions. But if <tt>LLLazyBase<T></tt> derives normally from (say) @c
- * LLLazyGrandBase providing those methods, then unqualified getLazy() would
- * be ambiguous: you'd have to write <tt>LLLazyBase<T>::getLazy<T>()</tt>,
- * which is even uglier than <tt>LLLazyBase<T>::get()</tt>, and therefore
- * pointless. You can make the compiler not care which @c LLLazyGrandBase
- * instance you're talking about by making @c LLLazyGrandBase a @c virtual
- * base class of @c LLLazyBase. But in that case,
- * <tt>LLLazyGrandBase::getLazy<T>()</tt> can't access
- * <tt>LLLazyBase<T>::get()</tt>!
- *
- * We want <tt>getLazy<T>()</tt> to access <tt>LLLazyBase<T>::get()</tt> as if
- * in the lexical context of some subclass method. Ironically, free functions
- * let us do that better than methods on a @c virtual base class -- but that
- * implies passing @c this explicitly. So be it.
- */
-//@{
-#if (! GCC33)
-template <typename T, class MYCLASS>
-T& getLazy(MYCLASS* this_) { return this_->LLLazyBase<T>::get(); }
-template <typename T, class MYCLASS>
-const T& getLazy(const MYCLASS* this_) { return this_->LLLazyBase<T>::get(); }
-#else // gcc 3.3
-// For const-correctness, we really should have two getLazy() variants: one
-// accepting const MYCLASS* and returning const T&, the other accepting
-// non-const MYCLASS* and returning non-const T&. This works fine on the Mac
-// (gcc 4.0.1) and Windows (MSVC 8.0), but fails on our Linux 32-bit Debian
-// Sarge stations (gcc 3.3.5). Since I really don't know how to beat that aging
-// compiler over the head to make it do the right thing, I'm going to have to
-// move forward with the wrong thing: a single getLazy() function that accepts
-// const MYCLASS* and returns non-const T&.
-template <typename T, class MYCLASS>
-T& getLazy(const MYCLASS* this_) { return const_cast<MYCLASS*>(this_)->LLLazyBase<T>::get(); }
-#endif // gcc 3.3
-template <typename T, class MYCLASS>
-void setLazy(MYCLASS* this_, T* instance) { this_->LLLazyBase<T>::set(instance); }
-template <typename T, class MYCLASS>
-void setLazy(MYCLASS* this_, const typename LLLazy<T>::Factory& factory)
-{
- this_->LLLazyBase<T>::set(factory);
-}
-//@}
-
-#endif /* ! defined(LL_LLLAZY_H) */
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index 0a57ef1c48..84d2a12f65 100755
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -394,7 +394,7 @@ public:
LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN));
LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
LLSD nop;
- F64 until(LLTimer::getElapsedSeconds() + 2);
+ F64 until = (LLTimer::getElapsedSeconds() + 2).value();
while (childin.size() && LLTimer::getElapsedSeconds() < until)
{
mainloop.post(nop);
diff --git a/indra/llcommon/lllinkedqueue.h b/indra/llcommon/lllinkedqueue.h
deleted file mode 100755
index 8336608809..0000000000
--- a/indra/llcommon/lllinkedqueue.h
+++ /dev/null
@@ -1,309 +0,0 @@
-/**
- * @file lllinkedqueue.h
- * @brief Declaration of linked queue classes.
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLLINKEDQUEUE_H
-#define LL_LLLINKEDQUEUE_H
-
-#include "llerror.h"
-
-// node that actually contains the data
-template <class DATA_TYPE> class LLLinkedQueueNode
-{
-public:
- DATA_TYPE mData;
- LLLinkedQueueNode *mNextp;
- LLLinkedQueueNode *mPrevp;
-
-
-public:
- LLLinkedQueueNode();
- LLLinkedQueueNode(const DATA_TYPE data);
-
- // destructor does not, by default, destroy associated data
- // however, the mDatap must be NULL to ensure that we aren't causing memory leaks
- ~LLLinkedQueueNode();
-};
-
-
-
-template <class DATA_TYPE> class LLLinkedQueue
-{
-
-public:
- LLLinkedQueue();
-
- // destructor destroys list and nodes, but not data in nodes
- ~LLLinkedQueue();
-
- // Puts at end of FIFO
- void push(const DATA_TYPE data);
-
- // Takes off front of FIFO
- BOOL pop(DATA_TYPE &data);
- BOOL peek(DATA_TYPE &data);
-
- void reset();
-
- S32 getLength() const;
-
- BOOL isEmpty() const;
-
- BOOL remove(const DATA_TYPE data);
-
- BOOL checkData(const DATA_TYPE data) const;
-
-private:
- // add node to end of list
- // set mCurrentp to mQueuep
- void addNodeAtEnd(LLLinkedQueueNode<DATA_TYPE> *nodep);
-
-private:
- LLLinkedQueueNode<DATA_TYPE> mHead; // head node
- LLLinkedQueueNode<DATA_TYPE> mTail; // tail node
- S32 mLength;
-};
-
-
-//
-// Nodes
-//
-
-template <class DATA_TYPE>
-LLLinkedQueueNode<DATA_TYPE>::LLLinkedQueueNode() :
- mData(), mNextp(NULL), mPrevp(NULL)
-{ }
-
-template <class DATA_TYPE>
-LLLinkedQueueNode<DATA_TYPE>::LLLinkedQueueNode(const DATA_TYPE data) :
- mData(data), mNextp(NULL), mPrevp(NULL)
-{ }
-
-template <class DATA_TYPE>
-LLLinkedQueueNode<DATA_TYPE>::~LLLinkedQueueNode()
-{ }
-
-
-//
-// Queue itself
-//
-
-template <class DATA_TYPE>
-LLLinkedQueue<DATA_TYPE>::LLLinkedQueue()
-: mHead(),
- mTail(),
- mLength(0)
-{ }
-
-
-// destructor destroys list and nodes, but not data in nodes
-template <class DATA_TYPE>
-LLLinkedQueue<DATA_TYPE>::~LLLinkedQueue()
-{
- reset();
-}
-
-
-// put data into a node and stick it at the end of the list
-template <class DATA_TYPE>
-void LLLinkedQueue<DATA_TYPE>::push(const DATA_TYPE data)
-{
- // make the new node
- LLLinkedQueueNode<DATA_TYPE> *nodep = new LLLinkedQueueNode<DATA_TYPE>(data);
-
- addNodeAtEnd(nodep);
-}
-
-
-// search the list starting at mHead.mNextp and remove the link with mDatap == data
-// set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-BOOL LLLinkedQueue<DATA_TYPE>::remove(const DATA_TYPE data)
-{
- BOOL b_found = FALSE;
-
- LLLinkedQueueNode<DATA_TYPE> *currentp = mHead.mNextp;
-
- while (currentp)
- {
- if (currentp->mData == data)
- {
- b_found = TRUE;
-
- // if there is a next one, fix it
- if (currentp->mNextp)
- {
- currentp->mNextp->mPrevp = currentp->mPrevp;
- }
- else // we are at end of list
- {
- mTail.mPrevp = currentp->mPrevp;
- }
-
- // if there is a previous one, fix it
- if (currentp->mPrevp)
- {
- currentp->mPrevp->mNextp = currentp->mNextp;
- }
- else // we are at beginning of list
- {
- mHead.mNextp = currentp->mNextp;
- }
-
- // remove the node
- delete currentp;
- mLength--;
- break;
- }
- currentp = currentp->mNextp;
- }
-
- return b_found;
-}
-
-
-// remove all nodes from the list but do not delete associated data
-template <class DATA_TYPE>
-void LLLinkedQueue<DATA_TYPE>::reset()
-{
- LLLinkedQueueNode<DATA_TYPE> *currentp;
- LLLinkedQueueNode<DATA_TYPE> *nextp;
- currentp = mHead.mNextp;
-
- while (currentp)
- {
- nextp = currentp->mNextp;
- delete currentp;
- currentp = nextp;
- }
-
- // reset mHead and mCurrentp
- mHead.mNextp = NULL;
- mTail.mPrevp = NULL;
- mLength = 0;
-}
-
-template <class DATA_TYPE>
-S32 LLLinkedQueue<DATA_TYPE>::getLength() const
-{
- return mLength;
-}
-
-template <class DATA_TYPE>
-BOOL LLLinkedQueue<DATA_TYPE>::isEmpty() const
-{
- return mLength <= 0;
-}
-
-// check to see if data is in list
-// set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep
-// return TRUE if found, FALSE if not found
-template <class DATA_TYPE>
-BOOL LLLinkedQueue<DATA_TYPE>::checkData(const DATA_TYPE data) const
-{
- LLLinkedQueueNode<DATA_TYPE> *currentp = mHead.mNextp;
-
- while (currentp)
- {
- if (currentp->mData == data)
- {
- return TRUE;
- }
- currentp = currentp->mNextp;
- }
- return FALSE;
-}
-
-template <class DATA_TYPE>
-BOOL LLLinkedQueue<DATA_TYPE>::pop(DATA_TYPE &data)
-{
- LLLinkedQueueNode<DATA_TYPE> *currentp;
-
- currentp = mHead.mNextp;
- if (!currentp)
- {
- return FALSE;
- }
-
- mHead.mNextp = currentp->mNextp;
- if (currentp->mNextp)
- {
- currentp->mNextp->mPrevp = currentp->mPrevp;
- }
- else
- {
- mTail.mPrevp = currentp->mPrevp;
- }
-
- data = currentp->mData;
- delete currentp;
- mLength--;
- return TRUE;
-}
-
-template <class DATA_TYPE>
-BOOL LLLinkedQueue<DATA_TYPE>::peek(DATA_TYPE &data)
-{
- LLLinkedQueueNode<DATA_TYPE> *currentp;
-
- currentp = mHead.mNextp;
- if (!currentp)
- {
- return FALSE;
- }
- data = currentp->mData;
- return TRUE;
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-// private members
-//////////////////////////////////////////////////////////////////////////////////////////
-
-
-// add node to end of list
-// set mCurrentp to mQueuep
-template <class DATA_TYPE>
-void LLLinkedQueue<DATA_TYPE>::addNodeAtEnd(LLLinkedQueueNode<DATA_TYPE> *nodep)
-{
- // add the node to the end of the list
- nodep->mNextp = NULL;
- nodep->mPrevp = mTail.mPrevp;
- mTail.mPrevp = nodep;
-
- // if there's something in the list, fix its back pointer
- if (nodep->mPrevp)
- {
- nodep->mPrevp->mNextp = nodep;
- }
- else // otherwise fix the head node
- {
- mHead.mNextp = nodep;
- }
- mLength++;
-}
-
-#endif
diff --git a/indra/llcommon/llliveappconfig.cpp b/indra/llcommon/llliveappconfig.cpp
index 3a3dfa9f28..7c87c5a1a0 100755
--- a/indra/llcommon/llliveappconfig.cpp
+++ b/indra/llcommon/llliveappconfig.cpp
@@ -47,8 +47,8 @@ LLLiveAppConfig::~LLLiveAppConfig()
// virtual
bool LLLiveAppConfig::loadFile()
{
- llinfos << "LLLiveAppConfig::loadFile(): reading from "
- << filename() << llendl;
+ LL_INFOS() << "LLLiveAppConfig::loadFile(): reading from "
+ << filename() << LL_ENDL;
llifstream file(filename());
LLSD config;
if (file.is_open())
@@ -56,15 +56,15 @@ bool LLLiveAppConfig::loadFile()
LLSDSerialize::fromXML(config, file);
if(!config.isMap())
{
- llwarns << "Live app config not an map in " << filename()
- << " Ignoring the data." << llendl;
+ LL_WARNS() << "Live app config not an map in " << filename()
+ << " Ignoring the data." << LL_ENDL;
return false;
}
file.close();
}
else
{
- llinfos << "Live file " << filename() << " does not exit." << llendl;
+ LL_INFOS() << "Live file " << filename() << " does not exit." << LL_ENDL;
}
// *NOTE: we do not handle the else case here because we would not
// have attempted to load the file unless LLLiveFile had
diff --git a/indra/llcommon/lllocalidhashmap.h b/indra/llcommon/lllocalidhashmap.h
deleted file mode 100755
index 8f4f91a560..0000000000
--- a/indra/llcommon/lllocalidhashmap.h
+++ /dev/null
@@ -1,895 +0,0 @@
-/**
- * @file lllocalidhashmap.h
- * @brief Map specialized for dealing with local ids
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLLOCALIDHASHMAP_H
-#define LL_LLLOCALIDHASHMAP_H
-
-#include "stdtypes.h"
-#include "llerror.h"
-
-const S32 MAX_ITERS = 4;
-// LocalID hash map
-
-//
-// LLLocalIDHashNode
-//
-
-template <class DATA, int SIZE>
-class LLLocalIDHashNode
-{
-public:
- LLLocalIDHashNode();
-
-public:
- S32 mCount;
- U32 mKey[SIZE];
- DATA mData[SIZE];
- LLLocalIDHashNode<DATA, SIZE> *mNextNodep;
-};
-
-
-//
-// LLLocalIDHashNode implementation
-//
-template <class DATA, int SIZE>
-LLLocalIDHashNode<DATA, SIZE>::LLLocalIDHashNode()
-{
- mCount = 0;
- mNextNodep = NULL;
-}
-
-//
-// LLLocalIDHashMapIter
-//
-template <class DATA_TYPE, int SIZE>
-class LLLocalIDHashMap;
-
-template <class DATA_TYPE, int SIZE>
-class LLLocalIDHashMapIter
-{
-public:
- LLLocalIDHashMapIter(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp);
- ~LLLocalIDHashMapIter();
-
- void setMap(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp);
- inline void first();
- inline void next();
- inline DATA_TYPE& current(); // *NOTE: Deprecate? Phoenix 2005-04-15
- inline BOOL done() const;
- inline S32 currentBin() const;
- inline void setBin(S32 bin);
-
- DATA_TYPE& operator*() const
- {
- return mCurHashNodep->mData[mCurHashNodeKey];
- }
- DATA_TYPE* operator->() const
- {
- return &(operator*());
- }
-
- LLLocalIDHashMap<DATA_TYPE, SIZE> *mHashMapp;
- LLLocalIDHashNode<DATA_TYPE, SIZE> *mCurHashNodep;
-
- S32 mCurHashMapNodeNum;
- S32 mCurHashNodeKey;
-
- DATA_TYPE mNull;
-
- S32 mIterID;
-};
-
-
-
-template <class DATA_TYPE, int SIZE>
-class LLLocalIDHashMap
-{
-public:
- friend class LLLocalIDHashMapIter<DATA_TYPE, SIZE>;
-
- LLLocalIDHashMap(); // DO NOT use this unless you explicitly setNull, or the data type constructs a "null"
- // object by default
- // basic constructor including sorter
- LLLocalIDHashMap(const DATA_TYPE &null_data);
- // Hack, this should really be a const ref, but I'm not doing it that way because the sim
- // usually uses pointers.
- ~LLLocalIDHashMap();
-
- inline DATA_TYPE &get(const U32 local_id);
- inline BOOL check(const U32 local_id) const;
- inline DATA_TYPE &set(const U32 local_id, const DATA_TYPE data);
- inline BOOL remove(const U32 local_id);
- void removeAll();
-
- void setNull(const DATA_TYPE data) { mNull = data; }
-
- inline S32 getLength() const; // Warning, NOT O(1!)
-
- void dumpIter();
- void dumpBin(U32 bin);
-
-protected:
- // Only used by the iterator.
- void addIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter);
- void removeIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter);
-
- // Remove the item and shift all items afterward down the list,
- // fixing up iterators as we go.
- BOOL removeWithShift(const U32 local_id);
-
-protected:
- LLLocalIDHashNode<DATA_TYPE, SIZE> mNodes[256];
-
- S32 mIterCount;
- LLLocalIDHashMapIter<DATA_TYPE, SIZE> *mIters[MAX_ITERS];
-
- DATA_TYPE mNull;
-};
-
-
-//
-// LLLocalIDHashMap implementation
-//
-
-template <class DATA_TYPE, int SIZE>
-LLLocalIDHashMap<DATA_TYPE, SIZE>::LLLocalIDHashMap()
-: mIterCount(0),
- mNull()
-{
- S32 i;
- for (i = 0; i < MAX_ITERS; i++)
- {
- mIters[i] = NULL;
- }
-}
-
-template <class DATA_TYPE, int SIZE>
-LLLocalIDHashMap<DATA_TYPE, SIZE>::LLLocalIDHashMap(const DATA_TYPE &null_data)
-: mIterCount(0),
- mNull(null_data)
-{
- S32 i;
- for (i = 0; i < MAX_ITERS; i++)
- {
- mIters[i] = NULL;
- }
-}
-
-template <class DATA_TYPE, int SIZE>
-LLLocalIDHashMap<DATA_TYPE, SIZE>::~LLLocalIDHashMap()
-{
- S32 i;
- for (i = 0; i < MAX_ITERS; i++)
- {
- if (mIters[i])
- {
- mIters[i]->mHashMapp = NULL;
- mIterCount--;
- }
- }
- removeAll();
-}
-
-template <class DATA_TYPE, int SIZE>
-void LLLocalIDHashMap<DATA_TYPE, SIZE>::removeAll()
-{
- S32 bin;
- for (bin = 0; bin < 256; bin++)
- {
- LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
-
- BOOL first = TRUE;
- do // First node guaranteed to be there
- {
- S32 i;
- const S32 count = nodep->mCount;
-
- // Iterate through all members of this node
- for (i = 0; i < count; i++)
- {
- nodep->mData[i] = mNull;
- }
-
- nodep->mCount = 0;
- // Done with all objects in this node, go to the next.
-
- LLLocalIDHashNode<DATA_TYPE, SIZE>* curp = nodep;
- nodep = nodep->mNextNodep;
-
- // Delete the node if it's not the first node
- if (first)
- {
- first = FALSE;
- curp->mNextNodep = NULL;
- }
- else
- {
- delete curp;
- }
- } while (nodep);
- }
-}
-
-template <class DATA_TYPE, int SIZE>
-void LLLocalIDHashMap<DATA_TYPE, SIZE>::dumpIter()
-{
- std::cout << "Hash map with " << mIterCount << " iterators" << std::endl;
-
- std::cout << "Hash Map Iterators:" << std::endl;
- S32 i;
- for (i = 0; i < MAX_ITERS; i++)
- {
- if (mIters[i])
- {
- llinfos << i << " " << mIters[i]->mCurHashNodep << " " << mIters[i]->mCurHashNodeKey << llendl;
- }
- else
- {
- llinfos << i << "null" << llendl;
- }
- }
-}
-
-template <class DATA_TYPE, int SIZE>
-void LLLocalIDHashMap<DATA_TYPE, SIZE>::dumpBin(U32 bin)
-{
- std::cout << "Dump bin " << bin << std::endl;
-
- LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
- S32 node = 0;
- do // First node guaranteed to be there.
- {
- std::cout << "Bin " << bin
- << " node " << node
- << " count " << nodep->mCount
- << " contains " << std::flush;
-
- S32 i;
- for (i = 0; i < nodep->mCount; i++)
- {
- std::cout << nodep->mData[i] << " " << std::flush;
- }
-
- std::cout << std::endl;
-
- nodep = nodep->mNextNodep;
- node++;
- } while (nodep);
-}
-
-template <class DATA_TYPE, int SIZE>
-inline S32 LLLocalIDHashMap<DATA_TYPE, SIZE>::getLength() const
-{
- S32 count = 0;
- S32 bin;
- for (bin = 0; bin < 256; bin++)
- {
- const LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
- while (nodep)
- {
- count += nodep->mCount;
- nodep = nodep->mNextNodep;
- }
- }
- return count;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline DATA_TYPE &LLLocalIDHashMap<DATA_TYPE, SIZE>::get(const U32 local_id)
-{
- LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff];
-
- do // First node guaranteed to be there
- {
- S32 i;
- const S32 count = nodep->mCount;
-
- // Iterate through all members of this node
- for (i = 0; i < count; i++)
- {
- if (nodep->mKey[i] == local_id)
- {
- // We found it.
- return nodep->mData[i];
- }
- }
-
- // Done with all objects in this node, go to the next.
- nodep = nodep->mNextNodep;
- } while (nodep);
-
- return mNull;
-}
-
-
-template <class DATA_TYPE, int SIZE>
-inline BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::check(const U32 local_id) const
-{
- const LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff];
-
- do // First node guaranteed to be there
- {
- S32 i;
- const S32 count = nodep->mCount;
-
- // Iterate through all members of this node
- for (i = 0; i < count; i++)
- {
- if (nodep->mKey[i] == local_id)
- {
- // We found it.
- return TRUE;
- }
- }
-
- // Done with all objects in this node, go to the next.
- nodep = nodep->mNextNodep;
- } while (nodep);
-
- // Didn't find anything
- return FALSE;
-}
-
-
-template <class DATA_TYPE, int SIZE>
-inline DATA_TYPE &LLLocalIDHashMap<DATA_TYPE, SIZE>::set(const U32 local_id, const DATA_TYPE data)
-{
- // Set is just like a normal find, except that if we find a match
- // we replace it with the input value.
- // If we don't find a match, we append to the end of the list.
-
- LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff];
-
- while (1)
- {
- const S32 count = nodep->mCount;
-
- S32 i;
- for (i = 0; i < count; i++)
- {
- if (nodep->mKey[i] == local_id)
- {
- // We found a match for this key, replace the data with
- // the incoming data.
- nodep->mData[i] = data;
- return nodep->mData[i];
- }
- }
- if (!nodep->mNextNodep)
- {
- // We've iterated through all of the keys without finding a match
- if (i < SIZE)
- {
- // There's still some space on this node, append
- // the key and data to it.
- nodep->mKey[i] = local_id;
- nodep->mData[i] = data;
- nodep->mCount++;
-
- return nodep->mData[i];
- }
- else
- {
- // This node is full, append a new node to the end.
- nodep->mNextNodep = new LLLocalIDHashNode<DATA_TYPE, SIZE>;
- nodep->mNextNodep->mKey[0] = local_id;
- nodep->mNextNodep->mData[0] = data;
- nodep->mNextNodep->mCount = 1;
-
- return nodep->mNextNodep->mData[0];
- }
- }
-
- // No match on this node, go to the next
- nodep = nodep->mNextNodep;
- }
-}
-
-
-template <class DATA_TYPE, int SIZE>
-inline BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::remove(const U32 local_id)
-{
- // Remove is the trickiest operation.
- // What we want to do is swap the last element of the last
- // node if we find the one that we want to remove, but we have
- // to deal with deleting the node from the tail if it's empty, but
- // NOT if it's the only node left.
-
- const S32 node_index = local_id & 0xff;
-
- LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[node_index];
-
- // A modification of the standard search algorithm.
- do // First node guaranteed to be there
- {
- const S32 count = nodep->mCount;
-
- S32 i;
- for (i = 0; i < count; i++)
- {
- if (nodep->mKey[i] == local_id)
- {
- // If we're removing the item currently pointed to by one
- // or more iterators, we can just swap in the last item
- // and back the iterator(s) up by one.
- // Otherwise, we need to do a slow and safe shift of all
- // items back to one position to fill the hole and fix up
- // all iterators we find.
- BOOL need_shift = FALSE;
- S32 cur_iter;
- if (mIterCount)
- {
- for (cur_iter = 0; cur_iter < MAX_ITERS; cur_iter++)
- {
- if (mIters[cur_iter])
- {
- // We only care if the hash map node is on the one
- // that we're working on. If it's before, we've already
- // traversed it, if it's after, changing the order doesn't
- // matter.
- if (mIters[cur_iter]->mCurHashMapNodeNum == node_index)
- {
- if ((mIters[cur_iter]->mCurHashNodep == nodep)
- && (mIters[cur_iter]->mCurHashNodeKey == i))
- {
- // it's on the one we're deleting, we'll
- // fix the iterator quickly below.
- }
- else
- {
- // We're trying to remove an item on this
- // iterator's chain that this
- // iterator doesn't point to! We need to do
- // the slow remove-and-shift-down case.
- need_shift = TRUE;
- }
- }
- }
- }
- }
-
- // Removing an item that isn't pointed to by all iterators
- if (need_shift)
- {
- return removeWithShift(local_id);
- }
-
- // Fix the iterators that point to this node/i pair, the
- // one we're deleting
- for (cur_iter = 0; cur_iter < MAX_ITERS; cur_iter++)
- {
- if (mIters[cur_iter])
- {
- // We only care if the hash map node is on the one
- // that we're working on. If it's before, we've already
- // traversed it, if it's after, changing the order doesn't
- // matter.
- if (mIters[cur_iter]->mCurHashMapNodeNum == node_index)
- {
- if ((mIters[cur_iter]->mCurHashNodep == nodep)
- && (mIters[cur_iter]->mCurHashNodeKey == i))
- {
- // We can handle the case where we're deleting
- // the element we're on trivially (sort of).
- if (nodep->mCount > 1)
- {
- // If we're not going to delete this node,
- // it's OK.
- mIters[cur_iter]->mCurHashNodeKey--;
- }
- else
- {
- // We're going to delete this node, because this
- // is the last element on it.
-
- // Find the next node, and then back up one.
- mIters[cur_iter]->next();
- mIters[cur_iter]->mCurHashNodeKey--;
- }
- }
- }
- }
- }
-
- // We found the node that we want to remove.
- // Find the last (and next-to-last) node, and the index of the last
- // element. We could conceviably start from the node we're on,
- // but that makes it more complicated, this is easier.
-
- LLLocalIDHashNode<DATA_TYPE, SIZE> *prevp = &mNodes[node_index];
- LLLocalIDHashNode<DATA_TYPE, SIZE> *lastp = prevp;
-
- // Find the last and next-to-last
- while (lastp->mNextNodep)
- {
- prevp = lastp;
- lastp = lastp->mNextNodep;
- }
-
- // First, swap in the last to the current location.
- nodep->mKey[i] = lastp->mKey[lastp->mCount - 1];
- nodep->mData[i] = lastp->mData[lastp->mCount - 1];
-
- // Now, we delete the entry
- lastp->mCount--;
- lastp->mData[lastp->mCount] = mNull;
-
- if (!lastp->mCount)
- {
- // We deleted the last element!
- if (lastp != &mNodes[local_id & 0xff])
- {
- // Only blitz the node if it's not the head
- // Set the previous node to point to NULL, then
- // blitz the empty last node
- prevp->mNextNodep = NULL;
- delete lastp;
- }
- }
-
- return TRUE;
- }
- }
-
- // Iterate to the next node, we've scanned all the entries in this one.
- nodep = nodep->mNextNodep;
- } while (nodep);
-
- return FALSE;
-}
-
-template <class DATA_TYPE, int SIZE>
-BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::removeWithShift(const U32 local_id)
-{
- const S32 node_index = local_id & 0xFF;
- LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[node_index];
- LLLocalIDHashNode<DATA_TYPE, SIZE>* prevp = NULL;
- BOOL found = FALSE;
-
- do // First node guaranteed to be there
- {
- const S32 count = nodep->mCount;
- S32 i;
- for (i = 0; i < count; i++)
- {
- if (nodep->mKey[i] == local_id)
- {
- // Found the item. Start shifting items from later
- // in the list over this item.
- found = TRUE;
- }
-
- if (found)
- {
- // If there is an iterator on this node, we need to
- // back it up.
- S32 cur_iter;
- for (cur_iter = 0; cur_iter <MAX_ITERS; cur_iter++)
- {
- LLLocalIDHashMapIter<DATA_TYPE, SIZE>* iter;
- iter = mIters[cur_iter];
- // If an iterator is on this node,i pair, then back it up.
- if (iter
- && iter->mCurHashMapNodeNum == node_index
- && iter->mCurHashNodep == nodep
- && iter->mCurHashNodeKey == i)
- {
- if (i > 0)
- {
- // Don't need to move iterator nodep, since
- // we're in the same node.
- iter->mCurHashNodeKey--;
- }
- else if (prevp)
- {
- // need to go the previous node, last item
- iter->mCurHashNodep = prevp;
- iter->mCurHashNodeKey = prevp->mCount - 1;
- }
- else
- {
- // we're on the first item in the list, but
- // need to go back anyhow.
-
- // BUG: If this deletion empties the list,
- // iter->done() will be wrong until
- // iter->next() is called.
- iter->mCurHashNodeKey = -1;
- }
- }
- }
-
- // Copy data from the next position into this position.
- if (i < count-1)
- {
- // we're not on the last item in the node,
- // so we can copy within the node
- nodep->mKey[i] = nodep->mKey[i+1];
- nodep->mData[i] = nodep->mData[i+1];
- }
- else if (nodep->mNextNodep)
- {
- // we're on the last item in the node,
- // but there's a next node we can copy from
- nodep->mKey[i] = nodep->mNextNodep->mKey[0];
- nodep->mData[i] = nodep->mNextNodep->mData[0];
- }
- else
- {
- // We're on the last position in the list.
- // No one to copy from. Replace with nothing.
- nodep->mKey[i] = 0;
- nodep->mData[i] = mNull;
- }
- }
- }
-
- // Last node in chain, so delete the last node
- if (found
- && !nodep->mNextNodep)
- {
- // delete the last item off the last node
- nodep->mCount--;
-
- if (nodep->mCount == 0)
- {
- // We deleted the last element!
- if (nodep != &mNodes[node_index])
- {
- // Always have a prevp if we're not the head.
- llassert(prevp);
-
- // Only blitz the node if it's not the head
- // Set the previous node to point to NULL, then
- // blitz the empty last node
- prevp->mNextNodep = NULL;
- delete nodep;
- nodep = NULL;
- }
- }
-
- // Deleted last item in chain, so we're done.
- return found;
- }
-
- prevp = nodep;
- nodep = nodep->mNextNodep;
- } while (nodep);
-
- return found;
-}
-
-template <class DATA_TYPE, int SIZE>
-void LLLocalIDHashMap<DATA_TYPE, SIZE>::removeIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter)
-{
- S32 i;
- for (i = 0; i < MAX_ITERS; i++)
- {
- if (mIters[i] == iter)
- {
- mIters[i] = NULL;
- mIterCount--;
- return;
- }
- }
- llerrs << "Iterator " << iter << " not found for removal in hash map!" << llendl;
-}
-
-template <class DATA_TYPE, int SIZE>
-void LLLocalIDHashMap<DATA_TYPE, SIZE>::addIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter)
-{
- S32 i;
- for (i = 0; i < MAX_ITERS; i++)
- {
- if (mIters[i] == NULL)
- {
- mIters[i] = iter;
- mIterCount++;
- return;
- }
- }
- llerrs << "More than " << MAX_ITERS << " iterating over a map simultaneously!" << llendl;
-}
-
-
-
-//
-// LLLocalIDHashMapIter Implementation
-//
-template <class DATA_TYPE, int SIZE>
-LLLocalIDHashMapIter<DATA_TYPE, SIZE>::LLLocalIDHashMapIter(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp)
-{
- mHashMapp = NULL;
- setMap(hash_mapp);
-}
-
-template <class DATA_TYPE, int SIZE>
-LLLocalIDHashMapIter<DATA_TYPE, SIZE>::~LLLocalIDHashMapIter()
-{
- if (mHashMapp)
- {
- mHashMapp->removeIter(this);
- }
-}
-
-template <class DATA_TYPE, int SIZE>
-void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::setMap(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp)
-{
- if (mHashMapp)
- {
- mHashMapp->removeIter(this);
- }
- mHashMapp = hash_mapp;
- if (mHashMapp)
- {
- mHashMapp->addIter(this);
- }
-
- mCurHashNodep = NULL;
- mCurHashMapNodeNum = -1;
- mCurHashNodeKey = 0;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::first()
-{
- // Iterate through until we find the first non-empty node;
- S32 i;
- for (i = 0; i < 256; i++)
- {
- if (mHashMapp->mNodes[i].mCount)
- {
-
- mCurHashNodep = &mHashMapp->mNodes[i];
- mCurHashMapNodeNum = i;
- mCurHashNodeKey = 0;
- //return mCurHashNodep->mData[0];
- return;
- }
- }
-
- // Completely empty!
- mCurHashNodep = NULL;
- //return mNull;
- return;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline BOOL LLLocalIDHashMapIter<DATA_TYPE, SIZE>::done() const
-{
- return mCurHashNodep ? FALSE : TRUE;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline S32 LLLocalIDHashMapIter<DATA_TYPE, SIZE>::currentBin() const
-{
- if ( (mCurHashMapNodeNum > 255)
- ||(mCurHashMapNodeNum < 0))
- {
- return 0;
- }
- else
- {
- return mCurHashMapNodeNum;
- }
-}
-
-template <class DATA_TYPE, int SIZE>
-inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::setBin(S32 bin)
-{
- // Iterate through until we find the first non-empty node;
- S32 i;
- bin = llclamp(bin, 0, 255);
- for (i = bin; i < 256; i++)
- {
- if (mHashMapp->mNodes[i].mCount)
- {
-
- mCurHashNodep = &mHashMapp->mNodes[i];
- mCurHashMapNodeNum = i;
- mCurHashNodeKey = 0;
- return;
- }
- }
- for (i = 0; i < bin; i++)
- {
- if (mHashMapp->mNodes[i].mCount)
- {
-
- mCurHashNodep = &mHashMapp->mNodes[i];
- mCurHashMapNodeNum = i;
- mCurHashNodeKey = 0;
- return;
- }
- }
- // Completely empty!
- mCurHashNodep = NULL;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline DATA_TYPE &LLLocalIDHashMapIter<DATA_TYPE, SIZE>::current()
-{
- if (!mCurHashNodep)
- {
- return mNull;
- }
- return mCurHashNodep->mData[mCurHashNodeKey];
-}
-
-template <class DATA_TYPE, int SIZE>
-inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::next()
-{
- // No current entry, this iterator is done
- if (!mCurHashNodep)
- {
- //return mNull;
- return;
- }
-
- // Go to the next element
- mCurHashNodeKey++;
- if (mCurHashNodeKey < mCurHashNodep->mCount)
- {
- // We're not done with this node, return the current element
- //return mCurHashNodep->mData[mCurHashNodeKey];
- return;
- }
-
- // Done with this node, move to the next
- mCurHashNodep = mCurHashNodep->mNextNodep;
- if (mCurHashNodep)
- {
- // Return the first element
- mCurHashNodeKey = 0;
- //return mCurHashNodep->mData[0];
- return;
- }
-
- // Find the next non-empty node (keyed on the first byte)
- mCurHashMapNodeNum++;
-
- S32 i;
- for (i = mCurHashMapNodeNum; i < 256; i++)
- {
- if (mHashMapp->mNodes[i].mCount)
- {
- // We found one that wasn't empty
- mCurHashNodep = &mHashMapp->mNodes[i];
- mCurHashMapNodeNum = i;
- mCurHashNodeKey = 0;
- //return mCurHashNodep->mData[0];
- return;
- }
- }
-
- // OK, we're done, nothing else to iterate
- mCurHashNodep = NULL;
- mHashMapp->mIterCount--; // Decrement since we're safe to do removes now
- //return mNull;
- return;
-}
-
-#endif // LL_LLLOCALIDHASHMAP_H
diff --git a/indra/llcommon/lllog.cpp b/indra/llcommon/lllog.cpp
deleted file mode 100755
index fc4058b5c9..0000000000
--- a/indra/llcommon/lllog.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * @file lllog.cpp
- * @author Don
- * @date 2007-11-27
- * @brief Class to log messages to syslog for streambase to process.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "lllog.h"
-
-#include "llapp.h"
-#include "llsd.h"
-#include "llsdserialize.h"
-
-
-class LLLogImpl
-{
-public:
- LLLogImpl(LLApp* app) : mApp(app) {}
- ~LLLogImpl() {}
-
- void log(const std::string &message, LLSD& info);
- bool useLegacyLogMessage(const std::string &message);
-
-private:
- LLApp* mApp;
-};
-
-
-//@brief Function to log a message to syslog for streambase to collect.
-void LLLogImpl::log(const std::string &message, LLSD& info)
-{
- static S32 sequence = 0;
- LLSD log_config = mApp->getOption("log-messages");
- if (log_config.has(message))
- {
- LLSD message_config = log_config[message];
- if (message_config.has("use-syslog"))
- {
- if (! message_config["use-syslog"].asBoolean())
- {
- return;
- }
- }
- }
- llinfos << "LLLOGMESSAGE (" << (sequence++) << ") " << message
- << " " << LLSDNotationStreamer(info) << llendl;
-}
-
-//@brief Function to check if specified legacy log message should be sent.
-bool LLLogImpl::useLegacyLogMessage(const std::string &message)
-{
- LLSD log_config = mApp->getOption("log-messages");
- if (log_config.has(message))
- {
- LLSD message_config = log_config[message];
- if (message_config.has("use-legacy"))
- {
- return message_config["use-legacy"].asBoolean();
- }
- }
- return true;
-}
-
-
-LLLog::LLLog(LLApp* app)
-{
- mImpl = new LLLogImpl(app);
-}
-
-LLLog::~LLLog()
-{
- delete mImpl;
- mImpl = NULL;
-}
-
-void LLLog::log(const std::string &message, LLSD& info)
-{
- if (mImpl) mImpl->log(message, info);
-}
-
-bool LLLog::useLegacyLogMessage(const std::string &message)
-{
- if (mImpl)
- {
- return mImpl->useLegacyLogMessage(message);
- }
- return true;
-}
-
diff --git a/indra/llcommon/lllog.h b/indra/llcommon/lllog.h
deleted file mode 100755
index 7964412e83..0000000000
--- a/indra/llcommon/lllog.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- * @file lllog.h
- * @author Don
- * @date 2007-11-27
- * @brief Class to log messages to syslog for streambase to process.
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLLOG_H
-#define LL_LLLOG_H
-
-#include <string>
-
-class LLLogImpl;
-class LLApp;
-class LLSD;
-
-class LL_COMMON_API LLLog
-{
-public:
- LLLog(LLApp* app);
- virtual ~LLLog();
-
- virtual void log(const std::string &message, LLSD& info);
- virtual bool useLegacyLogMessage(const std::string &message);
-
-private:
- LLLogImpl* mImpl;
-};
-
-#endif /* LL_LLLOG_H */
-
diff --git a/indra/llcommon/lllslconstants.h b/indra/llcommon/lllslconstants.h
deleted file mode 100755
index 926ce32d75..0000000000
--- a/indra/llcommon/lllslconstants.h
+++ /dev/null
@@ -1,242 +0,0 @@
-/**
- * @file lllslconstants.h
- * @author James Cook
- * @brief Constants used in lsl.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLLSLCONSTANTS_H
-#define LL_LLLSLCONSTANTS_H
-
-// LSL: Return flags for llGetAgentInfo
-const U32 AGENT_FLYING = 0x0001;
-const U32 AGENT_ATTACHMENTS = 0x0002;
-const U32 AGENT_SCRIPTED = 0x0004;
-const U32 AGENT_MOUSELOOK = 0x0008;
-const U32 AGENT_SITTING = 0x0010;
-const U32 AGENT_ON_OBJECT = 0x0020;
-const U32 AGENT_AWAY = 0x0040;
-const U32 AGENT_WALKING = 0x0080;
-const U32 AGENT_IN_AIR = 0x0100;
-const U32 AGENT_TYPING = 0x0200;
-const U32 AGENT_CROUCHING = 0x0400;
-const U32 AGENT_BUSY = 0x0800;
-const U32 AGENT_ALWAYS_RUN = 0x1000;
-const U32 AGENT_AUTOPILOT = 0x2000;
-
-const S32 LSL_REMOTE_DATA_CHANNEL = 1;
-const S32 LSL_REMOTE_DATA_REQUEST = 2;
-const S32 LSL_REMOTE_DATA_REPLY = 3;
-
-// Constants used in extended LSL primitive setter and getters
-const S32 LSL_PRIM_TYPE_LEGACY = 1; // No longer supported.
-const S32 LSL_PRIM_MATERIAL = 2;
-const S32 LSL_PRIM_PHYSICS = 3;
-const S32 LSL_PRIM_TEMP_ON_REZ = 4;
-const S32 LSL_PRIM_PHANTOM = 5;
-const S32 LSL_PRIM_POSITION = 6;
-const S32 LSL_PRIM_SIZE = 7;
-const S32 LSL_PRIM_ROTATION = 8;
-const S32 LSL_PRIM_TYPE = 9; // Replacement for LSL_PRIM_TYPE_LEGACY
-const S32 LSL_PRIM_TEXTURE = 17;
-const S32 LSL_PRIM_COLOR = 18;
-const S32 LSL_PRIM_BUMP_SHINY = 19;
-const S32 LSL_PRIM_FULLBRIGHT = 20;
-const S32 LSL_PRIM_FLEXIBLE = 21;
-const S32 LSL_PRIM_TEXGEN = 22;
-const S32 LSL_PRIM_POINT_LIGHT = 23;
-const S32 LSL_PRIM_CAST_SHADOWS = 24;
-const S32 LSL_PRIM_GLOW = 25;
-const S32 LSL_PRIM_TEXT = 26;
-const S32 LSL_PRIM_NAME = 27;
-const S32 LSL_PRIM_DESC = 28;
-const S32 LSL_PRIM_ROT_LOCAL = 29;
-const S32 LSL_PRIM_PHYSICS_SHAPE_TYPE = 30;
-const S32 LSL_PRIM_OMEGA = 32;
-const S32 LSL_PRIM_POS_LOCAL = 33;
-const S32 LSL_PRIM_LINK_TARGET = 34;
-const S32 LSL_PRIM_SLICE = 35;
-
-const S32 LSL_PRIM_PHYSICS_SHAPE_PRIM = 0;
-const S32 LSL_PRIM_PHYSICS_SHAPE_NONE = 1;
-const S32 LSL_PRIM_PHYSICS_SHAPE_CONVEX = 2;
-
-const S32 LSL_PRIM_TYPE_BOX = 0;
-const S32 LSL_PRIM_TYPE_CYLINDER= 1;
-const S32 LSL_PRIM_TYPE_PRISM = 2;
-const S32 LSL_PRIM_TYPE_SPHERE = 3;
-const S32 LSL_PRIM_TYPE_TORUS = 4;
-const S32 LSL_PRIM_TYPE_TUBE = 5;
-const S32 LSL_PRIM_TYPE_RING = 6;
-const S32 LSL_PRIM_TYPE_SCULPT = 7;
-
-const S32 LSL_PRIM_HOLE_DEFAULT = 0x00;
-const S32 LSL_PRIM_HOLE_CIRCLE = 0x10;
-const S32 LSL_PRIM_HOLE_SQUARE = 0x20;
-const S32 LSL_PRIM_HOLE_TRIANGLE= 0x30;
-
-const S32 LSL_PRIM_MATERIAL_STONE = 0;
-const S32 LSL_PRIM_MATERIAL_METAL = 1;
-const S32 LSL_PRIM_MATERIAL_GLASS = 2;
-const S32 LSL_PRIM_MATERIAL_WOOD = 3;
-const S32 LSL_PRIM_MATERIAL_FLESH = 4;
-const S32 LSL_PRIM_MATERIAL_PLASTIC = 5;
-const S32 LSL_PRIM_MATERIAL_RUBBER = 6;
-const S32 LSL_PRIM_MATERIAL_LIGHT = 7;
-
-const S32 LSL_PRIM_SHINY_NONE = 0;
-const S32 LSL_PRIM_SHINY_LOW = 1;
-const S32 LSL_PRIM_SHINY_MEDIUM = 2;
-const S32 LSL_PRIM_SHINY_HIGH = 3;
-
-const S32 LSL_PRIM_TEXGEN_DEFAULT = 0;
-const S32 LSL_PRIM_TEXGEN_PLANAR = 1;
-
-const S32 LSL_PRIM_BUMP_NONE = 0;
-const S32 LSL_PRIM_BUMP_BRIGHT = 1;
-const S32 LSL_PRIM_BUMP_DARK = 2;
-const S32 LSL_PRIM_BUMP_WOOD = 3;
-const S32 LSL_PRIM_BUMP_BARK = 4;
-const S32 LSL_PRIM_BUMP_BRICKS = 5;
-const S32 LSL_PRIM_BUMP_CHECKER = 6;
-const S32 LSL_PRIM_BUMP_CONCRETE = 7;
-const S32 LSL_PRIM_BUMP_TILE = 8;
-const S32 LSL_PRIM_BUMP_STONE = 9;
-const S32 LSL_PRIM_BUMP_DISKS = 10;
-const S32 LSL_PRIM_BUMP_GRAVEL = 11;
-const S32 LSL_PRIM_BUMP_BLOBS = 12;
-const S32 LSL_PRIM_BUMP_SIDING = 13;
-const S32 LSL_PRIM_BUMP_LARGETILE = 14;
-const S32 LSL_PRIM_BUMP_STUCCO = 15;
-const S32 LSL_PRIM_BUMP_SUCTION = 16;
-const S32 LSL_PRIM_BUMP_WEAVE = 17;
-
-const S32 LSL_PRIM_SCULPT_TYPE_SPHERE = 1;
-const S32 LSL_PRIM_SCULPT_TYPE_TORUS = 2;
-const S32 LSL_PRIM_SCULPT_TYPE_PLANE = 3;
-const S32 LSL_PRIM_SCULPT_TYPE_CYLINDER = 4;
-const S32 LSL_PRIM_SCULPT_TYPE_MASK = 7;
-const S32 LSL_PRIM_SCULPT_FLAG_INVERT = 64;
-const S32 LSL_PRIM_SCULPT_FLAG_MIRROR = 128;
-
-const S32 LSL_ALL_SIDES = -1;
-const S32 LSL_LINK_ROOT = 1;
-const S32 LSL_LINK_FIRST_CHILD = 2;
-const S32 LSL_LINK_SET = -1;
-const S32 LSL_LINK_ALL_OTHERS = -2;
-const S32 LSL_LINK_ALL_CHILDREN = -3;
-const S32 LSL_LINK_THIS = -4;
-
-// LSL constants for llSetForSell
-const S32 SELL_NOT = 0;
-const S32 SELL_ORIGINAL = 1;
-const S32 SELL_COPY = 2;
-const S32 SELL_CONTENTS = 3;
-
-// LSL constants for llSetPayPrice
-const S32 PAY_PRICE_HIDE = -1;
-const S32 PAY_PRICE_DEFAULT = -2;
-const S32 MAX_PAY_BUTTONS = 4;
-const S32 PAY_BUTTON_DEFAULT_0 = 1;
-const S32 PAY_BUTTON_DEFAULT_1 = 5;
-const S32 PAY_BUTTON_DEFAULT_2 = 10;
-const S32 PAY_BUTTON_DEFAULT_3 = 20;
-
-// lsl email registration.
-const S32 EMAIL_REG_SUBSCRIBE_OBJECT = 0x01;
-const S32 EMAIL_REG_UNSUBSCRIBE_OBJECT = 0x02;
-const S32 EMAIL_REG_UNSUBSCRIBE_SIM = 0x04;
-
-const S32 LIST_STAT_RANGE = 0;
-const S32 LIST_STAT_MIN = 1;
-const S32 LIST_STAT_MAX = 2;
-const S32 LIST_STAT_MEAN = 3;
-const S32 LIST_STAT_MEDIAN = 4;
-const S32 LIST_STAT_STD_DEV = 5;
-const S32 LIST_STAT_SUM = 6;
-const S32 LIST_STAT_SUM_SQUARES = 7;
-const S32 LIST_STAT_NUM_COUNT = 8;
-const S32 LIST_STAT_GEO_MEAN = 9;
-
-const S32 STRING_TRIM_HEAD = 0x01;
-const S32 STRING_TRIM_TAIL = 0x02;
-const S32 STRING_TRIM = STRING_TRIM_HEAD | STRING_TRIM_TAIL;
-
-// llGetObjectDetails
-const S32 OBJECT_UNKNOWN_DETAIL = -1;
-const S32 OBJECT_NAME = 1;
-const S32 OBJECT_DESC = 2;
-const S32 OBJECT_POS = 3;
-const S32 OBJECT_ROT = 4;
-const S32 OBJECT_VELOCITY = 5;
-const S32 OBJECT_OWNER = 6;
-const S32 OBJECT_GROUP = 7;
-const S32 OBJECT_CREATOR = 8;
-const S32 OBJECT_RUNNING_SCRIPT_COUNT = 9;
-const S32 OBJECT_TOTAL_SCRIPT_COUNT = 10;
-const S32 OBJECT_SCRIPT_MEMORY = 11;
-const S32 OBJECT_SCRIPT_TIME = 12;
-const S32 OBJECT_PRIM_EQUIVALENCE = 13;
-const S32 OBJECT_SERVER_COST = 14;
-const S32 OBJECT_STREAMING_COST = 15;
-const S32 OBJECT_PHYSICS_COST = 16;
-const S32 OBJECT_CHARACTER_TIME = 17;
-const S32 OBJECT_ROOT = 18;
-const S32 OBJECT_ATTACHED_POINT = 19;
-const S32 OBJECT_PATHFINDING_TYPE = 20;
-const S32 OBJECT_PHYSICS = 21;
-const S32 OBJECT_PHANTOM = 22;
-const S32 OBJECT_TEMP_ON_REZ = 23;
-const S32 OBJECT_RENDER_WEIGHT = 24;
-
-// llTextBox() magic token string - yes this is a hack. sue me.
-char const* const TEXTBOX_MAGIC_TOKEN = "!!llTextBox!!";
-
-// changed() event flags
-const U32 CHANGED_NONE = 0x0;
-const U32 CHANGED_INVENTORY = 0x1;
-const U32 CHANGED_COLOR = 0x2;
-const U32 CHANGED_SHAPE = 0x4;
-const U32 CHANGED_SCALE = 0x8;
-const U32 CHANGED_TEXTURE = 0x10;
-const U32 CHANGED_LINK = 0x20;
-const U32 CHANGED_ALLOWED_DROP = 0x40;
-const U32 CHANGED_OWNER = 0x80;
-const U32 CHANGED_REGION = 0x100;
-const U32 CHANGED_TELEPORT = 0x200;
-const U32 CHANGED_REGION_START = 0x400;
-const U32 CHANGED_MEDIA = 0x800;
-
-// Possible error results
-const U32 LSL_STATUS_OK = 0;
-const U32 LSL_STATUS_MALFORMED_PARAMS = 1000;
-const U32 LSL_STATUS_TYPE_MISMATCH = 1001;
-const U32 LSL_STATUS_BOUNDS_ERROR = 1002;
-const U32 LSL_STATUS_NOT_FOUND = 1003;
-const U32 LSL_STATUS_NOT_SUPPORTED = 1004;
-const U32 LSL_STATUS_INTERNAL_ERROR = 1999;
-
-// Start per-function errors below, starting at 2000:
-const U32 LSL_STATUS_WHITELIST_FAILED = 2001;
-
-#endif
diff --git a/indra/llcommon/llmap.h b/indra/llcommon/llmap.h
deleted file mode 100755
index 6294a15d3b..0000000000
--- a/indra/llcommon/llmap.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/**
- * @file llmap.h
- * @brief LLMap class header file
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLMAP_H
-#define LL_LLMAP_H
-
-// llmap uses the fast stl library code in a manner consistant with LLSkipMap, et. al.
-
-template<class INDEX_TYPE, class MAPPED_TYPE> class LLMap
-{
-private:
- typedef typename std::map<INDEX_TYPE, MAPPED_TYPE> stl_map_t;
- typedef typename stl_map_t::iterator stl_iter_t;
- typedef typename stl_map_t::value_type stl_value_t;
-
- stl_map_t mStlMap;
- stl_iter_t mCurIter; // *iterator = pair<const INDEX_TYPE, MAPPED_TYPE>
- MAPPED_TYPE dummy_data;
- INDEX_TYPE dummy_index;
-
-public:
- LLMap() : mStlMap()
- {
- memset((void*)(&dummy_data), 0x0, sizeof(MAPPED_TYPE));
- memset((void*)(&dummy_index), 0x0, sizeof(INDEX_TYPE));
- mCurIter = mStlMap.begin();
- }
- ~LLMap()
- {
- mStlMap.clear();
- }
-
- // use these functions to itterate through a list
- void resetMap()
- {
- mCurIter = mStlMap.begin();
- }
-
- // get the current data and bump mCurrentp
- // This is kind of screwy since it returns a reference;
- // We have to have a dummy value for when we reach the end
- // or in case we have an empty list. Presumably, this value
- // will initialize to some NULL value that will end the iterator.
- // We really shouldn't be using getNextData() or getNextKey() anyway...
- MAPPED_TYPE &getNextData()
- {
- if (mCurIter == mStlMap.end())
- {
- return dummy_data;
- }
- else
- {
- return (*mCurIter++).second;
- }
- }
-
- const INDEX_TYPE &getNextKey()
- {
- if (mCurIter == mStlMap.end())
- {
- return dummy_index;
- }
- else
- {
- return (*mCurIter++).first;
- }
- }
-
- MAPPED_TYPE &getFirstData()
- {
- resetMap();
- return getNextData();
- }
-
- const INDEX_TYPE &getFirstKey()
- {
- resetMap();
- return getNextKey();
- }
-
- S32 getLength()
- {
- return mStlMap.size();
- }
-
- void addData(const INDEX_TYPE &index, MAPPED_TYPE pointed_to)
- {
- mStlMap.insert(stl_value_t(index, pointed_to));
- }
-
- void addData(const INDEX_TYPE &index)
- {
- mStlMap.insert(stl_value_t(index, dummy_data));
- }
-
- // if index doesn't exist, then insert a new node and return it
- MAPPED_TYPE &getData(const INDEX_TYPE &index)
- {
- std::pair<stl_iter_t, bool> res;
- res = mStlMap.insert(stl_value_t(index, dummy_data));
- return res.first->second;
- }
-
- // if index doesn't exist, then insert a new node, return it, and set b_new_entry to true
- MAPPED_TYPE &getData(const INDEX_TYPE &index, BOOL &b_new_entry)
- {
- std::pair<stl_iter_t, bool> res;
- res = mStlMap.insert(stl_value_t(index, dummy_data));
- b_new_entry = res.second;
- return res.first->second;
- }
-
- // If there, returns the data.
- // If not, returns NULL.
- // Never adds entries to the map.
- MAPPED_TYPE getIfThere(const INDEX_TYPE &index)
- {
- stl_iter_t iter;
- iter = mStlMap.find(index);
- if (iter == mStlMap.end())
- {
- return (MAPPED_TYPE)0;
- }
- else
- {
- return (*iter).second;
- }
- }
-
-
- // if index doesn't exist, then make a new node and return it
- MAPPED_TYPE &operator[](const INDEX_TYPE &index)
- {
- return getData(index);
- }
-
- // do a reverse look-up, return NULL if failed
- INDEX_TYPE reverseLookup(const MAPPED_TYPE data)
- {
- stl_iter_t iter;
- stl_iter_t end_iter;
- iter = mStlMap.begin();
- end_iter = mStlMap.end();
- while (iter != end_iter)
- {
- if ((*iter).second == data)
- return (*iter).first;
- iter++;
- }
- return (INDEX_TYPE)0;
- }
-
- BOOL removeData(const INDEX_TYPE &index)
- {
- mCurIter = mStlMap.find(index);
- if (mCurIter == mStlMap.end())
- {
- return FALSE;
- }
- else
- {
- stl_iter_t iter = mCurIter++; // incrament mCurIter to the next element
- mStlMap.erase(iter);
- return TRUE;
- }
- }
-
- // does this index exist?
- BOOL checkData(const INDEX_TYPE &index)
- {
- stl_iter_t iter;
- iter = mStlMap.find(index);
- if (iter == mStlMap.end())
- {
- return FALSE;
- }
- else
- {
- mCurIter = iter;
- return TRUE;
- }
- }
-
- BOOL deleteData(const INDEX_TYPE &index)
- {
- mCurIter = mStlMap.find(index);
- if (mCurIter == mStlMap.end())
- {
- return FALSE;
- }
- else
- {
- stl_iter_t iter = mCurIter++; // incrament mCurIter to the next element
- delete (*iter).second;
- mStlMap.erase(iter);
- return TRUE;
- }
- }
-
- void deleteAllData()
- {
- stl_iter_t iter;
- stl_iter_t end_iter;
- iter = mStlMap.begin();
- end_iter = mStlMap.end();
- while (iter != end_iter)
- {
- delete (*iter).second;
- iter++;
- }
- mStlMap.clear();
- mCurIter = mStlMap.end();
- }
-
- void removeAllData()
- {
- mStlMap.clear();
- }
-};
-
-
-#endif
diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp
index 1409c55d1c..ed80af36d8 100755
--- a/indra/llcommon/llmd5.cpp
+++ b/indra/llcommon/llmd5.cpp
@@ -76,7 +76,6 @@ documentation and/or software.
#include "llmd5.h"
-#include <cassert>
#include <iostream> // cerr
// how many bytes to grab at a time when checking files
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index 70ad10ad55..e0b2aa87c2 100755
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -27,12 +27,9 @@
#include "linden_common.h"
-//#if MEM_TRACK_MEM
#include "llthread.h"
-//#endif
#if defined(LL_WINDOWS)
-//# include <windows.h>
# include <psapi.h>
#elif defined(LL_DARWIN)
# include <sys/types.h>
@@ -46,15 +43,18 @@
#include "llsys.h"
#include "llframetimer.h"
+#include "lltrace.h"
//----------------------------------------------------------------------------
//static
char* LLMemory::reserveMem = 0;
-U32 LLMemory::sAvailPhysicalMemInKB = U32_MAX ;
-U32 LLMemory::sMaxPhysicalMemInKB = 0;
-U32 LLMemory::sAllocatedMemInKB = 0;
-U32 LLMemory::sAllocatedPageSizeInKB = 0 ;
-U32 LLMemory::sMaxHeapSizeInKB = U32_MAX ;
+U32Kilobytes LLMemory::sAvailPhysicalMemInKB(U32_MAX);
+U32Kilobytes LLMemory::sMaxPhysicalMemInKB(0);
+static LLTrace::SampleStatHandle<F64Megabytes> sAllocatedMem("allocated_mem", "active memory in use by application");
+static LLTrace::SampleStatHandle<F64Megabytes> sVirtualMem("virtual_mem", "virtual memory assigned to application");
+U32Kilobytes LLMemory::sAllocatedMemInKB(0);
+U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0);
+U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX);
BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE;
#if __DEBUG_PRIVATE_MEM__
@@ -67,7 +67,7 @@ void ll_assert_aligned_func(uintptr_t ptr,U32 alignment)
// Redundant, place to set breakpoints.
if (ptr%alignment!=0)
{
- llwarns << "alignment check failed" << llendl;
+ LL_WARNS() << "alignment check failed" << LL_ENDL;
}
llassert(ptr%alignment==0);
#endif
@@ -97,9 +97,9 @@ void LLMemory::freeReserve()
}
//static
-void LLMemory::initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure)
+void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure)
{
- sMaxHeapSizeInKB = (U32)(max_heap_size_gb * 1024 * 1024) ;
+ sMaxHeapSizeInKB = max_heap_size;
sEnableMemoryFailurePrevention = prevent_heap_failure ;
}
@@ -112,14 +112,16 @@ void LLMemory::updateMemoryInfo()
if (!GetProcessMemoryInfo(self, &counters, sizeof(counters)))
{
- llwarns << "GetProcessMemoryInfo failed" << llendl;
+ LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
return ;
}
- sAllocatedMemInKB = (U32)(counters.WorkingSetSize / 1024) ;
- sAllocatedPageSizeInKB = (U32)(counters.PagefileUsage / 1024) ;
+ sAllocatedMemInKB = (U32Bytes)(counters.WorkingSetSize) ;
+ sample(sAllocatedMem, sAllocatedMemInKB);
+ sAllocatedPageSizeInKB = (U32Bytes)(counters.PagefileUsage) ;
+ sample(sVirtualMem, sAllocatedPageSizeInKB);
- U32 avail_phys, avail_virtual;
+ U32Kilobytes avail_phys, avail_virtual;
LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
@@ -129,13 +131,13 @@ void LLMemory::updateMemoryInfo()
}
else
{
- sAvailPhysicalMemInKB = 0 ;
+ sAvailPhysicalMemInKB = U32Kilobytes(0);
}
#else
//not valid for other systems for now.
- sAllocatedMemInKB = (U32)(LLMemory::getCurrentRSS() / 1024) ;
- sMaxPhysicalMemInKB = U32_MAX ;
- sAvailPhysicalMemInKB = U32_MAX ;
+ sAllocatedMemInKB = (U32Bytes)LLMemory::getCurrentRSS();
+ sMaxPhysicalMemInKB = (U32Bytes)U32_MAX ;
+ sAvailPhysicalMemInKB = (U32Bytes)U32_MAX ;
#endif
return ;
@@ -156,7 +158,7 @@ void* LLMemory::tryToAlloc(void* address, U32 size)
{
if(!VirtualFree(address, 0, MEM_RELEASE))
{
- llerrs << "error happens when free some memory reservation." << llendl ;
+ LL_ERRS() << "error happens when free some memory reservation." << LL_ENDL ;
}
}
return address ;
@@ -174,14 +176,14 @@ void LLMemory::logMemoryInfo(BOOL update)
LLPrivateMemoryPoolManager::getInstance()->updateStatistics() ;
}
- llinfos << "Current allocated physical memory(KB): " << sAllocatedMemInKB << llendl ;
- llinfos << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << llendl ;
- llinfos << "Current availabe physical memory(KB): " << sAvailPhysicalMemInKB << llendl ;
- llinfos << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << llendl ;
+ LL_INFOS() << "Current allocated physical memory(KB): " << sAllocatedMemInKB << LL_ENDL ;
+ LL_INFOS() << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << LL_ENDL ;
+ LL_INFOS() << "Current availabe physical memory(KB): " << sAvailPhysicalMemInKB << LL_ENDL ;
+ LL_INFOS() << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << LL_ENDL ;
- llinfos << "--- private pool information -- " << llendl ;
- llinfos << "Total reserved (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalReservedSize / 1024 << llendl ;
- llinfos << "Total allocated (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalAllocatedSize / 1024 << llendl ;
+ LL_INFOS() << "--- private pool information -- " << LL_ENDL ;
+ LL_INFOS() << "Total reserved (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalReservedSize / 1024 << LL_ENDL ;
+ LL_INFOS() << "Total allocated (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalAllocatedSize / 1024 << LL_ENDL ;
}
//return 0: everything is normal;
@@ -190,8 +192,8 @@ void LLMemory::logMemoryInfo(BOOL update)
//static
bool LLMemory::isMemoryPoolLow()
{
- static const U32 LOW_MEMEOY_POOL_THRESHOLD_KB = 64 * 1024 ; //64 MB for emergency use
- const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB
+ static const U32Megabytes LOW_MEMORY_POOL_THRESHOLD(64);
+ const static U32Megabytes MAX_SIZE_CHECKED_MEMORY_BLOCK(64);
static void* last_reserved_address = NULL ;
if(!sEnableMemoryFailurePrevention)
@@ -199,32 +201,32 @@ bool LLMemory::isMemoryPoolLow()
return false ; //no memory failure prevention.
}
- if(sAvailPhysicalMemInKB < (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2)) //out of physical memory
+ if(sAvailPhysicalMemInKB < (LOW_MEMORY_POOL_THRESHOLD / 4)) //out of physical memory
{
return true ;
}
- if(sAllocatedPageSizeInKB + (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2) > sMaxHeapSizeInKB) //out of virtual address space.
+ if(sAllocatedPageSizeInKB + (LOW_MEMORY_POOL_THRESHOLD / 4) > sMaxHeapSizeInKB) //out of virtual address space.
{
return true ;
}
- bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB ||
- sAllocatedPageSizeInKB + LOW_MEMEOY_POOL_THRESHOLD_KB > sMaxHeapSizeInKB) ;
+ bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMORY_POOL_THRESHOLD
+ || sAllocatedPageSizeInKB + LOW_MEMORY_POOL_THRESHOLD > sMaxHeapSizeInKB) ;
//check the virtual address space fragmentation
if(!is_low)
{
if(!last_reserved_address)
{
- last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+ last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
}
else
{
- last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+ last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
if(!last_reserved_address) //failed, try once more
{
- last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+ last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
}
}
@@ -235,19 +237,19 @@ bool LLMemory::isMemoryPoolLow()
}
//static
-U32 LLMemory::getAvailableMemKB()
+U32Kilobytes LLMemory::getAvailableMemKB()
{
return sAvailPhysicalMemInKB ;
}
//static
-U32 LLMemory::getMaxMemKB()
+U32Kilobytes LLMemory::getMaxMemKB()
{
return sMaxPhysicalMemInKB ;
}
//static
-U32 LLMemory::getAllocatedMemKB()
+U32Kilobytes LLMemory::getAllocatedMemKB()
{
return sAllocatedMemInKB ;
}
@@ -263,7 +265,7 @@ U64 LLMemory::getCurrentRSS()
if (!GetProcessMemoryInfo(self, &counters, sizeof(counters)))
{
- llwarns << "GetProcessMemoryInfo failed" << llendl;
+ LL_WARNS() << "GetProcessMemoryInfo failed" << LL_ENDL;
return 0;
}
@@ -301,7 +303,7 @@ U32 LLMemory::getWorkingSetSize()
// if (sysctl(ctl, 2, &page_size, &size, NULL, 0) == -1)
// {
-// llwarns << "Couldn't get page size" << llendl;
+// LL_WARNS() << "Couldn't get page size" << LL_ENDL;
// return 0;
// } else {
// return page_size;
@@ -320,11 +322,11 @@ U64 LLMemory::getCurrentRSS()
// If we ever wanted it, the process virtual size is also available as:
// virtualSize = basicInfo.virtual_size;
-// llinfos << "resident size is " << residentSize << llendl;
+// LL_INFOS() << "resident size is " << residentSize << LL_ENDL;
}
else
{
- llwarns << "task_info failed" << llendl;
+ LL_WARNS() << "task_info failed" << LL_ENDL;
}
return residentSize;
@@ -345,7 +347,7 @@ U64 LLMemory::getCurrentRSS()
if (fp == NULL)
{
- llwarns << "couldn't open " << statPath << llendl;
+ LL_WARNS() << "couldn't open " << statPath << LL_ENDL;
goto bail;
}
@@ -358,7 +360,7 @@ U64 LLMemory::getCurrentRSS()
&rss);
if (ret != 1)
{
- llwarns << "couldn't parse contents of " << statPath << llendl;
+ LL_WARNS() << "couldn't parse contents of " << statPath << LL_ENDL;
rss = 0;
}
}
@@ -388,12 +390,12 @@ U64 LLMemory::getCurrentRSS()
sprintf(path, "/proc/%d/psinfo", (int)getpid());
int proc_fd = -1;
if((proc_fd = open(path, O_RDONLY)) == -1){
- llwarns << "LLmemory::getCurrentRSS() unable to open " << path << ". Returning 0 RSS!" << llendl;
+ LL_WARNS() << "LLmemory::getCurrentRSS() unable to open " << path << ". Returning 0 RSS!" << LL_ENDL;
return 0;
}
psinfo_t proc_psinfo;
if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
- llwarns << "LLmemory::getCurrentRSS() Unable to read from " << path << ". Returning 0 RSS!" << llendl;
+ LL_WARNS() << "LLmemory::getCurrentRSS() Unable to read from " << path << ". Returning 0 RSS!" << LL_ENDL;
close(proc_fd);
return 0;
}
@@ -423,141 +425,6 @@ U32 LLMemory::getWorkingSetSize()
#endif
//--------------------------------------------------------------------------------------------------
-#if MEM_TRACK_MEM
-#include "llframetimer.h"
-
-//static
-LLMemTracker* LLMemTracker::sInstance = NULL ;
-
-LLMemTracker::LLMemTracker()
-{
- mLastAllocatedMem = LLMemory::getWorkingSetSize() ;
- mCapacity = 128 ;
- mCurIndex = 0 ;
- mCounter = 0 ;
- mDrawnIndex = 0 ;
- mPaused = FALSE ;
-
- mMutexp = new LLMutex() ;
- mStringBuffer = new char*[128] ;
- mStringBuffer[0] = new char[mCapacity * 128] ;
- for(S32 i = 1 ; i < mCapacity ; i++)
- {
- mStringBuffer[i] = mStringBuffer[i-1] + 128 ;
- }
-}
-
-LLMemTracker::~LLMemTracker()
-{
- delete[] mStringBuffer[0] ;
- delete[] mStringBuffer;
- delete mMutexp ;
-}
-
-//static
-LLMemTracker* LLMemTracker::getInstance()
-{
- if(!sInstance)
- {
- sInstance = new LLMemTracker() ;
- }
- return sInstance ;
-}
-
-//static
-void LLMemTracker::release()
-{
- if(sInstance)
- {
- delete sInstance ;
- sInstance = NULL ;
- }
-}
-
-//static
-void LLMemTracker::track(const char* function, const int line)
-{
- static const S32 MIN_ALLOCATION = 0 ; //1KB
-
- if(mPaused)
- {
- return ;
- }
-
- U32 allocated_mem = LLMemory::getWorkingSetSize() ;
-
- LLMutexLock lock(mMutexp) ;
-
- S32 delta_mem = allocated_mem - mLastAllocatedMem ;
- mLastAllocatedMem = allocated_mem ;
-
- if(delta_mem <= 0)
- {
- return ; //occupied memory does not grow
- }
-
- if(delta_mem < MIN_ALLOCATION)
- {
- return ;
- }
-
- char* buffer = mStringBuffer[mCurIndex++] ;
- F32 time = (F32)LLFrameTimer::getElapsedSeconds() ;
- S32 hours = (S32)(time / (60*60));
- S32 mins = (S32)((time - hours*(60*60)) / 60);
- S32 secs = (S32)((time - hours*(60*60) - mins*60));
- strcpy(buffer, function) ;
- sprintf(buffer + strlen(function), " line: %d DeltaMem: %d (bytes) Time: %d:%02d:%02d", line, delta_mem, hours,mins,secs) ;
-
- if(mCounter < mCapacity)
- {
- mCounter++ ;
- }
- if(mCurIndex >= mCapacity)
- {
- mCurIndex = 0 ;
- }
-}
-
-
-//static
-void LLMemTracker::preDraw(BOOL pause)
-{
- mMutexp->lock() ;
-
- mPaused = pause ;
- mDrawnIndex = mCurIndex - 1;
- mNumOfDrawn = 0 ;
-}
-
-//static
-void LLMemTracker::postDraw()
-{
- mMutexp->unlock() ;
-}
-
-//static
-const char* LLMemTracker::getNextLine()
-{
- if(mNumOfDrawn >= mCounter)
- {
- return NULL ;
- }
- mNumOfDrawn++;
-
- if(mDrawnIndex < 0)
- {
- mDrawnIndex = mCapacity - 1 ;
- }
-
- return mStringBuffer[mDrawnIndex--] ;
-}
-
-#endif //MEM_TRACK_MEM
-//--------------------------------------------------------------------------------------------------
-
-
-//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
//minimum slot size and minimal slot size interval
const U32 ATOMIC_MEM_SLOT = 16 ; //bytes
@@ -961,7 +828,7 @@ void LLPrivateMemoryPool::LLMemoryChunk::dump()
total_size += blk_list[i]->getBufferSize() ;
if((U32)blk_list[i]->getBuffer() < (U32)blk_list[i-1]->getBuffer() + blk_list[i-1]->getBufferSize())
{
- llerrs << "buffer corrupted." << llendl ;
+ LL_ERRS() << "buffer corrupted." << LL_ENDL ;
}
}
@@ -982,32 +849,32 @@ void LLPrivateMemoryPool::LLMemoryChunk::dump()
}
else
{
- llerrs << "gap happens" << llendl ;
+ LL_ERRS() << "gap happens" << LL_ENDL ;
}
}
#endif
#if 0
- llinfos << "---------------------------" << llendl ;
- llinfos << "Chunk buffer: " << (U32)getBuffer() << " size: " << getBufferSize() << llendl ;
+ LL_INFOS() << "---------------------------" << LL_ENDL ;
+ LL_INFOS() << "Chunk buffer: " << (U32)getBuffer() << " size: " << getBufferSize() << LL_ENDL ;
- llinfos << "available blocks ... " << llendl ;
+ LL_INFOS() << "available blocks ... " << LL_ENDL ;
for(S32 i = 0 ; i < mBlockLevels ; i++)
{
LLMemoryBlock* blk = mAvailBlockList[i] ;
while(blk)
{
- llinfos << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << llendl ;
+ LL_INFOS() << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << LL_ENDL ;
blk = blk->mNext ;
}
}
- llinfos << "free blocks ... " << llendl ;
+ LL_INFOS() << "free blocks ... " << LL_ENDL ;
for(S32 i = 0 ; i < mPartitionLevels ; i++)
{
LLMemoryBlock* blk = mFreeSpaceList[i] ;
while(blk)
{
- llinfos << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << llendl ;
+ LL_INFOS() << "blk buffer " << (U32)blk->getBuffer() << " size: " << blk->getBufferSize() << LL_ENDL ;
blk = blk->mNext ;
}
}
@@ -1403,7 +1270,7 @@ char* LLPrivateMemoryPool::allocate(U32 size)
if(to_log)
{
- llwarns << "The memory pool overflows, now using heap directly!" << llendl ;
+ LL_WARNS() << "The memory pool overflows, now using heap directly!" << LL_ENDL ;
to_log = false ;
}
@@ -1496,7 +1363,7 @@ void LLPrivateMemoryPool::destroyPool()
if(mNumOfChunks > 0)
{
- llwarns << "There is some memory not freed when destroy the memory pool!" << llendl ;
+ LL_WARNS() << "There is some memory not freed when destroy the memory pool!" << LL_ENDL ;
}
mNumOfChunks = 0 ;
@@ -1514,11 +1381,11 @@ bool LLPrivateMemoryPool::checkSize(U32 asked_size)
{
if(mReservedPoolSize + asked_size > mMaxPoolSize)
{
- llinfos << "Max pool size: " << mMaxPoolSize << llendl ;
- llinfos << "Total reserved size: " << mReservedPoolSize + asked_size << llendl ;
- llinfos << "Total_allocated Size: " << getTotalAllocatedSize() << llendl ;
+ LL_INFOS() << "Max pool size: " << mMaxPoolSize << LL_ENDL ;
+ LL_INFOS() << "Total reserved size: " << mReservedPoolSize + asked_size << LL_ENDL ;
+ LL_INFOS() << "Total_allocated Size: " << getTotalAllocatedSize() << LL_ENDL ;
- //llerrs << "The pool is overflowing..." << llendl ;
+ //LL_ERRS() << "The pool is overflowing..." << LL_ENDL ;
return false ;
}
@@ -1731,7 +1598,7 @@ void LLPrivateMemoryPool::removeFromHashTable(LLMemoryChunk* chunk)
void LLPrivateMemoryPool::rehash()
{
- llinfos << "new hash factor: " << mHashFactor << llendl ;
+ LL_INFOS() << "new hash factor: " << mHashFactor << LL_ENDL ;
mChunkHashList.clear() ;
mChunkHashList.resize(mHashFactor) ;
@@ -1811,7 +1678,7 @@ void LLPrivateMemoryPool::LLChunkHashElement::remove(LLPrivateMemoryPool::LLMemo
}
else
{
- llerrs << "This slot does not contain this chunk!" << llendl ;
+ LL_ERRS() << "This slot does not contain this chunk!" << LL_ENDL ;
}
}
@@ -1843,12 +1710,12 @@ LLPrivateMemoryPoolManager::~LLPrivateMemoryPoolManager()
#if __DEBUG_PRIVATE_MEM__
if(!sMemAllocationTracker.empty())
{
- llwarns << "there is potential memory leaking here. The list of not freed memory blocks are from: " <<llendl ;
+ LL_WARNS() << "there is potential memory leaking here. The list of not freed memory blocks are from: " <<LL_ENDL ;
S32 k = 0 ;
for(mem_allocation_info_t::iterator iter = sMemAllocationTracker.begin() ; iter != sMemAllocationTracker.end() ; ++iter)
{
- llinfos << k++ << ", " << (U32)iter->first << " : " << iter->second << llendl ;
+ LL_INFOS() << k++ << ", " << (U32)iter->first << " : " << iter->second << LL_ENDL ;
}
sMemAllocationTracker.clear() ;
}
@@ -2044,7 +1911,7 @@ void LLPrivateMemoryPoolManager::freeMem(LLPrivateMemoryPool* poolp, void* addr
}
else
{
- llerrs << "private pool is used before initialized.!" << llendl ;
+ LL_ERRS() << "private pool is used before initialized.!" << LL_ENDL ;
}
}
}
@@ -2118,7 +1985,7 @@ void LLPrivateMemoryPoolTester::test(U32 min_size, U32 max_size, U32 stride, U32
//allocate space for p ;
if(!(p = ::new char**[times]) || !(*p = ::new char*[times * levels]))
{
- llerrs << "memory initialization for p failed" << llendl ;
+ LL_ERRS() << "memory initialization for p failed" << LL_ENDL ;
}
//init
@@ -2190,8 +2057,8 @@ void LLPrivateMemoryPoolTester::testAndTime(U32 size, U32 times)
{
LLTimer timer ;
- llinfos << " -**********************- " << llendl ;
- llinfos << "test size: " << size << " test times: " << times << llendl ;
+ LL_INFOS() << " -**********************- " << LL_ENDL ;
+ LL_INFOS() << "test size: " << size << " test times: " << times << LL_ENDL ;
timer.reset() ;
char** p = new char*[times] ;
@@ -2203,7 +2070,7 @@ void LLPrivateMemoryPoolTester::testAndTime(U32 size, U32 times)
p[i] = ALLOCATE_MEM(sPool, size) ;
if(!p[i])
{
- llerrs << "allocation failed" << llendl ;
+ LL_ERRS() << "allocation failed" << LL_ENDL ;
}
}
//de-allocation
@@ -2212,7 +2079,7 @@ void LLPrivateMemoryPoolTester::testAndTime(U32 size, U32 times)
FREE_MEM(sPool, p[i]) ;
p[i] = NULL ;
}
- llinfos << "time spent using customized memory pool: " << timer.getElapsedTimeF32() << llendl ;
+ LL_INFOS() << "time spent using customized memory pool: " << timer.getElapsedTimeF32() << LL_ENDL ;
timer.reset() ;
@@ -2223,7 +2090,7 @@ void LLPrivateMemoryPoolTester::testAndTime(U32 size, U32 times)
p[i] = ::new char[size] ;
if(!p[i])
{
- llerrs << "allocation failed" << llendl ;
+ LL_ERRS() << "allocation failed" << LL_ENDL ;
}
}
//de-allocation
@@ -2232,7 +2099,7 @@ void LLPrivateMemoryPoolTester::testAndTime(U32 size, U32 times)
::delete[] p[i] ;
p[i] = NULL ;
}
- llinfos << "time spent using standard allocator/de-allocator: " << timer.getElapsedTimeF32() << llendl ;
+ LL_INFOS() << "time spent using standard allocator/de-allocator: " << timer.getElapsedTimeF32() << LL_ENDL ;
delete[] p;
}
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index 61e30f11cc..db52f2b1f4 100755
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -27,15 +27,35 @@
#define LLMEMORY_H
#include "linden_common.h"
+#include "llunits.h"
+#if !LL_WINDOWS
+#include <stdint.h>
+#endif
class LLMutex ;
#if LL_WINDOWS && LL_DEBUG
#define LL_CHECK_MEMORY llassert(_CrtCheckMemory());
#else
-#define LL_CHECK_MEMORY
+#define LL_CHECK_MEMORY
+#endif
+
+
+#if LL_WINDOWS
+#define LL_ALIGN_OF __alignof
+#else
+#define LL_ALIGN_OF __align_of__
+#endif
+
+#if LL_WINDOWS
+#define LL_DEFAULT_HEAP_ALIGN 8
+#elif LL_DARWIN
+#define LL_DEFAULT_HEAP_ALIGN 16
+#elif LL_LINUX
+#define LL_DEFAULT_HEAP_ALIGN 8
#endif
+
LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment);
#ifdef SHOW_ASSERT
@@ -74,7 +94,8 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16)
-inline void* ll_aligned_malloc( size_t size, int align )
+
+inline void* ll_aligned_malloc_fallback( size_t size, int align )
{
#if defined(LL_WINDOWS)
return _aligned_malloc(size, align);
@@ -88,7 +109,7 @@ inline void* ll_aligned_malloc( size_t size, int align )
#endif
}
-inline void ll_aligned_free( void* ptr )
+inline void ll_aligned_free_fallback( void* ptr )
{
#if defined(LL_WINDOWS)
_aligned_free(ptr);
@@ -161,7 +182,7 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi
#if defined(LL_WINDOWS)
return _aligned_malloc(size, 32);
#elif defined(LL_DARWIN)
- return ll_aligned_malloc( size, 32 );
+ return ll_aligned_malloc_fallback( size, 32 );
#else
void *rtn;
if (LL_LIKELY(0 == posix_memalign(&rtn, 32, size)))
@@ -176,12 +197,54 @@ inline void ll_aligned_free_32(void *p)
#if defined(LL_WINDOWS)
_aligned_free(p);
#elif defined(LL_DARWIN)
- ll_aligned_free( p );
+ ll_aligned_free_fallback( p );
#else
free(p); // posix_memalign() is compatible with heap deallocator
#endif
}
+// general purpose dispatch functions that are forced inline so they can compile down to a single call
+template<size_t ALIGNMENT>
+LL_FORCE_INLINE void* ll_aligned_malloc(size_t size)
+{
+ if (LL_DEFAULT_HEAP_ALIGN % ALIGNMENT == 0)
+ {
+ return malloc(size);
+ }
+ else if (ALIGNMENT == 16)
+ {
+ return ll_aligned_malloc_16(size);
+ }
+ else if (ALIGNMENT == 32)
+ {
+ return ll_aligned_malloc_32(size);
+ }
+ else
+ {
+ return ll_aligned_malloc_fallback(size, ALIGNMENT);
+ }
+}
+
+template<size_t ALIGNMENT>
+LL_FORCE_INLINE void ll_aligned_free(void* ptr)
+{
+ if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
+ {
+ free(ptr);
+ }
+ else if (ALIGNMENT == 16)
+ {
+ ll_aligned_free_16(ptr);
+ }
+ else if (ALIGNMENT == 32)
+ {
+ return ll_aligned_free_32(ptr);
+ }
+ else
+ {
+ return ll_aligned_free_fallback(ptr);
+ }
+}
// Copy words 16-byte blocks from src to dst. Source and destination MUST NOT OVERLAP.
// Source and dest must be 16-byte aligned and size must be multiple of 16.
@@ -269,70 +332,25 @@ public:
static U64 getCurrentRSS();
static U32 getWorkingSetSize();
static void* tryToAlloc(void* address, U32 size);
- static void initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure);
+ static void initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure);
static void updateMemoryInfo() ;
static void logMemoryInfo(BOOL update = FALSE);
static bool isMemoryPoolLow();
- static U32 getAvailableMemKB() ;
- static U32 getMaxMemKB() ;
- static U32 getAllocatedMemKB() ;
+ static U32Kilobytes getAvailableMemKB() ;
+ static U32Kilobytes getMaxMemKB() ;
+ static U32Kilobytes getAllocatedMemKB() ;
private:
static char* reserveMem;
- static U32 sAvailPhysicalMemInKB ;
- static U32 sMaxPhysicalMemInKB ;
- static U32 sAllocatedMemInKB;
- static U32 sAllocatedPageSizeInKB ;
+ static U32Kilobytes sAvailPhysicalMemInKB ;
+ static U32Kilobytes sMaxPhysicalMemInKB ;
+ static U32Kilobytes sAllocatedMemInKB;
+ static U32Kilobytes sAllocatedPageSizeInKB ;
- static U32 sMaxHeapSizeInKB;
+ static U32Kilobytes sMaxHeapSizeInKB;
static BOOL sEnableMemoryFailurePrevention;
};
-//----------------------------------------------------------------------------
-#if MEM_TRACK_MEM
-class LLMutex ;
-class LL_COMMON_API LLMemTracker
-{
-private:
- LLMemTracker() ;
- ~LLMemTracker() ;
-
-public:
- static void release() ;
- static LLMemTracker* getInstance() ;
-
- void track(const char* function, const int line) ;
- void preDraw(BOOL pause) ;
- void postDraw() ;
- const char* getNextLine() ;
-
-private:
- static LLMemTracker* sInstance ;
-
- char** mStringBuffer ;
- S32 mCapacity ;
- U32 mLastAllocatedMem ;
- S32 mCurIndex ;
- S32 mCounter;
- S32 mDrawnIndex;
- S32 mNumOfDrawn;
- BOOL mPaused;
- LLMutex* mMutexp ;
-};
-
-#define MEM_TRACK_RELEASE LLMemTracker::release() ;
-#define MEM_TRACK LLMemTracker::getInstance()->track(__FUNCTION__, __LINE__) ;
-
-#else // MEM_TRACK_MEM
-
-#define MEM_TRACK_RELEASE
-#define MEM_TRACK
-
-#endif // MEM_TRACK_MEM
-
-//----------------------------------------------------------------------------
-
-
//
//class LLPrivateMemoryPool defines a private memory pool for an application to use, so the application does not
//need to access the heap directly fro each memory allocation. Throught this, the allocation speed is faster,
diff --git a/indra/llcommon/llmemorystream.cpp b/indra/llcommon/llmemorystream.cpp
index 723d94f025..707ac8fd0f 100755
--- a/indra/llcommon/llmemorystream.cpp
+++ b/indra/llcommon/llmemorystream.cpp
@@ -45,7 +45,7 @@ void LLMemoryStreamBuf::reset(const U8* start, S32 length)
int LLMemoryStreamBuf::underflow()
{
- //lldebugs << "LLMemoryStreamBuf::underflow()" << llendl;
+ //LL_DEBUGS() << "LLMemoryStreamBuf::underflow()" << LL_ENDL;
if(gptr() < egptr())
{
return *gptr();
diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp
index 731e58bd20..1fc821d9a9 100755
--- a/indra/llcommon/llmetricperformancetester.cpp
+++ b/indra/llcommon/llmetricperformancetester.cpp
@@ -29,9 +29,9 @@
#include "indra_constants.h"
#include "llerror.h"
#include "llsdserialize.h"
-#include "llstat.h"
#include "lltreeiterators.h"
#include "llmetricperformancetester.h"
+#include "llfasttimer.h"
//----------------------------------------------------------------------------------------------
// LLMetricPerformanceTesterBasic : static methods and testers management
@@ -56,7 +56,7 @@ BOOL LLMetricPerformanceTesterBasic::addTester(LLMetricPerformanceTesterBasic* t
std::string name = tester->getTesterName() ;
if (getTester(name))
{
- llerrs << "Tester name is already used by some other tester : " << name << llendl ;
+ LL_ERRS() << "Tester name is already used by some other tester : " << name << LL_ENDL ;
return FALSE;
}
@@ -91,7 +91,7 @@ LLMetricPerformanceTesterBasic* LLMetricPerformanceTesterBasic::getTester(std::s
// Return TRUE if this metric is requested or if the general default "catch all" metric is requested
BOOL LLMetricPerformanceTesterBasic::isMetricLogRequested(std::string name)
{
- return (LLFastTimer::sMetricLog && ((LLFastTimer::sLogName == name) || (LLFastTimer::sLogName == DEFAULT_METRIC_NAME)));
+ return (LLTrace::BlockTimer::sMetricLog && ((LLTrace::BlockTimer::sLogName == name) || (LLTrace::BlockTimer::sLogName == DEFAULT_METRIC_NAME)));
}
/*static*/
@@ -136,7 +136,7 @@ void LLMetricPerformanceTesterBasic::doAnalysisMetrics(std::string baseline, std
std::ifstream target_is(target.c_str());
if (!base_is.is_open() || !target_is.is_open())
{
- llwarns << "'-analyzeperformance' error : baseline or current target file inexistent" << llendl;
+ LL_WARNS() << "'-analyzeperformance' error : baseline or current target file inexistent" << LL_ENDL;
base_is.close();
target_is.close();
return;
@@ -176,7 +176,7 @@ LLMetricPerformanceTesterBasic::LLMetricPerformanceTesterBasic(std::string name)
{
if (mName == std::string())
{
- llerrs << "LLMetricPerformanceTesterBasic construction invalid : Empty name passed to constructor" << llendl ;
+ LL_ERRS() << "LLMetricPerformanceTesterBasic construction invalid : Empty name passed to constructor" << LL_ENDL ;
}
mValidInstance = LLMetricPerformanceTesterBasic::addTester(this) ;
@@ -194,8 +194,7 @@ void LLMetricPerformanceTesterBasic::preOutputTestResults(LLSD* sd)
void LLMetricPerformanceTesterBasic::postOutputTestResults(LLSD* sd)
{
- LLMutexLock lock(LLFastTimer::sLogLock);
- LLFastTimer::sLogQueue.push((*sd));
+ LLTrace::BlockTimer::pushLog(*sd);
}
void LLMetricPerformanceTesterBasic::outputTestResults()
@@ -242,7 +241,7 @@ void LLMetricPerformanceTesterBasic::analyzePerformance(std::ofstream* os, LLSD*
(F32)((*base)[label][ mMetricStrings[index] ].asReal()), (F32)((*current)[label][ mMetricStrings[index] ].asReal())) ;
break;
default:
- llerrs << "unsupported metric " << mMetricStrings[index] << " LLSD type: " << (S32)(*current)[label][ mMetricStrings[index] ].type() << llendl ;
+ LL_ERRS() << "unsupported metric " << mMetricStrings[index] << " LLSD type: " << (S32)(*current)[label][ mMetricStrings[index] ].type() << LL_ENDL ;
}
}
}
@@ -306,7 +305,7 @@ void LLMetricPerformanceTesterWithSession::analyzePerformance(std::ofstream* os,
if (!mBaseSessionp || !mCurrentSessionp)
{
- llerrs << "Error loading test sessions." << llendl ;
+ LL_ERRS() << "Error loading test sessions." << LL_ENDL ;
}
// Compare
diff --git a/indra/llcommon/llmetrics.cpp b/indra/llcommon/llmetrics.cpp
index 3078139f43..d40afe5160 100755
--- a/indra/llcommon/llmetrics.cpp
+++ b/indra/llcommon/llmetrics.cpp
@@ -65,7 +65,7 @@ void LLMetricsImpl::recordEventDetails(const std::string& location,
metrics["location"] = location;
metrics["stats"] = stats;
- llinfos << "LLMETRICS: " << (LLSDNotationStreamer(metrics)) << llendl;
+ LL_INFOS() << "LLMETRICS: " << (LLSDNotationStreamer(metrics)) << LL_ENDL;
}
// Store this:
@@ -128,7 +128,7 @@ void LLMetricsImpl::printTotals(LLSD metadata)
out_sd["stats"] = stats;
- llinfos << "LLMETRICS: AGGREGATE: " << LLSDOStreamer<LLSDNotationFormatter>(out_sd) << llendl;
+ LL_INFOS() << "LLMETRICS: AGGREGATE: " << LLSDOStreamer<LLSDNotationFormatter>(out_sd) << LL_ENDL;
}
LLMetrics::LLMetrics()
diff --git a/indra/llcommon/llmetrics.h b/indra/llcommon/llmetrics.h
index 4f0ae56338..85a6986049 100755
--- a/indra/llcommon/llmetrics.h
+++ b/indra/llcommon/llmetrics.h
@@ -38,7 +38,7 @@ public:
LLMetrics();
virtual ~LLMetrics();
- // Adds this event to aggregate totals and records details to syslog (llinfos)
+ // Adds this event to aggregate totals and records details to syslog (LL_INFOS())
virtual void recordEventDetails(const std::string& location,
const std::string& mesg,
bool success,
diff --git a/indra/llcommon/llmortician.h b/indra/llcommon/llmortician.h
index 319955ef93..9517e2db5e 100755
--- a/indra/llcommon/llmortician.h
+++ b/indra/llcommon/llmortician.h
@@ -28,6 +28,7 @@
#define LLMORTICIAN_H
#include "stdtypes.h"
+#include <list>
class LL_COMMON_API LLMortician
{
diff --git a/indra/llcommon/llmutex.cpp b/indra/llcommon/llmutex.cpp
new file mode 100644
index 0000000000..9c13ef9e30
--- /dev/null
+++ b/indra/llcommon/llmutex.cpp
@@ -0,0 +1,205 @@
+/**
+ * @file llmutex.cpp
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llapr.h"
+
+#include "apr_portable.h"
+
+#include "llmutex.h"
+#include "llthread.h"
+
+//============================================================================
+
+LLMutex::LLMutex(apr_pool_t *poolp) :
+ mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD)
+{
+ //if (poolp)
+ //{
+ // mIsLocalPool = FALSE;
+ // mAPRPoolp = poolp;
+ //}
+ //else
+ {
+ mIsLocalPool = TRUE;
+ apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
+ }
+ apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
+}
+
+
+LLMutex::~LLMutex()
+{
+#if MUTEX_DEBUG
+ //bad assertion, the subclass LLSignal might be "locked", and that's OK
+ //llassert_always(!isLocked()); // better not be locked!
+#endif
+ if (ll_apr_is_initialized())
+ {
+ apr_thread_mutex_destroy(mAPRMutexp);
+ if (mIsLocalPool)
+ {
+ apr_pool_destroy(mAPRPoolp);
+ }
+ }
+ mAPRMutexp = NULL;
+}
+
+
+void LLMutex::lock()
+{
+ if(isSelfLocked())
+ { //redundant lock
+ mCount++;
+ return;
+ }
+
+ apr_thread_mutex_lock(mAPRMutexp);
+
+#if MUTEX_DEBUG
+ // Have to have the lock before we can access the debug info
+ U32 id = LLThread::currentID();
+ if (mIsLocked[id] != FALSE)
+ LL_ERRS() << "Already locked in Thread: " << id << LL_ENDL;
+ mIsLocked[id] = TRUE;
+#endif
+
+ mLockingThread = LLThread::currentID();
+}
+
+void LLMutex::unlock()
+{
+ if (mCount > 0)
+ { //not the root unlock
+ mCount--;
+ return;
+ }
+
+#if MUTEX_DEBUG
+ // Access the debug info while we have the lock
+ U32 id = LLThread::currentID();
+ if (mIsLocked[id] != TRUE)
+ LL_ERRS() << "Not locked in Thread: " << id << LL_ENDL;
+ mIsLocked[id] = FALSE;
+#endif
+
+ mLockingThread = NO_THREAD;
+ apr_thread_mutex_unlock(mAPRMutexp);
+}
+
+bool LLMutex::isLocked()
+{
+ apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
+ if (APR_STATUS_IS_EBUSY(status))
+ {
+ return true;
+ }
+ else
+ {
+ apr_thread_mutex_unlock(mAPRMutexp);
+ return false;
+ }
+}
+
+bool LLMutex::isSelfLocked()
+{
+ return mLockingThread == LLThread::currentID();
+}
+
+U32 LLMutex::lockingThread() const
+{
+ return mLockingThread;
+}
+
+bool LLMutex::trylock()
+{
+ if(isSelfLocked())
+ { //redundant lock
+ mCount++;
+ return true;
+ }
+
+ apr_status_t status(apr_thread_mutex_trylock(mAPRMutexp));
+ if (APR_STATUS_IS_EBUSY(status))
+ {
+ return false;
+ }
+
+#if MUTEX_DEBUG
+ // Have to have the lock before we can access the debug info
+ U32 id = LLThread::currentID();
+ if (mIsLocked[id] != FALSE)
+ LL_ERRS() << "Already locked in Thread: " << id << LL_ENDL;
+ mIsLocked[id] = TRUE;
+#endif
+
+ mLockingThread = LLThread::currentID();
+ return true;
+}
+
+//============================================================================
+
+LLCondition::LLCondition(apr_pool_t *poolp) :
+ LLMutex(poolp)
+{
+ // base class (LLMutex) has already ensured that mAPRPoolp is set up.
+
+ apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
+}
+
+
+LLCondition::~LLCondition()
+{
+ apr_thread_cond_destroy(mAPRCondp);
+ mAPRCondp = NULL;
+}
+
+
+void LLCondition::wait()
+{
+ if (!isLocked())
+ { //mAPRMutexp MUST be locked before calling apr_thread_cond_wait
+ apr_thread_mutex_lock(mAPRMutexp);
+#if MUTEX_DEBUG
+ // avoid asserts on destruction in non-release builds
+ U32 id = LLThread::currentID();
+ mIsLocked[id] = TRUE;
+#endif
+ }
+ apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
+}
+
+void LLCondition::signal()
+{
+ apr_thread_cond_signal(mAPRCondp);
+}
+
+void LLCondition::broadcast()
+{
+ apr_thread_cond_broadcast(mAPRCondp);
+}
+
+
+//============================================================================
diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h
new file mode 100644
index 0000000000..3659a319a2
--- /dev/null
+++ b/indra/llcommon/llmutex.h
@@ -0,0 +1,141 @@
+/**
+ * @file llmutex.h
+ * @brief Base classes for mutex and condition handling.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLMUTEX_H
+#define LL_LLMUTEX_H
+
+#include "stdtypes.h"
+
+//============================================================================
+
+#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
+
+struct apr_thread_mutex_t;
+struct apr_pool_t;
+struct apr_thread_cond_t;
+
+class LL_COMMON_API LLMutex
+{
+public:
+ typedef enum
+ {
+ NO_THREAD = 0xFFFFFFFF
+ } e_locking_thread;
+
+ LLMutex(apr_pool_t *apr_poolp = NULL); // NULL pool constructs a new pool for the mutex
+ virtual ~LLMutex();
+
+ void lock(); // blocks
+ bool trylock(); // non-blocking, returns true if lock held.
+ void unlock(); // undefined behavior when called on mutex not being held
+ bool isLocked(); // non-blocking, but does do a lock/unlock so not free
+ bool isSelfLocked(); //return true if locked in a same thread
+ U32 lockingThread() const; //get ID of locking thread
+
+protected:
+ apr_thread_mutex_t *mAPRMutexp;
+ mutable U32 mCount;
+ mutable U32 mLockingThread;
+
+ apr_pool_t *mAPRPoolp;
+ BOOL mIsLocalPool;
+
+#if MUTEX_DEBUG
+ std::map<U32, BOOL> mIsLocked;
+#endif
+};
+
+// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
+class LL_COMMON_API LLCondition : public LLMutex
+{
+public:
+ LLCondition(apr_pool_t* apr_poolp); // Defaults to global pool, could use the thread pool as well.
+ ~LLCondition();
+
+ void wait(); // blocks
+ void signal();
+ void broadcast();
+
+protected:
+ apr_thread_cond_t* mAPRCondp;
+};
+
+class LLMutexLock
+{
+public:
+ LLMutexLock(LLMutex* mutex)
+ {
+ mMutex = mutex;
+
+ if(mMutex)
+ mMutex->lock();
+ }
+ ~LLMutexLock()
+ {
+ if(mMutex)
+ mMutex->unlock();
+ }
+private:
+ LLMutex* mMutex;
+};
+
+//============================================================================
+
+// Scoped locking class similar in function to LLMutexLock but uses
+// the trylock() method to conditionally acquire lock without
+// blocking. Caller resolves the resulting condition by calling
+// the isLocked() method and either punts or continues as indicated.
+//
+// Mostly of interest to callers needing to avoid stalls who can
+// guarantee another attempt at a later time.
+
+class LLMutexTrylock
+{
+public:
+ LLMutexTrylock(LLMutex* mutex)
+ : mMutex(mutex),
+ mLocked(false)
+ {
+ if (mMutex)
+ mLocked = mMutex->trylock();
+ }
+
+ ~LLMutexTrylock()
+ {
+ if (mMutex && mLocked)
+ mMutex->unlock();
+ }
+
+ bool isLocked() const
+ {
+ return mLocked;
+ }
+
+private:
+ LLMutex* mMutex;
+ bool mLocked;
+};
+#endif // LL_LLTHREAD_H
diff --git a/indra/llcommon/llnametable.h b/indra/llcommon/llnametable.h
index d3283543f3..d3283543f3 100755..100644
--- a/indra/llcommon/llnametable.h
+++ b/indra/llcommon/llnametable.h
diff --git a/indra/llcommon/lloptioninterface.cpp b/indra/llcommon/lloptioninterface.cpp
deleted file mode 100755
index 23fae76dc0..0000000000
--- a/indra/llcommon/lloptioninterface.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * @file lloptioninterface.cpp
- * @brief
- *
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "lloptioninterface.h"
-
-
-LLOptionInterface::~LLOptionInterface()
-{
-
-}
diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h
index 88c09c8dca..c9ebc70d19 100755
--- a/indra/llcommon/llpointer.h
+++ b/indra/llcommon/llpointer.h
@@ -27,6 +27,7 @@
#define LLPOINTER_H
#include "llerror.h" // *TODO: consider eliminating this
+#include "llmutex.h"
//----------------------------------------------------------------------------
// RefCount objects should generally only be accessed by way of LLPointer<>'s
@@ -97,24 +98,13 @@ public:
LLPointer<Type>& operator =(Type* ptr)
{
- if( mPointer != ptr )
- {
- unref();
- mPointer = ptr;
- ref();
- }
-
+ assign(ptr);
return *this;
}
LLPointer<Type>& operator =(const LLPointer<Type>& ptr)
{
- if( mPointer != ptr.mPointer )
- {
- unref();
- mPointer = ptr.mPointer;
- ref();
- }
+ assign(ptr);
return *this;
}
@@ -122,12 +112,7 @@ public:
template<typename Subclass>
LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)
{
- if( mPointer != ptr.get() )
- {
- unref();
- mPointer = ptr.get();
- ref();
- }
+ assign(ptr.get());
return *this;
}
@@ -144,6 +129,16 @@ protected:
void ref();
void unref();
#else
+
+ void assign(const LLPointer<Type>& ptr)
+ {
+ if( mPointer != ptr.mPointer )
+ {
+ unref();
+ mPointer = ptr.mPointer;
+ ref();
+ }
+ }
void ref()
{
if (mPointer)
@@ -156,12 +151,12 @@ protected:
{
if (mPointer)
{
- Type *tempp = mPointer;
+ Type *temp = mPointer;
mPointer = NULL;
- tempp->unref();
+ temp->unref();
if (mPointer != NULL)
{
- llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
+ LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
unref();
}
}
@@ -171,4 +166,52 @@ protected:
Type* mPointer;
};
+template<typename Type>
+class LLCopyOnWritePointer : public LLPointer<Type>
+{
+public:
+ typedef LLCopyOnWritePointer<Type> self_t;
+ typedef LLPointer<Type> pointer_t;
+
+ LLCopyOnWritePointer()
+ : mStayUnique(false)
+ {}
+
+ LLCopyOnWritePointer(Type* ptr)
+ : LLPointer<Type>(ptr),
+ mStayUnique(false)
+ {}
+
+ LLCopyOnWritePointer(LLPointer<Type>& ptr)
+ : LLPointer<Type>(ptr),
+ mStayUnique(false)
+ {
+ if (ptr.mForceUnique)
+ {
+ makeUnique();
+ }
+ }
+
+ Type* write()
+ {
+ makeUnique();
+ return pointer_t::mPointer;
+ }
+
+ void makeUnique()
+ {
+ if (pointer_t::notNull() && pointer_t::mPointer->getNumRefs() > 1)
+ {
+ *(pointer_t* )(this) = new Type(*pointer_t::mPointer);
+ }
+ }
+
+ const Type* operator->() const { return pointer_t::mPointer; }
+ const Type& operator*() const { return *pointer_t::mPointer; }
+
+ void setStayUnique(bool stay) { makeUnique(); mStayUnique = stay; }
+private:
+ bool mStayUnique;
+};
+
#endif
diff --git a/indra/llcommon/lloptioninterface.h b/indra/llcommon/llpredicate.cpp
index 93b465db32..1278948e24 100755..100644
--- a/indra/llcommon/lloptioninterface.h
+++ b/indra/llcommon/llpredicate.cpp
@@ -1,8 +1,8 @@
/**
- * @file lloptioninterface.h
- * @brief
+ * @file llpredicate.cpp
+ * @brief abstraction for filtering objects by predicates, with arbitrary boolean expressions
*
- * $LicenseInfo:firstyear=2009&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
@@ -23,18 +23,19 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-
-#ifndef LL_LLOPTIONINTERFACE_H
-#define LL_LLOPTIONINTERFACE_H
-
#include "linden_common.h"
-class LLSD;
-class LLOptionInterface
+#include "llpredicate.h"
+
+namespace LLPredicate
{
-public:
- virtual ~LLOptionInterface() = 0;
- virtual LLSD getOption(const std::string& name) const = 0;
-};
+ const U32 cPredicateFlagsFromEnum[5] =
+ {
+ 0xAAAAaaaa, // 10101010101010101010101010101010
+ 0xCCCCcccc, // 11001100110011001100110011001100
+ 0xF0F0F0F0, // 11110000111100001111000011110000
+ 0xFF00FF00, // 11111111000000001111111100000000
+ 0xFFFF0000 // 11111111111111110000000000000000
+ };
+}
-#endif
diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h
new file mode 100644
index 0000000000..a0e970a799
--- /dev/null
+++ b/indra/llcommon/llpredicate.h
@@ -0,0 +1,210 @@
+/**
+ * @file llpredicate.h
+ * @brief abstraction for filtering objects by predicates, with arbitrary boolean expressions
+ *
+ * $LicenseInfo:firstyear=2008&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPREDICATE_H
+#define LL_LLPREDICATE_H
+
+#include "llerror.h"
+
+namespace LLPredicate
+{
+ template<typename ENUM> class Rule;
+
+ extern const U32 cPredicateFlagsFromEnum[5];
+
+ template<typename ENUM>
+ class Value
+ {
+ public:
+ typedef U32 predicate_flag_t;
+ static const S32 cMaxEnum = 5;
+
+ Value(ENUM e, bool predicate_value = true)
+ : mPredicateFlags(predicate_value ? cPredicateFlagsFromEnum[e] : ~cPredicateFlagsFromEnum[e])
+ {
+ llassert(0 <= e && e < cMaxEnum);
+ }
+
+ Value()
+ : mPredicateFlags(0xFFFFffff)
+ {}
+
+ Value operator!() const
+ {
+ Value new_value;
+ new_value.mPredicateFlags = ~mPredicateFlags;
+ return new_value;
+ }
+
+ Value operator &&(const Value other) const
+ {
+ Value new_value;
+ new_value.mPredicateFlags = mPredicateFlags & other.mPredicateFlags;
+ return new_value;
+ }
+
+ Value operator ||(const Value other) const
+ {
+ Value new_value;
+ new_value.mPredicateFlags = mPredicateFlags | other.mPredicateFlags;
+ return new_value;
+ }
+
+ void set(ENUM e, bool value = true)
+ {
+ llassert(0 <= e && e < cMaxEnum);
+ predicate_flag_t flags_to_modify;
+ predicate_flag_t mask = cPredicateFlagsFromEnum[e];
+ if (value)
+ { // add predicate "e" to flags that don't contain it already
+ flags_to_modify = (mPredicateFlags & ~mask);
+ // clear flags not containing e
+ mPredicateFlags &= mask;
+ // add back flags shifted to contain e
+ mPredicateFlags |= flags_to_modify << (0x1 << e);
+ }
+ else
+ { // remove predicate "e" from flags that contain it
+ flags_to_modify = (mPredicateFlags & mask);
+ // clear flags containing e
+ mPredicateFlags &= ~mask;
+ // add back flags shifted to not contain e
+ mPredicateFlags |= flags_to_modify >> (0x1 << e);
+ }
+ }
+
+ void forget(ENUM e)
+ {
+ set(e, true);
+ U32 flags_with_predicate = mPredicateFlags;
+ set(e, false);
+ // ambiguous value is result of adding and removing predicate at the same time!
+ mPredicateFlags |= flags_with_predicate;
+ }
+
+ bool allSet() const
+ {
+ return mPredicateFlags == ~0;
+ }
+
+ bool noneSet() const
+ {
+ return mPredicateFlags == 0;
+ }
+
+ bool someSet() const
+ {
+ return mPredicateFlags != 0;
+ }
+
+ private:
+ predicate_flag_t mPredicateFlags;
+ };
+
+ template<typename ENUM>
+ class Rule
+ {
+ public:
+ Rule(ENUM value)
+ : mRule(value)
+ {}
+
+ Rule(const Value<ENUM> other)
+ : mRule(other)
+ {}
+
+ Rule()
+ {}
+
+ void require(ENUM e)
+ {
+ mRule.set(e, require);
+ }
+
+ void allow(ENUM e)
+ {
+ mRule.forget(e);
+ }
+
+ bool check(const Value<ENUM> value) const
+ {
+ return (mRule && value).someSet();
+ }
+
+ bool requires(const Value<ENUM> value) const
+ {
+ return (mRule && value).someSet() && (!mRule && value).noneSet();
+ }
+
+ bool isAmbivalent(const Value<ENUM> value) const
+ {
+ return (mRule && value).someSet() && (!mRule && value).someSet();
+ }
+
+ bool acceptsAll() const
+ {
+ return mRule.allSet();
+ }
+
+ bool acceptsNone() const
+ {
+ return mRule.noneSet();
+ }
+
+ Rule operator!() const
+ {
+ Rule new_rule;
+ new_rule.mRule = !mRule;
+ return new_rule;
+ }
+
+ Rule operator &&(const Rule other) const
+ {
+ Rule new_rule;
+ new_rule.mRule = mRule && other.mRule;
+ return new_rule;
+ }
+
+ Rule operator ||(const Rule other) const
+ {
+ Rule new_rule;
+ new_rule.mRule = mRule || other.mRule;
+ return new_rule;
+ }
+
+ private:
+ Value<ENUM> mRule;
+ };
+}
+
+template<typename ENUM>
+LLPredicate::Value<ENUM> ll_make_predicate(ENUM e, bool predicate_value = true)
+{
+ return LLPredicate::Value<ENUM>(e, predicate_value);
+}
+
+
+#endif // LL_LLPREDICATE_H
diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index 7fdb537ab5..309165da7f 100755
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -181,4 +181,25 @@
# define LL_COMMON_API
#endif // LL_COMMON_LINK_SHARED
+#if LL_WINDOWS
+#define LL_TYPEOF(exp) decltype(exp)
+#elif LL_LINUX
+#define LL_TYPEOF(exp) typeof(exp)
+#elif LL_DARWIN
+#define LL_TYPEOF(exp) typeof(exp)
+#endif
+
+#define LL_TO_STRING_HELPER(x) #x
+#define LL_TO_STRING(x) LL_TO_STRING_HELPER(x)
+#define LL_FILE_LINENO_MSG(msg) __FILE__ "(" LL_TO_STRING(__LINE__) ") : " msg
+#define LL_GLUE_IMPL(x, y) x##y
+#define LL_GLUE_TOKENS(x, y) LL_GLUE_IMPL(x, y)
+
+#if LL_WINDOWS
+#define LL_COMPILE_TIME_MESSAGE(msg) __pragma(message(LL_FILE_LINENO_MSG(msg)))
+#else
+// no way to get gcc 4.2 to print a user-defined diagnostic message only when a macro is used
+#define LL_COMPILE_TIME_MESSAGE(msg)
+#endif
+
#endif // not LL_LINDEN_PREPROCESSOR_H
diff --git a/indra/llcommon/llpriqueuemap.h b/indra/llcommon/llpriqueuemap.h
index da997c7b04..d8d3edd48a 100755
--- a/indra/llcommon/llpriqueuemap.h
+++ b/indra/llcommon/llpriqueuemap.h
@@ -84,7 +84,7 @@ public:
pqm_iter iter = mMap.find(LLPQMKey<DATA_TYPE>(priority, data));
if (iter != mMap.end())
{
- llerrs << "Pushing already existing data onto queue!" << llendl;
+ LL_ERRS() << "Pushing already existing data onto queue!" << LL_ENDL;
}
#endif
mMap.insert(pqm_pair(LLPQMKey<DATA_TYPE>(priority, data), data));
@@ -112,14 +112,14 @@ public:
iter = mMap.find(cur_key);
if (iter == mMap.end())
{
- llwarns << "Data not on priority queue!" << llendl;
+ LL_WARNS() << "Data not on priority queue!" << LL_ENDL;
// OK, try iterating through all of the data and seeing if we just screwed up the priority
// somehow.
for (iter = mMap.begin(); iter != mMap.end(); iter++)
{
if ((*(iter)).second == data)
{
- llerrs << "Data on priority queue but priority not matched!" << llendl;
+ LL_ERRS() << "Data on priority queue but priority not matched!" << LL_ENDL;
}
}
return;
diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h
index d711ce2f74..43ccadc412 100755
--- a/indra/llcommon/llprocess.h
+++ b/indra/llcommon/llprocess.h
@@ -29,6 +29,7 @@
#include "llinitparam.h"
#include "llsdparam.h"
+#include "llwin32headerslean.h"
#include "apr_thread_proc.h"
#include <boost/shared_ptr.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
@@ -38,8 +39,7 @@
#include <stdexcept>
#if LL_WINDOWS
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h> // HANDLE (eye roll)
+#include "llwin32headerslean.h" // for HANDLE
#elif LL_LINUX
#if defined(Status)
#undef Status
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index fd8f603d21..69043dc173 100755
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -32,9 +32,7 @@
//#include <memory>
#if LL_WINDOWS
-# define WIN32_LEAN_AND_MEAN
-# include <winsock2.h>
-# include <windows.h>
+# include "llwin32headerslean.h"
# define _interlockedbittestandset _renamed_interlockedbittestandset
# define _interlockedbittestandreset _renamed_interlockedbittestandreset
# include <intrin.h>
@@ -702,7 +700,7 @@ private:
__cpuid(0x1, eax, ebx, ecx, edx);
if(feature_infos[0] != (S32)edx)
{
- llerrs << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << llendl;
+ LL_ERRS() << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << LL_ENDL;
}
#endif // LL_RELEASE_FOR_DOWNLOAD
@@ -877,7 +875,7 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL)
LLProcessorInfo::~LLProcessorInfo() {}
-F64 LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); }
+F64MegahertzImplicit LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); }
bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); }
bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); }
bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); }
diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h
index 6364d3c8bb..90e5bc59ee 100755
--- a/indra/llcommon/llprocessor.h
+++ b/indra/llcommon/llprocessor.h
@@ -27,6 +27,8 @@
#ifndef LLPROCESSOR_H
#define LLPROCESSOR_H
+#include "llunits.h"
+
class LLProcessorInfoImpl;
class LL_COMMON_API LLProcessorInfo
@@ -35,7 +37,7 @@ public:
LLProcessorInfo();
~LLProcessorInfo();
- F64 getCPUFrequency() const;
+ F64MegahertzImplicit getCPUFrequency() const;
bool hasSSE() const;
bool hasSSE2() const;
bool hasAltivec() const;
diff --git a/indra/llcommon/llptrskiplist.h b/indra/llcommon/llptrskiplist.h
deleted file mode 100755
index 67c7cde352..0000000000
--- a/indra/llcommon/llptrskiplist.h
+++ /dev/null
@@ -1,724 +0,0 @@
-/**
- * @file llptrskiplist.h
- * @brief Skip list implementation.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLPTRSKIPLIST_H
-#define LL_LLPTRSKIPLIST_H
-
-#include "llerror.h"
-#include "llrand.h"
-//#include "vmath.h"
-#include "llrand.h"
-
-/////////////////////////////////////////////
-//
-// LLPtrSkipList implementation - skip list for pointers to objects
-//
-
-template <class DATA_TYPE, S32 BINARY_DEPTH = 8>
-class LLPtrSkipList
-{
-public:
- friend class LLPtrSkipNode;
-
- // basic constructor
- LLPtrSkipList();
- // basic constructor including sorter
- LLPtrSkipList(BOOL (*insert_first)(DATA_TYPE *first, DATA_TYPE *second),
- BOOL (*equals)(DATA_TYPE *first, DATA_TYPE *second));
- ~LLPtrSkipList();
-
- inline void setInsertFirst(BOOL (*insert_first)(const DATA_TYPE *first, const DATA_TYPE *second));
- inline void setEquals(BOOL (*equals)(const DATA_TYPE *first, const DATA_TYPE *second));
-
- inline BOOL addData(DATA_TYPE *data);
-
- inline BOOL checkData(const DATA_TYPE *data);
-
- inline S32 getLength(); // returns number of items in the list - NOT constant time!
-
- inline BOOL removeData(const DATA_TYPE *data);
-
- // note that b_sort is ignored
- inline BOOL moveData(const DATA_TYPE *data, LLPtrSkipList *newlist, BOOL b_sort);
-
- inline BOOL moveCurrentData(LLPtrSkipList *newlist, BOOL b_sort);
-
- // resort -- use when the value we're sorting by changes
- /* IW 12/6/02 - This doesn't work!
- Instead, remove the data BEFORE you change it
- Then re-insert it after you change it
- BOOL resortData(DATA_TYPE *data)
- */
-
- // remove all nodes from the list but do not delete data
- inline void removeAllNodes();
-
- inline BOOL deleteData(const DATA_TYPE *data);
-
- // remove all nodes from the list and delete data
- inline void deleteAllData();
-
- // place mCurrentp on first node
- inline void resetList();
-
- // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
- inline DATA_TYPE *getCurrentData();
-
- // same as getCurrentData() but a more intuitive name for the operation
- inline DATA_TYPE *getNextData();
-
- // remove the Node at mCurentOperatingp
- // leave mCurrentp and mCurentOperatingp on the next entry
- inline void removeCurrentData();
-
- // delete the Node at mCurentOperatingp
- // leave mCurrentp and mCurentOperatingp on the next entry
- inline void deleteCurrentData();
-
- // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
- inline DATA_TYPE *getFirstData();
-
- // TRUE if nodes are not in sorted order
- inline BOOL corrupt();
-
-protected:
- class LLPtrSkipNode
- {
- public:
- LLPtrSkipNode()
- : mData(NULL)
- {
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mForward[i] = NULL;
- }
- }
-
- LLPtrSkipNode(DATA_TYPE *data)
- : mData(data)
- {
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mForward[i] = NULL;
- }
- }
-
- ~LLPtrSkipNode()
- {
- if (mData)
- {
- llerror("Attempting to call LLPtrSkipNode destructor with a non-null mDatap!", 1);
- }
- }
-
- // delete associated data and NULLs out pointer
- void deleteData()
- {
- delete mData;
- mData = NULL;
- }
-
- // NULLs out pointer
- void removeData()
- {
- mData = NULL;
- }
-
- DATA_TYPE *mData;
- LLPtrSkipNode *mForward[BINARY_DEPTH];
- };
-
- static BOOL defaultEquals(const DATA_TYPE *first, const DATA_TYPE *second)
- {
- return first == second;
- }
-
-
- LLPtrSkipNode mHead;
- LLPtrSkipNode *mUpdate[BINARY_DEPTH];
- LLPtrSkipNode *mCurrentp;
- LLPtrSkipNode *mCurrentOperatingp;
- S32 mLevel;
- BOOL (*mInsertFirst)(const DATA_TYPE *first, const DATA_TYPE *second);
- BOOL (*mEquals)(const DATA_TYPE *first, const DATA_TYPE *second);
-};
-
-
-// basic constructor
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::LLPtrSkipList()
- : mInsertFirst(NULL), mEquals(defaultEquals)
-{
- if (BINARY_DEPTH < 2)
- {
- llerrs << "Trying to create skip list with too little depth, "
- "must be 2 or greater" << llendl;
- }
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mUpdate[i] = NULL;
- }
- mLevel = 1;
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-// basic constructor including sorter
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::LLPtrSkipList(BOOL (*insert_first)(DATA_TYPE *first, DATA_TYPE *second),
- BOOL (*equals)(DATA_TYPE *first, DATA_TYPE *second))
- :mInsertFirst(insert_first), mEquals(equals)
-{
- if (BINARY_DEPTH < 2)
- {
- llerrs << "Trying to create skip list with too little depth, "
- "must be 2 or greater" << llendl;
- }
- mLevel = 1;
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mHead.mForward[i] = NULL;
- mUpdate[i] = NULL;
- }
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::~LLPtrSkipList()
-{
- removeAllNodes();
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::setInsertFirst(BOOL (*insert_first)(const DATA_TYPE *first, const DATA_TYPE *second))
-{
- mInsertFirst = insert_first;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::setEquals(BOOL (*equals)(const DATA_TYPE *first, const DATA_TYPE *second))
-{
- mEquals = equals;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::addData(DATA_TYPE *data)
-{
- S32 level;
- LLPtrSkipNode *current = &mHead;
- LLPtrSkipNode *temp;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mData, data)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mData < data))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
-
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- // now add the new node
- S32 newlevel;
- for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
- {
- if (ll_frand() < 0.5f)
- break;
- }
-
- LLPtrSkipNode *snode = new LLPtrSkipNode(data);
-
- if (newlevel > mLevel)
- {
- mHead.mForward[mLevel] = NULL;
- mUpdate[mLevel] = &mHead;
- mLevel = newlevel;
- }
-
- for (level = 0; level < newlevel; level++)
- {
- snode->mForward[level] = mUpdate[level]->mForward[level];
- mUpdate[level]->mForward[level] = snode;
- }
- return TRUE;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::checkData(const DATA_TYPE *data)
-{
- S32 level;
- LLPtrSkipNode *current = &mHead;
- LLPtrSkipNode *temp;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mData, data)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mData < data))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
-
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- if (current)
- {
- return mEquals(current->mData, data);
- }
- else
- {
- return FALSE;
- }
-}
-
-// returns number of items in the list
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline S32 LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getLength()
-{
- U32 length = 0;
- for (LLPtrSkipNode* temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0])
- {
- length++;
- }
- return length;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::removeData(const DATA_TYPE *data)
-{
- S32 level;
- LLPtrSkipNode *current = &mHead;
- LLPtrSkipNode *temp;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mData, data)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mData < data))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
-
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- if (!current)
- {
- // empty list or beyond the end!
- return FALSE;
- }
-
- // is this the one we want?
- if (!mEquals(current->mData, data))
- {
- // nope!
- return FALSE;
- }
- else
- {
- // yes it is! change pointers as required
- for (level = 0; level < mLevel; level++)
- {
- if (mUpdate[level]->mForward[level] != current)
- {
- // cool, we've fixed all the pointers!
- break;
- }
- mUpdate[level]->mForward[level] = current->mForward[level];
- }
-
- // clean up cuurent
- current->removeData();
- delete current;
-
- // clean up mHead
- while ( (mLevel > 1)
- &&(!mHead.mForward[mLevel - 1]))
- {
- mLevel--;
- }
- }
- return TRUE;
-}
-
-// note that b_sort is ignored
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::moveData(const DATA_TYPE *data, LLPtrSkipList *newlist, BOOL b_sort)
-{
- BOOL removed = removeData(data);
- BOOL added = newlist->addData(data);
- return removed && added;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::moveCurrentData(LLPtrSkipList *newlist, BOOL b_sort)
-{
- if (mCurrentOperatingp)
- {
- mCurrentp = mCurrentOperatingp->mForward[0];
- BOOL removed = removeData(mCurrentOperatingp);
- BOOL added = newlist->addData(mCurrentOperatingp);
- mCurrentOperatingp = mCurrentp;
- return removed && added;
- }
- return FALSE;
-}
-
-// resort -- use when the value we're sorting by changes
-/* IW 12/6/02 - This doesn't work!
- Instead, remove the data BEFORE you change it
- Then re-insert it after you change it
-BOOL resortData(DATA_TYPE *data)
-{
- removeData(data);
- addData(data);
-}
-*/
-
-// remove all nodes from the list but do not delete data
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::removeAllNodes()
-{
- LLPtrSkipNode *temp;
- // reset mCurrentp
- mCurrentp = *(mHead.mForward);
-
- while (mCurrentp)
- {
- temp = mCurrentp->mForward[0];
- mCurrentp->removeData();
- delete mCurrentp;
- mCurrentp = temp;
- }
-
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mHead.mForward[i] = NULL;
- mUpdate[i] = NULL;
- }
-
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::deleteData(const DATA_TYPE *data)
-{
- S32 level;
- LLPtrSkipNode *current = &mHead;
- LLPtrSkipNode *temp;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mData, data)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mData < data))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
-
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- if (!current)
- {
- // empty list or beyond the end!
- return FALSE;
- }
-
- // is this the one we want?
- if (!mEquals(current->mData, data))
- {
- // nope!
- return FALSE;
- }
- else
- {
- // do we need to fix current or currentop?
- if (current == mCurrentp)
- {
- mCurrentp = current->mForward[0];
- }
-
- if (current == mCurrentOperatingp)
- {
- mCurrentOperatingp = current->mForward[0];
- }
-
- // yes it is! change pointers as required
- for (level = 0; level < mLevel; level++)
- {
- if (mUpdate[level]->mForward[level] != current)
- {
- // cool, we've fixed all the pointers!
- break;
- }
- mUpdate[level]->mForward[level] = current->mForward[level];
- }
-
- // clean up cuurent
- current->deleteData();
- delete current;
-
- // clean up mHead
- while ( (mLevel > 1)
- &&(!mHead.mForward[mLevel - 1]))
- {
- mLevel--;
- }
- }
- return TRUE;
-}
-
-// remove all nodes from the list and delete data
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::deleteAllData()
-{
- LLPtrSkipNode *temp;
- // reset mCurrentp
- mCurrentp = *(mHead.mForward);
-
- while (mCurrentp)
- {
- temp = mCurrentp->mForward[0];
- mCurrentp->deleteData();
- delete mCurrentp;
- mCurrentp = temp;
- }
-
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mHead.mForward[i] = NULL;
- mUpdate[i] = NULL;
- }
-
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-// place mCurrentp on first node
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::resetList()
-{
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE *LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getCurrentData()
-{
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = *mCurrentp->mForward;
- return mCurrentOperatingp->mData;
- }
- else
- {
- //return NULL; // causes compile warning
- return 0; // equivalent, but no warning
- }
-}
-
-// same as getCurrentData() but a more intuitive name for the operation
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE *LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getNextData()
-{
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = *mCurrentp->mForward;
- return mCurrentOperatingp->mData;
- }
- else
- {
- //return NULL; // causes compile warning
- return 0; // equivalent, but no warning
- }
-}
-
-// remove the Node at mCurentOperatingp
-// leave mCurrentp and mCurentOperatingp on the next entry
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::removeCurrentData()
-{
- if (mCurrentOperatingp)
- {
- removeData(mCurrentOperatingp->mData);
- }
-}
-
-// delete the Node at mCurentOperatingp
-// leave mCurrentp and mCurentOperatingp on the next entry
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::deleteCurrentData()
-{
- if (mCurrentOperatingp)
- {
- deleteData(mCurrentOperatingp->mData);
- }
-}
-
-// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE *LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getFirstData()
-{
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mForward[0];
- return mCurrentOperatingp->mData;
- }
- else
- {
- //return NULL; // causes compile warning
- return 0; // equivalent, but no warning
- }
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::corrupt()
-{
- LLPtrSkipNode *previous = mHead.mForward[0];
-
- // Empty lists are not corrupt.
- if (!previous) return FALSE;
-
- LLPtrSkipNode *current = previous->mForward[0];
- while(current)
- {
- if (!mInsertFirst(previous->mData, current->mData))
- {
- // prev shouldn't be in front of cur!
- return TRUE;
- }
- current = current->mForward[0];
- }
- return FALSE;
-}
-
-#endif
diff --git a/indra/llcommon/llptrskipmap.h b/indra/llcommon/llptrskipmap.h
deleted file mode 100755
index 94bc71ec55..0000000000
--- a/indra/llcommon/llptrskipmap.h
+++ /dev/null
@@ -1,1239 +0,0 @@
-/**
- * @file llptrskipmap.h
- * @brief Just like a LLSkipMap, but since it's pointers, you can call
- * deleteAllData
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-#ifndef LL_LLPTRSKIPMAP_H
-#define LL_LLPTRSKIPMAP_H
-
-#include "llerror.h"
-#include "llrand.h"
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH = 8>
-class LLPtrSkipMapNode
-{
-public:
- LLPtrSkipMapNode()
- {
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mForward[i] = NULL;
- }
-
- U8 *zero = (U8 *)&mIndex;
-
- for (i = 0; i < (S32)sizeof(INDEX_T); i++)
- {
- *(zero + i) = 0;
- }
-
- zero = (U8 *)&mData;
-
- for (i = 0; i < (S32)sizeof(DATA_T); i++)
- {
- *(zero + i) = 0;
- }
- }
-
- LLPtrSkipMapNode(const INDEX_T &index)
- : mIndex(index)
- {
-
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mForward[i] = NULL;
- }
-
- U8 *zero = (U8 *)&mData;
-
- for (i = 0; i < (S32)sizeof(DATA_T); i++)
- {
- *(zero + i) = 0;
- }
- }
-
- LLPtrSkipMapNode(const INDEX_T &index, DATA_T datap)
- : mIndex(index)
- {
-
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mForward[i] = NULL;
- }
-
- mData = datap;
- }
-
- ~LLPtrSkipMapNode()
- {
- }
-
- // delete associated data and NULLs out pointer
- void deleteData()
- {
- delete mData;
- mData = 0;
- }
-
- // NULLs out pointer
- void removeData()
- {
- mData = 0;
- }
-
- INDEX_T mIndex;
- DATA_T mData;
- LLPtrSkipMapNode *mForward[BINARY_DEPTH];
-
-private:
- // Disallow copying of LLPtrSkipMapNodes by not implementing these methods.
- LLPtrSkipMapNode(const LLPtrSkipMapNode &);
- LLPtrSkipMapNode &operator=(const LLPtrSkipMapNode &rhs);
-};
-
-//---------------------------------------------------------------------------
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH = 8>
-class LLPtrSkipMap
-{
-public:
- typedef BOOL (*compare)(const DATA_T& first, const DATA_T& second);
- typedef compare insert_func;
- typedef compare equals_func;
-
- void init();
-
- // basic constructor
- LLPtrSkipMap();
-
- // basic constructor including sorter
- LLPtrSkipMap(insert_func insert_first, equals_func equals);
-
- ~LLPtrSkipMap();
-
- void setInsertFirst(insert_func insert_first);
- void setEquals(equals_func equals);
-
- DATA_T &addData(const INDEX_T &index, DATA_T datap);
- DATA_T &addData(const INDEX_T &index);
- DATA_T &getData(const INDEX_T &index);
- DATA_T &operator[](const INDEX_T &index);
-
- // If index present, returns data.
- // If index not present, adds <index,NULL> and returns NULL.
- DATA_T &getData(const INDEX_T &index, BOOL &b_new_entry);
-
- // returns data entry before and after index
- BOOL getInterval(const INDEX_T &index, INDEX_T &index_before, INDEX_T &index_after,
- DATA_T &data_before, DATA_T &data_after );
-
- // Returns TRUE if data present in map.
- BOOL checkData(const INDEX_T &index);
-
- // Returns TRUE if key is present in map. This is useful if you
- // are potentially storing NULL pointers in the map
- BOOL checkKey(const INDEX_T &index);
-
- // If there, returns the data.
- // If not, returns NULL.
- // Never adds entries to the map.
- DATA_T getIfThere(const INDEX_T &index);
-
- INDEX_T reverseLookup(const DATA_T datap);
-
- // returns number of items in the list
- S32 getLength(); // WARNING! getLength is O(n), not O(1)!
-
- BOOL removeData(const INDEX_T &index);
- BOOL deleteData(const INDEX_T &index);
-
- // remove all nodes from the list but do not delete data
- void removeAllData();
- void deleteAllData();
-
- // place mCurrentp on first node
- void resetList();
-
- // return the data currently pointed to
- DATA_T getCurrentDataWithoutIncrement();
-
- // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
- DATA_T getCurrentData();
-
- // same as getCurrentData() but a more intuitive name for the operation
- DATA_T getNextData();
-
- INDEX_T getNextKey();
-
- // return the key currently pointed to
- INDEX_T getCurrentKeyWithoutIncrement();
-
- // remove the Node at mCurentOperatingp
- // leave mCurrentp and mCurentOperatingp on the next entry
- void removeCurrentData();
-
- void deleteCurrentData();
-
- // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
- DATA_T getFirstData();
-
- INDEX_T getFirstKey();
-
- static BOOL defaultEquals(const INDEX_T &first, const INDEX_T &second)
- {
- return first == second;
- }
-
-private:
- // don't generate implicit copy constructor or copy assignment
- LLPtrSkipMap(const LLPtrSkipMap &);
- LLPtrSkipMap &operator=(const LLPtrSkipMap &);
-
-private:
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> mHead;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *mUpdate[BINARY_DEPTH];
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *mCurrentp;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *mCurrentOperatingp;
- S32 mLevel;
- BOOL (*mInsertFirst)(const INDEX_T &first, const INDEX_T &second);
- BOOL (*mEquals)(const INDEX_T &first, const INDEX_T &second);
- S32 mNumberOfSteps;
-};
-
-//////////////////////////////////////////////////
-//
-// LLPtrSkipMap implementation
-//
-//
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::LLPtrSkipMap()
- : mInsertFirst(NULL),
- mEquals(defaultEquals),
- mNumberOfSteps(0)
-{
- if (BINARY_DEPTH < 2)
- {
- llerrs << "Trying to create skip list with too little depth, "
- "must be 2 or greater" << llendl;
- }
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mUpdate[i] = NULL;
- }
- mLevel = 1;
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::LLPtrSkipMap(insert_func insert_first,
- equals_func equals)
-: mInsertFirst(insert_first),
- mEquals(equals),
- mNumberOfSteps(0)
-{
- if (BINARY_DEPTH < 2)
- {
- llerrs << "Trying to create skip list with too little depth, "
- "must be 2 or greater" << llendl;
- }
- mLevel = 1;
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mHead.mForward[i] = NULL;
- mUpdate[i] = NULL;
- }
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::~LLPtrSkipMap()
-{
- removeAllData();
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::setInsertFirst(insert_func insert_first)
-{
- mInsertFirst = insert_first;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::setEquals(equals_func equals)
-{
- mEquals = equals;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::addData(const INDEX_T &index, DATA_T datap)
-{
- S32 level;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- // replace the existing data if a node is already there
- if ( (current)
- &&(mEquals(current->mIndex, index)))
- {
- current->mData = datap;
- return current->mData;
- }
-
- // now add the new node
- S32 newlevel;
- for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
- {
- if (ll_frand() < 0.5f)
- {
- break;
- }
- }
-
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *snode
- = new LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>(index, datap);
-
- if (newlevel > mLevel)
- {
- mHead.mForward[mLevel] = NULL;
- mUpdate[mLevel] = &mHead;
- mLevel = newlevel;
- }
-
- for (level = 0; level < newlevel; level++)
- {
- snode->mForward[level] = mUpdate[level]->mForward[level];
- mUpdate[level]->mForward[level] = snode;
- }
- return snode->mData;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::addData(const INDEX_T &index)
-{
- S32 level;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- // now add the new node
- S32 newlevel;
- for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
- {
- if (ll_frand() < 0.5f)
- break;
- }
-
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *snode
- = new LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>(index);
-
- if (newlevel > mLevel)
- {
- mHead.mForward[mLevel] = NULL;
- mUpdate[mLevel] = &mHead;
- mLevel = newlevel;
- }
-
- for (level = 0; level < newlevel; level++)
- {
- snode->mForward[level] = mUpdate[level]->mForward[level];
- mUpdate[level]->mForward[level] = snode;
- }
- return snode->mData;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getData(const INDEX_T &index)
-{
- S32 level;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
-
- mNumberOfSteps = 0;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- mNumberOfSteps++;
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- mNumberOfSteps++;
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
- mNumberOfSteps++;
-
- if ( (current)
- &&(mEquals(current->mIndex, index)))
- {
-
- return current->mData;
- }
-
- // now add the new node
- S32 newlevel;
- for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
- {
- if (ll_frand() < 0.5f)
- break;
- }
-
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *snode
- = new LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>(index);
-
- if (newlevel > mLevel)
- {
- mHead.mForward[mLevel] = NULL;
- mUpdate[mLevel] = &mHead;
- mLevel = newlevel;
- }
-
- for (level = 0; level < newlevel; level++)
- {
- snode->mForward[level] = mUpdate[level]->mForward[level];
- mUpdate[level]->mForward[level] = snode;
- }
-
- return snode->mData;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getInterval(const INDEX_T &index,
- INDEX_T &index_before,
- INDEX_T &index_after,
- DATA_T &data_before,
- DATA_T &data_after)
-{
- S32 level;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
-
- mNumberOfSteps = 0;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- mNumberOfSteps++;
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- mNumberOfSteps++;
- }
- *(mUpdate + level) = current;
- }
- }
-
- BOOL both_found = TRUE;
-
- if (current != &mHead)
- {
- index_before = current->mIndex;
- data_before = current->mData;
- }
- else
- {
- data_before = 0;
- index_before = 0;
- both_found = FALSE;
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- mNumberOfSteps++;
- current = *current->mForward;
-
- if (current)
- {
- data_after = current->mData;
- index_after = current->mIndex;
- }
- else
- {
- data_after = 0;
- index_after = 0;
- both_found = FALSE;
- }
-
- return both_found;
-}
-
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::operator[](const INDEX_T &index)
-{
-
- return getData(index);
-}
-
-// If index present, returns data.
-// If index not present, adds <index,NULL> and returns NULL.
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getData(const INDEX_T &index, BOOL &b_new_entry)
-{
- S32 level;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
-
- mNumberOfSteps = 0;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- mNumberOfSteps++;
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- mNumberOfSteps++;
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- mNumberOfSteps++;
- current = *current->mForward;
-
- if ( (current)
- &&(mEquals(current->mIndex, index)))
- {
-
- return current->mData;
- }
- b_new_entry = TRUE;
- addData(index);
-
- return current->mData;
-}
-
-// Returns TRUE if data present in map.
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::checkData(const INDEX_T &index)
-{
- S32 level;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- if (current)
- {
- // Gets rid of some compiler ambiguity for the LLPointer<> templated class.
- if (current->mData)
- {
- return mEquals(current->mIndex, index);
- }
- }
-
- return FALSE;
-}
-
-// Returns TRUE if key is present in map. This is useful if you
-// are potentially storing NULL pointers in the map
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::checkKey(const INDEX_T &index)
-{
- S32 level;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- if (current)
- {
- return mEquals(current->mIndex, index);
- }
-
- return FALSE;
-}
-
-// If there, returns the data.
-// If not, returns NULL.
-// Never adds entries to the map.
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getIfThere(const INDEX_T &index)
-{
- S32 level;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
-
- mNumberOfSteps = 0;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- mNumberOfSteps++;
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- mNumberOfSteps++;
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- mNumberOfSteps++;
- current = *current->mForward;
-
- if (current)
- {
- if (mEquals(current->mIndex, index))
- {
- return current->mData;
- }
- }
-
- // Avoid Linux compiler warning on returning NULL.
- return (DATA_T)0;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::reverseLookup(const DATA_T datap)
-{
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
-
- while (current)
- {
- if (datap == current->mData)
- {
-
- return current->mIndex;
- }
- current = *current->mForward;
- }
-
- // not found! return NULL
- return INDEX_T();
-}
-
-// returns number of items in the list
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline S32 LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getLength()
-{
- U32 length = 0;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>* temp;
- for (temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0])
- {
- length++;
- }
-
- return length;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::removeData(const INDEX_T &index)
-{
- S32 level;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- if (!current)
- {
- // empty list or beyond the end!
-
- return FALSE;
- }
-
- // is this the one we want?
- if (!mEquals(current->mIndex, index))
- {
- // nope!
-
- return FALSE;
- }
- else
- {
- // do we need to fix current or currentop?
- if (current == mCurrentp)
- {
- mCurrentp = *current->mForward;
- }
-
- if (current == mCurrentOperatingp)
- {
- mCurrentOperatingp = *current->mForward;
- }
- // yes it is! change pointers as required
- for (level = 0; level < mLevel; level++)
- {
- if (*((*(mUpdate + level))->mForward + level) != current)
- {
- // cool, we've fixed all the pointers!
- break;
- }
- *((*(mUpdate + level))->mForward + level) = *(current->mForward + level);
- }
-
- // clean up cuurent
- current->removeData();
- delete current;
-
- // clean up mHead
- while ( (mLevel > 1)
- &&(!*(mHead.mForward + mLevel - 1)))
- {
- mLevel--;
- }
- }
-
- return TRUE;
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::deleteData(const INDEX_T &index)
-{
- S32 level;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead;
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- if (!current)
- {
- // empty list or beyond the end!
-
- return FALSE;
- }
-
- // is this the one we want?
- if (!mEquals(current->mIndex, index))
- {
- // nope!
-
- return FALSE;
- }
- else
- {
- // do we need to fix current or currentop?
- if (current == mCurrentp)
- {
- mCurrentp = *current->mForward;
- }
-
- if (current == mCurrentOperatingp)
- {
- mCurrentOperatingp = *current->mForward;
- }
- // yes it is! change pointers as required
- for (level = 0; level < mLevel; level++)
- {
- if (*((*(mUpdate + level))->mForward + level) != current)
- {
- // cool, we've fixed all the pointers!
- break;
- }
- *((*(mUpdate + level))->mForward + level) = *(current->mForward + level);
- }
-
- // clean up cuurent
- current->deleteData();
- delete current;
-
- // clean up mHead
- while ( (mLevel > 1)
- &&(!*(mHead.mForward + mLevel - 1)))
- {
- mLevel--;
- }
- }
-
- return TRUE;
-}
-
-// remove all nodes from the list but do not delete data
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::removeAllData()
-{
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
- // reset mCurrentp
- mCurrentp = *(mHead.mForward);
-
- while (mCurrentp)
- {
- temp = mCurrentp->mForward[0];
- mCurrentp->removeData();
- delete mCurrentp;
- mCurrentp = temp;
- }
-
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mHead.mForward[i] = NULL;
- mUpdate[i] = NULL;
- }
-
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::deleteAllData()
-{
- LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp;
- // reset mCurrentp
- mCurrentp = *(mHead.mForward);
-
- while (mCurrentp)
- {
- temp = mCurrentp->mForward[0];
- mCurrentp->deleteData();
- delete mCurrentp;
- mCurrentp = temp;
- }
-
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mHead.mForward[i] = NULL;
- mUpdate[i] = NULL;
- }
-
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-// place mCurrentp on first node
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::resetList()
-{
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-
-// return the data currently pointed to
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getCurrentDataWithoutIncrement()
-{
- if (mCurrentOperatingp)
- {
- return mCurrentOperatingp->mData;
- }
- else
- {
- //return NULL; // causes warning
- return (DATA_T)0; // equivalent, but no warning
- }
-}
-
-// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getCurrentData()
-{
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mForward[0];
- return mCurrentOperatingp->mData;
- }
- else
- {
- //return NULL; // causes warning
- return (DATA_T)0; // equivalent, but no warning
- }
-}
-
-// same as getCurrentData() but a more intuitive name for the operation
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getNextData()
-{
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mForward[0];
- return mCurrentOperatingp->mData;
- }
- else
- {
- //return NULL; // causes compile warning
- return (DATA_T)0; // equivalent, but removes warning
- }
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getNextKey()
-{
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mForward[0];
- return mCurrentOperatingp->mIndex;
- }
- else
- {
- return mHead.mIndex;
- }
-}
-
-// return the key currently pointed to
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getCurrentKeyWithoutIncrement()
-{
- if (mCurrentOperatingp)
- {
- return mCurrentOperatingp->mIndex;
- }
- else
- {
- //return NULL; // causes compile warning
- return (INDEX_T)0; // equivalent, but removes warning
- }
-}
-
-
-// remove the Node at mCurentOperatingp
-// leave mCurrentp and mCurentOperatingp on the next entry
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::removeCurrentData()
-{
- if (mCurrentOperatingp)
- {
- removeData(mCurrentOperatingp->mIndex);
- }
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::deleteCurrentData()
-{
- if (mCurrentOperatingp)
- {
- deleteData(mCurrentOperatingp->mIndex);
- }
-}
-
-// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getFirstData()
-{
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mForward[0];
- return mCurrentOperatingp->mData;
- }
- else
- {
- //return NULL; // causes compile warning
- return (DATA_T)0; // equivalent, but removes warning
- }
-}
-
-template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH>
-inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getFirstKey()
-{
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mForward[0];
- return mCurrentOperatingp->mIndex;
- }
- else
- {
- return mHead.mIndex;
- }
-}
-
-#endif
diff --git a/indra/llcommon/llptrto.h b/indra/llcommon/llptrto.h
index 7091d36f6b..4082e30de6 100755
--- a/indra/llcommon/llptrto.h
+++ b/indra/llcommon/llptrto.h
@@ -33,7 +33,6 @@
#include "llpointer.h"
#include "llrefcount.h" // LLRefCount
-#include "llthread.h" // LLThreadSafeRefCount
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/utility/enable_if.hpp>
diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp
index abf47a0f57..8cef4293cd 100755
--- a/indra/llcommon/llqueuedthread.cpp
+++ b/indra/llcommon/llqueuedthread.cpp
@@ -28,6 +28,7 @@
#include "llstl.h"
#include "lltimer.h" // ms_sleep()
+#include "lltracethreadrecorder.h"
//============================================================================
@@ -80,7 +81,7 @@ void LLQueuedThread::shutdown()
}
if (timeout == 0)
{
- llwarns << "~LLQueuedThread (" << mName << ") timed out!" << llendl;
+ LL_WARNS() << "~LLQueuedThread (" << mName << ") timed out!" << LL_ENDL;
}
}
else
@@ -101,7 +102,7 @@ void LLQueuedThread::shutdown()
}
if (active_count)
{
- llwarns << "~LLQueuedThread() called with active requests: " << active_count << llendl;
+ LL_WARNS() << "~LLQueuedThread() called with active requests: " << active_count << LL_ENDL;
}
}
@@ -134,8 +135,8 @@ S32 LLQueuedThread::updateQueue(F32 max_time_ms)
pending = getPending();
if(pending > 0)
{
- unpause();
- }
+ unpause();
+ }
}
else
{
@@ -198,11 +199,11 @@ void LLQueuedThread::printQueueStats()
if (!mRequestQueue.empty())
{
QueuedRequest *req = *mRequestQueue.begin();
- llinfos << llformat("Pending Requests:%d Current status:%d", mRequestQueue.size(), req->getStatus()) << llendl;
+ LL_INFOS() << llformat("Pending Requests:%d Current status:%d", mRequestQueue.size(), req->getStatus()) << LL_ENDL;
}
else
{
- llinfos << "Queued Thread Idle" << llendl;
+ LL_INFOS() << "Queued Thread Idle" << LL_ENDL;
}
unlockData();
}
@@ -233,7 +234,7 @@ bool LLQueuedThread::addRequest(QueuedRequest* req)
mRequestQueue.insert(req);
mRequestHash.insert(req);
#if _DEBUG
-// llinfos << llformat("LLQueuedThread::Added req [%08d]",handle) << llendl;
+// LL_INFOS() << llformat("LLQueuedThread::Added req [%08d]",handle) << LL_ENDL;
#endif
unlockData();
@@ -245,7 +246,7 @@ bool LLQueuedThread::addRequest(QueuedRequest* req)
// MAIN thread
bool LLQueuedThread::waitForResult(LLQueuedThread::handle_t handle, bool auto_complete)
{
- llassert (handle != nullHandle())
+ llassert (handle != nullHandle());
bool res = false;
bool waspaused = isPaused();
bool done = false;
@@ -364,7 +365,7 @@ bool LLQueuedThread::completeRequest(handle_t handle)
llassert_always(req->getStatus() != STATUS_QUEUED);
llassert_always(req->getStatus() != STATUS_INPROGRESS);
#if _DEBUG
-// llinfos << llformat("LLQueuedThread::Completed req [%08d]",handle) << llendl;
+// LL_INFOS() << llformat("LLQueuedThread::Completed req [%08d]",handle) << LL_ENDL;
#endif
mRequestHash.erase(handle);
req->deleteRequest();
@@ -385,7 +386,7 @@ bool LLQueuedThread::check()
{
if (entry->getHashKey() > mNextHandle)
{
- llerrs << "Hash Error" << llendl;
+ LL_ERRS() << "Hash Error" << LL_ENDL;
return false;
}
entry = entry->getNextEntry();
@@ -403,6 +404,7 @@ S32 LLQueuedThread::processNextRequest()
QueuedRequest *req;
// Get next request from pool
lockData();
+
while(1)
{
req = NULL;
@@ -467,10 +469,11 @@ S32 LLQueuedThread::processNextRequest()
ms_sleep(1); // sleep the thread a little
}
}
+
+ LLTrace::get_thread_recorder()->pushToParent();
}
S32 pending = getPending();
-
return pending;
}
@@ -499,6 +502,7 @@ void LLQueuedThread::run()
if (isQuitting())
{
+ LLTrace::get_thread_recorder()->pushToParent();
endThread();
break;
}
@@ -507,15 +511,16 @@ void LLQueuedThread::run()
threadedUpdate();
- int res = processNextRequest();
- if (res == 0)
+ int pending_work = processNextRequest();
+
+ if (pending_work == 0)
{
mIdleThread = TRUE;
ms_sleep(1);
}
//LLThread::yield(); // thread should yield after each request
}
- llinfos << "LLQueuedThread " << mName << " EXITING." << llendl;
+ LL_INFOS() << "LLQueuedThread " << mName << " EXITING." << LL_ENDL;
}
// virtual
diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp
index e1876599fc..a638df2c7c 100755
--- a/indra/llcommon/llrefcount.cpp
+++ b/indra/llcommon/llrefcount.cpp
@@ -76,7 +76,7 @@ LLRefCount::~LLRefCount()
{
if (mRef != 0)
{
- llerrs << "deleting non-zero reference" << llendl;
+ LL_ERRS() << "deleting non-zero reference" << LL_ENDL;
}
#if LL_REF_COUNT_DEBUG
@@ -95,8 +95,8 @@ void LLRefCount::ref() const
if(mMutexp->isLocked())
{
mCrashAtUnlock = TRUE ;
- llerrs << "the mutex is locked by the thread: " << mLockedThreadID
- << " Current thread: " << LLThread::currentID() << llendl ;
+ LL_ERRS() << "the mutex is locked by the thread: " << mLockedThreadID
+ << " Current thread: " << LLThread::currentID() << LL_ENDL ;
}
mMutexp->lock() ;
@@ -123,8 +123,8 @@ S32 LLRefCount::unref() const
if(mMutexp->isLocked())
{
mCrashAtUnlock = TRUE ;
- llerrs << "the mutex is locked by the thread: " << mLockedThreadID
- << " Current thread: " << LLThread::currentID() << llendl ;
+ LL_ERRS() << "the mutex is locked by the thread: " << mLockedThreadID
+ << " Current thread: " << LLThread::currentID() << LL_ENDL ;
}
mMutexp->lock() ;
diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h
index 32ae15435a..72011d04a0 100755
--- a/indra/llcommon/llrefcount.h
+++ b/indra/llcommon/llrefcount.h
@@ -28,6 +28,8 @@
#include <boost/noncopyable.hpp>
#include <boost/intrusive_ptr.hpp>
+#include "llmutex.h"
+#include "llapr.h"
#define LL_REF_COUNT_DEBUG 0
#if LL_REF_COUNT_DEBUG
@@ -61,7 +63,7 @@ public:
inline S32 unref() const
{
llassert(mRef >= 1);
- if (0 == --mRef)
+ if (0 == --mRef)
{
delete this;
return 0;
@@ -87,22 +89,91 @@ private:
#endif
};
+
+//============================================================================
+
+// see llmemory.h for LLPointer<> definition
+
+class LL_COMMON_API LLThreadSafeRefCount
+{
+public:
+ static void initThreadSafeRefCount(); // creates sMutex
+ static void cleanupThreadSafeRefCount(); // destroys sMutex
+
+private:
+ static LLMutex* sMutex;
+
+protected:
+ virtual ~LLThreadSafeRefCount(); // use unref()
+
+public:
+ LLThreadSafeRefCount();
+ LLThreadSafeRefCount(const LLThreadSafeRefCount&);
+ LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref)
+ {
+ mRef = 0;
+ return *this;
+ }
+
+ void ref()
+ {
+ mRef++;
+ }
+
+ void unref()
+ {
+ llassert(mRef >= 1);
+ if ((--mRef) == 0) // See note in llapr.h on atomic decrement operator return value.
+ {
+ // If we hit zero, the caller should be the only smart pointer owning the object and we can delete it.
+ // It is technically possible for a vanilla pointer to mess this up, or another thread to
+ // jump in, find this object, create another smart pointer and end up dangling, but if
+ // the code is that bad and not thread-safe, it's trouble already.
+ delete this;
+ }
+ }
+
+ S32 getNumRefs() const
+ {
+ const S32 currentVal = mRef.CurrentValue();
+ return currentVal;
+ }
+
+private:
+ LLAtomic32< S32 > mRef;
+};
+
/**
* intrusive pointer support
* this allows you to use boost::intrusive_ptr with any LLRefCount-derived type
*/
+/**
+ * intrusive pointer support for LLThreadSafeRefCount
+ * this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type
+ */
namespace boost
{
- inline void intrusive_ptr_add_ref(LLRefCount* p)
+ inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p)
{
p->ref();
}
- inline void intrusive_ptr_release(LLRefCount* p)
+ inline void intrusive_ptr_release(LLThreadSafeRefCount* p)
{
- p->unref();
+ p->unref();
+ }
+
+ inline void intrusive_ptr_add_ref(LLRefCount* p)
+ {
+ p->ref();
+ }
+
+ inline void intrusive_ptr_release(LLRefCount* p)
+ {
+ p->unref();
}
};
+
#endif
diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h
index bb0d60247e..29950c108d 100755
--- a/indra/llcommon/llregistry.h
+++ b/indra/llcommon/llregistry.h
@@ -29,7 +29,6 @@
#include <list>
-#include <boost/type_traits.hpp>
#include "llsingleton.h"
#include "llstl.h"
@@ -47,12 +46,11 @@ template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultC
class LLRegistry
{
public:
- typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
- typedef typename boost::add_reference<typename boost::add_const<KEY>::type>::type ref_const_key_t;
- typedef typename boost::add_reference<typename boost::add_const<VALUE>::type>::type ref_const_value_t;
- typedef typename boost::add_reference<VALUE>::type ref_value_t;
- typedef typename boost::add_pointer<typename boost::add_const<VALUE>::type>::type ptr_const_value_t;
- typedef typename boost::add_pointer<VALUE>::type ptr_value_t;
+ typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t;
+ typedef const KEY& ref_const_key_t;
+ typedef const VALUE& ref_const_value_t;
+ typedef const VALUE* ptr_const_value_t;
+ typedef VALUE* ptr_value_t;
class Registrar
{
@@ -64,7 +62,7 @@ public:
{
if (mMap.insert(std::make_pair(key, value)).second == false)
{
- llwarns << "Tried to register " << key << " but it was already registered!" << llendl;
+ LL_WARNS() << "Tried to register " << key << " but it was already registered!" << LL_ENDL;
return false;
}
return true;
@@ -309,7 +307,7 @@ public:
{
if (singleton_t::instance().exists(key))
{
- llerrs << "Duplicate registry entry under key \"" << key << "\"" << llendl;
+ LL_ERRS() << "Duplicate registry entry under key \"" << key << "\"" << LL_ENDL;
}
singleton_t::instance().mStaticScope->add(key, value);
}
diff --git a/indra/llcommon/llsafehandle.h b/indra/llcommon/llsafehandle.h
index 8d52d9bb15..4226bf04f0 100755
--- a/indra/llcommon/llsafehandle.h
+++ b/indra/llcommon/llsafehandle.h
@@ -134,7 +134,7 @@ protected:
tempp->unref();
if (mPointer != NULL)
{
- llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
+ LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL;
unref();
}
}
diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp
index 9f4460a988..2e7b46f885 100755
--- a/indra/llcommon/llsdparam.cpp
+++ b/indra/llcommon/llsdparam.cpp
@@ -30,13 +30,14 @@
// Project includes
#include "llsdparam.h"
#include "llsdutil.h"
+#include "boost/bind.hpp"
static LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
static LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
static LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
static const LLSD NO_VALUE_MARKER;
-LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion");
+LLTrace::BlockTimerStatHandle FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion");
//
// LLParamSDParser
@@ -102,13 +103,13 @@ void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool
//readSDValues(sd, block);
}
-void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)
+void LLParamSDParser::writeSDImpl(LLSD& sd, const LLInitParam::BaseBlock& block, const LLInitParam::predicate_rule_t rules, const LLInitParam::BaseBlock* diff_block)
{
mNameStack.clear();
mWriteRootSD = &sd;
name_stack_t name_stack;
- block.serializeBlock(*this, name_stack);
+ block.serializeBlock(*this, name_stack, rules, diff_block);
}
/*virtual*/ std::string LLParamSDParser::getCurrentElementName()
@@ -299,6 +300,7 @@ void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd)
LLInitParam::Parser::name_stack_t stack = LLInitParam::Parser::name_stack_t();
readSDValues(cb, sd, stack);
}
+
namespace LLInitParam
{
// LLSD specialization
@@ -329,13 +331,14 @@ namespace LLInitParam
p.writeValue<LLSD::String>(sd.asString(), name_stack);
}
- void ParamValue<LLSD, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const
+ bool ParamValue<LLSD, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack_range, const predicate_rule_t predicate_rule, const BaseBlock* diff_block) const
{
// attempt to write LLSD out directly
- if (!p.writeValue<LLSD>(mValue, name_stack))
+ if (!p.writeValue<LLSD>(mValue, name_stack_range))
{
// otherwise read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
- LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack);
+ LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack_range);
}
+ return true;
}
}
diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h
index 6ef5debd7b..1542f95e68 100755
--- a/indra/llcommon/llsdparam.h
+++ b/indra/llcommon/llsdparam.h
@@ -30,6 +30,7 @@
#include "llinitparam.h"
#include "boost/function.hpp"
+#include "llfasttimer.h"
struct LL_COMMON_API LLParamSDParserUtilities
{
@@ -50,11 +51,28 @@ typedef LLInitParam::Parser parser_t;
public:
LLParamSDParser();
void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false);
- void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block);
+ template<typename BLOCK>
+ void writeSD(LLSD& sd,
+ const BLOCK& block,
+ const LLInitParam::predicate_rule_t rules = LLInitParam::default_parse_rules(),
+ const LLInitParam::BaseBlock* diff_block = NULL)
+ {
+ if (!diff_block
+ && !rules.isAmbivalent(LLInitParam::HAS_DEFAULT_VALUE))
+ {
+ diff_block = &LLInitParam::defaultValue<BLOCK>();
+ }
+ writeSDImpl(sd, block, rules, diff_block);
+ }
/*virtual*/ std::string getCurrentElementName();
private:
+ void writeSDImpl(LLSD& sd,
+ const LLInitParam::BaseBlock& block,
+ const LLInitParam::predicate_rule_t,
+ const LLInitParam::BaseBlock* diff_block);
+
void submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack);
template<typename T>
@@ -92,7 +110,7 @@ private:
};
-extern LL_COMMON_API LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR;
+extern LL_COMMON_API LLTrace::BlockTimerStatHandle FTM_SD_PARAM_ADAPTOR;
template<typename T>
class LLSDParamAdapter : public T
{
@@ -100,7 +118,7 @@ public:
LLSDParamAdapter() {}
LLSDParamAdapter(const LLSD& sd)
{
- LLFastTimer _(FTM_SD_PARAM_ADAPTOR);
+ LL_RECORD_BLOCK_TIME(FTM_SD_PARAM_ADAPTOR);
LLParamSDParser parser;
// don't spam for implicit parsing of LLSD, as we want to allow arbitrary freeform data and ignore most of it
bool parse_silently = true;
diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp
index ad4fce6f35..04d7a6ed56 100755
--- a/indra/llcommon/llsdserialize.cpp
+++ b/indra/llcommon/llsdserialize.cpp
@@ -81,7 +81,7 @@ void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize
break;
default:
- llwarns << "serialize request for unknown ELLSD_Serialize" << llendl;
+ LL_WARNS() << "serialize request for unknown ELLSD_Serialize" << LL_ENDL;
}
if (f.notNull())
@@ -169,7 +169,7 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
}
else
{
- llwarns << "deserialize request for unknown ELLSD_Serialize" << llendl;
+ LL_WARNS() << "deserialize request for unknown ELLSD_Serialize" << LL_ENDL;
}
if (p.notNull())
@@ -179,7 +179,7 @@ bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
}
fail:
- llwarns << "deserialize LLSD parse failure" << llendl;
+ LL_WARNS() << "deserialize LLSD parse failure" << LL_ENDL;
return false;
}
@@ -445,7 +445,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
}
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading map." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading map." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -464,7 +464,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
}
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading array." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading array." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -500,7 +500,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
}
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading boolean." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading boolean." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -526,7 +526,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
}
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading boolean." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading boolean." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -539,7 +539,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
data = integer;
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading integer." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading integer." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -553,7 +553,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
data = real;
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading real." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading real." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -567,7 +567,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
data = id;
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading uuid." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading uuid." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -582,7 +582,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
}
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading string." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading string." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -604,7 +604,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
}
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading link." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading link." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -627,7 +627,7 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
}
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading date." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading date." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -640,15 +640,15 @@ S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
}
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading data." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading data." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
default:
parse_count = PARSE_FAILURE;
- llinfos << "Unrecognized character while parsing: int(" << (int)c
- << ")" << llendl;
+ LL_INFOS() << "Unrecognized character while parsing: int(" << (int)c
+ << ")" << LL_ENDL;
break;
}
if(PARSE_FAILURE == parse_count)
@@ -909,7 +909,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
}
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading binary map." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading binary map." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -928,7 +928,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
}
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading binary array." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading binary array." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -953,7 +953,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
data = (S32)ntohl(value_nbo);
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading binary integer." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading binary integer." << LL_ENDL;
}
break;
}
@@ -965,7 +965,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
data = ll_ntohd(real_nbo);
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading binary real." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading binary real." << LL_ENDL;
}
break;
}
@@ -977,7 +977,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
data = id;
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading binary uuid." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading binary uuid." << LL_ENDL;
}
break;
}
@@ -998,8 +998,8 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
}
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading binary (notation-style) string."
- << llendl;
+ LL_INFOS() << "STREAM FAILURE reading binary (notation-style) string."
+ << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -1018,7 +1018,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
}
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading binary string." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading binary string." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -1037,7 +1037,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
}
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading binary link." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading binary link." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -1050,7 +1050,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
data = LLDate(real);
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading binary date." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading binary date." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -1079,7 +1079,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
}
if(istr.fail())
{
- llinfos << "STREAM FAILURE reading binary." << llendl;
+ LL_INFOS() << "STREAM FAILURE reading binary." << LL_ENDL;
parse_count = PARSE_FAILURE;
}
break;
@@ -1087,8 +1087,8 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
default:
parse_count = PARSE_FAILURE;
- llinfos << "Unrecognized character while parsing: int(" << (int)c
- << ")" << llendl;
+ LL_INFOS() << "Unrecognized character while parsing: int(" << (int)c
+ << ")" << LL_ENDL;
break;
}
if(PARSE_FAILURE == parse_count)
@@ -2017,7 +2017,7 @@ std::string zip_llsd(LLSD& data)
S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION);
if (ret != Z_OK)
{
- llwarns << "Failed to compress LLSD block." << llendl;
+ LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
return std::string();
}
@@ -2044,7 +2044,7 @@ std::string zip_llsd(LLSD& data)
if (strm.avail_out >= CHUNK)
{
free(output);
- llwarns << "Failed to compress LLSD block." << llendl;
+ LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
return std::string();
}
@@ -2056,7 +2056,7 @@ std::string zip_llsd(LLSD& data)
else
{
free(output);
- llwarns << "Failed to compress LLSD block." << llendl;
+ LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL;
return std::string();
}
}
@@ -2073,7 +2073,7 @@ std::string zip_llsd(LLSD& data)
LLSD test_sd;
if (!unzip_llsd(test_sd, test, result.size()))
{
- llerrs << "Invalid compression result!" << llendl;
+ LL_ERRS() << "Invalid compression result!" << LL_ENDL;
}
#endif
@@ -2163,7 +2163,7 @@ bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
if (!LLSDSerialize::fromBinary(data, istr, cur_size))
{
- llwarns << "Failed to unzip LLSD block" << llendl;
+ LL_WARNS() << "Failed to unzip LLSD block" << LL_ENDL;
free(result);
return false;
}
diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp
index 614a2d5636..4e2af0e589 100755
--- a/indra/llcommon/llsdserialize_xml.cpp
+++ b/indra/llcommon/llsdserialize_xml.cpp
@@ -406,7 +406,7 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data)
}
if (mEmitErrors)
{
- llinfos << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:" << (char*) buffer << llendl;
+ LL_INFOS() << "LLSDXMLParser::Impl::parse: XML_STATUS_ERROR parsing:" << (char*) buffer << LL_ENDL;
}
data = LLSD();
return LLSDParser::PARSE_FAILURE;
@@ -487,7 +487,7 @@ S32 LLSDXMLParser::Impl::parseLines(std::istream& input, LLSD& data)
{
if (mEmitErrors)
{
- llinfos << "LLSDXMLParser::Impl::parseLines: XML_STATUS_ERROR" << llendl;
+ LL_INFOS() << "LLSDXMLParser::Impl::parseLines: XML_STATUS_ERROR" << LL_ENDL;
}
return LLSDParser::PARSE_FAILURE;
}
@@ -549,7 +549,7 @@ void LLSDXMLParser::Impl::parsePart(const char* buf, int len)
XML_Status status = XML_Parse(mParser, buf, len, false);
if (status == XML_STATUS_ERROR)
{
- llinfos << "Unexpected XML parsing error at start" << llendl;
+ LL_INFOS() << "Unexpected XML parsing error at start" << LL_ENDL;
}
}
}
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index 532d3f9341..d0b536c39a 100755
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -29,7 +29,7 @@
#ifndef LL_LLSDUTIL_H
#define LL_LLSDUTIL_H
-class LLSD;
+#include "llsd.h"
// U32
LL_COMMON_API LLSD ll_sd_from_U32(const U32);
diff --git a/indra/llcommon/llsecondlifeurls.cpp b/indra/llcommon/llsecondlifeurls.cpp
deleted file mode 100755
index 9154e05e43..0000000000
--- a/indra/llcommon/llsecondlifeurls.cpp
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * @file llsecondlifeurls.cpp
- * @brief Urls used in the product
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llsecondlifeurls.h"
-/*
-const std::string CREATE_ACCOUNT_URL (
- "http://join.secondlife.com/");
-
-const std::string MANAGE_ACCOUNT (
- "http://secondlife.com/account/"); // *TODO: NOT USED
-
-const std::string AUCTION_URL (
- "http://secondlife.com/auctions/auction-detail.php?id=");
-
-const std::string EVENTS_URL (
- "http://secondlife.com/events/");
-*/
-const std::string TIER_UP_URL (
- "http://secondlife.com/app/landtier"); // *TODO: Translate (simulator)
-
-const std::string DIRECTX_9_URL (
- "http://secondlife.com/support/"); // *TODO: NOT USED
-/*
-const std::string LAND_URL (
- "http://secondlife.com/app/landtier"); // *TODO: NOT USED
-
-const std::string UPGRADE_TO_PREMIUM_URL (
- "http://secondlife.com/app/upgrade/"); // *TODO: NOT USED
-
-const std::string AMD_AGP_URL (
- "http://secondlife.com/support/"); // *TODO: NOT USED
-
-const std::string VIA_URL (
- "http://secondlife.com/support/"); // *TODO: NOT USED
-
-const std::string SUPPORT_URL (
- "http://secondlife.com/support/");
-
-const std::string INTEL_CHIPSET_URL (
- "http://secondlife.com/support/"); // *TODO: NOT USED
-
-const std::string SIS_CHIPSET_URL (
- "http://secondlife.com/support/"); // *TODO: NOT USED
-
-const std::string BLOGS_URL (
- "http://blog.secondlife.com/"); // *TODO: NOT USED
-
-const std::string BUY_CURRENCY_URL (
- "http://secondlife.com/app/currency/");
-
-const std::string LSL_DOC_URL (
- "http://secondlife.com/app/lsldoc/"); // *TODO: NOT USED
-
-const std::string SL_KB_URL (
- "http://secondlife.com/knowledgebase/"); // *TODO: NOT USED
-
-const std::string RELEASE_NOTES_BASE_URL (
- "http://secondlife.com/app/releasenotes/");
-*/
-
diff --git a/indra/llcommon/llsecondlifeurls.h b/indra/llcommon/llsecondlifeurls.h
deleted file mode 100755
index 62f357ffed..0000000000
--- a/indra/llcommon/llsecondlifeurls.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * @file llsecondlifeurls.h
- * @brief Global URLs to pages on our web site
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLSECONDLIFEURLS_H
-#define LL_LLSECONDLIFEURLS_H
-/*
-// Account registration web page
-LL_COMMON_API extern const std::string CREATE_ACCOUNT_URL;
-
-// Manage Account
-LL_COMMON_API extern const std::string MANAGE_ACCOUNT;
-
-LL_COMMON_API extern const std::string AUCTION_URL;
-
-LL_COMMON_API extern const std::string EVENTS_URL;
-*/
-// Tier up to a new land level.
-LL_COMMON_API extern const std::string TIER_UP_URL;
-
-
-// Tier up to a new land level.
-LL_COMMON_API extern const std::string LAND_URL;
-
-// How to get DirectX 9
-LL_COMMON_API extern const std::string DIRECTX_9_URL;
-
-/*
-// Upgrade from basic membership to premium membership
-LL_COMMON_API extern const std::string UPGRADE_TO_PREMIUM_URL;
-
-
-// Out of date VIA chipset
-LL_COMMON_API extern const std::string VIA_URL;
-
-// Support URL
-LL_COMMON_API extern const std::string SUPPORT_URL;
-
-// Linden Blogs page
-LL_COMMON_API extern const std::string BLOGS_URL;
-
-// Currency page
-LL_COMMON_API extern const std::string BUY_CURRENCY_URL;
-
-// LSL script wiki
-LL_COMMON_API extern const std::string LSL_DOC_URL;
-
-// SL KnowledgeBase page
-LL_COMMON_API extern const std::string SL_KB_URL;
-
-// Release Notes Redirect URL for Server and Viewer
-LL_COMMON_API extern const std::string RELEASE_NOTES_BASE_URL;
-*/
-#endif
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 40002313f1..6e6291a165 100755
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -67,6 +67,11 @@ private:
INITIALIZED,
DELETED
} EInitState;
+
+ static DERIVED_TYPE* constructSingleton()
+ {
+ return new DERIVED_TYPE();
+ }
// stores pointer to singleton instance
struct SingletonLifetimeManager
@@ -79,7 +84,7 @@ private:
static void construct()
{
sData.mInitState = CONSTRUCTING;
- sData.mInstance = new DERIVED_TYPE();
+ sData.mInstance = constructSingleton();
sData.mInitState = INITIALIZING;
}
@@ -138,18 +143,21 @@ public:
llassert(false);
return NULL;
case CONSTRUCTING:
- llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl;
+ LL_ERRS() << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << LL_ENDL;
return NULL;
case INITIALIZING:
// go ahead and flag ourselves as initialized so we can be reentrant during initialization
sData.mInitState = INITIALIZED;
+ // initialize singleton after constructing it so that it can reference other singletons which in turn depend on it,
+ // thus breaking cyclic dependencies
sData.mInstance->initSingleton();
return sData.mInstance;
case INITIALIZED:
return sData.mInstance;
case DELETED:
- llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
+ LL_WARNS() << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << LL_ENDL;
SingletonLifetimeManager::construct();
+ // same as first time construction
sData.mInitState = INITIALIZED;
sData.mInstance->initSingleton();
return sData.mInstance;
@@ -190,6 +198,8 @@ private:
struct SingletonData
{
+ // explicitly has a default constructor so that member variables are zero initialized in BSS
+ // and only changed by singleton logic, not constructor running during startup
EInitState mInitState;
DERIVED_TYPE* mInstance;
};
diff --git a/indra/llcommon/llskiplist.h b/indra/llcommon/llskiplist.h
deleted file mode 100755
index ed132381f9..0000000000
--- a/indra/llcommon/llskiplist.h
+++ /dev/null
@@ -1,517 +0,0 @@
-/**
- * @file llskiplist.h
- * @brief skip list implementation
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-#ifndef LL_LLSKIPLIST_H
-#define LL_LLSKIPLIST_H
-
-#include "llrand.h"
-#include "llrand.h"
-
-// NOTA BENE: Insert first needs to be < NOT <=
-// Binary depth must be >= 2
-template <class DATA_TYPE, S32 BINARY_DEPTH = 10>
-class LLSkipList
-{
-public:
- typedef BOOL (*compare)(const DATA_TYPE& first, const DATA_TYPE& second);
- typedef compare insert_func;
- typedef compare equals_func;
-
- void init();
-
- // basic constructor
- LLSkipList();
-
- // basic constructor including sorter
- LLSkipList(insert_func insert_first, equals_func equals);
- ~LLSkipList();
-
- inline void setInsertFirst(insert_func insert_first);
- inline void setEquals(equals_func equals);
-
- inline BOOL addData(const DATA_TYPE& data);
- inline BOOL checkData(const DATA_TYPE& data);
-
- // returns number of items in the list
- inline S32 getLength() const; // NOT a constant time operation, traverses entire list!
-
- inline BOOL moveData(const DATA_TYPE& data, LLSkipList *newlist);
-
- inline BOOL removeData(const DATA_TYPE& data);
-
- // remove all nodes from the list but do not delete data
- inline void removeAllNodes();
-
- // place mCurrentp on first node
- inline void resetList();
-
- // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
- inline DATA_TYPE getCurrentData();
-
- // same as getCurrentData() but a more intuitive name for the operation
- inline DATA_TYPE getNextData();
-
- // remove the Node at mCurentOperatingp
- // leave mCurrentp and mCurentOperatingp on the next entry
- inline void removeCurrentData();
-
- // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
- inline DATA_TYPE getFirstData();
-
- class LLSkipNode
- {
- public:
- LLSkipNode()
- : mData(0)
- {
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mForward[i] = NULL;
- }
- }
-
- LLSkipNode(DATA_TYPE data)
- : mData(data)
- {
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mForward[i] = NULL;
- }
- }
-
- ~LLSkipNode()
- {
- }
-
- DATA_TYPE mData;
- LLSkipNode *mForward[BINARY_DEPTH];
-
- private:
- // Disallow copying of LLSkipNodes by not implementing these methods.
- LLSkipNode(const LLSkipNode &);
- LLSkipNode &operator=(const LLSkipNode &);
- };
-
- static BOOL defaultEquals(const DATA_TYPE& first, const DATA_TYPE& second)
- {
- return first == second;
- }
-
-private:
- LLSkipNode mHead;
- LLSkipNode *mUpdate[BINARY_DEPTH];
- LLSkipNode *mCurrentp;
- LLSkipNode *mCurrentOperatingp;
- S32 mLevel;
- insert_func mInsertFirst;
- equals_func mEquals;
-
-private:
- // Disallow copying of LLSkipNodes by not implementing these methods.
- LLSkipList(const LLSkipList &);
- LLSkipList &operator=(const LLSkipList &);
-};
-
-
-///////////////////////
-//
-// Implementation
-//
-
-
-// Binary depth must be >= 2
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::init()
-{
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mHead.mForward[i] = NULL;
- mUpdate[i] = NULL;
- }
- mLevel = 1;
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-
-// basic constructor
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline LLSkipList<DATA_TYPE, BINARY_DEPTH>::LLSkipList()
-: mInsertFirst(NULL),
- mEquals(defaultEquals)
-{
- init();
-}
-
-// basic constructor including sorter
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline LLSkipList<DATA_TYPE, BINARY_DEPTH>::LLSkipList(insert_func insert,
- equals_func equals)
-: mInsertFirst(insert),
- mEquals(equals)
-{
- init();
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline LLSkipList<DATA_TYPE, BINARY_DEPTH>::~LLSkipList()
-{
- removeAllNodes();
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::setInsertFirst(insert_func insert_first)
-{
- mInsertFirst = insert_first;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::setEquals(equals_func equals)
-{
- mEquals = equals;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::addData(const DATA_TYPE& data)
-{
- S32 level;
- LLSkipNode *current = &mHead;
- LLSkipNode *temp;
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mData, data)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mData < data))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- // now add the new node
- S32 newlevel;
- for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
- {
- if (ll_frand() < 0.5f)
- break;
- }
-
- LLSkipNode *snode = new LLSkipNode(data);
-
- if (newlevel > mLevel)
- {
- mHead.mForward[mLevel] = NULL;
- mUpdate[mLevel] = &mHead;
- mLevel = newlevel;
- }
-
- for (level = 0; level < newlevel; level++)
- {
- snode->mForward[level] = mUpdate[level]->mForward[level];
- mUpdate[level]->mForward[level] = snode;
- }
- return TRUE;
-}
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::checkData(const DATA_TYPE& data)
-{
- S32 level;
- LLSkipNode *current = &mHead;
- LLSkipNode *temp;
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mData, data)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mData < data))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
-
- if (current)
- {
- return mEquals(current->mData, data);
- }
-
- return FALSE;
-}
-
-// returns number of items in the list
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline S32 LLSkipList<DATA_TYPE, BINARY_DEPTH>::getLength() const
-{
- U32 length = 0;
- for (LLSkipNode* temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0])
- {
- length++;
- }
- return length;
-}
-
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::moveData(const DATA_TYPE& data, LLSkipList *newlist)
-{
- BOOL removed = removeData(data);
- BOOL added = newlist->addData(data);
- return removed && added;
-}
-
-
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::removeData(const DATA_TYPE& data)
-{
- S32 level;
- LLSkipNode *current = &mHead;
- LLSkipNode *temp;
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mData, data)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mData < data))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
-
- if (!current)
- {
- // empty list or beyond the end!
- return FALSE;
- }
-
- // is this the one we want?
- if (!mEquals(current->mData, data))
- {
- // nope!
- return FALSE;
- }
- else
- {
- // do we need to fix current or currentop?
- if (current == mCurrentp)
- {
- mCurrentp = current->mForward[0];
- }
-
- if (current == mCurrentOperatingp)
- {
- mCurrentOperatingp = current->mForward[0];
- }
- // yes it is! change pointers as required
- for (level = 0; level < mLevel; level++)
- {
- if (mUpdate[level]->mForward[level] != current)
- {
- // cool, we've fixed all the pointers!
- break;
- }
- mUpdate[level]->mForward[level] = current->mForward[level];
- }
-
- // clean up cuurent
- delete current;
-
- // clean up mHead
- while ( (mLevel > 1)
- &&(!mHead.mForward[mLevel - 1]))
- {
- mLevel--;
- }
- }
- return TRUE;
-}
-
-// remove all nodes from the list but do not delete data
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::removeAllNodes()
-{
- LLSkipNode *temp;
- // reset mCurrentp
- mCurrentp = *(mHead.mForward);
-
- while (mCurrentp)
- {
- temp = mCurrentp->mForward[0];
- delete mCurrentp;
- mCurrentp = temp;
- }
-
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mHead.mForward[i] = NULL;
- mUpdate[i] = NULL;
- }
-
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-// place mCurrentp on first node
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::resetList()
-{
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipList<DATA_TYPE, BINARY_DEPTH>::getCurrentData()
-{
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mForward[0];
- return mCurrentOperatingp->mData;
- }
- else
- {
- //return NULL; // causes compile warning
- return (DATA_TYPE)0; // equivalent, but no warning
- }
-}
-
-// same as getCurrentData() but a more intuitive name for the operation
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipList<DATA_TYPE, BINARY_DEPTH>::getNextData()
-{
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mForward[0];
- return mCurrentOperatingp->mData;
- }
- else
- {
- //return NULL; // causes compile warning
- return (DATA_TYPE)0; // equivalent, but no warning
- }
-}
-
-// remove the Node at mCurentOperatingp
-// leave mCurrentp and mCurentOperatingp on the next entry
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::removeCurrentData()
-{
- if (mCurrentOperatingp)
- {
- removeData(mCurrentOperatingp->mData);
- }
-}
-
-// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipList<DATA_TYPE, BINARY_DEPTH>::getFirstData()
-{
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mForward[0];
- return mCurrentOperatingp->mData;
- }
- else
- {
- //return NULL; // causes compile warning
- return (DATA_TYPE)0; // equivalent, but no warning
- }
-}
-
-
-#endif
diff --git a/indra/llcommon/llskipmap.h b/indra/llcommon/llskipmap.h
deleted file mode 100755
index 49ff2928d1..0000000000
--- a/indra/llcommon/llskipmap.h
+++ /dev/null
@@ -1,1022 +0,0 @@
-/**
- * @file llskipmap.h
- * @brief Associative container based on the skiplist algorithm.
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLSKIPMAP_H
-#define LL_LLSKIPMAP_H
-
-#include "llerror.h"
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH = 8>
-class LLSkipMap
-{
-public:
- // basic constructor
- LLSkipMap();
-
- // basic constructor including sorter
- LLSkipMap(BOOL (*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second),
- BOOL (*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second));
-
- ~LLSkipMap();
-
- void setInsertFirst(BOOL (*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second));
- void setEquals(BOOL (*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second));
-
- DATA_TYPE &addData(const INDEX_TYPE &index, DATA_TYPE datap);
- DATA_TYPE &addData(const INDEX_TYPE &index);
- DATA_TYPE &getData(const INDEX_TYPE &index);
- DATA_TYPE &operator[](const INDEX_TYPE &index);
-
- // If index present, returns data.
- // If index not present, adds <index,NULL> and returns NULL.
- DATA_TYPE &getData(const INDEX_TYPE &index, BOOL &b_new_entry);
-
- // Returns TRUE if data present in map.
- BOOL checkData(const INDEX_TYPE &index);
-
- // Returns TRUE if key is present in map. This is useful if you
- // are potentially storing NULL pointers in the map
- BOOL checkKey(const INDEX_TYPE &index);
-
- // If there, returns the data.
- // If not, returns NULL.
- // Never adds entries to the map.
- DATA_TYPE getIfThere(const INDEX_TYPE &index);
-
- INDEX_TYPE reverseLookup(const DATA_TYPE datap);
-
- // returns number of items in the list
- S32 getLength(); // WARNING! getLength is O(n), not O(1)!
-
- BOOL removeData(const INDEX_TYPE &index);
-
- // remove all nodes from the list but do not delete data
- void removeAllData();
-
- // place mCurrentp on first node
- void resetList();
-
- // return the data currently pointed to
- DATA_TYPE getCurrentDataWithoutIncrement();
-
- // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
- DATA_TYPE getCurrentData();
-
- // same as getCurrentData() but a more intuitive name for the operation
- DATA_TYPE getNextData();
-
- INDEX_TYPE getNextKey();
-
- // return the key currently pointed to
- INDEX_TYPE getCurrentKeyWithoutIncrement();
-
- // The internal iterator is at the end of the list.
- BOOL notDone() const;
-
- // remove the Node at mCurentOperatingp
- // leave mCurrentp and mCurentOperatingp on the next entry
- void removeCurrentData();
-
- void deleteCurrentData();
-
- // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
- DATA_TYPE getFirstData();
-
- INDEX_TYPE getFirstKey();
-
- class LLSkipMapNode
- {
- public:
- LLSkipMapNode()
- {
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mForward[i] = NULL;
- }
-
- U8 *zero = (U8 *)&mIndex;
-
- for (i = 0; i < (S32)sizeof(INDEX_TYPE); i++)
- {
- *(zero + i) = 0;
- }
-
- zero = (U8 *)&mData;
-
- for (i = 0; i < (S32)sizeof(DATA_TYPE); i++)
- {
- *(zero + i) = 0;
- }
- }
-
- LLSkipMapNode(const INDEX_TYPE &index)
- : mIndex(index)
- {
-
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mForward[i] = NULL;
- }
-
- U8 *zero = (U8 *)&mData;
-
- for (i = 0; i < (S32)sizeof(DATA_TYPE); i++)
- {
- *(zero + i) = 0;
- }
- }
-
- LLSkipMapNode(const INDEX_TYPE &index, DATA_TYPE datap)
- : mIndex(index)
- {
-
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mForward[i] = NULL;
- }
-
- mData = datap;
- }
-
- ~LLSkipMapNode()
- {
- }
-
-
- INDEX_TYPE mIndex;
- DATA_TYPE mData;
- LLSkipMapNode *mForward[BINARY_DEPTH];
-
- private:
- // Disallow copying of LLSkipMapNodes by not implementing these methods.
- LLSkipMapNode(const LLSkipMapNode &);
- LLSkipMapNode &operator=(const LLSkipMapNode &rhs);
- };
-
- static BOOL defaultEquals(const INDEX_TYPE &first, const INDEX_TYPE &second)
- {
- return first == second;
- }
-
-private:
- // don't generate implicit copy constructor or copy assignment
- LLSkipMap(const LLSkipMap &);
- LLSkipMap &operator=(const LLSkipMap &);
-
-private:
- LLSkipMapNode mHead;
- LLSkipMapNode *mUpdate[BINARY_DEPTH];
- LLSkipMapNode *mCurrentp;
- LLSkipMapNode *mCurrentOperatingp;
- S32 mLevel;
- BOOL (*mInsertFirst)(const INDEX_TYPE &first, const INDEX_TYPE &second);
- BOOL (*mEquals)(const INDEX_TYPE &first, const INDEX_TYPE &second);
- S32 mNumberOfSteps;
-};
-
-//////////////////////////////////////////////////
-//
-// LLSkipMap implementation
-//
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::LLSkipMap()
- : mInsertFirst(NULL),
- mEquals(defaultEquals)
-{
- // Skipmaps must have binary depth of at least 2
- cassert(BINARY_DEPTH >= 2);
-
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mUpdate[i] = NULL;
- }
- mLevel = 1;
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::LLSkipMap(BOOL (*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second),
- BOOL (*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second))
- : mInsertFirst(insert_first),
- mEquals(equals)
-{
- // Skipmaps must have binary depth of at least 2
- cassert(BINARY_DEPTH >= 2);
-
- mLevel = 1;
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mHead.mForward[i] = NULL;
- mUpdate[i] = NULL;
- }
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::~LLSkipMap()
-{
- removeAllData();
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::setInsertFirst(BOOL (*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second))
-{
- mInsertFirst = insert_first;
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::setEquals(BOOL (*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second))
-{
- mEquals = equals;
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::addData(const INDEX_TYPE &index, DATA_TYPE datap)
-{
- S32 level;
- LLSkipMapNode *current = &mHead;
- LLSkipMapNode *temp;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- // replace the existing data if a node is already there
- if ( (current)
- &&(mEquals(current->mIndex, index)))
- {
- current->mData = datap;
- return current->mData;
- }
-
- // now add the new node
- S32 newlevel;
- for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
- {
- if (rand() & 1)
- {
- break;
- }
- }
-
- LLSkipMapNode *snode = new LLSkipMapNode(index, datap);
-
- if (newlevel > mLevel)
- {
- mHead.mForward[mLevel] = NULL;
- mUpdate[mLevel] = &mHead;
- mLevel = newlevel;
- }
-
- for (level = 0; level < newlevel; level++)
- {
- snode->mForward[level] = mUpdate[level]->mForward[level];
- mUpdate[level]->mForward[level] = snode;
- }
- return snode->mData;
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::addData(const INDEX_TYPE &index)
-{
- S32 level;
- LLSkipMapNode *current = &mHead;
- LLSkipMapNode *temp;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- // now add the new node
- S32 newlevel;
- for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
- {
- if (rand() & 1)
- break;
- }
-
- LLSkipMapNode *snode = new LLSkipMapNode(index);
-
- if (newlevel > mLevel)
- {
- mHead.mForward[mLevel] = NULL;
- mUpdate[mLevel] = &mHead;
- mLevel = newlevel;
- }
-
- for (level = 0; level < newlevel; level++)
- {
- snode->mForward[level] = mUpdate[level]->mForward[level];
- mUpdate[level]->mForward[level] = snode;
- }
- return snode->mData;
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getData(const INDEX_TYPE &index)
-{
- S32 level;
- LLSkipMapNode *current = &mHead;
- LLSkipMapNode *temp;
-
- mNumberOfSteps = 0;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- mNumberOfSteps++;
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- mNumberOfSteps++;
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
- mNumberOfSteps++;
-
- if ( (current)
- &&(mEquals(current->mIndex, index)))
- {
-
- return current->mData;
- }
-
- // now add the new node
- S32 newlevel;
- for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++)
- {
- if (rand() & 1)
- break;
- }
-
- LLSkipMapNode *snode = new LLSkipMapNode(index);
-
- if (newlevel > mLevel)
- {
- mHead.mForward[mLevel] = NULL;
- mUpdate[mLevel] = &mHead;
- mLevel = newlevel;
- }
-
- for (level = 0; level < newlevel; level++)
- {
- snode->mForward[level] = mUpdate[level]->mForward[level];
- mUpdate[level]->mForward[level] = snode;
- }
-
- return snode->mData;
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::operator[](const INDEX_TYPE &index)
-{
-
- return getData(index);
-}
-
-// If index present, returns data.
-// If index not present, adds <index,NULL> and returns NULL.
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getData(const INDEX_TYPE &index, BOOL &b_new_entry)
-{
- S32 level;
- LLSkipMapNode *current = &mHead;
- LLSkipMapNode *temp;
-
- mNumberOfSteps = 0;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- mNumberOfSteps++;
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- mNumberOfSteps++;
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- mNumberOfSteps++;
- current = *current->mForward;
-
- if ( (current)
- &&(mEquals(current->mIndex, index)))
- {
-
- return current->mData;
- }
- b_new_entry = TRUE;
- addData(index);
-
- return current->mData;
-}
-
-// Returns TRUE if data present in map.
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::checkData(const INDEX_TYPE &index)
-{
- S32 level;
- LLSkipMapNode *current = &mHead;
- LLSkipMapNode *temp;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- if (current)
- {
- // Gets rid of some compiler ambiguity for the LLPointer<> templated class.
- if (current->mData)
- {
- return mEquals(current->mIndex, index);
- }
- }
-
- return FALSE;
-}
-
-// Returns TRUE if key is present in map. This is useful if you
-// are potentially storing NULL pointers in the map
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::checkKey(const INDEX_TYPE &index)
-{
- S32 level;
- LLSkipMapNode *current = &mHead;
- LLSkipMapNode *temp;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- if (current)
- {
- return mEquals(current->mIndex, index);
- }
-
- return FALSE;
-}
-
-// If there, returns the data.
-// If not, returns NULL.
-// Never adds entries to the map.
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getIfThere(const INDEX_TYPE &index)
-{
- S32 level;
- LLSkipMapNode *current = &mHead;
- LLSkipMapNode *temp;
-
- mNumberOfSteps = 0;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- mNumberOfSteps++;
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- mNumberOfSteps++;
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- mNumberOfSteps++;
- current = *current->mForward;
-
- if (current)
- {
- if (mEquals(current->mIndex, index))
- {
- return current->mData;
- }
- }
-
- // Avoid Linux compiler warning on returning NULL.
- return DATA_TYPE();
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::reverseLookup(const DATA_TYPE datap)
-{
- LLSkipMapNode *current = &mHead;
-
- while (current)
- {
- if (datap == current->mData)
- {
-
- return current->mIndex;
- }
- current = *current->mForward;
- }
-
- // not found! return NULL
- return INDEX_TYPE();
-}
-
-// returns number of items in the list
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline S32 LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getLength()
-{
- U32 length = 0;
- for (LLSkipMapNode* temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0])
- {
- length++;
- }
-
- return length;
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::removeData(const INDEX_TYPE &index)
-{
- S32 level;
- LLSkipMapNode *current = &mHead;
- LLSkipMapNode *temp;
-
- // find the pointer one in front of the one we want
- if (mInsertFirst)
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(mInsertFirst(temp->mIndex, index)))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
- else
- {
- for (level = mLevel - 1; level >= 0; level--)
- {
- temp = *(current->mForward + level);
- while ( (temp)
- &&(temp->mIndex < index))
- {
- current = temp;
- temp = *(current->mForward + level);
- }
- *(mUpdate + level) = current;
- }
- }
-
- // we're now just in front of where we want to be . . . take one step forward
- current = *current->mForward;
-
- if (!current)
- {
- // empty list or beyond the end!
-
- return FALSE;
- }
-
- // is this the one we want?
- if (!mEquals(current->mIndex, index))
- {
- // nope!
-
- return FALSE;
- }
- else
- {
- // do we need to fix current or currentop?
- if (current == mCurrentp)
- {
- mCurrentp = *current->mForward;
- }
-
- if (current == mCurrentOperatingp)
- {
- mCurrentOperatingp = *current->mForward;
- }
- // yes it is! change pointers as required
- for (level = 0; level < mLevel; level++)
- {
- if (*((*(mUpdate + level))->mForward + level) != current)
- {
- // cool, we've fixed all the pointers!
- break;
- }
- *((*(mUpdate + level))->mForward + level) = *(current->mForward + level);
- }
-
- delete current;
-
- // clean up mHead
- while ( (mLevel > 1)
- &&(!*(mHead.mForward + mLevel - 1)))
- {
- mLevel--;
- }
- }
-
- return TRUE;
-}
-
-
-// remove all nodes from the list but do not delete data
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::removeAllData()
-{
- LLSkipMapNode *temp;
- // reset mCurrentp
- mCurrentp = *(mHead.mForward);
-
- while (mCurrentp)
- {
- temp = mCurrentp->mForward[0];
- delete mCurrentp;
- mCurrentp = temp;
- }
-
- S32 i;
- for (i = 0; i < BINARY_DEPTH; i++)
- {
- mHead.mForward[i] = NULL;
- mUpdate[i] = NULL;
- }
-
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-
-// place mCurrentp on first node
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::resetList()
-{
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
-}
-
-
-// return the data currently pointed to
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getCurrentDataWithoutIncrement()
-{
- if (mCurrentOperatingp)
- {
- return mCurrentOperatingp->mData;
- }
- else
- {
- return DATA_TYPE();
- }
-}
-
-// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getCurrentData()
-{
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mForward[0];
- return mCurrentOperatingp->mData;
- }
- else
- {
- // Basic types, like int, have default constructors that initialize
- // them to zero. g++ 2.95 supports this. "int()" is zero.
- // This also is nice for LLUUID()
- return DATA_TYPE();
- }
-}
-
-// same as getCurrentData() but a more intuitive name for the operation
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getNextData()
-{
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mForward[0];
- return mCurrentOperatingp->mData;
- }
- else
- {
- // Basic types, like int, have default constructors that initialize
- // them to zero. g++ 2.95 supports this. "int()" is zero.
- // This also is nice for LLUUID()
- return DATA_TYPE();
- }
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getNextKey()
-{
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mForward[0];
- return mCurrentOperatingp->mIndex;
- }
- else
- {
- return mHead.mIndex;
- }
-}
-
-// return the key currently pointed to
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getCurrentKeyWithoutIncrement()
-{
- if (mCurrentOperatingp)
- {
- return mCurrentOperatingp->mIndex;
- }
- else
- {
- // See comment for getNextData()
- return INDEX_TYPE();
- }
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::notDone() const
-{
- if (mCurrentOperatingp)
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-}
-
-
-// remove the Node at mCurentOperatingp
-// leave mCurrentp and mCurentOperatingp on the next entry
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::removeCurrentData()
-{
- if (mCurrentOperatingp)
- {
- removeData(mCurrentOperatingp->mIndex);
- }
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::deleteCurrentData()
-{
- if (mCurrentOperatingp)
- {
- deleteData(mCurrentOperatingp->mIndex);
- }
-}
-
-// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getFirstData()
-{
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mForward[0];
- return mCurrentOperatingp->mData;
- }
- else
- {
- // See comment for getNextData()
- return DATA_TYPE();
- }
-}
-
-template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH>
-inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getFirstKey()
-{
- mCurrentp = *(mHead.mForward);
- mCurrentOperatingp = *(mHead.mForward);
- if (mCurrentp)
- {
- mCurrentOperatingp = mCurrentp;
- mCurrentp = mCurrentp->mForward[0];
- return mCurrentOperatingp->mIndex;
- }
- else
- {
- return mHead.mIndex;
- }
-}
-
-#endif
diff --git a/indra/llcommon/llsortedvector.h b/indra/llcommon/llsortedvector.h
deleted file mode 100755
index 391b82ee44..0000000000
--- a/indra/llcommon/llsortedvector.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- * @file llsortedvector.h
- * @author Nat Goodspeed
- * @date 2012-04-08
- * @brief LLSortedVector class wraps a vector that we maintain in sorted
- * order so we can perform binary-search lookups.
- *
- * $LicenseInfo:firstyear=2012&license=viewerlgpl$
- * Copyright (c) 2012, Linden Research, Inc.
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LLSORTEDVECTOR_H)
-#define LL_LLSORTEDVECTOR_H
-
-#include <vector>
-#include <algorithm>
-
-/**
- * LLSortedVector contains a std::vector<std::pair> that we keep sorted on the
- * first of the pair. This makes insertion somewhat more expensive than simple
- * std::vector::push_back(), but allows us to use binary search for lookups.
- * It's intended for small aggregates where lookup is far more performance-
- * critical than insertion; in such cases a binary search on a small, sorted
- * std::vector can be more performant than a std::map lookup.
- */
-template <typename KEY, typename VALUE>
-class LLSortedVector
-{
-public:
- typedef LLSortedVector<KEY, VALUE> self;
- typedef KEY key_type;
- typedef VALUE mapped_type;
- typedef std::pair<key_type, mapped_type> value_type;
- typedef std::vector<value_type> PairVector;
- typedef typename PairVector::iterator iterator;
- typedef typename PairVector::const_iterator const_iterator;
-
- /// Empty
- LLSortedVector() {}
-
- /// Fixed initial size
- LLSortedVector(std::size_t size):
- mVector(size)
- {}
-
- /// Bulk load
- template <typename ITER>
- LLSortedVector(ITER begin, ITER end):
- mVector(begin, end)
- {
- // Allow caller to dump in a bunch of (pairs convertible to)
- // value_type if desired, but make sure we sort afterwards.
- std::sort(mVector.begin(), mVector.end());
- }
-
- /// insert(key, value)
- std::pair<iterator, bool> insert(const key_type& key, const mapped_type& value)
- {
- return insert(value_type(key, value));
- }
-
- /// insert(value_type)
- std::pair<iterator, bool> insert(const value_type& pair)
- {
- typedef std::pair<iterator, bool> iterbool;
- iterator found = std::lower_bound(mVector.begin(), mVector.end(), pair,
- less<value_type>());
- // have to check for end() before it's even valid to dereference
- if (found == mVector.end())
- {
- std::size_t index(mVector.size());
- mVector.push_back(pair);
- // don't forget that push_back() invalidates 'found'
- return iterbool(mVector.begin() + index, true);
- }
- if (found->first == pair.first)
- {
- return iterbool(found, false);
- }
- // remember that insert() invalidates 'found' -- save index
- std::size_t index(found - mVector.begin());
- mVector.insert(found, pair);
- // okay, convert from index back to iterator
- return iterbool(mVector.begin() + index, true);
- }
-
- iterator begin() { return mVector.begin(); }
- iterator end() { return mVector.end(); }
- const_iterator begin() const { return mVector.begin(); }
- const_iterator end() const { return mVector.end(); }
-
- bool empty() const { return mVector.empty(); }
- std::size_t size() const { return mVector.size(); }
-
- /// find
- iterator find(const key_type& key)
- {
- iterator found = std::lower_bound(mVector.begin(), mVector.end(),
- value_type(key, mapped_type()),
- less<value_type>());
- if (found == mVector.end() || found->first != key)
- return mVector.end();
- return found;
- }
-
- const_iterator find(const key_type& key) const
- {
- return const_cast<self*>(this)->find(key);
- }
-
-private:
- // Define our own 'less' comparator so we can specialize without messing
- // with std::less.
- template <typename T>
- struct less: public std::less<T> {};
-
- // Specialize 'less' for an LLSortedVector::value_type involving
- // std::type_info*. This is one of LLSortedVector's foremost use cases. We
- // specialize 'less' rather than just defining a specific comparator
- // because LLSortedVector should be usable for other key_types as well.
- template <typename T>
- struct less< std::pair<std::type_info*, T> >:
- public std::binary_function<std::pair<std::type_info*, T>,
- std::pair<std::type_info*, T>,
- bool>
- {
- bool operator()(const std::pair<std::type_info*, T>& lhs,
- const std::pair<std::type_info*, T>& rhs) const
- {
- return lhs.first->before(*rhs.first);
- }
- };
-
- // Same as above, but with const std::type_info*.
- template <typename T>
- struct less< std::pair<const std::type_info*, T> >:
- public std::binary_function<std::pair<const std::type_info*, T>,
- std::pair<const std::type_info*, T>,
- bool>
- {
- bool operator()(const std::pair<const std::type_info*, T>& lhs,
- const std::pair<const std::type_info*, T>& rhs) const
- {
- return lhs.first->before(*rhs.first);
- }
- };
-
- PairVector mVector;
-};
-
-#endif /* ! defined(LL_LLSORTEDVECTOR_H) */
diff --git a/indra/llcommon/llstack.h b/indra/llcommon/llstack.h
deleted file mode 100755
index 315de6ba2d..0000000000
--- a/indra/llcommon/llstack.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * @file llstack.h
- * @brief LLStack template class
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLSTACK_H
-#define LL_LLSTACK_H
-
-#include "linked_lists.h"
-
-template <class DATA_TYPE> class LLStack
-{
-private:
- LLLinkedList<DATA_TYPE> mStack;
-
-public:
- LLStack() {}
- ~LLStack() {}
-
- void push(DATA_TYPE *data) { mStack.addData(data); }
- DATA_TYPE *pop() { DATA_TYPE *tempp = mStack.getFirstData(); mStack.removeCurrentData(); return tempp; }
- void deleteAllData() { mStack.deleteAllData(); }
- void removeAllNodes() { mStack.removeAllNodes(); }
-};
-
-#endif
-
diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp
index ccd7ef91c2..e0e9056380 100755
--- a/indra/llcommon/llstacktrace.cpp
+++ b/indra/llcommon/llstacktrace.cpp
@@ -32,7 +32,7 @@
#include <iostream>
#include <sstream>
-#include "windows.h"
+#include "llwin32headerslean.h"
#include "Dbghelp.h"
typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp
deleted file mode 100755
index 3678c8e1c1..0000000000
--- a/indra/llcommon/llstat.cpp
+++ /dev/null
@@ -1,404 +0,0 @@
-/**
- * @file llstat.cpp
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "llstat.h"
-#include "lllivefile.h"
-#include "llerrorcontrol.h"
-#include "llframetimer.h"
-#include "timing.h"
-#include "llsd.h"
-#include "llsdserialize.h"
-#include "llstl.h"
-#include "u64.h"
-
-
-// statics
-//------------------------------------------------------------------------
-LLTimer LLStat::sTimer;
-LLFrameTimer LLStat::sFrameTimer;
-
-void LLStat::reset()
-{
- mNumValues = 0;
- mLastValue = 0.f;
- delete[] mBins;
- mBins = new ValueEntry[mNumBins];
- mCurBin = mNumBins-1;
- mNextBin = 0;
-}
-
-LLStat::LLStat(std::string name, S32 num_bins, BOOL use_frame_timer)
-: mUseFrameTimer(use_frame_timer),
- mNumBins(num_bins),
- mName(name),
- mBins(NULL)
-{
- llassert(mNumBins > 0);
- mLastTime = 0.f;
-
- reset();
-
- if (!mName.empty())
- {
- stat_map_t::iterator iter = getStatList().find(mName);
- if (iter != getStatList().end())
- llwarns << "LLStat with duplicate name: " << mName << llendl;
- getStatList().insert(std::make_pair(mName, this));
- }
-}
-
-LLStat::stat_map_t& LLStat::getStatList()
-{
- static LLStat::stat_map_t stat_list;
- return stat_list;
-}
-
-
-LLStat::~LLStat()
-{
- delete[] mBins;
-
- if (!mName.empty())
- {
- // handle multiple entries with the same name
- stat_map_t::iterator iter = getStatList().find(mName);
- while (iter != getStatList().end() && iter->second != this)
- ++iter;
- getStatList().erase(iter);
- }
-}
-
-void LLStat::start()
-{
- if (mUseFrameTimer)
- {
- mBins[mNextBin].mBeginTime = sFrameTimer.getElapsedSeconds();
- }
- else
- {
- mBins[mNextBin].mBeginTime = sTimer.getElapsedTimeF64();
- }
-}
-
-void LLStat::addValue(const F32 value)
-{
- if (mNumValues < mNumBins)
- {
- mNumValues++;
- }
-
- // Increment the bin counters.
- mCurBin++;
- if (mCurBin >= mNumBins)
- {
- mCurBin = 0;
- }
- mNextBin++;
- if (mNextBin >= mNumBins)
- {
- mNextBin = 0;
- }
-
- mBins[mCurBin].mValue = value;
- if (mUseFrameTimer)
- {
- mBins[mCurBin].mTime = sFrameTimer.getElapsedSeconds();
- }
- else
- {
- mBins[mCurBin].mTime = sTimer.getElapsedTimeF64();
- }
- mBins[mCurBin].mDT = (F32)(mBins[mCurBin].mTime - mBins[mCurBin].mBeginTime);
-
- //this value is used to prime the min/max calls
- mLastTime = mBins[mCurBin].mTime;
- mLastValue = value;
-
- // Set the begin time for the next stat segment.
- mBins[mNextBin].mBeginTime = mBins[mCurBin].mTime;
- mBins[mNextBin].mTime = mBins[mCurBin].mTime;
- mBins[mNextBin].mDT = 0.f;
-}
-
-
-F32 LLStat::getMax() const
-{
- S32 i;
- F32 current_max = mLastValue;
- if (mNumBins == 0)
- {
- current_max = 0.f;
- }
- else
- {
- for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
- {
- // Skip the bin we're currently filling.
- if (i == mNextBin)
- {
- continue;
- }
- if (mBins[i].mValue > current_max)
- {
- current_max = mBins[i].mValue;
- }
- }
- }
- return current_max;
-}
-
-F32 LLStat::getMean() const
-{
- S32 i;
- F32 current_mean = 0.f;
- S32 samples = 0;
- for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
- {
- // Skip the bin we're currently filling.
- if (i == mNextBin)
- {
- continue;
- }
- current_mean += mBins[i].mValue;
- samples++;
- }
-
- // There will be a wrap error at 2^32. :)
- if (samples != 0)
- {
- current_mean /= samples;
- }
- else
- {
- current_mean = 0.f;
- }
- return current_mean;
-}
-
-F32 LLStat::getMin() const
-{
- S32 i;
- F32 current_min = mLastValue;
-
- if (mNumBins == 0)
- {
- current_min = 0.f;
- }
- else
- {
- for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
- {
- // Skip the bin we're currently filling.
- if (i == mNextBin)
- {
- continue;
- }
- if (mBins[i].mValue < current_min)
- {
- current_min = mBins[i].mValue;
- }
- }
- }
- return current_min;
-}
-
-F32 LLStat::getPrev(S32 age) const
-{
- S32 bin;
- bin = mCurBin - age;
-
- while (bin < 0)
- {
- bin += mNumBins;
- }
-
- if (bin == mNextBin)
- {
- // Bogus for bin we're currently working on.
- return 0.f;
- }
- return mBins[bin].mValue;
-}
-
-F32 LLStat::getPrevPerSec(S32 age) const
-{
- S32 bin;
- bin = mCurBin - age;
-
- while (bin < 0)
- {
- bin += mNumBins;
- }
-
- if (bin == mNextBin)
- {
- // Bogus for bin we're currently working on.
- return 0.f;
- }
- return mBins[bin].mValue / mBins[bin].mDT;
-}
-
-F32 LLStat::getCurrent() const
-{
- return mBins[mCurBin].mValue;
-}
-
-F32 LLStat::getCurrentPerSec() const
-{
- return mBins[mCurBin].mValue / mBins[mCurBin].mDT;
-}
-
-F32 LLStat::getMeanPerSec() const
-{
- S32 i;
- F32 value = 0.f;
- F32 dt = 0.f;
-
- for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
- {
- // Skip the bin we're currently filling.
- if (i == mNextBin)
- {
- continue;
- }
- value += mBins[i].mValue;
- dt += mBins[i].mDT;
- }
-
- if (dt > 0.f)
- {
- return value/dt;
- }
- else
- {
- return 0.f;
- }
-}
-
-F32 LLStat::getMeanDuration() const
-{
- F32 dur = 0.0f;
- S32 count = 0;
- for (S32 i=0; (i < mNumBins) && (i < mNumValues); i++)
- {
- if (i == mNextBin)
- {
- continue;
- }
- dur += mBins[i].mDT;
- count++;
- }
-
- if (count > 0)
- {
- dur /= F32(count);
- return dur;
- }
- else
- {
- return 0.f;
- }
-}
-
-F32 LLStat::getMaxPerSec() const
-{
- F32 value;
-
- if (mNextBin != 0)
- {
- value = mBins[0].mValue/mBins[0].mDT;
- }
- else if (mNumValues > 0)
- {
- value = mBins[1].mValue/mBins[1].mDT;
- }
- else
- {
- value = 0.f;
- }
-
- for (S32 i = 0; (i < mNumBins) && (i < mNumValues); i++)
- {
- // Skip the bin we're currently filling.
- if (i == mNextBin)
- {
- continue;
- }
- value = llmax(value, mBins[i].mValue/mBins[i].mDT);
- }
- return value;
-}
-
-F32 LLStat::getMinPerSec() const
-{
- S32 i;
- F32 value;
-
- if (mNextBin != 0)
- {
- value = mBins[0].mValue/mBins[0].mDT;
- }
- else if (mNumValues > 0)
- {
- value = mBins[1].mValue/mBins[0].mDT;
- }
- else
- {
- value = 0.f;
- }
-
- for (i = 0; (i < mNumBins) && (i < mNumValues); i++)
- {
- // Skip the bin we're currently filling.
- if (i == mNextBin)
- {
- continue;
- }
- value = llmin(value, mBins[i].mValue/mBins[i].mDT);
- }
- return value;
-}
-
-U32 LLStat::getNumValues() const
-{
- return mNumValues;
-}
-
-S32 LLStat::getNumBins() const
-{
- return mNumBins;
-}
-
-S32 LLStat::getNextBin() const
-{
- return mNextBin;
-}
-
-F64 LLStat::getLastTime() const
-{
- return mLastTime;
-}
diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h
deleted file mode 100755
index 38377a010b..0000000000
--- a/indra/llcommon/llstat.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * @file llstat.h
- * @brief Runtime statistics accumulation.
- *
- * $LicenseInfo:firstyear=2001&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLSTAT_H
-#define LL_LLSTAT_H
-
-#include <map>
-
-#include "lltimer.h"
-#include "llframetimer.h"
-
-class LLSD;
-
-// ----------------------------------------------------------------------------
-class LL_COMMON_API LLStat
-{
-private:
- typedef std::multimap<std::string, LLStat*> stat_map_t;
-
- static stat_map_t& getStatList();
-
-public:
- LLStat(std::string name = std::string(), S32 num_bins = 32, BOOL use_frame_timer = FALSE);
- ~LLStat();
-
- void start(); // Start the timer for the current "frame", otherwise uses the time tracked from
- // the last addValue
- void reset();
- void addValue(const F32 value = 1.f); // Adds the current value being tracked, and tracks the DT.
- void addValue(const S32 value) { addValue((F32)value); }
- void addValue(const U32 value) { addValue((F32)value); }
-
- S32 getNextBin() const;
-
- F32 getPrev(S32 age) const; // Age is how many "addValues" previously - zero is current
- F32 getPrevPerSec(S32 age) const; // Age is how many "addValues" previously - zero is current
- F32 getCurrent() const;
- F32 getCurrentPerSec() const;
-
- F32 getMin() const;
- F32 getMinPerSec() const;
- F32 getMean() const;
- F32 getMeanPerSec() const;
- F32 getMeanDuration() const;
- F32 getMax() const;
- F32 getMaxPerSec() const;
-
- U32 getNumValues() const;
- S32 getNumBins() const;
-
- F64 getLastTime() const;
-private:
- BOOL mUseFrameTimer;
- U32 mNumValues;
- U32 mNumBins;
- F32 mLastValue;
- F64 mLastTime;
-
- struct ValueEntry
- {
- ValueEntry()
- : mValue(0.f),
- mBeginTime(0.0),
- mTime(0.0),
- mDT(0.f)
- {}
- F32 mValue;
- F64 mBeginTime;
- F64 mTime;
- F32 mDT;
- };
- ValueEntry* mBins;
- S32 mCurBin;
- S32 mNextBin;
-
- std::string mName;
-
- static LLTimer sTimer;
- static LLFrameTimer sFrameTimer;
-
-public:
- static LLStat* getStat(const std::string& name)
- {
- // return the first stat that matches 'name'
- stat_map_t::iterator iter = getStatList().find(name);
- if (iter != getStatList().end())
- return iter->second;
- else
- return NULL;
- }
-};
-
-#endif // LL_STAT_
diff --git a/indra/llcommon/llstatenums.h b/indra/llcommon/llstatenums.h
index 81c4085d16..6515a3e3cb 100755..100644
--- a/indra/llcommon/llstatenums.h
+++ b/indra/llcommon/llstatenums.h
@@ -26,50 +26,6 @@
#ifndef LL_LLSTATENUMS_H
#define LL_LLSTATENUMS_H
-enum
-{
- LL_SIM_STAT_TIME_DILATION = 0,
- LL_SIM_STAT_FPS = 1,
- LL_SIM_STAT_PHYSFPS = 2,
- LL_SIM_STAT_AGENTUPS = 3,
- LL_SIM_STAT_FRAMEMS = 4,
- LL_SIM_STAT_NETMS = 5,
- LL_SIM_STAT_SIMOTHERMS = 6,
- LL_SIM_STAT_SIMPHYSICSMS = 7,
- LL_SIM_STAT_AGENTMS = 8,
- LL_SIM_STAT_IMAGESMS = 9,
- LL_SIM_STAT_SCRIPTMS = 10,
- LL_SIM_STAT_NUMTASKS = 11,
- LL_SIM_STAT_NUMTASKSACTIVE = 12,
- LL_SIM_STAT_NUMAGENTMAIN = 13,
- LL_SIM_STAT_NUMAGENTCHILD = 14,
- LL_SIM_STAT_NUMSCRIPTSACTIVE = 15,
- LL_SIM_STAT_LSLIPS = 16,
- LL_SIM_STAT_INPPS = 17,
- LL_SIM_STAT_OUTPPS = 18,
- LL_SIM_STAT_PENDING_DOWNLOADS = 19,
- LL_SIM_STAT_PENDING_UPLOADS = 20,
- LL_SIM_STAT_VIRTUAL_SIZE_KB = 21,
- LL_SIM_STAT_RESIDENT_SIZE_KB = 22,
- LL_SIM_STAT_PENDING_LOCAL_UPLOADS = 23,
- LL_SIM_STAT_TOTAL_UNACKED_BYTES = 24,
- LL_SIM_STAT_PHYSICS_PINNED_TASKS = 25,
- LL_SIM_STAT_PHYSICS_LOD_TASKS = 26,
- LL_SIM_STAT_SIMPHYSICSSTEPMS = 27,
- LL_SIM_STAT_SIMPHYSICSSHAPEMS = 28,
- LL_SIM_STAT_SIMPHYSICSOTHERMS = 29,
- LL_SIM_STAT_SIMPHYSICSMEMORY = 30,
- LL_SIM_STAT_SCRIPT_EPS = 31,
- LL_SIM_STAT_SIMSPARETIME = 32,
- LL_SIM_STAT_SIMSLEEPTIME = 33,
- LL_SIM_STAT_IOPUMPTIME = 34,
- LL_SIM_STAT_PCTSCRIPTSRUN = 35,
- LL_SIM_STAT_REGION_IDLE = 36, // dataserver only
- LL_SIM_STAT_REGION_IDLE_POSSIBLE = 37, // dataserver only
- LL_SIM_STAT_SIMAISTEPTIMEMS = 38,
- LL_SIM_STAT_SKIPPEDAISILSTEPS_PS = 39,
- LL_SIM_STAT_PCTSTEPPEDCHARACTERS = 40
-};
#endif
diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h
index 0a39288f5a..02f10fa2ba 100755
--- a/indra/llcommon/llstl.h
+++ b/indra/llcommon/llstl.h
@@ -31,8 +31,8 @@
#include <algorithm>
#include <map>
#include <vector>
+#include <list>
#include <set>
-#include <deque>
#include <typeinfo>
// Use to compare the first element only of a pair
@@ -125,7 +125,7 @@ struct DeletePairedPointerArray
// compiler, the second unary_function template parameter can be set
// to void.
//
-// Here's a snippit showing how you use this object:
+// Here's a snippet showing how you use this object:
//
// typedef std::map<int, widget*> map_type;
// map_type widget_map;
@@ -170,6 +170,49 @@ struct CopyNewPointer
}
};
+template<typename T, typename ALLOC>
+void delete_and_clear(std::list<T*, ALLOC>& list)
+{
+ std::for_each(list.begin(), list.end(), DeletePointer());
+ list.clear();
+}
+
+template<typename T, typename ALLOC>
+void delete_and_clear(std::vector<T*, ALLOC>& vector)
+{
+ std::for_each(vector.begin(), vector.end(), DeletePointer());
+ vector.clear();
+}
+
+template<typename T, typename COMPARE, typename ALLOC>
+void delete_and_clear(std::set<T*, COMPARE, ALLOC>& set)
+{
+ std::for_each(set.begin(), set.end(), DeletePointer());
+ set.clear();
+}
+
+template<typename K, typename V, typename COMPARE, typename ALLOC>
+void delete_and_clear(std::map<K, V*, COMPARE, ALLOC>& map)
+{
+ std::for_each(map.begin(), map.end(), DeletePairedPointer());
+ map.clear();
+}
+
+template<typename T>
+void delete_and_clear(T*& ptr)
+{
+ delete ptr;
+ ptr = NULL;
+}
+
+
+template<typename T>
+void delete_and_clear_array(T*& ptr)
+{
+ delete[] ptr;
+ ptr = NULL;
+}
+
// Simple function to help with finding pointers in maps.
// For example:
// typedef map_t;
@@ -229,7 +272,6 @@ inline T get_if_there(const std::map<K,T>& inmap, const K& key, T default_value)
}
};
-// Useful for replacing the removeObj() functionality of LLDynamicArray
// Example:
// for (std::vector<T>::iterator iter = mList.begin(); iter != mList.end(); )
// {
@@ -238,8 +280,8 @@ inline T get_if_there(const std::map<K,T>& inmap, const K& key, T default_value)
// else
// ++iter;
// }
-template <typename T, typename Iter>
-inline Iter vector_replace_with_last(std::vector<T>& invec, Iter iter)
+template <typename T>
+inline typename std::vector<T>::iterator vector_replace_with_last(std::vector<T>& invec, typename std::vector<T>::iterator iter)
{
typename std::vector<T>::iterator last = invec.end(); --last;
if (iter == invec.end())
@@ -259,7 +301,6 @@ inline Iter vector_replace_with_last(std::vector<T>& invec, Iter iter)
}
};
-// Useful for replacing the removeObj() functionality of LLDynamicArray
// Example:
// vector_replace_with_last(mList, x);
template <typename T>
@@ -522,4 +563,151 @@ namespace std
};
} // std
+
+/**
+ * Implementation for ll_template_cast() (q.v.).
+ *
+ * Default implementation: trying to cast two completely unrelated types
+ * returns 0. Typically you'd specify T and U as pointer types, but in fact T
+ * can be any type that can be initialized with 0.
+ */
+template <typename T, typename U>
+struct ll_template_cast_impl
+{
+ T operator()(U)
+ {
+ return 0;
+ }
+};
+
+/**
+ * ll_template_cast<T>(some_value) is for use in a template function when
+ * some_value might be of arbitrary type, but you want to recognize type T
+ * specially.
+ *
+ * It's designed for use with pointer types. Example:
+ * @code
+ * struct SpecialClass
+ * {
+ * void someMethod(const std::string&) const;
+ * };
+ *
+ * template <class REALCLASS>
+ * void somefunc(const REALCLASS& instance)
+ * {
+ * const SpecialClass* ptr = ll_template_cast<const SpecialClass*>(&instance);
+ * if (ptr)
+ * {
+ * ptr->someMethod("Call method only available on SpecialClass");
+ * }
+ * }
+ * @endcode
+ *
+ * Why is this better than dynamic_cast<>? Because unless OtherClass is
+ * polymorphic, the following won't even compile (gcc 4.0.1):
+ * @code
+ * OtherClass other;
+ * SpecialClass* ptr = dynamic_cast<SpecialClass*>(&other);
+ * @endcode
+ * to say nothing of this:
+ * @code
+ * void function(int);
+ * SpecialClass* ptr = dynamic_cast<SpecialClass*>(&function);
+ * @endcode
+ * ll_template_cast handles these kinds of cases by returning 0.
+ */
+template <typename T, typename U>
+T ll_template_cast(U value)
+{
+ return ll_template_cast_impl<T, U>()(value);
+}
+
+/**
+ * Implementation for ll_template_cast() (q.v.).
+ *
+ * Implementation for identical types: return same value.
+ */
+template <typename T>
+struct ll_template_cast_impl<T, T>
+{
+ T operator()(T value)
+ {
+ return value;
+ }
+};
+
+/**
+ * LL_TEMPLATE_CONVERTIBLE(dest, source) asserts that, for a value @c s of
+ * type @c source, <tt>ll_template_cast<dest>(s)</tt> will return @c s --
+ * presuming that @c source can be converted to @c dest by the normal rules of
+ * C++.
+ *
+ * By default, <tt>ll_template_cast<dest>(s)</tt> will return 0 unless @c s's
+ * type is literally identical to @c dest. (This is because of the
+ * straightforward application of template specialization rules.) That can
+ * lead to surprising results, e.g.:
+ *
+ * @code
+ * Foo myFoo;
+ * const Foo* fooptr = ll_template_cast<const Foo*>(&myFoo);
+ * @endcode
+ *
+ * Here @c fooptr will be 0 because <tt>&myFoo</tt> is of type <tt>Foo*</tt>
+ * -- @em not <tt>const Foo*</tt>. (Declaring <tt>const Foo myFoo;</tt> would
+ * force the compiler to do the right thing.)
+ *
+ * More disappointingly:
+ * @code
+ * struct Base {};
+ * struct Subclass: public Base {};
+ * Subclass object;
+ * Base* ptr = ll_template_cast<Base*>(&object);
+ * @endcode
+ *
+ * Here @c ptr will be 0 because <tt>&object</tt> is of type
+ * <tt>Subclass*</tt> rather than <tt>Base*</tt>. We @em want this cast to
+ * succeed, but without our help ll_template_cast can't recognize it.
+ *
+ * The following would suffice:
+ * @code
+ * LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
+ * ...
+ * Base* ptr = ll_template_cast<Base*>(&object);
+ * @endcode
+ *
+ * However, as noted earlier, this is easily fooled:
+ * @code
+ * const Base* ptr = ll_template_cast<const Base*>(&object);
+ * @endcode
+ * would still produce 0 because we haven't yet seen:
+ * @code
+ * LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
+ * @endcode
+ *
+ * @TODO
+ * This macro should use Boost type_traits facilities for stripping and
+ * re-adding @c const and @c volatile qualifiers so that invoking
+ * LL_TEMPLATE_CONVERTIBLE(dest, source) will automatically generate all
+ * permitted permutations. It's really not fair to the coder to require
+ * separate:
+ * @code
+ * LL_TEMPLATE_CONVERTIBLE(Base*, Subclass*);
+ * LL_TEMPLATE_CONVERTIBLE(const Base*, Subclass*);
+ * LL_TEMPLATE_CONVERTIBLE(const Base*, const Subclass*);
+ * @endcode
+ *
+ * (Naturally we omit <tt>LL_TEMPLATE_CONVERTIBLE(Base*, const Subclass*)</tt>
+ * because that's not permitted by normal C++ assignment anyway.)
+ */
+#define LL_TEMPLATE_CONVERTIBLE(DEST, SOURCE) \
+template <> \
+struct ll_template_cast_impl<DEST, SOURCE> \
+{ \
+ DEST operator()(SOURCE wrapper) \
+ { \
+ return wrapper; \
+ } \
+}
+
+
#endif // LL_LLSTL_H
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index 22c8681983..76979f29f6 100755
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -28,15 +28,15 @@
#include "llstring.h"
#include "llerror.h"
+#include "llfasttimer.h"
+#include "llsd.h"
#if LL_WINDOWS
-#define WIN32_LEAN_AND_MEAN
-#include <winsock2.h>
-#include <windows.h>
+#include "llwin32headerslean.h"
#include <winnls.h> // for WideCharToMultiByte
#endif
-LLFastTimer::DeclareTimer FT_STRING_FORMAT("String Format");
+LLTrace::BlockTimerStatHandle FT_STRING_FORMAT("String Format");
std::string ll_safe_string(const char* in)
@@ -110,7 +110,7 @@ bool _read_file_into_string(std::string& str, const std::string& filename)
llifstream ifs(filename, llifstream::binary);
if (!ifs.is_open())
{
- llinfos << "Unable to open file " << filename << llendl;
+ LL_INFOS() << "Unable to open file " << filename << LL_ENDL;
return false;
}
@@ -188,7 +188,7 @@ S32 wchar_to_utf8chars(llwchar in_char, char* outchars)
}
else
{
- llwarns << "Invalid Unicode character " << cur_char << "!" << llendl;
+ LL_WARNS() << "Invalid Unicode character " << cur_char << "!" << LL_ENDL;
*outchars++ = LL_UNKNOWN_CHAR;
}
return outchars - base;
@@ -1195,7 +1195,7 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,
template<>
S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions)
{
- LLFastTimer ft(FT_STRING_FORMAT);
+ LL_RECORD_BLOCK_TIME(FT_STRING_FORMAT);
S32 res = 0;
std::string output;
@@ -1268,7 +1268,7 @@ S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions)
template<>
S32 LLStringUtil::format(std::string& s, const LLSD& substitutions)
{
- LLFastTimer ft(FT_STRING_FORMAT);
+ LL_RECORD_BLOCK_TIME(FT_STRING_FORMAT);
S32 res = 0;
if (!substitutions.isMap())
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index f9702868c8..0177f48bf5 100755
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -29,10 +29,12 @@
#include <string>
#include <cstdio>
-#include <locale>
+//#include <locale>
#include <iomanip>
-#include "llsd.h"
-#include "llfasttimer.h"
+#include <algorithm>
+#include <vector>
+#include <map>
+#include "llformat.h"
#if LL_LINUX || LL_SOLARIS
#include <wctype.h>
@@ -49,6 +51,7 @@
#endif
const char LL_UNKNOWN_CHAR = '?';
+class LLSD;
#if LL_DARWIN || LL_LINUX || LL_SOLARIS
// Template specialization of char_traits for U16s. Only necessary on Mac and Linux (exists on Windows already)
@@ -518,10 +521,13 @@ LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len);
LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str);
-
LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len);
LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str);
+#if LL_WINDOWS
+inline std::string wstring_to_utf8str(const llutf16string &utf16str) { return utf16str_to_utf8str(utf16str);}
+#endif
+
// Length of this UTF32 string in bytes when transformed to UTF8
LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr);
diff --git a/indra/llcommon/llstringtable.cpp b/indra/llcommon/llstringtable.cpp
index 7ad3805351..f288999964 100755
--- a/indra/llcommon/llstringtable.cpp
+++ b/indra/llcommon/llstringtable.cpp
@@ -317,7 +317,7 @@ void LLStringTable::removeString(const char *str)
mUniqueEntries--;
if (mUniqueEntries < 0)
{
- llerror("LLStringTable:removeString trying to remove too many strings!", 0);
+ LL_ERRS() << "LLStringTable:removeString trying to remove too many strings!" << LL_ENDL;
}
delete iter->second;
mStringHash.erase(iter);
@@ -343,7 +343,7 @@ void LLStringTable::removeString(const char *str)
mUniqueEntries--;
if (mUniqueEntries < 0)
{
- llerror("LLStringTable:removeString trying to remove too many strings!", 0);
+ LL_ERRS() << "LLStringTable:removeString trying to remove too many strings!" << LL_ENDL;
}
strlist->remove(entry);
delete entry;
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index e63045659e..07fe259e47 100755
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -42,6 +42,7 @@
#include "llprocessor.h"
#include "llerrorcontrol.h"
#include "llevents.h"
+#include "llformat.h"
#include "lltimer.h"
#include "llsdserialize.h"
#include "llsdutil.h"
@@ -58,9 +59,7 @@
using namespace llsd;
#if LL_WINDOWS
-# define WIN32_LEAN_AND_MEAN
-# include <winsock2.h>
-# include <windows.h>
+# include "llwin32headerslean.h"
# include <psapi.h> // GetPerformanceInfo() et al.
#elif LL_DARWIN
# include <errno.h>
@@ -645,7 +644,7 @@ S32 LLOSInfo::getMaxOpenFiles()
}
else
{
- llerrs << "LLOSInfo::getMaxOpenFiles: sysconf error for _SC_OPEN_MAX" << llendl;
+ LL_ERRS() << "LLOSInfo::getMaxOpenFiles: sysconf error for _SC_OPEN_MAX" << LL_ENDL;
}
}
}
@@ -704,12 +703,12 @@ U32 LLOSInfo::getProcessVirtualSizeKB()
sprintf(proc_ps, "/proc/%d/psinfo", (int)getpid());
int proc_fd = -1;
if((proc_fd = open(proc_ps, O_RDONLY)) == -1){
- llwarns << "unable to open " << proc_ps << llendl;
+ LL_WARNS() << "unable to open " << proc_ps << LL_ENDL;
return 0;
}
psinfo_t proc_psinfo;
if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
- llwarns << "Unable to read " << proc_ps << llendl;
+ LL_WARNS() << "Unable to read " << proc_ps << LL_ENDL;
close(proc_fd);
return 0;
}
@@ -750,12 +749,12 @@ U32 LLOSInfo::getProcessResidentSizeKB()
sprintf(proc_ps, "/proc/%d/psinfo", (int)getpid());
int proc_fd = -1;
if((proc_fd = open(proc_ps, O_RDONLY)) == -1){
- llwarns << "unable to open " << proc_ps << llendl;
+ LL_WARNS() << "unable to open " << proc_ps << LL_ENDL;
return 0;
}
psinfo_t proc_psinfo;
if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
- llwarns << "Unable to read " << proc_ps << llendl;
+ LL_WARNS() << "Unable to read " << proc_ps << LL_ENDL;
close(proc_fd);
return 0;
}
@@ -870,7 +869,7 @@ LLMemoryInfo::LLMemoryInfo()
}
#if LL_WINDOWS
-static U32 LLMemoryAdjustKBResult(U32 inKB)
+static U32Kilobytes LLMemoryAdjustKBResult(U32Kilobytes inKB)
{
// Moved this here from llfloaterabout.cpp
@@ -881,16 +880,16 @@ static U32 LLMemoryAdjustKBResult(U32 inKB)
// returned from the GetMemoryStatusEx function. Here we keep the
// original adjustment from llfoaterabout.cpp until this can be
// fixed somehow.
- inKB += 1024;
+ inKB += U32Megabytes(1);
return inKB;
}
#endif
-U32 LLMemoryInfo::getPhysicalMemoryKB() const
+U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
{
#if LL_WINDOWS
- return LLMemoryAdjustKBResult(mStatsMap["Total Physical KB"].asInteger());
+ return LLMemoryAdjustKBResult(U32Kilobytes(mStatsMap["Total Physical KB"].asInteger()));
#elif LL_DARWIN
// This might work on Linux as well. Someone check...
@@ -900,17 +899,17 @@ U32 LLMemoryInfo::getPhysicalMemoryKB() const
size_t len = sizeof(phys);
sysctl(mib, 2, &phys, &len, NULL, 0);
- return (U32)(phys >> 10);
+ return U64Bytes(phys);
#elif LL_LINUX
U64 phys = 0;
phys = (U64)(getpagesize()) * (U64)(get_phys_pages());
- return (U32)(phys >> 10);
+ return U64Bytes(phys);
#elif LL_SOLARIS
U64 phys = 0;
phys = (U64)(getpagesize()) * (U64)(sysconf(_SC_PHYS_PAGES));
- return (U32)(phys >> 10);
+ return U64Bytes(phys);
#else
return 0;
@@ -918,32 +917,32 @@ U32 LLMemoryInfo::getPhysicalMemoryKB() const
#endif
}
-U32 LLMemoryInfo::getPhysicalMemoryClamped() const
+U32Bytes LLMemoryInfo::getPhysicalMemoryClamped() const
{
// Return the total physical memory in bytes, but clamp it
// to no more than U32_MAX
- U32 phys_kb = getPhysicalMemoryKB();
- if (phys_kb >= 4194304 /* 4GB in KB */)
+ U32Kilobytes phys_kb = getPhysicalMemoryKB();
+ if (phys_kb >= U32Gigabytes(4))
{
- return U32_MAX;
+ return U32Bytes(U32_MAX);
}
else
{
- return phys_kb << 10;
+ return phys_kb;
}
}
//static
-void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb)
+void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb)
{
#if LL_WINDOWS
// Sigh, this shouldn't be a static method, then we wouldn't have to
// reload this data separately from refresh()
LLSD statsMap(loadStatsMap());
- avail_physical_mem_kb = statsMap["Avail Physical KB"].asInteger();
- avail_virtual_mem_kb = statsMap["Avail Virtual KB"].asInteger();
+ avail_physical_mem_kb = (U32Kilobytes)statsMap["Avail Physical KB"].asInteger();
+ avail_virtual_mem_kb = (U32Kilobytes)statsMap["Avail Virtual KB"].asInteger();
#elif LL_DARWIN
// mStatsMap is derived from vm_stat, look for (e.g.) "kb free":
@@ -960,8 +959,8 @@ void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_v
// Pageins: 2097212.
// Pageouts: 41759.
// Object cache: 841598 hits of 7629869 lookups (11% hit rate)
- avail_physical_mem_kb = -1 ;
- avail_virtual_mem_kb = -1 ;
+ avail_physical_mem_kb = (U32Kilobytes)-1 ;
+ avail_virtual_mem_kb = (U32Kilobytes)-1 ;
#elif LL_LINUX
// mStatsMap is derived from MEMINFO_FILE:
@@ -1012,15 +1011,15 @@ void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_v
// DirectMap4k: 434168 kB
// DirectMap2M: 477184 kB
// (could also run 'free', but easier to read a file than run a program)
- avail_physical_mem_kb = -1 ;
- avail_virtual_mem_kb = -1 ;
+ avail_physical_mem_kb = (U32Kilobytes)-1 ;
+ avail_virtual_mem_kb = (U32Kilobytes)-1 ;
#else
//do not know how to collect available memory info for other systems.
//leave it blank here for now.
- avail_physical_mem_kb = -1 ;
- avail_virtual_mem_kb = -1 ;
+ avail_physical_mem_kb = (U32Kilobytes)-1 ;
+ avail_virtual_mem_kb = (U32Kilobytes)-1 ;
#endif
}
@@ -1433,9 +1432,14 @@ public:
LL_CONT << "slowest framerate for last " << int(prevSize * MEM_INFO_THROTTLE)
<< " seconds ";
}
+
+ S32 precision = LL_CONT.precision();
+
LL_CONT << std::fixed << std::setprecision(1) << framerate << '\n'
- << LLMemoryInfo() << LL_ENDL;
+ << LLMemoryInfo();
+ LL_CONT.precision(precision);
+ LL_CONT << LL_ENDL;
return false;
}
@@ -1482,7 +1486,7 @@ BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile)
size_t nwrit = fwrite(buffer, sizeof(U8), bytes, dst);
if (nwrit < (size_t) bytes)
{
- llwarns << "Short write on " << tmpfile << ": Wrote " << nwrit << " of " << bytes << " bytes." << llendl;
+ LL_WARNS() << "Short write on " << tmpfile << ": Wrote " << nwrit << " of " << bytes << " bytes." << LL_ENDL;
goto err;
}
} while(gzeof(src) == 0);
@@ -1515,14 +1519,14 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile)
{
if (gzwrite(dst, buffer, bytes) <= 0)
{
- llwarns << "gzwrite failed: " << gzerror(dst, NULL) << llendl;
+ LL_WARNS() << "gzwrite failed: " << gzerror(dst, NULL) << LL_ENDL;
goto err;
}
}
if (ferror(src))
{
- llwarns << "Error reading " << srcfile << llendl;
+ LL_WARNS() << "Error reading " << srcfile << LL_ENDL;
goto err;
}
diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h
index cfed0fff17..962367f69f 100755
--- a/indra/llcommon/llsys.h
+++ b/indra/llcommon/llsys.h
@@ -33,7 +33,7 @@
// use an LLCPUInfo object:
//
// LLCPUInfo info;
-// llinfos << info << llendl;
+// LL_INFOS() << info << LL_ENDL;
//
#include "llsd.h"
@@ -105,22 +105,22 @@ class LL_COMMON_API LLMemoryInfo
Here's how you use an LLMemoryInfo:
LLMemoryInfo info;
-<br> llinfos << info << llendl;
+<br> LL_INFOS() << info << LL_ENDL;
*/
{
public:
LLMemoryInfo(); ///< Default constructor
void stream(std::ostream& s) const; ///< output text info to s
- U32 getPhysicalMemoryKB() const; ///< Memory size in KiloBytes
+ U32Kilobytes getPhysicalMemoryKB() const;
/*! Memory size in bytes, if total memory is >= 4GB then U32_MAX will
** be returned.
*/
- U32 getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
+ U32Bytes getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
//get the available memory infomation in KiloBytes.
- static void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb);
+ static void getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb);
// Retrieve a map of memory statistics. The keys of the map are platform-
// dependent. The values are in kilobytes to try to avoid integer overflow.
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index e67d1bc57b..51c89e1eaf 100755
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -29,13 +29,49 @@
#include "apr_portable.h"
#include "llthread.h"
+#include "llmutex.h"
#include "lltimer.h"
+#include "lltrace.h"
+#include "lltracethreadrecorder.h"
#if LL_LINUX || LL_SOLARIS
#include <sched.h>
#endif
+
+#ifdef LL_WINDOWS
+const DWORD MS_VC_EXCEPTION=0x406D1388;
+
+#pragma pack(push,8)
+typedef struct tagTHREADNAME_INFO
+{
+ DWORD dwType; // Must be 0x1000.
+ LPCSTR szName; // Pointer to name (in user addr space).
+ DWORD dwThreadID; // Thread ID (-1=caller thread).
+ DWORD dwFlags; // Reserved for future use, must be zero.
+} THREADNAME_INFO;
+#pragma pack(pop)
+
+void set_thread_name( DWORD dwThreadID, const char* threadName)
+{
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = threadName;
+ info.dwThreadID = dwThreadID;
+ info.dwFlags = 0;
+
+ __try
+ {
+ ::RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (DWORD*)&info );
+ }
+ __except(EXCEPTION_CONTINUE_EXECUTION)
+ {
+ }
+}
+#endif
+
+
//----------------------------------------------------------------------------
// Usage:
// void run_func(LLThread* thread)
@@ -56,19 +92,24 @@
//
//----------------------------------------------------------------------------
-#if !LL_DARWIN
-U32 ll_thread_local sThreadID = 0;
+#if LL_DARWIN
+// statically allocated thread local storage not supported in Darwin executable formats
+#elif LL_WINDOWS
+U32 __declspec(thread) sThreadID = 0;
+#elif LL_LINUX
+U32 __thread sThreadID = 0;
#endif
U32 LLThread::sIDIter = 0;
+
LL_COMMON_API void assert_main_thread()
{
static U32 s_thread_id = LLThread::currentID();
if (LLThread::currentID() != s_thread_id)
{
- llwarns << "Illegal execution from thread id " << (S32) LLThread::currentID()
- << " outside main thread " << (S32) s_thread_id << llendl;
+ LL_WARNS() << "Illegal execution from thread id " << (S32) LLThread::currentID()
+ << " outside main thread " << (S32) s_thread_id << LL_ENDL;
}
}
@@ -86,6 +127,13 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
{
LLThread *threadp = (LLThread *)datap;
+#ifdef LL_WINDOWS
+ set_thread_name(-1, threadp->mName.c_str());
+#endif
+
+ // for now, hard code all LLThreads to report to single master thread recorder, which is known to be running on main thread
+ threadp->mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder());
+
#if !LL_DARWIN
sThreadID = threadp->mID;
#endif
@@ -93,21 +141,26 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
// Run the user supplied function
threadp->run();
- //llinfos << "LLThread::staticRun() Exiting: " << threadp->mName << llendl;
+ //LL_INFOS() << "LLThread::staticRun() Exiting: " << threadp->mName << LL_ENDL;
+
+ delete threadp->mRecorder;
+ threadp->mRecorder = NULL;
// We're done with the run function, this thread is done executing now.
+ //NB: we are using this flag to sync across threads...we really need memory barriers here
threadp->mStatus = STOPPED;
return NULL;
}
-
LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
mPaused(FALSE),
mName(name),
mAPRThreadp(NULL),
- mStatus(STOPPED)
+ mStatus(STOPPED),
+ mRecorder(NULL)
{
+
mID = ++sIDIter;
// Thread creation probably CAN be paranoid about APR being initialized, if necessary
@@ -150,10 +203,10 @@ void LLThread::shutdown()
// First, set the flag that indicates that we're ready to die
setQuitting();
- //llinfos << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << llendl;
+ //LL_INFOS() << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << LL_ENDL;
// Now wait a bit for the thread to exit
// It's unclear whether I should even bother doing this - this destructor
- // should netver get called unless we're already stopped, really...
+ // should never get called unless we're already stopped, really...
S32 counter = 0;
const S32 MAX_WAIT = 600;
while (counter < MAX_WAIT)
@@ -172,8 +225,10 @@ void LLThread::shutdown()
if (!isStopped())
{
// This thread just wouldn't stop, even though we gave it time
- //llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl;
+ //LL_WARNS() << "LLThread::~LLThread() exiting thread before clean exit!" << LL_ENDL;
// Put a stake in its heart.
+ delete mRecorder;
+
apr_thread_exit(mAPRThreadp, -1);
return;
}
@@ -191,6 +246,14 @@ void LLThread::shutdown()
apr_pool_destroy(mAPRPoolp);
mAPRPoolp = 0;
}
+
+ if (mRecorder)
+ {
+ // missed chance to properly shut down recorder (needs to be done in thread context)
+ // probably due to abnormal thread termination
+ // so just leak it and remove it from parent
+ LLTrace::get_master_thread_recorder()->removeChildRecorder(mRecorder);
+ }
}
@@ -212,9 +275,10 @@ void LLThread::start()
else
{
mStatus = STOPPED;
- llwarns << "failed to start thread " << mName << llendl;
+ LL_WARNS() << "failed to start thread " << mName << LL_ENDL;
ll_apr_warn_status(status);
}
+
}
//============================================================================
@@ -283,7 +347,13 @@ void LLThread::setQuitting()
// static
U32 LLThread::currentID()
{
+#if LL_DARWIN
+ // statically allocated thread local storage not supported in Darwin executable formats
return (U32)apr_os_thread_current();
+#else
+ return sThreadID;
+#endif
+
}
// static
@@ -316,185 +386,6 @@ void LLThread::wakeLocked()
//============================================================================
-LLMutex::LLMutex(apr_pool_t *poolp) :
- mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD)
-{
- //if (poolp)
- //{
- // mIsLocalPool = FALSE;
- // mAPRPoolp = poolp;
- //}
- //else
- {
- mIsLocalPool = TRUE;
- apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
- }
- apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
-}
-
-
-LLMutex::~LLMutex()
-{
-#if MUTEX_DEBUG
- //bad assertion, the subclass LLSignal might be "locked", and that's OK
- //llassert_always(!isLocked()); // better not be locked!
-#endif
- apr_thread_mutex_destroy(mAPRMutexp);
- mAPRMutexp = NULL;
- if (mIsLocalPool)
- {
- apr_pool_destroy(mAPRPoolp);
- }
-}
-
-
-void LLMutex::lock()
-{
- if(isSelfLocked())
- { //redundant lock
- mCount++;
- return;
- }
-
- apr_thread_mutex_lock(mAPRMutexp);
-
-#if MUTEX_DEBUG
- // Have to have the lock before we can access the debug info
- U32 id = LLThread::currentID();
- if (mIsLocked[id] != FALSE)
- llerrs << "Already locked in Thread: " << id << llendl;
- mIsLocked[id] = TRUE;
-#endif
-
-#if LL_DARWIN
- mLockingThread = LLThread::currentID();
-#else
- mLockingThread = sThreadID;
-#endif
-}
-
-bool LLMutex::trylock()
-{
- if(isSelfLocked())
- { //redundant lock
- mCount++;
- return true;
- }
-
- apr_status_t status(apr_thread_mutex_trylock(mAPRMutexp));
- if (APR_STATUS_IS_EBUSY(status))
- {
- return false;
- }
-
-#if MUTEX_DEBUG
- // Have to have the lock before we can access the debug info
- U32 id = LLThread::currentID();
- if (mIsLocked[id] != FALSE)
- llerrs << "Already locked in Thread: " << id << llendl;
- mIsLocked[id] = TRUE;
-#endif
-
-#if LL_DARWIN
- mLockingThread = LLThread::currentID();
-#else
- mLockingThread = sThreadID;
-#endif
- return true;
-}
-
-void LLMutex::unlock()
-{
- if (mCount > 0)
- { //not the root unlock
- mCount--;
- return;
- }
-
-#if MUTEX_DEBUG
- // Access the debug info while we have the lock
- U32 id = LLThread::currentID();
- if (mIsLocked[id] != TRUE)
- llerrs << "Not locked in Thread: " << id << llendl;
- mIsLocked[id] = FALSE;
-#endif
-
- mLockingThread = NO_THREAD;
- apr_thread_mutex_unlock(mAPRMutexp);
-}
-
-bool LLMutex::isLocked()
-{
- apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
- if (APR_STATUS_IS_EBUSY(status))
- {
- return true;
- }
- else
- {
- apr_thread_mutex_unlock(mAPRMutexp);
- return false;
- }
-}
-
-bool LLMutex::isSelfLocked()
-{
-#if LL_DARWIN
- return mLockingThread == LLThread::currentID();
-#else
- return mLockingThread == sThreadID;
-#endif
-}
-
-U32 LLMutex::lockingThread() const
-{
- return mLockingThread;
-}
-
-//============================================================================
-
-LLCondition::LLCondition(apr_pool_t *poolp) :
- LLMutex(poolp)
-{
- // base class (LLMutex) has already ensured that mAPRPoolp is set up.
-
- apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
-}
-
-
-LLCondition::~LLCondition()
-{
- apr_thread_cond_destroy(mAPRCondp);
- mAPRCondp = NULL;
-}
-
-
-void LLCondition::wait()
-{
- if (!isLocked())
- { //mAPRMutexp MUST be locked before calling apr_thread_cond_wait
- apr_thread_mutex_lock(mAPRMutexp);
-#if MUTEX_DEBUG
- // avoid asserts on destruction in non-release builds
- U32 id = LLThread::currentID();
- mIsLocked[id] = TRUE;
-#endif
- }
- apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
-}
-
-void LLCondition::signal()
-{
- apr_thread_cond_signal(mAPRCondp);
-}
-
-void LLCondition::broadcast()
-{
- apr_thread_cond_broadcast(mAPRCondp);
-}
-
-//============================================================================
-
//----------------------------------------------------------------------------
//static
@@ -533,11 +424,10 @@ LLThreadSafeRefCount::~LLThreadSafeRefCount()
{
if (mRef != 0)
{
- llerrs << "deleting non-zero reference" << llendl;
+ LL_ERRS() << "deleting non-zero reference" << LL_ENDL;
}
}
-
//============================================================================
LLResponder::~LLResponder()
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 8c7143304f..6f9ec10fd3 100755
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -31,20 +31,20 @@
#include "llapr.h"
#include "apr_thread_cond.h"
#include "boost/intrusive_ptr.hpp"
+#include "llmutex.h"
+#include "llrefcount.h"
-class LLThread;
-class LLMutex;
-class LLCondition;
+LL_COMMON_API void assert_main_thread();
-#if LL_WINDOWS
-#define ll_thread_local __declspec(thread)
-#else
-#define ll_thread_local __thread
-#endif
+namespace LLTrace
+{
+ class ThreadRecorder;
+}
class LL_COMMON_API LLThread
{
private:
+ friend class LLMutex;
static U32 sIDIter;
public:
@@ -98,11 +98,11 @@ private:
BOOL mPaused;
// static function passed to APR thread creation routine
- static void *APR_THREAD_FUNC staticRun(apr_thread_t *apr_threadp, void *datap);
+ static void *APR_THREAD_FUNC staticRun(struct apr_thread_t *apr_threadp, void *datap);
protected:
std::string mName;
- LLCondition* mRunCondition;
+ class LLCondition* mRunCondition;
LLMutex* mDataLock;
apr_thread_t *mAPRThreadp;
@@ -110,6 +110,7 @@ protected:
BOOL mIsLocalPool;
EThreadStatus mStatus;
U32 mID;
+ LLTrace::ThreadRecorder* mRecorder;
//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
@@ -140,117 +141,6 @@ protected:
// mDataLock->unlock();
};
-//============================================================================
-
-#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
-
-class LL_COMMON_API LLMutex
-{
-public:
- typedef enum
- {
- NO_THREAD = 0xFFFFFFFF
- } e_locking_thread;
-
- LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
- virtual ~LLMutex();
-
- void lock(); // blocks
- bool trylock(); // non-blocking, returns true if lock held.
- void unlock(); // undefined behavior when called on mutex not being held
- bool isLocked(); // non-blocking, but does do a lock/unlock so not free
- bool isSelfLocked(); //return true if locked in a same thread
- U32 lockingThread() const; //get ID of locking thread
-
-protected:
- apr_thread_mutex_t *mAPRMutexp;
- mutable U32 mCount;
- mutable U32 mLockingThread;
-
- apr_pool_t *mAPRPoolp;
- BOOL mIsLocalPool;
-
-#if MUTEX_DEBUG
- std::map<U32, BOOL> mIsLocked;
-#endif
-};
-
-//============================================================================
-
-// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
-class LL_COMMON_API LLCondition : public LLMutex
-{
-public:
- LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well.
- ~LLCondition();
-
- void wait(); // blocks
- void signal();
- void broadcast();
-
-protected:
- apr_thread_cond_t *mAPRCondp;
-};
-
-//============================================================================
-
-class LLMutexLock
-{
-public:
- LLMutexLock(LLMutex* mutex)
- {
- mMutex = mutex;
-
- if(mMutex)
- mMutex->lock();
- }
- ~LLMutexLock()
- {
- if(mMutex)
- mMutex->unlock();
- }
-private:
- LLMutex* mMutex;
-};
-
-//============================================================================
-
-// Scoped locking class similar in function to LLMutexLock but uses
-// the trylock() method to conditionally acquire lock without
-// blocking. Caller resolves the resulting condition by calling
-// the isLocked() method and either punts or continues as indicated.
-//
-// Mostly of interest to callers needing to avoid stalls who can
-// guarantee another attempt at a later time.
-
-class LLMutexTrylock
-{
-public:
- LLMutexTrylock(LLMutex* mutex)
- : mMutex(mutex),
- mLocked(false)
- {
- if (mMutex)
- mLocked = mMutex->trylock();
- }
-
- ~LLMutexTrylock()
- {
- if (mMutex && mLocked)
- mMutex->unlock();
- }
-
- bool isLocked() const
- {
- return mLocked;
- }
-
-private:
- LLMutex* mMutex;
- bool mLocked;
-};
-
-//============================================================================
void LLThread::lockData()
{
@@ -265,76 +155,6 @@ void LLThread::unlockData()
//============================================================================
-// see llmemory.h for LLPointer<> definition
-
-class LL_COMMON_API LLThreadSafeRefCount
-{
-public:
- static void initThreadSafeRefCount(); // creates sMutex
- static void cleanupThreadSafeRefCount(); // destroys sMutex
-
-private:
- static LLMutex* sMutex;
-
-protected:
- virtual ~LLThreadSafeRefCount(); // use unref()
-
-public:
- LLThreadSafeRefCount();
- LLThreadSafeRefCount(const LLThreadSafeRefCount&);
- LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref)
- {
- mRef = 0;
- return *this;
- }
-
- void ref()
- {
- mRef++;
- }
-
- void unref()
- {
- llassert(mRef >= 1);
- if ((--mRef) == 0) // See note in llapr.h on atomic decrement operator return value.
- {
- // If we hit zero, the caller should be the only smart pointer owning the object and we can delete it.
- // It is technically possible for a vanilla pointer to mess this up, or another thread to
- // jump in, find this object, create another smart pointer and end up dangling, but if
- // the code is that bad and not thread-safe, it's trouble already.
- delete this;
- }
- }
-
- S32 getNumRefs() const
- {
- const S32 currentVal = mRef.CurrentValue();
- return currentVal;
- }
-
-private:
- LLAtomic32< S32 > mRef;
-};
-
-
-/**
- * intrusive pointer support for LLThreadSafeRefCount
- * this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type
- */
-namespace boost
-{
- inline void intrusive_ptr_add_ref(LLThreadSafeRefCount* p)
- {
- p->ref();
- }
-
- inline void intrusive_ptr_release(LLThreadSafeRefCount* p)
- {
- p->unref();
- }
-};
-//============================================================================
-
// Simple responder for self destructing callbacks
// Pure virtual class
class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
diff --git a/indra/llcommon/llthreadlocalstorage.cpp b/indra/llcommon/llthreadlocalstorage.cpp
new file mode 100644
index 0000000000..8cef05caac
--- /dev/null
+++ b/indra/llcommon/llthreadlocalstorage.cpp
@@ -0,0 +1,119 @@
+/**
+ * @file llthreadlocalstorage.cpp
+ * @author Richard
+ * @date 2013-1-11
+ * @brief implementation of thread local storage utility classes
+ *
+ * $LicenseInfo:firstyear=2013&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llthreadlocalstorage.h"
+#include "llapr.h"
+
+//
+//LLThreadLocalPointerBase
+//
+bool LLThreadLocalPointerBase::sInitialized = false;
+
+void LLThreadLocalPointerBase::set( void* value )
+{
+ llassert(sInitialized && mThreadKey);
+
+ apr_status_t result = apr_threadkey_private_set((void*)value, mThreadKey);
+ if (result != APR_SUCCESS)
+ {
+ ll_apr_warn_status(result);
+ LL_ERRS() << "Failed to set thread local data" << LL_ENDL;
+ }
+}
+
+void* LLThreadLocalPointerBase::get() const
+{
+ // llassert(sInitialized);
+ void* ptr;
+ apr_status_t result =
+ apr_threadkey_private_get(&ptr, mThreadKey);
+ if (result != APR_SUCCESS)
+ {
+ ll_apr_warn_status(result);
+ LL_ERRS() << "Failed to get thread local data" << LL_ENDL;
+ }
+ return ptr;
+}
+
+
+void LLThreadLocalPointerBase::initStorage( )
+{
+ apr_status_t result = apr_threadkey_private_create(&mThreadKey, NULL, gAPRPoolp);
+ if (result != APR_SUCCESS)
+ {
+ ll_apr_warn_status(result);
+ LL_ERRS() << "Failed to allocate thread local data" << LL_ENDL;
+ }
+}
+
+void LLThreadLocalPointerBase::destroyStorage()
+{
+ if (sInitialized)
+ {
+ if (mThreadKey)
+ {
+ apr_status_t result = apr_threadkey_private_delete(mThreadKey);
+ if (result != APR_SUCCESS)
+ {
+ ll_apr_warn_status(result);
+ LL_ERRS() << "Failed to delete thread local data" << LL_ENDL;
+ }
+ }
+ }
+}
+
+//static
+void LLThreadLocalPointerBase::initAllThreadLocalStorage()
+{
+ if (!sInitialized)
+ {
+ for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances();
+ it != end_it;
+ ++it)
+ {
+ (*it).initStorage();
+ }
+ sInitialized = true;
+ }
+}
+
+//static
+void LLThreadLocalPointerBase::destroyAllThreadLocalStorage()
+{
+ if (sInitialized)
+ {
+ //for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances();
+ // it != end_it;
+ // ++it)
+ //{
+ // (*it).destroyStorage();
+ //}
+ sInitialized = false;
+ }
+}
diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h
new file mode 100644
index 0000000000..ec3b52c8cb
--- /dev/null
+++ b/indra/llcommon/llthreadlocalstorage.h
@@ -0,0 +1,185 @@
+/**
+ * @file llthreadlocalstorage.h
+ * @author Richard
+ * @brief Class wrappers for thread local storage
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTHREADLOCALSTORAGE_H
+#define LL_LLTHREADLOCALSTORAGE_H
+
+#include "llinstancetracker.h"
+
+class LLThreadLocalPointerBase : public LLInstanceTracker<LLThreadLocalPointerBase>
+{
+public:
+ LLThreadLocalPointerBase()
+ : mThreadKey(NULL)
+ {
+ if (sInitialized)
+ {
+ initStorage();
+ }
+ }
+
+ LLThreadLocalPointerBase( const LLThreadLocalPointerBase& other)
+ : mThreadKey(NULL)
+ {
+ if (sInitialized)
+ {
+ initStorage();
+ }
+ }
+
+ ~LLThreadLocalPointerBase()
+ {
+ destroyStorage();
+ }
+
+ static void initAllThreadLocalStorage();
+ static void destroyAllThreadLocalStorage();
+
+protected:
+ void set(void* value);
+
+ void* get() const;
+
+ void initStorage();
+ void destroyStorage();
+
+protected:
+ struct apr_threadkey_t* mThreadKey;
+ static bool sInitialized;
+};
+
+template <typename T>
+class LLThreadLocalPointer : public LLThreadLocalPointerBase
+{
+public:
+
+ LLThreadLocalPointer()
+ {}
+
+ explicit LLThreadLocalPointer(T* value)
+ {
+ set(value);
+ }
+
+
+ LLThreadLocalPointer(const LLThreadLocalPointer<T>& other)
+ : LLThreadLocalPointerBase(other)
+ {
+ set(other.get());
+ }
+
+ LL_FORCE_INLINE T* get() const
+ {
+ return (T*)LLThreadLocalPointerBase::get();
+ }
+
+ T* operator -> () const
+ {
+ return (T*)get();
+ }
+
+ T& operator*() const
+ {
+ return *(T*)get();
+ }
+
+ LLThreadLocalPointer<T>& operator = (T* value)
+ {
+ set((void*)value);
+ return *this;
+ }
+
+ bool operator ==(const T* other) const
+ {
+ if (!sInitialized) return false;
+ return get() == other;
+ }
+
+ bool isNull() const { return !sInitialized || get() == NULL; }
+
+ bool notNull() const { return sInitialized && get() != NULL; }
+};
+
+template<typename DERIVED_TYPE>
+class LLThreadLocalSingletonPointer
+{
+public:
+ LL_FORCE_INLINE static DERIVED_TYPE* getInstance()
+ {
+#if LL_DARWIN
+ createTLSKey();
+ return (DERIVED_TYPE*)pthread_getspecific(sInstanceKey);
+#else
+ return sInstance;
+#endif
+ }
+
+ static void setInstance(DERIVED_TYPE* instance)
+ {
+#if LL_DARWIN
+ createTLSKey();
+ pthread_setspecific(sInstanceKey, (void*)instance);
+#else
+ sInstance = instance;
+#endif
+ }
+
+private:
+
+#if LL_WINDOWS
+ static __declspec(thread) DERIVED_TYPE* sInstance;
+#elif LL_LINUX
+ static __thread DERIVED_TYPE* sInstance;
+#elif LL_DARWIN
+ static void TLSError()
+ {
+ LL_ERRS() << "Could not create thread local storage" << LL_ENDL;
+ }
+ static void createTLSKey()
+ {
+ static S32 key_created = pthread_key_create(&sInstanceKey, NULL);
+ if (key_created != 0)
+ {
+ LL_ERRS() << "Could not create thread local storage" << LL_ENDL;
+ }
+ }
+ static pthread_key_t sInstanceKey;
+#endif
+};
+
+#if LL_WINDOWS
+template<typename DERIVED_TYPE>
+__declspec(thread) DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL;
+#elif LL_LINUX
+template<typename DERIVED_TYPE>
+__thread DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL;
+#elif LL_DARWIN
+template<typename DERIVED_TYPE>
+pthread_key_t LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstanceKey;
+#endif
+
+#endif // LL_LLTHREADLOCALSTORAGE_H
diff --git a/indra/llcommon/llthreadsafequeue.cpp b/indra/llcommon/llthreadsafequeue.cpp
index 8a73e632a9..185f0d63fb 100755
--- a/indra/llcommon/llthreadsafequeue.cpp
+++ b/indra/llcommon/llthreadsafequeue.cpp
@@ -54,7 +54,7 @@ LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * po
LLThreadSafeQueueImplementation::~LLThreadSafeQueueImplementation()
{
if(mQueue != 0) {
- if(apr_queue_size(mQueue) != 0) llwarns <<
+ if(apr_queue_size(mQueue) != 0) LL_WARNS() <<
"terminating queue which still contains " << apr_queue_size(mQueue) <<
" elements;" << "memory will be leaked" << LL_ENDL;
apr_queue_term(mQueue);
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 9ebc6de7f4..ab105a82e6 100755
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -31,11 +31,9 @@
#include "u64.h"
#if LL_WINDOWS
-# define WIN32_LEAN_AND_MEAN
-# include <winsock2.h>
-# include <windows.h>
+# include "llwin32headerslean.h"
#elif LL_LINUX || LL_SOLARIS || LL_DARWIN
-# include <errno.h>
+# include <errno.h>
# include <sys/time.h>
#else
# error "architecture not supported"
@@ -45,7 +43,6 @@
//
// Locally used constants
//
-const U32 SEC_PER_DAY = 86400;
const F64 SEC_TO_MICROSEC = 1000000.f;
const U64 SEC_TO_MICROSEC_U64 = 1000000;
const F64 USEC_TO_SEC_F64 = 0.000001;
@@ -58,11 +55,6 @@ const F64 USEC_TO_SEC_F64 = 0.000001;
S32 gUTCOffset = 0; // viewer's offset from server UTC, in seconds
LLTimer* LLTimer::sTimer = NULL;
-F64 gClockFrequency = 0.0;
-F64 gClockFrequencyInv = 0.0;
-F64 gClocksToMicroseconds = 0.0;
-U64 gTotalTimeClockCount = 0;
-U64 gLastTotalTimeClockCount = 0;
//
// Forward declarations
@@ -190,7 +182,7 @@ U64 get_clock_count()
return clock_count.QuadPart - offset;
}
-F64 calc_clock_frequency(U32 uiMeasureMSecs)
+F64 calc_clock_frequency()
{
__int64 freq;
QueryPerformanceFrequency((LARGE_INTEGER *) &freq);
@@ -201,7 +193,7 @@ F64 calc_clock_frequency(U32 uiMeasureMSecs)
#if LL_LINUX || LL_DARWIN || LL_SOLARIS
// Both Linux and Mac use gettimeofday for accurate time
-F64 calc_clock_frequency(unsigned int uiMeasureMSecs)
+F64 calc_clock_frequency()
{
return 1000000.0; // microseconds, so 1 MHz.
}
@@ -216,56 +208,68 @@ U64 get_clock_count()
#endif
-void update_clock_frequencies()
+TimerInfo::TimerInfo()
+: mClockFrequency(0.0),
+ mTotalTimeClockCount(0),
+ mLastTotalTimeClockCount(0)
+{}
+
+void TimerInfo::update()
{
- gClockFrequency = calc_clock_frequency(50U);
- gClockFrequencyInv = 1.0/gClockFrequency;
- gClocksToMicroseconds = gClockFrequencyInv * SEC_TO_MICROSEC;
+ mClockFrequency = calc_clock_frequency();
+ mClockFrequencyInv = 1.0/mClockFrequency;
+ mClocksToMicroseconds = mClockFrequencyInv;
}
+TimerInfo& get_timer_info()
+{
+ static TimerInfo sTimerInfo;
+ return sTimerInfo;
+}
///////////////////////////////////////////////////////////////////////////////
// returns a U64 number that represents the number of
-// microseconds since the unix epoch - Jan 1, 1970
-U64 totalTime()
+// microseconds since the Unix epoch - Jan 1, 1970
+U64MicrosecondsImplicit totalTime()
{
U64 current_clock_count = get_clock_count();
- if (!gTotalTimeClockCount)
+ if (!get_timer_info().mTotalTimeClockCount || get_timer_info().mClocksToMicroseconds.value() == 0)
{
- update_clock_frequencies();
- gTotalTimeClockCount = current_clock_count;
+ get_timer_info().update();
+ get_timer_info().mTotalTimeClockCount = current_clock_count;
#if LL_WINDOWS
- // Synch us up with local time (even though we PROBABLY don't need to, this is how it was implemented)
+ // Sync us up with local time (even though we PROBABLY don't need to, this is how it was implemented)
// Unix platforms use gettimeofday so they are synced, although this probably isn't a good assumption to
// make in the future.
- gTotalTimeClockCount = (U64)(time(NULL) * gClockFrequency);
+ get_timer_info().mTotalTimeClockCount = (U64)(time(NULL) * get_timer_info().mClockFrequency);
#endif
// Update the last clock count
- gLastTotalTimeClockCount = current_clock_count;
+ get_timer_info().mLastTotalTimeClockCount = current_clock_count;
}
else
{
- if (current_clock_count >= gLastTotalTimeClockCount)
+ if (current_clock_count >= get_timer_info().mLastTotalTimeClockCount)
{
// No wrapping, we're all okay.
- gTotalTimeClockCount += current_clock_count - gLastTotalTimeClockCount;
+ get_timer_info().mTotalTimeClockCount += current_clock_count - get_timer_info().mLastTotalTimeClockCount;
}
else
{
// We've wrapped. Compensate correctly
- gTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - gLastTotalTimeClockCount) + current_clock_count;
+ get_timer_info().mTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - get_timer_info().mLastTotalTimeClockCount) + current_clock_count;
}
// Update the last clock count
- gLastTotalTimeClockCount = current_clock_count;
+ get_timer_info().mLastTotalTimeClockCount = current_clock_count;
}
// Return the total clock tick count in microseconds.
- return (U64)(gTotalTimeClockCount*gClocksToMicroseconds);
+ U64Microseconds time(get_timer_info().mTotalTimeClockCount*get_timer_info().mClocksToMicroseconds);
+ return time;
}
@@ -273,9 +277,9 @@ U64 totalTime()
LLTimer::LLTimer()
{
- if (!gClockFrequency)
+ if (!get_timer_info().mClockFrequency)
{
- update_clock_frequencies();
+ get_timer_info().update();
}
mStarted = TRUE;
@@ -283,20 +287,32 @@ LLTimer::LLTimer()
}
LLTimer::~LLTimer()
+{}
+
+// static
+void LLTimer::initClass()
+{
+ if (!sTimer) sTimer = new LLTimer;
+}
+
+// static
+void LLTimer::cleanupClass()
{
+ delete sTimer; sTimer = NULL;
}
// static
-U64 LLTimer::getTotalTime()
+U64MicrosecondsImplicit LLTimer::getTotalTime()
{
// simply call into the implementation function.
- return totalTime();
+ U64MicrosecondsImplicit total_time = totalTime();
+ return total_time;
}
// static
-F64 LLTimer::getTotalSeconds()
+F64SecondsImplicit LLTimer::getTotalSeconds()
{
- return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64;
+ return F64Microseconds(U64_to_F64(getTotalTime()));
}
void LLTimer::reset()
@@ -343,43 +359,43 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount)
}
-F64 LLTimer::getElapsedTimeF64() const
+F64SecondsImplicit LLTimer::getElapsedTimeF64() const
{
U64 last = mLastClockCount;
- return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv;
+ return (F64)getElapsedTimeAndUpdate(last) * get_timer_info().mClockFrequencyInv;
}
-F32 LLTimer::getElapsedTimeF32() const
+F32SecondsImplicit LLTimer::getElapsedTimeF32() const
{
return (F32)getElapsedTimeF64();
}
-F64 LLTimer::getElapsedTimeAndResetF64()
+F64SecondsImplicit LLTimer::getElapsedTimeAndResetF64()
{
- return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv;
+ return (F64)getElapsedTimeAndUpdate(mLastClockCount) * get_timer_info().mClockFrequencyInv;
}
-F32 LLTimer::getElapsedTimeAndResetF32()
+F32SecondsImplicit LLTimer::getElapsedTimeAndResetF32()
{
return (F32)getElapsedTimeAndResetF64();
}
///////////////////////////////////////////////////////////////////////////////
-void LLTimer::setTimerExpirySec(F32 expiration)
+void LLTimer::setTimerExpirySec(F32SecondsImplicit expiration)
{
mExpirationTicks = get_clock_count()
- + (U64)((F32)(expiration * gClockFrequency));
+ + (U64)((F32)(expiration * get_timer_info().mClockFrequency.value()));
}
-F32 LLTimer::getRemainingTimeF32() const
+F32SecondsImplicit LLTimer::getRemainingTimeF32() const
{
U64 cur_ticks = get_clock_count();
if (cur_ticks > mExpirationTicks)
{
return 0.0f;
}
- return F32((mExpirationTicks - cur_ticks) * gClockFrequencyInv);
+ return F32((mExpirationTicks - cur_ticks) * get_timer_info().mClockFrequencyInv);
}
@@ -392,7 +408,7 @@ BOOL LLTimer::checkExpirationAndReset(F32 expiration)
}
mExpirationTicks = cur_ticks
- + (U64)((F32)(expiration * gClockFrequency));
+ + (U64)((F32)(expiration * get_timer_info().mClockFrequency));
return TRUE;
}
@@ -448,7 +464,7 @@ BOOL LLTimer::knownBadTimer()
{
if (!wcscmp(pci_id, bad_pci_list[check]))
{
-// llwarns << "unreliable PCI chipset found!! " << pci_id << endl;
+// LL_WARNS() << "unreliable PCI chipset found!! " << pci_id << endl;
failed = TRUE;
break;
}
@@ -491,20 +507,20 @@ BOOL is_daylight_savings()
struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time)
{
- S32 pacific_offset_hours;
+ S32Hours pacific_offset_hours;
if (pacific_daylight_time)
{
- pacific_offset_hours = 7;
+ pacific_offset_hours = S32Hours(7);
}
else
{
- pacific_offset_hours = 8;
+ pacific_offset_hours = S32Hours(8);
}
// We subtract off the PST/PDT offset _before_ getting
// "UTC" time, because this will handle wrapping around
// for 5 AM UTC -> 10 PM PDT of the previous day.
- utc_time -= pacific_offset_hours * MIN_PER_HOUR * SEC_PER_MIN;
+ utc_time -= S32SecondsImplicit(pacific_offset_hours);
// Internal buffer to PST/PDT (see above)
struct tm* internal_time = gmtime(&utc_time);
@@ -521,7 +537,7 @@ struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time)
}
-void microsecondsToTimecodeString(U64 current_time, std::string& tcstring)
+void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring)
{
U64 hours;
U64 minutes;
@@ -543,9 +559,9 @@ void microsecondsToTimecodeString(U64 current_time, std::string& tcstring)
}
-void secondsToTimecodeString(F32 current_time, std::string& tcstring)
+void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring)
{
- microsecondsToTimecodeString((U64)((F64)(SEC_TO_MICROSEC*current_time)), tcstring);
+ microsecondsToTimecodeString(current_time, tcstring);
}
diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h
index e73741217c..ec70213447 100755
--- a/indra/llcommon/lltimer.h
+++ b/indra/llcommon/lltimer.h
@@ -37,6 +37,7 @@
#include <string>
#include <list>
// units conversions
+#include "llunits.h"
#ifndef USEC_PER_SEC
const U32 USEC_PER_SEC = 1000000;
#endif
@@ -55,27 +56,34 @@ public:
protected:
U64 mLastClockCount;
U64 mExpirationTicks;
- BOOL mStarted;
+ bool mStarted;
public:
LLTimer();
~LLTimer();
- static void initClass() { if (!sTimer) sTimer = new LLTimer; }
- static void cleanupClass() { delete sTimer; sTimer = NULL; }
+ static void initClass();
+ static void cleanupClass();
// Return a high precision number of seconds since the start of
// this application instance.
- static F64 getElapsedSeconds()
+ static F64SecondsImplicit getElapsedSeconds()
+ {
+ if (sTimer)
{
return sTimer->getElapsedTimeF64();
}
+ else
+ {
+ return 0;
+ }
+ }
// Return a high precision usec since epoch
- static U64 getTotalTime();
+ static U64MicrosecondsImplicit getTotalTime();
// Return a high precision seconds since epoch
- static F64 getTotalSeconds();
+ static F64SecondsImplicit getTotalSeconds();
// MANIPULATORS
@@ -83,21 +91,21 @@ public:
void stop() { mStarted = FALSE; }
void reset(); // Resets the timer
void setLastClockCount(U64 current_count); // Sets the timer so that the next elapsed call will be relative to this time
- void setTimerExpirySec(F32 expiration);
+ void setTimerExpirySec(F32SecondsImplicit expiration);
BOOL checkExpirationAndReset(F32 expiration);
BOOL hasExpired() const;
- F32 getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset
- F64 getElapsedTimeAndResetF64();
+ F32SecondsImplicit getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset
+ F64SecondsImplicit getElapsedTimeAndResetF64();
- F32 getRemainingTimeF32() const;
+ F32SecondsImplicit getRemainingTimeF32() const;
static BOOL knownBadTimer();
// ACCESSORS
- F32 getElapsedTimeF32() const; // Returns elapsed time in seconds
- F64 getElapsedTimeF64() const; // Returns elapsed time in seconds
+ F32SecondsImplicit getElapsedTimeF32() const; // Returns elapsed time in seconds
+ F64SecondsImplicit getElapsedTimeF64() const; // Returns elapsed time in seconds
- BOOL getStarted() const { return mStarted; }
+ bool getStarted() const { return mStarted; }
static U64 getCurrentClockCount(); // Returns the raw clockticks
@@ -106,9 +114,21 @@ public:
//
// Various functions for initializing/accessing clock and timing stuff. Don't use these without REALLY knowing how they work.
//
+struct TimerInfo
+{
+ TimerInfo();
+ void update();
+
+ F64HertzImplicit mClockFrequency;
+ F64SecondsImplicit mClockFrequencyInv;
+ F64MicrosecondsImplicit mClocksToMicroseconds;
+ U64 mTotalTimeClockCount;
+ U64 mLastTotalTimeClockCount;
+};
+
+TimerInfo& get_timer_info();
+
LL_COMMON_API U64 get_clock_count();
-LL_COMMON_API F64 calc_clock_frequency(U32 msecs);
-LL_COMMON_API void update_clock_frequencies();
// Sleep for milliseconds
LL_COMMON_API void ms_sleep(U32 ms);
@@ -146,13 +166,6 @@ static inline time_t time_max()
}
}
-// These are really statics but they've been global for awhile
-// and they're material to other timing classes. If you are
-// not implementing a timer class, do not use these directly.
-extern LL_COMMON_API F64 gClockFrequency;
-extern LL_COMMON_API F64 gClockFrequencyInv;
-extern LL_COMMON_API F64 gClocksToMicroseconds;
-
// Correction factor used by time_corrected() above.
extern LL_COMMON_API S32 gUTCOffset;
@@ -167,9 +180,9 @@ LL_COMMON_API BOOL is_daylight_savings();
// struct tm* internal_time = utc_to_pacific_time(utc_time, gDaylight);
LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time);
-LL_COMMON_API void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);
-LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstring);
+LL_COMMON_API void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring);
+LL_COMMON_API void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring);
-U64 LL_COMMON_API totalTime(); // Returns current system time in microseconds
+U64MicrosecondsImplicit LL_COMMON_API totalTime(); // Returns current system time in microseconds
#endif
diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp
new file mode 100644
index 0000000000..54079a4689
--- /dev/null
+++ b/indra/llcommon/lltrace.cpp
@@ -0,0 +1,86 @@
+/**
+ * @file lltrace.cpp
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltrace.h"
+#include "lltracerecording.h"
+#include "lltracethreadrecorder.h"
+#include "llfasttimer.h"
+
+namespace LLTrace
+{
+
+MemStatHandle gTraceMemStat("LLTrace");
+
+StatBase::StatBase( const char* name, const char* description )
+: mName(name),
+ mDescription(description ? description : "")
+{
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ if (LLTrace::get_thread_recorder().notNull())
+ {
+ LL_ERRS() << "Attempting to declare trace object after program initialization. Trace objects should be statically initialized." << LL_ENDL;
+ }
+#endif
+}
+
+const char* StatBase::getUnitLabel() const
+{
+ return "";
+}
+
+TimeBlockTreeNode::TimeBlockTreeNode()
+: mBlock(NULL),
+ mParent(NULL),
+ mNeedsSorting(false),
+ mCollapsed(true)
+{}
+
+void TimeBlockTreeNode::setParent( BlockTimerStatHandle* parent )
+{
+ llassert_always(parent != mBlock);
+ llassert_always(parent != NULL);
+
+ TimeBlockTreeNode* parent_tree_node = get_thread_recorder()->getTimeBlockTreeNode(parent->getIndex());
+ if (!parent_tree_node) return;
+
+ if (mParent)
+ {
+ std::vector<BlockTimerStatHandle*>& children = mParent->getChildren();
+ std::vector<BlockTimerStatHandle*>::iterator found_it = std::find(children.begin(), children.end(), mBlock);
+ if (found_it != children.end())
+ {
+ children.erase(found_it);
+ }
+ }
+
+ mParent = parent;
+ mBlock->getCurrentAccumulator().mParent = parent;
+ parent_tree_node->mChildren.push_back(mBlock);
+ parent_tree_node->mNeedsSorting = true;
+}
+
+}
diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h
new file mode 100644
index 0000000000..5f1289dad8
--- /dev/null
+++ b/indra/llcommon/lltrace.h
@@ -0,0 +1,492 @@
+/**
+ * @file lltrace.h
+ * @brief Runtime statistics accumulation.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRACE_H
+#define LL_LLTRACE_H
+
+#include "stdtypes.h"
+#include "llpreprocessor.h"
+
+#include "llmemory.h"
+#include "llrefcount.h"
+#include "lltraceaccumulators.h"
+#include "llthreadlocalstorage.h"
+#include "lltimer.h"
+#include "llpointer.h"
+#include "llunits.h"
+
+#define LL_TRACE_ENABLED 1
+
+namespace LLTrace
+{
+class Recording;
+
+template<typename T>
+T storage_value(T val) { return val; }
+
+template<typename UNIT_TYPE, typename STORAGE_TYPE>
+STORAGE_TYPE storage_value(LLUnit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); }
+
+template<typename UNIT_TYPE, typename STORAGE_TYPE>
+STORAGE_TYPE storage_value(LLUnitImplicit<STORAGE_TYPE, UNIT_TYPE> val) { return val.value(); }
+
+class StatBase
+{
+public:
+ StatBase(const char* name, const char* description);
+ virtual ~StatBase() {};
+ virtual const char* getUnitLabel() const;
+
+ const std::string& getName() const { return mName; }
+ const std::string& getDescription() const { return mDescription; }
+
+protected:
+ std::string mName;
+ std::string mDescription;
+};
+
+template<typename ACCUMULATOR>
+class StatType
+: public StatBase,
+ public LLInstanceTracker<StatType<ACCUMULATOR>, std::string>
+{
+public:
+ typedef LLInstanceTracker<StatType<ACCUMULATOR>, std::string> instance_tracker_t;
+ StatType(const char* name, const char* description)
+ : instance_tracker_t(name),
+ StatBase(name, description),
+ mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot())
+ {}
+
+ LL_FORCE_INLINE ACCUMULATOR& getCurrentAccumulator() const
+ {
+ ACCUMULATOR* accumulator_storage = LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance();
+ return accumulator_storage ? accumulator_storage[mAccumulatorIndex] : (*AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer())[mAccumulatorIndex];
+ }
+
+ size_t getIndex() const { return mAccumulatorIndex; }
+ static size_t getNumIndices() { return AccumulatorBuffer<ACCUMULATOR>::getNumIndices(); }
+
+protected:
+ const size_t mAccumulatorIndex;
+};
+
+
+template<>
+class StatType<TimeBlockAccumulator::CallCountFacet>
+: public StatType<TimeBlockAccumulator>
+{
+public:
+
+ StatType(const char* name, const char* description = "")
+ : StatType<TimeBlockAccumulator>(name, description)
+ {}
+};
+
+template<>
+class StatType<TimeBlockAccumulator::SelfTimeFacet>
+ : public StatType<TimeBlockAccumulator>
+{
+public:
+
+ StatType(const char* name, const char* description = "")
+ : StatType<TimeBlockAccumulator>(name, description)
+ {}
+};
+
+template <typename T = F64>
+class EventStatHandle
+: public StatType<EventAccumulator>
+{
+public:
+ typedef F64 storage_t;
+ typedef StatType<EventAccumulator> stat_t;
+ typedef EventStatHandle<T> self_t;
+
+ EventStatHandle(const char* name, const char* description = NULL)
+ : stat_t(name, description)
+ {}
+
+ /*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
+
+};
+
+template<typename T, typename VALUE_T>
+void record(EventStatHandle<T>& measurement, VALUE_T value)
+{
+#if LL_TRACE_ENABLED
+ T converted_value(value);
+ measurement.getCurrentAccumulator().record(storage_value(converted_value));
+#endif
+}
+
+template <typename T = F64>
+class SampleStatHandle
+: public StatType<SampleAccumulator>
+{
+public:
+ typedef F64 storage_t;
+ typedef StatType<SampleAccumulator> stat_t;
+ typedef SampleStatHandle<T> self_t;
+
+ SampleStatHandle(const char* name, const char* description = NULL)
+ : stat_t(name, description)
+ {}
+
+ /*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
+};
+
+template<typename T, typename VALUE_T>
+void sample(SampleStatHandle<T>& measurement, VALUE_T value)
+{
+#if LL_TRACE_ENABLED
+ T converted_value(value);
+ measurement.getCurrentAccumulator().sample(storage_value(converted_value));
+#endif
+}
+
+template <typename T = F64>
+class CountStatHandle
+: public StatType<CountAccumulator>
+{
+public:
+ typedef F64 storage_t;
+ typedef StatType<CountAccumulator> stat_t;
+ typedef CountStatHandle<T> self_t;
+
+ CountStatHandle(const char* name, const char* description = NULL)
+ : stat_t(name, description)
+ {}
+
+ /*virtual*/ const char* getUnitLabel() const { return LLGetUnitLabel<T>::getUnitLabel(); }
+};
+
+template<typename T, typename VALUE_T>
+void add(CountStatHandle<T>& count, VALUE_T value)
+{
+#if LL_TRACE_ENABLED
+ T converted_value(value);
+ count.getCurrentAccumulator().add(storage_value(converted_value));
+#endif
+}
+
+template<>
+class StatType<MemAccumulator::AllocationFacet>
+: public StatType<MemAccumulator>
+{
+public:
+
+ StatType(const char* name, const char* description = "")
+ : StatType<MemAccumulator>(name, description)
+ {}
+};
+
+template<>
+class StatType<MemAccumulator::DeallocationFacet>
+: public StatType<MemAccumulator>
+{
+public:
+
+ StatType(const char* name, const char* description = "")
+ : StatType<MemAccumulator>(name, description)
+ {}
+};
+
+class MemStatHandle : public StatType<MemAccumulator>
+{
+public:
+ typedef StatType<MemAccumulator> stat_t;
+ MemStatHandle(const char* name, const char* description = "")
+ : stat_t(name, description)
+ {
+ mName = name;
+ }
+
+ void setName(const char* name)
+ {
+ mName = name;
+ setKey(name);
+ }
+
+ /*virtual*/ const char* getUnitLabel() const { return "KB"; }
+
+ StatType<MemAccumulator::AllocationFacet>& allocations()
+ {
+ return static_cast<StatType<MemAccumulator::AllocationFacet>&>(*(StatType<MemAccumulator>*)this);
+ }
+
+ StatType<MemAccumulator::DeallocationFacet>& deallocations()
+ {
+ return static_cast<StatType<MemAccumulator::DeallocationFacet>&>(*(StatType<MemAccumulator>*)this);
+ }
+};
+
+
+// measures effective memory footprint of specified type
+// specialize to cover different types
+template<typename T, typename IS_MEM_TRACKABLE = void, typename IS_UNITS = void>
+struct MeasureMem
+{
+ static size_t measureFootprint(const T& value)
+ {
+ return sizeof(T);
+ }
+};
+
+template<typename T, typename IS_BYTES>
+struct MeasureMem<T, typename T::mem_trackable_tag_t, IS_BYTES>
+{
+ static size_t measureFootprint(const T& value)
+ {
+ return sizeof(T) + value.getMemFootprint();
+ }
+};
+
+template<typename T, typename IS_MEM_TRACKABLE>
+struct MeasureMem<T, IS_MEM_TRACKABLE, typename T::is_unit_t>
+{
+ static size_t measureFootprint(const T& value)
+ {
+ return U32Bytes(value).value();
+ }
+};
+
+template<typename T, typename IS_MEM_TRACKABLE, typename IS_BYTES>
+struct MeasureMem<T*, IS_MEM_TRACKABLE, IS_BYTES>
+{
+ static size_t measureFootprint(const T* value)
+ {
+ if (!value)
+ {
+ return 0;
+ }
+ return MeasureMem<T>::measureFootprint(*value);
+ }
+};
+
+template<typename T, typename IS_MEM_TRACKABLE, typename IS_BYTES>
+struct MeasureMem<LLPointer<T>, IS_MEM_TRACKABLE, IS_BYTES>
+{
+ static size_t measureFootprint(const LLPointer<T> value)
+ {
+ if (value.isNull())
+ {
+ return 0;
+ }
+ return MeasureMem<T>::measureFootprint(*value);
+ }
+};
+
+template<typename IS_MEM_TRACKABLE, typename IS_BYTES>
+struct MeasureMem<S32, IS_MEM_TRACKABLE, IS_BYTES>
+{
+ static size_t measureFootprint(S32 value)
+ {
+ return value;
+ }
+};
+
+template<typename IS_MEM_TRACKABLE, typename IS_BYTES>
+struct MeasureMem<U32, IS_MEM_TRACKABLE, IS_BYTES>
+{
+ static size_t measureFootprint(U32 value)
+ {
+ return value;
+ }
+};
+
+template<typename T, typename IS_MEM_TRACKABLE, typename IS_BYTES>
+struct MeasureMem<std::basic_string<T>, IS_MEM_TRACKABLE, IS_BYTES>
+{
+ static size_t measureFootprint(const std::basic_string<T>& value)
+ {
+ return value.capacity() * sizeof(T);
+ }
+};
+
+
+template<typename T>
+inline void claim_alloc(MemStatHandle& measurement, const T& value)
+{
+#if LL_TRACE_ENABLED
+ S32 size = MeasureMem<T>::measureFootprint(value);
+ if(size == 0) return;
+ MemAccumulator& accumulator = measurement.getCurrentAccumulator();
+ accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size);
+ accumulator.mAllocations.record(size);
+#endif
+}
+
+template<typename T>
+inline void disclaim_alloc(MemStatHandle& measurement, const T& value)
+{
+#if LL_TRACE_ENABLED
+ S32 size = MeasureMem<T>::measureFootprint(value);
+ if(size == 0) return;
+ MemAccumulator& accumulator = measurement.getCurrentAccumulator();
+ accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size);
+ accumulator.mDeallocations.add(size);
+#endif
+}
+
+template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN>
+class MemTrackableNonVirtual
+{
+public:
+ typedef void mem_trackable_tag_t;
+
+ MemTrackableNonVirtual(const char* name)
+#if LL_TRACE_ENABLED
+ : mMemFootprint(0)
+#endif
+ {
+#if LL_TRACE_ENABLED
+ static bool name_initialized = false;
+ if (!name_initialized)
+ {
+ name_initialized = true;
+ sMemStat.setName(name);
+ }
+#endif
+ }
+
+#if LL_TRACE_ENABLED
+ ~MemTrackableNonVirtual()
+ {
+ disclaimMem(mMemFootprint);
+ }
+
+ static MemStatHandle& getMemStatHandle()
+ {
+ return sMemStat;
+ }
+
+ S32 getMemFootprint() const { return mMemFootprint; }
+#endif
+
+ void* operator new(size_t size)
+ {
+#if LL_TRACE_ENABLED
+ claim_alloc(sMemStat, size);
+#endif
+ return ll_aligned_malloc<ALIGNMENT>(size);
+ }
+
+ template<int CUSTOM_ALIGNMENT>
+ static void* aligned_new(size_t size)
+ {
+#if LL_TRACE_ENABLED
+ claim_alloc(sMemStat, size);
+#endif
+ return ll_aligned_malloc<CUSTOM_ALIGNMENT>(size);
+ }
+
+ void operator delete(void* ptr, size_t size)
+ {
+#if LL_TRACE_ENABLED
+ disclaim_alloc(sMemStat, size);
+#endif
+ ll_aligned_free<ALIGNMENT>(ptr);
+ }
+
+ template<int CUSTOM_ALIGNMENT>
+ static void aligned_delete(void* ptr, size_t size)
+ {
+#if LL_TRACE_ENABLED
+ disclaim_alloc(sMemStat, size);
+#endif
+ ll_aligned_free<CUSTOM_ALIGNMENT>(ptr);
+ }
+
+ void* operator new [](size_t size)
+ {
+#if LL_TRACE_ENABLED
+ claim_alloc(sMemStat, size);
+#endif
+ return ll_aligned_malloc<ALIGNMENT>(size);
+ }
+
+ void operator delete[](void* ptr, size_t size)
+ {
+#if LL_TRACE_ENABLED
+ disclaim_alloc(sMemStat, size);
+#endif
+ ll_aligned_free<ALIGNMENT>(ptr);
+ }
+
+ // claim memory associated with other objects/data as our own, adding to our calculated footprint
+ template<typename CLAIM_T>
+ void claimMem(const CLAIM_T& value) const
+ {
+#if LL_TRACE_ENABLED
+ S32 size = MeasureMem<CLAIM_T>::measureFootprint(value);
+ claim_alloc(sMemStat, size);
+ mMemFootprint += size;
+#endif
+ }
+
+ // remove memory we had claimed from our calculated footprint
+ template<typename CLAIM_T>
+ void disclaimMem(const CLAIM_T& value) const
+ {
+#if LL_TRACE_ENABLED
+ S32 size = MeasureMem<CLAIM_T>::measureFootprint(value);
+ disclaim_alloc(sMemStat, size);
+ mMemFootprint -= size;
+#endif
+ }
+
+private:
+#if LL_TRACE_ENABLED
+ // use signed values so that we can temporarily go negative
+ // and reconcile in destructor
+ // NB: this assumes that no single class is responsible for > 2GB of allocations
+ mutable S32 mMemFootprint;
+
+ static MemStatHandle sMemStat;
+#endif
+
+};
+
+#if LL_TRACE_ENABLED
+template<typename DERIVED, size_t ALIGNMENT>
+MemStatHandle MemTrackableNonVirtual<DERIVED, ALIGNMENT>::sMemStat(typeid(MemTrackableNonVirtual<DERIVED, ALIGNMENT>).name());
+#endif
+
+template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN>
+class MemTrackable : public MemTrackableNonVirtual<DERIVED, ALIGNMENT>
+{
+public:
+ MemTrackable(const char* name)
+ : MemTrackableNonVirtual<DERIVED, ALIGNMENT>(name)
+ {}
+
+ virtual ~MemTrackable()
+ {}
+};
+}
+
+#endif // LL_LLTRACE_H
diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp
new file mode 100644
index 0000000000..385d31edd7
--- /dev/null
+++ b/indra/llcommon/lltraceaccumulators.cpp
@@ -0,0 +1,302 @@
+/**
+ * @file lltracesampler.cpp
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltraceaccumulators.h"
+#include "lltrace.h"
+#include "lltracethreadrecorder.h"
+
+namespace LLTrace
+{
+
+extern MemStatHandle gTraceMemStat;
+
+
+///////////////////////////////////////////////////////////////////////
+// AccumulatorBufferGroup
+///////////////////////////////////////////////////////////////////////
+
+AccumulatorBufferGroup::AccumulatorBufferGroup()
+{
+ claim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator));
+ claim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator));
+ claim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator));
+ claim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator));
+ claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemAccumulator));
+}
+
+AccumulatorBufferGroup::AccumulatorBufferGroup(const AccumulatorBufferGroup& other)
+: mCounts(other.mCounts),
+ mSamples(other.mSamples),
+ mEvents(other.mEvents),
+ mStackTimers(other.mStackTimers),
+ mMemStats(other.mMemStats)
+{
+ claim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator));
+ claim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator));
+ claim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator));
+ claim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator));
+ claim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemAccumulator));
+}
+
+AccumulatorBufferGroup::~AccumulatorBufferGroup()
+{
+ disclaim_alloc(gTraceMemStat, mCounts.capacity() * sizeof(CountAccumulator));
+ disclaim_alloc(gTraceMemStat, mSamples.capacity() * sizeof(SampleAccumulator));
+ disclaim_alloc(gTraceMemStat, mEvents.capacity() * sizeof(EventAccumulator));
+ disclaim_alloc(gTraceMemStat, mStackTimers.capacity() * sizeof(TimeBlockAccumulator));
+ disclaim_alloc(gTraceMemStat, mMemStats.capacity() * sizeof(MemAccumulator));
+}
+
+void AccumulatorBufferGroup::handOffTo(AccumulatorBufferGroup& other)
+{
+ other.mCounts.reset(&mCounts);
+ other.mSamples.reset(&mSamples);
+ other.mEvents.reset(&mEvents);
+ other.mStackTimers.reset(&mStackTimers);
+ other.mMemStats.reset(&mMemStats);
+}
+
+void AccumulatorBufferGroup::makeCurrent()
+{
+ mCounts.makeCurrent();
+ mSamples.makeCurrent();
+ mEvents.makeCurrent();
+ mStackTimers.makeCurrent();
+ mMemStats.makeCurrent();
+
+ ThreadRecorder* thread_recorder = get_thread_recorder().get();
+ AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers;
+ // update stacktimer parent pointers
+ for (S32 i = 0, end_i = mStackTimers.size(); i < end_i; i++)
+ {
+ TimeBlockTreeNode* tree_node = thread_recorder->getTimeBlockTreeNode(i);
+ if (tree_node)
+ {
+ timer_accumulator_buffer[i].mParent = tree_node->mParent;
+ }
+ }
+}
+
+//static
+void AccumulatorBufferGroup::clearCurrent()
+{
+ AccumulatorBuffer<CountAccumulator>::clearCurrent();
+ AccumulatorBuffer<SampleAccumulator>::clearCurrent();
+ AccumulatorBuffer<EventAccumulator>::clearCurrent();
+ AccumulatorBuffer<TimeBlockAccumulator>::clearCurrent();
+ AccumulatorBuffer<MemAccumulator>::clearCurrent();
+}
+
+bool AccumulatorBufferGroup::isCurrent() const
+{
+ return mCounts.isCurrent();
+}
+
+void AccumulatorBufferGroup::append( const AccumulatorBufferGroup& other )
+{
+ mCounts.addSamples(other.mCounts, SEQUENTIAL);
+ mSamples.addSamples(other.mSamples, SEQUENTIAL);
+ mEvents.addSamples(other.mEvents, SEQUENTIAL);
+ mMemStats.addSamples(other.mMemStats, SEQUENTIAL);
+ mStackTimers.addSamples(other.mStackTimers, SEQUENTIAL);
+}
+
+void AccumulatorBufferGroup::merge( const AccumulatorBufferGroup& other)
+{
+ mCounts.addSamples(other.mCounts, NON_SEQUENTIAL);
+ mSamples.addSamples(other.mSamples, NON_SEQUENTIAL);
+ mEvents.addSamples(other.mEvents, NON_SEQUENTIAL);
+ mMemStats.addSamples(other.mMemStats, NON_SEQUENTIAL);
+ // for now, hold out timers from merge, need to be displayed per thread
+ //mStackTimers.addSamples(other.mStackTimers, NON_SEQUENTIAL);
+}
+
+void AccumulatorBufferGroup::reset(AccumulatorBufferGroup* other)
+{
+ mCounts.reset(other ? &other->mCounts : NULL);
+ mSamples.reset(other ? &other->mSamples : NULL);
+ mEvents.reset(other ? &other->mEvents : NULL);
+ mStackTimers.reset(other ? &other->mStackTimers : NULL);
+ mMemStats.reset(other ? &other->mMemStats : NULL);
+}
+
+void AccumulatorBufferGroup::sync()
+{
+ if (isCurrent())
+ {
+ F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds();
+
+ mSamples.sync(time_stamp);
+ mMemStats.sync(time_stamp);
+ }
+}
+
+F64 SampleAccumulator::mergeSumsOfSquares(const SampleAccumulator& a, const SampleAccumulator& b)
+{
+ const F64 epsilon = 0.0000001;
+
+ if (a.getSamplingTime() > epsilon && b.getSamplingTime() > epsilon)
+ {
+ // combine variance (and hence standard deviation) of 2 different sized sample groups using
+ // the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+ F64 n_1 = a.getSamplingTime(),
+ n_2 = b.getSamplingTime();
+ F64 m_1 = a.getMean(),
+ m_2 = b.getMean();
+ F64 v_1 = a.getSumOfSquares() / a.getSamplingTime(),
+ v_2 = b.getSumOfSquares() / b.getSamplingTime();
+ if (n_1 < epsilon)
+ {
+ return b.getSumOfSquares();
+ }
+ else
+ {
+ return a.getSamplingTime()
+ * ((((n_1 - epsilon) * v_1)
+ + ((n_2 - epsilon) * v_2)
+ + (((n_1 * n_2) / (n_1 + n_2))
+ * ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+ / (n_1 + n_2 - epsilon));
+ }
+ }
+
+ return a.getSumOfSquares();
+}
+
+
+void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppendType append_type )
+{
+ if (append_type == NON_SEQUENTIAL)
+ {
+ return;
+ }
+
+ if (!mHasValue)
+ {
+ *this = other;
+
+ if (append_type == NON_SEQUENTIAL)
+ {
+ // restore own last value state
+ mLastValue = NaN;
+ mHasValue = false;
+ }
+ }
+ else if (other.mHasValue)
+ {
+ mSum += other.mSum;
+
+ if (other.mMin < mMin) { mMin = other.mMin; }
+ if (other.mMax > mMax) { mMax = other.mMax; }
+
+ mSumOfSquares = mergeSumsOfSquares(*this, other);
+
+ if (append_type == SEQUENTIAL)
+ {
+ mLastValue = other.mLastValue;
+ mLastSampleTimeStamp = other.mLastSampleTimeStamp;
+ }
+ }
+}
+
+void SampleAccumulator::reset( const SampleAccumulator* other )
+{
+ mLastValue = other ? other->mLastValue : NaN;
+ mHasValue = other ? other->mHasValue : false;
+ mNumSamples = 0;
+ mSum = 0;
+ mMin = mLastValue;
+ mMax = mLastValue;
+ mMean = mLastValue;
+ llassert(!mHasValue || mMean < 0 || mMean >= 0);
+ mSumOfSquares = 0;
+ mLastSampleTimeStamp = LLTimer::getTotalSeconds();
+ mTotalSamplingTime = 0;
+}
+
+F64 EventAccumulator::mergeSumsOfSquares(const EventAccumulator& a, const EventAccumulator& b)
+{
+ if (a.mNumSamples && b.mNumSamples)
+ {
+ // combine variance (and hence standard deviation) of 2 different sized sample groups using
+ // the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm
+ F64 n_1 = a.mNumSamples,
+ n_2 = b.mNumSamples;
+ F64 m_1 = a.mMean,
+ m_2 = b.mMean;
+ F64 v_1 = a.mSumOfSquares / a.mNumSamples,
+ v_2 = b.mSumOfSquares / b.mNumSamples;
+ return (F64)a.mNumSamples
+ * ((((n_1 - 1.f) * v_1)
+ + ((n_2 - 1.f) * v_2)
+ + (((n_1 * n_2) / (n_1 + n_2))
+ * ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2))))
+ / (n_1 + n_2 - 1.f));
+ }
+
+ return a.mSumOfSquares;
+}
+
+void EventAccumulator::addSamples( const EventAccumulator& other, EBufferAppendType append_type )
+{
+ if (other.mNumSamples)
+ {
+ if (!mNumSamples)
+ {
+ *this = other;
+ }
+ else
+ {
+ mSum += other.mSum;
+
+ // NOTE: both conditions will hold first time through
+ if (other.mMin < mMin) { mMin = other.mMin; }
+ if (other.mMax > mMax) { mMax = other.mMax; }
+
+ mSumOfSquares = mergeSumsOfSquares(*this, other);
+
+ F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples);
+ mNumSamples += other.mNumSamples;
+ mMean = mMean * weight + other.mMean * (1.f - weight);
+ if (append_type == SEQUENTIAL) mLastValue = other.mLastValue;
+ }
+ }
+}
+
+void EventAccumulator::reset( const EventAccumulator* other )
+{
+ mNumSamples = 0;
+ mSum = 0;
+ mMin = NaN;
+ mMax = NaN;
+ mMean = NaN;
+ mSumOfSquares = 0;
+ mLastValue = other ? other->mLastValue : NaN;
+}
+
+
+}
diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h
new file mode 100644
index 0000000000..42fad8a793
--- /dev/null
+++ b/indra/llcommon/lltraceaccumulators.h
@@ -0,0 +1,590 @@
+
+/**
+ * @file lltraceaccumulators.h
+ * @brief Storage for accumulating statistics
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRACEACCUMULATORS_H
+#define LL_LLTRACEACCUMULATORS_H
+
+
+#include "stdtypes.h"
+#include "llpreprocessor.h"
+#include "llunits.h"
+#include "lltimer.h"
+#include "llrefcount.h"
+#include "llthreadlocalstorage.h"
+#include "llmemory.h"
+#include <limits>
+
+namespace LLTrace
+{
+ const F64 NaN = std::numeric_limits<double>::quiet_NaN();
+
+ enum EBufferAppendType
+ {
+ SEQUENTIAL,
+ NON_SEQUENTIAL
+ };
+
+ template<typename ACCUMULATOR>
+ class AccumulatorBuffer : public LLRefCount
+ {
+ typedef AccumulatorBuffer<ACCUMULATOR> self_t;
+ static const S32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 32;
+ private:
+ struct StaticAllocationMarker { };
+
+ AccumulatorBuffer(StaticAllocationMarker m)
+ : mStorageSize(0),
+ mStorage(NULL)
+ {}
+
+ public:
+
+ AccumulatorBuffer(const AccumulatorBuffer& other = *getDefaultBuffer())
+ : mStorageSize(0),
+ mStorage(NULL)
+ {
+ resize(sNextStorageSlot);
+ for (S32 i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i] = other.mStorage[i];
+ }
+ }
+
+ ~AccumulatorBuffer()
+ {
+ if (isCurrent())
+ {
+ LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
+ }
+ delete[] mStorage;
+ }
+
+ LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index)
+ {
+ return mStorage[index];
+ }
+
+ LL_FORCE_INLINE const ACCUMULATOR& operator[](size_t index) const
+ {
+ return mStorage[index];
+ }
+
+ void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, EBufferAppendType append_type)
+ {
+ llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot);
+ for (size_t i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i].addSamples(other.mStorage[i], append_type);
+ }
+ }
+
+ void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other)
+ {
+ llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize >= sNextStorageSlot);
+ for (size_t i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i] = other.mStorage[i];
+ }
+ }
+
+ void reset(const AccumulatorBuffer<ACCUMULATOR>* other = NULL)
+ {
+ llassert(mStorageSize >= sNextStorageSlot);
+ for (size_t i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i].reset(other ? &other->mStorage[i] : NULL);
+ }
+ }
+
+ void sync(F64SecondsImplicit time_stamp)
+ {
+ llassert(mStorageSize >= sNextStorageSlot);
+ for (size_t i = 0; i < sNextStorageSlot; i++)
+ {
+ mStorage[i].sync(time_stamp);
+ }
+ }
+
+ void makeCurrent()
+ {
+ LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(mStorage);
+ }
+
+ bool isCurrent() const
+ {
+ return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage;
+ }
+
+ static void clearCurrent()
+ {
+ LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL);
+ }
+
+ // NOTE: this is not thread-safe. We assume that slots are reserved in the main thread before any child threads are spawned
+ size_t reserveSlot()
+ {
+ size_t next_slot = sNextStorageSlot++;
+ if (next_slot >= mStorageSize)
+ {
+ // don't perform doubling, as this should only happen during startup
+ // want to keep a tight bounds as we will have a lot of these buffers
+ resize(mStorageSize + mStorageSize / 2);
+ }
+ llassert(mStorage && next_slot < mStorageSize);
+ return next_slot;
+ }
+
+ void resize(size_t new_size)
+ {
+ if (new_size <= mStorageSize) return;
+
+ ACCUMULATOR* old_storage = mStorage;
+ mStorage = new ACCUMULATOR[new_size];
+ if (old_storage)
+ {
+ for (S32 i = 0; i < mStorageSize; i++)
+ {
+ mStorage[i] = old_storage[i];
+ }
+ }
+ mStorageSize = new_size;
+ delete[] old_storage;
+
+ self_t* default_buffer = getDefaultBuffer();
+ if (this != default_buffer
+ && new_size > default_buffer->size())
+ {
+ //NB: this is not thread safe, but we assume that all resizing occurs during static initialization
+ default_buffer->resize(new_size);
+ }
+ }
+
+ size_t size() const
+ {
+ return getNumIndices();
+ }
+
+ size_t capacity() const
+ {
+ return mStorageSize;
+ }
+
+ static size_t getNumIndices()
+ {
+ return sNextStorageSlot;
+ }
+
+ static self_t* getDefaultBuffer()
+ {
+ static bool sInitialized = false;
+ if (!sInitialized)
+ {
+ // this buffer is allowed to leak so that trace calls from global destructors have somewhere to put their data
+ // so as not to trigger an access violation
+ sDefaultBuffer = new AccumulatorBuffer(StaticAllocationMarker());
+ sInitialized = true;
+ sDefaultBuffer->resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE);
+ }
+ return sDefaultBuffer;
+ }
+
+ private:
+ ACCUMULATOR* mStorage;
+ size_t mStorageSize;
+ static size_t sNextStorageSlot;
+ static self_t* sDefaultBuffer;
+ };
+
+ template<typename ACCUMULATOR> size_t AccumulatorBuffer<ACCUMULATOR>::sNextStorageSlot = 0;
+ template<typename ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>* AccumulatorBuffer<ACCUMULATOR>::sDefaultBuffer = NULL;
+
+ class EventAccumulator
+ {
+ public:
+ typedef F64 value_t;
+ static F64 getDefaultValue() { return NaN; }
+
+ EventAccumulator()
+ : mSum(0),
+ mMin(NaN),
+ mMax(NaN),
+ mMean(NaN),
+ mSumOfSquares(0),
+ mNumSamples(0),
+ mLastValue(NaN)
+ {}
+
+ void record(F64 value)
+ {
+ if (mNumSamples == 0)
+ {
+ mSum = value;
+ mMean = value;
+ mMin = value;
+ mMax = value;
+ }
+ else
+ {
+ mSum += value;
+ F64 old_mean = mMean;
+ mMean += (value - old_mean) / (F64)mNumSamples;
+ mSumOfSquares += (value - old_mean) * (value - mMean);
+
+ if (value < mMin) { mMin = value; }
+ else if (value > mMax) { mMax = value; }
+ }
+
+ mNumSamples++;
+ mLastValue = value;
+ }
+
+ void addSamples(const EventAccumulator& other, EBufferAppendType append_type);
+ void reset(const EventAccumulator* other);
+ void sync(F64SecondsImplicit) {}
+
+ F64 getSum() const { return mSum; }
+ F32 getMin() const { return mMin; }
+ F32 getMax() const { return mMax; }
+ F64 getLastValue() const { return mLastValue; }
+ F64 getMean() const { return mMean; }
+ F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mNumSamples); }
+ F64 getSumOfSquares() const { return mSumOfSquares; }
+ S32 getSampleCount() const { return mNumSamples; }
+ bool hasValue() const { return mNumSamples > 0; }
+
+ // helper utility to calculate combined sumofsquares total
+ static F64 mergeSumsOfSquares(const EventAccumulator& a, const EventAccumulator& b);
+
+ private:
+ F64 mSum,
+ mLastValue;
+
+ F64 mMean,
+ mSumOfSquares;
+
+ F32 mMin,
+ mMax;
+
+ S32 mNumSamples;
+ };
+
+
+ class SampleAccumulator
+ {
+ public:
+ typedef F64 value_t;
+ static F64 getDefaultValue() { return NaN; }
+
+ SampleAccumulator()
+ : mSum(0),
+ mMin(NaN),
+ mMax(NaN),
+ mMean(NaN),
+ mSumOfSquares(0),
+ mLastSampleTimeStamp(0),
+ mTotalSamplingTime(0),
+ mNumSamples(0),
+ mLastValue(NaN),
+ mHasValue(false)
+ {}
+
+ void sample(F64 value)
+ {
+ F64SecondsImplicit time_stamp = LLTimer::getTotalSeconds();
+
+ // store effect of last value
+ sync(time_stamp);
+
+ if (!mHasValue)
+ {
+ mHasValue = true;
+
+ mMin = value;
+ mMax = value;
+ mMean = value;
+ mLastSampleTimeStamp = time_stamp;
+ }
+ else
+ {
+ if (value < mMin) { mMin = value; }
+ else if (value > mMax) { mMax = value; }
+ }
+
+ mLastValue = value;
+ mNumSamples++;
+ }
+
+ void addSamples(const SampleAccumulator& other, EBufferAppendType append_type);
+ void reset(const SampleAccumulator* other);
+
+ void sync(F64SecondsImplicit time_stamp)
+ {
+ if (mHasValue && time_stamp != mLastSampleTimeStamp)
+ {
+ F64SecondsImplicit delta_time = time_stamp - mLastSampleTimeStamp;
+ mSum += mLastValue * delta_time;
+ mTotalSamplingTime += delta_time;
+ F64 old_mean = mMean;
+ mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean);
+ mSumOfSquares += delta_time * (mLastValue - old_mean) * (mLastValue - mMean);
+ }
+ mLastSampleTimeStamp = time_stamp;
+ }
+
+ F64 getSum() const { return mSum; }
+ F32 getMin() const { return mMin; }
+ F32 getMax() const { return mMax; }
+ F64 getLastValue() const { return mLastValue; }
+ F64 getMean() const { return mMean; }
+ F64 getStandardDeviation() const { return sqrtf(mSumOfSquares / mTotalSamplingTime); }
+ F64 getSumOfSquares() const { return mSumOfSquares; }
+ F64SecondsImplicit getSamplingTime() const { return mTotalSamplingTime; }
+ S32 getSampleCount() const { return mNumSamples; }
+ bool hasValue() const { return mHasValue; }
+
+ // helper utility to calculate combined sumofsquares total
+ static F64 mergeSumsOfSquares(const SampleAccumulator& a, const SampleAccumulator& b);
+
+ private:
+ F64 mSum,
+ mLastValue;
+
+ F64 mMean,
+ mSumOfSquares;
+
+ F64SecondsImplicit
+ mLastSampleTimeStamp,
+ mTotalSamplingTime;
+
+ F32 mMin,
+ mMax;
+
+ S32 mNumSamples;
+ // distinct from mNumSamples, since we might have inherited a last value from
+ // a previous sampling period
+ bool mHasValue;
+ };
+
+ class CountAccumulator
+ {
+ public:
+ typedef F64 value_t;
+ static F64 getDefaultValue() { return 0; }
+
+ CountAccumulator()
+ : mSum(0),
+ mNumSamples(0)
+ {}
+
+ void add(F64 value)
+ {
+ mNumSamples++;
+ mSum += value;
+ }
+
+ void addSamples(const CountAccumulator& other, EBufferAppendType /*type*/)
+ {
+ mSum += other.mSum;
+ mNumSamples += other.mNumSamples;
+ }
+
+ void reset(const CountAccumulator* other)
+ {
+ mNumSamples = 0;
+ mSum = 0;
+ }
+
+ void sync(F64SecondsImplicit) {}
+
+ F64 getSum() const { return mSum; }
+
+ S32 getSampleCount() const { return mNumSamples; }
+
+ bool hasValue() const { return true; }
+
+ private:
+ F64 mSum;
+
+ S32 mNumSamples;
+ };
+
+ class TimeBlockAccumulator
+ {
+ public:
+ typedef F64Seconds value_t;
+ static F64Seconds getDefaultValue() { return F64Seconds(0); }
+
+ typedef TimeBlockAccumulator self_t;
+
+ // fake classes that allows us to view different facets of underlying statistic
+ struct CallCountFacet
+ {
+ typedef S32 value_t;
+ };
+
+ struct SelfTimeFacet
+ {
+ typedef F64Seconds value_t;
+ };
+
+ // arrays are allocated with 32 byte alignment
+ void *operator new [](size_t size)
+ {
+ return ll_aligned_malloc<32>(size);
+ }
+
+ void operator delete[](void* ptr, size_t size)
+ {
+ ll_aligned_free<32>(ptr);
+ }
+
+ TimeBlockAccumulator();
+ void addSamples(const self_t& other, EBufferAppendType append_type);
+ void reset(const self_t* other);
+ void sync(F64SecondsImplicit) {}
+ bool hasValue() const { return true; }
+
+ //
+ // members
+ //
+ U64 mTotalTimeCounter,
+ mSelfTimeCounter;
+ S32 mCalls;
+ class BlockTimerStatHandle* mParent; // last acknowledged parent of this time block
+ class BlockTimerStatHandle* mLastCaller; // used to bootstrap tree construction
+ U16 mActiveCount; // number of timers with this ID active on stack
+ bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
+
+ };
+
+ class BlockTimerStatHandle;
+
+ class TimeBlockTreeNode
+ {
+ public:
+ TimeBlockTreeNode();
+
+ void setParent(BlockTimerStatHandle* parent);
+ BlockTimerStatHandle* getParent() { return mParent; }
+
+ BlockTimerStatHandle* mBlock;
+ BlockTimerStatHandle* mParent;
+ std::vector<BlockTimerStatHandle*> mChildren;
+ bool mCollapsed;
+ bool mNeedsSorting;
+ };
+
+ struct BlockTimerStackRecord
+ {
+ class BlockTimer* mActiveTimer;
+ class BlockTimerStatHandle* mTimeBlock;
+ U64 mChildTime;
+ };
+
+ struct MemAccumulator
+ {
+ typedef F64Bytes value_t;
+ static F64Bytes getDefaultValue() { return F64Bytes(0); }
+
+ typedef MemAccumulator self_t;
+
+ // fake classes that allows us to view different facets of underlying statistic
+ struct AllocationFacet
+ {
+ typedef F64Bytes value_t;
+ static F64Bytes getDefaultValue() { return F64Bytes(0); }
+ };
+
+ struct DeallocationFacet
+ {
+ typedef F64Bytes value_t;
+ static F64Bytes getDefaultValue() { return F64Bytes(0); }
+ };
+
+ void addSamples(const MemAccumulator& other, EBufferAppendType append_type)
+ {
+ mAllocations.addSamples(other.mAllocations, append_type);
+ mDeallocations.addSamples(other.mDeallocations, append_type);
+
+ if (append_type == SEQUENTIAL)
+ {
+ mSize.addSamples(other.mSize, SEQUENTIAL);
+ }
+ else
+ {
+ F64 allocation_delta(other.mAllocations.getSum() - other.mDeallocations.getSum());
+ mSize.sample(mSize.hasValue()
+ ? mSize.getLastValue() + allocation_delta
+ : allocation_delta);
+ }
+ }
+
+ void reset(const MemAccumulator* other)
+ {
+ mSize.reset(other ? &other->mSize : NULL);
+ mAllocations.reset(other ? &other->mAllocations : NULL);
+ mDeallocations.reset(other ? &other->mDeallocations : NULL);
+ }
+
+ void sync(F64SecondsImplicit time_stamp)
+ {
+ mSize.sync(time_stamp);
+ }
+
+ bool hasValue() const { return mSize.hasValue(); }
+
+ SampleAccumulator mSize;
+ EventAccumulator mAllocations;
+ CountAccumulator mDeallocations;
+ };
+
+ struct AccumulatorBufferGroup : public LLRefCount
+ {
+ AccumulatorBufferGroup();
+ AccumulatorBufferGroup(const AccumulatorBufferGroup&);
+ ~AccumulatorBufferGroup();
+
+ void handOffTo(AccumulatorBufferGroup& other);
+ void makeCurrent();
+ bool isCurrent() const;
+ static void clearCurrent();
+
+ void append(const AccumulatorBufferGroup& other);
+ void merge(const AccumulatorBufferGroup& other);
+ void reset(AccumulatorBufferGroup* other = NULL);
+ void sync();
+
+ AccumulatorBuffer<CountAccumulator> mCounts;
+ AccumulatorBuffer<SampleAccumulator> mSamples;
+ AccumulatorBuffer<EventAccumulator> mEvents;
+ AccumulatorBuffer<TimeBlockAccumulator> mStackTimers;
+ AccumulatorBuffer<MemAccumulator> mMemStats;
+ };
+}
+
+#endif // LL_LLTRACEACCUMULATORS_H
+
diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp
new file mode 100644
index 0000000000..0b10438b9f
--- /dev/null
+++ b/indra/llcommon/lltracerecording.cpp
@@ -0,0 +1,1251 @@
+/**
+ * @file lltracesampler.cpp
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltracerecording.h"
+
+#include "lltrace.h"
+#include "llfasttimer.h"
+#include "lltracethreadrecorder.h"
+#include "llthread.h"
+
+inline F64 lerp(F64 a, F64 b, F64 u)
+{
+ return a + ((b - a) * u);
+}
+
+namespace LLTrace
+{
+
+extern MemStatHandle gTraceMemStat;
+
+///////////////////////////////////////////////////////////////////////
+// Recording
+///////////////////////////////////////////////////////////////////////
+
+Recording::Recording(EPlayState state)
+: mElapsedSeconds(0),
+ mActiveBuffers(NULL)
+{
+ claim_alloc(gTraceMemStat, this);
+ mBuffers = new AccumulatorBufferGroup();
+ claim_alloc(gTraceMemStat, mBuffers);
+ setPlayState(state);
+}
+
+Recording::Recording( const Recording& other )
+: mActiveBuffers(NULL)
+{
+ claim_alloc(gTraceMemStat, this);
+ *this = other;
+}
+
+Recording& Recording::operator = (const Recording& other)
+{
+ // this will allow us to seamlessly start without affecting any data we've acquired from other
+ setPlayState(PAUSED);
+
+ const_cast<Recording&>(other).update();
+ EPlayState other_play_state = other.getPlayState();
+
+ mBuffers = other.mBuffers;
+
+ // above call will clear mElapsedSeconds as a side effect, so copy it here
+ mElapsedSeconds = other.mElapsedSeconds;
+ mSamplingTimer = other.mSamplingTimer;
+
+ setPlayState(other_play_state);
+
+ return *this;
+}
+
+
+Recording::~Recording()
+{
+ disclaim_alloc(gTraceMemStat, this);
+ disclaim_alloc(gTraceMemStat, mBuffers);
+
+ // allow recording destruction without thread recorder running,
+ // otherwise thread shutdown could crash if a recording outlives the thread recorder
+ // besides, recording construction and destruction is fine without a recorder...just don't attempt to start one
+ if (isStarted() && LLTrace::get_thread_recorder().notNull())
+ {
+ LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
+ }
+}
+
+// brings recording to front of recorder stack, with up to date info
+void Recording::update()
+{
+#if LL_TRACE_ENABLED
+ if (isStarted())
+ {
+ mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+
+ // must have
+ llassert(mActiveBuffers != NULL
+ && LLTrace::get_thread_recorder().notNull());
+
+ if(!mActiveBuffers->isCurrent())
+ {
+ AccumulatorBufferGroup* buffers = mBuffers.write();
+ LLTrace::get_thread_recorder()->deactivate(buffers);
+ mActiveBuffers = LLTrace::get_thread_recorder()->activate(buffers);
+ }
+
+ mSamplingTimer.reset();
+ }
+#endif
+}
+
+void Recording::handleReset()
+{
+#if LL_TRACE_ENABLED
+ mBuffers.write()->reset();
+
+ mElapsedSeconds = F64Seconds(0.0);
+ mSamplingTimer.reset();
+#endif
+}
+
+void Recording::handleStart()
+{
+#if LL_TRACE_ENABLED
+ mSamplingTimer.reset();
+ mBuffers.setStayUnique(true);
+ // must have thread recorder running on this thread
+ llassert(LLTrace::get_thread_recorder().notNull());
+ mActiveBuffers = LLTrace::get_thread_recorder()->activate(mBuffers.write());
+#endif
+}
+
+void Recording::handleStop()
+{
+#if LL_TRACE_ENABLED
+ mElapsedSeconds += mSamplingTimer.getElapsedTimeF64();
+ // must have thread recorder running on this thread
+ llassert(LLTrace::get_thread_recorder().notNull());
+ LLTrace::get_thread_recorder()->deactivate(mBuffers.write());
+ mActiveBuffers = NULL;
+ mBuffers.setStayUnique(false);
+#endif
+}
+
+void Recording::handleSplitTo(Recording& other)
+{
+#if LL_TRACE_ENABLED
+ mBuffers.write()->handOffTo(*other.mBuffers.write());
+#endif
+}
+
+void Recording::appendRecording( Recording& other )
+{
+#if LL_TRACE_ENABLED
+ update();
+ other.update();
+ mBuffers.write()->append(*other.mBuffers);
+ mElapsedSeconds += other.mElapsedSeconds;
+#endif
+}
+
+bool Recording::hasValue(const StatType<TimeBlockAccumulator>& stat)
+{
+ update();
+ const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+ const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+ return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
+}
+
+F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator>& stat)
+{
+ update();
+ const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+ const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+ return F64Seconds((F64)(accumulator.mTotalTimeCounter) + (F64)(active_accumulator ? active_accumulator->mTotalTimeCounter : 0))
+ / (F64)LLTrace::BlockTimer::countsPerSecond();
+}
+
+F64Seconds Recording::getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
+{
+ update();
+ const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+ const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+ return F64Seconds(((F64)(accumulator.mSelfTimeCounter) + (F64)(active_accumulator ? active_accumulator->mSelfTimeCounter : 0)) / (F64)LLTrace::BlockTimer::countsPerSecond());
+}
+
+
+S32 Recording::getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
+{
+ update();
+ const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+ const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+ return accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0);
+}
+
+F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator>& stat)
+{
+ update();
+ const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+ const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+
+ return F64Seconds((F64)(accumulator.mTotalTimeCounter + (active_accumulator ? active_accumulator->mTotalTimeCounter : 0))
+ / ((F64)LLTrace::BlockTimer::countsPerSecond() * mElapsedSeconds.value()));
+}
+
+F64Seconds Recording::getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat)
+{
+ update();
+ const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+ const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+
+ return F64Seconds((F64)(accumulator.mSelfTimeCounter + (active_accumulator ? active_accumulator->mSelfTimeCounter : 0))
+ / ((F64)LLTrace::BlockTimer::countsPerSecond() * mElapsedSeconds.value()));
+}
+
+F32 Recording::getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat)
+{
+ update();
+ const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()];
+ const TimeBlockAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mStackTimers[stat.getIndex()] : NULL;
+ return (F32)(accumulator.mCalls + (active_accumulator ? active_accumulator->mCalls : 0)) / mElapsedSeconds.value();
+}
+
+bool Recording::hasValue(const StatType<MemAccumulator>& stat)
+{
+ update();
+ const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+ const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+ return accumulator.mSize.hasValue() || (active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.hasValue() : false);
+}
+
+F64Kilobytes Recording::getMin(const StatType<MemAccumulator>& stat)
+{
+ update();
+ const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+ const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+ return F64Bytes(llmin(accumulator.mSize.getMin(), (active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.getMin() : F32_MAX)));
+}
+
+F64Kilobytes Recording::getMean(const StatType<MemAccumulator>& stat)
+{
+ update();
+ const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+ const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+
+ if (active_accumulator && active_accumulator->mSize.hasValue())
+ {
+ return F64Bytes(lerp(accumulator.mSize.getMean(), active_accumulator->mSize.getMean(), active_accumulator->mSize.getSampleCount() / (accumulator.mSize.getSampleCount() + active_accumulator->mSize.getSampleCount())));
+ }
+ else
+ {
+ return F64Bytes(accumulator.mSize.getMean());
+ }
+}
+
+F64Kilobytes Recording::getMax(const StatType<MemAccumulator>& stat)
+{
+ update();
+ const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+ const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+ return F64Bytes(llmax(accumulator.mSize.getMax(), active_accumulator && active_accumulator->mSize.hasValue() ? active_accumulator->mSize.getMax() : F32_MIN));
+}
+
+F64Kilobytes Recording::getStandardDeviation(const StatType<MemAccumulator>& stat)
+{
+ update();
+ const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+ const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+ if (active_accumulator && active_accumulator->hasValue())
+ {
+ F64 sum_of_squares = SampleAccumulator::mergeSumsOfSquares(accumulator.mSize, active_accumulator->mSize);
+ return F64Bytes(sqrtf(sum_of_squares / (accumulator.mSize.getSamplingTime().value() + active_accumulator->mSize.getSamplingTime().value())));
+ }
+ else
+ {
+ return F64Bytes(accumulator.mSize.getStandardDeviation());
+ }
+}
+
+F64Kilobytes Recording::getLastValue(const StatType<MemAccumulator>& stat)
+{
+ update();
+ const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+ const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+ return F64Bytes(active_accumulator ? active_accumulator->mSize.getLastValue() : accumulator.mSize.getLastValue());
+}
+
+bool Recording::hasValue(const StatType<MemAccumulator::AllocationFacet>& stat)
+{
+ update();
+ const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+ const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+ return accumulator.mAllocations.hasValue() || (active_accumulator ? active_accumulator->mAllocations.hasValue() : false);
+}
+
+F64Kilobytes Recording::getSum(const StatType<MemAccumulator::AllocationFacet>& stat)
+{
+ update();
+ const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+ const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+ return F64Bytes(accumulator.mAllocations.getSum() + (active_accumulator ? active_accumulator->mAllocations.getSum() : 0));
+}
+
+F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::AllocationFacet>& stat)
+{
+ update();
+ const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+ const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+ return F64Bytes((accumulator.mAllocations.getSum() + (active_accumulator ? active_accumulator->mAllocations.getSum() : 0)) / mElapsedSeconds.value());
+}
+
+S32 Recording::getSampleCount(const StatType<MemAccumulator::AllocationFacet>& stat)
+{
+ update();
+ const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+ const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+ return accumulator.mAllocations.getSampleCount() + (active_accumulator ? active_accumulator->mAllocations.getSampleCount() : 0);
+}
+
+bool Recording::hasValue(const StatType<MemAccumulator::DeallocationFacet>& stat)
+{
+ update();
+ const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+ const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+ return accumulator.mDeallocations.hasValue() || (active_accumulator ? active_accumulator->mDeallocations.hasValue() : false);
+}
+
+
+F64Kilobytes Recording::getSum(const StatType<MemAccumulator::DeallocationFacet>& stat)
+{
+ update();
+ const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+ const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+ return F64Bytes(accumulator.mDeallocations.getSum() + (active_accumulator ? active_accumulator->mDeallocations.getSum() : 0));
+}
+
+F64Kilobytes Recording::getPerSec(const StatType<MemAccumulator::DeallocationFacet>& stat)
+{
+ update();
+ const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+ const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+ return F64Bytes((accumulator.mDeallocations.getSum() + (active_accumulator ? active_accumulator->mDeallocations.getSum() : 0)) / mElapsedSeconds.value());
+}
+
+S32 Recording::getSampleCount(const StatType<MemAccumulator::DeallocationFacet>& stat)
+{
+ update();
+ const MemAccumulator& accumulator = mBuffers->mMemStats[stat.getIndex()];
+ const MemAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mMemStats[stat.getIndex()] : NULL;
+ return accumulator.mDeallocations.getSampleCount() + (active_accumulator ? active_accumulator->mDeallocations.getSampleCount() : 0);
+}
+
+bool Recording::hasValue(const StatType<CountAccumulator>& stat)
+{
+ update();
+ const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
+ const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
+ return accumulator.hasValue() || (active_accumulator ? active_accumulator->hasValue() : false);
+}
+
+F64 Recording::getSum(const StatType<CountAccumulator>& stat)
+{
+ update();
+ const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
+ const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
+ return accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0);
+}
+
+F64 Recording::getPerSec( const StatType<CountAccumulator>& stat )
+{
+ update();
+ const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
+ const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
+ F64 sum = accumulator.getSum() + (active_accumulator ? active_accumulator->getSum() : 0);
+ return sum / mElapsedSeconds.value();
+}
+
+S32 Recording::getSampleCount( const StatType<CountAccumulator>& stat )
+{
+ update();
+ const CountAccumulator& accumulator = mBuffers->mCounts[stat.getIndex()];
+ const CountAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mCounts[stat.getIndex()] : NULL;
+ return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0);
+}
+
+bool Recording::hasValue(const StatType<SampleAccumulator>& stat)
+{
+ update();
+ const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+ const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+ return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
+}
+
+F64 Recording::getMin( const StatType<SampleAccumulator>& stat )
+{
+ update();
+ const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+ const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+ return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX);
+}
+
+F64 Recording::getMax( const StatType<SampleAccumulator>& stat )
+{
+ update();
+ const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+ const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+ return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN);
+}
+
+F64 Recording::getMean( const StatType<SampleAccumulator>& stat )
+{
+ update();
+ const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+ const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+ if (active_accumulator && active_accumulator->hasValue())
+ {
+ return lerp(accumulator.getMean(), active_accumulator->getMean(), active_accumulator->getSampleCount() / (accumulator.getSampleCount() + active_accumulator->getSampleCount()));
+ }
+ else
+ {
+ return accumulator.getMean();
+ }
+}
+
+F64 Recording::getStandardDeviation( const StatType<SampleAccumulator>& stat )
+{
+ update();
+ const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+ const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+
+ if (active_accumulator && active_accumulator->hasValue())
+ {
+ F64 sum_of_squares = SampleAccumulator::mergeSumsOfSquares(accumulator, *active_accumulator);
+ return sqrtf(sum_of_squares / (accumulator.getSamplingTime() + active_accumulator->getSamplingTime()));
+ }
+ else
+ {
+ return accumulator.getStandardDeviation();
+ }
+}
+
+F64 Recording::getLastValue( const StatType<SampleAccumulator>& stat )
+{
+ update();
+ const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+ const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+ return (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getLastValue() : accumulator.getLastValue());
+}
+
+S32 Recording::getSampleCount( const StatType<SampleAccumulator>& stat )
+{
+ update();
+ const SampleAccumulator& accumulator = mBuffers->mSamples[stat.getIndex()];
+ const SampleAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mSamples[stat.getIndex()] : NULL;
+ return accumulator.getSampleCount() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSampleCount() : 0);
+}
+
+bool Recording::hasValue(const StatType<EventAccumulator>& stat)
+{
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+ return accumulator.hasValue() || (active_accumulator && active_accumulator->hasValue());
+}
+
+F64 Recording::getSum( const StatType<EventAccumulator>& stat)
+{
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+ return (F64)(accumulator.getSum() + (active_accumulator && active_accumulator->hasValue() ? active_accumulator->getSum() : 0));
+}
+
+F64 Recording::getMin( const StatType<EventAccumulator>& stat )
+{
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+ return llmin(accumulator.getMin(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMin() : F32_MAX);
+}
+
+F64 Recording::getMax( const StatType<EventAccumulator>& stat )
+{
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+ return llmax(accumulator.getMax(), active_accumulator && active_accumulator->hasValue() ? active_accumulator->getMax() : F32_MIN);
+}
+
+F64 Recording::getMean( const StatType<EventAccumulator>& stat )
+{
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+ if (active_accumulator && active_accumulator->hasValue())
+ {
+ return lerp(accumulator.getMean(), active_accumulator->getMean(), active_accumulator->getSampleCount() / (accumulator.getSampleCount() + active_accumulator->getSampleCount()));
+ }
+ else
+ {
+ return accumulator.getMean();
+ }
+}
+
+F64 Recording::getStandardDeviation( const StatType<EventAccumulator>& stat )
+{
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+
+ if (active_accumulator && active_accumulator->hasValue())
+ {
+ F64 sum_of_squares = EventAccumulator::mergeSumsOfSquares(accumulator, *active_accumulator);
+ return sqrtf(sum_of_squares / (accumulator.getSampleCount() + active_accumulator->getSampleCount()));
+ }
+ else
+ {
+ return accumulator.getStandardDeviation();
+ }
+}
+
+F64 Recording::getLastValue( const StatType<EventAccumulator>& stat )
+{
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+ return active_accumulator ? active_accumulator->getLastValue() : accumulator.getLastValue();
+}
+
+S32 Recording::getSampleCount( const StatType<EventAccumulator>& stat )
+{
+ update();
+ const EventAccumulator& accumulator = mBuffers->mEvents[stat.getIndex()];
+ const EventAccumulator* active_accumulator = mActiveBuffers ? &mActiveBuffers->mEvents[stat.getIndex()] : NULL;
+ return accumulator.getSampleCount() + (active_accumulator ? active_accumulator->getSampleCount() : 0);
+}
+
+///////////////////////////////////////////////////////////////////////
+// PeriodicRecording
+///////////////////////////////////////////////////////////////////////
+
+PeriodicRecording::PeriodicRecording( S32 num_periods, EPlayState state)
+: mAutoResize(num_periods == 0),
+ mCurPeriod(0),
+ mNumRecordedPeriods(0),
+ mRecordingPeriods(num_periods ? num_periods : 1)
+{
+ setPlayState(state);
+ claim_alloc(gTraceMemStat, this);
+}
+
+PeriodicRecording::~PeriodicRecording()
+{
+ disclaim_alloc(gTraceMemStat, this);
+}
+
+void PeriodicRecording::nextPeriod()
+{
+ if (mAutoResize)
+ {
+ mRecordingPeriods.push_back(Recording());
+ }
+
+ Recording& old_recording = getCurRecording();
+ mCurPeriod = (mCurPeriod + 1) % mRecordingPeriods.size();
+ old_recording.splitTo(getCurRecording());
+
+ mNumRecordedPeriods = llmin((S32)mRecordingPeriods.size() - 1, mNumRecordedPeriods + 1);
+}
+
+void PeriodicRecording::appendRecording(Recording& recording)
+{
+ getCurRecording().appendRecording(recording);
+ nextPeriod();
+}
+
+
+void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other )
+{
+ if (other.mRecordingPeriods.empty()) return;
+
+ getCurRecording().update();
+ other.getCurRecording().update();
+
+ const S32 other_recording_slots = other.mRecordingPeriods.size();
+ const S32 other_num_recordings = other.getNumRecordedPeriods();
+ const S32 other_current_recording_index = other.mCurPeriod;
+ const S32 other_oldest_recording_index = (other_current_recording_index + other_recording_slots - other_num_recordings) % other_recording_slots;
+
+ // append first recording into our current slot
+ getCurRecording().appendRecording(other.mRecordingPeriods[other_oldest_recording_index]);
+
+ // from now on, add new recordings for everything after the first
+ S32 other_index = (other_oldest_recording_index + 1) % other_recording_slots;
+
+ if (mAutoResize)
+ {
+ // push back recordings for everything in the middle
+ S32 other_index = (other_oldest_recording_index + 1) % other_recording_slots;
+ while (other_index != other_current_recording_index)
+ {
+ mRecordingPeriods.push_back(other.mRecordingPeriods[other_index]);
+ other_index = (other_index + 1) % other_recording_slots;
+ }
+
+ // add final recording, if it wasn't already added as the first
+ if (other_num_recordings > 1)
+ {
+ mRecordingPeriods.push_back(other.mRecordingPeriods[other_current_recording_index]);
+ }
+
+ mCurPeriod = mRecordingPeriods.size() - 1;
+ mNumRecordedPeriods = mRecordingPeriods.size() - 1;
+ }
+ else
+ {
+ S32 num_to_copy = llmin((S32)mRecordingPeriods.size(), (S32)other_num_recordings);
+
+ std::vector<Recording>::iterator src_it = other.mRecordingPeriods.begin() + other_index ;
+ std::vector<Recording>::iterator dest_it = mRecordingPeriods.begin() + mCurPeriod;
+
+ // already consumed the first recording from other, so start counting at 1
+ for(S32 i = 1; i < num_to_copy; i++)
+ {
+ *dest_it = *src_it;
+
+ if (++src_it == other.mRecordingPeriods.end())
+ {
+ src_it = other.mRecordingPeriods.begin();
+ }
+
+ if (++dest_it == mRecordingPeriods.end())
+ {
+ dest_it = mRecordingPeriods.begin();
+ }
+ }
+
+ // want argument to % to be positive, otherwise result could be negative and thus out of bounds
+ llassert(num_to_copy >= 1);
+ // advance to last recording period copied, and make that our current period
+ mCurPeriod = (mCurPeriod + num_to_copy - 1) % mRecordingPeriods.size();
+ mNumRecordedPeriods = llmin((S32)mRecordingPeriods.size() - 1, mNumRecordedPeriods + num_to_copy - 1);
+ }
+
+ // end with fresh period, otherwise next appendPeriodicRecording() will merge the first
+ // recording period with the last one appended here
+ nextPeriod();
+ getCurRecording().setPlayState(getPlayState());
+}
+
+F64Seconds PeriodicRecording::getDuration() const
+{
+ F64Seconds duration;
+ S32 num_periods = mRecordingPeriods.size();
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ S32 index = (mCurPeriod + num_periods - i) % num_periods;
+ duration += mRecordingPeriods[index].getDuration();
+ }
+ return duration;
+}
+
+
+LLTrace::Recording PeriodicRecording::snapshotCurRecording() const
+{
+ Recording recording_copy(getCurRecording());
+ recording_copy.stop();
+ return recording_copy;
+}
+
+
+Recording& PeriodicRecording::getLastRecording()
+{
+ return getPrevRecording(1);
+}
+
+const Recording& PeriodicRecording::getLastRecording() const
+{
+ return getPrevRecording(1);
+}
+
+Recording& PeriodicRecording::getCurRecording()
+{
+ return mRecordingPeriods[mCurPeriod];
+}
+
+const Recording& PeriodicRecording::getCurRecording() const
+{
+ return mRecordingPeriods[mCurPeriod];
+}
+
+Recording& PeriodicRecording::getPrevRecording( S32 offset )
+{
+ S32 num_periods = mRecordingPeriods.size();
+ offset = llclamp(offset, 0, num_periods - 1);
+ return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
+}
+
+const Recording& PeriodicRecording::getPrevRecording( S32 offset ) const
+{
+ S32 num_periods = mRecordingPeriods.size();
+ offset = llclamp(offset, 0, num_periods - 1);
+ return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods];
+}
+
+void PeriodicRecording::handleStart()
+{
+ getCurRecording().start();
+}
+
+void PeriodicRecording::handleStop()
+{
+ getCurRecording().pause();
+}
+
+void PeriodicRecording::handleReset()
+{
+ getCurRecording().stop();
+
+ if (mAutoResize)
+ {
+ mRecordingPeriods.clear();
+ mRecordingPeriods.push_back(Recording());
+ }
+ else
+ {
+ for (std::vector<Recording>::iterator it = mRecordingPeriods.begin(), end_it = mRecordingPeriods.end();
+ it != end_it;
+ ++it)
+ {
+ it->reset();
+ }
+ }
+ mCurPeriod = 0;
+ mNumRecordedPeriods = 0;
+ getCurRecording().setPlayState(getPlayState());
+}
+
+void PeriodicRecording::handleSplitTo(PeriodicRecording& other)
+{
+ getCurRecording().splitTo(other.getCurRecording());
+}
+
+F64 PeriodicRecording::getPeriodMin( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+{
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ bool has_value = false;
+ F64 min_val = std::numeric_limits<F64>::max();
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ min_val = llmin(min_val, recording.getMin(stat));
+ has_value = true;
+ }
+ }
+
+ return has_value
+ ? min_val
+ : NaN;
+}
+
+F64 PeriodicRecording::getPeriodMax( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+{
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ bool has_value = false;
+ F64 max_val = std::numeric_limits<F64>::min();
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ max_val = llmax(max_val, recording.getMax(stat));
+ has_value = true;
+ }
+ }
+
+ return has_value
+ ? max_val
+ : NaN;
+}
+
+// calculates means using aggregates per period
+F64 PeriodicRecording::getPeriodMean( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+{
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ F64 mean = 0;
+ S32 valid_period_count = 0;
+
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ mean += recording.getMean(stat);
+ valid_period_count++;
+ }
+ }
+
+ return valid_period_count
+ ? mean / (F64)valid_period_count
+ : NaN;
+}
+
+
+F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<EventAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+{
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ F64 period_mean = getPeriodMean(stat, num_periods);
+ F64 sum_of_squares = 0;
+ S32 valid_period_count = 0;
+
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ F64 delta = recording.getMean(stat) - period_mean;
+ sum_of_squares += delta * delta;
+ valid_period_count++;
+ }
+ }
+
+ return valid_period_count
+ ? sqrt((F64)sum_of_squares / (F64)valid_period_count)
+ : NaN;
+}
+
+F64 PeriodicRecording::getPeriodMin( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+{
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ bool has_value = false;
+ F64 min_val = std::numeric_limits<F64>::max();
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ min_val = llmin(min_val, recording.getMin(stat));
+ has_value = true;
+ }
+ }
+
+ return has_value
+ ? min_val
+ : NaN;
+}
+
+F64 PeriodicRecording::getPeriodMax(const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/)
+{
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ bool has_value = false;
+ F64 max_val = std::numeric_limits<F64>::min();
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ max_val = llmax(max_val, recording.getMax(stat));
+ has_value = true;
+ }
+ }
+
+ return has_value
+ ? max_val
+ : NaN;
+}
+
+
+F64 PeriodicRecording::getPeriodMean( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+{
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ S32 valid_period_count = 0;
+ F64 mean = 0;
+
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ mean += recording.getMean(stat);
+ valid_period_count++;
+ }
+ }
+
+ return valid_period_count
+ ? mean / F64(valid_period_count)
+ : NaN;
+}
+
+F64 PeriodicRecording::getPeriodStandardDeviation( const StatType<SampleAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+{
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ F64 period_mean = getPeriodMean(stat, num_periods);
+ S32 valid_period_count = 0;
+ F64 sum_of_squares = 0;
+
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ F64 delta = recording.getMean(stat) - period_mean;
+ sum_of_squares += delta * delta;
+ valid_period_count++;
+ }
+ }
+
+ return valid_period_count
+ ? sqrt(sum_of_squares / (F64)valid_period_count)
+ : NaN;
+}
+
+
+F64Kilobytes PeriodicRecording::getPeriodMin( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+{
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ F64Kilobytes min_val(std::numeric_limits<F64>::max());
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ min_val = llmin(min_val, recording.getMin(stat));
+ }
+
+ return min_val;
+}
+
+F64Kilobytes PeriodicRecording::getPeriodMin(const MemStatHandle& stat, S32 num_periods)
+{
+ return getPeriodMin(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
+}
+
+F64Kilobytes PeriodicRecording::getPeriodMax(const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/)
+{
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ F64Kilobytes max_val(0.0);
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ max_val = llmax(max_val, recording.getMax(stat));
+ }
+
+ return max_val;
+}
+
+F64Kilobytes PeriodicRecording::getPeriodMax(const MemStatHandle& stat, S32 num_periods)
+{
+ return getPeriodMax(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
+}
+
+F64Kilobytes PeriodicRecording::getPeriodMean( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+{
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ F64Kilobytes mean(0);
+
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ mean += recording.getMean(stat);
+ }
+
+ return mean / F64(num_periods);
+}
+
+F64Kilobytes PeriodicRecording::getPeriodMean(const MemStatHandle& stat, S32 num_periods)
+{
+ return getPeriodMean(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
+}
+
+F64Kilobytes PeriodicRecording::getPeriodStandardDeviation( const StatType<MemAccumulator>& stat, S32 num_periods /*= S32_MAX*/ )
+{
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ F64Kilobytes period_mean = getPeriodMean(stat, num_periods);
+ S32 valid_period_count = 0;
+ F64 sum_of_squares = 0;
+
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ F64Kilobytes delta = recording.getMean(stat) - period_mean;
+ sum_of_squares += delta.value() * delta.value();
+ valid_period_count++;
+ }
+ }
+
+ return F64Kilobytes(valid_period_count
+ ? sqrt(sum_of_squares / (F64)valid_period_count)
+ : NaN);
+}
+
+F64Kilobytes PeriodicRecording::getPeriodStandardDeviation(const MemStatHandle& stat, S32 num_periods)
+{
+ return getPeriodStandardDeviation(static_cast<const StatType<MemAccumulator>&>(stat), num_periods);
+}
+
+///////////////////////////////////////////////////////////////////////
+// ExtendableRecording
+///////////////////////////////////////////////////////////////////////
+
+void ExtendableRecording::extend()
+{
+ // push the data back to accepted recording
+ mAcceptedRecording.appendRecording(mPotentialRecording);
+ // flush data, so we can start from scratch
+ mPotentialRecording.reset();
+}
+
+void ExtendableRecording::handleStart()
+{
+ mPotentialRecording.start();
+}
+
+void ExtendableRecording::handleStop()
+{
+ mPotentialRecording.pause();
+}
+
+void ExtendableRecording::handleReset()
+{
+ mAcceptedRecording.reset();
+ mPotentialRecording.reset();
+}
+
+void ExtendableRecording::handleSplitTo(ExtendableRecording& other)
+{
+ mPotentialRecording.splitTo(other.mPotentialRecording);
+}
+
+
+///////////////////////////////////////////////////////////////////////
+// ExtendablePeriodicRecording
+///////////////////////////////////////////////////////////////////////
+
+
+ExtendablePeriodicRecording::ExtendablePeriodicRecording()
+: mAcceptedRecording(0),
+ mPotentialRecording(0)
+{}
+
+void ExtendablePeriodicRecording::extend()
+{
+ // push the data back to accepted recording
+ mAcceptedRecording.appendPeriodicRecording(mPotentialRecording);
+ // flush data, so we can start from scratch
+ mPotentialRecording.reset();
+}
+
+
+void ExtendablePeriodicRecording::handleStart()
+{
+ mPotentialRecording.start();
+}
+
+void ExtendablePeriodicRecording::handleStop()
+{
+ mPotentialRecording.pause();
+}
+
+void ExtendablePeriodicRecording::handleReset()
+{
+ mAcceptedRecording.reset();
+ mPotentialRecording.reset();
+}
+
+void ExtendablePeriodicRecording::handleSplitTo(ExtendablePeriodicRecording& other)
+{
+ mPotentialRecording.splitTo(other.mPotentialRecording);
+}
+
+
+PeriodicRecording& get_frame_recording()
+{
+ static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(200, PeriodicRecording::STARTED));
+ return *sRecording;
+}
+
+}
+
+void LLStopWatchControlsMixinCommon::start()
+{
+ switch (mPlayState)
+ {
+ case STOPPED:
+ handleReset();
+ handleStart();
+ mPlayState = STARTED;
+ break;
+ case PAUSED:
+ handleStart();
+ mPlayState = STARTED;
+ break;
+ case STARTED:
+ break;
+ default:
+ llassert(false);
+ break;
+ }
+}
+
+void LLStopWatchControlsMixinCommon::stop()
+{
+ switch (mPlayState)
+ {
+ case STOPPED:
+ break;
+ case PAUSED:
+ mPlayState = STOPPED;
+ break;
+ case STARTED:
+ handleStop();
+ mPlayState = STOPPED;
+ break;
+ default:
+ llassert(false);
+ break;
+ }
+}
+
+void LLStopWatchControlsMixinCommon::pause()
+{
+ switch (mPlayState)
+ {
+ case STOPPED:
+ // stay stopped, don't go to pause
+ break;
+ case PAUSED:
+ break;
+ case STARTED:
+ handleStop();
+ mPlayState = PAUSED;
+ break;
+ default:
+ llassert(false);
+ break;
+ }
+}
+
+void LLStopWatchControlsMixinCommon::unpause()
+{
+ switch (mPlayState)
+ {
+ case STOPPED:
+ // stay stopped, don't start
+ break;
+ case PAUSED:
+ handleStart();
+ mPlayState = STARTED;
+ break;
+ case STARTED:
+ break;
+ default:
+ llassert(false);
+ break;
+ }
+}
+
+void LLStopWatchControlsMixinCommon::resume()
+{
+ switch (mPlayState)
+ {
+ case STOPPED:
+ handleStart();
+ mPlayState = STARTED;
+ break;
+ case PAUSED:
+ handleStart();
+ mPlayState = STARTED;
+ break;
+ case STARTED:
+ break;
+ default:
+ llassert(false);
+ break;
+ }
+}
+
+void LLStopWatchControlsMixinCommon::restart()
+{
+ switch (mPlayState)
+ {
+ case STOPPED:
+ handleReset();
+ handleStart();
+ mPlayState = STARTED;
+ break;
+ case PAUSED:
+ handleReset();
+ handleStart();
+ mPlayState = STARTED;
+ break;
+ case STARTED:
+ handleReset();
+ break;
+ default:
+ llassert(false);
+ break;
+ }
+}
+
+void LLStopWatchControlsMixinCommon::reset()
+{
+ handleReset();
+}
+
+void LLStopWatchControlsMixinCommon::setPlayState( EPlayState state )
+{
+ switch(state)
+ {
+ case STOPPED:
+ stop();
+ break;
+ case PAUSED:
+ pause();
+ break;
+ case STARTED:
+ start();
+ break;
+ default:
+ llassert(false);
+ break;
+ }
+
+ mPlayState = state;
+}
diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h
new file mode 100644
index 0000000000..d0b4a842a6
--- /dev/null
+++ b/indra/llcommon/lltracerecording.h
@@ -0,0 +1,670 @@
+/**
+ * @file lltracerecording.h
+ * @brief Sampling object for collecting runtime statistics originating from lltrace.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRACERECORDING_H
+#define LL_LLTRACERECORDING_H
+
+#include "stdtypes.h"
+#include "llpreprocessor.h"
+
+#include "lltimer.h"
+#include "lltraceaccumulators.h"
+#include "llpointer.h"
+
+class LLStopWatchControlsMixinCommon
+{
+public:
+ virtual ~LLStopWatchControlsMixinCommon() {}
+
+ enum EPlayState
+ {
+ STOPPED,
+ PAUSED,
+ STARTED
+ };
+
+ void start(); // moves to started state, resetting if stopped
+ void stop(); // moves to stopped state
+ void pause(); // moves to paused state, unless stopped
+ void unpause(); // moves to started state if paused
+ void resume(); // moves to started state, without resetting
+ void restart(); // moves to started state, always resetting
+ void reset(); // resets
+
+ bool isStarted() const { return mPlayState == STARTED; }
+ bool isPaused() const { return mPlayState == PAUSED; }
+ bool isStopped() const { return mPlayState == STOPPED; }
+
+ EPlayState getPlayState() const { return mPlayState; }
+ // force play state to specific value by calling appropriate handle* methods
+ void setPlayState(EPlayState state);
+
+protected:
+ LLStopWatchControlsMixinCommon()
+ : mPlayState(STOPPED)
+ {}
+
+private:
+ // override these methods to provide started/stopped semantics
+
+ // activate behavior (without reset)
+ virtual void handleStart() = 0;
+ // deactivate behavior
+ virtual void handleStop() = 0;
+ // clear accumulated state, may be called while started
+ virtual void handleReset() = 0;
+
+ EPlayState mPlayState;
+};
+
+template<typename DERIVED>
+class LLStopWatchControlsMixin
+: public LLStopWatchControlsMixinCommon
+{
+public:
+
+ typedef LLStopWatchControlsMixin<DERIVED> self_t;
+ virtual void splitTo(DERIVED& other)
+ {
+ EPlayState play_state = getPlayState();
+ stop();
+ other.reset();
+
+ handleSplitTo(other);
+
+ other.setPlayState(play_state);
+ }
+
+ virtual void splitFrom(DERIVED& other)
+ {
+ static_cast<self_t&>(other).handleSplitTo(*static_cast<DERIVED*>(this));
+ }
+private:
+ self_t& operator = (const self_t& other)
+ {
+ // don't do anything, derived class must implement logic
+ }
+
+ // atomically stop this object while starting the other
+ // no data can be missed in between stop and start
+ virtual void handleSplitTo(DERIVED& other) {};
+
+};
+
+namespace LLTrace
+{
+ template<typename T>
+ class StatType;
+
+ template<typename T>
+ class CountStatHandle;
+
+ template<typename T>
+ class SampleStatHandle;
+
+ template<typename T>
+ class EventStatHandle;
+
+ class MemStatHandle;
+
+ template<typename T>
+ struct RelatedTypes
+ {
+ typedef F64 fractional_t;
+ typedef T sum_t;
+ };
+
+ template<typename T, typename UNIT_T>
+ struct RelatedTypes<LLUnit<T, UNIT_T> >
+ {
+ typedef LLUnit<typename RelatedTypes<T>::fractional_t, UNIT_T> fractional_t;
+ typedef LLUnit<typename RelatedTypes<T>::sum_t, UNIT_T> sum_t;
+ };
+
+ template<>
+ struct RelatedTypes<bool>
+ {
+ typedef F64 fractional_t;
+ typedef S32 sum_t;
+ };
+
+ class Recording
+ : public LLStopWatchControlsMixin<Recording>
+ {
+ public:
+ Recording(EPlayState state = LLStopWatchControlsMixinCommon::STOPPED);
+
+ Recording(const Recording& other);
+ ~Recording();
+
+ Recording& operator = (const Recording& other);
+
+ // accumulate data from subsequent, non-overlapping recording
+ void appendRecording(Recording& other);
+
+ // grab latest recorded data
+ void update();
+
+ // ensure that buffers are exclusively owned by this recording
+ void makeUnique() { mBuffers.makeUnique(); }
+
+ // Timer accessors
+ bool hasValue(const StatType<TimeBlockAccumulator>& stat);
+ F64Seconds getSum(const StatType<TimeBlockAccumulator>& stat);
+ F64Seconds getSum(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat);
+ S32 getSum(const StatType<TimeBlockAccumulator::CallCountFacet>& stat);
+
+ F64Seconds getPerSec(const StatType<TimeBlockAccumulator>& stat);
+ F64Seconds getPerSec(const StatType<TimeBlockAccumulator::SelfTimeFacet>& stat);
+ F32 getPerSec(const StatType<TimeBlockAccumulator::CallCountFacet>& stat);
+
+ // Memory accessors
+ bool hasValue(const StatType<MemAccumulator>& stat);
+ F64Kilobytes getMin(const StatType<MemAccumulator>& stat);
+ F64Kilobytes getMean(const StatType<MemAccumulator>& stat);
+ F64Kilobytes getMax(const StatType<MemAccumulator>& stat);
+ F64Kilobytes getStandardDeviation(const StatType<MemAccumulator>& stat);
+ F64Kilobytes getLastValue(const StatType<MemAccumulator>& stat);
+
+ bool hasValue(const StatType<MemAccumulator::AllocationFacet>& stat);
+ F64Kilobytes getSum(const StatType<MemAccumulator::AllocationFacet>& stat);
+ F64Kilobytes getPerSec(const StatType<MemAccumulator::AllocationFacet>& stat);
+ S32 getSampleCount(const StatType<MemAccumulator::AllocationFacet>& stat);
+
+ bool hasValue(const StatType<MemAccumulator::DeallocationFacet>& stat);
+ F64Kilobytes getSum(const StatType<MemAccumulator::DeallocationFacet>& stat);
+ F64Kilobytes getPerSec(const StatType<MemAccumulator::DeallocationFacet>& stat);
+ S32 getSampleCount(const StatType<MemAccumulator::DeallocationFacet>& stat);
+
+ // CountStatHandle accessors
+ bool hasValue(const StatType<CountAccumulator>& stat);
+ F64 getSum(const StatType<CountAccumulator>& stat);
+ template <typename T>
+ typename RelatedTypes<T>::sum_t getSum(const CountStatHandle<T>& stat)
+ {
+ return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const StatType<CountAccumulator>&> (stat));
+ }
+
+ F64 getPerSec(const StatType<CountAccumulator>& stat);
+ template <typename T>
+ typename RelatedTypes<T>::fractional_t getPerSec(const CountStatHandle<T>& stat)
+ {
+ return (typename RelatedTypes<T>::fractional_t)getPerSec(static_cast<const StatType<CountAccumulator>&> (stat));
+ }
+
+ S32 getSampleCount(const StatType<CountAccumulator>& stat);
+
+
+ // SampleStatHandle accessors
+ bool hasValue(const StatType<SampleAccumulator>& stat);
+
+ F64 getMin(const StatType<SampleAccumulator>& stat);
+ template <typename T>
+ T getMin(const SampleStatHandle<T>& stat)
+ {
+ return (T)getMin(static_cast<const StatType<SampleAccumulator>&> (stat));
+ }
+
+ F64 getMax(const StatType<SampleAccumulator>& stat);
+ template <typename T>
+ T getMax(const SampleStatHandle<T>& stat)
+ {
+ return (T)getMax(static_cast<const StatType<SampleAccumulator>&> (stat));
+ }
+
+ F64 getMean(const StatType<SampleAccumulator>& stat);
+ template <typename T>
+ typename RelatedTypes<T>::fractional_t getMean(SampleStatHandle<T>& stat)
+ {
+ return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const StatType<SampleAccumulator>&> (stat));
+ }
+
+ F64 getStandardDeviation(const StatType<SampleAccumulator>& stat);
+ template <typename T>
+ typename RelatedTypes<T>::fractional_t getStandardDeviation(const SampleStatHandle<T>& stat)
+ {
+ return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const StatType<SampleAccumulator>&> (stat));
+ }
+
+ F64 getLastValue(const StatType<SampleAccumulator>& stat);
+ template <typename T>
+ T getLastValue(const SampleStatHandle<T>& stat)
+ {
+ return (T)getLastValue(static_cast<const StatType<SampleAccumulator>&> (stat));
+ }
+
+ S32 getSampleCount(const StatType<SampleAccumulator>& stat);
+
+ // EventStatHandle accessors
+ bool hasValue(const StatType<EventAccumulator>& stat);
+
+ F64 getSum(const StatType<EventAccumulator>& stat);
+ template <typename T>
+ typename RelatedTypes<T>::sum_t getSum(const EventStatHandle<T>& stat)
+ {
+ return (typename RelatedTypes<T>::sum_t)getSum(static_cast<const StatType<EventAccumulator>&> (stat));
+ }
+
+ F64 getMin(const StatType<EventAccumulator>& stat);
+ template <typename T>
+ T getMin(const EventStatHandle<T>& stat)
+ {
+ return (T)getMin(static_cast<const StatType<EventAccumulator>&> (stat));
+ }
+
+ F64 getMax(const StatType<EventAccumulator>& stat);
+ template <typename T>
+ T getMax(const EventStatHandle<T>& stat)
+ {
+ return (T)getMax(static_cast<const StatType<EventAccumulator>&> (stat));
+ }
+
+ F64 getMean(const StatType<EventAccumulator>& stat);
+ template <typename T>
+ typename RelatedTypes<T>::fractional_t getMean(EventStatHandle<T>& stat)
+ {
+ return (typename RelatedTypes<T>::fractional_t)getMean(static_cast<const StatType<EventAccumulator>&> (stat));
+ }
+
+ F64 getStandardDeviation(const StatType<EventAccumulator>& stat);
+ template <typename T>
+ typename RelatedTypes<T>::fractional_t getStandardDeviation(const EventStatHandle<T>& stat)
+ {
+ return (typename RelatedTypes<T>::fractional_t)getStandardDeviation(static_cast<const StatType<EventAccumulator>&> (stat));
+ }
+
+ F64 getLastValue(const StatType<EventAccumulator>& stat);
+ template <typename T>
+ T getLastValue(const EventStatHandle<T>& stat)
+ {
+ return (T)getLastValue(static_cast<const StatType<EventAccumulator>&> (stat));
+ }
+
+ S32 getSampleCount(const StatType<EventAccumulator>& stat);
+
+ F64Seconds getDuration() const { return mElapsedSeconds; }
+
+ protected:
+ friend class ThreadRecorder;
+
+ // implementation for LLStopWatchControlsMixin
+ /*virtual*/ void handleStart();
+ /*virtual*/ void handleStop();
+ /*virtual*/ void handleReset();
+ /*virtual*/ void handleSplitTo(Recording& other);
+
+ // returns data for current thread
+ class ThreadRecorder* getThreadRecorder();
+
+ LLTimer mSamplingTimer;
+ F64Seconds mElapsedSeconds;
+ LLCopyOnWritePointer<AccumulatorBufferGroup> mBuffers;
+ AccumulatorBufferGroup* mActiveBuffers;
+
+ };
+
+ class LL_COMMON_API PeriodicRecording
+ : public LLStopWatchControlsMixin<PeriodicRecording>
+ {
+ public:
+ PeriodicRecording(S32 num_periods, EPlayState state = STOPPED);
+ ~PeriodicRecording();
+
+ void nextPeriod();
+ S32 getNumRecordedPeriods()
+ {
+ // current period counts if not active
+ return mNumRecordedPeriods + (isStarted() ? 0 : 1);
+ }
+
+ F64Seconds getDuration() const;
+
+ void appendPeriodicRecording(PeriodicRecording& other);
+ void appendRecording(Recording& recording);
+ Recording& getLastRecording();
+ const Recording& getLastRecording() const;
+ Recording& getCurRecording();
+ const Recording& getCurRecording() const;
+ Recording& getPrevRecording(S32 offset);
+ const Recording& getPrevRecording(S32 offset) const;
+ Recording snapshotCurRecording() const;
+
+ template <typename T>
+ S32 getSampleCount(const StatType<T>& stat, S32 num_periods = S32_MAX)
+ {
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ S32 num_samples = 0;
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ num_samples += recording.getSampleCount(stat);
+ }
+ return num_samples;
+ }
+
+ //
+ // PERIODIC MIN
+ //
+
+ // catch all for stats that have a defined sum
+ template <typename T>
+ typename T::value_t getPeriodMin(const StatType<T>& stat, S32 num_periods = S32_MAX)
+ {
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ bool has_value = false;
+ typename T::value_t min_val(std::numeric_limits<typename T::value_t>::max());
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ min_val = llmin(min_val, recording.getSum(stat));
+ has_value = true;
+ }
+ }
+
+ return has_value
+ ? min_val
+ : T::getDefaultValue();
+ }
+
+ template<typename T>
+ T getPeriodMin(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ {
+ return T(getPeriodMin(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
+ }
+
+ F64 getPeriodMin(const StatType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
+ template<typename T>
+ T getPeriodMin(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ {
+ return T(getPeriodMin(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
+ }
+
+ F64 getPeriodMin(const StatType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
+ template<typename T>
+ T getPeriodMin(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ {
+ return T(getPeriodMin(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
+ }
+
+ F64Kilobytes getPeriodMin(const StatType<MemAccumulator>& stat, S32 num_periods = S32_MAX);
+ F64Kilobytes getPeriodMin(const MemStatHandle& stat, S32 num_periods = S32_MAX);
+
+ template <typename T>
+ typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMinPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX)
+ {
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ typename RelatedTypes<typename T::value_t>::fractional_t min_val(std::numeric_limits<F64>::max());
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ min_val = llmin(min_val, recording.getPerSec(stat));
+ }
+ return (typename RelatedTypes<typename T::value_t>::fractional_t) min_val;
+ }
+
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodMinPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ {
+ return typename RelatedTypes<T>::fractional_t(getPeriodMinPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
+ }
+
+ //
+ // PERIODIC MAX
+ //
+
+ // catch all for stats that have a defined sum
+ template <typename T>
+ typename T::value_t getPeriodMax(const StatType<T>& stat, S32 num_periods = S32_MAX)
+ {
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ bool has_value = false;
+ typename T::value_t max_val(std::numeric_limits<typename T::value_t>::min());
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.hasValue(stat))
+ {
+ max_val = llmax(max_val, recording.getSum(stat));
+ has_value = true;
+ }
+ }
+
+ return has_value
+ ? max_val
+ : T::getDefaultValue();
+ }
+
+ template<typename T>
+ T getPeriodMax(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ {
+ return T(getPeriodMax(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
+ }
+
+ F64 getPeriodMax(const StatType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
+ template<typename T>
+ T getPeriodMax(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ {
+ return T(getPeriodMax(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
+ }
+
+ F64 getPeriodMax(const StatType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
+ template<typename T>
+ T getPeriodMax(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ {
+ return T(getPeriodMax(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
+ }
+
+ F64Kilobytes getPeriodMax(const StatType<MemAccumulator>& stat, S32 num_periods = S32_MAX);
+ F64Kilobytes getPeriodMax(const MemStatHandle& stat, S32 num_periods = S32_MAX);
+
+ template <typename T>
+ typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMaxPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX)
+ {
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ F64 max_val = std::numeric_limits<F64>::min();
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ max_val = llmax(max_val, recording.getPerSec(stat));
+ }
+ return (typename RelatedTypes<typename T::value_t>::fractional_t)max_val;
+ }
+
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodMaxPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ {
+ return typename RelatedTypes<T>::fractional_t(getPeriodMaxPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
+ }
+
+ //
+ // PERIODIC MEAN
+ //
+
+ // catch all for stats that have a defined sum
+ template <typename T>
+ typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMean(const StatType<T >& stat, S32 num_periods = S32_MAX)
+ {
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ typename RelatedTypes<typename T::value_t>::fractional_t mean(0);
+
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.getDuration() > (F32Seconds)0.f)
+ {
+ mean += recording.getSum(stat);
+ }
+ }
+ return (num_periods
+ ? typename RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods)
+ : typename RelatedTypes<typename T::value_t>::fractional_t(NaN));
+ }
+
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodMean(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ {
+ return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
+ }
+ F64 getPeriodMean(const StatType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodMean(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ {
+ return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
+ }
+
+ F64 getPeriodMean(const StatType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodMean(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ {
+ return typename RelatedTypes<T>::fractional_t(getPeriodMean(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
+ }
+
+ F64Kilobytes getPeriodMean(const StatType<MemAccumulator>& stat, S32 num_periods = S32_MAX);
+ F64Kilobytes getPeriodMean(const MemStatHandle& stat, S32 num_periods = S32_MAX);
+
+ template <typename T>
+ typename RelatedTypes<typename T::value_t>::fractional_t getPeriodMeanPerSec(const StatType<T>& stat, S32 num_periods = S32_MAX)
+ {
+ num_periods = llmin(num_periods, getNumRecordedPeriods());
+
+ typename RelatedTypes<typename T::value_t>::fractional_t mean = 0;
+
+ for (S32 i = 1; i <= num_periods; i++)
+ {
+ Recording& recording = getPrevRecording(i);
+ if (recording.getDuration() > (F32Seconds)0.f)
+ {
+ mean += recording.getPerSec(stat);
+ }
+ }
+
+ return (num_periods
+ ? typename RelatedTypes<typename T::value_t>::fractional_t(mean / num_periods)
+ : typename RelatedTypes<typename T::value_t>::fractional_t(NaN));
+ }
+
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodMeanPerSec(const CountStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ {
+ return typename RelatedTypes<T>::fractional_t(getPeriodMeanPerSec(static_cast<const StatType<CountAccumulator>&>(stat), num_periods));
+ }
+
+ //
+ // PERIODIC STANDARD DEVIATION
+ //
+
+ F64 getPeriodStandardDeviation(const StatType<SampleAccumulator>& stat, S32 num_periods = S32_MAX);
+
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const SampleStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ {
+ return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<SampleAccumulator>&>(stat), num_periods));
+ }
+
+ F64 getPeriodStandardDeviation(const StatType<EventAccumulator>& stat, S32 num_periods = S32_MAX);
+ template<typename T>
+ typename RelatedTypes<T>::fractional_t getPeriodStandardDeviation(const EventStatHandle<T>& stat, S32 num_periods = S32_MAX)
+ {
+ return typename RelatedTypes<T>::fractional_t(getPeriodStandardDeviation(static_cast<const StatType<EventAccumulator>&>(stat), num_periods));
+ }
+
+ F64Kilobytes getPeriodStandardDeviation(const StatType<MemAccumulator>& stat, S32 num_periods = S32_MAX);
+ F64Kilobytes getPeriodStandardDeviation(const MemStatHandle& stat, S32 num_periods = S32_MAX);
+
+ private:
+ // implementation for LLStopWatchControlsMixin
+ /*virtual*/ void handleStart();
+ /*virtual*/ void handleStop();
+ /*virtual*/ void handleReset();
+ /*virtual*/ void handleSplitTo(PeriodicRecording& other);
+
+ private:
+ std::vector<Recording> mRecordingPeriods;
+ const bool mAutoResize;
+ S32 mCurPeriod;
+ S32 mNumRecordedPeriods;
+ };
+
+ PeriodicRecording& get_frame_recording();
+
+ class ExtendableRecording
+ : public LLStopWatchControlsMixin<ExtendableRecording>
+ {
+ public:
+ void extend();
+
+ Recording& getAcceptedRecording() { return mAcceptedRecording; }
+ const Recording& getAcceptedRecording() const {return mAcceptedRecording;}
+
+ Recording& getPotentialRecording() { return mPotentialRecording; }
+ const Recording& getPotentialRecording() const { return mPotentialRecording;}
+
+ private:
+ // implementation for LLStopWatchControlsMixin
+ /*virtual*/ void handleStart();
+ /*virtual*/ void handleStop();
+ /*virtual*/ void handleReset();
+ /*virtual*/ void handleSplitTo(ExtendableRecording& other);
+
+ private:
+ Recording mAcceptedRecording;
+ Recording mPotentialRecording;
+ };
+
+ class ExtendablePeriodicRecording
+ : public LLStopWatchControlsMixin<ExtendablePeriodicRecording>
+ {
+ public:
+ ExtendablePeriodicRecording();
+ void extend();
+
+ PeriodicRecording& getResults() { return mAcceptedRecording; }
+ const PeriodicRecording& getResults() const {return mAcceptedRecording;}
+
+ void nextPeriod() { mPotentialRecording.nextPeriod(); }
+
+ private:
+ // implementation for LLStopWatchControlsMixin
+ /*virtual*/ void handleStart();
+ /*virtual*/ void handleStop();
+ /*virtual*/ void handleReset();
+ /*virtual*/ void handleSplitTo(ExtendablePeriodicRecording& other);
+
+ private:
+ PeriodicRecording mAcceptedRecording;
+ PeriodicRecording mPotentialRecording;
+ };
+}
+
+#endif // LL_LLTRACERECORDING_H
diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp
new file mode 100644
index 0000000000..181fc2f058
--- /dev/null
+++ b/indra/llcommon/lltracethreadrecorder.cpp
@@ -0,0 +1,329 @@
+/**
+ * @file lltracethreadrecorder.cpp
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltracethreadrecorder.h"
+#include "llfasttimer.h"
+#include "lltrace.h"
+
+namespace LLTrace
+{
+extern MemStatHandle gTraceMemStat;
+
+static ThreadRecorder* sMasterThreadRecorder = NULL;
+
+///////////////////////////////////////////////////////////////////////
+// ThreadRecorder
+///////////////////////////////////////////////////////////////////////
+
+ThreadRecorder::ThreadRecorder()
+: mParentRecorder(NULL)
+{
+ init();
+}
+
+void ThreadRecorder::init()
+{
+#if LL_TRACE_ENABLED
+ LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(&mBlockTimerStackRecord);
+ //NB: the ordering of initialization in this function is very fragile due to a large number of implicit dependencies
+ set_thread_recorder(this);
+ BlockTimerStatHandle& root_time_block = BlockTimer::getRootTimeBlock();
+
+ BlockTimerStackRecord* timer_stack = LLThreadLocalSingletonPointer<BlockTimerStackRecord>::getInstance();
+ timer_stack->mTimeBlock = &root_time_block;
+ timer_stack->mActiveTimer = NULL;
+
+ mNumTimeBlockTreeNodes = AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer()->size();
+
+ mTimeBlockTreeNodes = new TimeBlockTreeNode[mNumTimeBlockTreeNodes];
+
+ activate(&mThreadRecordingBuffers);
+
+ // initialize time block parent pointers
+ for (BlockTimerStatHandle::instance_tracker_t::instance_iter it = BlockTimerStatHandle::instance_tracker_t::beginInstances(), end_it = BlockTimerStatHandle::instance_tracker_t::endInstances();
+ it != end_it;
+ ++it)
+ {
+ BlockTimerStatHandle& time_block = static_cast<BlockTimerStatHandle&>(*it);
+ TimeBlockTreeNode& tree_node = mTimeBlockTreeNodes[it->getIndex()];
+ tree_node.mBlock = &time_block;
+ tree_node.mParent = &root_time_block;
+
+ it->getCurrentAccumulator().mParent = &root_time_block;
+ }
+
+ mRootTimer = new BlockTimer(root_time_block);
+ timer_stack->mActiveTimer = mRootTimer;
+
+ BlockTimer::getRootTimeBlock().getCurrentAccumulator().mActiveCount = 1;
+
+ claim_alloc(gTraceMemStat, this);
+ claim_alloc(gTraceMemStat, mRootTimer);
+ claim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes);
+#endif
+}
+
+
+ThreadRecorder::ThreadRecorder( ThreadRecorder& parent )
+: mParentRecorder(&parent)
+{
+ init();
+ mParentRecorder->addChildRecorder(this);
+}
+
+
+ThreadRecorder::~ThreadRecorder()
+{
+#if LL_TRACE_ENABLED
+ LLThreadLocalSingletonPointer<BlockTimerStackRecord>::setInstance(NULL);
+
+ disclaim_alloc(gTraceMemStat, this);
+ disclaim_alloc(gTraceMemStat, sizeof(BlockTimer));
+ disclaim_alloc(gTraceMemStat, sizeof(TimeBlockTreeNode) * mNumTimeBlockTreeNodes);
+
+ deactivate(&mThreadRecordingBuffers);
+
+ delete mRootTimer;
+
+ if (!mActiveRecordings.empty())
+ {
+ std::for_each(mActiveRecordings.begin(), mActiveRecordings.end(), DeletePointer());
+ mActiveRecordings.clear();
+ }
+
+ set_thread_recorder(NULL);
+ delete[] mTimeBlockTreeNodes;
+
+ if (mParentRecorder)
+ {
+ mParentRecorder->removeChildRecorder(this);
+ }
+#endif
+}
+
+TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode( S32 index )
+{
+#if LL_TRACE_ENABLED
+ if (0 <= index && index < mNumTimeBlockTreeNodes)
+ {
+ return &mTimeBlockTreeNodes[index];
+ }
+#endif
+ return NULL;
+}
+
+AccumulatorBufferGroup* ThreadRecorder::activate( AccumulatorBufferGroup* recording)
+{
+#if LL_TRACE_ENABLED
+ ActiveRecording* active_recording = new ActiveRecording(recording);
+ if (!mActiveRecordings.empty())
+ {
+ AccumulatorBufferGroup& prev_active_recording = mActiveRecordings.back()->mPartialRecording;
+ prev_active_recording.sync();
+ BlockTimer::updateTimes();
+ prev_active_recording.handOffTo(active_recording->mPartialRecording);
+ }
+ mActiveRecordings.push_back(active_recording);
+
+ mActiveRecordings.back()->mPartialRecording.makeCurrent();
+ return &active_recording->mPartialRecording;
+#else
+ return NULL;
+#endif
+}
+
+ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::bringUpToDate( AccumulatorBufferGroup* recording )
+{
+#if LL_TRACE_ENABLED
+ if (mActiveRecordings.empty()) return mActiveRecordings.end();
+
+ mActiveRecordings.back()->mPartialRecording.sync();
+ BlockTimer::updateTimes();
+
+ active_recording_list_t::reverse_iterator it, end_it;
+ for (it = mActiveRecordings.rbegin(), end_it = mActiveRecordings.rend();
+ it != end_it;
+ ++it)
+ {
+ ActiveRecording* cur_recording = *it;
+
+ active_recording_list_t::reverse_iterator next_it = it;
+ ++next_it;
+
+ // if we have another recording further down in the stack...
+ if (next_it != mActiveRecordings.rend())
+ {
+ // ...push our gathered data down to it
+ (*next_it)->mPartialRecording.append(cur_recording->mPartialRecording);
+ }
+
+ // copy accumulated measurements into result buffer and clear accumulator (mPartialRecording)
+ cur_recording->movePartialToTarget();
+
+ if (cur_recording->mTargetRecording == recording)
+ {
+ // found the recording, so return it
+ break;
+ }
+ }
+
+ if (it == end_it)
+ {
+ LL_WARNS() << "Recording not active on this thread" << LL_ENDL;
+ }
+
+ return (++it).base();
+#else
+ return ThreadRecorder::active_recording_list_t::iterator();
+#endif
+}
+
+void ThreadRecorder::deactivate( AccumulatorBufferGroup* recording )
+{
+#if LL_TRACE_ENABLED
+ active_recording_list_t::iterator recording_it = bringUpToDate(recording);
+ // this method should only be called on a thread where the recorder is active
+ llassert_always(recording_it != mActiveRecordings.end());
+
+ ActiveRecording* recording_to_remove = *recording_it;
+ bool was_current = recording_to_remove->mPartialRecording.isCurrent();
+ llassert(recording_to_remove->mTargetRecording == recording);
+ mActiveRecordings.erase(recording_it);
+ if (was_current)
+ {
+ if (mActiveRecordings.empty())
+ {
+ AccumulatorBufferGroup::clearCurrent();
+ }
+ else
+ {
+ mActiveRecordings.back()->mPartialRecording.makeCurrent();
+ }
+ }
+ delete recording_to_remove;
+#endif
+}
+
+ThreadRecorder::ActiveRecording::ActiveRecording( AccumulatorBufferGroup* target )
+: mTargetRecording(target)
+{}
+
+void ThreadRecorder::ActiveRecording::movePartialToTarget()
+{
+#if LL_TRACE_ENABLED
+ mTargetRecording->append(mPartialRecording);
+ // reset based on self to keep history
+ mPartialRecording.reset(&mPartialRecording);
+#endif
+}
+
+
+// called by child thread
+void ThreadRecorder::addChildRecorder( class ThreadRecorder* child )
+{
+#if LL_TRACE_ENABLED
+ { LLMutexLock lock(&mChildListMutex);
+ mChildThreadRecorders.push_back(child);
+ }
+#endif
+}
+
+// called by child thread
+void ThreadRecorder::removeChildRecorder( class ThreadRecorder* child )
+{
+#if LL_TRACE_ENABLED
+ { LLMutexLock lock(&mChildListMutex);
+ mChildThreadRecorders.remove(child);
+ }
+#endif
+}
+
+void ThreadRecorder::pushToParent()
+{
+#if LL_TRACE_ENABLED
+ { LLMutexLock lock(&mSharedRecordingMutex);
+ LLTrace::get_thread_recorder()->bringUpToDate(&mThreadRecordingBuffers);
+ mSharedRecordingBuffers.append(mThreadRecordingBuffers);
+ mThreadRecordingBuffers.reset();
+ }
+#endif
+}
+
+
+static LLTrace::BlockTimerStatHandle FTM_PULL_TRACE_DATA_FROM_CHILDREN("Pull child thread trace data");
+
+void ThreadRecorder::pullFromChildren()
+{
+#if LL_TRACE_ENABLED
+ LL_RECORD_BLOCK_TIME(FTM_PULL_TRACE_DATA_FROM_CHILDREN);
+ if (mActiveRecordings.empty()) return;
+
+ { LLMutexLock lock(&mChildListMutex);
+
+ AccumulatorBufferGroup& target_recording_buffers = mActiveRecordings.back()->mPartialRecording;
+ target_recording_buffers.sync();
+ for (child_thread_recorder_list_t::iterator it = mChildThreadRecorders.begin(), end_it = mChildThreadRecorders.end();
+ it != end_it;
+ ++it)
+ { LLMutexLock lock(&(*it)->mSharedRecordingMutex);
+
+ target_recording_buffers.merge((*it)->mSharedRecordingBuffers);
+ (*it)->mSharedRecordingBuffers.reset();
+ }
+ }
+#endif
+}
+
+
+void set_master_thread_recorder( ThreadRecorder* recorder )
+{
+ sMasterThreadRecorder = recorder;
+}
+
+
+ThreadRecorder* get_master_thread_recorder()
+{
+ return sMasterThreadRecorder;
+}
+
+LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder_ptr()
+{
+ static LLThreadLocalPointer<ThreadRecorder> s_thread_recorder;
+ return s_thread_recorder;
+}
+
+const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder()
+{
+ return get_thread_recorder_ptr();
+}
+
+void set_thread_recorder( ThreadRecorder* recorder )
+{
+ get_thread_recorder_ptr() = recorder;
+}
+
+}
diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h
new file mode 100644
index 0000000000..a797c6687e
--- /dev/null
+++ b/indra/llcommon/lltracethreadrecorder.h
@@ -0,0 +1,102 @@
+/**
+ * @file lltrace.h
+ * @brief Runtime statistics accumulation.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLTRACETHREADRECORDER_H
+#define LL_LLTRACETHREADRECORDER_H
+
+#include "stdtypes.h"
+#include "llpreprocessor.h"
+
+#include "llmutex.h"
+#include "lltraceaccumulators.h"
+#include "llthreadlocalstorage.h"
+
+namespace LLTrace
+{
+ class LL_COMMON_API ThreadRecorder
+ {
+ protected:
+ struct ActiveRecording;
+ typedef std::vector<ActiveRecording*> active_recording_list_t;
+ public:
+ ThreadRecorder();
+ explicit ThreadRecorder(ThreadRecorder& parent);
+
+ ~ThreadRecorder();
+
+ AccumulatorBufferGroup* activate(AccumulatorBufferGroup* recording);
+ void deactivate(AccumulatorBufferGroup* recording);
+ active_recording_list_t::iterator bringUpToDate(AccumulatorBufferGroup* recording);
+
+ void addChildRecorder(class ThreadRecorder* child);
+ void removeChildRecorder(class ThreadRecorder* child);
+
+ // call this periodically to gather stats data from child threads
+ void pullFromChildren();
+ void pushToParent();
+
+ TimeBlockTreeNode* getTimeBlockTreeNode(S32 index);
+
+ protected:
+ void init();
+
+ protected:
+ struct ActiveRecording
+ {
+ ActiveRecording(AccumulatorBufferGroup* target);
+
+ AccumulatorBufferGroup* mTargetRecording;
+ AccumulatorBufferGroup mPartialRecording;
+
+ void movePartialToTarget();
+ };
+
+ AccumulatorBufferGroup mThreadRecordingBuffers;
+
+ BlockTimerStackRecord mBlockTimerStackRecord;
+ active_recording_list_t mActiveRecordings;
+
+ class BlockTimer* mRootTimer;
+ TimeBlockTreeNode* mTimeBlockTreeNodes;
+ size_t mNumTimeBlockTreeNodes;
+ typedef std::list<class ThreadRecorder*> child_thread_recorder_list_t;
+
+ child_thread_recorder_list_t mChildThreadRecorders; // list of child thread recorders associated with this master
+ LLMutex mChildListMutex; // protects access to child list
+ LLMutex mSharedRecordingMutex;
+ AccumulatorBufferGroup mSharedRecordingBuffers;
+ ThreadRecorder* mParentRecorder;
+
+ };
+
+ const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder();
+ void set_thread_recorder(ThreadRecorder*);
+
+ void set_master_thread_recorder(ThreadRecorder*);
+ ThreadRecorder* get_master_thread_recorder();
+}
+
+#endif // LL_LLTRACETHREADRECORDER_H
diff --git a/indra/llcommon/lltypeinfolookup.h b/indra/llcommon/lltypeinfolookup.h
deleted file mode 100755
index 0b6862444e..0000000000
--- a/indra/llcommon/lltypeinfolookup.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/**
- * @file lltypeinfolookup.h
- * @author Nat Goodspeed
- * @date 2012-04-08
- * @brief Template data structure like std::map<std::type_info*, T>
- *
- * $LicenseInfo:firstyear=2012&license=viewerlgpl$
- * Copyright (c) 2012, Linden Research, Inc.
- * $/LicenseInfo$
- */
-
-#if ! defined(LL_LLTYPEINFOLOOKUP_H)
-#define LL_LLTYPEINFOLOOKUP_H
-
-#include <boost/unordered_map.hpp>
-#include <boost/functional/hash.hpp>
-#include <boost/optional.hpp>
-#include <functional> // std::binary_function
-#include <typeinfo>
-
-/**
- * The following helper classes are based on the Boost.Unordered documentation:
- * http://www.boost.org/doc/libs/1_45_0/doc/html/unordered/hash_equality.html
- */
-
-/**
- * Compute hash for a string passed as const char*
- */
-struct const_char_star_hash: public std::unary_function<const char*, std::size_t>
-{
- std::size_t operator()(const char* str) const
- {
- std::size_t seed = 0;
- for ( ; *str; ++str)
- {
- boost::hash_combine(seed, *str);
- }
- return seed;
- }
-};
-
-/**
- * Compute equality for strings passed as const char*
- *
- * I (nat) suspect that this is where the default behavior breaks for the
- * const char* values returned from std::type_info::name(). If you compare the
- * two const char* pointer values, as a naive, unspecialized implementation
- * will surely do, they'll compare unequal.
- */
-struct const_char_star_equal: public std::binary_function<const char*, const char*, bool>
-{
- bool operator()(const char* lhs, const char* rhs) const
- {
- return strcmp(lhs, rhs) == 0;
- }
-};
-
-/**
- * LLTypeInfoLookup is specifically designed for use cases for which you might
- * consider std::map<std::type_info*, VALUE>. We have several such data
- * structures in the viewer. The trouble with them is that at least on Linux,
- * you can't rely on always getting the same std::type_info* for a given type:
- * different load modules will produce different std::type_info*.
- * LLTypeInfoLookup contains a workaround to address this issue.
- *
- * The API deliberately diverges from std::map in several respects:
- * * It avoids iterators, not only begin()/end() but also as return values
- * from insert() and find(). This bypasses transform_iterator overhead.
- * * Since we literally use compile-time types as keys, the essential insert()
- * and find() methods accept the key type as a @em template parameter,
- * accepting and returning value_type as a normal runtime value. This is to
- * permit future optimization (e.g. compile-time type hashing) without
- * changing the API.
- */
-template <typename VALUE>
-class LLTypeInfoLookup
-{
- // Use this for our underlying implementation: lookup by
- // std::type_info::name() string. This is one of the rare cases in which I
- // dare use const char* directly, rather than std::string, because I'm
- // sure that every value returned by std::type_info::name() is static.
- // HOWEVER, specify our own hash + equality functors: naively comparing
- // distinct const char* values won't work.
- typedef boost::unordered_map<const char*, VALUE,
- const_char_star_hash, const_char_star_equal> impl_map_type;
-
-public:
- typedef VALUE value_type;
-
- LLTypeInfoLookup() {}
-
- bool empty() const { return mMap.empty(); }
- std::size_t size() const { return mMap.size(); }
-
- template <typename KEY>
- bool insert(const value_type& value)
- {
- // Obtain and store the std::type_info::name() string as the key.
- // Return just the bool from std::map::insert()'s return pair.
- return mMap.insert(typename impl_map_type::value_type(typeid(KEY).name(), value)).second;
- }
-
- template <typename KEY>
- boost::optional<value_type> find() const
- {
- // Use the std::type_info::name() string as the key.
- typename impl_map_type::const_iterator found = mMap.find(typeid(KEY).name());
- if (found == mMap.end())
- return boost::optional<value_type>();
- return found->second;
- }
-
-private:
- impl_map_type mMap;
-};
-
-#endif /* ! defined(LL_LLTYPEINFOLOOKUP_H) */
diff --git a/indra/llcommon/llunits.h b/indra/llcommon/llunits.h
new file mode 100644
index 0000000000..0fcb8281a0
--- /dev/null
+++ b/indra/llcommon/llunits.h
@@ -0,0 +1,129 @@
+/**
+ * @file llunits.h
+ * @brief Unit definitions
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLUNITTYPE_H
+#define LL_LLUNITTYPE_H
+
+#include "stdtypes.h"
+#include "llunittype.h"
+
+//
+// Unit declarations
+//
+
+namespace LLUnits
+{
+LL_DECLARE_BASE_UNIT(Bytes, "B");
+// technically, these are kibibytes, mibibytes, etc. but we should stick with commonly accepted terminology
+LL_DECLARE_DERIVED_UNIT(Kilobytes, "KB", Bytes, / 1024);
+LL_DECLARE_DERIVED_UNIT(Megabytes, "MB", Kilobytes, / 1024);
+LL_DECLARE_DERIVED_UNIT(Gigabytes, "GB", Megabytes, / 1024);
+}
+
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bytes);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobytes);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabytes);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabytes);
+
+namespace LLUnits
+{
+// technically, these are kibibits, mibibits, etc. but we should stick with commonly accepted terminology
+LL_DECLARE_DERIVED_UNIT(Bits, "b", Bytes, * 8 );
+LL_DECLARE_DERIVED_UNIT(Kilobits, "Kb", Bits, / 1024);
+LL_DECLARE_DERIVED_UNIT(Megabits, "Mb", Kilobits, / 1024);
+LL_DECLARE_DERIVED_UNIT(Gigabits, "Gb", Megabits, / 1024);
+}
+
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bits);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobits);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabits);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabits);
+
+namespace LLUnits
+{
+LL_DECLARE_BASE_UNIT(Seconds, "s");
+LL_DECLARE_DERIVED_UNIT(Minutes, "min", Seconds, / 60);
+LL_DECLARE_DERIVED_UNIT(Hours, "h", Minutes, / 60);
+LL_DECLARE_DERIVED_UNIT(Days, "d", Hours, / 24);
+LL_DECLARE_DERIVED_UNIT(Milliseconds, "ms", Seconds, * 1000);
+LL_DECLARE_DERIVED_UNIT(Microseconds, "\x09\x3cs", Milliseconds, * 1000);
+LL_DECLARE_DERIVED_UNIT(Nanoseconds, "ns", Microseconds, * 1000);
+}
+
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Seconds);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Minutes);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hours);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Days);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Milliseconds);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Microseconds);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Nanoseconds);
+
+namespace LLUnits
+{
+LL_DECLARE_BASE_UNIT(Meters, "m");
+LL_DECLARE_DERIVED_UNIT(Kilometers, "km", Meters, / 1000);
+LL_DECLARE_DERIVED_UNIT(Centimeters, "cm", Meters, * 100);
+LL_DECLARE_DERIVED_UNIT(Millimeters, "mm", Meters, * 1000);
+}
+
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Meters);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilometers);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Centimeters);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Millimeters);
+
+namespace LLUnits
+{
+// rare units
+LL_DECLARE_BASE_UNIT(Hertz, "Hz");
+LL_DECLARE_DERIVED_UNIT(Kilohertz, "KHz", Hertz, / 1000);
+LL_DECLARE_DERIVED_UNIT(Megahertz, "MHz", Kilohertz, / 1000);
+LL_DECLARE_DERIVED_UNIT(Gigahertz, "GHz", Megahertz, / 1000);
+
+LL_DECLARE_BASE_UNIT(Radians, "rad");
+LL_DECLARE_DERIVED_UNIT(Degrees, "deg", Radians, * 57.29578f);
+
+LL_DECLARE_BASE_UNIT(Percent, "%");
+LL_DECLARE_DERIVED_UNIT(Ratio, "x", Percent, / 100);
+
+LL_DECLARE_BASE_UNIT(Triangles, "tris");
+LL_DECLARE_DERIVED_UNIT(Kilotriangles, "ktris", Triangles, / 1000);
+
+} // namespace LLUnits
+
+// rare units
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hertz);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilohertz);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megahertz);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigahertz);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Radians);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Degrees);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Percent);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Ratio);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Triangles);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilotriangles);
+
+
+#endif // LL_LLUNITTYPE_H
diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h
new file mode 100644
index 0000000000..0e05ecd683
--- /dev/null
+++ b/indra/llcommon/llunittype.h
@@ -0,0 +1,836 @@
+/**
+ * @file llunit.h
+ * @brief Unit conversion classes
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2012, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_UNITTYPE_H
+#define LL_UNITTYPE_H
+
+#include "stdtypes.h"
+#include "llpreprocessor.h"
+#include "llerror.h"
+
+//lightweight replacement of type traits for simple type equality check
+template<typename S, typename T>
+struct LLIsSameType
+{
+ static const bool value = false;
+};
+
+template<typename T>
+struct LLIsSameType<T, T>
+{
+ static const bool value = true;
+};
+
+// workaround for decltype() not existing and typeof() not working inline in gcc 4.2
+template<typename S, typename T>
+struct LLResultTypeAdd
+{
+ typedef LL_TYPEOF(S() + T()) type_t;
+};
+
+template<typename S, typename T>
+struct LLResultTypeSubtract
+{
+ typedef LL_TYPEOF(S() - T()) type_t;
+};
+
+template<typename S, typename T>
+struct LLResultTypeMultiply
+{
+ typedef LL_TYPEOF(S() * T()) type_t;
+};
+
+template<typename S, typename T>
+struct LLResultTypeDivide
+{
+ typedef LL_TYPEOF(S() / T(1)) type_t;
+};
+
+template<typename S, typename T>
+struct LLResultTypePromote
+{
+ typedef LL_TYPEOF((true) ? S() : T()) type_t;
+};
+
+template<typename STORAGE_TYPE, typename UNITS>
+struct LLUnit
+{
+ typedef LLUnit<STORAGE_TYPE, UNITS> self_t;
+ typedef STORAGE_TYPE storage_t;
+ typedef void is_unit_t;
+
+ // value initialization
+ LL_FORCE_INLINE explicit LLUnit(storage_t value = storage_t())
+ : mValue(value)
+ {}
+
+ // unit initialization and conversion
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE LLUnit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+ : mValue(convert(other).mValue)
+ {}
+
+ LL_FORCE_INLINE storage_t value() const
+ {
+ return mValue;
+ }
+
+ LL_FORCE_INLINE void value(storage_t value)
+ {
+ mValue = value;
+ }
+
+ template<typename NEW_UNITS>
+ storage_t valueInUnits()
+ {
+ return LLUnit<storage_t, NEW_UNITS>(*this).value();
+ }
+
+ template<typename NEW_UNITS>
+ void valueInUnits(storage_t value)
+ {
+ *this = LLUnit<storage_t, NEW_UNITS>(value);
+ }
+
+ LL_FORCE_INLINE void operator += (self_t other)
+ {
+ mValue += convert(other).mValue;
+ }
+
+ LL_FORCE_INLINE void operator -= (self_t other)
+ {
+ mValue -= convert(other).mValue;
+ }
+
+ LL_FORCE_INLINE void operator *= (storage_t multiplicand)
+ {
+ mValue *= multiplicand;
+ }
+
+ LL_FORCE_INLINE void operator *= (self_t multiplicand)
+ {
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported.");
+ }
+
+ LL_FORCE_INLINE void operator /= (storage_t divisor)
+ {
+ mValue /= divisor;
+ }
+
+ void operator /= (self_t divisor)
+ {
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types.");
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return mValue == convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return mValue != convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return mValue < convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return mValue <= convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return mValue > convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return mValue >= convert(other).value();
+ }
+
+ LL_FORCE_INLINE static self_t convert(self_t v)
+ {
+ return v;
+ }
+
+ template<typename FROM_STORAGE_TYPE>
+ LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, UNITS> v)
+ {
+ self_t result;
+ result.mValue = (STORAGE_TYPE)v.value();
+ return result;
+ }
+
+ template<typename FROM_UNITS>
+ LL_FORCE_INLINE static self_t convert(LLUnit<STORAGE_TYPE, FROM_UNITS> v)
+ {
+ self_t result;
+ STORAGE_TYPE divisor = ll_convert_units(v, result);
+ result.mValue /= divisor;
+ return result;
+ }
+
+ template<typename FROM_STORAGE_TYPE, typename FROM_UNITS>
+ LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, FROM_UNITS> v)
+ {
+ typedef typename LLResultTypePromote<FROM_STORAGE_TYPE, STORAGE_TYPE>::type_t result_storage_t;
+ LLUnit<result_storage_t, UNITS> result;
+ result_storage_t divisor = ll_convert_units(v, result);
+ result.value(result.value() / divisor);
+ return self_t(result.value());
+ }
+
+protected:
+ storage_t mValue;
+};
+
+template<typename STORAGE_TYPE, typename UNITS>
+std::ostream& operator <<(std::ostream& s, const LLUnit<STORAGE_TYPE, UNITS>& unit)
+{
+ s << unit.value() << UNITS::getUnitLabel();
+ return s;
+}
+
+template<typename STORAGE_TYPE, typename UNITS>
+std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNITS>& unit)
+{
+ STORAGE_TYPE val;
+ s >> val;
+ unit.value(val);
+ return s;
+}
+
+template<typename STORAGE_TYPE, typename UNITS>
+struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
+{
+ typedef LLUnitImplicit<STORAGE_TYPE, UNITS> self_t;
+ typedef typename LLUnit<STORAGE_TYPE, UNITS>::storage_t storage_t;
+ typedef LLUnit<STORAGE_TYPE, UNITS> base_t;
+
+ LL_FORCE_INLINE LLUnitImplicit(storage_t value = storage_t())
+ : base_t(value)
+ {}
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE LLUnitImplicit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+ : base_t(other)
+ {}
+
+ // unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc)
+ // this allows for interoperability with legacy code
+ LL_FORCE_INLINE operator storage_t() const
+ {
+ return base_t::value();
+ }
+
+ using base_t::operator +=;
+ LL_FORCE_INLINE void operator += (storage_t value)
+ {
+ base_t::mValue += value;
+ }
+
+ // this overload exists to explicitly catch use of another implicit unit
+ // without ambiguity between conversion to storage_t vs conversion to base_t
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE void operator += (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+ {
+ base_t::mValue += convert(other).value();
+ }
+
+ using base_t::operator -=;
+ LL_FORCE_INLINE void operator -= (storage_t value)
+ {
+ base_t::mValue -= value;
+ }
+
+ // this overload exists to explicitly catch use of another implicit unit
+ // without ambiguity between conversion to storage_t vs conversion to base_t
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE void operator -= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
+ {
+ base_t::mValue -= convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue == convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator == (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue == convert(other).value();
+ }
+
+ template<typename STORAGE_T>
+ LL_FORCE_INLINE bool operator == (STORAGE_T other) const
+ {
+ return base_t::mValue == other;
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue != convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator != (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue != convert(other).value();
+ }
+
+ template<typename STORAGE_T>
+ LL_FORCE_INLINE bool operator != (STORAGE_T other) const
+ {
+ return base_t::mValue != other;
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue < convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator < (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue < convert(other).value();
+ }
+
+ template<typename STORAGE_T>
+ LL_FORCE_INLINE bool operator < (STORAGE_T other) const
+ {
+ return base_t::mValue < other;
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue <= convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator <= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue <= convert(other).value();
+ }
+
+ template<typename STORAGE_T>
+ LL_FORCE_INLINE bool operator <= (STORAGE_T other) const
+ {
+ return base_t::mValue <= other;
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue > convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator > (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue > convert(other).value();
+ }
+
+ template<typename STORAGE_T>
+ LL_FORCE_INLINE bool operator > (STORAGE_T other) const
+ {
+ return base_t::mValue > other;
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue >= convert(other).value();
+ }
+
+ template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
+ LL_FORCE_INLINE bool operator >= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
+ {
+ return base_t::mValue >= convert(other).value();
+ }
+
+ template<typename STORAGE_T>
+ LL_FORCE_INLINE bool operator >= (STORAGE_T other) const
+ {
+ return base_t::mValue >= other;
+ }
+};
+
+template<typename STORAGE_TYPE, typename UNITS>
+std::ostream& operator <<(std::ostream& s, const LLUnitImplicit<STORAGE_TYPE, UNITS>& unit)
+{
+ s << unit.value() << UNITS::getUnitLabel();
+ return s;
+}
+
+template<typename STORAGE_TYPE, typename UNITS>
+std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNITS>& unit)
+{
+ STORAGE_TYPE val;
+ s >> val;
+ unit = val;
+ return s;
+}
+
+template<typename S1, typename T1, typename S2, typename T2>
+LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out)
+{
+ S2 divisor(1);
+
+ LL_STATIC_ASSERT((LLIsSameType<T1, T2>::value
+ || !LLIsSameType<T1, typename T1::base_unit_t>::value
+ || !LLIsSameType<T2, typename T2::base_unit_t>::value),
+ "conversion requires compatible units");
+
+ if (LLIsSameType<T1, T2>::value)
+ {
+ // T1 and T2 same type, just assign
+ out.value((S2)in.value());
+ }
+ else if (T1::sLevel > T2::sLevel)
+ {
+ // reduce T1
+ LLUnit<S2, typename T1::base_unit_t> new_in;
+ divisor *= (S2)ll_convert_units(in, new_in);
+ divisor *= (S2)ll_convert_units(new_in, out);
+ }
+ else
+ {
+ // reduce T2
+ LLUnit<S2, typename T2::base_unit_t> new_out;
+ divisor *= (S2)ll_convert_units(in, new_out);
+ divisor *= (S2)ll_convert_units(new_out, out);
+ }
+ return divisor;
+}
+
+template<typename T>
+struct LLStorageType
+{
+ typedef T type_t;
+};
+
+template<typename STORAGE_TYPE, typename UNITS>
+struct LLStorageType<LLUnit<STORAGE_TYPE, UNITS> >
+{
+ typedef STORAGE_TYPE type_t;
+};
+
+// all of these operators need to perform type promotion on the storage type of the units, so they
+// cannot be expressed as operations on identical types with implicit unit conversion
+// e.g. typeof(S32Bytes(x) + F32Megabytes(y)) <==> F32Bytes
+
+//
+// operator +
+//
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
+{
+ LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result += second;
+ return result;
+}
+
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNITS> operator + (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second)
+{
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
+ return LLUnit<STORAGE_TYPE, UNITS>(0);
+}
+
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNITS> operator + (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second)
+{
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
+ return LLUnit<STORAGE_TYPE, UNITS>(0);
+}
+
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
+{
+ LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result += second;
+ return result;
+}
+
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
+{
+ LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result += second;
+ return result;
+}
+
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
+{
+ LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result += LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
+ return result;
+}
+
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator + (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
+{
+ LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
+ result += second;
+ return result;
+}
+
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::
+ type_t, UNITS> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
+{
+ LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
+ result += second;
+ return result;
+}
+
+//
+// operator -
+//
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
+{
+ LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result -= second;
+ return result;
+}
+
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNITS> operator - (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second)
+{
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
+ return LLUnit<STORAGE_TYPE, UNITS>(0);
+}
+
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
+LLUnit<STORAGE_TYPE, UNITS> operator - (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second)
+{
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
+ return LLUnit<STORAGE_TYPE, UNITS>(0);
+}
+
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
+{
+ LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result -= second;
+ return result;
+}
+
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
+{
+ LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result -= second;
+ return result;
+}
+
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
+{
+ LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
+ result -= LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
+ return result;
+}
+
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator - (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
+{
+ LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
+ result -= second;
+ return result;
+}
+
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
+{
+ LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
+ result -= second;
+ return result;
+}
+
+//
+// operator *
+//
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LLUnit<STORAGE_TYPE1, UNITS1> operator * (LLUnit<STORAGE_TYPE1, UNITS1>, LLUnit<STORAGE_TYPE2, UNITS2>)
+{
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
+ return LLUnit<STORAGE_TYPE1, UNITS1>();
+}
+
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
+{
+ return LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() * second);
+}
+
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNITS> second)
+{
+ return LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
+}
+
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LLUnitImplicit<STORAGE_TYPE1, UNITS1> operator * (LLUnitImplicit<STORAGE_TYPE1, UNITS1>, LLUnitImplicit<STORAGE_TYPE2, UNITS2>)
+{
+ // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
+ LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
+ return LLUnitImplicit<STORAGE_TYPE1, UNITS1>();
+}
+
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
+{
+ return LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, UNITLESS_TYPE>::type_t, UNITS>(first.value() * second);
+}
+
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
+{
+ return LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
+}
+
+
+//
+// operator /
+//
+
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
+{
+ return LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
+}
+
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
+{
+ return first.value() / first.convert(second).value();
+}
+
+template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
+LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
+{
+ return LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
+}
+
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
+{
+ return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
+}
+
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
+{
+ return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
+}
+
+template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
+LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
+{
+ return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
+}
+
+template<typename T>
+struct LLGetUnitLabel
+{
+ static const char* getUnitLabel() { return ""; }
+};
+
+template<typename T, typename STORAGE_T>
+struct LLGetUnitLabel<LLUnit<STORAGE_T, T> >
+{
+ static const char* getUnitLabel() { return T::getUnitLabel(); }
+};
+
+template<typename T>
+struct LLUnitLinearOps
+{
+ typedef LLUnitLinearOps<T> self_t;
+
+ LLUnitLinearOps(T val)
+ : mValue(val),
+ mDivisor(1)
+ {}
+
+ template<typename OTHER_T>
+ self_t operator * (OTHER_T other)
+ {
+ return mValue * other;
+ }
+
+ template<typename OTHER_T>
+ self_t operator / (OTHER_T other)
+ {
+ mDivisor *= other;
+ return *this;
+ }
+
+ template<typename OTHER_T>
+ self_t operator + (OTHER_T other)
+ {
+ mValue += other * mDivisor;
+ return *this;
+ }
+
+ template<typename OTHER_T>
+ self_t operator - (OTHER_T other)
+ {
+ mValue -= other * mDivisor;
+ return *this;
+ }
+
+ T mValue;
+ T mDivisor;
+};
+
+template<typename T>
+struct LLUnitInverseLinearOps
+{
+ typedef LLUnitInverseLinearOps<T> self_t;
+
+ LLUnitInverseLinearOps(T val)
+ : mValue(val),
+ mDivisor(1),
+ mMultiplicand(1)
+ {}
+
+ template<typename OTHER_T>
+ self_t operator * (OTHER_T other)
+ {
+ mDivisor *= other;
+ return *this;
+ }
+
+ template<typename OTHER_T>
+ self_t operator / (OTHER_T other)
+ {
+ mValue *= other;
+ mMultiplicand *= other;
+ return *this;
+ }
+
+ template<typename OTHER_T>
+ self_t operator + (OTHER_T other)
+ {
+ mValue -= other * mMultiplicand;
+ return *this;
+ }
+
+ template<typename OTHER_T>
+ self_t operator - (OTHER_T other)
+ {
+ mValue += other * mMultiplicand;
+ return *this;
+ }
+
+ T mValue;
+ T mDivisor;
+ T mMultiplicand;
+};
+
+#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \
+struct base_unit_name \
+{ \
+ static const int sLevel = 0; \
+ typedef base_unit_name base_unit_t; \
+ static const char* getUnitLabel() { return unit_label; } \
+ template<typename T> \
+ static LLUnit<T, base_unit_name> fromValue(T value) { return LLUnit<T, base_unit_name>(value); } \
+ template<typename STORAGE_T, typename UNIT_T> \
+ static LLUnit<STORAGE_T, base_unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
+ { return LLUnit<STORAGE_T, base_unit_name>(value); } \
+}
+
+
+#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation) \
+struct unit_name \
+{ \
+ static const int sLevel = base_unit_name::sLevel + 1; \
+ typedef base_unit_name base_unit_t; \
+ static const char* getUnitLabel() { return unit_label; } \
+ template<typename T> \
+ static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); } \
+ template<typename STORAGE_T, typename UNIT_T> \
+ static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
+ { return LLUnit<STORAGE_T, unit_name>(value); } \
+}; \
+ \
+template<typename S1, typename S2> \
+LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out) \
+{ \
+ typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t; \
+ LLUnitInverseLinearOps<result_storage_t> result = \
+ LLUnitInverseLinearOps<result_storage_t>(in.value()) conversion_operation; \
+ out = LLUnit<S2, base_unit_name>((S2)result.mValue); \
+ return result.mDivisor; \
+} \
+ \
+template<typename S1, typename S2> \
+LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out) \
+{ \
+ typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t; \
+ LLUnitLinearOps<result_storage_t> result = \
+ LLUnitLinearOps<result_storage_t>(in.value()) conversion_operation; \
+ out = LLUnit<S2, unit_name>((S2)result.mValue); \
+ return result.mDivisor; \
+}
+
+#define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name) \
+ typedef LLUnit<F32, ns::unit_name> F32##unit_name; \
+ typedef LLUnitImplicit<F32, ns::unit_name> F32##unit_name##Implicit;\
+ typedef LLUnit<F64, ns::unit_name> F64##unit_name; \
+ typedef LLUnitImplicit<F64, ns::unit_name> F64##unit_name##Implicit;\
+ typedef LLUnit<S32, ns::unit_name> S32##unit_name; \
+ typedef LLUnitImplicit<S32, ns::unit_name> S32##unit_name##Implicit;\
+ typedef LLUnit<S64, ns::unit_name> S64##unit_name; \
+ typedef LLUnitImplicit<S64, ns::unit_name> S64##unit_name##Implicit;\
+ typedef LLUnit<U32, ns::unit_name> U32##unit_name; \
+ typedef LLUnitImplicit<U32, ns::unit_name> U32##unit_name##Implicit;\
+ typedef LLUnit<U64, ns::unit_name> U64##unit_name; \
+ typedef LLUnitImplicit<U64, ns::unit_name> U64##unit_name##Implicit
+
+#endif //LL_UNITTYPE_H
diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp
index 37f5b3d6a3..9f12d49244 100755
--- a/indra/llcommon/lluri.cpp
+++ b/indra/llcommon/lluri.cpp
@@ -359,7 +359,7 @@ LLURI LLURI::buildHTTP(const std::string& prefix,
it != path.endArray();
++it)
{
- lldebugs << "PATH: inserting " << it->asString() << llendl;
+ LL_DEBUGS() << "PATH: inserting " << it->asString() << LL_ENDL;
result.mEscapedPath += "/" + escapePathComponent(it->asString());
}
}
@@ -399,8 +399,8 @@ LLURI LLURI::buildHTTP(const std::string& prefix,
}
else
{
- llwarns << "Valid path arguments to buildHTTP are array, string, or undef, you passed type"
- << path.type() << llendl;
+ LL_WARNS() << "Valid path arguments to buildHTTP are array, string, or undef, you passed type"
+ << path.type() << LL_ENDL;
}
result.mEscapedOpaque = "//" + result.mEscapedAuthority +
result.mEscapedPath;
@@ -584,7 +584,7 @@ LLSD LLURI::queryMap() const
// static
LLSD LLURI::queryMap(std::string escaped_query_string)
{
- lldebugs << "LLURI::queryMap query params: " << escaped_query_string << llendl;
+ LL_DEBUGS() << "LLURI::queryMap query params: " << escaped_query_string << LL_ENDL;
LLSD result = LLSD::emptyArray();
while(!escaped_query_string.empty())
@@ -610,12 +610,12 @@ LLSD LLURI::queryMap(std::string escaped_query_string)
{
std::string key = unescape(tuple.substr(0,key_end));
std::string value = unescape(tuple.substr(key_end+1));
- lldebugs << "inserting key " << key << " value " << value << llendl;
+ LL_DEBUGS() << "inserting key " << key << " value " << value << LL_ENDL;
result[key] = value;
}
else
{
- lldebugs << "inserting key " << unescape(tuple) << " value true" << llendl;
+ LL_DEBUGS() << "inserting key " << unescape(tuple) << " value true" << LL_ENDL;
result[unescape(tuple)] = true;
}
}
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index 0aaa50d231..e3671047b4 100755
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -27,9 +27,7 @@
// We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes.
#if LL_WINDOWS
-#undef WIN32_LEAN_AND_MEAN
-#include <winsock2.h>
-#include <windows.h>
+#include "llwin32headers.h"
// ugh, this is ugly. We need to straighten out our linking for this library
#pragma comment(lib, "IPHLPAPI.lib")
#include <iphlpapi.h>
@@ -234,7 +232,7 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit)
{
if(emit)
{
- llwarns << "Warning! Using broken UUID string format" << llendl;
+ LL_WARNS() << "Warning! Using broken UUID string format" << LL_ENDL;
}
broken_format = TRUE;
}
@@ -244,7 +242,7 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit)
if(emit)
{
//don't spam the logs because a resident can't spell.
- llwarns << "Bad UUID string: " << in_string << llendl;
+ LL_WARNS() << "Bad UUID string: " << in_string << LL_ENDL;
}
setNull();
return FALSE;
@@ -283,7 +281,7 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit)
{
if(emit)
{
- llwarns << "Invalid UUID string character" << llendl;
+ LL_WARNS() << "Invalid UUID string character" << LL_ENDL;
}
setNull();
return FALSE;
@@ -308,7 +306,7 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit)
{
if(emit)
{
- llwarns << "Invalid UUID string character" << llendl;
+ LL_WARNS() << "Invalid UUID string character" << LL_ENDL;
}
setNull();
return FALSE;
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index 7889828c85..0699dcda83 100755
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -28,6 +28,7 @@
#include <iostream>
#include <set>
+#include <vector>
#include "stdtypes.h"
#include "llpreprocessor.h"
diff --git a/indra/llcommon/lluuidhashmap.h b/indra/llcommon/lluuidhashmap.h
deleted file mode 100755
index e294670030..0000000000
--- a/indra/llcommon/lluuidhashmap.h
+++ /dev/null
@@ -1,583 +0,0 @@
-/**
- * @file lluuidhashmap.h
- * @brief A uuid based hash map.
- *
- * $LicenseInfo:firstyear=2003&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLUUIDHASHMAP_H
-#define LL_LLUUIDHASHMAP_H
-
-#include "stdtypes.h"
-#include "llerror.h"
-#include "lluuid.h"
-
-// UUID hash map
-
- /*
- LLUUIDHashMap<uuid_pair, 32> foo(test_equals);
- LLUUIDHashMapIter<uuid_pair, 32> bar(&foo);
-
- LLDynamicArray<LLUUID> source_ids;
- const S32 COUNT = 100000;
- S32 q;
- for (q = 0; q < COUNT; q++)
- {
- llinfos << "Creating" << llendl;
- LLUUID id;
- id.generate();
- //llinfos << q << ":" << id << llendl;
- uuid_pair pair;
- pair.mUUID = id;
- pair.mValue = q;
- foo.set(id, pair);
- source_ids.put(id);
- //ms_sleep(1);
- }
-
- uuid_pair cur;
- llinfos << "Iterating" << llendl;
- for (cur = bar.first(); !bar.done(); cur = bar.next())
- {
- if (source_ids[cur.mValue] != cur.mUUID)
- {
- llerrs << "Incorrect value iterated!" << llendl;
- }
- //llinfos << cur.mValue << ":" << cur.mUUID << llendl;
- //ms_sleep(1);
- }
-
- llinfos << "Finding" << llendl;
- for (q = 0; q < COUNT; q++)
- {
- cur = foo.get(source_ids[q]);
- if (source_ids[cur.mValue] != cur.mUUID)
- {
- llerrs << "Incorrect value found!" << llendl;
- }
- //llinfos << res.mValue << ":" << res.mUUID << llendl;
- //ms_sleep(1);
- }
-
- llinfos << "Removing" << llendl;
- for (q = 0; q < COUNT/2; q++)
- {
- if (!foo.remove(source_ids[q]))
- {
- llerrs << "Remove failed!" << llendl;
- }
- //ms_sleep(1);
- }
-
- llinfos << "Iterating" << llendl;
- for (cur = bar.first(); !bar.done(); cur = bar.next())
- {
- if (source_ids[cur.mValue] != cur.mUUID)
- {
- llerrs << "Incorrect value found!" << llendl;
- }
- //llinfos << cur.mValue << ":" << cur.mUUID << llendl;
- //ms_sleep(1);
- }
- llinfos << "Done with UUID map test" << llendl;
-
- return 0;
- */
-
-
-//
-// LLUUIDHashNode
-//
-
-template <class DATA, int SIZE>
-class LLUUIDHashNode
-{
-public:
- LLUUIDHashNode();
-
-public:
- S32 mCount;
- U8 mKey[SIZE];
- DATA mData[SIZE];
- LLUUIDHashNode<DATA, SIZE> *mNextNodep;
-};
-
-
-//
-// LLUUIDHashNode implementation
-//
-template <class DATA, int SIZE>
-LLUUIDHashNode<DATA, SIZE>::LLUUIDHashNode()
-{
- mCount = 0;
- mNextNodep = NULL;
-}
-
-
-template <class DATA_TYPE, int SIZE>
-class LLUUIDHashMap
-{
-public:
- // basic constructor including sorter
- LLUUIDHashMap(BOOL (*equals)(const LLUUID &uuid, const DATA_TYPE &data),
- const DATA_TYPE &null_data);
- ~LLUUIDHashMap();
-
- inline DATA_TYPE &get(const LLUUID &uuid);
- inline BOOL check(const LLUUID &uuid) const;
- inline DATA_TYPE &set(const LLUUID &uuid, const DATA_TYPE &type);
- inline BOOL remove(const LLUUID &uuid);
- void removeAll();
-
- inline S32 getLength() const; // Warning, NOT O(1!)
-public:
- BOOL (*mEquals)(const LLUUID &uuid, const DATA_TYPE &data);
- LLUUIDHashNode<DATA_TYPE, SIZE> mNodes[256];
-
- S32 mIterCount;
-protected:
- DATA_TYPE mNull;
-};
-
-
-//
-// LLUUIDHashMap implementation
-//
-
-template <class DATA_TYPE, int SIZE>
-LLUUIDHashMap<DATA_TYPE, SIZE>::LLUUIDHashMap(BOOL (*equals)(const LLUUID &uuid, const DATA_TYPE &data),
- const DATA_TYPE &null_data)
-: mEquals(equals),
- mIterCount(0),
- mNull(null_data)
-{ }
-
-template <class DATA_TYPE, int SIZE>
-LLUUIDHashMap<DATA_TYPE, SIZE>::~LLUUIDHashMap()
-{
- removeAll();
-}
-
-template <class DATA_TYPE, int SIZE>
-void LLUUIDHashMap<DATA_TYPE, SIZE>::removeAll()
-{
- S32 bin;
- for (bin = 0; bin < 256; bin++)
- {
- LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin];
-
- BOOL first = TRUE;
- while (nodep)
- {
- S32 i;
- const S32 count = nodep->mCount;
-
- // Iterate through all members of this node
- for (i = 0; i < count; i++)
- {
- nodep->mData[i] = mNull;
- }
-
- nodep->mCount = 0;
- // Done with all objects in this node, go to the next.
-
- LLUUIDHashNode<DATA_TYPE, SIZE>* curp = nodep;
- nodep = nodep->mNextNodep;
-
- // Delete the node if it's not the first node
- if (first)
- {
- first = FALSE;
- curp->mNextNodep = NULL;
- }
- else
- {
- delete curp;
- }
- }
- }
-}
-
-template <class DATA_TYPE, int SIZE>
-inline S32 LLUUIDHashMap<DATA_TYPE, SIZE>::getLength() const
-{
- S32 count = 0;
- S32 bin;
- for (bin = 0; bin < 256; bin++)
- {
- LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = (LLUUIDHashNode<DATA_TYPE, SIZE>*) &mNodes[bin];
- while (nodep)
- {
- count += nodep->mCount;
- nodep = nodep->mNextNodep;
- }
- }
- return count;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline DATA_TYPE &LLUUIDHashMap<DATA_TYPE, SIZE>::get(const LLUUID &uuid)
-{
- LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[uuid.mData[0]];
-
- // Grab the second byte of the UUID, which is the key for the node data
- const S32 second_byte = uuid.mData[1];
- while (nodep)
- {
- S32 i;
- const S32 count = nodep->mCount;
-
- // Iterate through all members of this node
- for (i = 0; i < count; i++)
- {
- if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
- {
- // The second byte matched, and our equality test passed.
- // We found it.
- return nodep->mData[i];
- }
- }
-
- // Done with all objects in this node, go to the next.
- nodep = nodep->mNextNodep;
- }
- return mNull;
-}
-
-
-template <class DATA_TYPE, int SIZE>
-inline BOOL LLUUIDHashMap<DATA_TYPE, SIZE>::check(const LLUUID &uuid) const
-{
- const LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[uuid.mData[0]];
-
- // Grab the second byte of the UUID, which is the key for the node data
- const S32 second_byte = uuid.mData[1];
- while (nodep)
- {
- S32 i;
- const S32 count = nodep->mCount;
-
- // Iterate through all members of this node
- for (i = 0; i < count; i++)
- {
- if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
- {
- // The second byte matched, and our equality test passed.
- // We found it.
- return TRUE;
- }
- }
-
- // Done with all objects in this node, go to the next.
- nodep = nodep->mNextNodep;
- }
-
- // Didn't find anything
- return FALSE;
-}
-
-
-template <class DATA_TYPE, int SIZE>
-inline DATA_TYPE &LLUUIDHashMap<DATA_TYPE, SIZE>::set(const LLUUID &uuid, const DATA_TYPE &data)
-{
- // Set is just like a normal find, except that if we find a match
- // we replace it with the input value.
- // If we don't find a match, we append to the end of the list.
-
- LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[uuid.mData[0]];
-
- const S32 second_byte = uuid.mData[1];
- while (1)
- {
- const S32 count = nodep->mCount;
-
- S32 i;
- for (i = 0; i < count; i++)
- {
- if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
- {
- // We found a match for this key, replace the data with
- // the incoming data.
- nodep->mData[i] = data;
- return nodep->mData[i];
- }
- }
- if (!nodep->mNextNodep)
- {
- // We've iterated through all of the keys without finding a match
- if (i < SIZE)
- {
- // There's still some space on this node, append
- // the key and data to it.
- nodep->mKey[i] = second_byte;
- nodep->mData[i] = data;
- nodep->mCount++;
-
- return nodep->mData[i];
- }
- else
- {
- // This node is full, append a new node to the end.
- nodep->mNextNodep = new LLUUIDHashNode<DATA_TYPE, SIZE>;
- nodep->mNextNodep->mKey[0] = second_byte;
- nodep->mNextNodep->mData[0] = data;
- nodep->mNextNodep->mCount = 1;
-
- return nodep->mNextNodep->mData[0];
- }
- }
-
- // No match on this node, go to the next
- nodep = nodep->mNextNodep;
- }
-}
-
-
-template <class DATA_TYPE, int SIZE>
-inline BOOL LLUUIDHashMap<DATA_TYPE, SIZE>::remove(const LLUUID &uuid)
-{
- if (mIterCount)
- {
- // We don't allow remove when we're iterating, it's bad karma!
- llerrs << "Attempted remove while an outstanding iterator in LLUUIDHashMap!" << llendl;
- }
- // Remove is the trickiest operation.
- // What we want to do is swap the last element of the last
- // node if we find the one that we want to remove, but we have
- // to deal with deleting the node from the tail if it's empty, but
- // NOT if it's the only node left.
-
- LLUUIDHashNode<DATA_TYPE, SIZE> *nodep = &mNodes[uuid.mData[0]];
-
- // Not empty, we need to search through the nodes
- const S32 second_byte = uuid.mData[1];
-
- // A modification of the standard search algorithm.
- while (nodep)
- {
- const S32 count = nodep->mCount;
-
- S32 i;
- for (i = 0; i < count; i++)
- {
- if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i]))
- {
- // We found the node that we want to remove.
- // Find the last (and next-to-last) node, and the index of the last
- // element. We could conceviably start from the node we're on,
- // but that makes it more complicated, this is easier.
-
- LLUUIDHashNode<DATA_TYPE, SIZE> *prevp = &mNodes[uuid.mData[0]];
- LLUUIDHashNode<DATA_TYPE, SIZE> *lastp = prevp;
-
- // Find the last and next-to-last
- while (lastp->mNextNodep)
- {
- prevp = lastp;
- lastp = lastp->mNextNodep;
- }
-
- // First, swap in the last to the current location.
- nodep->mKey[i] = lastp->mKey[lastp->mCount - 1];
- nodep->mData[i] = lastp->mData[lastp->mCount - 1];
-
- // Now, we delete the entry
- lastp->mCount--;
- lastp->mData[lastp->mCount] = mNull;
-
- if (!lastp->mCount)
- {
- // We deleted the last element!
- if (lastp != &mNodes[uuid.mData[0]])
- {
- // Only blitz the node if it's not the head
- // Set the previous node to point to NULL, then
- // blitz the empty last node
- prevp->mNextNodep = NULL;
- delete lastp;
- }
- }
- return TRUE;
- }
- }
-
- // Iterate to the next node, we've scanned all the entries in this one.
- nodep = nodep->mNextNodep;
- }
- return FALSE;
-}
-
-
-//
-// LLUUIDHashMapIter
-//
-
-template <class DATA_TYPE, int SIZE>
-class LLUUIDHashMapIter
-{
-public:
- LLUUIDHashMapIter(LLUUIDHashMap<DATA_TYPE, SIZE> *hash_mapp);
- ~LLUUIDHashMapIter();
-
-
- inline void reset();
- inline void first();
- inline void next();
- inline BOOL done() const;
-
- DATA_TYPE& operator*() const
- {
- return mCurHashNodep->mData[mCurHashNodeKey];
- }
- DATA_TYPE* operator->() const
- {
- return &(operator*());
- }
-
-protected:
- LLUUIDHashMap<DATA_TYPE, SIZE> *mHashMapp;
- LLUUIDHashNode<DATA_TYPE, SIZE> *mCurHashNodep;
-
- S32 mCurHashMapNodeNum;
- S32 mCurHashNodeKey;
-
- DATA_TYPE mNull;
-};
-
-
-//
-// LLUUIDHashMapIter Implementation
-//
-template <class DATA_TYPE, int SIZE>
-LLUUIDHashMapIter<DATA_TYPE, SIZE>::LLUUIDHashMapIter(LLUUIDHashMap<DATA_TYPE, SIZE> *hash_mapp)
-{
- mHashMapp = hash_mapp;
- mCurHashNodep = NULL;
- mCurHashMapNodeNum = 0;
- mCurHashNodeKey = 0;
-}
-
-template <class DATA_TYPE, int SIZE>
-LLUUIDHashMapIter<DATA_TYPE, SIZE>::~LLUUIDHashMapIter()
-{
- reset();
-}
-
-template <class DATA_TYPE, int SIZE>
-inline void LLUUIDHashMapIter<DATA_TYPE, SIZE>::reset()
-{
- if (mCurHashNodep)
- {
- // We're partway through an iteration, we can clean up now
- mHashMapp->mIterCount--;
- mCurHashNodep = NULL;
- }
-}
-
-template <class DATA_TYPE, int SIZE>
-inline void LLUUIDHashMapIter<DATA_TYPE, SIZE>::first()
-{
- // Iterate through until we find the first non-empty node;
- S32 i;
- for (i = 0; i < 256; i++)
- {
- if (mHashMapp->mNodes[i].mCount)
- {
- if (!mCurHashNodep)
- {
- // Increment, since it's no longer safe for us to do a remove
- mHashMapp->mIterCount++;
- }
-
- mCurHashNodep = &mHashMapp->mNodes[i];
- mCurHashMapNodeNum = i;
- mCurHashNodeKey = 0;
- //return mCurHashNodep->mData[0];
- return;
- }
- }
-
- // Completely empty!
- mCurHashNodep = NULL;
- //return mNull;
- return;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline BOOL LLUUIDHashMapIter<DATA_TYPE, SIZE>::done() const
-{
- return mCurHashNodep ? FALSE : TRUE;
-}
-
-template <class DATA_TYPE, int SIZE>
-inline void LLUUIDHashMapIter<DATA_TYPE, SIZE>::next()
-{
- // No current entry, this iterator is done
- if (!mCurHashNodep)
- {
- //return mNull;
- return;
- }
-
- // Go to the next element
- mCurHashNodeKey++;
- if (mCurHashNodeKey < mCurHashNodep->mCount)
- {
- // We're not done with this node, return the current element
- //return mCurHashNodep->mData[mCurHashNodeKey];
- return;
- }
-
- // Done with this node, move to the next
- mCurHashNodep = mCurHashNodep->mNextNodep;
- if (mCurHashNodep)
- {
- // Return the first element
- mCurHashNodeKey = 0;
- //return mCurHashNodep->mData[0];
- return;
- }
-
- // Find the next non-empty node (keyed on the first byte)
- mCurHashMapNodeNum++;
-
- S32 i;
- for (i = mCurHashMapNodeNum; i < 256; i++)
- {
- if (mHashMapp->mNodes[i].mCount)
- {
- // We found one that wasn't empty
- mCurHashNodep = &mHashMapp->mNodes[i];
- mCurHashMapNodeNum = i;
- mCurHashNodeKey = 0;
- //return mCurHashNodep->mData[0];
- return;
- }
- }
-
- // OK, we're done, nothing else to iterate
- mCurHashNodep = NULL;
- mHashMapp->mIterCount--; // Decrement since we're safe to do removes now
- //return mNull;
-}
-
-#endif // LL_LLUUIDHASHMAP_H
diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llwin32headers.h
index ef68a0eaf5..8cfa40ada8 100755..100644
--- a/indra/llcommon/llversionserver.h
+++ b/indra/llcommon/llwin32headers.h
@@ -1,8 +1,8 @@
/**
- * @file llversionserver.h
- * @brief
+ * @file llwin32headers.h
+ * @brief sanitized include of windows header files
*
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
@@ -24,15 +24,19 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLVERSIONSERVER_H
-#define LL_LLVERSIONSERVER_H
-
-const S32 LL_VERSION_MAJOR = 2;
-const S32 LL_VERSION_MINOR = 1;
-const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 264760;
-
-const char * const LL_CHANNEL = "Second Life Server";
+#ifndef LL_LLWINDOWS_H
+#define LL_LLWINDOWS_H
+#ifdef LL_WINDOWS
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#undef WIN32_LEAN_AND_MEAN
+#include <winsock2.h>
+#include <windows.h>
+// reset to default, which is lean
+#define WIN32_LEAN_AND_MEAN
+#undef NOMINMAX
+#endif
#endif
diff --git a/indra/llcommon/lldarrayptr.h b/indra/llcommon/llwin32headerslean.h
index c9a0b204d1..314e7a85d1 100755..100644
--- a/indra/llcommon/lldarrayptr.h
+++ b/indra/llcommon/llwin32headerslean.h
@@ -1,6 +1,6 @@
/**
- * @file lldarrayptr.h
- * @brief Wrapped std::vector for backward compatibility.
+ * @file llwin32headerslean.h
+ * @brief sanitized include of windows header files
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
@@ -23,14 +23,18 @@
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
-#ifndef LL_LLDARRAYPTR_H
-#define LL_LLDARRAYPTR_H
-#include "lldarray.h"
+#ifndef LL_LLWINDOWS_H
+#define LL_LLWINDOWS_H
-template <class Type, int BlockSize = 32>
-class LLDynamicArrayPtr : public LLDynamicArray<Type, BlockSize>
-{
-};
+#ifdef LL_WINDOWS
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif
+#define WIN32_LEAN_AND_MEAN
+#include <winsock2.h>
+#include <windows.h>
+#undef NOMINMAX
+#endif
-#endif // LL_LLDARRAYPTR_H
+#endif
diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp
index 3d05a30ac2..4c197dc1d6 100755
--- a/indra/llcommon/llworkerthread.cpp
+++ b/indra/llcommon/llworkerthread.cpp
@@ -50,8 +50,8 @@ LLWorkerThread::~LLWorkerThread()
// Delete any workers in the delete queue (should be safe - had better be!)
if (!mDeleteList.empty())
{
- llwarns << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
- << " entries in delete list." << llendl;
+ LL_WARNS() << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
+ << " entries in delete list." << LL_ENDL;
}
delete mDeleteMutex;
@@ -65,8 +65,8 @@ void LLWorkerThread::clearDeleteList()
// Delete any workers in the delete queue (should be safe - had better be!)
if (!mDeleteList.empty())
{
- llwarns << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
- << " entries in delete list." << llendl;
+ LL_WARNS() << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size()
+ << " entries in delete list." << LL_ENDL;
mDeleteMutex->lock();
for (delete_list_t::iterator iter = mDeleteList.begin(); iter != mDeleteList.end(); ++iter)
@@ -142,7 +142,7 @@ LLWorkerThread::handle_t LLWorkerThread::addWorkRequest(LLWorkerClass* workercla
bool res = addRequest(req);
if (!res)
{
- llerrs << "add called after LLWorkerThread::cleanupClass()" << llendl;
+ LL_ERRS() << "add called after LLWorkerThread::cleanupClass()" << LL_ENDL;
req->deleteRequest();
handle = nullHandle();
}
@@ -209,7 +209,7 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
{
if (!mWorkerThread)
{
- llerrs << "LLWorkerClass() called with NULL workerthread: " << name << llendl;
+ LL_ERRS() << "LLWorkerClass() called with NULL workerthread: " << name << LL_ENDL;
}
}
@@ -223,12 +223,12 @@ LLWorkerClass::~LLWorkerClass()
LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle);
if (!workreq)
{
- llerrs << "LLWorkerClass destroyed with stale work handle" << llendl;
+ LL_ERRS() << "LLWorkerClass destroyed with stale work handle" << LL_ENDL;
}
if (workreq->getStatus() != LLWorkerThread::STATUS_ABORTED &&
workreq->getStatus() != LLWorkerThread::STATUS_COMPLETE)
{
- llerrs << "LLWorkerClass destroyed with active worker! Worker Status: " << workreq->getStatus() << llendl;
+ LL_ERRS() << "LLWorkerClass destroyed with active worker! Worker Status: " << workreq->getStatus() << LL_ENDL;
}
}
}
@@ -238,7 +238,7 @@ void LLWorkerClass::setWorkerThread(LLWorkerThread* workerthread)
mMutex.lock();
if (mRequestHandle != LLWorkerThread::nullHandle())
{
- llerrs << "LLWorkerClass attempt to change WorkerThread with active worker!" << llendl;
+ LL_ERRS() << "LLWorkerClass attempt to change WorkerThread with active worker!" << LL_ENDL;
}
mWorkerThread = workerthread;
mMutex.unlock();
@@ -298,10 +298,10 @@ void LLWorkerClass::addWork(S32 param, U32 priority)
llassert_always(!(mWorkFlags & (WCF_WORKING|WCF_HAVE_WORK)));
if (mRequestHandle != LLWorkerThread::nullHandle())
{
- llerrs << "LLWorkerClass attempt to add work with active worker!" << llendl;
+ LL_ERRS() << "LLWorkerClass attempt to add work with active worker!" << LL_ENDL;
}
#if _DEBUG
-// llinfos << "addWork: " << mWorkerClassName << " Param: " << param << llendl;
+// LL_INFOS() << "addWork: " << mWorkerClassName << " Param: " << param << LL_ENDL;
#endif
startWork(param);
clearFlags(WCF_WORK_FINISHED|WCF_WORK_ABORTED);
@@ -316,7 +316,7 @@ void LLWorkerClass::abortWork(bool autocomplete)
#if _DEBUG
// LLWorkerThread::WorkRequest* workreq = mWorkerThread->getRequest(mRequestHandle);
// if (workreq)
-// llinfos << "abortWork: " << mWorkerClassName << " Param: " << workreq->getParam() << llendl;
+// LL_INFOS() << "abortWork: " << mWorkerClassName << " Param: " << workreq->getParam() << LL_ENDL;
#endif
if (mRequestHandle != LLWorkerThread::nullHandle())
{
diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h
index be46394d6e..09776816a8 100755
--- a/indra/llcommon/llworkerthread.h
+++ b/indra/llcommon/llworkerthread.h
@@ -26,10 +26,11 @@
#ifndef LL_LLWORKERTHREAD_H
#define LL_LLWORKERTHREAD_H
-#include <queue>
-#include <string>
+#include <list>
#include <map>
+#include <queue>
#include <set>
+#include <string>
#include "llqueuedthread.h"
#include "llapr.h"
diff --git a/indra/llcommon/metaclass.cpp b/indra/llcommon/metaclass.cpp
deleted file mode 100755
index 5e403511cf..0000000000
--- a/indra/llcommon/metaclass.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * @file metaclass.cpp
- * @author Babbage
- * @date 2006-05-15
- * @brief Implementation of LLMetaClass
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "metaclass.h"
-
-#include "metaproperty.h"
-#include "reflective.h"
-
-LLMetaClass::LLMetaClass()
-{
-}
-
-//virtual
-LLMetaClass::~LLMetaClass()
-{
-}
-
-const LLMetaProperty* LLMetaClass::findProperty(const std::string& name) const
-{
- PropertyIterator iter = mProperties.find(name);
- if(iter == mProperties.end())
- {
- return NULL;
- }
- return (*iter).second;
-}
-
-void LLMetaClass::addProperty(const LLMetaProperty* property)
-{
- mProperties.insert(std::make_pair(property->getName(), property));
-}
-
-U32 LLMetaClass::getPropertyCount() const
-{
- return mProperties.size();
-}
-
-LLMetaClass::PropertyIterator LLMetaClass::beginProperties() const
-{
- return mProperties.begin();
-}
-
-LLMetaClass::PropertyIterator LLMetaClass::endProperties() const
-{
- return mProperties.end();
-}
-
-bool LLMetaClass::isInstance(const LLReflective* object) const
-{
- // TODO: Babbage: Search through super classes of objects MetaClass.
- const LLMetaClass* object_meta_class = &(object->getMetaClass());
- return (object_meta_class == this);
-}
-
diff --git a/indra/llcommon/metaclass.h b/indra/llcommon/metaclass.h
deleted file mode 100755
index 626757d58d..0000000000
--- a/indra/llcommon/metaclass.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * @file metaclass.h
- * @author Babbage
- * @date 2006-05-15
- * @brief Reflective meta information describing a class.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_METACLASS_H
-#define LL_METACLASS_H
-
-#include <string>
-#include <map>
-
-#include "stdtypes.h"
-
-class LLReflective;
-class LLMetaProperty;
-class LLMetaMethod;
-class LL_COMMON_API LLMetaClass
-{
-public:
-
- LLMetaClass();
- virtual ~LLMetaClass();
-
- // Create instance of this MetaClass. NULL if class is abstract.
- // Gives ownership of returned object.
- // virtual LLReflective* create() const = 0;
-
- // Returns named property or NULL.
- const LLMetaProperty* findProperty(const std::string& name) const;
-
- // Add property to metaclass. Takes ownership of given property.
- void addProperty(const LLMetaProperty* property);
-
- typedef std::map<std::string, const LLMetaProperty*>::const_iterator PropertyIterator;
-
- U32 getPropertyCount() const;
-
- PropertyIterator beginProperties() const;
- PropertyIterator endProperties() const;
-
- // Returns named property or NULL.
- // const LLMetaMethod* findMethod(const std::string& name) const;
-
- // Add method to metaclass. Takes ownership of given method.
- // void addMethod(const LLMetaMethod* method);
-
- // Find MetaClass by name. NULL if name is unknown.
- // static LLMetaClass* findClass(const std::string& name);
-
- // True if object is instance of this meta class.
- bool isInstance(const LLReflective* object) const;
-
-private:
-
- typedef std::map<std::string, const LLMetaProperty*> PropertyMap;
- PropertyMap mProperties;
-};
-
-#endif // LL_METACLASS_H
diff --git a/indra/llcommon/metaclasst.h b/indra/llcommon/metaclasst.h
deleted file mode 100755
index b9a7ae219d..0000000000
--- a/indra/llcommon/metaclasst.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- * @file metaclasst.h
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_METACLASST_H
-#define LL_METACLASST_H
-
-#include "metaclass.h"
-
-template<class TObject>
-class LLMetaClassT : public LLMetaClass
-{
- public:
-
- virtual ~LLMetaClassT() {;}
-
- static const LLMetaClassT& instance()
- {
- static const LLMetaClassT& instance = buildMetaClass();
- return instance;
- }
-
- private:
-
- static const LLMetaClassT& buildMetaClass()
- {
- LLMetaClassT& meta_class = *(new LLMetaClassT());
- reflectProperties(meta_class);
- return meta_class;
- }
-
- LLMetaClassT() {;}
-
- static void reflectProperties(LLMetaClass&)
- {
- }
-};
-
-#endif // LL_METACLASST_H
diff --git a/indra/llcommon/metaproperty.cpp b/indra/llcommon/metaproperty.cpp
deleted file mode 100755
index 98d850bf1e..0000000000
--- a/indra/llcommon/metaproperty.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * @file metaproperty.cpp
- * @author Babbage
- * @date 2006-05-15
- * @brief Implementation of LLMetaProperty.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "metaproperty.h"
-
-#include "metaclass.h"
-
-LLMetaProperty::LLMetaProperty(const std::string& name, const LLMetaClass& object_class) :
- mName(name), mObjectClass(object_class)
-{
-}
-
-//virtual
-LLMetaProperty::~LLMetaProperty()
-{
-}
-
-const LLMetaClass& LLMetaProperty::getObjectMetaClass() const
-{
- return mObjectClass;
-}
-
-void LLMetaProperty::checkObjectClass(const LLReflective* object) const
-{
- if(! mObjectClass.isInstance(object))
- {
- throw "class cast exception";
- }
-}
diff --git a/indra/llcommon/metaproperty.h b/indra/llcommon/metaproperty.h
deleted file mode 100755
index bd5bb1a30f..0000000000
--- a/indra/llcommon/metaproperty.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * @file metaproperty.h
- * @author Babbage
- * @date 2006-05-15
- * @brief Reflective meta information describing a property of a class.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_METAPROPERTY_H
-#define LL_METAPROPERTY_H
-
-#include "stdtypes.h"
-#include "llsd.h"
-#include "reflective.h"
-
-class LLMetaClass;
-class LLReflective;
-class LL_COMMON_API LLMetaProperty
-{
-public:
- LLMetaProperty(const std::string& name, const LLMetaClass& object_class);
- virtual ~LLMetaProperty();
-
- // Get property name.
- const std::string& getName() const {return mName;}
-
- // Get value of this property.
- virtual const LLReflective* get(const LLReflective* object) const = 0;
-
- // Set value of this property.
- // virtual void set(LLReflective* object, const LLReflective* value) = 0;
-
- // Get value of this property as LLSD. Default returns undefined LLSD.
- virtual LLSD getLLSD(const LLReflective* object) const = 0;
-
- // Get the MetaClass of legal values of this property.
- // const LLMetaClass& getValueMetaClass();
-
- // Get the meta class that this property is a member of.
- const LLMetaClass& getObjectMetaClass() const;
-
-protected:
-
- // Check object is instance of object class, throw exception if not.
- void checkObjectClass(const LLReflective* object) const;
-
-private:
-
- std::string mName;
- const LLMetaClass& mObjectClass;
-};
-
-#endif // LL_METAPROPERTY_H
diff --git a/indra/llcommon/metapropertyt.h b/indra/llcommon/metapropertyt.h
deleted file mode 100755
index 7a36c161da..0000000000
--- a/indra/llcommon/metapropertyt.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/**
- * @file metapropertyt.h
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_METAPROPERTYT_H
-#define LL_METAPROPERTYT_H
-
-#include "llsd.h"
-#include "llstring.h"
-#include "metaclasst.h"
-#include "metaproperty.h"
-#include "reflectivet.h"
-
-template<class TProperty>
-class LLMetaPropertyT : public LLMetaProperty
-{
-public:
-
- virtual ~LLMetaPropertyT() {;}
-
- // Get value of this property. Gives ownership of returned value.
- virtual const LLReflective* get(const LLReflective* object) const
- {
- checkObjectClass(object);
- return getProperty(object);
- }
-
- // Set value of this property.
- /*virtual void set(LLReflective* object, const LLReflective* value)
- {
- // TODO: Babbage: Check types.
- ref(object) = static_cast<const LLReflectiveT<TProperty>* >(value)->getValue();
- }*/
-
- // Get value of this property as LLSD.
- virtual LLSD getLLSD(const LLReflective* object) const
- {
- return LLSD();
- }
-
-protected:
-
- LLMetaPropertyT(const std::string& name, const LLMetaClass& object_class) : LLMetaProperty(name, object_class) {;}
-
- virtual const TProperty* getProperty(const LLReflective* object) const = 0;
-};
-
-template <>
-inline const LLReflective* LLMetaPropertyT<S32>::get(const LLReflective* object) const
-{
- checkObjectClass(object);
- return NULL;
-}
-
-template <>
-inline const LLReflective* LLMetaPropertyT<std::string>::get(const LLReflective* object) const
-{
- checkObjectClass(object);
- return NULL;
-}
-
-template <>
-inline const LLReflective* LLMetaPropertyT<LLUUID>::get(const LLReflective* object) const
-{
- checkObjectClass(object);
- return NULL;
-}
-
-template <>
-inline const LLReflective* LLMetaPropertyT<bool>::get(const LLReflective* object) const
-{
- checkObjectClass(object);
- return NULL;
-}
-
-template <>
-inline LLSD LLMetaPropertyT<S32>::getLLSD(const LLReflective* object) const
-{
- return *(getProperty(object));
-}
-
-template <>
-inline LLSD LLMetaPropertyT<std::string>::getLLSD(const LLReflective* object) const
-{
- return *(getProperty(object));
-}
-
-template <>
-inline LLSD LLMetaPropertyT<LLUUID>::getLLSD(const LLReflective* object) const
-{
- return *(getProperty(object));
-}
-
-template <>
-inline LLSD LLMetaPropertyT<bool>::getLLSD(const LLReflective* object) const
-{
- return *(getProperty(object));
-}
-
-template<class TObject, class TProperty>
-class LLMetaPropertyTT : public LLMetaPropertyT<TProperty>
-{
-public:
-
- LLMetaPropertyTT(const std::string& name, const LLMetaClass& object_class, TProperty (TObject::*property)) :
- LLMetaPropertyT<TProperty>(name, object_class), mProperty(property) {;}
-
-protected:
-
- // Get void* to property.
- virtual const TProperty* getProperty(const LLReflective* object) const
- {
- const TObject* typed_object = static_cast<const TObject*>(object);
- return &(typed_object->*mProperty);
- };
-
-private:
-
- TProperty (TObject::*mProperty);
-};
-
-template<class TObject, class TProperty>
-class LLMetaPropertyPtrTT : public LLMetaPropertyT<TProperty>
-{
-public:
-
- LLMetaPropertyPtrTT(const std::string& name, const LLMetaClass& object_class, TProperty* (TObject::*property)) :
- LLMetaPropertyT<TProperty>(name, object_class), mProperty(property) {;}
-
-protected:
-
- // Get void* to property.
- virtual const TProperty* getProperty(const LLReflective* object) const
- {
- const TObject* typed_object = static_cast<const TObject*>(object);
- return typed_object->*mProperty;
- };
-
-private:
-
- TProperty* (TObject::*mProperty);
-};
-
-// Utility function to simplify the registration of members.
-template<class TObject, class TProperty>
-void reflectProperty(LLMetaClass& meta_class, const std::string& name, TProperty (TObject::*property))
-{
- typedef LLMetaPropertyTT<TObject, TProperty> PropertyType;
- const LLMetaProperty* meta_property = new PropertyType(name, meta_class, property);
- meta_class.addProperty(meta_property);
-}
-
-// Utility function to simplify the registration of ptr properties.
-template<class TObject, class TProperty>
-void reflectPtrProperty(LLMetaClass& meta_class, const std::string& name, TProperty* (TObject::*property))
-{
- typedef LLMetaPropertyPtrTT<TObject, TProperty> PropertyType;
- const LLMetaProperty* meta_property = new PropertyType(name, meta_class, property);
- meta_class.addProperty(meta_property);
-}
-
-#endif // LL_METAPROPERTYT_H
diff --git a/indra/llcommon/reflective.cpp b/indra/llcommon/reflective.cpp
deleted file mode 100755
index 2cc0e7e1f2..0000000000
--- a/indra/llcommon/reflective.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * @file reflective.cpp
- * @author Babbage
- * @date 2006-05-15
- * @brief Implementation of LLReflective.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "reflective.h"
-
-LLReflective::LLReflective()
-{
-}
-
-//virtual
-LLReflective::~LLReflective()
-{
-}
diff --git a/indra/llcommon/reflective.h b/indra/llcommon/reflective.h
deleted file mode 100755
index da5c5a2630..0000000000
--- a/indra/llcommon/reflective.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * @file reflective.h
- * @author Babbage
- * @date 2006-05-15
- * @brief Interface that must be implemented by all reflective classes.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_REFLECTIVE_H
-#define LL_REFLECTIVE_H
-
-class LLMetaClass;
-class LL_COMMON_API LLReflective
-{
-public:
- LLReflective();
- virtual ~LLReflective();
-
- virtual const LLMetaClass& getMetaClass() const = 0;
-};
-
-#endif // LL_REFLECTIVE_H
diff --git a/indra/llcommon/reflectivet.h b/indra/llcommon/reflectivet.h
deleted file mode 100755
index 958921f23e..0000000000
--- a/indra/llcommon/reflectivet.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/**
- * @file reflectivet.h
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_REFLECTIVET_H
-#define LL_REFLECTIVET_H
-
-#include "reflective.h"
-
-template <class T>
-class LLReflectiveT : public LLReflective
-{
-public:
-
- LLReflectiveT(const T& value) : mValue(value) {;}
- virtual ~LLReflectiveT() {;}
-
- virtual const LLMetaClass& getMetaClass() const {return LLMetaClassT<LLReflectiveT<T> >::instance();}
-
- const T& getValue() const {return mValue;}
-
-private:
-
- T mValue;
-};
-
-#endif
diff --git a/indra/llcommon/roles_constants.h b/indra/llcommon/roles_constants.h
deleted file mode 100755
index effd15ea72..0000000000
--- a/indra/llcommon/roles_constants.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/**
- * @file roles_constants.h
- * @brief General Roles Constants
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_ROLES_CONSTANTS_H
-#define LL_ROLES_CONSTANTS_H
-
-// This value includes the everyone group.
-const S32 MAX_ROLES = 10;
-
-enum LLRoleMemberChangeType
-{
- RMC_ADD,
- RMC_REMOVE,
- RMC_NONE
-};
-
-enum LLRoleChangeType
-{
- RC_UPDATE_NONE,
- RC_UPDATE_DATA,
- RC_UPDATE_POWERS,
- RC_UPDATE_ALL,
- RC_CREATE,
- RC_DELETE
-};
-
-//
-// Powers
-//
-
-// KNOWN HOLES: use these for any single bit powers you need
-// bit 0x1 << 46
-// bit 0x1 << 49 and above
-
-// These powers were removed to make group roles simpler
-// bit 0x1 << 41 (GP_ACCOUNTING_VIEW)
-// bit 0x1 << 46 (GP_PROPOSAL_VIEW)
-
-const U64 GP_NO_POWERS = 0x0;
-const U64 GP_ALL_POWERS = 0xFFFFFFFFFFFFFFFFLL;
-
-// Membership
-const U64 GP_MEMBER_INVITE = 0x1 << 1; // Invite member
-const U64 GP_MEMBER_EJECT = 0x1 << 2; // Eject member from group
-const U64 GP_MEMBER_OPTIONS = 0x1 << 3; // Toggle "Open enrollment" and change "Signup Fee"
-const U64 GP_MEMBER_VISIBLE_IN_DIR = 0x1LL << 47;
-
-// Roles
-const U64 GP_ROLE_CREATE = 0x1 << 4; // Create new roles
-const U64 GP_ROLE_DELETE = 0x1 << 5; // Delete roles
-const U64 GP_ROLE_PROPERTIES = 0x1 << 6; // Change Role Names, Titles, and Descriptions (Of roles the user is in, only, or any role in group?)
-const U64 GP_ROLE_ASSIGN_MEMBER_LIMITED = 0x1 << 7; // Assign Member to a Role that the assigner is in
-const U64 GP_ROLE_ASSIGN_MEMBER = 0x1 << 8; // Assign Member to Role
-const U64 GP_ROLE_REMOVE_MEMBER = 0x1 << 9; // Remove Member from Role
-const U64 GP_ROLE_CHANGE_ACTIONS = 0x1 << 10; // Change actions a role can perform
-
-// Group Identity
-const U64 GP_GROUP_CHANGE_IDENTITY = 0x1 << 11; // Charter, insignia, 'Show In Group List', 'Publish on the web', 'Mature', all 'Show Member In Group Profile' checkboxes
-
-// Parcel Management
-const U64 GP_LAND_DEED = 0x1 << 12; // Deed Land and Buy Land for Group
-const U64 GP_LAND_RELEASE = 0x1 << 13; // Release Land (to Gov. Linden)
-const U64 GP_LAND_SET_SALE_INFO = 0x1 << 14; // Set for sale info (Toggle "For Sale", Set Price, Set Target, Toggle "Sell objects with the land")
-const U64 GP_LAND_DIVIDE_JOIN = 0x1 << 15; // Divide and Join Parcels
-
-// Parcel Identity
-const U64 GP_LAND_FIND_PLACES = 0x1 << 17; // Toggle "Show in Find Places" and Set Category.
-const U64 GP_LAND_CHANGE_IDENTITY = 0x1 << 18; // Change Parcel Identity: Parcel Name, Parcel Description, Snapshot, 'Publish on the web', and 'Mature' checkbox
-const U64 GP_LAND_SET_LANDING_POINT = 0x1 << 19; // Set Landing Point
-
-// Parcel Settings
-const U64 GP_LAND_CHANGE_MEDIA = 0x1 << 20; // Change Media Settings
-const U64 GP_LAND_EDIT = 0x1 << 21; // Toggle Edit Land
-const U64 GP_LAND_OPTIONS = 0x1 << 22; // Toggle Set Home Point, Fly, Outside Scripts, Create/Edit Objects, Landmark, and Damage checkboxes
-
-// Parcel Powers
-const U64 GP_LAND_ALLOW_EDIT_LAND = 0x1 << 23; // Bypass Edit Land Restriction
-const U64 GP_LAND_ALLOW_FLY = 0x1 << 24; // Bypass Fly Restriction
-const U64 GP_LAND_ALLOW_CREATE = 0x1 << 25; // Bypass Create/Edit Objects Restriction
-const U64 GP_LAND_ALLOW_LANDMARK = 0x1 << 26; // Bypass Landmark Restriction
-const U64 GP_LAND_ALLOW_SET_HOME = 0x1 << 28; // Bypass Set Home Point Restriction
-const U64 GP_LAND_ALLOW_HOLD_EVENT = 0x1LL << 41; // Allowed to hold events on group-owned land
-
-
-// Parcel Access
-const U64 GP_LAND_MANAGE_ALLOWED = 0x1 << 29; // Manage Allowed List
-const U64 GP_LAND_MANAGE_BANNED = 0x1 << 30; // Manage Banned List
-const U64 GP_LAND_MANAGE_PASSES = 0x1LL << 31; // Change Sell Pass Settings
-const U64 GP_LAND_ADMIN = 0x1LL << 32; // Eject and Freeze Users on the land
-
-// Parcel Content
-const U64 GP_LAND_RETURN_GROUP_SET = 0x1LL << 33; // Return objects on parcel that are set to group
-const U64 GP_LAND_RETURN_NON_GROUP = 0x1LL << 34; // Return objects on parcel that are not set to group
-const U64 GP_LAND_RETURN_GROUP_OWNED= 0x1LL << 48; // Return objects on parcel that are owned by the group
-
-// Select a power-bit based on an object's relationship to a parcel.
-const U64 GP_LAND_RETURN = GP_LAND_RETURN_GROUP_OWNED
- | GP_LAND_RETURN_GROUP_SET
- | GP_LAND_RETURN_NON_GROUP;
-
-const U64 GP_LAND_GARDENING = 0x1LL << 35; // Parcel Gardening - plant and move linden trees
-
-// Object Management
-const U64 GP_OBJECT_DEED = 0x1LL << 36; // Deed Object
-const U64 GP_OBJECT_MANIPULATE = 0x1LL << 38; // Manipulate Group Owned Objects (Move, Copy, Mod)
-const U64 GP_OBJECT_SET_SALE = 0x1LL << 39; // Set Group Owned Object for Sale
-
-// Accounting
-const U64 GP_ACCOUNTING_ACCOUNTABLE = 0x1LL << 40; // Pay Group Liabilities and Receive Group Dividends
-
-// Notices
-const U64 GP_NOTICES_SEND = 0x1LL << 42; // Send Notices
-const U64 GP_NOTICES_RECEIVE = 0x1LL << 43; // Receive Notices and View Notice History
-
-// Proposals
-// TODO: _DEPRECATED suffix as part of vote removal - DEV-24856:
-const U64 GP_PROPOSAL_START = 0x1LL << 44; // Start Proposal
-// TODO: _DEPRECATED suffix as part of vote removal - DEV-24856:
-const U64 GP_PROPOSAL_VOTE = 0x1LL << 45; // Vote on Proposal
-
-// Group chat moderation related
-const U64 GP_SESSION_JOIN = 0x1LL << 16; //can join session
-const U64 GP_SESSION_VOICE = 0x1LL << 27; //can hear/talk
-const U64 GP_SESSION_MODERATOR = 0x1LL << 37; //can mute people's session
-
-const U64 GP_DEFAULT_MEMBER = GP_ACCOUNTING_ACCOUNTABLE
- | GP_LAND_ALLOW_SET_HOME
- | GP_NOTICES_RECEIVE
- | GP_SESSION_JOIN
- | GP_SESSION_VOICE
- ;
-
-const U64 GP_DEFAULT_OFFICER = GP_DEFAULT_MEMBER // Superset of GP_DEFAULT_MEMBER
- | GP_GROUP_CHANGE_IDENTITY
- | GP_LAND_ADMIN
- | GP_LAND_ALLOW_EDIT_LAND
- | GP_LAND_ALLOW_FLY
- | GP_LAND_ALLOW_CREATE
- | GP_LAND_ALLOW_LANDMARK
- | GP_LAND_CHANGE_IDENTITY
- | GP_LAND_CHANGE_MEDIA
- | GP_LAND_DEED
- | GP_LAND_DIVIDE_JOIN
- | GP_LAND_EDIT
- | GP_LAND_FIND_PLACES
- | GP_LAND_GARDENING
- | GP_LAND_MANAGE_ALLOWED
- | GP_LAND_MANAGE_BANNED
- | GP_LAND_MANAGE_PASSES
- | GP_LAND_OPTIONS
- | GP_LAND_RELEASE
- | GP_LAND_RETURN_GROUP_OWNED
- | GP_LAND_RETURN_GROUP_SET
- | GP_LAND_RETURN_NON_GROUP
- | GP_LAND_SET_LANDING_POINT
- | GP_LAND_SET_SALE_INFO
- | GP_MEMBER_EJECT
- | GP_MEMBER_INVITE
- | GP_MEMBER_OPTIONS
- | GP_MEMBER_VISIBLE_IN_DIR
- | GP_NOTICES_SEND
- | GP_OBJECT_DEED
- | GP_OBJECT_MANIPULATE
- | GP_OBJECT_SET_SALE
- | GP_ROLE_ASSIGN_MEMBER_LIMITED
- | GP_ROLE_PROPERTIES
- | GP_SESSION_MODERATOR
- ;
-#endif
diff --git a/indra/llcommon/stdenums.h b/indra/llcommon/stdenums.h
deleted file mode 100755
index efcbe76795..0000000000
--- a/indra/llcommon/stdenums.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/**
- * @file stdenums.h
- * @brief Enumerations for indra.
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_STDENUMS_H
-#define LL_STDENUMS_H
-
-//----------------------------------------------------------------------------
-// DEPRECATED - create new, more specific files for shared enums/constants
-//----------------------------------------------------------------------------
-
-// this enum is used by the llview.h (viewer) and the llassetstorage.h (viewer and sim)
-enum EDragAndDropType
-{
- DAD_NONE = 0,
- DAD_TEXTURE = 1,
- DAD_SOUND = 2,
- DAD_CALLINGCARD = 3,
- DAD_LANDMARK = 4,
- DAD_SCRIPT = 5,
- DAD_CLOTHING = 6,
- DAD_OBJECT = 7,
- DAD_NOTECARD = 8,
- DAD_CATEGORY = 9,
- DAD_ROOT_CATEGORY = 10,
- DAD_BODYPART = 11,
- DAD_ANIMATION = 12,
- DAD_GESTURE = 13,
- DAD_LINK = 14,
- DAD_MESH = 15,
- DAD_WIDGET = 16,
- DAD_PERSON = 17,
- DAD_COUNT = 18, // number of types in this enum
-};
-
-// Reasons for drags to be denied.
-// ordered by priority for multi-drag
-enum EAcceptance
-{
- ACCEPT_POSTPONED, // we are asynchronously determining acceptance
- ACCEPT_NO, // Uninformative, general purpose denial.
- ACCEPT_NO_LOCKED, // Operation would be valid, but permissions are set to disallow it.
- ACCEPT_YES_COPY_SINGLE, // We'll take a copy of a single item
- ACCEPT_YES_SINGLE, // Accepted. OK to drag and drop single item here.
- ACCEPT_YES_COPY_MULTI, // We'll take a copy of multiple items
- ACCEPT_YES_MULTI // Accepted. OK to drag and drop multiple items here.
-};
-
-// This is used by the DeRezObject message to determine where to put
-// derezed tasks.
-enum EDeRezDestination
-{
- DRD_SAVE_INTO_AGENT_INVENTORY = 0,
- DRD_ACQUIRE_TO_AGENT_INVENTORY = 1, // try to leave copy in world
- DRD_SAVE_INTO_TASK_INVENTORY = 2,
- DRD_ATTACHMENT = 3,
- DRD_TAKE_INTO_AGENT_INVENTORY = 4, // delete from world
- DRD_FORCE_TO_GOD_INVENTORY = 5, // force take copy
- DRD_TRASH = 6,
- DRD_ATTACHMENT_TO_INV = 7,
- DRD_ATTACHMENT_EXISTS = 8,
- DRD_RETURN_TO_OWNER = 9, // back to owner's inventory
- DRD_RETURN_TO_LAST_OWNER = 10, // deeded object back to last owner's inventory
-
- DRD_COUNT = 11
-};
-
-
-// This is used by the return to owner code to determine the reason
-// that this object is being returned.
-enum EReturnReason
-{
- RR_GENERIC = 0,
- RR_SANDBOX = 1,
- RR_PARCEL_OWNER = 2,
- RR_PARCEL_AUTO = 3,
- RR_PARCEL_FULL = 4,
- RR_OFF_WORLD = 5,
-
- RR_COUNT = 6
-};
-
-// This is used for filling in the first byte of the ExtraID field of
-// the ObjectProperties message.
-enum EObjectPropertiesExtraID
-{
- OPEID_NONE = 0,
- OPEID_ASSET_ID = 1,
- OPEID_FROM_TASK_ID = 2,
-
- OPEID_COUNT = 3
-};
-
-enum EAddPosition
-{
- ADD_TOP,
- ADD_BOTTOM,
- ADD_DEFAULT
-};
-
-enum LLGroupChange
-{
- GC_PROPERTIES,
- GC_MEMBER_DATA,
- GC_ROLE_DATA,
- GC_ROLE_MEMBER_DATA,
- GC_TITLES,
- GC_ALL
-};
-
-//----------------------------------------------------------------------------
-// DEPRECATED - create new, more specific files for shared enums/constants
-//----------------------------------------------------------------------------
-
-#endif
diff --git a/indra/llcommon/string_table.h b/indra/llcommon/string_table.h
index fe6416fb50..fe6416fb50 100755..100644
--- a/indra/llcommon/string_table.h
+++ b/indra/llcommon/string_table.h
diff --git a/indra/llcommon/stringize.h b/indra/llcommon/stringize.h
index 72f2e58ce1..2df008febb 100755
--- a/indra/llcommon/stringize.h
+++ b/indra/llcommon/stringize.h
@@ -31,21 +31,64 @@
#include <sstream>
#include <boost/lambda/lambda.hpp>
+#include <llstring.h>
/**
- * stringize(item) encapsulates an idiom we use constantly, using
+ * gstringize(item) encapsulates an idiom we use constantly, using
* operator<<(std::ostringstream&, TYPE) followed by std::ostringstream::str()
+ * or their wstring equivalents
* to render a string expressing some item.
*/
-template <typename T>
-std::string stringize(const T& item)
+template <typename CHARTYPE, typename T>
+std::basic_string<CHARTYPE> gstringize(const T& item)
{
- std::ostringstream out;
+ std::basic_ostringstream<CHARTYPE> out;
out << item;
return out.str();
}
/**
+ *partial specialization of stringize for handling wstring
+ *TODO: we should have similar specializations for wchar_t[] but not until it is needed.
+ */
+inline std::string stringize(const std::wstring& item)
+{
+ LL_WARNS() << "WARNING: Possible narrowing" << LL_ENDL;
+
+ std::string s;
+
+ s = wstring_to_utf8str(item);
+ return gstringize<char>(s);
+}
+
+/**
+ * Specialization of gstringize for std::string return types
+ */
+template <typename T>
+std::string stringize(const T& item)
+{
+ return gstringize<char>(item);
+}
+
+/**
+ * Specialization for generating wstring from string.
+ * Both a convenience function and saves a miniscule amount of overhead.
+ */
+inline std::wstring wstringize(const std::string& item)
+{
+ return gstringize<wchar_t>(item.c_str());
+}
+
+/**
+ * Specialization of gstringize for std::wstring return types
+ */
+template <typename T>
+std::wstring wstringize(const T& item)
+{
+ return gstringize<wchar_t>(item);
+}
+
+/**
* stringize_f(functor)
*/
template <typename Functor>
diff --git a/indra/llcommon/tests/bitpack_test.cpp b/indra/llcommon/tests/bitpack_test.cpp
index afc0c18cd0..9bfd567068 100755
--- a/indra/llcommon/tests/bitpack_test.cpp
+++ b/indra/llcommon/tests/bitpack_test.cpp
@@ -28,7 +28,7 @@
#include "linden_common.h"
-#include "../bitpack.h"
+#include "../llbitpack.h"
#include "../test/lltut.h"
diff --git a/indra/llcommon/tests/commonmisc_test.cpp b/indra/llcommon/tests/commonmisc_test.cpp
index b115c153c1..4b3e07fa75 100755
--- a/indra/llcommon/tests/commonmisc_test.cpp
+++ b/indra/llcommon/tests/commonmisc_test.cpp
@@ -339,7 +339,7 @@ namespace tut
/*
if(actual != expected)
{
- llwarns << "iteration " << i << llendl;
+ LL_WARNS() << "iteration " << i << LL_ENDL;
std::ostringstream e_str;
std::string::iterator iter = expected.begin();
std::string::iterator end = expected.end();
@@ -349,8 +349,8 @@ namespace tut
}
e_str << std::endl;
llsd_serialize_string(e_str, expected);
- llwarns << "expected size: " << expected.size() << llendl;
- llwarns << "expected: " << e_str.str() << llendl;
+ LL_WARNS() << "expected size: " << expected.size() << LL_ENDL;
+ LL_WARNS() << "expected: " << e_str.str() << LL_ENDL;
std::ostringstream a_str;
iter = actual.begin();
@@ -361,8 +361,8 @@ namespace tut
}
a_str << std::endl;
llsd_serialize_string(a_str, actual);
- llwarns << "actual size: " << actual.size() << llendl;
- llwarns << "actual: " << a_str.str() << llendl;
+ LL_WARNS() << "actual size: " << actual.size() << LL_ENDL;
+ LL_WARNS() << "actual: " << a_str.str() << LL_ENDL;
}
*/
ensure_equals("string value", actual, expected);
diff --git a/indra/llcommon/tests/lldeadmantimer_test.cpp b/indra/llcommon/tests/lldeadmantimer_test.cpp
index 7fd2dde6e0..23167762c3 100644
--- a/indra/llcommon/tests/lldeadmantimer_test.cpp
+++ b/indra/llcommon/tests/lldeadmantimer_test.cpp
@@ -37,12 +37,12 @@
static LLDeadmanTimer::time_type float_time_to_u64(F64 delta)
{
- return LLDeadmanTimer::time_type(delta * gClockFrequency);
+ return LLDeadmanTimer::time_type(delta * get_timer_info().mClockFrequency);
}
static F64 u64_time_to_float(LLDeadmanTimer::time_type delta)
{
- return delta * gClockFrequencyInv;
+ return delta * get_timer_info().mClockFrequencyInv;
}
@@ -54,7 +54,7 @@ struct deadmantimer_test
deadmantimer_test()
{
// LLTimer internals updating
- update_clock_frequencies();
+ get_timer_info().update();
}
};
diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp
index 279a90e51b..b28c5ba4b3 100755
--- a/indra/llcommon/tests/llerror_test.cpp
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -40,7 +40,7 @@ namespace
{
void test_that_error_h_includes_enough_things_to_compile_a_message()
{
- llinfos << "!" << llendl;
+ LL_INFOS() << "!" << LL_ENDL;
}
}
@@ -55,7 +55,7 @@ namespace tut
class TestRecorder : public LLError::Recorder
{
public:
- TestRecorder() : mWantsTime(false) { }
+ TestRecorder() { mWantsTime = false; }
~TestRecorder() { LLError::removeRecorder(this); }
void recordMessage(LLError::ELevel level,
@@ -68,7 +68,6 @@ namespace tut
void clearMessages() { mMessages.clear(); }
void setWantsTime(bool t) { mWantsTime = t; }
- bool wantsTime() { return mWantsTime; }
std::string message(int n)
{
@@ -82,8 +81,6 @@ namespace tut
private:
typedef std::vector<std::string> MessageVector;
MessageVector mMessages;
-
- bool mWantsTime;
};
struct ErrorTestData
@@ -144,8 +141,8 @@ namespace tut
void ErrorTestObject::test<1>()
// basic test of output
{
- llinfos << "test" << llendl;
- llinfos << "bob" << llendl;
+ LL_INFOS() << "test" << LL_ENDL;
+ LL_INFOS() << "bob" << LL_ENDL;
ensure_message_contains(0, "test");
ensure_message_contains(1, "bob");
@@ -156,11 +153,11 @@ namespace
{
void writeSome()
{
- lldebugs << "one" << llendl;
- llinfos << "two" << llendl;
- llwarns << "three" << llendl;
- llerrs << "four" << llendl;
- // fatal messages write out and addtional "error" message
+ LL_DEBUGS() << "one" << LL_ENDL;
+ LL_INFOS() << "two" << LL_ENDL;
+ LL_WARNS() << "three" << LL_ENDL;
+ // fatal messages write out an additional "error" message
+ LL_ERRS() << "four" << LL_ENDL;
}
};
@@ -259,19 +256,20 @@ namespace
std::string writeReturningLocation()
{
- llinfos << "apple" << llendl; int this_line = __LINE__;
+ LL_INFOS() << "apple" << LL_ENDL; int this_line = __LINE__;
return locationString(this_line);
}
- std::string writeReturningLocationAndFunction()
+ void writeReturningLocationAndFunction(std::string& location, std::string& function)
{
- llinfos << "apple" << llendl; int this_line = __LINE__;
- return locationString(this_line) + __FUNCTION__;
+ LL_INFOS() << "apple" << LL_ENDL; int this_line = __LINE__;
+ location = locationString(this_line);
+ function = __FUNCTION__;
}
std::string errorReturningLocation()
{
- llerrs << "die" << llendl; int this_line = __LINE__;
+ LL_ERRS() << "die" << LL_ENDL; int this_line = __LINE__;
return locationString(this_line);
}
}
@@ -306,13 +304,13 @@ namespace tut
std::string logFromGlobal(bool id)
{
- llinfos << (id ? "logFromGlobal: " : "") << "hi" << llendl;
+ LL_INFOS() << (id ? "logFromGlobal: " : "") << "hi" << LL_ENDL;
return "logFromGlobal";
}
static std::string logFromStatic(bool id)
{
- llinfos << (id ? "logFromStatic: " : "") << "hi" << llendl;
+ LL_INFOS() << (id ? "logFromStatic: " : "") << "hi" << LL_ENDL;
return "logFromStatic";
}
@@ -320,7 +318,7 @@ namespace
{
std::string logFromAnon(bool id)
{
- llinfos << (id ? "logFromAnon: " : "") << "hi" << llendl;
+ LL_INFOS() << (id ? "logFromAnon: " : "") << "hi" << LL_ENDL;
return "logFromAnon";
}
}
@@ -328,7 +326,7 @@ namespace
namespace Foo {
std::string logFromNamespace(bool id)
{
- llinfos << (id ? "Foo::logFromNamespace: " : "") << "hi" << llendl;
+ LL_INFOS() << (id ? "Foo::logFromNamespace: " : "") << "hi" << LL_ENDL;
//return "Foo::logFromNamespace";
// there is no standard way to get the namespace name, hence
// we won't be testing for it
@@ -342,12 +340,12 @@ namespace
public:
std::string logFromMember(bool id)
{
- llinfos << (id ? "ClassWithNoLogType::logFromMember: " : "") << "hi" << llendl;
+ LL_INFOS() << (id ? "ClassWithNoLogType::logFromMember: " : "") << "hi" << LL_ENDL;
return "ClassWithNoLogType::logFromMember";
}
static std::string logFromStatic(bool id)
{
- llinfos << (id ? "ClassWithNoLogType::logFromStatic: " : "") << "hi" << llendl;
+ LL_INFOS() << (id ? "ClassWithNoLogType::logFromStatic: " : "") << "hi" << LL_ENDL;
return "ClassWithNoLogType::logFromStatic";
}
};
@@ -357,12 +355,12 @@ namespace
public:
std::string logFromMember(bool id)
{
- llinfos << (id ? "ClassWithLogType::logFromMember: " : "") << "hi" << llendl;
+ LL_INFOS() << (id ? "ClassWithLogType::logFromMember: " : "") << "hi" << LL_ENDL;
return "ClassWithLogType::logFromMember";
}
static std::string logFromStatic(bool id)
{
- llinfos << (id ? "ClassWithLogType::logFromStatic: " : "") << "hi" << llendl;
+ LL_INFOS() << (id ? "ClassWithLogType::logFromStatic: " : "") << "hi" << LL_ENDL;
return "ClassWithLogType::logFromStatic";
}
};
@@ -434,19 +432,19 @@ namespace
{
std::string innerLogger()
{
- llinfos << "inside" << llendl;
+ LL_INFOS() << "inside" << LL_ENDL;
return "moo";
}
std::string outerLogger()
{
- llinfos << "outside(" << innerLogger() << ")" << llendl;
+ LL_INFOS() << "outside(" << innerLogger() << ")" << LL_ENDL;
return "bar";
}
void uberLogger()
{
- llinfos << "uber(" << outerLogger() << "," << innerLogger() << ")" << llendl;
+ LL_INFOS() << "uber(" << outerLogger() << "," << innerLogger() << ")" << LL_ENDL;
}
class LogWhileLogging
@@ -454,7 +452,7 @@ namespace
public:
void print(std::ostream& out) const
{
- llinfos << "logging" << llendl;
+ LL_INFOS() << "logging" << LL_ENDL;
out << "baz";
}
};
@@ -465,7 +463,7 @@ namespace
void metaLogger()
{
LogWhileLogging l;
- llinfos << "meta(" << l << ")" << llendl;
+ LL_INFOS() << "meta(" << l << ")" << LL_ENDL;
}
}
@@ -495,7 +493,7 @@ namespace tut
}
template<> template<>
- // special handling of llerrs calls
+ // special handling of LL_ERRS() calls
void ErrorTestObject::test<8>()
{
LLError::setPrintLocation(false);
@@ -518,7 +516,7 @@ namespace
void ufoSighting()
{
- llinfos << "ufo" << llendl;
+ LL_INFOS() << "ufo" << LL_ENDL;
}
}
@@ -548,11 +546,13 @@ namespace tut
LLError::setPrintLocation(true);
LLError::setTimeFunction(roswell);
mRecorder->setWantsTime(true);
- std::string locationAndFunction = writeReturningLocationAndFunction();
+ std::string location,
+ function;
+ writeReturningLocationAndFunction(location, function);
- ensure_equals("order is time type location function message",
+ ensure_equals("order is location time type function message",
mRecorder->message(0),
- roswell() + " INFO: " + locationAndFunction + ": apple");
+ location + roswell() + " INFO: " + function + ": apple");
}
template<> template<>
@@ -562,7 +562,7 @@ namespace tut
TestRecorder* altRecorder(new TestRecorder);
LLError::addRecorder(altRecorder);
- llinfos << "boo" << llendl;
+ LL_INFOS() << "boo" << LL_ENDL;
ensure_message_contains(0, "boo");
ensure_equals("alt recorder count", altRecorder->countMessages(), 1);
@@ -574,7 +574,7 @@ namespace tut
anotherRecorder->setWantsTime(true);
LLError::addRecorder(anotherRecorder);
- llinfos << "baz" << llendl;
+ LL_INFOS() << "baz" << LL_ENDL;
std::string when = roswell();
@@ -590,10 +590,10 @@ class TestAlpha
{
LOG_CLASS(TestAlpha);
public:
- static void doDebug() { lldebugs << "add dice" << llendl; }
- static void doInfo() { llinfos << "any idea" << llendl; }
- static void doWarn() { llwarns << "aim west" << llendl; }
- static void doError() { llerrs << "ate eels" << llendl; }
+ static void doDebug() { LL_DEBUGS() << "add dice" << LL_ENDL; }
+ static void doInfo() { LL_INFOS() << "any idea" << LL_ENDL; }
+ static void doWarn() { LL_WARNS() << "aim west" << LL_ENDL; }
+ static void doError() { LL_ERRS() << "ate eels" << LL_ENDL; }
static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
};
@@ -601,10 +601,10 @@ class TestBeta
{
LOG_CLASS(TestBeta);
public:
- static void doDebug() { lldebugs << "bed down" << llendl; }
- static void doInfo() { llinfos << "buy iron" << llendl; }
- static void doWarn() { llwarns << "bad word" << llendl; }
- static void doError() { llerrs << "big easy" << llendl; }
+ static void doDebug() { LL_DEBUGS() << "bed down" << LL_ENDL; }
+ static void doInfo() { LL_INFOS() << "buy iron" << LL_ENDL; }
+ static void doWarn() { LL_WARNS() << "bad word" << LL_ENDL; }
+ static void doError() { LL_ERRS() << "big easy" << LL_ENDL; }
static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
};
diff --git a/indra/llcommon/tests/lleventcoro_test.cpp b/indra/llcommon/tests/lleventcoro_test.cpp
index 5ebde1a31d..cb5e15eff2 100755
--- a/indra/llcommon/tests/lleventcoro_test.cpp
+++ b/indra/llcommon/tests/lleventcoro_test.cpp
@@ -346,13 +346,13 @@ namespace tut
LLCoroEventPumps waiter;
replyName = waiter.getName0();
errorName = waiter.getName1();
- WrapLL_ERRS capture;
+ WrapLLErrs capture;
try
{
result = waiter.waitWithLog(self);
debug("no exception");
}
- catch (const WrapLL_ERRS::FatalException& e)
+ catch (const WrapLLErrs::FatalException& e)
{
debug(STRINGIZE("exception " << e.what()));
threw = e.what();
@@ -436,7 +436,7 @@ namespace tut
BEGIN
{
LLCoroEventPumps waiter;
- WrapLL_ERRS capture;
+ WrapLLErrs capture;
try
{
result = waiter.postAndWaitWithLog(self,
@@ -444,7 +444,7 @@ namespace tut
immediateAPI.getPump(), "reply", "error");
debug("no exception");
}
- catch (const WrapLL_ERRS::FatalException& e)
+ catch (const WrapLLErrs::FatalException& e)
{
debug(STRINGIZE("exception " << e.what()));
threw = e.what();
diff --git a/indra/llcommon/tests/lleventdispatcher_test.cpp b/indra/llcommon/tests/lleventdispatcher_test.cpp
index 263c9b171f..5a4df81bf1 100755
--- a/indra/llcommon/tests/lleventdispatcher_test.cpp
+++ b/indra/llcommon/tests/lleventdispatcher_test.cpp
@@ -312,7 +312,7 @@ namespace tut
{
struct lleventdispatcher_data
{
- WrapLL_ERRS redirect;
+ WrapLLErrs redirect;
Dispatcher work;
Vars v;
std::string name, desc;
diff --git a/indra/llcommon/tests/lleventfilter_test.cpp b/indra/llcommon/tests/lleventfilter_test.cpp
index ca05ef62a9..2cdfb52f2f 100755
--- a/indra/llcommon/tests/lleventfilter_test.cpp
+++ b/indra/llcommon/tests/lleventfilter_test.cpp
@@ -244,7 +244,7 @@ namespace tut
void filter_object::test<4>()
{
set_test_name("LLEventTimeout::errorAfter()");
- WrapLL_ERRS capture;
+ WrapLLErrs capture;
LLEventPump& driver(pumps.obtain("driver"));
TestEventTimeout filter(driver);
listener0.reset(0);
@@ -274,7 +274,7 @@ namespace tut
{
mainloop.post(17);
}
- catch (const WrapLL_ERRS::FatalException& e)
+ catch (const WrapLLErrs::FatalException& e)
{
threw = e.what();
}
diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp
index e769c3e22c..c7d4b8a06b 100755
--- a/indra/llcommon/tests/llinstancetracker_test.cpp
+++ b/indra/llcommon/tests/llinstancetracker_test.cpp
@@ -194,15 +194,15 @@ namespace tut
{
set_test_name("delete Keyed with outstanding instance_iter");
std::string what;
- Keyed* keyed = new Keyed("one");
+ Keyed* keyed = new Keyed("delete Keyed with outstanding instance_iter");
{
- WrapLL_ERRS wrapper;
+ WrapLLErrs wrapper;
Keyed::instance_iter i(Keyed::beginInstances());
try
{
delete keyed;
}
- catch (const WrapLL_ERRS::FatalException& e)
+ catch (const WrapLLErrs::FatalException& e)
{
what = e.what();
}
@@ -215,15 +215,15 @@ namespace tut
{
set_test_name("delete Keyed with outstanding key_iter");
std::string what;
- Keyed* keyed = new Keyed("one");
+ Keyed* keyed = new Keyed("delete Keyed with outstanding key_it");
{
- WrapLL_ERRS wrapper;
+ WrapLLErrs wrapper;
Keyed::key_iter i(Keyed::beginKeys());
try
{
delete keyed;
}
- catch (const WrapLL_ERRS::FatalException& e)
+ catch (const WrapLLErrs::FatalException& e)
{
what = e.what();
}
@@ -238,13 +238,13 @@ namespace tut
std::string what;
Unkeyed* unkeyed = new Unkeyed;
{
- WrapLL_ERRS wrapper;
+ WrapLLErrs wrapper;
Unkeyed::instance_iter i(Unkeyed::beginInstances());
try
{
delete unkeyed;
}
- catch (const WrapLL_ERRS::FatalException& e)
+ catch (const WrapLLErrs::FatalException& e)
{
what = e.what();
}
diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp
index 29060d4ef5..9ea822cb8d 100755
--- a/indra/llcommon/tests/llleap_test.cpp
+++ b/indra/llcommon/tests/llleap_test.cpp
@@ -22,7 +22,6 @@
// other Linden headers
#include "../test/lltut.h"
#include "../test/namedtempfile.h"
-#include "../test/manageapr.h"
#include "../test/catch_and_store_what_in.h"
#include "wrapllerrs.h"
#include "llevents.h"
@@ -33,8 +32,6 @@
using boost::assign::list_of;
-static ManageAPR manager;
-
StringVec sv(const StringVec& listof) { return listof; }
#if defined(LL_WINDOWS)
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index 3e68ef068e..e4e766d51b 100755
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -29,7 +29,6 @@
//#include <boost/lambda/bind.hpp>
// other Linden headers
#include "../test/lltut.h"
-#include "../test/manageapr.h"
#include "../test/namedtempfile.h"
#include "../test/catch_and_store_what_in.h"
#include "stringize.h"
@@ -46,9 +45,12 @@
#endif
//namespace lambda = boost::lambda;
-
-// static instance of this manages APR init/cleanup
-static ManageAPR manager;
+ std::string apr_strerror_helper(apr_status_t rv)
+{
+ char errbuf[256];
+ apr_strerror(rv, errbuf, sizeof(errbuf));
+ return errbuf;
+}
/*****************************************************************************
* Helpers
@@ -60,7 +62,8 @@ static ManageAPR manager;
#define aprchk(expr) aprchk_(#expr, (expr))
static void aprchk_(const char* call, apr_status_t rv, apr_status_t expected=APR_SUCCESS)
{
- tut::ensure_equals(STRINGIZE(call << " => " << rv << ": " << manager.strerror(rv)),
+ tut::ensure_equals(STRINGIZE(call << " => " << rv << ": " << apr_strerror_helper
+ (rv)),
rv, expected);
}
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index 4d436e8897..b5893135ea 100755
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -56,12 +56,9 @@ namespace lambda = boost::lambda;
#include "../llformat.h"
#include "../test/lltut.h"
-#include "../test/manageapr.h"
#include "../test/namedtempfile.h"
#include "stringize.h"
-static ManageAPR manager;
-
std::vector<U8> string_to_vector(const std::string& str)
{
return std::vector<U8>(str.begin(), str.end());
@@ -268,7 +265,7 @@ namespace tut
{
std::stringstream stream;
mFormatter->format(v, stream);
- //llinfos << "checkRoundTrip: length " << stream.str().length() << llendl;
+ //LL_INFOS() << "checkRoundTrip: length " << stream.str().length() << LL_ENDL;
LLSD w;
mParser->reset(); // reset() call is needed since test code re-uses mParser
mParser->parse(stream, w, stream.str().size());
@@ -1723,5 +1720,6 @@ namespace tut
"This string\n"
"has several\n"
"lines.");
+
}
}
diff --git a/indra/llcommon/tests/lltrace_test.cpp b/indra/llcommon/tests/lltrace_test.cpp
new file mode 100644
index 0000000000..0a9d85ad00
--- /dev/null
+++ b/indra/llcommon/tests/lltrace_test.cpp
@@ -0,0 +1,142 @@
+/**
+ * @file llsingleton_test.cpp
+ * @date 2011-08-11
+ * @brief Unit test for the LLSingleton class
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "lltrace.h"
+#include "lltracethreadrecorder.h"
+#include "lltracerecording.h"
+#include "../test/lltut.h"
+
+namespace LLUnits
+{
+ // using powers of 2 to allow strict floating point equality
+ LL_DECLARE_BASE_UNIT(Ounces, "oz");
+ LL_DECLARE_DERIVED_UNIT(TallCup, "", Ounces, / 12);
+ LL_DECLARE_DERIVED_UNIT(GrandeCup, "", Ounces, / 16);
+ LL_DECLARE_DERIVED_UNIT(VentiCup, "", Ounces, / 20);
+
+ LL_DECLARE_BASE_UNIT(Grams, "g");
+ LL_DECLARE_DERIVED_UNIT(Milligrams, "mg", Grams, * 1000);
+}
+
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Ounces);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, TallCup);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, GrandeCup);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, VentiCup);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Grams);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Milligrams);
+
+
+namespace tut
+{
+ using namespace LLTrace;
+ struct trace
+ {
+ ThreadRecorder mRecorder;
+ };
+
+ typedef test_group<trace> trace_t;
+ typedef trace_t::object trace_object_t;
+ tut::trace_t tut_singleton("LLTrace");
+
+ static CountStatHandle<S32> sCupsOfCoffeeConsumed("coffeeconsumed", "Delicious cup of dark roast.");
+ static SampleStatHandle<F32Milligrams> sCaffeineLevelStat("caffeinelevel", "Coffee buzz quotient");
+ static EventStatHandle<S32Ounces> sOuncesPerCup("cupsize", "Large, huge, or ginormous");
+
+ static F32 sCaffeineLevel(0.f);
+ const F32Milligrams sCaffeinePerOz(18.f);
+
+ void drink_coffee(S32 num_cups, S32Ounces cup_size)
+ {
+ add(sCupsOfCoffeeConsumed, num_cups);
+ for (S32 i = 0; i < num_cups; i++)
+ {
+ record(sOuncesPerCup, cup_size);
+ }
+
+ sCaffeineLevel += F32Ounces(num_cups * cup_size).value() * sCaffeinePerOz.value();
+ sample(sCaffeineLevelStat, sCaffeineLevel);
+ }
+
+ // basic data collection
+ template<> template<>
+ void trace_object_t::test<1>()
+ {
+ sample(sCaffeineLevelStat, sCaffeineLevel);
+
+ Recording all_day;
+ Recording at_work;
+ Recording after_3pm;
+
+ all_day.start();
+ {
+ // warm up with one grande cup
+ drink_coffee(1, S32TallCup(1));
+
+ // go to work
+ at_work.start();
+ {
+ // drink 3 tall cups, 1 after 3 pm
+ drink_coffee(2, S32GrandeCup(1));
+ after_3pm.start();
+ drink_coffee(1, S32GrandeCup(1));
+ }
+ at_work.stop();
+ drink_coffee(1, S32VentiCup(1));
+ }
+ // don't need to stop recordings to get accurate values out of them
+ //after_3pm.stop();
+ //all_day.stop();
+
+ ensure("count stats are counted when recording is active",
+ at_work.getSum(sCupsOfCoffeeConsumed) == 3
+ && all_day.getSum(sCupsOfCoffeeConsumed) == 5
+ && after_3pm.getSum(sCupsOfCoffeeConsumed) == 2);
+ ensure("measurement sums are counted when recording is active",
+ at_work.getSum(sOuncesPerCup) == S32Ounces(48)
+ && all_day.getSum(sOuncesPerCup) == S32Ounces(80)
+ && after_3pm.getSum(sOuncesPerCup) == S32Ounces(36));
+ ensure("measurement min is specific to when recording is active",
+ at_work.getMin(sOuncesPerCup) == S32GrandeCup(1)
+ && all_day.getMin(sOuncesPerCup) == S32TallCup(1)
+ && after_3pm.getMin(sOuncesPerCup) == S32GrandeCup(1));
+ ensure("measurement max is specific to when recording is active",
+ at_work.getMax(sOuncesPerCup) == S32GrandeCup(1)
+ && all_day.getMax(sOuncesPerCup) == S32VentiCup(1)
+ && after_3pm.getMax(sOuncesPerCup) == S32VentiCup(1));
+ ensure("sample min is specific to when recording is active",
+ at_work.getMin(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1)).value()
+ && all_day.getMin(sCaffeineLevelStat) == F32Milligrams(0.f)
+ && after_3pm.getMin(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(2)).value());
+ ensure("sample max is specific to when recording is active",
+ at_work.getMax(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(3)).value()
+ && all_day.getMax(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(3) + (S32Ounces)S32VentiCup(1)).value()
+ && after_3pm.getMax(sCaffeineLevelStat) == sCaffeinePerOz * ((S32Ounces)S32TallCup(1) + (S32Ounces)S32GrandeCup(3) + (S32Ounces)S32VentiCup(1)).value());
+ }
+
+}
diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp
new file mode 100644
index 0000000000..57cf9810af
--- /dev/null
+++ b/indra/llcommon/tests/llunits_test.cpp
@@ -0,0 +1,388 @@
+/**
+ * @file llsingleton_test.cpp
+ * @date 2011-08-11
+ * @brief Unit test for the LLSingleton class
+ *
+ * $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2011, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llunits.h"
+#include "../test/lltut.h"
+
+namespace LLUnits
+{
+ // using powers of 2 to allow strict floating point equality
+ LL_DECLARE_BASE_UNIT(Quatloos, "Quat");
+ LL_DECLARE_DERIVED_UNIT(Latinum, "Lat", Quatloos, / 4);
+ LL_DECLARE_DERIVED_UNIT(Solari, "Sol", Latinum, * 16);
+}
+
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Quatloos);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Latinum);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Solari);
+
+namespace LLUnits
+{
+ LL_DECLARE_BASE_UNIT(Celcius, "c");
+ LL_DECLARE_DERIVED_UNIT(Fahrenheit, "f", Celcius, * 9 / 5 + 32);
+ LL_DECLARE_DERIVED_UNIT(Kelvin, "k", Celcius, + 273.15f);
+}
+
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Celcius);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Fahrenheit);
+LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kelvin);
+
+
+namespace tut
+{
+ using namespace LLUnits;
+ struct units
+ {
+ };
+
+ typedef test_group<units> units_t;
+ typedef units_t::object units_object_t;
+ tut::units_t tut_singleton("LLUnit");
+
+ // storage type conversions
+ template<> template<>
+ void units_object_t::test<1>()
+ {
+ LLUnit<F32, Quatloos> float_quatloos;
+ ensure("default float unit is zero", float_quatloos == F32Quatloos(0.f));
+
+ LLUnit<F32, Quatloos> float_initialize_quatloos(1);
+ ensure("non-zero initialized unit", float_initialize_quatloos == F32Quatloos(1.f));
+
+ LLUnit<S32, Quatloos> int_quatloos;
+ ensure("default int unit is zero", int_quatloos == S32Quatloos(0));
+
+ int_quatloos = S32Quatloos(42);
+ ensure("int assignment is preserved", int_quatloos == S32Quatloos(42));
+ float_quatloos = int_quatloos;
+ ensure("float assignment from int preserves value", float_quatloos == F32Quatloos(42.f));
+
+ int_quatloos = float_quatloos;
+ ensure("int assignment from float preserves value", int_quatloos == S32Quatloos(42));
+
+ float_quatloos = F32Quatloos(42.1f);
+ int_quatloos = float_quatloos;
+ ensure("int units truncate float units on assignment", int_quatloos == S32Quatloos(42));
+
+ LLUnit<U32, Quatloos> unsigned_int_quatloos(float_quatloos);
+ ensure("unsigned int can be initialized from signed int", unsigned_int_quatloos == S32Quatloos(42));
+
+ S32Solari int_solari(1);
+
+ float_quatloos = int_solari;
+ ensure("fractional units are preserved in conversion from integer to float type", float_quatloos == F32Quatloos(0.25f));
+
+ int_quatloos = S32Quatloos(1);
+ F32Solari float_solari = int_quatloos;
+ ensure("can convert with fractional intermediates from integer to float type", float_solari == F32Solari(4.f));
+ }
+
+ // conversions to/from base unit
+ template<> template<>
+ void units_object_t::test<2>()
+ {
+ LLUnit<F32, Quatloos> quatloos(1.f);
+ LLUnit<F32, Latinum> latinum_bars(quatloos);
+ ensure("conversion between units is automatic via initialization", latinum_bars == F32Latinum(1.f / 4.f));
+
+ latinum_bars = S32Latinum(256);
+ quatloos = latinum_bars;
+ ensure("conversion between units is automatic via assignment, and bidirectional", quatloos == S32Quatloos(1024));
+
+ LLUnit<S32, Quatloos> single_quatloo(1);
+ LLUnit<F32, Latinum> quarter_latinum = single_quatloo;
+ ensure("division of integer unit preserves fractional values when converted to float unit", quarter_latinum == F32Latinum(0.25f));
+ }
+
+ // conversions across non-base units
+ template<> template<>
+ void units_object_t::test<3>()
+ {
+ LLUnit<F32, Quatloos> quatloos(1024);
+ LLUnit<F32, Solari> solari(quatloos);
+ ensure("conversions can work between indirectly related units: Quatloos -> Latinum -> Solari", solari == S32Solari(4096));
+
+ LLUnit<F32, Latinum> latinum_bars = solari;
+ ensure("Non base units can be converted between each other", latinum_bars == S32Latinum(256));
+ }
+
+ // math operations
+ template<> template<>
+ void units_object_t::test<4>()
+ {
+ // exercise math operations
+ LLUnit<F32, Quatloos> quatloos(1.f);
+ quatloos *= 4.f;
+ ensure(quatloos == S32Quatloos(4));
+ quatloos = quatloos * 2;
+ ensure(quatloos == S32Quatloos(8));
+ quatloos = 2.f * quatloos;
+ ensure(quatloos == S32Quatloos(16));
+
+ quatloos += F32Quatloos(4.f);
+ ensure(quatloos == S32Quatloos(20));
+ quatloos += S32Quatloos(4);
+ ensure(quatloos == S32Quatloos(24));
+ quatloos = quatloos + S32Quatloos(4);
+ ensure(quatloos == S32Quatloos(28));
+ quatloos = S32Quatloos(4) + quatloos;
+ ensure(quatloos == S32Quatloos(32));
+ quatloos += quatloos * 3;
+ ensure(quatloos == S32Quatloos(128));
+
+ quatloos -= quatloos / 4 * 3;
+ ensure(quatloos == S32Quatloos(32));
+ quatloos = quatloos - S32Quatloos(8);
+ ensure(quatloos == S32Quatloos(24));
+ quatloos -= S32Quatloos(4);
+ ensure(quatloos == S32Quatloos(20));
+ quatloos -= F32Quatloos(4.f);
+ ensure(quatloos == S32Quatloos(16));
+
+ quatloos /= 2.f;
+ ensure(quatloos == S32Quatloos(8));
+ quatloos = quatloos / 4;
+ ensure(quatloos == S32Quatloos(2));
+
+ F32 ratio = quatloos / LLUnit<F32, Quatloos>(2.f);
+ ensure(ratio == 1);
+ ratio = quatloos / LLUnit<F32, Solari>(8.f);
+ ensure(ratio == 1);
+
+ quatloos += LLUnit<F32, Solari>(8.f);
+ ensure(quatloos == S32Quatloos(4));
+ quatloos -= LLUnit<F32, Latinum>(1.f);
+ ensure(quatloos == S32Quatloos(0));
+ }
+
+ // comparison operators
+ template<> template<>
+ void units_object_t::test<5>()
+ {
+ LLUnit<S32, Quatloos> quatloos(1);
+ ensure("can perform less than comparison against same type", quatloos < S32Quatloos(2));
+ ensure("can perform less than comparison against different storage type", quatloos < F32Quatloos(2.f));
+ ensure("can perform less than comparison against different units", quatloos < S32Latinum(5));
+ ensure("can perform less than comparison against different storage type and units", quatloos < F32Latinum(5.f));
+
+ ensure("can perform greater than comparison against same type", quatloos > S32Quatloos(0));
+ ensure("can perform greater than comparison against different storage type", quatloos > F32Quatloos(0.f));
+ ensure("can perform greater than comparison against different units", quatloos > S32Latinum(0));
+ ensure("can perform greater than comparison against different storage type and units", quatloos > F32Latinum(0.f));
+
+ }
+
+ bool accept_explicit_quatloos(S32Quatloos q)
+ {
+ return true;
+ }
+
+ bool accept_implicit_quatloos(S32Quatloos q)
+ {
+ return true;
+ }
+
+ // signature compatibility
+ template<> template<>
+ void units_object_t::test<6>()
+ {
+ S32Quatloos quatloos(1);
+ ensure("can pass unit values as argument", accept_explicit_quatloos(S32Quatloos(1)));
+ ensure("can pass unit values as argument", accept_explicit_quatloos(quatloos));
+ }
+
+ // implicit units
+ template<> template<>
+ void units_object_t::test<7>()
+ {
+ LLUnit<F32, Quatloos> quatloos;
+ LLUnitImplicit<F32, Quatloos> quatloos_implicit = quatloos + S32Quatloos(1);
+ ensure("can initialize implicit unit from explicit", quatloos_implicit == 1);
+
+ quatloos = quatloos_implicit;
+ ensure("can assign implicit unit to explicit unit", quatloos == S32Quatloos(1));
+ quatloos += quatloos_implicit;
+ ensure("can perform math operation using mixture of implicit and explicit units", quatloos == S32Quatloos(2));
+
+ // math operations on implicits
+ quatloos_implicit = 1;
+ ensure(quatloos_implicit == 1);
+
+ quatloos_implicit += 2;
+ ensure(quatloos_implicit == 3);
+
+ quatloos_implicit *= 2;
+ ensure(quatloos_implicit == 6);
+
+ quatloos_implicit -= 1;
+ ensure(quatloos_implicit == 5);
+
+ quatloos_implicit /= 5;
+ ensure(quatloos_implicit == 1);
+
+ quatloos_implicit = quatloos_implicit + 3 + quatloos_implicit;
+ ensure(quatloos_implicit == 5);
+
+ quatloos_implicit = 10 - quatloos_implicit - 1;
+ ensure(quatloos_implicit == 4);
+
+ quatloos_implicit = 2 * quatloos_implicit * 2;
+ ensure(quatloos_implicit == 16);
+
+ F32 one_half = quatloos_implicit / (quatloos_implicit * 2);
+ ensure(one_half == 0.5f);
+
+ // implicit conversion to POD
+ F32 float_val = quatloos_implicit;
+ ensure("implicit units convert implicitly to regular values", float_val == 16);
+
+ S32 int_val = quatloos_implicit;
+ ensure("implicit units convert implicitly to regular values", int_val == 16);
+
+ // conversion of implicits
+ LLUnitImplicit<F32, Latinum> latinum_implicit(2);
+ ensure("implicit units of different types are comparable", latinum_implicit * 2 == quatloos_implicit);
+
+ quatloos_implicit += F32Quatloos(10);
+ ensure("can add-assign explicit units", quatloos_implicit == 26);
+
+ quatloos_implicit -= F32Quatloos(10);
+ ensure("can subtract-assign explicit units", quatloos_implicit == 16);
+
+ // comparisons
+ ensure("can compare greater than implicit unit", quatloos_implicit > F32QuatloosImplicit(0.f));
+ ensure("can compare greater than non-implicit unit", quatloos_implicit > F32Quatloos(0.f));
+ ensure("can compare greater than or equal to implicit unit", quatloos_implicit >= F32QuatloosImplicit(0.f));
+ ensure("can compare greater than or equal to non-implicit unit", quatloos_implicit >= F32Quatloos(0.f));
+ ensure("can compare less than implicit unit", quatloos_implicit < F32QuatloosImplicit(20.f));
+ ensure("can compare less than non-implicit unit", quatloos_implicit < F32Quatloos(20.f));
+ ensure("can compare less than or equal to implicit unit", quatloos_implicit <= F32QuatloosImplicit(20.f));
+ ensure("can compare less than or equal to non-implicit unit", quatloos_implicit <= F32Quatloos(20.f));
+ }
+
+ // precision tests
+ template<> template<>
+ void units_object_t::test<8>()
+ {
+ U32Bytes max_bytes(U32_MAX);
+ S32Megabytes mega_bytes = max_bytes;
+ ensure("max available precision is used when converting units", mega_bytes == (S32Megabytes)4095);
+
+ mega_bytes = (S32Megabytes)-5 + (U32Megabytes)1;
+ ensure("can mix signed and unsigned in units addition", mega_bytes == (S32Megabytes)-4);
+
+ mega_bytes = (U32Megabytes)5 + (S32Megabytes)-1;
+ ensure("can mix unsigned and signed in units addition", mega_bytes == (S32Megabytes)4);
+ }
+
+ // default units
+ template<> template<>
+ void units_object_t::test<9>()
+ {
+ U32Gigabytes GB(1);
+ U32Megabytes MB(GB);
+ U32Kilobytes KB(GB);
+ U32Bytes B(GB);
+
+ ensure("GB -> MB conversion", MB.value() == 1024);
+ ensure("GB -> KB conversion", KB.value() == 1024 * 1024);
+ ensure("GB -> B conversion", B.value() == 1024 * 1024 * 1024);
+
+ KB = U32Kilobytes(1);
+ U32Kilobits Kb(KB);
+ U32Bits b(KB);
+ ensure("KB -> Kb conversion", Kb.value() == 8);
+ ensure("KB -> b conversion", b.value() == 8 * 1024);
+
+ U32Days days(1);
+ U32Hours hours(days);
+ U32Minutes minutes(days);
+ U32Seconds seconds(days);
+ U32Milliseconds ms(days);
+
+ ensure("days -> hours conversion", hours.value() == 24);
+ ensure("days -> minutes conversion", minutes.value() == 24 * 60);
+ ensure("days -> seconds conversion", seconds.value() == 24 * 60 * 60);
+ ensure("days -> ms conversion", ms.value() == 24 * 60 * 60 * 1000);
+
+ U32Kilometers km(1);
+ U32Meters m(km);
+ U32Centimeters cm(km);
+ U32Millimeters mm(km);
+
+ ensure("km -> m conversion", m.value() == 1000);
+ ensure("km -> cm conversion", cm.value() == 1000 * 100);
+ ensure("km -> mm conversion", mm.value() == 1000 * 1000);
+
+ U32Gigahertz GHz(1);
+ U32Megahertz MHz(GHz);
+ U32Kilohertz KHz(GHz);
+ U32Hertz Hz(GHz);
+
+ ensure("GHz -> MHz conversion", MHz.value() == 1000);
+ ensure("GHz -> KHz conversion", KHz.value() == 1000 * 1000);
+ ensure("GHz -> Hz conversion", Hz.value() == 1000 * 1000 * 1000);
+
+ F32Radians rad(6.2831853071795f);
+ S32Degrees deg(rad);
+ ensure("radians -> degrees conversion", deg.value() == 360);
+
+ F32Percent percent(50);
+ F32Ratio ratio(percent);
+ ensure("percent -> ratio conversion", ratio.value() == 0.5f);
+
+ U32Kilotriangles ktris(1);
+ U32Triangles tris(ktris);
+ ensure("kilotriangles -> triangles conversion", tris.value() == 1000);
+ }
+
+ bool value_near(F32 value, F32 target, F32 threshold)
+ {
+ return fabsf(value - target) < threshold;
+ }
+
+ // linear transforms
+ template<> template<>
+ void units_object_t::test<10>()
+ {
+ F32Celcius float_celcius(100);
+ F32Fahrenheit float_fahrenheit(float_celcius);
+ ensure("floating point celcius -> fahrenheit conversion using linear transform", value_near(float_fahrenheit.value(), 212, 0.1f) );
+
+ float_celcius = float_fahrenheit;
+ ensure("floating point fahrenheit -> celcius conversion using linear transform (round trip)", value_near(float_celcius.value(), 100.f, 0.1f) );
+
+ S32Celcius int_celcius(100);
+ S32Fahrenheit int_fahrenheit(int_celcius);
+ ensure("integer celcius -> fahrenheit conversion using linear transform", int_fahrenheit.value() == 212);
+
+ int_celcius = int_fahrenheit;
+ ensure("integer fahrenheit -> celcius conversion using linear transform (round trip)", int_celcius.value() == 100);
+ }
+}
diff --git a/indra/llcommon/tests/reflection_test.cpp b/indra/llcommon/tests/reflection_test.cpp
deleted file mode 100755
index 8980ebb1f1..0000000000
--- a/indra/llcommon/tests/reflection_test.cpp
+++ /dev/null
@@ -1,220 +0,0 @@
-/**
- * @file reflection_test.cpp
- * @date May 2006
- * @brief Reflection unit tests.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "../linden_common.h"
-#include "../reflective.h"
-#include "../metaclasst.h"
-#include "../metapropertyt.h"
-#include "../stdtypes.h"
-
-#include "../test/lltut.h"
-
-namespace tut
-{
- class TestAggregatedData : public LLReflective
- {
- public:
- TestAggregatedData() {;}
- virtual const LLMetaClass& getMetaClass() const;
-
- private:
- };
-
- class TestReflectionData : public LLReflective
- {
- public:
- TestReflectionData() : mInt(42), mString("foo"), mNullPtr(NULL), mPtr(new TestAggregatedData()), mRef(*(new TestAggregatedData)) {;}
- virtual ~TestReflectionData() {delete mPtr;}
- virtual const LLMetaClass& getMetaClass() const;
-
- static U32 getPropertyCount() {return 5;}
-
- private:
-
- friend class LLMetaClassT<TestReflectionData>;
- S32 mInt;
- std::string mString;
- TestAggregatedData* mNullPtr;
- TestAggregatedData* mPtr;
- TestAggregatedData mObj;
- TestAggregatedData& mRef;
- };
-}
-
-template <>
-void LLMetaClassT<tut::TestReflectionData>::reflectProperties(LLMetaClass& meta_class)
-{
- reflectProperty(meta_class, "mInt", &tut::TestReflectionData::mInt);
- reflectProperty(meta_class, "mString", &tut::TestReflectionData::mString);
- reflectPtrProperty(meta_class, "mNullPtr", &tut::TestReflectionData::mNullPtr);
- reflectPtrProperty(meta_class, "mPtr", &tut::TestReflectionData::mPtr);
- reflectProperty(meta_class, "mObj", &tut::TestReflectionData::mObj);
- //reflectProperty(meta_class, "mRef", &tut::TestReflectionData::mRef); // AARGH!
-}
-
-namespace tut
-{
- // virtual
- const LLMetaClass& TestReflectionData::getMetaClass() const
- {
- return LLMetaClassT<TestReflectionData>::instance();
- }
-
- const LLMetaClass& TestAggregatedData::getMetaClass() const
- {
- return LLMetaClassT<TestAggregatedData>::instance();
- }
-}
-
-namespace tut
-{
- typedef tut::test_group<TestReflectionData> TestReflectionGroup;
- typedef TestReflectionGroup::object TestReflectionObject;
- TestReflectionGroup gTestReflectionGroup("reflection");
-
- template<> template<>
- void TestReflectionObject::test<1>()
- {
- // Check properties can be found.
- const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
- const LLMetaProperty* null = NULL;
- ensure_not_equals(meta_class.findProperty("mInt"), null);
- ensure_not_equals(meta_class.findProperty("mString"), null);
- }
-
- template<> template<>
- void TestReflectionObject::test<2>()
- {
- // Check non-existent property cannot be found.
- const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
- const LLMetaProperty* null = NULL;
- ensure_equals(meta_class.findProperty("foo"), null);
- }
-
- template<> template<>
- void TestReflectionObject::test<3>()
- {
- // Check integer property has correct value.
- const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
- ensure_equals(meta_class.findProperty("mInt")->getLLSD(this).asInteger(), 42);
- }
-
- template<> template<>
- void TestReflectionObject::test<4>()
- {
- // Check string property has correct value.
- const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
- ensure_equals(meta_class.findProperty("mString")->getLLSD(this).asString(), std::string("foo"));
- }
-
- template<> template<>
- void TestReflectionObject::test<5>()
- {
- // Check NULL reference property has correct value.
- const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
- const LLReflective* null = NULL;
- ensure_equals(meta_class.findProperty("mNullPtr")->get(this), null);
- }
-
- template<> template<>
- void TestReflectionObject::test<6>()
- {
- // Check reference property has correct value.
- const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
- const LLReflective* null = NULL;
- const LLReflective* ref = meta_class.findProperty("mPtr")->get(this);
- ensure_not_equals(ref, null);
- }
-
- template<> template<>
- void TestReflectionObject::test<7>()
- {
- // Check reflective property has correct value.
- const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
- const LLReflective* null = NULL;
- const LLReflective* ref = meta_class.findProperty("mObj")->get(this);
- ensure_not_equals(ref, null);
- }
-
- template<> template<>
- void TestReflectionObject::test<8>()
- {
- // Check property count.
- const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
- ensure_equals(meta_class.getPropertyCount(), TestReflectionData::getPropertyCount());
- }
-
- template<> template<>
- void TestReflectionObject::test<9>()
- {
- // Check property iteration.
- const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
- U32 count = 0;
- LLMetaClass::PropertyIterator iter;
- for(iter = meta_class.beginProperties(); iter != meta_class.endProperties(); ++iter)
- {
- ++count;
- }
- ensure_equals(count, TestReflectionData::getPropertyCount());
- }
-
- template<> template<>
- void TestReflectionObject::test<10>()
- {
- // Check meta classes of different types do not compare equal.
- const LLMetaClass* reflection_data_meta_class = &(LLMetaClassT<TestReflectionData>::instance());
- const LLMetaClass* aggregated_data_meta_class = &(LLMetaClassT<TestAggregatedData>::instance());
- ensure_not_equals(reflection_data_meta_class, aggregated_data_meta_class);
- }
-
- template<> template<>
- void TestReflectionObject::test<11>()
- {
- // Check class cast checks.
- const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance();
- TestAggregatedData* aggregated_data = new TestAggregatedData();
- LLMetaClass::PropertyIterator iter;
- U32 exception_count = 0;
- for(iter = meta_class.beginProperties(); iter != meta_class.endProperties(); ++iter)
- {
- try
- {
- const LLMetaProperty* property = (*iter).second;
- const LLReflective* reflective = property->get(aggregated_data); // Wrong reflective type, should throw exception.
-
- // useless op to get rid of compiler warning.
- reflective = reflective;
- }
- catch(...)
- {
- ++exception_count;
- }
- }
- ensure_equals(exception_count, getPropertyCount());
-
- }
-}
diff --git a/indra/llcommon/tests/stringize_test.cpp b/indra/llcommon/tests/stringize_test.cpp
index 3d34f23998..3e4ca548e5 100755
--- a/indra/llcommon/tests/stringize_test.cpp
+++ b/indra/llcommon/tests/stringize_test.cpp
@@ -67,6 +67,8 @@ namespace tut
llsd["i"] = i;
llsd["d"] = d;
llsd["abc"] = abc;
+ def = L"def ghi";
+
}
char c;
@@ -76,6 +78,7 @@ namespace tut
float f;
double d;
std::string abc;
+ std::wstring def;
LLSD llsd;
};
typedef test_group<stringize_data> stringize_group;
@@ -92,6 +95,7 @@ namespace tut
ensure_equals(stringize(f), "3.14159");
ensure_equals(stringize(d), "3.14159");
ensure_equals(stringize(abc), "abc def");
+ ensure_equals(stringize(def), "def ghi"); //Will generate llwarns due to narrowing.
ensure_equals(stringize(llsd), "{'abc':'abc def','d':r3.14159,'i':i34}");
}
@@ -101,4 +105,20 @@ namespace tut
ensure_equals(STRINGIZE("c is " << c), "c is c");
ensure_equals(STRINGIZE(std::setprecision(4) << d), "3.142");
}
+
+ template<> template<>
+ void stringize_object::test<3>()
+ {
+ //Tests rely on validity of wstring_to_utf8str()
+ ensure_equals(wstring_to_utf8str(wstringize(c)), wstring_to_utf8str(L"c"));
+ ensure_equals(wstring_to_utf8str(wstringize(s)), wstring_to_utf8str(L"17"));
+ ensure_equals(wstring_to_utf8str(wstringize(i)), wstring_to_utf8str(L"34"));
+ ensure_equals(wstring_to_utf8str(wstringize(l)), wstring_to_utf8str(L"68"));
+ ensure_equals(wstring_to_utf8str(wstringize(f)), wstring_to_utf8str(L"3.14159"));
+ ensure_equals(wstring_to_utf8str(wstringize(d)), wstring_to_utf8str(L"3.14159"));
+ ensure_equals(wstring_to_utf8str(wstringize(abc)), wstring_to_utf8str(L"abc def"));
+ ensure_equals(wstring_to_utf8str(wstringize(abc)), wstring_to_utf8str(wstringize(abc.c_str())));
+ ensure_equals(wstring_to_utf8str(wstringize(def)), wstring_to_utf8str(L"def ghi"));
+ // ensure_equals(wstring_to_utf8str(wstringize(llsd)), wstring_to_utf8str(L"{'abc':'abc def','d':r3.14159,'i':i34}"));
+ }
} // namespace tut
diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h
index a4d3a4e026..3137bd8fea 100755
--- a/indra/llcommon/tests/wrapllerrs.h
+++ b/indra/llcommon/tests/wrapllerrs.h
@@ -46,9 +46,9 @@
// replicate, but better to reuse
extern void wouldHaveCrashed(const std::string& message);
-struct WrapLL_ERRS
+struct WrapLLErrs
{
- WrapLL_ERRS():
+ WrapLLErrs():
// Resetting Settings discards the default Recorder that writes to
// stderr. Otherwise, expected llerrs (LL_ERRS) messages clutter the
// console output of successful tests, potentially confusing things.
@@ -57,10 +57,10 @@ struct WrapLL_ERRS
mPriorFatal(LLError::getFatalFunction())
{
// Make LL_ERRS call our own operator() method
- LLError::setFatalFunction(boost::bind(&WrapLL_ERRS::operator(), this, _1));
+ LLError::setFatalFunction(boost::bind(&WrapLLErrs::operator(), this, _1));
}
- ~WrapLL_ERRS()
+ ~WrapLLErrs()
{
LLError::setFatalFunction(mPriorFatal);
LLError::restoreSettings(mPriorErrorSettings);
diff --git a/indra/llcommon/timing.h b/indra/llcommon/timing.h
deleted file mode 100755
index c408d4c446..0000000000
--- a/indra/llcommon/timing.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/**
- * @file timing.h
- * @brief Cross-platform routines for doing timing.
- *
- * $LicenseInfo:firstyear=2000&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_TIMING_H
-#define LL_TIMING_H
-
-
-#if LL_LINUX || LL_DARWIN || LL_SOLARIS
-#include <sys/time.h>
-#endif
-
-
-const F32 SEC_TO_MICROSEC = 1000000.f;
-const U64 SEC_TO_MICROSEC_U64 = 1000000;
-const U32 SEC_PER_DAY = 86400;
-
-// functionality has been moved lltimer.{cpp,h}. This file will be deprecated in the future.
-
-#endif
diff --git a/indra/llcommon/u64.cpp b/indra/llcommon/u64.cpp
index eea16c5036..02c2c15d26 100755
--- a/indra/llcommon/u64.cpp
+++ b/indra/llcommon/u64.cpp
@@ -36,7 +36,7 @@ U64 str_to_U64(const std::string& str)
if (!aptr)
{
- llwarns << "str_to_U64: Bad string to U64 conversion attempt: format\n" << llendl;
+ LL_WARNS() << "str_to_U64: Bad string to U64 conversion attempt: format\n" << LL_ENDL;
}
else
{