From 819adb5eb4d7f982121f3dbd82750e05d26864d9 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Thu, 1 Nov 2012 00:26:44 -0700 Subject: SH-3405 FIX convert existing stats to lltrace system final removal of remaining LLStat code --- indra/llcommon/llinstancetracker.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/llcommon/llinstancetracker.h') diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 403df08990..3a1187a4c1 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -77,8 +77,8 @@ protected: /// This mix-in class adds support for tracking all instances of the specified class parameter T /// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup /// If KEY is not provided, then instances are stored in a simple set -/// @NOTE: see explicit specialization below for default KEY==T* case -template +/// @NOTE: see explicit specialization below for default KEY==void case +template class LLInstanceTracker : public LLInstanceTrackerBase { typedef LLInstanceTracker MyT; @@ -224,12 +224,12 @@ private: KEY mInstanceKey; }; -/// explicit specialization for default case where KEY is T* +/// explicit specialization for default case where KEY is void /// use a simple std::set template -class LLInstanceTracker : public LLInstanceTrackerBase +class LLInstanceTracker : public LLInstanceTrackerBase { - typedef LLInstanceTracker MyT; + typedef LLInstanceTracker MyT; typedef typename std::set InstanceSet; struct StaticData: public StaticBase { -- cgit v1.3 From 3fd640a6e3dea7a3551c239323d782fb082e1dbd Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Sun, 23 Dec 2012 12:27:25 -0800 Subject: SH-3468 WIP add memory tracking base class fixed crash on exit by making LLInstanceTracker iterators use atomic iterator nesting count for thread safety --- indra/llcommon/llapr.cpp | 1 + indra/llcommon/llapr.h | 137 +---------------- indra/llcommon/llinstancetracker.cpp | 18 +++ indra/llcommon/llinstancetracker.h | 27 ++-- indra/llcommon/llstl.h | 1 + indra/llcommon/llthreadlocalpointer.h | 164 +++++++++++++++++++++ indra/llcommon/lltrace.h | 1 + indra/llcommon/llworkerthread.h | 5 +- .../quicktime/media_plugin_quicktime.cpp | 21 +-- 9 files changed, 221 insertions(+), 154 deletions(-) create mode 100644 indra/llcommon/llthreadlocalpointer.h (limited to 'indra/llcommon/llinstancetracker.h') diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 6affdad61b..092c276936 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -29,6 +29,7 @@ #include "linden_common.h" #include "llapr.h" #include "apr_dso.h" +#include "llthreadlocalpointer.h" apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool. diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index 2faf4aad2d..b3c9bfd58c 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -42,7 +42,6 @@ #include "apr_atomic.h" #include "llstring.h" -#include "llinstancetracker.h" extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp; extern apr_thread_mutex_t* gCallStacksLogMutexp; @@ -170,14 +169,17 @@ public: LLAtomic32(Type x) {apr_atomic_set32(&mData, apr_uint32_t(x)); }; ~LLAtomic32() {}; - operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); } + operator const Type() { return get(); } Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); } void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); } void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); } Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++ - Type operator --(int) { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise) + Type operator ++() { apr_atomic_inc32(&mData); return get(); } // ++Type + Type operator --(int) { const Type result(get()); apr_atomic_dec32(&mData); return result; } // Type-- + Type operator --() { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise) private: + const Type get() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); } apr_uint32_t mData; }; @@ -262,134 +264,5 @@ public: //******************************************************************************************************************************* }; -class LLThreadLocalPointerBase : public LLInstanceTracker -{ -public: - LLThreadLocalPointerBase() - : mThreadKey(NULL) - { - if (sInitialized) - { - initStorage(); - } - } - - LLThreadLocalPointerBase( const LLThreadLocalPointerBase& other) - : mThreadKey(NULL) - { - if (sInitialized) - { - initStorage(); - } - } - - ~LLThreadLocalPointerBase() - { - destroyStorage(); - } - - static void initAllThreadLocalStorage(); - static void destroyAllThreadLocalStorage(); - -protected: - void set(void* value); - - LL_FORCE_INLINE void* get() - { - // llassert(sInitialized); - void* ptr; - apr_status_t result = - apr_threadkey_private_get(&ptr, mThreadKey); - if (result != APR_SUCCESS) - { - ll_apr_warn_status(result); - llerrs << "Failed to get thread local data" << llendl; - } - return ptr; - } - - LL_FORCE_INLINE const void* get() const - { - void* ptr; - apr_status_t result = - apr_threadkey_private_get(&ptr, mThreadKey); - if (result != APR_SUCCESS) - { - ll_apr_warn_status(result); - llerrs << "Failed to get thread local data" << llendl; - } - return ptr; - } - - void initStorage(); - void destroyStorage(); - -protected: - apr_threadkey_t* mThreadKey; - static bool sInitialized; -}; - -template -class LLThreadLocalPointer : public LLThreadLocalPointerBase -{ -public: - - LLThreadLocalPointer() - {} - - explicit LLThreadLocalPointer(T* value) - { - set(value); - } - - - LLThreadLocalPointer(const LLThreadLocalPointer& other) - : LLThreadLocalPointerBase(other) - { - set(other.get()); - } - - LL_FORCE_INLINE T* get() - { - return (T*)LLThreadLocalPointerBase::get(); - } - - const T* get() const - { - return (const T*)LLThreadLocalPointerBase::get(); - } - - T* operator -> () - { - return (T*)get(); - } - - const T* operator -> () const - { - return (T*)get(); - } - - T& operator*() - { - return *(T*)get(); - } - - const T& operator*() const - { - return *(T*)get(); - } - - LLThreadLocalPointer& operator = (T* value) - { - set((void*)value); - return *this; - } - - bool operator ==(T* other) - { - if (!sInitialized) return false; - return get() == other; - } -}; #endif // LL_LLAPR_H diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp index 5dc3ea5d7b..071a637cda 100644 --- a/indra/llcommon/llinstancetracker.cpp +++ b/indra/llcommon/llinstancetracker.cpp @@ -27,6 +27,8 @@ #include "linden_common.h" // associated header #include "llinstancetracker.h" +#include "llapr.h" + // STL headers // std headers // external library headers @@ -47,3 +49,19 @@ void * & LLInstanceTrackerBase::getInstances(std::type_info const & info) InstancesMap::mapped_type())) .first->second; } + +void LLInstanceTrackerBase::StaticBase::incrementDepth() +{ + apr_atomic_inc32(&sIterationNestDepth); +} + +void LLInstanceTrackerBase::StaticBase::decrementDepth() +{ + apr_atomic_dec32(&sIterationNestDepth); +} + +U32 LLInstanceTrackerBase::StaticBase::getDepth() +{ + apr_uint32_t data = apr_atomic_read32(&sIterationNestDepth); + return data; +} diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 3a1187a4c1..9dd6d4a7ed 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -70,7 +70,12 @@ protected: StaticBase(): sIterationNestDepth(0) {} - S32 sIterationNestDepth; + + void incrementDepth(); + void decrementDepth(); + U32 getDepth(); + private: + U32 sIterationNestDepth; }; }; @@ -99,12 +104,12 @@ public: instance_iter(const typename InstanceMap::iterator& it) : mIterator(it) { - ++getStatic().sIterationNestDepth; + getStatic().incrementDepth(); } ~instance_iter() { - --getStatic().sIterationNestDepth; + getStatic().decrementDepth(); } @@ -133,18 +138,18 @@ public: key_iter(typename InstanceMap::iterator it) : mIterator(it) { - ++getStatic().sIterationNestDepth; + getStatic().incrementDepth(); } key_iter(const key_iter& other) : mIterator(other.mIterator) { - ++getStatic().sIterationNestDepth; + getStatic().incrementDepth(); } ~key_iter() { - --getStatic().sIterationNestDepth; + getStatic().decrementDepth(); } @@ -203,7 +208,7 @@ protected: virtual ~LLInstanceTracker() { // it's unsafe to delete instances of this type while all instances are being iterated over. - llassert_always(getStatic().sIterationNestDepth == 0); + llassert_always(getStatic().getDepth() == 0); remove_(); } virtual void setKey(KEY key) { remove_(); add_(key); } @@ -262,18 +267,18 @@ public: instance_iter(const typename InstanceSet::iterator& it) : mIterator(it) { - ++getStatic().sIterationNestDepth; + getStatic().incrementDepth(); } instance_iter(const instance_iter& other) : mIterator(other.mIterator) { - ++getStatic().sIterationNestDepth; + getStatic().incrementDepth(); } ~instance_iter() { - --getStatic().sIterationNestDepth; + getStatic().decrementDepth(); } private: @@ -306,7 +311,7 @@ protected: virtual ~LLInstanceTracker() { // it's unsafe to delete instances of this type while all instances are being iterated over. - llassert_always(getStatic().sIterationNestDepth == 0); + llassert_always(getStatic().getDepth() == 0); getSet_().erase(static_cast(this)); } diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index d3941e1bc9..424138dad1 100644 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/indra/llcommon/llthreadlocalpointer.h b/indra/llcommon/llthreadlocalpointer.h new file mode 100644 index 0000000000..d40a8b5a27 --- /dev/null +++ b/indra/llcommon/llthreadlocalpointer.h @@ -0,0 +1,164 @@ +/** + * @file llthreadlocalpointer.h + * @author Richard + * @brief Pointer class that manages a distinct value per thread + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLTHREADLOCALPOINTER_H +#define LL_LLTHREADLOCALPOINTER_H + +#include "llinstancetracker.h" +#include "llapr.h" + +class LLThreadLocalPointerBase : public LLInstanceTracker +{ +public: + LLThreadLocalPointerBase() + : mThreadKey(NULL) + { + if (sInitialized) + { + initStorage(); + } + } + + LLThreadLocalPointerBase( const LLThreadLocalPointerBase& other) + : mThreadKey(NULL) + { + if (sInitialized) + { + initStorage(); + } + } + + ~LLThreadLocalPointerBase() + { + destroyStorage(); + } + + static void initAllThreadLocalStorage(); + static void destroyAllThreadLocalStorage(); + +protected: + void set(void* value); + + LL_FORCE_INLINE void* get() + { + // llassert(sInitialized); + void* ptr; + apr_status_t result = + apr_threadkey_private_get(&ptr, mThreadKey); + if (result != APR_SUCCESS) + { + ll_apr_warn_status(result); + llerrs << "Failed to get thread local data" << llendl; + } + return ptr; + } + + LL_FORCE_INLINE const void* get() const + { + void* ptr; + apr_status_t result = + apr_threadkey_private_get(&ptr, mThreadKey); + if (result != APR_SUCCESS) + { + ll_apr_warn_status(result); + llerrs << "Failed to get thread local data" << llendl; + } + return ptr; + } + + void initStorage(); + void destroyStorage(); + +protected: + apr_threadkey_t* mThreadKey; + static bool sInitialized; +}; + +template +class LLThreadLocalPointer : public LLThreadLocalPointerBase +{ +public: + + LLThreadLocalPointer() + {} + + explicit LLThreadLocalPointer(T* value) + { + set(value); + } + + + LLThreadLocalPointer(const LLThreadLocalPointer& other) + : LLThreadLocalPointerBase(other) + { + set(other.get()); + } + + LL_FORCE_INLINE T* get() + { + return (T*)LLThreadLocalPointerBase::get(); + } + + const T* get() const + { + return (const T*)LLThreadLocalPointerBase::get(); + } + + T* operator -> () + { + return (T*)get(); + } + + const T* operator -> () const + { + return (T*)get(); + } + + T& operator*() + { + return *(T*)get(); + } + + const T& operator*() const + { + return *(T*)get(); + } + + LLThreadLocalPointer& operator = (T* value) + { + set((void*)value); + return *this; + } + + bool operator ==(T* other) + { + if (!sInitialized) return false; + return get() == other; + } +}; + +#endif // LL_LLTHREADLOCALPOINTER_H diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index 4bb19f6070..05191cafaa 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -34,6 +34,7 @@ #include "llrefcount.h" #include "llunit.h" #include "llapr.h" +#include "llthreadlocalpointer.h" #include diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h index be46394d6e..09776816a8 100644 --- a/indra/llcommon/llworkerthread.h +++ b/indra/llcommon/llworkerthread.h @@ -26,10 +26,11 @@ #ifndef LL_LLWORKERTHREAD_H #define LL_LLWORKERTHREAD_H -#include -#include +#include #include +#include #include +#include #include "llqueuedthread.h" #include "llapr.h" diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp index 24328202cb..eb18a3776f 100644 --- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -28,18 +28,10 @@ #include "linden_common.h" -#include "llgl.h" - -#include "llplugininstance.h" -#include "llpluginmessage.h" -#include "llpluginmessageclasses.h" -#include "media_plugin_base.h" - -#if LL_QUICKTIME_ENABLED - #if defined(LL_DARWIN) #include #elif defined(LL_WINDOWS) + #include "llwin32headers.h" #include "MacTypes.h" #include "QTML.h" #include "Movies.h" @@ -48,6 +40,17 @@ #include "QTLoadLibraryUtils.h" #endif +#include "llgl.h" + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#if LL_QUICKTIME_ENABLED + + + // TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint //////////////////////////////////////////////////////////////////////////////// // -- cgit v1.3 From cc7d92147c4a4502ec2ac04f150e94a4ac18f79e Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Fri, 19 Apr 2013 20:09:00 -0700 Subject: SH-4080 WIP interesting: random crash on Mac removed unused dll support from llinstancetracker as it didn't appear to be thread safe --- indra/llcommon/llinstancetracker.cpp | 16 ---------------- indra/llcommon/llinstancetracker.h | 20 ++------------------ 2 files changed, 2 insertions(+), 34 deletions(-) (limited to 'indra/llcommon/llinstancetracker.h') diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp index 071a637cda..7ff8324fe3 100644 --- a/indra/llcommon/llinstancetracker.cpp +++ b/indra/llcommon/llinstancetracker.cpp @@ -34,22 +34,6 @@ // external library headers // other Linden headers -//static -void * & LLInstanceTrackerBase::getInstances(std::type_info const & info) -{ - typedef std::map InstancesMap; - static InstancesMap instances; - - // std::map::insert() is just what we want here. You attempt to insert a - // (key, value) pair. If the specified key doesn't yet exist, it inserts - // the pair and returns a std::pair of (iterator, true). If the specified - // key DOES exist, insert() simply returns (iterator, false). One lookup - // handles both cases. - return instances.insert(InstancesMap::value_type(info.name(), - InstancesMap::mapped_type())) - .first->second; -} - void LLInstanceTrackerBase::StaticBase::incrementDepth() { apr_atomic_inc32(&sIterationNestDepth); diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 9dd6d4a7ed..596bea548d 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -46,22 +46,6 @@ class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable { protected: - /// Get a process-unique void* pointer slot for the specified type_info - static void * & getInstances(std::type_info const & info); - - /// Find or create a STATICDATA instance for the specified TRACKED class. - /// STATICDATA must be default-constructible. - template - static STATICDATA& getStatic() - { - void *& instances = getInstances(typeid(TRACKED)); - if (! instances) - { - instances = new STATICDATA; - } - return *static_cast(instances); - } - /// It's not essential to derive your STATICDATA (for use with /// getStatic()) from StaticBase; it's just that both known /// implementations do. @@ -92,7 +76,7 @@ class LLInstanceTracker : public LLInstanceTrackerBase { InstanceMap sMap; }; - static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic(); } + static StaticData& getStatic() { static StaticData sData; return sData;} static InstanceMap& getMap_() { return getStatic().sMap; } public: @@ -240,7 +224,7 @@ class LLInstanceTracker : public LLInstanceTrackerBase { InstanceSet sSet; }; - static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic(); } + static StaticData& getStatic() { static StaticData sData; return sData; } static InstanceSet& getSet_() { return getStatic().sSet; } public: -- cgit v1.3 From 62c8844414b84ee9e8cc488f4e02cbaed5f67a14 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Sun, 21 Apr 2013 23:10:03 -0700 Subject: SH-3931 WIP Interesting: Add graphs to visualize scene load metrics added ExtendablePeriodicRecording and ability to append periodic recordings to each other --- indra/llcommon/llinstancetracker.h | 10 ++- indra/llcommon/lltracerecording.cpp | 136 ++++++++++++++++++++++++++++++++++++ indra/llcommon/lltracerecording.h | 28 +++++++- 3 files changed, 170 insertions(+), 4 deletions(-) (limited to 'indra/llcommon/llinstancetracker.h') diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 596bea548d..a79ddd088d 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -67,6 +67,7 @@ protected: /// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup /// If KEY is not provided, then instances are stored in a simple set /// @NOTE: see explicit specialization below for default KEY==void case +/// @NOTE: this class is not thread-safe unless used as read-only template class LLInstanceTracker : public LLInstanceTrackerBase { @@ -120,13 +121,13 @@ public: typedef boost::iterator_facade super_t; key_iter(typename InstanceMap::iterator it) - : mIterator(it) + : mIterator(it) { getStatic().incrementDepth(); } key_iter(const key_iter& other) - : mIterator(other.mIterator) + : mIterator(other.mIterator) { getStatic().incrementDepth(); } @@ -171,7 +172,10 @@ public: return instance_iter(getMap_().end()); } - static S32 instanceCount() { return getMap_().size(); } + static S32 instanceCount() + { + return getMap_().size(); + } static key_iter beginKeys() { diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index 21156b4d61..2917c217d7 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -396,6 +396,76 @@ void PeriodicRecording::nextPeriod() } } + +void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other ) +{ + if (other.mRecordingPeriods.size() < 2) return; + + EPlayState play_state = getPlayState(); + pause(); + + EPlayState other_play_state = other.getPlayState(); + other.pause(); + + if (mAutoResize) + { + // copy everything after current period of other recording to end of buffer + // this will only apply if other recording is using a fixed circular buffer + if (other.mCurPeriod < other.mRecordingPeriods.size() - 1) + { + std::copy( other.mRecordingPeriods.begin() + other.mCurPeriod + 1, + other.mRecordingPeriods.end(), + std::back_inserter(mRecordingPeriods)); + } + + // copy everything from beginning of other recording's buffer up to, but not including + // current period + std::copy( other.mRecordingPeriods.begin(), + other.mRecordingPeriods.begin() + other.mCurPeriod, + std::back_inserter(mRecordingPeriods)); + + mCurPeriod = mRecordingPeriods.size() - 1; + } + else + { + size_t num_to_copy = llmin( mRecordingPeriods.size(), other.mRecordingPeriods.size() ); + std::vector::iterator src_it = other.mRecordingPeriods.begin() + + ( (other.mCurPeriod + 1) // cur period + + (other.mRecordingPeriods.size() - num_to_copy) // minus room for copy + % other.mRecordingPeriods.size()); + std::vector::iterator dest_it = mRecordingPeriods.begin() + ((mCurPeriod + 1) % mRecordingPeriods.size()); + + for(S32 i = 0; i < num_to_copy; i++) + { + *dest_it = *src_it; + + if (++src_it == other.mRecordingPeriods.end()) + { + src_it = other.mRecordingPeriods.begin(); + } + + if (++dest_it == mRecordingPeriods.end()) + { + dest_it = mRecordingPeriods.begin(); + } + } + + mCurPeriod = (mCurPeriod + num_to_copy) % mRecordingPeriods.size(); + } + + // if copying from periodic recording that wasn't active advance our period to the next available one + // otherwise continue recording on top of the last period of data received from the other recording + if (other_play_state != STARTED) + { + nextPeriod(); + } + + setPlayState(play_state); + other.setPlayState(other_play_state); +} + + + void PeriodicRecording::start() { getCurRecording().start(); @@ -503,6 +573,72 @@ void ExtendableRecording::splitFrom(ExtendableRecording& other) mPotentialRecording.splitFrom(other.mPotentialRecording); } +/////////////////////////////////////////////////////////////////////// +// ExtendablePeriodicRecording +/////////////////////////////////////////////////////////////////////// + +void ExtendablePeriodicRecording::extend() +{ + // stop recording to get latest data + mPotentialRecording.stop(); + // push the data back to accepted recording + mAcceptedRecording.appendPeriodicRecording(mPotentialRecording); + // flush data, so we can start from scratch + mPotentialRecording.reset(); + // go back to play state we were in initially + mPotentialRecording.setPlayState(getPlayState()); +} + +void ExtendablePeriodicRecording::start() +{ + LLStopWatchControlsMixin::start(); + mPotentialRecording.start(); +} + +void ExtendablePeriodicRecording::stop() +{ + LLStopWatchControlsMixin::stop(); + mPotentialRecording.stop(); +} + +void ExtendablePeriodicRecording::pause() +{ + LLStopWatchControlsMixin::pause(); + mPotentialRecording.pause(); +} + +void ExtendablePeriodicRecording::resume() +{ + LLStopWatchControlsMixin::resume(); + mPotentialRecording.resume(); +} + +void ExtendablePeriodicRecording::restart() +{ + LLStopWatchControlsMixin::restart(); + mAcceptedRecording.reset(); + mPotentialRecording.restart(); +} + +void ExtendablePeriodicRecording::reset() +{ + LLStopWatchControlsMixin::reset(); + mAcceptedRecording.reset(); + mPotentialRecording.reset(); +} + +void ExtendablePeriodicRecording::splitTo(ExtendablePeriodicRecording& other) +{ + LLStopWatchControlsMixin::splitTo(other); + mPotentialRecording.splitTo(other.mPotentialRecording); +} + +void ExtendablePeriodicRecording::splitFrom(ExtendablePeriodicRecording& other) +{ + LLStopWatchControlsMixin::splitFrom(other); + mPotentialRecording.splitFrom(other.mPotentialRecording); +} + PeriodicRecording& get_frame_recording() { static LLThreadLocalPointer sRecording(new PeriodicRecording(1000, PeriodicRecording::STARTED)); diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index 7c4113dbf0..23b031b49b 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -254,6 +254,8 @@ namespace LLTrace void nextPeriod(); U32 getNumPeriods() { return mRecordingPeriods.size(); } + void appendPeriodicRecording(PeriodicRecording& other); + Recording& getLastRecording() { U32 num_periods = mRecordingPeriods.size(); @@ -424,6 +426,7 @@ namespace LLTrace void extend(); Recording& getAcceptedRecording() { return mAcceptedRecording; } + const Recording& getAcceptedRecording() const {return mAcceptedRecording;} // implementation for LLStopWatchControlsMixin /*virtual*/ void start(); @@ -435,11 +438,34 @@ namespace LLTrace /*virtual*/ void splitTo(ExtendableRecording& other); /*virtual*/ void splitFrom(ExtendableRecording& other); - const Recording& getAcceptedRecording() const {return mAcceptedRecording;} private: Recording mAcceptedRecording; Recording mPotentialRecording; }; + + class ExtendablePeriodicRecording + : public LLStopWatchControlsMixin + { + public: + void extend(); + + PeriodicRecording& getAcceptedRecording() { return mAcceptedRecording; } + const PeriodicRecording& getAcceptedRecording() const {return mAcceptedRecording;} + + // implementation for LLStopWatchControlsMixin + /*virtual*/ void start(); + /*virtual*/ void stop(); + /*virtual*/ void pause(); + /*virtual*/ void resume(); + /*virtual*/ void restart(); + /*virtual*/ void reset(); + /*virtual*/ void splitTo(ExtendablePeriodicRecording& other); + /*virtual*/ void splitFrom(ExtendablePeriodicRecording& other); + + private: + PeriodicRecording mAcceptedRecording; + PeriodicRecording mPotentialRecording; + }; } #endif // LL_LLTRACERECORDING_H -- cgit v1.3