diff options
Diffstat (limited to 'indra/llcommon')
-rwxr-xr-x | indra/llcommon/llapr.cpp | 2 | ||||
-rw-r--r-- | indra/llcommon/lltrace.h | 298 | ||||
-rw-r--r-- | indra/llcommon/lltraceaccumulators.cpp | 5 | ||||
-rw-r--r-- | indra/llcommon/lltraceaccumulators.h | 36 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.cpp | 60 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.h | 17 | ||||
-rw-r--r-- | indra/llcommon/llunittype.h | 1 |
7 files changed, 81 insertions, 338 deletions
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 4346740e47..a548c96002 100755 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -243,7 +243,7 @@ void LLVolatileAPRPool::clearVolatileAPRPool() llassert_always(mNumActiveRef > 0) ; } - llassert(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ; + llassert(mNumTotalRef <= (FULL_VOLATILE_APR_POOL << 2)) ; } BOOL LLVolatileAPRPool::isFull() diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index da4bf6e36b..226f64d0c7 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -35,6 +35,8 @@ #include "lltraceaccumulators.h" #include "llthreadlocalstorage.h" #include "lltimer.h" +#include "llpointer.h" +#include "llunits.h" #include <list> @@ -206,39 +208,6 @@ public: {} }; -template<> -class TraceType<MemStatAccumulator::ShadowAllocationFacet> - : public TraceType<MemStatAccumulator> -{ -public: - - TraceType(const char* name, const char* description = "") - : TraceType<MemStatAccumulator>(name, description) - {} -}; - -template<> -class TraceType<MemStatAccumulator::ShadowDeallocationFacet> - : public TraceType<MemStatAccumulator> -{ -public: - - TraceType(const char* name, const char* description = "") - : TraceType<MemStatAccumulator>(name, description) - {} -}; - -template<> -class TraceType<MemStatAccumulator::ShadowMemFacet> - : public TraceType<MemStatAccumulator> -{ -public: - - TraceType(const char* name, const char* description = "") - : TraceType<MemStatAccumulator>(name, description) - {} -}; - class MemStatHandle : public TraceType<MemStatAccumulator> { public: @@ -264,109 +233,40 @@ public: { return static_cast<TraceType<MemStatAccumulator::DeallocationFacet>&>(*(TraceType<MemStatAccumulator>*)this); } - - TraceType<MemStatAccumulator::ShadowAllocationFacet>& shadowAllocations() - { - return static_cast<TraceType<MemStatAccumulator::ShadowAllocationFacet>&>(*(TraceType<MemStatAccumulator>*)this); - } - - TraceType<MemStatAccumulator::ShadowDeallocationFacet>& shadowDeallocations() - { - return static_cast<TraceType<MemStatAccumulator::ShadowDeallocationFacet>&>(*(TraceType<MemStatAccumulator>*)this); - } - - TraceType<MemStatAccumulator::ShadowMemFacet>& shadowMem() - { - return static_cast<TraceType<MemStatAccumulator::ShadowMemFacet>&>(*(TraceType<MemStatAccumulator>*)this); - } }; -inline void claim_footprint(MemStatHandle& measurement, S32 size) -{ - if(size == 0) return; - MemStatAccumulator& accumulator = measurement.getCurrentAccumulator(); - accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size); - accumulator.mFootprintAllocations.record(size); -} - -inline void disclaim_footprint(MemStatHandle& measurement, S32 size) -{ - if(size == 0) return; - MemStatAccumulator& accumulator = measurement.getCurrentAccumulator(); - accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size); - accumulator.mFootprintDeallocations.add(size); -} - -inline void claim_shadow(MemStatHandle& measurement, S32 size) -{ - if(size == 0) return; - MemStatAccumulator& accumulator = measurement.getCurrentAccumulator(); - accumulator.mShadowSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size); - accumulator.mShadowAllocations.record(size); -} - -inline void disclaim_shadow(MemStatHandle& measurement, S32 size) -{ - if(size == 0) return; - MemStatAccumulator& accumulator = measurement.getCurrentAccumulator(); - accumulator.mShadowSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size); - accumulator.mShadowDeallocations.add(size); -} // measures effective memory footprint of specified type // specialize to cover different types - -template<typename T, typename IS_MEM_TRACKABLE = void> +template<typename T, typename IS_MEM_TRACKABLE = void, typename IS_UNITS = void> struct MeasureMem { static size_t measureFootprint(const T& value) { return sizeof(T); } - - static size_t measureFootprint() - { - return sizeof(T); - } - - static size_t measureShadow(const T& value) - { - return 0; - } - - static size_t measureShadow() - { - return 0; - } }; -template<typename T> -struct MeasureMem<T, typename T::mem_trackable_tag_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(); } +}; - static size_t measureFootprint() - { - return sizeof(T); - } - - static size_t measureShadow(const T& value) - { - return value.getMemShadow(); - } - - static size_t measureShadow() +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 MeasureMem<T>::measureShadow(); + return U32Bytes(value).value(); } }; - -template<typename T, typename IS_MEM_TRACKABLE> -struct MeasureMem<T*, IS_MEM_TRACKABLE> +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) { @@ -376,46 +276,68 @@ struct MeasureMem<T*, IS_MEM_TRACKABLE> } return MeasureMem<T>::measureFootprint(*value); } +}; - static size_t measureFootprint() +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) { - return MeasureMem<T>::measureFootprint(); + if (value.isNull()) + { + return 0; + } + return MeasureMem<T>::measureFootprint(*value); } +}; - static size_t measureShadow(const T* value) +template<typename IS_MEM_TRACKABLE, typename IS_BYTES> +struct MeasureMem<S32, IS_MEM_TRACKABLE, IS_BYTES> +{ + static size_t measureFootprint(S32 value) { - return MeasureMem<T>::measureShadow(*value); + return value; } +}; - static size_t measureShadow() +template<typename IS_MEM_TRACKABLE, typename IS_BYTES> +struct MeasureMem<U32, IS_MEM_TRACKABLE, IS_BYTES> +{ + static size_t measureFootprint(U32 value) { - return MeasureMem<T>::measureShadow(); + return value; } }; -template<typename T, typename IS_MEM_TRACKABLE> -struct MeasureMem<std::basic_string<T>, IS_MEM_TRACKABLE> +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); } +}; - static size_t measureFootprint() - { - return sizeof(std::basic_string<T>); - } - static size_t measureShadow(const std::basic_string<T>& value) - { - return 0; - } +template<typename T> +inline void claim_footprint(MemStatHandle& measurement, const T& value) +{ + S32 size = MeasureMem<T>::measureFootprint(value); + if(size == 0) return; + MemStatAccumulator& accumulator = measurement.getCurrentAccumulator(); + accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() + (F64)size : (F64)size); + accumulator.mFootprintAllocations.record(size); +} - static size_t measureShadow() - { - return 0; - } -}; +template<typename T> +inline void disclaim_footprint(MemStatHandle& measurement, const T& value) +{ + S32 size = MeasureMem<T>::measureFootprint(value); + if(size == 0) return; + MemStatAccumulator& accumulator = measurement.getCurrentAccumulator(); + accumulator.mSize.sample(accumulator.mSize.hasValue() ? accumulator.mSize.getLastValue() - (F64)size : -(F64)size); + accumulator.mFootprintDeallocations.add(size); +} template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN> class MemTrackable @@ -423,28 +345,20 @@ class MemTrackable public: typedef void mem_trackable_tag_t; - enum EMemType - { - MEM_FOOTPRINT, - MEM_SHADOW - }; - - MemTrackable() - : mMemFootprint(0), - mMemShadow(0) + MemTrackable(const char* name) + : mMemFootprint(0) { static bool name_initialized = false; if (!name_initialized) { name_initialized = true; - sMemStat.setName(typeid(DERIVED).name()); + sMemStat.setName(name); } } virtual ~MemTrackable() { - disclaimMem(mMemFootprint, MEM_FOOTPRINT); - disclaimMem(mMemShadow, MEM_SHADOW); + disclaimMem(mMemFootprint); } static MemStatHandle& getMemStatHandle() @@ -453,7 +367,6 @@ public: } S32 getMemFootprint() const { return mMemFootprint; } - S32 getMemShadow() const { return mMemShadow; } void* operator new(size_t size) { @@ -467,7 +380,7 @@ public: ll_aligned_free(ALIGNMENT, ptr); } - void *operator new [](size_t size) + void* operator new [](size_t size) { claim_footprint(sMemStat, size); return ll_aligned_malloc(ALIGNMENT, size); @@ -481,98 +394,27 @@ public: // claim memory associated with other objects/data as our own, adding to our calculated footprint template<typename CLAIM_T> - CLAIM_T& claimMem(CLAIM_T& value, EMemType mem_type = MEM_FOOTPRINT) - { - trackAlloc(MeasureMem<CLAIM_T>::measureFootprint(value), mem_type); - trackAlloc(MeasureMem<CLAIM_T>::measureShadow(value), MEM_SHADOW); - return value; - } - - template<typename CLAIM_T> - const CLAIM_T& claimMem(const CLAIM_T& value, EMemType mem_type = MEM_FOOTPRINT) - { - trackAlloc(MeasureMem<CLAIM_T>::measureFootprint(value), mem_type); - trackAlloc(MeasureMem<CLAIM_T>::measureShadow(value), MEM_SHADOW); - return value; - } - - size_t& claimMem(size_t& size, EMemType mem_type = MEM_FOOTPRINT) - { - trackAlloc(size, mem_type); - return size; - } - - S32& claimMem(S32& size, EMemType mem_type = MEM_FOOTPRINT) + void claimMem(const CLAIM_T& value) const { - trackAlloc(size, mem_type); - return size; + S32 size = MeasureMem<CLAIM_T>::measureFootprint(value); + claim_footprint(sMemStat, size); + mMemFootprint += size; } // remove memory we had claimed from our calculated footprint template<typename CLAIM_T> - CLAIM_T& disclaimMem(CLAIM_T& value, EMemType mem_type = MEM_FOOTPRINT) - { - trackDealloc(MeasureMem<CLAIM_T>::measureFootprint(value), mem_type); - trackDealloc(MeasureMem<CLAIM_T>::measureShadow(value), MEM_SHADOW); - return value; - } - - template<typename CLAIM_T> - const CLAIM_T& disclaimMem(const CLAIM_T& value, EMemType mem_type = MEM_FOOTPRINT) - { - trackDealloc(MeasureMem<CLAIM_T>::measureFootprint(value), mem_type); - trackDealloc(MeasureMem<CLAIM_T>::measureShadow(value), MEM_SHADOW); - return value; - } - - size_t& disclaimMem(size_t& size, EMemType mem_type = MEM_FOOTPRINT) + void disclaimMem(const CLAIM_T& value) const { - trackDealloc(size, mem_type); - return size; - } - - S32& disclaimMem(S32& size, EMemType mem_type = MEM_FOOTPRINT) - { - trackDealloc(size, mem_type); - return size; - } - -private: - - void trackAlloc(S32 size, EMemType mem_type) - { - if (mem_type == MEM_FOOTPRINT) - { - claim_footprint(sMemStat, size); - mMemFootprint += size; - } - else - { - claim_shadow(sMemStat, size); - mMemShadow += size; - } - } - - void trackDealloc(S32 size, EMemType mem_type) - { - if (mem_type == MEM_FOOTPRINT) - { - disclaim_footprint(sMemStat, size); - mMemFootprint -= size; - } - else - { - disclaim_shadow(sMemStat, size); - mMemShadow -= size; - } + S32 size = MeasureMem<CLAIM_T>::measureFootprint(value); + disclaim_footprint(sMemStat, size); + mMemFootprint -= size; } private: // 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 - S32 mMemFootprint, - mMemShadow; + mutable S32 mMemFootprint; static MemStatHandle sMemStat; }; diff --git a/indra/llcommon/lltraceaccumulators.cpp b/indra/llcommon/lltraceaccumulators.cpp index a7bd04415e..f5f2e7df1c 100644 --- a/indra/llcommon/lltraceaccumulators.cpp +++ b/indra/llcommon/lltraceaccumulators.cpp @@ -125,6 +125,11 @@ void AccumulatorBufferGroup::sync() void SampleAccumulator::addSamples( const SampleAccumulator& other, EBufferAppendType append_type ) { + if (append_type == NON_SEQUENTIAL) + { + return; + } + if (!mHasValue) { *this = other; diff --git a/indra/llcommon/lltraceaccumulators.h b/indra/llcommon/lltraceaccumulators.h index 5cba3e5360..ecc569f5d6 100644 --- a/indra/llcommon/lltraceaccumulators.h +++ b/indra/llcommon/lltraceaccumulators.h @@ -498,32 +498,14 @@ namespace LLTrace typedef F64Bytes value_t; }; - struct ShadowAllocationFacet - { - typedef F64Bytes value_t; - }; - - struct ShadowDeallocationFacet - { - typedef F64Bytes value_t; - }; - - struct ShadowMemFacet - { - typedef F64Bytes value_t; - }; - void addSamples(const MemStatAccumulator& other, EBufferAppendType append_type) { mFootprintAllocations.addSamples(other.mFootprintAllocations, append_type); mFootprintDeallocations.addSamples(other.mFootprintDeallocations, append_type); - mShadowAllocations.addSamples(other.mShadowAllocations, append_type); - mShadowDeallocations.addSamples(other.mShadowDeallocations, append_type); if (append_type == SEQUENTIAL) { mSize.addSamples(other.mSize, SEQUENTIAL); - mShadowSize.addSamples(other.mShadowSize, SEQUENTIAL); } else { @@ -531,36 +513,24 @@ namespace LLTrace mSize.sample(mSize.hasValue() ? mSize.getLastValue() + allocation_delta : allocation_delta); - - F64 shadow_allocation_delta(other.mShadowAllocations.getSum() - other.mShadowDeallocations.getSum()); - mShadowSize.sample(mShadowSize.hasValue() - ? mShadowSize.getLastValue() + shadow_allocation_delta - : shadow_allocation_delta); } } void reset(const MemStatAccumulator* other) { mSize.reset(other ? &other->mSize : NULL); - mShadowSize.reset(other ? &other->mShadowSize : NULL); mFootprintAllocations.reset(other ? &other->mFootprintAllocations : NULL); mFootprintDeallocations.reset(other ? &other->mFootprintDeallocations : NULL); - mShadowAllocations.reset(other ? &other->mShadowAllocations : NULL); - mShadowDeallocations.reset(other ? &other->mShadowDeallocations : NULL); } void sync(F64SecondsImplicit time_stamp) { mSize.sync(time_stamp); - mShadowSize.sync(time_stamp); } - SampleAccumulator mSize, - mShadowSize; - EventAccumulator mFootprintAllocations, - mShadowAllocations; - CountAccumulator mFootprintDeallocations, - mShadowDeallocations; + SampleAccumulator mSize; + EventAccumulator mFootprintAllocations; + CountAccumulator mFootprintDeallocations; }; struct AccumulatorBufferGroup : public LLRefCount diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index fb2293844a..ce4a433cca 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -173,11 +173,6 @@ bool Recording::hasValue(const TraceType<MemStatAccumulator>& stat) return mBuffers->mMemStats[stat.getIndex()].mSize.hasValue(); } -bool Recording::hasValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat) -{ - return mBuffers->mMemStats[stat.getIndex()].mShadowSize.hasValue(); -} - F64Kilobytes Recording::getMin(const TraceType<MemStatAccumulator>& stat) { return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getMin()); @@ -203,31 +198,6 @@ F64Kilobytes Recording::getLastValue(const TraceType<MemStatAccumulator>& stat) return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue()); } -F64Kilobytes Recording::getMin(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat) -{ - return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getMin()); -} - -F64Kilobytes Recording::getMean(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat) -{ - return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getMean()); -} - -F64Kilobytes Recording::getMax(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat) -{ - return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getMax()); -} - -F64Kilobytes Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat) -{ - return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getStandardDeviation()); -} - -F64Kilobytes Recording::getLastValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat) -{ - return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowSize.getLastValue()); -} - F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::AllocationFacet>& stat) { return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mFootprintAllocations.getSum()); @@ -258,36 +228,6 @@ S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::DeallocationFa return mBuffers->mMemStats[stat.getIndex()].mFootprintDeallocations.getSampleCount(); } -F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat) -{ - return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowAllocations.getSum()); -} - -F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat) -{ - return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowAllocations.getSum() / mElapsedSeconds.value()); -} - -S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat) -{ - return mBuffers->mMemStats[stat.getIndex()].mShadowAllocations.getSampleCount(); -} - -F64Kilobytes Recording::getSum(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat) -{ - return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowDeallocations.getSum()); -} - -F64Kilobytes Recording::getPerSec(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat) -{ - return F64Bytes(mBuffers->mMemStats[stat.getIndex()].mShadowDeallocations.getSum() / mElapsedSeconds.value()); -} - -S32 Recording::getSampleCount(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat) -{ - return mBuffers->mMemStats[stat.getIndex()].mShadowDeallocations.getSampleCount(); -} - F64 Recording::getSum( const TraceType<CountAccumulator>& stat ) { return mBuffers->mCounts[stat.getIndex()].getSum(); diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index 13dffdc701..5cf7596966 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -30,9 +30,9 @@ #include "stdtypes.h" #include "llpreprocessor.h" -#include "llpointer.h" #include "lltimer.h" #include "lltraceaccumulators.h" +#include "llpointer.h" class LLStopWatchControlsMixinCommon { @@ -178,7 +178,6 @@ namespace LLTrace // Memory accessors bool hasValue(const TraceType<MemStatAccumulator>& stat); - bool hasValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat); F64Kilobytes getMin(const TraceType<MemStatAccumulator>& stat); F64Kilobytes getMean(const TraceType<MemStatAccumulator>& stat); @@ -186,12 +185,6 @@ namespace LLTrace F64Kilobytes getStandardDeviation(const TraceType<MemStatAccumulator>& stat); F64Kilobytes getLastValue(const TraceType<MemStatAccumulator>& stat); - F64Kilobytes getMin(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat); - F64Kilobytes getMean(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat); - F64Kilobytes getMax(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat); - F64Kilobytes getStandardDeviation(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat); - F64Kilobytes getLastValue(const TraceType<MemStatAccumulator::ShadowMemFacet>& stat); - F64Kilobytes getSum(const TraceType<MemStatAccumulator::AllocationFacet>& stat); F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::AllocationFacet>& stat); S32 getSampleCount(const TraceType<MemStatAccumulator::AllocationFacet>& stat); @@ -200,14 +193,6 @@ namespace LLTrace F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::DeallocationFacet>& stat); S32 getSampleCount(const TraceType<MemStatAccumulator::DeallocationFacet>& stat); - F64Kilobytes getSum(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat); - F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat); - S32 getSampleCount(const TraceType<MemStatAccumulator::ShadowAllocationFacet>& stat); - - F64Kilobytes getSum(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat); - F64Kilobytes getPerSec(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat); - S32 getSampleCount(const TraceType<MemStatAccumulator::ShadowDeallocationFacet>& stat); - // CountStatHandle accessors F64 getSum(const TraceType<CountAccumulator>& stat); template <typename T> diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h index fb72d6d8a9..0e05ecd683 100644 --- a/indra/llcommon/llunittype.h +++ b/indra/llcommon/llunittype.h @@ -80,6 +80,7 @@ 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()) |