llmemory.h cleanup. pulled llpointer, refcounter, smartpointer, singleton and safe handle out into their own headers. llmemory.h drags all those headers in for legacy support until everything else is cleaned up. getCurrentRSS() moved into LLMemory. getWorkingSetSize() added to LLMemory.
This commit is contained in:
@@ -58,12 +58,14 @@ set(llcommon_SOURCE_FILES
|
||||
llprocessor.cpp
|
||||
llqueuedthread.cpp
|
||||
llrand.cpp
|
||||
llrefcount.cpp
|
||||
llrun.cpp
|
||||
llsd.cpp
|
||||
llsdserialize.cpp
|
||||
llsdserialize_xml.cpp
|
||||
llsdutil.cpp
|
||||
llsecondlifeurls.cpp
|
||||
llsingleton.cpp
|
||||
llstat.cpp
|
||||
llstacktrace.cpp
|
||||
llstreamtools.cpp
|
||||
@@ -159,6 +161,7 @@ set(llcommon_HEADER_FILES
|
||||
llmortician.h
|
||||
llnametable.h
|
||||
lloptioninterface.h
|
||||
llpointer.h
|
||||
llpreprocessor.h
|
||||
llpriqueuemap.h
|
||||
llprocesslauncher.h
|
||||
@@ -168,6 +171,8 @@ set(llcommon_HEADER_FILES
|
||||
llqueuedthread.h
|
||||
llrand.h
|
||||
llrun.h
|
||||
llrefcount.h
|
||||
llsafehandle.h
|
||||
llscopedvolatileaprpool.h
|
||||
llsd.h
|
||||
llsdserialize.h
|
||||
@@ -175,6 +180,7 @@ set(llcommon_HEADER_FILES
|
||||
llsdutil.h
|
||||
llsecondlifeurls.h
|
||||
llsimplehash.h
|
||||
llsingleton.h
|
||||
llskiplist.h
|
||||
llskipmap.h
|
||||
llstack.h
|
||||
@@ -205,6 +211,7 @@ set(llcommon_HEADER_FILES
|
||||
stdenums.h
|
||||
stdtypes.h
|
||||
string_table.h
|
||||
stringize.h
|
||||
timer.h
|
||||
timing.h
|
||||
u64.h
|
||||
|
||||
@@ -276,37 +276,12 @@ void operator delete[] (void *p)
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
LLRefCount::LLRefCount() :
|
||||
mRef(0)
|
||||
{
|
||||
}
|
||||
|
||||
LLRefCount::LLRefCount(const LLRefCount& other)
|
||||
: mRef(0)
|
||||
{
|
||||
}
|
||||
|
||||
LLRefCount::~LLRefCount()
|
||||
{
|
||||
if (mRef != 0)
|
||||
{
|
||||
llerrs << "deleting non-zero reference" << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
LLRefCount& LLRefCount::operator=(const LLRefCount&)
|
||||
{
|
||||
// do nothing, since ref count is specific to *this* reference
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#if defined(LL_WINDOWS)
|
||||
|
||||
U64 getCurrentRSS()
|
||||
U64 LLMemory::getCurrentRSS()
|
||||
{
|
||||
HANDLE self = GetCurrentProcess();
|
||||
PROCESS_MEMORY_COUNTERS counters;
|
||||
@@ -320,6 +295,20 @@ U64 getCurrentRSS()
|
||||
return counters.WorkingSetSize;
|
||||
}
|
||||
|
||||
//static
|
||||
U32 LLMemory::getWorkingSetSize()
|
||||
{
|
||||
PROCESS_MEMORY_COUNTERS pmc ;
|
||||
U32 ret = 0 ;
|
||||
|
||||
if (GetProcessMemoryInfo( GetCurrentProcess(), &pmc, sizeof(pmc)) )
|
||||
{
|
||||
ret = pmc.WorkingSetSize ;
|
||||
}
|
||||
|
||||
return ret ;
|
||||
}
|
||||
|
||||
#elif defined(LL_DARWIN)
|
||||
|
||||
/*
|
||||
@@ -344,7 +333,7 @@ U64 getCurrentRSS()
|
||||
// }
|
||||
// }
|
||||
|
||||
U64 getCurrentRSS()
|
||||
U64 LLMemory::getCurrentRSS()
|
||||
{
|
||||
U64 residentSize = 0;
|
||||
task_basic_info_data_t basicInfo;
|
||||
@@ -366,9 +355,14 @@ U64 getCurrentRSS()
|
||||
return residentSize;
|
||||
}
|
||||
|
||||
U32 LLMemory::getWorkingSetSize()
|
||||
{
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
#elif defined(LL_LINUX)
|
||||
|
||||
U64 getCurrentRSS()
|
||||
U64 LLMemory::getCurrentRSS()
|
||||
{
|
||||
static const char statPath[] = "/proc/self/stat";
|
||||
LLFILE *fp = LLFile::fopen(statPath, "r");
|
||||
@@ -400,6 +394,10 @@ bail:
|
||||
return rss;
|
||||
}
|
||||
|
||||
U32 LLMemory::getWorkingSetSize()
|
||||
{
|
||||
return 0 ;
|
||||
}
|
||||
#elif LL_SOLARIS
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -407,7 +405,7 @@ bail:
|
||||
#define _STRUCTURED_PROC 1
|
||||
#include <sys/procfs.h>
|
||||
|
||||
U64 getCurrentRSS()
|
||||
U64 LLMemory::getCurrentRSS()
|
||||
{
|
||||
char path [LL_MAX_PATH]; /* Flawfinder: ignore */
|
||||
|
||||
@@ -428,11 +426,22 @@ U64 getCurrentRSS()
|
||||
|
||||
return((U64)proc_psinfo.pr_rssize * 1024);
|
||||
}
|
||||
|
||||
U32 LLMemory::getWorkingSetSize()
|
||||
{
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
U64 getCurrentRSS()
|
||||
U64 LLMemory::getCurrentRSS()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
U32 LLMemory::getWorkingSetSize()
|
||||
{
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,20 +29,15 @@
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#ifndef LL_MEMORY_H
|
||||
#define LL_MEMORY_H
|
||||
#ifndef LLMEMORY_H
|
||||
#define LLMEMORY_H
|
||||
|
||||
|
||||
#include <new>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "llerror.h"
|
||||
|
||||
extern S32 gTotalDAlloc;
|
||||
extern S32 gTotalDAUse;
|
||||
extern S32 gDACount;
|
||||
|
||||
const U32 LLREFCOUNT_SENTINEL_VALUE = 0xAAAAAAAA;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#if LL_DEBUG
|
||||
@@ -128,431 +123,18 @@ public:
|
||||
static void initClass();
|
||||
static void cleanupClass();
|
||||
static void freeReserve();
|
||||
// Return the resident set size of the current process, in bytes.
|
||||
// Return value is zero if not known.
|
||||
static U64 getCurrentRSS();
|
||||
static U32 getWorkingSetSize();
|
||||
private:
|
||||
static char* reserveMem;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// RefCount objects should generally only be accessed by way of LLPointer<>'s
|
||||
// NOTE: LLPointer<LLFoo> x = new LLFoo(); MAY NOT BE THREAD SAFE
|
||||
// if LLFoo::LLFoo() does anything like put itself in an update queue.
|
||||
// The queue may get accessed before it gets assigned to x.
|
||||
// The correct implementation is:
|
||||
// LLPointer<LLFoo> x = new LLFoo; // constructor does not do anything interesting
|
||||
// x->instantiate(); // does stuff like place x into an update queue
|
||||
|
||||
// see llthread.h for LLThreadSafeRefCount
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class LL_COMMON_API LLRefCount
|
||||
{
|
||||
protected:
|
||||
LLRefCount(const LLRefCount&);
|
||||
private:
|
||||
LLRefCount&operator=(const LLRefCount&);
|
||||
|
||||
protected:
|
||||
virtual ~LLRefCount(); // use unref()
|
||||
|
||||
public:
|
||||
LLRefCount();
|
||||
|
||||
void ref()
|
||||
{
|
||||
mRef++;
|
||||
}
|
||||
|
||||
S32 unref()
|
||||
{
|
||||
llassert(mRef >= 1);
|
||||
if (0 == --mRef)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return mRef;
|
||||
}
|
||||
|
||||
S32 getNumRefs() const
|
||||
{
|
||||
return mRef;
|
||||
}
|
||||
|
||||
private:
|
||||
S32 mRef;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Note: relies on Type having ref() and unref() methods
|
||||
template <class Type> class LLPointer
|
||||
{
|
||||
public:
|
||||
|
||||
LLPointer() :
|
||||
mPointer(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
LLPointer(Type* ptr) :
|
||||
mPointer(ptr)
|
||||
{
|
||||
ref();
|
||||
}
|
||||
|
||||
LLPointer(const LLPointer<Type>& ptr) :
|
||||
mPointer(ptr.mPointer)
|
||||
{
|
||||
ref();
|
||||
}
|
||||
|
||||
// support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||
template<typename Subclass>
|
||||
LLPointer(const LLPointer<Subclass>& ptr) :
|
||||
mPointer(ptr.get())
|
||||
{
|
||||
ref();
|
||||
}
|
||||
|
||||
~LLPointer()
|
||||
{
|
||||
unref();
|
||||
}
|
||||
|
||||
Type* get() const { return mPointer; }
|
||||
const Type* operator->() const { return mPointer; }
|
||||
Type* operator->() { return mPointer; }
|
||||
const Type& operator*() const { return *mPointer; }
|
||||
Type& operator*() { return *mPointer; }
|
||||
|
||||
operator BOOL() const { return (mPointer != NULL); }
|
||||
operator bool() const { return (mPointer != NULL); }
|
||||
bool operator!() const { return (mPointer == NULL); }
|
||||
bool isNull() const { return (mPointer == NULL); }
|
||||
bool notNull() const { return (mPointer != NULL); }
|
||||
|
||||
operator Type*() const { return mPointer; }
|
||||
operator const Type*() const { return mPointer; }
|
||||
bool operator !=(Type* ptr) const { return (mPointer != ptr); }
|
||||
bool operator ==(Type* ptr) const { return (mPointer == ptr); }
|
||||
bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
|
||||
bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
|
||||
bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
|
||||
|
||||
LLPointer<Type>& operator =(Type* ptr)
|
||||
{
|
||||
if( mPointer != ptr )
|
||||
{
|
||||
unref();
|
||||
mPointer = ptr;
|
||||
ref();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
LLPointer<Type>& operator =(const LLPointer<Type>& ptr)
|
||||
{
|
||||
if( mPointer != ptr.mPointer )
|
||||
{
|
||||
unref();
|
||||
mPointer = ptr.mPointer;
|
||||
ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||
template<typename Subclass>
|
||||
LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)
|
||||
{
|
||||
if( mPointer != ptr.get() )
|
||||
{
|
||||
unref();
|
||||
mPointer = ptr.get();
|
||||
ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Just exchange the pointers, which will not change the reference counts.
|
||||
static void swap(LLPointer<Type>& a, LLPointer<Type>& b)
|
||||
{
|
||||
Type* temp = a.mPointer;
|
||||
a.mPointer = b.mPointer;
|
||||
b.mPointer = temp;
|
||||
}
|
||||
|
||||
protected:
|
||||
void ref()
|
||||
{
|
||||
if (mPointer)
|
||||
{
|
||||
mPointer->ref();
|
||||
}
|
||||
}
|
||||
|
||||
void unref()
|
||||
{
|
||||
if (mPointer)
|
||||
{
|
||||
Type *tempp = mPointer;
|
||||
mPointer = NULL;
|
||||
tempp->unref();
|
||||
if (mPointer != NULL)
|
||||
{
|
||||
llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
|
||||
unref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
Type* mPointer;
|
||||
};
|
||||
|
||||
//template <class Type>
|
||||
//class LLPointerTraits
|
||||
//{
|
||||
// static Type* null();
|
||||
//};
|
||||
//
|
||||
// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL.
|
||||
// This is useful in instances where operations on NULL pointers are semantically safe and/or
|
||||
// when error checking occurs at a different granularity or in a different part of the code
|
||||
// than when referencing an object via a LLSafeHandle.
|
||||
//
|
||||
|
||||
template <class Type>
|
||||
class LLSafeHandle
|
||||
{
|
||||
public:
|
||||
LLSafeHandle() :
|
||||
mPointer(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
LLSafeHandle(Type* ptr) :
|
||||
mPointer(NULL)
|
||||
{
|
||||
assign(ptr);
|
||||
}
|
||||
|
||||
LLSafeHandle(const LLSafeHandle<Type>& ptr) :
|
||||
mPointer(NULL)
|
||||
{
|
||||
assign(ptr.mPointer);
|
||||
}
|
||||
|
||||
// support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||
template<typename Subclass>
|
||||
LLSafeHandle(const LLSafeHandle<Subclass>& ptr) :
|
||||
mPointer(NULL)
|
||||
{
|
||||
assign(ptr.get());
|
||||
}
|
||||
|
||||
~LLSafeHandle()
|
||||
{
|
||||
unref();
|
||||
}
|
||||
|
||||
const Type* operator->() const { return nonNull(mPointer); }
|
||||
Type* operator->() { return nonNull(mPointer); }
|
||||
|
||||
Type* get() const { return mPointer; }
|
||||
// we disallow these operations as they expose our null objects to direct manipulation
|
||||
// and bypass the reference counting semantics
|
||||
//const Type& operator*() const { return *nonNull(mPointer); }
|
||||
//Type& operator*() { return *nonNull(mPointer); }
|
||||
|
||||
operator BOOL() const { return mPointer != NULL; }
|
||||
operator bool() const { return mPointer != NULL; }
|
||||
bool operator!() const { return mPointer == NULL; }
|
||||
bool isNull() const { return mPointer == NULL; }
|
||||
bool notNull() const { return mPointer != NULL; }
|
||||
|
||||
|
||||
operator Type*() const { return mPointer; }
|
||||
operator const Type*() const { return mPointer; }
|
||||
bool operator !=(Type* ptr) const { return (mPointer != ptr); }
|
||||
bool operator ==(Type* ptr) const { return (mPointer == ptr); }
|
||||
bool operator ==(const LLSafeHandle<Type>& ptr) const { return (mPointer == ptr.mPointer); }
|
||||
bool operator < (const LLSafeHandle<Type>& ptr) const { return (mPointer < ptr.mPointer); }
|
||||
bool operator > (const LLSafeHandle<Type>& ptr) const { return (mPointer > ptr.mPointer); }
|
||||
|
||||
LLSafeHandle<Type>& operator =(Type* ptr)
|
||||
{
|
||||
assign(ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LLSafeHandle<Type>& operator =(const LLSafeHandle<Type>& ptr)
|
||||
{
|
||||
assign(ptr.mPointer);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||
template<typename Subclass>
|
||||
LLSafeHandle<Type>& operator =(const LLSafeHandle<Subclass>& ptr)
|
||||
{
|
||||
assign(ptr.get());
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
typedef Type* (*NullFunc)();
|
||||
static const NullFunc sNullFunc;
|
||||
|
||||
protected:
|
||||
void ref()
|
||||
{
|
||||
if (mPointer)
|
||||
{
|
||||
mPointer->ref();
|
||||
}
|
||||
}
|
||||
|
||||
void unref()
|
||||
{
|
||||
if (mPointer)
|
||||
{
|
||||
Type *tempp = mPointer;
|
||||
mPointer = NULL;
|
||||
tempp->unref();
|
||||
if (mPointer != NULL)
|
||||
{
|
||||
llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
|
||||
unref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assign(Type* ptr)
|
||||
{
|
||||
if( mPointer != ptr )
|
||||
{
|
||||
unref();
|
||||
mPointer = ptr;
|
||||
ref();
|
||||
}
|
||||
}
|
||||
|
||||
static Type* nonNull(Type* ptr)
|
||||
{
|
||||
return ptr == NULL ? sNullFunc() : ptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
Type* mPointer;
|
||||
};
|
||||
|
||||
// LLInitializedPointer is just a pointer with a default constructor that initializes it to NULL
|
||||
// NOT a smart pointer like LLPointer<>
|
||||
// Useful for example in std::map<int,LLInitializedPointer<LLFoo> >
|
||||
// (std::map uses the default constructor for creating new entries)
|
||||
template <typename T> class LLInitializedPointer
|
||||
{
|
||||
public:
|
||||
LLInitializedPointer() : mPointer(NULL) {}
|
||||
~LLInitializedPointer() { delete mPointer; }
|
||||
|
||||
const T* operator->() const { return mPointer; }
|
||||
T* operator->() { return mPointer; }
|
||||
const T& operator*() const { return *mPointer; }
|
||||
T& operator*() { return *mPointer; }
|
||||
operator const T*() const { return mPointer; }
|
||||
operator T*() { return mPointer; }
|
||||
T* operator=(T* x) { return (mPointer = x); }
|
||||
operator bool() const { return mPointer != NULL; }
|
||||
bool operator!() const { return mPointer == NULL; }
|
||||
bool operator==(T* rhs) { return mPointer == rhs; }
|
||||
bool operator==(const LLInitializedPointer<T>* rhs) { return mPointer == rhs.mPointer; }
|
||||
|
||||
protected:
|
||||
T* mPointer;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// LLSingleton implements the getInstance() method part of the Singleton
|
||||
// pattern. It can't make the derived class constructors protected, though, so
|
||||
// you have to do that yourself.
|
||||
//
|
||||
// There are two ways to use LLSingleton. The first way is to inherit from it
|
||||
// while using the typename that you'd like to be static as the template
|
||||
// parameter, like so:
|
||||
//
|
||||
// class Foo: public LLSingleton<Foo>{};
|
||||
//
|
||||
// Foo& instance = Foo::instance();
|
||||
//
|
||||
// The second way is to use the singleton class directly, without inheritance:
|
||||
//
|
||||
// typedef LLSingleton<Foo> FooSingleton;
|
||||
//
|
||||
// Foo& instance = FooSingleton::instance();
|
||||
//
|
||||
// In this case, the class being managed as a singleton needs to provide an
|
||||
// initSingleton() method since the LLSingleton virtual method won't be
|
||||
// available
|
||||
//
|
||||
// As currently written, it is not thread-safe.
|
||||
template <typename T>
|
||||
class LLSingleton
|
||||
{
|
||||
static bool &needsInit()
|
||||
{
|
||||
static bool needs_init = true;
|
||||
return needs_init;
|
||||
}
|
||||
public:
|
||||
static bool instanceExists()
|
||||
{
|
||||
return !needsInit();
|
||||
}
|
||||
virtual ~LLSingleton() {}
|
||||
#ifdef LL_MSVC7
|
||||
// workaround for VC7 compiler bug
|
||||
// adapted from http://www.codeproject.com/KB/tips/VC2003MeyersSingletonBug.aspx
|
||||
// our version doesn't introduce a nested struct so that you can still declare LLSingleton<MyClass>
|
||||
// a friend and hide your constructor
|
||||
static T* getInstance()
|
||||
{
|
||||
LLSingleton<T> singleton;
|
||||
return singleton.vsHack();
|
||||
}
|
||||
|
||||
T* vsHack()
|
||||
#else
|
||||
static T* getInstance()
|
||||
#endif
|
||||
{
|
||||
static T instance;
|
||||
bool &needs_init = needsInit();
|
||||
if (needs_init)
|
||||
{
|
||||
needs_init = false;
|
||||
instance.initSingleton();
|
||||
}
|
||||
return &instance;
|
||||
}
|
||||
|
||||
static T& instance()
|
||||
{
|
||||
return *getInstance();
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void initSingleton() {}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Return the resident set size of the current process, in bytes.
|
||||
// Return value is zero if not known.
|
||||
LL_COMMON_API U64 getCurrentRSS();
|
||||
//EVENTUALLY REMOVE THESE:
|
||||
#include "llpointer.h"
|
||||
#include "llrefcount.h"
|
||||
#include "llsingleton.h"
|
||||
#include "llsafehandle.h"
|
||||
|
||||
#endif
|
||||
|
||||
170
indra/llcommon/llpointer.h
Normal file
170
indra/llcommon/llpointer.h
Normal file
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* @file llpointer.h
|
||||
* @brief A reference-counted pointer for objects derived from LLRefCount
|
||||
*
|
||||
* $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 LLPOINTER_H
|
||||
#define LLPOINTER_H
|
||||
|
||||
#include "llerror.h" // *TODO: consider eliminating this
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// RefCount objects should generally only be accessed by way of LLPointer<>'s
|
||||
// NOTE: LLPointer<LLFoo> x = new LLFoo(); MAY NOT BE THREAD SAFE
|
||||
// if LLFoo::LLFoo() does anything like put itself in an update queue.
|
||||
// The queue may get accessed before it gets assigned to x.
|
||||
// The correct implementation is:
|
||||
// LLPointer<LLFoo> x = new LLFoo; // constructor does not do anything interesting
|
||||
// x->instantiate(); // does stuff like place x into an update queue
|
||||
|
||||
// see llthread.h for LLThreadSafeRefCount
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// Note: relies on Type having ref() and unref() methods
|
||||
template <class Type> class LLPointer
|
||||
{
|
||||
public:
|
||||
|
||||
LLPointer() :
|
||||
mPointer(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
LLPointer(Type* ptr) :
|
||||
mPointer(ptr)
|
||||
{
|
||||
ref();
|
||||
}
|
||||
|
||||
LLPointer(const LLPointer<Type>& ptr) :
|
||||
mPointer(ptr.mPointer)
|
||||
{
|
||||
ref();
|
||||
}
|
||||
|
||||
// support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||
template<typename Subclass>
|
||||
LLPointer(const LLPointer<Subclass>& ptr) :
|
||||
mPointer(ptr.get())
|
||||
{
|
||||
ref();
|
||||
}
|
||||
|
||||
~LLPointer()
|
||||
{
|
||||
unref();
|
||||
}
|
||||
|
||||
Type* get() const { return mPointer; }
|
||||
const Type* operator->() const { return mPointer; }
|
||||
Type* operator->() { return mPointer; }
|
||||
const Type& operator*() const { return *mPointer; }
|
||||
Type& operator*() { return *mPointer; }
|
||||
|
||||
operator BOOL() const { return (mPointer != NULL); }
|
||||
operator bool() const { return (mPointer != NULL); }
|
||||
bool operator!() const { return (mPointer == NULL); }
|
||||
bool isNull() const { return (mPointer == NULL); }
|
||||
bool notNull() const { return (mPointer != NULL); }
|
||||
|
||||
operator Type*() const { return mPointer; }
|
||||
bool operator !=(Type* ptr) const { return (mPointer != ptr); }
|
||||
bool operator ==(Type* ptr) const { return (mPointer == ptr); }
|
||||
bool operator ==(const LLPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); }
|
||||
bool operator < (const LLPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); }
|
||||
bool operator > (const LLPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); }
|
||||
|
||||
LLPointer<Type>& operator =(Type* ptr)
|
||||
{
|
||||
if( mPointer != ptr )
|
||||
{
|
||||
unref();
|
||||
mPointer = ptr;
|
||||
ref();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
LLPointer<Type>& operator =(const LLPointer<Type>& ptr)
|
||||
{
|
||||
if( mPointer != ptr.mPointer )
|
||||
{
|
||||
unref();
|
||||
mPointer = ptr.mPointer;
|
||||
ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||
template<typename Subclass>
|
||||
LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr)
|
||||
{
|
||||
if( mPointer != ptr.get() )
|
||||
{
|
||||
unref();
|
||||
mPointer = ptr.get();
|
||||
ref();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Just exchange the pointers, which will not change the reference counts.
|
||||
static void swap(LLPointer<Type>& a, LLPointer<Type>& b)
|
||||
{
|
||||
Type* temp = a.mPointer;
|
||||
a.mPointer = b.mPointer;
|
||||
b.mPointer = temp;
|
||||
}
|
||||
|
||||
protected:
|
||||
void ref()
|
||||
{
|
||||
if (mPointer)
|
||||
{
|
||||
mPointer->ref();
|
||||
}
|
||||
}
|
||||
|
||||
void unref()
|
||||
{
|
||||
if (mPointer)
|
||||
{
|
||||
Type *tempp = mPointer;
|
||||
mPointer = NULL;
|
||||
tempp->unref();
|
||||
if (mPointer != NULL)
|
||||
{
|
||||
llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
|
||||
unref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
Type* mPointer;
|
||||
};
|
||||
|
||||
#endif
|
||||
164
indra/llcommon/llrefcount.cpp
Normal file
164
indra/llcommon/llrefcount.cpp
Normal file
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* @file llrefcount.cpp
|
||||
* @brief Base class for reference counted objects for use with LLPointer
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llrefcount.h"
|
||||
|
||||
#include "llerror.h"
|
||||
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
#include "llthread.h"
|
||||
#include "llapr.h"
|
||||
#endif
|
||||
|
||||
LLRefCount::LLRefCount(const LLRefCount& other)
|
||||
: mRef(0)
|
||||
{
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
if(gAPRPoolp)
|
||||
{
|
||||
mMutexp = new LLMutex(gAPRPoolp) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMutexp = NULL ;
|
||||
}
|
||||
mCrashAtUnlock = FALSE ;
|
||||
#endif
|
||||
}
|
||||
|
||||
LLRefCount& LLRefCount::operator=(const LLRefCount&)
|
||||
{
|
||||
// do nothing, since ref count is specific to *this* reference
|
||||
return *this;
|
||||
}
|
||||
|
||||
LLRefCount::LLRefCount() :
|
||||
mRef(0)
|
||||
{
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
if(gAPRPoolp)
|
||||
{
|
||||
mMutexp = new LLMutex(gAPRPoolp) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
mMutexp = NULL ;
|
||||
}
|
||||
mCrashAtUnlock = FALSE ;
|
||||
#endif
|
||||
}
|
||||
|
||||
LLRefCount::~LLRefCount()
|
||||
{
|
||||
if (mRef != 0)
|
||||
{
|
||||
llerrs << "deleting non-zero reference" << llendl;
|
||||
}
|
||||
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
if(gAPRPoolp)
|
||||
{
|
||||
delete mMutexp ;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
void LLRefCount::ref() const
|
||||
{
|
||||
if(mMutexp)
|
||||
{
|
||||
if(mMutexp->isLocked())
|
||||
{
|
||||
mCrashAtUnlock = TRUE ;
|
||||
llerrs << "the mutex is locked by the thread: " << mLockedThreadID
|
||||
<< " Current thread: " << LLThread::currentID() << llendl ;
|
||||
}
|
||||
|
||||
mMutexp->lock() ;
|
||||
mLockedThreadID = LLThread::currentID() ;
|
||||
|
||||
mRef++;
|
||||
|
||||
if(mCrashAtUnlock)
|
||||
{
|
||||
while(1); //crash here.
|
||||
}
|
||||
mMutexp->unlock() ;
|
||||
}
|
||||
else
|
||||
{
|
||||
mRef++;
|
||||
}
|
||||
}
|
||||
|
||||
S32 LLRefCount::unref() const
|
||||
{
|
||||
if(mMutexp)
|
||||
{
|
||||
if(mMutexp->isLocked())
|
||||
{
|
||||
mCrashAtUnlock = TRUE ;
|
||||
llerrs << "the mutex is locked by the thread: " << mLockedThreadID
|
||||
<< " Current thread: " << LLThread::currentID() << llendl ;
|
||||
}
|
||||
|
||||
mMutexp->lock() ;
|
||||
mLockedThreadID = LLThread::currentID() ;
|
||||
|
||||
llassert(mRef >= 1);
|
||||
if (0 == --mRef)
|
||||
{
|
||||
if(mCrashAtUnlock)
|
||||
{
|
||||
while(1); //crash here.
|
||||
}
|
||||
mMutexp->unlock() ;
|
||||
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(mCrashAtUnlock)
|
||||
{
|
||||
while(1); //crash here.
|
||||
}
|
||||
mMutexp->unlock() ;
|
||||
return mRef;
|
||||
}
|
||||
else
|
||||
{
|
||||
llassert(mRef >= 1);
|
||||
if (0 == --mRef)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return mRef;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
89
indra/llcommon/llrefcount.h
Normal file
89
indra/llcommon/llrefcount.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* @file llrefcount.h
|
||||
* @brief Base class for reference counted objects for use with LLPointer
|
||||
*
|
||||
* $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 LLREFCOUNT_H
|
||||
#define LLREFCOUNT_H
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#define LL_REF_COUNT_DEBUG 0
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
class LLMutex ;
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// RefCount objects should generally only be accessed by way of LLPointer<>'s
|
||||
// see llthread.h for LLThreadSafeRefCount
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class LL_COMMON_API LLRefCount
|
||||
{
|
||||
protected:
|
||||
LLRefCount(const LLRefCount& other);
|
||||
LLRefCount& operator=(const LLRefCount&);
|
||||
virtual ~LLRefCount(); // use unref()
|
||||
|
||||
public:
|
||||
LLRefCount();
|
||||
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
void ref() const ;
|
||||
S32 unref() const ;
|
||||
#else
|
||||
inline void ref() const
|
||||
{
|
||||
mRef++;
|
||||
}
|
||||
|
||||
inline S32 unref() const
|
||||
{
|
||||
llassert(mRef >= 1);
|
||||
if (0 == --mRef)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
return mRef;
|
||||
}
|
||||
#endif
|
||||
|
||||
//NOTE: when passing around a const LLRefCount object, this can return different results
|
||||
// at different types, since mRef is mutable
|
||||
S32 getNumRefs() const
|
||||
{
|
||||
return mRef;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable S32 mRef;
|
||||
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
LLMutex* mMutexp ;
|
||||
mutable U32 mLockedThreadID ;
|
||||
mutable BOOL mCrashAtUnlock ;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
162
indra/llcommon/llsafehandle.h
Normal file
162
indra/llcommon/llsafehandle.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/**
|
||||
* @file llsafehandle.h
|
||||
* @brief Reference-counted object where Object() is valid, not NULL.
|
||||
*
|
||||
* $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 LLSAFEHANDLE_H
|
||||
#define LLSAFEHANDLE_H
|
||||
|
||||
#include "llerror.h" // *TODO: consider eliminating this
|
||||
|
||||
// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL.
|
||||
// This is useful in instances where operations on NULL pointers are semantically safe and/or
|
||||
// when error checking occurs at a different granularity or in a different part of the code
|
||||
// than when referencing an object via a LLSafeHandle.
|
||||
|
||||
template <class Type>
|
||||
class LLSafeHandle
|
||||
{
|
||||
public:
|
||||
LLSafeHandle() :
|
||||
mPointer(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
LLSafeHandle(Type* ptr) :
|
||||
mPointer(NULL)
|
||||
{
|
||||
assign(ptr);
|
||||
}
|
||||
|
||||
LLSafeHandle(const LLSafeHandle<Type>& ptr) :
|
||||
mPointer(NULL)
|
||||
{
|
||||
assign(ptr.mPointer);
|
||||
}
|
||||
|
||||
// support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||
template<typename Subclass>
|
||||
LLSafeHandle(const LLSafeHandle<Subclass>& ptr) :
|
||||
mPointer(NULL)
|
||||
{
|
||||
assign(ptr.get());
|
||||
}
|
||||
|
||||
~LLSafeHandle()
|
||||
{
|
||||
unref();
|
||||
}
|
||||
|
||||
const Type* operator->() const { return nonNull(mPointer); }
|
||||
Type* operator->() { return nonNull(mPointer); }
|
||||
|
||||
Type* get() const { return mPointer; }
|
||||
void clear() { assign(NULL); }
|
||||
// we disallow these operations as they expose our null objects to direct manipulation
|
||||
// and bypass the reference counting semantics
|
||||
//const Type& operator*() const { return *nonNull(mPointer); }
|
||||
//Type& operator*() { return *nonNull(mPointer); }
|
||||
|
||||
operator BOOL() const { return mPointer != NULL; }
|
||||
operator bool() const { return mPointer != NULL; }
|
||||
bool operator!() const { return mPointer == NULL; }
|
||||
bool isNull() const { return mPointer == NULL; }
|
||||
bool notNull() const { return mPointer != NULL; }
|
||||
|
||||
|
||||
operator Type*() const { return mPointer; }
|
||||
operator const Type*() const { return mPointer; }
|
||||
bool operator !=(Type* ptr) const { return (mPointer != ptr); }
|
||||
bool operator ==(Type* ptr) const { return (mPointer == ptr); }
|
||||
bool operator ==(const LLSafeHandle<Type>& ptr) const { return (mPointer == ptr.mPointer); }
|
||||
bool operator < (const LLSafeHandle<Type>& ptr) const { return (mPointer < ptr.mPointer); }
|
||||
bool operator > (const LLSafeHandle<Type>& ptr) const { return (mPointer > ptr.mPointer); }
|
||||
|
||||
LLSafeHandle<Type>& operator =(Type* ptr)
|
||||
{
|
||||
assign(ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LLSafeHandle<Type>& operator =(const LLSafeHandle<Type>& ptr)
|
||||
{
|
||||
assign(ptr.mPointer);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed.
|
||||
template<typename Subclass>
|
||||
LLSafeHandle<Type>& operator =(const LLSafeHandle<Subclass>& ptr)
|
||||
{
|
||||
assign(ptr.get());
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
typedef Type* (*NullFunc)();
|
||||
static const NullFunc sNullFunc;
|
||||
|
||||
protected:
|
||||
void ref()
|
||||
{
|
||||
if (mPointer)
|
||||
{
|
||||
mPointer->ref();
|
||||
}
|
||||
}
|
||||
|
||||
void unref()
|
||||
{
|
||||
if (mPointer)
|
||||
{
|
||||
Type *tempp = mPointer;
|
||||
mPointer = NULL;
|
||||
tempp->unref();
|
||||
if (mPointer != NULL)
|
||||
{
|
||||
llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl;
|
||||
unref();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void assign(Type* ptr)
|
||||
{
|
||||
if( mPointer != ptr )
|
||||
{
|
||||
unref();
|
||||
mPointer = ptr;
|
||||
ref();
|
||||
}
|
||||
}
|
||||
|
||||
static Type* nonNull(Type* ptr)
|
||||
{
|
||||
return ptr == NULL ? sNullFunc() : ptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
Type* mPointer;
|
||||
};
|
||||
|
||||
#endif
|
||||
32
indra/llcommon/llsingleton.cpp
Normal file
32
indra/llcommon/llsingleton.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* @file llsingleton.cpp
|
||||
* @author Brad Kittenbrink
|
||||
*
|
||||
* $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 "linden_common.h"
|
||||
|
||||
#include "llsingleton.h"
|
||||
|
||||
std::map<std::string, void *> * LLSingletonRegistry::sSingletonMap = NULL;
|
||||
|
||||
201
indra/llcommon/llsingleton.h
Normal file
201
indra/llcommon/llsingleton.h
Normal file
@@ -0,0 +1,201 @@
|
||||
/**
|
||||
* @file llsingleton.h
|
||||
*
|
||||
* $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 LLSINGLETON_H
|
||||
#define LLSINGLETON_H
|
||||
|
||||
#include "llerror.h" // *TODO: eliminate this
|
||||
|
||||
#include <typeinfo>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
/// @brief A global registry of all singletons to prevent duplicate allocations
|
||||
/// across shared library boundaries
|
||||
class LL_COMMON_API LLSingletonRegistry {
|
||||
private:
|
||||
typedef std::map<std::string, void *> TypeMap;
|
||||
static TypeMap * sSingletonMap;
|
||||
|
||||
static void checkInit()
|
||||
{
|
||||
if(sSingletonMap == NULL)
|
||||
{
|
||||
sSingletonMap = new TypeMap();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename T> static void * & get()
|
||||
{
|
||||
std::string name(typeid(T).name());
|
||||
|
||||
checkInit();
|
||||
|
||||
// the first entry of the pair returned by insert will be either the existing
|
||||
// iterator matching our key, or the newly inserted NULL initialized entry
|
||||
// see "Insert element" in http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
|
||||
TypeMap::iterator result =
|
||||
sSingletonMap->insert(std::make_pair(name, (void*)NULL)).first;
|
||||
|
||||
return result->second;
|
||||
}
|
||||
};
|
||||
|
||||
// LLSingleton implements the getInstance() method part of the Singleton
|
||||
// pattern. It can't make the derived class constructors protected, though, so
|
||||
// you have to do that yourself.
|
||||
//
|
||||
// There are two ways to use LLSingleton. The first way is to inherit from it
|
||||
// while using the typename that you'd like to be static as the template
|
||||
// parameter, like so:
|
||||
//
|
||||
// class Foo: public LLSingleton<Foo>{};
|
||||
//
|
||||
// Foo& instance = Foo::instance();
|
||||
//
|
||||
// The second way is to use the singleton class directly, without inheritance:
|
||||
//
|
||||
// typedef LLSingleton<Foo> FooSingleton;
|
||||
//
|
||||
// Foo& instance = FooSingleton::instance();
|
||||
//
|
||||
// In this case, the class being managed as a singleton needs to provide an
|
||||
// initSingleton() method since the LLSingleton virtual method won't be
|
||||
// available
|
||||
//
|
||||
// As currently written, it is not thread-safe.
|
||||
|
||||
template <typename DERIVED_TYPE>
|
||||
class LLSingleton : private boost::noncopyable
|
||||
{
|
||||
|
||||
private:
|
||||
typedef enum e_init_state
|
||||
{
|
||||
UNINITIALIZED,
|
||||
CONSTRUCTING,
|
||||
INITIALIZING,
|
||||
INITIALIZED,
|
||||
DELETED
|
||||
} EInitState;
|
||||
|
||||
static void deleteSingleton()
|
||||
{
|
||||
delete getData().mSingletonInstance;
|
||||
getData().mSingletonInstance = NULL;
|
||||
}
|
||||
|
||||
// stores pointer to singleton instance
|
||||
// and tracks initialization state of singleton
|
||||
struct SingletonInstanceData
|
||||
{
|
||||
EInitState mInitState;
|
||||
DERIVED_TYPE* mSingletonInstance;
|
||||
|
||||
SingletonInstanceData()
|
||||
: mSingletonInstance(NULL),
|
||||
mInitState(UNINITIALIZED)
|
||||
{}
|
||||
|
||||
~SingletonInstanceData()
|
||||
{
|
||||
deleteSingleton();
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
virtual ~LLSingleton()
|
||||
{
|
||||
SingletonInstanceData& data = getData();
|
||||
data.mSingletonInstance = NULL;
|
||||
data.mInitState = DELETED;
|
||||
}
|
||||
|
||||
static SingletonInstanceData& getData()
|
||||
{
|
||||
// this is static to cache the lookup results
|
||||
static void * & registry = LLSingletonRegistry::get<DERIVED_TYPE>();
|
||||
|
||||
// *TODO - look into making this threadsafe
|
||||
if(NULL == registry)
|
||||
{
|
||||
static SingletonInstanceData data;
|
||||
registry = &data;
|
||||
}
|
||||
|
||||
return *static_cast<SingletonInstanceData *>(registry);
|
||||
}
|
||||
|
||||
static DERIVED_TYPE* getInstance()
|
||||
{
|
||||
SingletonInstanceData& data = getData();
|
||||
|
||||
if (data.mInitState == CONSTRUCTING)
|
||||
{
|
||||
llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl;
|
||||
}
|
||||
|
||||
if (data.mInitState == DELETED)
|
||||
{
|
||||
llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
|
||||
}
|
||||
|
||||
if (!data.mSingletonInstance)
|
||||
{
|
||||
data.mInitState = CONSTRUCTING;
|
||||
data.mSingletonInstance = new DERIVED_TYPE();
|
||||
data.mInitState = INITIALIZING;
|
||||
data.mSingletonInstance->initSingleton();
|
||||
data.mInitState = INITIALIZED;
|
||||
}
|
||||
|
||||
return data.mSingletonInstance;
|
||||
}
|
||||
|
||||
// Reference version of getInstance()
|
||||
// Preferred over getInstance() as it disallows checking for NULL
|
||||
static DERIVED_TYPE& instance()
|
||||
{
|
||||
return *getInstance();
|
||||
}
|
||||
|
||||
// Has this singleton been created uet?
|
||||
// Use this to avoid accessing singletons before the can safely be constructed
|
||||
static bool instanceExists()
|
||||
{
|
||||
return getData().mInitState == INITIALIZED;
|
||||
}
|
||||
|
||||
// Has this singleton already been deleted?
|
||||
// Use this to avoid accessing singletons from a static object's destructor
|
||||
static bool destroyed()
|
||||
{
|
||||
return getData().mInitState == DELETED;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void initSingleton() {}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -3789,10 +3789,21 @@
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>DebugShowMemory</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Show Total Allocated Memory</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>DebugShowRenderInfo</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Show depth buffer contents</string>
|
||||
<string>Show stats about current scene</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
||||
@@ -2628,7 +2628,7 @@ void LLAppViewer::handleViewerCrash()
|
||||
gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath();
|
||||
gDebugInfo["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
|
||||
gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
|
||||
gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer) getCurrentRSS() >> 10;
|
||||
gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer) LLMemory::getCurrentRSS() >> 10;
|
||||
gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin();
|
||||
gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ void display_stats()
|
||||
F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency");
|
||||
if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq)
|
||||
{
|
||||
gMemoryAllocated = getCurrentRSS();
|
||||
gMemoryAllocated = LLMemory::getCurrentRSS();
|
||||
U32 memory = (U32)(gMemoryAllocated / (1024*1024));
|
||||
llinfos << llformat("MEMORY: %d MB", memory) << llendl;
|
||||
gRecentMemoryTime.reset();
|
||||
|
||||
@@ -707,7 +707,7 @@ void send_stats()
|
||||
agent["ping"] = gAvgSimPing;
|
||||
agent["meters_traveled"] = gAgent.getDistanceTraveled();
|
||||
agent["regions_visited"] = gAgent.getRegionsVisited();
|
||||
agent["mem_use"] = getCurrentRSS() / 1024.0;
|
||||
agent["mem_use"] = LLMemory::getCurrentRSS() / 1024.0;
|
||||
|
||||
LLSD &system = body["system"];
|
||||
|
||||
|
||||
@@ -333,6 +333,13 @@ public:
|
||||
addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc;
|
||||
}
|
||||
|
||||
#if LL_WINDOWS
|
||||
if (gSavedSettings.getBOOL("DebugShowMemory"))
|
||||
{
|
||||
addText(xpos, ypos, llformat("Memory: %d (KB)", LLMemory::getWorkingSetSize() / 1024));
|
||||
ypos += y_inc;
|
||||
}
|
||||
#endif
|
||||
if (gDisplayCameraPos)
|
||||
{
|
||||
std::string camera_view_text;
|
||||
|
||||
Reference in New Issue
Block a user