211 lines
6.9 KiB
C++
211 lines
6.9 KiB
C++
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
|
// Copyright (C) 2010 Winch Gate Property Limited
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program 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 Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#ifndef NL_RESOURCE_PTR_H
|
|
#define NL_RESOURCE_PTR_H
|
|
|
|
|
|
#include "nel/misc/types_nl.h"
|
|
#include "nel/misc/debug.h"
|
|
#include "nel/misc/stream.h"
|
|
#include "nel/misc/smart_ptr.h"
|
|
|
|
#include <cstdio>
|
|
|
|
namespace NLMISC
|
|
{
|
|
|
|
// For debug only.
|
|
#define REF_TRACE(_s) ((void)0)
|
|
//#define REF_TRACE(_s) nlinfo("%s: %d \n", _s, pinfo!=&CRefCount::NullPtrInfo?pinfo->RefCount:0)
|
|
|
|
// ***************************************************************************
|
|
/**
|
|
* CResourcePtr: an handle on a ptr. T Must derive from CRefCount.
|
|
* A CResourcePtr is a CRefPtr able to find its pointer using a key.
|
|
*
|
|
* This way, the resource can be loaded, unloaded, changed and the pointer stays valid.
|
|
* Sample:
|
|
*\code
|
|
|
|
// Our resource type
|
|
class CResource : NLMISC::CRefCount
|
|
{
|
|
public:
|
|
int data;
|
|
void thisIsGood();
|
|
};
|
|
|
|
// Provide a class to retrieve a resource using a key (here, it is a string)
|
|
class CResourceFinder
|
|
{
|
|
public:
|
|
static void *getResource (const std::string &key)
|
|
{
|
|
static CResource a;
|
|
static CResource b;
|
|
if (key == "a")
|
|
return &a;
|
|
if (key == "b")
|
|
return &b;
|
|
return NULL;
|
|
}
|
|
};
|
|
|
|
// Pointer typedef
|
|
typedef CResourcePtr<CResource, std::string, CResourceFinder> TAPtr;
|
|
|
|
// Exemple of utilsation
|
|
void foo()
|
|
{
|
|
// Get the "a" resource
|
|
TAPtr rscA("a");
|
|
|
|
// The test call the cast operator and update the cached pointer.
|
|
// If the pointer has been deleted, the function is called to retrieve a new pointer.
|
|
// If the resource doesn't exist, it returns NULL.
|
|
if (rscA)
|
|
{
|
|
// Use the pointer in cache, this is fast
|
|
rscA->thisIsGood();
|
|
}
|
|
|
|
// Get the "b" resource
|
|
rsc = "b";
|
|
if (rsc)
|
|
{
|
|
// Use the pointer in cache, this is fast
|
|
rsc->thisIsGood();
|
|
}
|
|
}
|
|
|
|
\endcode
|
|
*
|
|
* \b PERFORMANCE \b WARNING! operator=() and the cast operator are about 10 times slower than normal pointers. So use them wisely.
|
|
* A good way to do it : using CResourcePtr in a debug mode in which the resources can be unloaded/reloaded, and using CStaticResourcePtr, else.
|
|
* Also, an object used with a CResourcePtr will allocate a small PtrInfo (one only per object, not per ptr).
|
|
* TPtr is the type of the pointed object.
|
|
* TKey is the key used to retrieve the object pointer.
|
|
* TResourceFinder is a class with a static method "static void *getResource (const TKey &key)" that returns a pointer on an object using a key.
|
|
* If the function return a non NULL pointer (resource found), the ResourcePtr is initialised with it.
|
|
* \sa CSmartPtr, CRefCount, CRefPtr
|
|
* \author Cyril 'Hulud' Corvazier
|
|
*/
|
|
template <class TPtr, class TKey, class TResourceFinder>
|
|
class CResourcePtr
|
|
{
|
|
private:
|
|
CRefCount::CPtrInfo *pinfo; // A ptr to the handle of the object.
|
|
TKey Key; // The key used to find the pointer
|
|
mutable TPtr *Ptr; // A cache for pinfo->Ptr. Useful to speed up ope->() and ope*()
|
|
|
|
void unRef() const; // Just release the handle pinfo, but do not update pinfo/Ptr, if deleted.
|
|
|
|
public:
|
|
|
|
/// Init a NULL Ptr.
|
|
CResourcePtr();
|
|
/// Retrieve a ptr using the key. If the pointer doesn't exist, the CResourcePtr is NULL.
|
|
CResourcePtr(const TKey &key);
|
|
/// Copy constructor.
|
|
CResourcePtr(const CResourcePtr ©);
|
|
/// Release the RefPtr.
|
|
~CResourcePtr(void);
|
|
|
|
|
|
/// Cast operator. Check if the object has been deleted somewhere, and return NULL if this is the case.
|
|
operator TPtr*() const;
|
|
/// Cast operator. Check if the object has been deleted somewhere, and return NULL if this is the case.
|
|
TPtr* getPtr() const;
|
|
|
|
/** Indirection operator. Doesn't update the ptr and doesn't test if the pointer has been deleted, and doesn't check NULL.
|
|
* You must test the pointer first using the cast operator.
|
|
*/
|
|
TPtr& operator*(void) const;
|
|
/** Selection operator. Doesn't update the ptr and doesn't test if the pointer has been deleted, and doesn't check NULL.
|
|
* You must test the pointer first using the cast operator.
|
|
*/
|
|
TPtr* operator->(void) const;
|
|
|
|
/// Retrieve a ptr using the key. If the pointer doesn't exist, the CResourcePtr is NULL.
|
|
CResourcePtr& operator=(const TKey &key);
|
|
/// operator=. Giving a NULL pointer is a valid operation.
|
|
CResourcePtr& operator=(const CResourcePtr ©);
|
|
};
|
|
|
|
// ***************************************************************************
|
|
/**
|
|
* CStaticResourcePtr: a CResourcePtr remplacement that doesn't support the resource unload/reload.
|
|
* The object size is the same than a standard pointer.
|
|
* The pointer resource is retrieved at once and is keeped all along the life of the object.
|
|
* No memory / cpu overhead.
|
|
* Typically, you will use the CResourcePtr in a "reloadable resource version" of your software and
|
|
* the CStaticResourcePtr in the release version of your software.
|
|
*
|
|
* \author Cyril 'Hulud' Corvazier
|
|
*/
|
|
template <class TPtr, class TKey, class TResourceFinder>
|
|
class CStaticResourcePtr
|
|
{
|
|
private:
|
|
mutable TPtr *Ptr; // The pointer
|
|
|
|
public:
|
|
|
|
/// Init a NULL Ptr.
|
|
CStaticResourcePtr();
|
|
/// Retrieve a ptr using the key. If the pointer doesn't exist, the CStaticResourcePtr is NULL.
|
|
CStaticResourcePtr(const TKey &key);
|
|
/// Copy constructor.
|
|
CStaticResourcePtr(const CStaticResourcePtr ©);
|
|
/// Release the RefPtr.
|
|
~CStaticResourcePtr(void);
|
|
|
|
|
|
/// Cast operator. No check are done.
|
|
operator TPtr*() const;
|
|
/// Cast operator. No check are done.
|
|
TPtr* getPtr() const;
|
|
|
|
/// Indirection operator. No check are done.
|
|
TPtr& operator*(void) const;
|
|
/// Selection operator. No check are done.
|
|
TPtr* operator->(void) const;
|
|
|
|
/// Retrieve a ptr using the key. If the pointer doesn't exist, the CStaticResourcePtr is NULL.
|
|
CStaticResourcePtr& operator=(const TKey &key);
|
|
/// operator=. Giving a NULL pointer is a valid operation.
|
|
CStaticResourcePtr& operator=(const CStaticResourcePtr ©);
|
|
};
|
|
|
|
|
|
}
|
|
|
|
|
|
// ***************************************************************************
|
|
// ***************************************************************************
|
|
// Implementation.
|
|
// ***************************************************************************
|
|
// ***************************************************************************
|
|
|
|
|
|
#include "resource_ptr_inline.h"
|
|
#undef SMART_TRACE
|
|
#undef REF_TRACE
|
|
|
|
#endif // NL_RESOURCE_PTR_H
|
|
|
|
/* End of resource_ptr.h */
|