Delegate support for lambdas and std::functions in general, also supporting const members now [Miodrag Milanovic]

This commit is contained in:
Miodrag Milanovic 2016-11-05 20:26:04 +01:00
parent f05e7ffad0
commit dedf3c9b9d
4 changed files with 106 additions and 61 deletions

View File

@ -17,7 +17,7 @@
// fatal error if not found
//-------------------------------------------------
delegate_late_bind &device_delegate_helper::bound_object(device_t &search_root)
delegate_late_bind &device_delegate_helper::bound_object(device_t &search_root) const
{
device_t *device = search_root.subdevice(m_device_name);
if (device == nullptr)

View File

@ -30,7 +30,7 @@ protected:
device_delegate_helper(const char *devname) : m_device_name(devname) { }
// internal helpers
delegate_late_bind &bound_object(device_t &search_root);
delegate_late_bind &bound_object(device_t &search_root) const;
static const char *safe_tag(device_t *object);
// internal state
@ -54,20 +54,24 @@ public:
device_delegate(const basetype &src) : basetype(src), device_delegate_helper(src.m_device_name) { }
device_delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object), device_delegate_helper(src.m_device_name) { }
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::const_member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
#ifdef USE_STATIC_DELEGATE
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_ref_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object), device_delegate_helper(safe_tag(dynamic_cast<device_t *>(object))) { }
#endif
device_delegate(std::function<_Signature> funcptr) : basetype(funcptr), device_delegate_helper(nullptr) { }
device_delegate &operator=(const thistype &src) { *static_cast<basetype *>(this) = src; m_device_name = src.m_device_name; return *this; }
// provide additional constructors that take a device name string
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname) : basetype(funcptr, name, (_FunctionClass *)nullptr), device_delegate_helper(devname) { }
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname, _FunctionClass *object) : basetype(funcptr, name, (_FunctionClass *)nullptr), device_delegate_helper(devname) { }
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, const char *devname, _FunctionClass *) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::const_member_func_type funcptr, const char *name, const char *devname) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::const_member_func_type funcptr, const char *name, const char *devname, _FunctionClass *) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
#ifdef USE_STATIC_DELEGATE
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_func_type funcptr, const char *name, const char *devname, _FunctionClass *object) : basetype(funcptr, name, (_FunctionClass *)nullptr), device_delegate_helper(devname) { }
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_ref_func_type funcptr, const char *name, const char *devname, _FunctionClass *object) : basetype(funcptr, name, (_FunctionClass *)nullptr), device_delegate_helper(devname) { }
device_delegate(typename basetype::template traits<device_t>::static_func_type funcptr, const char *name) : basetype(funcptr, name, (device_t *)nullptr), device_delegate_helper(nullptr) { }
device_delegate(typename basetype::template traits<device_t>::static_ref_func_type funcptr, const char *name) : basetype(funcptr, name, (device_t *)nullptr), device_delegate_helper(nullptr) { }
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_func_type funcptr, const char *name, const char *devname, _FunctionClass *) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
template<class _FunctionClass> device_delegate(typename basetype::template traits<_FunctionClass>::static_ref_func_type funcptr, const char *name, const char *devname, _FunctionClass *) : basetype(funcptr, name, static_cast<_FunctionClass *>(nullptr)), device_delegate_helper(devname) { }
device_delegate(typename basetype::template traits<device_t>::static_func_type funcptr, const char *name) : basetype(funcptr, name, static_cast<device_t *>(nullptr)), device_delegate_helper(nullptr) { }
device_delegate(typename basetype::template traits<device_t>::static_ref_func_type funcptr, const char *name) : basetype(funcptr, name, static_cast<device_t *>(nullptr)), device_delegate_helper(nullptr) { }
#endif
// and constructors that provide a search root

View File

@ -79,11 +79,11 @@
#define __DELEGATE_H__
// standard C++ includes
#include <exception>
#include <cstring>
#include <typeinfo>
#include <utility>
#include <cstring>
#include <cstdint>
#include <functional>
//**************************************************************************
// MACROS
@ -134,7 +134,7 @@
//**************************************************************************
// generic function type
typedef void (*delegate_generic_function)();
using delegate_generic_function = void(*)();
// ======================> generic_class
@ -180,9 +180,10 @@ public:
template<typename _ClassType, typename _ReturnType, typename... Params>
struct delegate_traits
{
typedef _ReturnType (*static_func_type)(_ClassType *, Params...);
typedef _ReturnType (*static_ref_func_type)(_ClassType &, Params...);
typedef _ReturnType (_ClassType::*member_func_type)(Params...);
using static_func_type = _ReturnType(*)(_ClassType *, Params...);
using static_ref_func_type = _ReturnType(*)(_ClassType &, Params...);
using member_func_type = _ReturnType(_ClassType::*)(Params...);
using const_member_func_type = _ReturnType(_ClassType::*)(Params...) const;
};
@ -247,7 +248,7 @@ private:
static _ReturnType method_stub(delegate_generic_class *object, Params ... args)
{
delegate_mfp *_this = reinterpret_cast<delegate_mfp *>(object);
typedef _ReturnType (_FunctionClass::*mfptype)(Params...);
using mfptype = _ReturnType(_FunctionClass::*)(Params...);
mfptype &mfp = *reinterpret_cast<mfptype *>(&_this->m_rawdata);
return (reinterpret_cast<_FunctionClass *>(_this->m_realobject)->*mfp)(std::forward<Params>(args)...);
}
@ -256,7 +257,7 @@ private:
// helper to convert a function of a given type to a generic function, forcing template
// instantiation to match the source type
template <typename _SourceType>
delegate_generic_function make_generic(_SourceType funcptr)
static delegate_generic_function make_generic(_SourceType funcptr)
{
return reinterpret_cast<delegate_generic_function>(funcptr);
}
@ -310,7 +311,7 @@ public:
bool isnull() const { return (m_function == 0 && m_this_delta==0); }
// getters
delegate_generic_class *real_object(delegate_generic_class *original) const { return original; }
static delegate_generic_class *real_object(delegate_generic_class *original) { return original; }
// binding helper
template<typename _FunctionType>
@ -341,11 +342,15 @@ class delegate_mfp
public:
// default constructor
delegate_mfp()
: m_function(0) { }
: m_function(0), m_this_delta(0), m_dummy1(0), m_dummy2(0), m_size(0)
{
}
// copy constructor
delegate_mfp(const delegate_mfp &src)
: m_function(src.m_function) { }
: m_function(src.m_function), m_this_delta(0), m_dummy1(0), m_dummy2(0), m_size(0)
{
}
// construct from any member function pointer
template<typename _MemberFunctionType, class _MemberFunctionClass, typename _ReturnType, typename _StaticFunctionType>
@ -361,7 +366,7 @@ public:
bool isnull() const { return (m_function == 0); }
// getters
delegate_generic_class *real_object(delegate_generic_class *original) const { return original; }
static delegate_generic_class *real_object(delegate_generic_class *original) { return original; }
// binding helper
template<typename _FunctionType>
@ -407,19 +412,22 @@ public:
template<class _FunctionClass>
struct traits
{
typedef typename delegate_traits<_FunctionClass, _ReturnType, Params...>::member_func_type member_func_type;
typedef typename delegate_traits<_FunctionClass, _ReturnType, Params...>::static_func_type static_func_type;
typedef typename delegate_traits<_FunctionClass, _ReturnType, Params...>::static_ref_func_type static_ref_func_type;
using member_func_type = typename delegate_traits<_FunctionClass, _ReturnType, Params...>::member_func_type;
using const_member_func_type = typename delegate_traits<_FunctionClass, _ReturnType, Params...>::const_member_func_type;
using static_func_type = typename delegate_traits<_FunctionClass, _ReturnType, Params...>::static_func_type;
using static_ref_func_type = typename delegate_traits<_FunctionClass, _ReturnType, Params...>::static_ref_func_type;
};
typedef typename traits<delegate_generic_class>::static_func_type generic_static_func;
typedef MEMBER_ABI generic_static_func generic_member_func;
using functional_type = std::function<_ReturnType(Params...)>;
using generic_static_func = typename traits<delegate_generic_class>::static_func_type;
using generic_member_func = MEMBER_ABI generic_static_func;
// generic constructor
delegate_base()
: m_function(nullptr),
m_object(nullptr),
m_name(nullptr),
m_latebinder(nullptr),
m_raw_function(nullptr) { }
m_raw_function(nullptr),
m_std_func(nullptr){ }
// copy constructor
delegate_base(const delegate_base &src)
@ -428,7 +436,8 @@ public:
m_name(src.m_name),
m_latebinder(src.m_latebinder),
m_raw_function(src.m_raw_function),
m_raw_mfp(src.m_raw_mfp)
m_raw_mfp(src.m_raw_mfp),
m_std_func(src.m_std_func)
{
bind(src.object());
}
@ -440,7 +449,8 @@ public:
m_name(src.m_name),
m_latebinder(src.m_latebinder),
m_raw_function(src.m_raw_function),
m_raw_mfp(src.m_raw_mfp)
m_raw_mfp(src.m_raw_mfp),
m_std_func(src.m_std_func)
{
late_bind(object);
}
@ -453,7 +463,21 @@ public:
m_name(name),
m_latebinder(&late_bind_helper<_FunctionClass>),
m_raw_function(nullptr),
m_raw_mfp(funcptr, object, (_ReturnType *)nullptr, static_cast<generic_static_func>(nullptr))
m_raw_mfp(funcptr, object, static_cast<_ReturnType *>(nullptr), static_cast<generic_static_func>(nullptr)),
m_std_func(nullptr)
{
bind(reinterpret_cast<delegate_generic_class *>(object));
}
template<class _FunctionClass>
delegate_base(typename traits<_FunctionClass>::const_member_func_type funcptr, const char *name, _FunctionClass *object)
: m_function(nullptr),
m_object(nullptr),
m_name(name),
m_latebinder(&late_bind_helper<_FunctionClass>),
m_raw_function(nullptr),
m_raw_mfp(funcptr, object, static_cast<_ReturnType *>(nullptr), static_cast<generic_static_func>(nullptr)),
m_std_func(nullptr)
{
bind(reinterpret_cast<delegate_generic_class *>(object));
}
@ -465,7 +489,8 @@ public:
m_object(nullptr),
m_name(name),
m_latebinder(&late_bind_helper<_FunctionClass>),
m_raw_function(reinterpret_cast<generic_static_func>(funcptr))
m_raw_function(reinterpret_cast<generic_static_func>(funcptr)),
m_std_func(nullptr)
{
bind(reinterpret_cast<delegate_generic_class *>(object));
}
@ -477,11 +502,24 @@ public:
m_object(nullptr),
m_name(name),
m_latebinder(&late_bind_helper<_FunctionClass>),
m_raw_function(reinterpret_cast<generic_static_func>(funcptr))
m_raw_function(reinterpret_cast<generic_static_func>(funcptr)),
m_std_func(nullptr)
{
bind(reinterpret_cast<delegate_generic_class *>(object));
}
// construct from static reference function with object reference
delegate_base(functional_type funcptr, const char *name)
: m_function(nullptr),
m_object(nullptr),
m_name(name),
m_latebinder(nullptr),
m_raw_function(nullptr),
m_std_func(funcptr)
{
}
// copy operator
delegate_base &operator=(const delegate_base &src)
{
@ -493,6 +531,8 @@ public:
m_latebinder = src.m_latebinder;
m_raw_function = src.m_raw_function;
m_raw_mfp = src.m_raw_mfp;
m_std_func = src.m_std_func;
bind(src.object());
}
return *this;
@ -501,24 +541,26 @@ public:
// comparison helper
bool operator==(const delegate_base &rhs) const
{
return (m_raw_function == rhs.m_raw_function && object() == rhs.object() && m_raw_mfp == rhs.m_raw_mfp);
return (m_raw_function == rhs.m_raw_function && object() == rhs.object() && m_raw_mfp == rhs.m_raw_mfp && m_std_func.target_type().name() == rhs.m_std_func.target_type().name());
}
#define DELEGATE_CALL(x) \
if (is_mfp() && (HAS_DIFFERENT_ABI)) \
return (*reinterpret_cast<generic_member_func>(m_function)) x; \
else \
return (*m_function) x;
// call the function
_ReturnType operator()(Params... args) const { DELEGATE_CALL((m_object, std::forward<Params>(args)...)); }
_ReturnType operator()(Params... args) const {
if (is_mfp() && (HAS_DIFFERENT_ABI))
return (*reinterpret_cast<generic_member_func>(m_function)) (m_object, std::forward<Params>(args)...);
else if (m_std_func)
return m_std_func(std::forward<Params>(args)...);
else
return (*m_function) (m_object, std::forward<Params>(args)...);
}
// getters
bool has_object() const { return (object() != nullptr); }
bool has_object() const { return (object() != nullptr) || (m_std_func); }
const char *name() const { return m_name; }
// helpers
bool isnull() const { return (m_raw_function == nullptr && m_raw_mfp.isnull()); }
bool isnull() const { return (m_raw_function == nullptr && m_raw_mfp.isnull() && !m_std_func); }
bool is_mfp() const { return !m_raw_mfp.isnull(); }
// late binding
@ -529,7 +571,7 @@ protected:
delegate_generic_class *object() const { return is_mfp() ? m_raw_mfp.real_object(m_object) : m_object; }
// late binding function
typedef delegate_generic_class *(*late_bind_func)(delegate_late_bind &object);
using late_bind_func = delegate_generic_class*(*)(delegate_late_bind &object);
// late binding helper
template<class _FunctionClass>
@ -559,6 +601,7 @@ protected:
late_bind_func m_latebinder; // late binding helper
generic_static_func m_raw_function; // raw static function pointer
delegate_mfp m_raw_mfp; // raw member function pointer
functional_type m_std_func; // std::function pointer
};
@ -574,7 +617,7 @@ class delegate;
template<typename _ReturnType, typename... Params>
class delegate<_ReturnType (Params...)> : public delegate_base<_ReturnType, Params...>
{
typedef delegate_base<_ReturnType, Params...> basetype;
using basetype = delegate_base<_ReturnType, Params...>;
public:
// create a standard set of constructors
@ -582,6 +625,8 @@ public:
delegate(const basetype &src) : basetype(src) { }
delegate(const basetype &src, delegate_late_bind &object) : basetype(src, object) { }
template<class _FunctionClass> delegate(typename basetype::template traits<_FunctionClass>::member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
template<class _FunctionClass> delegate(typename basetype::template traits<_FunctionClass>::const_member_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
delegate(std::function<_ReturnType(Params...)> funcptr) : basetype(funcptr, "") { }
#ifdef USE_STATIC_DELEGATE
template<class _FunctionClass> delegate(typename basetype::template traits<_FunctionClass>::static_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }
template<class _FunctionClass> delegate(typename basetype::template traits<_FunctionClass>::static_ref_func_type funcptr, const char *name, _FunctionClass *object) : basetype(funcptr, name, object) { }

View File

@ -105,8 +105,6 @@ public:
uint8_t m_last_coin;
DECLARE_WRITE8_MEMBER(statriv2_videoram_w);
DECLARE_READ8_MEMBER(question_data_r);
DECLARE_READ8_MEMBER(laserdisc_io_r);
DECLARE_WRITE8_MEMBER(laserdisc_io_w);
DECLARE_CUSTOM_INPUT_MEMBER(latched_coin_r);
DECLARE_WRITE8_MEMBER(ppi_portc_hi_w);
DECLARE_DRIVER_INIT(addr_xlh);
@ -1141,25 +1139,23 @@ DRIVER_INIT_MEMBER(statriv2_state,addr_lmhe)
DRIVER_INIT_CALL(addr_lmh);
}
READ8_MEMBER(statriv2_state::laserdisc_io_r)
{
uint8_t result = 0x00;
if (offset == 1)
result = 0x18;
osd_printf_debug("%s:ld read ($%02X) = %02X\n", machine().describe_context(), 0x28 + offset, result);
return result;
}
WRITE8_MEMBER(statriv2_state::laserdisc_io_w)
{
osd_printf_debug("%s:ld write ($%02X) = %02X\n", machine().describe_context(), 0x28 + offset, data);
}
DRIVER_INIT_MEMBER(statriv2_state,laserdisc)
{
address_space &iospace = m_maincpu->space(AS_IO);
iospace.install_readwrite_handler(0x28, 0x2b, read8_delegate(FUNC(statriv2_state::laserdisc_io_r), this), write8_delegate(FUNC(statriv2_state::laserdisc_io_w), this));
iospace.install_readwrite_handler(0x28, 0x2b,
read8_delegate([this](address_space &space, offs_t offset, uint8_t mem_mask) -> uint8_t
{
uint8_t result = 0x00;
if (offset == 1)
result = 0x18;
osd_printf_debug("%s:ld read ($%02X) = %02X\n", machine().describe_context(), 0x28 + offset, result);
return result;
}),
write8_delegate([this](address_space &space, offs_t offset, uint8_t data, uint8_t mem_mask)
{
osd_printf_debug("%s:ld write ($%02X) = %02X\n", machine().describe_context(), 0x28 + offset, data);
})
);
}