JD2022-TU1/main/extern/dtest/dtcore/inc/dtmessage.h

174 lines
5.1 KiB
C++

#pragma once
#include "dtcore/inc/dtdefinitions.h"
#include "dtcore/inc/dtstream.h"
#include "dtcore/inc/dttypeinfo.h"
#include "dtcore/inc/dtmemory.h"
#include "dtcore/inc/dtfunctor.h"
namespace dt
{
class Message : public Serializable
{
DT_DECLARE_ROOT_TYPE(Message);
public:
};
//////////////////////////////////////////////////////////////////////////
class ConnectionDescriptor;
class MessageFactoryImpl;
class MessageCallbackAdapterBase
{
public:
virtual ~MessageCallbackAdapterBase() {}
virtual void Thunk(const ConnectionDescriptor& descriptor, const String& route, Message* msg) = 0;
};
template <class T> class MessageCallbackAdapter : public MessageCallbackAdapterBase
{
public:
MessageCallbackAdapter() {}
MessageCallbackAdapter(const Functor2<const ConnectionDescriptor&, T*>& callback)
: m_Callback(callback)
{
}
virtual void Thunk(const ConnectionDescriptor& descriptor, const String& route, Message* msg) override
{
DT_UNUSED(route);
if (m_Callback)
{
T* casted = DynamicCast<T>(msg);
DT_ASSERT(casted);
m_Callback(descriptor, casted);
}
}
private:
Functor2<const ConnectionDescriptor&, T*> m_Callback;
};
template <class T> class MessageCallbackAdapterWithRoute : public MessageCallbackAdapterBase
{
public:
MessageCallbackAdapterWithRoute() {}
MessageCallbackAdapterWithRoute(const Functor3<const ConnectionDescriptor&, const String&, T*>& callback)
: m_Callback(callback)
{
}
virtual void Thunk(const ConnectionDescriptor& descriptor, const String& route, Message* msg) override
{
if (m_Callback)
{
T* casted = DynamicCast<T>(msg);
DT_ASSERT(casted);
m_Callback(descriptor, route, casted);
}
}
private:
Functor3<const ConnectionDescriptor&, const String&, T*> m_Callback;
};
class MessageFactory
{
public:
MessageFactory();
~MessageFactory();
typedef Message* (*CreateFunction)();
template <class T> void Register()
{
RegisterInternal(
T::GetExactTypeInfo()->GetName(),
T::Create,
nullptr,
0_s,
String::Blank());
}
template <class T> void Unregister()
{
UnregisterInternal(T::GetExactTypeInfo()->GetName());
}
template <class T, class U, class V> void Register(U* self,
V func,
Seconds cachePeriodInSec = 0_s,
const String& defaultRole = GetRoleDefault())
{
RegisterInternal(
T::GetExactTypeInfo()->GetName(),
T::Create,
DT_NEW(MessageCallbackAdapter<T>)(Functor2<const ConnectionDescriptor&, T*>::Bind(func, self)),
cachePeriodInSec,
defaultRole);
}
template <class T, class U, class V> void RegisterWithRoute(U* self,
V func,
Seconds cachePeriodInSec = 0_s,
const String& defaultRole = GetRoleDefault())
{
RegisterInternal(
T::GetExactTypeInfo()->GetName(),
T::Create,
DT_NEW(MessageCallbackAdapterWithRoute<T>)(Functor3<const ConnectionDescriptor&, const String&, T*>::Bind(func, self)),
cachePeriodInSec,
defaultRole);
}
template <class T, class U, class V> void RegisterAs(U* self,
V func,
const String& alias,
Seconds cachePeriodInSec = 0_s,
const String& defaultRole = GetRoleDefault())
{
RegisterInternal(
alias,
T::Create,
DT_NEW(MessageCallbackAdapter<T>)(Functor2<const ConnectionDescriptor&, T*>::Bind(func, self)),
cachePeriodInSec,
defaultRole);
}
bool IsKnown(const String& msgType) const;
Message* Create(const String& msgType) const;
Seconds GetCachePeriodInSec(const String& msgType) const;
const String& GetRole(const String& msgType) const;
static const String& GetRoleGuest();
static const String& GetRoleReader();
static const String& GetRoleAdmin();
static const String& GetRoleInvalid();
static String GetRoleDefault();
static void SetRoleDefaultGetterFunction(const Functor0R<String>& getter);
bool Callback(const ConnectionDescriptor& descriptor, const String& route, Message* msg);
private:
void RegisterInternal(const String& typeName,
CreateFunction createFunc,
MessageCallbackAdapterBase* callback,
Seconds cachePeriodInSec,
const String& defaultRole);
void UnregisterInternal(const String& typeName);
MessageFactoryImpl* m_Impl;
};
}