首页 > Personal > Game > 游戏引擎设计系列2-对象管理
2018
09-24

游戏引擎设计系列2-对象管理

内存管理之后就是对象管理了,在c++中,为了管理对象的生命周期,需要设计智能指针来管理相应对象的创建和删除,比如std的智能指针。现在也比较推荐直接使用std的智能指针,但在2007年c++11的功能还在好像TR命名空间下,并不是正式版本,所以我们设计了自己的智能指针系统,并且嵌入了下篇文章需要提到的反射信息。不过需要清楚一点,智能指针在管理对象时虽然会带来很多方便,但是它自身也会有各种问题,比如大量使用会有一定的性能损失,比如毕竟不是完全的GC会出现循环引用问题,虽然可以用WeakPtr去规避,但是毕竟需要在写代码的时候多加小心。总的来说利大于弊吧。
首先需要定义一个PtrData,提供智能指针相关接口,
template PtrData
void AddRef() // 增加引用计数
void Release() // 减少引用计数,如果为0,删除Data,同时调用ReleaseWeak
void AddRefWeak() // 增加弱引用计数
void ReleaseWeak() // 减少弱引用计数,如果为0,删除this
// 下面的两个接口时为了反射用的
Identifier & GetTypeName() // 数据类型的名称,包含反射相关信息,通过模板推导类型,调用系统RTTI接口typeid获得type_info,不同类型进行cache
void * QueryInterface(const Identifier & typeName) // 通过类型名请求相应接口,如果是本身的类型直接返回,如果不是获取反射的TypeInfo,再通过TypeInfo获取相应数据

其次定义几种智能指针类型,其中包含数据Data和PtrData两部分,尽量在栈上创建,不要使用new创建,
NullPtr // 空指针
BasePtr // 基本指针,所有指针的基类
SharedPtr : BasePtr // 创建增加PtrData引用计数、释放删除PtrData引用计数
WeakPtr : BasePtr // 创建增加PtrData弱引用计数、释放删除PtrData弱引用计数,实际使用时转为SharedPtr
AutoPtr : BasePtr // 类似于SharedPtr,但是智能有一个所有者,新的赋值和构造都会删除自身的PtrData的所有权
TempPtr : BasePtr // 不增加任何PtrData引用计数,一般用于参数传递,不需要保证数据的有效性时,实际使用时转为SharedPtr

上面就是智能指针的内容了,同样现在可以使用std智能指针作为替代,不过里面使用unique_ptr代替了auto_ptr,同时禁止了复制构造和赋值,如果一定要使用需要用std::move标识。

除了智能指针,同时还定义了Object,作为所有需要管理的对象的基类
TempPtr(void) Owner // 用来保存指向对象的智能指针
衍生的会有接口
OnCreate
OnDestroy

过程中会用到一些功能模板,
/// check
template struct is_pointer { enum { result = false }; };
template struct is_pointer { enum { result = true }; };
template struct is_reference { enum { result = false }; };
template struct is_reference { enum { result = true }; };
template struct is_const { enum { result = false }; };
template struct is_const { enum { result = true }; };

/// remove
template struct remove_reference { typedef T result; };
template struct remove_reference { typedef T result; };
template struct remove_pointer { typedef T result; };
template struct remove_pointer { typedef T result; };
template struct remove_const { typedef T result; };
template struct remove_const { typedef T result; };
template struct remove_all { typedef T result; };
template struct remove_all { typedef T result; };
template struct remove_all { typedef T result; };
template struct remove_all { typedef T result; };
template struct remove_all { typedef T result; };
template struct remove_all { typedef T result; };

/// to variable type
template struct to_variable_type { typedef T result; };
template struct to_variable_type { typedef T result; };
template struct to_variable_type { typedef T result; };

/// to param type
template struct to_param_type { typedef const T & result; };
template struct to_param_type { typedef T & result; };
template struct to_param_type { typedef const T & result; };

/// to reference type
template struct to_reference_type
{
typedef T & result;
static inline result cast(T * ptr) { return *ptr; }
};

template struct to_reference_type
{
typedef T & result;
static inline result cast(T * ptr) { return *ptr; }
};

template<> struct to_reference_type
{
typedef void* & result;
static inline result cast(void * ptr) { return *(void**)ptr; }
};

/// select
template struct select { typedef T1 result; };
template struct select { typedef T2 result; };

/// cast to
template struct can_cast_to
{
private:
static FROM & source_object();
static int return_type(TO &);
static char return_type(…);
public:
enum
{
result = sizeof(int) == sizeof(return_type(source_object()))
};
};

/// select type name
template struct typename_fromrtti
{
static inline const Identifier & result()
{
static bool initialized = false;
static Identifier name;
if (!initialized)
{
Identifier rtti(TypeName(typeid(T)));
InterlockedExchange((long*)&rtti, InterlockedExchange((long*)&name, *(long*)&rtti));
initialized = true;
}
return name;
}
};

struct ChangeTypeName {};
template struct ChangeTypeName : public ChangeTypeName { typedef T TypeName; };
template struct change_typename { typedef T result; };
template struct change_typename { typedef typename T::TypeName result; };

template struct select_typename
{
typedef typename remove_all::result RT;
typedef typename_fromrtti::result>::result> result;
};

template<> struct select_typename
{
typedef typename_fromrtti result;
};

template struct typename_of : public select_typename::result
{
};

#define TYPE_NAME(className) typename_of::result()
#define ptr_new by_value << new #define ptr_new_reference by_reference << template struct default_impl
{
static inline PtrData * by_value(T * value) { return new PtrData(value); }
static inline PtrData * by_reference(T * value) {return new PtrData(value); }
};

template struct object_impl
{
static inline PtrData * by_value(T * value) { return new PtrData(value); }
static inline PtrData * by_reference(T * value) {
if (value) {
IPtrData * ret = value->Owner().GetRawPtrData();
if (ret){ ret->AddRef(); return ret; } else return by_value(value); }
return NULL;
}
};

template struct ptrdata_impl
{
static inline IPtrData * by_value(T * value) { return value; }
static inline IPtrData * by_reference(T * value)
{ value->AddRef(); return value; }
};

interface UsePtrData {};
template struct UsePtrData : public UsePtrData { typedef T PtrDataType; };
template struct select_impl
{
typedef typename select< can_cast_to::result,
ptrdata_impl,
typename select< can_cast_to::result,
object_impl,
default_impl::result
>::result
>
>::result
>::result result;
};

enum BY_VALUE { by_value };
enum BY_REFERENCE { by_reference };

template inline SharedPtr operator << (BY_VALUE, T * value) { =return SharedPtr(value, select_impl::result::by_value(value)); };

template inline SharedPtr operator << (BY_REFERENCE, T * value) { return SharedPtr(value, select_impl::result::by_reference(value));};

另外在使用时会加入一些模板的特例化。

最后编辑:
作者:wy182000
这个作者貌似有点懒,什么都没有留下。