- Moved all virtual function related template code to its own file because it depends on includes that cannot be done in dobject.h.

This commit is contained in:
Christoph Oelckers 2016-11-12 00:33:40 +01:00
parent 14a9c13113
commit 696af7d7e5
9 changed files with 136 additions and 129 deletions

View file

@ -1419,10 +1419,6 @@ public:
}; };
VMEXPORT_NATIVES_START(AActor, DThinker)
VMEXPORT_NATIVES_FUNC(DropInventory)
VMEXPORT_NATIVES_END(AActor)
class FActorIterator class FActorIterator
{ {
public: public:

View file

@ -48,6 +48,7 @@
#include "a_sharedglobal.h" #include "a_sharedglobal.h"
#include "dsectoreffect.h" #include "dsectoreffect.h"
#include "serializer.h" #include "serializer.h"
#include "virtual.h"
//========================================================================== //==========================================================================
// //

View file

@ -153,34 +153,6 @@ protected: \
#define HAS_FIELDS \ #define HAS_FIELDS \
static void InitNativeFields(); static void InitNativeFields();
// Templates really are powerful
#define VMEXPORTED_NATIVES_START \
template<class owner> class ExportedNatives : public ExportedNatives<typename owner::Super> {}; \
template<> class ExportedNatives<void> { \
protected: ExportedNatives<void>() {} \
public: \
static ExportedNatives<void> *Get() { static ExportedNatives<void> *Instance = nullptr; if (Instance == nullptr) Instance = new ExportedNatives<void>; return Instance; } \
ExportedNatives<void>(const ExportedNatives<void>&) = delete; \
ExportedNatives<void>(ExportedNatives<void>&&) = delete;
#define VMEXPORTED_NATIVES_FUNC(func) \
template<class ret, class object, class ... args> ret func(void *ptr, args ... arglist) { return ret(); }
#define VMEXPORTED_NATIVES_END };
#define VMEXPORT_NATIVES_START(cls, parent) \
template<> class ExportedNatives<cls> : public ExportedNatives<parent> { \
protected: ExportedNatives<cls>() {} \
public: \
static ExportedNatives<cls> *Get() { static ExportedNatives<cls> *Instance = nullptr; if (Instance == nullptr) Instance = new ExportedNatives<cls>; return Instance; } \
ExportedNatives<cls>(const ExportedNatives<cls>&) = delete; \
ExportedNatives<cls>(ExportedNatives<cls>&&) = delete;
#define VMEXPORT_NATIVES_FUNC(func) \
template<class ret, class object, class ... args> ret func(void *ptr, args ... arglist) { return static_cast<object *>(ptr)->object::func(arglist...); }
#define VMEXPORT_NATIVES_END(cls) };
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma section(".creg$u",read) # pragma section(".creg$u",read)
# define _DECLARE_TI(cls) __declspec(allocate(".creg$u")) ClassReg * const cls::RegistrationInfoPtr = &cls::RegistrationInfo; # define _DECLARE_TI(cls) __declspec(allocate(".creg$u")) ClassReg * const cls::RegistrationInfoPtr = &cls::RegistrationInfo;
@ -615,100 +587,8 @@ protected:
} }
}; };
//Initial list
VMEXPORTED_NATIVES_START
VMEXPORTED_NATIVES_FUNC(Destroy)
VMEXPORTED_NATIVES_FUNC(Tick)
VMEXPORTED_NATIVES_FUNC(DropInventory)
VMEXPORTED_NATIVES_END
class AInventory;// class AInventory;//
template<class T>
class DVMObject : public T
{
public:
static char *FormatClassName()
{
static char *name = nullptr;
if (name == nullptr)
{
name = new char[64];
mysnprintf(name, 64, "DVMObject<%s>", Super::RegistrationInfo.Name);
atterm([]{ delete[] DVMObject<T>::RegistrationInfo.Name; });
}
return name;
}
virtual PClass *StaticType() const
{
return RegistrationInfo.MyClass;
}
static ClassReg RegistrationInfo;
static ClassReg * const RegistrationInfoPtr;
typedef T Super;
private:
typedef DVMObject<T> ThisClass;
static void InPlaceConstructor(void *mem)
{
new((EInPlace *)mem) DVMObject<T>;
}
public:
void Destroy()
{
if (ObjectFlags & OF_SuperCall)
{
ObjectFlags &= OF_SuperCall;
ExportedNatives<T>::Get()->template Destroy<void, T>(this);
}
else
{
static int VIndex = -1;
if (VIndex < 0)
{
// Look up the virtual function index in the defining class because this may have gotten overloaded in subclasses with something different than a virtual override.
auto sym = dyn_cast<PFunction>(RUNTIME_CLASS(DObject)->Symbols.FindSymbol("Destroy", false));
assert(sym != nullptr);
VIndex = sym->Variants[0].Implementation->VirtualIndex;
assert(VIndex >= 0);
}
// Without the type cast this picks the 'void *' assignment...
VMValue params[1] = { (DObject*)this };
VMFrameStack stack;
stack.Call(GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr);
}
}
void Tick()
{
ExportedNatives<T>::Get()->template Tick<void, T>(this);
}
AInventory *DropInventory(AInventory *item)
{
return ExportedNatives<T>::Get()->template DropInventory<AInventory *, T>(this, item);
}
};
template<class T>
ClassReg DVMObject<T>::RegistrationInfo =
{
nullptr,
DVMObject<T>::FormatClassName(),
&DVMObject<T>::Super::RegistrationInfo,
nullptr,
nullptr,
DVMObject<T>::InPlaceConstructor,
nullptr,
sizeof(DVMObject<T>),
DVMObject<T>::MetaClassNum
};
template<class T> _DECLARE_TI(DVMObject<T>)
VMEXPORT_NATIVES_START(DObject, void)
VMEXPORT_NATIVES_FUNC(Destroy)
VMEXPORT_NATIVES_END(DObject)
// When you write to a pointer to an Object, you must call this for // When you write to a pointer to an Object, you must call this for
// proper bookkeeping in case the Object holding this pointer has // proper bookkeeping in case the Object holding this pointer has
// already been processed by the GC. // already been processed by the GC.

View file

@ -40,6 +40,7 @@
#include "doomerrors.h" #include "doomerrors.h"
#include "serializer.h" #include "serializer.h"
#include "d_player.h" #include "d_player.h"
#include "virtual.h"
static cycle_t ThinkCycles; static cycle_t ThinkCycles;

View file

@ -108,10 +108,6 @@ private:
DThinker *NextThinker, *PrevThinker; DThinker *NextThinker, *PrevThinker;
}; };
VMEXPORT_NATIVES_START(DThinker, DObject)
VMEXPORT_NATIVES_FUNC(Tick)
VMEXPORT_NATIVES_END(DThinker)
class FThinkerIterator class FThinkerIterator
{ {
protected: protected:

View file

@ -26,7 +26,6 @@
#include "a_hereticartifacts.cpp" #include "a_hereticartifacts.cpp"
#include "a_hereticweaps.cpp" #include "a_hereticweaps.cpp"
#include "a_ironlich.cpp" #include "a_ironlich.cpp"
#include "a_wizard.cpp"
static FRandom pr_podpain ("PodPain"); static FRandom pr_podpain ("PodPain");

View file

@ -72,6 +72,7 @@
#include "serializer.h" #include "serializer.h"
#include "r_utility.h" #include "r_utility.h"
#include "thingdef.h" #include "thingdef.h"
#include "virtual.h"
// MACROS ------------------------------------------------------------------ // MACROS ------------------------------------------------------------------

View file

@ -59,6 +59,7 @@
#include "p_blockmap.h" #include "p_blockmap.h"
#include "a_morph.h" #include "a_morph.h"
#include "p_spec.h" #include "p_spec.h"
#include "virtual.h"
static FRandom pr_skullpop ("SkullPop"); static FRandom pr_skullpop ("SkullPop");

132
src/virtual.h Normal file
View file

@ -0,0 +1,132 @@
// Templates really are powerful
#define VMEXPORTED_NATIVES_START \
template<class owner> class ExportedNatives : public ExportedNatives<typename owner::Super> {}; \
template<> class ExportedNatives<void> { \
protected: ExportedNatives<void>() {} \
public: \
static ExportedNatives<void> *Get() { static ExportedNatives<void> *Instance = nullptr; if (Instance == nullptr) Instance = new ExportedNatives<void>; return Instance; } \
ExportedNatives<void>(const ExportedNatives<void>&) = delete; \
ExportedNatives<void>(ExportedNatives<void>&&) = delete;
#define VMEXPORTED_NATIVES_FUNC(func) \
template<class ret, class object, class ... args> ret func(void *ptr, args ... arglist) { return ret(); }
#define VMEXPORTED_NATIVES_END };
#define VMEXPORT_NATIVES_START(cls, parent) \
template<> class ExportedNatives<cls> : public ExportedNatives<parent> { \
protected: ExportedNatives<cls>() {} \
public: \
static ExportedNatives<cls> *Get() { static ExportedNatives<cls> *Instance = nullptr; if (Instance == nullptr) Instance = new ExportedNatives<cls>; return Instance; } \
ExportedNatives<cls>(const ExportedNatives<cls>&) = delete; \
ExportedNatives<cls>(ExportedNatives<cls>&&) = delete;
#define VMEXPORT_NATIVES_FUNC(func) \
template<class ret, class object, class ... args> ret func(void *ptr, args ... arglist) { return static_cast<object *>(ptr)->object::func(arglist...); }
#define VMEXPORT_NATIVES_END(cls) };
//Initial list
VMEXPORTED_NATIVES_START
VMEXPORTED_NATIVES_FUNC(Destroy)
VMEXPORTED_NATIVES_FUNC(Tick)
VMEXPORTED_NATIVES_FUNC(DropInventory)
VMEXPORTED_NATIVES_END
template<class T>
class DVMObject : public T
{
public:
static char *FormatClassName()
{
static char *name = nullptr;
if (name == nullptr)
{
name = new char[64];
mysnprintf(name, 64, "DVMObject<%s>", Super::RegistrationInfo.Name);
atterm([]{ delete[] DVMObject<T>::RegistrationInfo.Name; });
}
return name;
}
virtual PClass *StaticType() const
{
return RegistrationInfo.MyClass;
}
static ClassReg RegistrationInfo;
static ClassReg * const RegistrationInfoPtr;
typedef T Super;
private:
typedef DVMObject<T> ThisClass;
static void InPlaceConstructor(void *mem)
{
new((EInPlace *)mem) DVMObject<T>;
}
public:
void Destroy()
{
if (ObjectFlags & OF_SuperCall)
{
ObjectFlags &= OF_SuperCall;
ExportedNatives<T>::Get()->template Destroy<void, T>(this);
}
else
{
static int VIndex = -1;
if (VIndex < 0)
{
// Look up the virtual function index in the defining class because this may have gotten overloaded in subclasses with something different than a virtual override.
auto sym = dyn_cast<PFunction>(RUNTIME_CLASS(DObject)->Symbols.FindSymbol("Destroy", false));
assert(sym != nullptr);
VIndex = sym->Variants[0].Implementation->VirtualIndex;
assert(VIndex >= 0);
}
// Without the type cast this picks the 'void *' assignment...
VMValue params[1] = { (DObject*)this };
VMFrameStack stack;
stack.Call(GetClass()->Virtuals[VIndex], params, 1, nullptr, 0, nullptr);
}
}
void Tick()
{
ExportedNatives<T>::Get()->template Tick<void, T>(this);
}
AInventory *DropInventory(AInventory *item)
{
return ExportedNatives<T>::Get()->template DropInventory<AInventory *, T>(this, item);
}
};
template<class T>
ClassReg DVMObject<T>::RegistrationInfo =
{
nullptr,
DVMObject<T>::FormatClassName(),
&DVMObject<T>::Super::RegistrationInfo,
nullptr,
nullptr,
DVMObject<T>::InPlaceConstructor,
nullptr,
sizeof(DVMObject<T>),
DVMObject<T>::MetaClassNum
};
template<class T> _DECLARE_TI(DVMObject<T>)
VMEXPORT_NATIVES_START(DObject, void)
VMEXPORT_NATIVES_FUNC(Destroy)
VMEXPORT_NATIVES_END(DObject)
VMEXPORT_NATIVES_START(DThinker, DObject)
VMEXPORT_NATIVES_FUNC(Tick)
VMEXPORT_NATIVES_END(DThinker)
VMEXPORT_NATIVES_START(AActor, DThinker)
VMEXPORT_NATIVES_FUNC(DropInventory)
VMEXPORT_NATIVES_END(AActor)