mirror of
https://github.com/holub/mame
synced 2025-06-22 20:38:50 +03:00
Netlist refactoring:
- Refactored netlist pmf code. - Small optimization for diode calculations. - Minor refactoring across the board. (nw)
This commit is contained in:
parent
093bda0193
commit
25152bd69a
@ -23,6 +23,7 @@ generic_diode::generic_diode(device_t &dev, pstring name)
|
|||||||
, m_Id(dev, name + ".m_Id", 0.0)
|
, m_Id(dev, name + ".m_Id", 0.0)
|
||||||
, m_G(dev, name + ".m_G", 1e-15)
|
, m_G(dev, name + ".m_G", 1e-15)
|
||||||
, m_Vt(0.0)
|
, m_Vt(0.0)
|
||||||
|
, m_Vmin(0.0)
|
||||||
, m_Is(0.0)
|
, m_Is(0.0)
|
||||||
, m_n(0.0)
|
, m_n(0.0)
|
||||||
, m_gmin(1e-15)
|
, m_gmin(1e-15)
|
||||||
@ -40,6 +41,7 @@ void generic_diode::set_param(const nl_double Is, const nl_double n, nl_double g
|
|||||||
m_gmin = gmin;
|
m_gmin = gmin;
|
||||||
|
|
||||||
m_Vt = 0.0258 * m_n;
|
m_Vt = 0.0258 * m_n;
|
||||||
|
m_Vmin = -5.0 * m_Vt;
|
||||||
|
|
||||||
m_Vcrit = m_Vt * std::log(m_Vt / m_Is / csqrt2);
|
m_Vcrit = m_Vt * std::log(m_Vt / m_Is / csqrt2);
|
||||||
m_VtInv = 1.0 / m_Vt;
|
m_VtInv = 1.0 / m_Vt;
|
||||||
@ -47,8 +49,7 @@ void generic_diode::set_param(const nl_double Is, const nl_double n, nl_double g
|
|||||||
|
|
||||||
void generic_diode::update_diode(const nl_double nVd)
|
void generic_diode::update_diode(const nl_double nVd)
|
||||||
{
|
{
|
||||||
#if 1
|
if (nVd < m_Vmin)
|
||||||
if (nVd < NL_FCONST(-5.0) * m_Vt)
|
|
||||||
{
|
{
|
||||||
m_Vd = nVd;
|
m_Vd = nVd;
|
||||||
m_G = m_gmin;
|
m_G = m_gmin;
|
||||||
@ -58,29 +59,19 @@ void generic_diode::update_diode(const nl_double nVd)
|
|||||||
{
|
{
|
||||||
m_Vd = nVd;
|
m_Vd = nVd;
|
||||||
//m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
|
//m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
|
||||||
const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
|
//const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv);
|
||||||
m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
|
const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv);
|
||||||
m_G = m_Is * m_VtInv * eVDVt + m_gmin;
|
m_Id = IseVDVt - m_Is;
|
||||||
|
m_G = IseVDVt * m_VtInv + m_gmin;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if 1
|
const double a = std::max((nVd - m_Vd) * m_VtInv, NL_FCONST(-0.99));
|
||||||
const nl_double a = std::max((nVd - m_Vd) * m_VtInv, NL_FCONST(-0.99));
|
|
||||||
m_Vd = m_Vd + std::log1p(a) * m_Vt;
|
m_Vd = m_Vd + std::log1p(a) * m_Vt;
|
||||||
#else
|
const double IseVDVt = m_Is * std::exp(m_Vd * m_VtInv);
|
||||||
m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
|
m_Id = IseVDVt - m_Is;
|
||||||
#endif
|
m_G = IseVDVt * m_VtInv + m_gmin;
|
||||||
const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
|
|
||||||
m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
|
|
||||||
|
|
||||||
m_G = m_Is * m_VtInv * eVDVt + m_gmin;
|
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
m_Vd = m_Vd + 20.0 * m_Vt * std::tanh((nVd - m_Vd) / 20.0 / m_Vt);
|
|
||||||
const nl_double eVDVt = std::exp(m_Vd * m_VtInv);
|
|
||||||
m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
|
|
||||||
m_G = m_Is * m_VtInv * eVDVt + m_gmin;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------
|
||||||
|
@ -338,29 +338,30 @@ class generic_diode
|
|||||||
public:
|
public:
|
||||||
generic_diode(device_t &dev, pstring name);
|
generic_diode(device_t &dev, pstring name);
|
||||||
|
|
||||||
void update_diode(const nl_double nVd);
|
void update_diode(const double nVd);
|
||||||
|
|
||||||
void set_param(const nl_double Is, const nl_double n, nl_double gmin);
|
void set_param(const double Is, const double n, double gmin);
|
||||||
|
|
||||||
inline nl_double I() const { return m_Id; }
|
inline double I() const { return m_Id; }
|
||||||
inline nl_double G() const { return m_G; }
|
inline double G() const { return m_G; }
|
||||||
inline nl_double Ieq() const { return (m_Id - m_Vd * m_G); }
|
inline double Ieq() const { return (m_Id - m_Vd * m_G); }
|
||||||
inline nl_double Vd() const { return m_Vd; }
|
inline double Vd() const { return m_Vd; }
|
||||||
|
|
||||||
/* owning object must save those ... */
|
/* owning object must save those ... */
|
||||||
|
|
||||||
private:
|
private:
|
||||||
state_var<nl_double> m_Vd;
|
state_var<double> m_Vd;
|
||||||
state_var<nl_double> m_Id;
|
state_var<double> m_Id;
|
||||||
state_var<nl_double> m_G;
|
state_var<double> m_G;
|
||||||
|
|
||||||
nl_double m_Vt;
|
double m_Vt;
|
||||||
nl_double m_Is;
|
double m_Vmin;
|
||||||
nl_double m_n;
|
double m_Is;
|
||||||
nl_double m_gmin;
|
double m_n;
|
||||||
|
double m_gmin;
|
||||||
|
|
||||||
nl_double m_VtInv;
|
double m_VtInv;
|
||||||
nl_double m_Vcrit;
|
double m_Vcrit;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! Class representing the diode model paramers.
|
/*! Class representing the diode model paramers.
|
||||||
|
@ -578,7 +578,7 @@ core_device_t::core_device_t(netlist_t &owner, const pstring &name)
|
|||||||
, logic_family_t()
|
, logic_family_t()
|
||||||
, netlist_ref(owner)
|
, netlist_ref(owner)
|
||||||
, m_hint_deactivate(false)
|
, m_hint_deactivate(false)
|
||||||
#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
|
#if (!NL_USE_PMF_VIRTUAL)
|
||||||
, m_static_update()
|
, m_static_update()
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -591,7 +591,7 @@ core_device_t::core_device_t(core_device_t &owner, const pstring &name)
|
|||||||
, logic_family_t()
|
, logic_family_t()
|
||||||
, netlist_ref(owner.netlist())
|
, netlist_ref(owner.netlist())
|
||||||
, m_hint_deactivate(false)
|
, m_hint_deactivate(false)
|
||||||
#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
|
#if (!NL_USE_PMF_VIRTUAL)
|
||||||
, m_static_update()
|
, m_static_update()
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
@ -607,14 +607,8 @@ core_device_t::~core_device_t()
|
|||||||
|
|
||||||
void core_device_t::set_delegate_pointer()
|
void core_device_t::set_delegate_pointer()
|
||||||
{
|
{
|
||||||
#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
|
#if (!NL_USE_PMF_VIRTUAL)
|
||||||
void (core_device_t::* pFunc)() = &core_device_t::update;
|
m_static_update.set_base(&core_device_t::update, this);
|
||||||
m_static_update = pFunc;
|
|
||||||
#elif (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV)
|
|
||||||
void (core_device_t::* pFunc)() = &core_device_t::update;
|
|
||||||
m_static_update = reinterpret_cast<net_update_delegate>((this->*pFunc));
|
|
||||||
#elif (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL)
|
|
||||||
m_static_update = plib::mfp::get_mfp<net_update_delegate>(&core_device_t::update, this);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1082,12 +1082,10 @@ namespace netlist
|
|||||||
|
|
||||||
void do_update() NL_NOEXCEPT
|
void do_update() NL_NOEXCEPT
|
||||||
{
|
{
|
||||||
#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
|
#if (NL_USE_PMF_VIRTUAL)
|
||||||
(this->*m_static_update)();
|
update();
|
||||||
#elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL))
|
|
||||||
m_static_update(this);
|
|
||||||
#else
|
#else
|
||||||
update();
|
m_static_update.call(this);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1104,14 +1102,9 @@ namespace netlist
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_hint_deactivate;
|
bool m_hint_deactivate;
|
||||||
#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
|
|
||||||
typedef void (core_device_t::*net_update_delegate)();
|
|
||||||
#elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL))
|
|
||||||
using net_update_delegate = MEMBER_ABI void (*)(core_device_t *);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
|
#if (!NL_USE_PMF_VIRTUAL)
|
||||||
net_update_delegate m_static_update;
|
plib::pmfp_base<void> m_static_update;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1277,11 +1270,11 @@ namespace netlist
|
|||||||
|
|
||||||
template<typename O, typename C> void save(O &owner, C &state, const pstring &stname)
|
template<typename O, typename C> void save(O &owner, C &state, const pstring &stname)
|
||||||
{
|
{
|
||||||
this->state().save_item(static_cast<void *>(&owner), state, pstring::from_utf8(owner.name()) + pstring(".") + stname);
|
this->state().save_item(static_cast<void *>(&owner), state, from_utf8(owner.name()) + pstring(".") + stname);
|
||||||
}
|
}
|
||||||
template<typename O, typename C> void save(O &owner, C *state, const pstring &stname, const std::size_t count)
|
template<typename O, typename C> void save(O &owner, C *state, const pstring &stname, const std::size_t count)
|
||||||
{
|
{
|
||||||
this->state().save_state_ptr(static_cast<void *>(&owner), pstring::from_utf8(owner.name()) + pstring(".") + stname, plib::state_manager_t::datatype_f<C>::f(), count, state);
|
this->state().save_state_ptr(static_cast<void *>(&owner), from_utf8(owner.name()) + pstring(".") + stname, plib::state_manager_t::datatype_f<C>::f(), count, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rebuild_lists(); /* must be called after post_load ! */
|
void rebuild_lists(); /* must be called after post_load ! */
|
||||||
@ -1299,6 +1292,10 @@ namespace netlist
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/* helper for save above */
|
||||||
|
static pstring from_utf8(const char *c) { return pstring(c, pstring::UTF8); }
|
||||||
|
static pstring from_utf8(const pstring &c) { return c; }
|
||||||
|
|
||||||
core_device_t *pget_single_device(const pstring classname, bool (*cc)(core_device_t *));
|
core_device_t *pget_single_device(const pstring classname, bool (*cc)(core_device_t *));
|
||||||
|
|
||||||
/* mostly rw */
|
/* mostly rw */
|
||||||
|
@ -18,59 +18,6 @@
|
|||||||
// SETUP
|
// SETUP
|
||||||
//============================================================
|
//============================================================
|
||||||
|
|
||||||
/*
|
|
||||||
* The following options determine how object::update is called.
|
|
||||||
* NL_PMF_TYPE_VIRTUAL
|
|
||||||
* Use stock virtual call
|
|
||||||
*
|
|
||||||
* NL_PMF_TYPE_GNUC_PMF
|
|
||||||
* Use standard pointer to member function syntax
|
|
||||||
*
|
|
||||||
* NL_PMF_TYPE_GNUC_PMF_CONV
|
|
||||||
* Use gnu extension and convert the pmf to a function pointer.
|
|
||||||
* This is not standard compliant and needs
|
|
||||||
* -Wno-pmf-conversions to compile.
|
|
||||||
*
|
|
||||||
* NL_PMF_TYPE_INTERNAL
|
|
||||||
* Use the same approach as MAME for deriving the function pointer.
|
|
||||||
* This is compiler-dependant as well
|
|
||||||
*
|
|
||||||
* Benchmarks for ./nltool -c run -f src/mame/drivers/nl_pong.c -t 10 -n pong_fast
|
|
||||||
*
|
|
||||||
* NL_PMF_TYPE_INTERNAL: 215%
|
|
||||||
* NL_PMF_TYPE_GNUC_PMF: 163%
|
|
||||||
* NL_PMF_TYPE_GNUC_PMF_CONV: 215%
|
|
||||||
* NL_PMF_TYPE_VIRTUAL: 213%
|
|
||||||
*
|
|
||||||
* The whole exercise was done to avoid virtual calls. In prior versions of
|
|
||||||
* netlist, the INTERNAL and GNUC_PMF_CONV approach provided significant improvement.
|
|
||||||
* Since than, was removed from functions declared as virtual.
|
|
||||||
* This may explain that the recent benchmarks show no difference at all.
|
|
||||||
*
|
|
||||||
* Disappointing is the GNUC_PMF performance.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This will be autodetected
|
|
||||||
// #define NL_PMF_TYPE 0
|
|
||||||
|
|
||||||
#define NL_PMF_TYPE_VIRTUAL 0
|
|
||||||
#define NL_PMF_TYPE_GNUC_PMF 1
|
|
||||||
#define NL_PMF_TYPE_GNUC_PMF_CONV 2
|
|
||||||
#define NL_PMF_TYPE_INTERNAL 3
|
|
||||||
|
|
||||||
#ifndef NL_PMF_TYPE
|
|
||||||
#if PHAS_PMF_INTERNAL
|
|
||||||
#define NL_PMF_TYPE NL_PMF_TYPE_INTERNAL
|
|
||||||
#else
|
|
||||||
#define NL_PMF_TYPE NL_PMF_TYPE_VIRTUAL
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV)
|
|
||||||
#pragma GCC diagnostic ignored "-Wpmf-conversions"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// GENERAL
|
// GENERAL
|
||||||
@ -156,6 +103,20 @@ using nperfcount_t = plib::chrono::counter<false>;
|
|||||||
#define NL_FCONST(x) x
|
#define NL_FCONST(x) x
|
||||||
using nl_double = double;
|
using nl_double = double;
|
||||||
|
|
||||||
|
/* The following option determines how object::update is called.
|
||||||
|
* If set to 1, a virtual call is used. If it is left undefined, the best
|
||||||
|
* approach will be automatically selected.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//#define NL_USE_PMF_VIRTUAL 1
|
||||||
|
|
||||||
|
#ifndef NL_USE_PMF_VIRTUAL
|
||||||
|
#if PPMF_TYPE == PPMF_TYPE_PMF
|
||||||
|
#define NL_USE_PMF_VIRTUAL 1
|
||||||
|
#else
|
||||||
|
#define NL_USE_PMF_VIRTUAL 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// WARNINGS
|
// WARNINGS
|
||||||
|
@ -63,6 +63,42 @@ typedef __int128_t INT128;
|
|||||||
// cut down delegate implementation
|
// cut down delegate implementation
|
||||||
//============================================================
|
//============================================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* NL_PMF_TYPE_GNUC_PMF
|
||||||
|
* Use standard pointer to member function syntax C++11
|
||||||
|
*
|
||||||
|
* NL_PMF_TYPE_GNUC_PMF_CONV
|
||||||
|
* Use gnu extension and convert the pmf to a function pointer.
|
||||||
|
* This is not standard compliant and needs
|
||||||
|
* -Wno-pmf-conversions to compile.
|
||||||
|
*
|
||||||
|
* NL_PMF_TYPE_INTERNAL
|
||||||
|
* Use the same approach as MAME for deriving the function pointer.
|
||||||
|
* This is compiler-dependent as well
|
||||||
|
*
|
||||||
|
* Benchmarks for ./nltool -c run -f src/mame/machine/nl_pong.cpp -t 10 -n pong_fast
|
||||||
|
*
|
||||||
|
* NL_PMF_TYPE_INTERNAL: 215% 215%
|
||||||
|
* NL_PMF_TYPE_GNUC_PMF: 163% 196%
|
||||||
|
* NL_PMF_TYPE_GNUC_PMF_CONV: 215% 215%
|
||||||
|
* NL_PMF_TYPE_VIRTUAL: 213% 209%
|
||||||
|
*
|
||||||
|
* The whole exercise was done to avoid virtual calls. In prior versions of
|
||||||
|
* netlist, the INTERNAL and GNUC_PMF_CONV approach provided significant improvement.
|
||||||
|
* Since than, "hot" was removed from functions declared as virtual.
|
||||||
|
* This may explain that the recent benchmarks show no difference at all.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This will be autodetected
|
||||||
|
// #define PPMF_TYPE 1
|
||||||
|
|
||||||
|
#define PPMF_TYPE_PMF 0
|
||||||
|
#define PPMF_TYPE_GNUC_PMF_CONV 1
|
||||||
|
#define PPMF_TYPE_INTERNAL 2
|
||||||
|
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
/* does not work in versions over 4.7.x of 32bit MINGW */
|
/* does not work in versions over 4.7.x of 32bit MINGW */
|
||||||
#if defined(__MINGW32__) && !defined(__x86_64) && defined(__i386__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)))
|
#if defined(__MINGW32__) && !defined(__x86_64) && defined(__i386__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)))
|
||||||
@ -87,6 +123,18 @@ typedef __int128_t INT128;
|
|||||||
#define MEMBER_ABI
|
#define MEMBER_ABI
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef PPMF_TYPE
|
||||||
|
#if PHAS_PMF_INTERNAL
|
||||||
|
#define PPMF_TYPE PPMF_TYPE_INTERNAL
|
||||||
|
#else
|
||||||
|
#define PPMF_TYPE PPMF_TYPE_PMF
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV)
|
||||||
|
#pragma GCC diagnostic ignored "-Wpmf-conversions"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace plib {
|
namespace plib {
|
||||||
/*
|
/*
|
||||||
* The following class was derived from the MAME delegate.h code.
|
* The following class was derived from the MAME delegate.h code.
|
||||||
@ -108,18 +156,13 @@ namespace plib {
|
|||||||
*reinterpret_cast<MemberFunctionType *>(this) = mftp;
|
*reinterpret_cast<MemberFunctionType *>(this) = mftp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// binding helper
|
|
||||||
template<typename FunctionType, typename ObjectType>
|
|
||||||
FunctionType update_after_bind(ObjectType *object)
|
|
||||||
{
|
|
||||||
return reinterpret_cast<FunctionType>(
|
|
||||||
convert_to_generic(reinterpret_cast<generic_class *>(object)));
|
|
||||||
}
|
|
||||||
template<typename FunctionType, typename MemberFunctionType, typename ObjectType>
|
template<typename FunctionType, typename MemberFunctionType, typename ObjectType>
|
||||||
static FunctionType get_mfp(MemberFunctionType mftp, ObjectType *object)
|
static FunctionType get_mfp(MemberFunctionType mftp, ObjectType *object)
|
||||||
{
|
{
|
||||||
mfp mfpo(mftp);
|
mfp mfpo(mftp);
|
||||||
return mfpo.update_after_bind<FunctionType>(object);
|
//return mfpo.update_after_bind<FunctionType>(object);
|
||||||
|
return reinterpret_cast<FunctionType>(
|
||||||
|
mfpo.convert_to_generic(reinterpret_cast<generic_class *>(object)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -144,9 +187,89 @@ namespace plib {
|
|||||||
// if odd, it's the byte offset into the vtable
|
// if odd, it's the byte offset into the vtable
|
||||||
int m_this_delta; // delta to apply to the 'this' pointer
|
int m_this_delta; // delta to apply to the 'this' pointer
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (PPMF_TYPE == PPMF_TYPE_PMF)
|
||||||
|
template<typename R, typename... Targs>
|
||||||
|
class pmfp_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class generic_class;
|
||||||
|
using generic_function = R (generic_class::*)(Targs...);
|
||||||
|
pmfp_base() : m_func(nullptr) {}
|
||||||
|
|
||||||
|
template<typename MemberFunctionType, typename O>
|
||||||
|
void set_base(MemberFunctionType mftp, O *object)
|
||||||
|
{
|
||||||
|
using function_ptr = R (O::*)(Targs...);
|
||||||
|
function_ptr t = mftp;
|
||||||
|
m_func = reinterpret_cast<generic_function>(t);
|
||||||
|
}
|
||||||
|
template<typename O>
|
||||||
|
inline R call(O *obj, Targs... args) const
|
||||||
|
{
|
||||||
|
using function_ptr = R (O::*)(Targs...);
|
||||||
|
function_ptr t = reinterpret_cast<function_ptr>(m_func);
|
||||||
|
return (obj->*t)(std::forward<Targs>(args)...);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
generic_function m_func;
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif ((PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV) || (PPMF_TYPE == PPMF_TYPE_INTERNAL))
|
||||||
|
template<typename R, typename... Targs>
|
||||||
|
class pmfp_base
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using generic_function = void (*)();
|
||||||
|
|
||||||
|
pmfp_base() : m_func(nullptr) {}
|
||||||
|
|
||||||
|
template<typename MemberFunctionType, typename O>
|
||||||
|
void set_base(MemberFunctionType mftp, O *object)
|
||||||
|
{
|
||||||
|
#if (PPMF_TYPE == PPMF_TYPE_INTERNAL)
|
||||||
|
using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args);
|
||||||
|
m_func = reinterpret_cast<generic_function>(plib::mfp::get_mfp<function_ptr>(mftp, object));
|
||||||
|
#elif (PPMF_TYPE == PPMF_TYPE_GNUC_PMF_CONV)
|
||||||
|
R (O::* pFunc)(Targs...) = mftp;
|
||||||
|
m_func = reinterpret_cast<generic_function>((object->*pFunc));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
template<typename O>
|
||||||
|
inline R call(O *obj, Targs... args) const
|
||||||
|
{
|
||||||
|
using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args);
|
||||||
|
return (*reinterpret_cast<function_ptr>(m_func))(obj, std::forward<Targs>(args)...);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
generic_function m_func;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<typename R, typename... Targs>
|
||||||
|
class pmfp : public pmfp_base<R, Targs...>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class generic_class;
|
||||||
|
pmfp() : pmfp_base<R, Targs...>(), m_obj(nullptr) {}
|
||||||
|
|
||||||
|
template<typename MemberFunctionType, typename O>
|
||||||
|
void set(MemberFunctionType mftp, O *object)
|
||||||
|
{
|
||||||
|
this->set_base(mftp, object);
|
||||||
|
m_obj = reinterpret_cast<generic_class *>(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline R operator()(Targs... args) const
|
||||||
|
{
|
||||||
|
return this->call(m_obj, std::forward<Targs>(args)...);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
generic_class *m_obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* PCONFIG_H_ */
|
#endif /* PCONFIG_H_ */
|
||||||
|
@ -81,7 +81,7 @@ void pfunction::compile_postfix(const std::vector<pstring> &inputs,
|
|||||||
throw plib::pexception(plib::pfmt("nld_function: stack count different to one on <{2}>")(expr));
|
throw plib::pexception(plib::pfmt("nld_function: stack count different to one on <{2}>")(expr));
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_prio(pstring v)
|
static int get_prio(pstring v)
|
||||||
{
|
{
|
||||||
if (v == "(" or v == ")")
|
if (v == "(" or v == ")")
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -371,7 +371,7 @@ void pstringbuffer::pcat(const pstring &s)
|
|||||||
* This improves startup performance by 30%.
|
* This improves startup performance by 30%.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if 0
|
#if 1
|
||||||
|
|
||||||
static std::stack<pstr_t *> *stk = nullptr;
|
static std::stack<pstr_t *> *stk = nullptr;
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
struct pstr_t
|
struct pstr_t
|
||||||
{
|
{
|
||||||
pstr_t(const int alen) { init(alen); }
|
pstr_t(const std::size_t alen) { init(alen); }
|
||||||
void init(const std::size_t alen)
|
void init(const std::size_t alen)
|
||||||
{
|
{
|
||||||
m_ref_count = 1;
|
m_ref_count = 1;
|
||||||
@ -169,13 +169,6 @@ public:
|
|||||||
|
|
||||||
const pstring_t ucase() const;
|
const pstring_t ucase() const;
|
||||||
|
|
||||||
// FIXME: do something with encoding
|
|
||||||
// FIXME: belongs into derived class
|
|
||||||
// This is only used in state saving to support "owners" whose name() function
|
|
||||||
// returns char*.
|
|
||||||
static pstring_t from_utf8(const mem_t *c) { return pstring_t(c, UTF8); }
|
|
||||||
static pstring_t from_utf8(const pstring_t &c) { return c; }
|
|
||||||
|
|
||||||
static void resetmem();
|
static void resetmem();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -502,12 +502,30 @@ static const pstring pmf_verbose[] =
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct tt
|
||||||
|
{
|
||||||
|
void test(int a) {printf ("test :%d\n", a);}
|
||||||
|
int test1() { return 1;}
|
||||||
|
};
|
||||||
|
|
||||||
|
plib::pmfp<void, int> atest;
|
||||||
|
plib::pmfp<int> atest1;
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
tool_options_t opts;
|
tool_options_t opts;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
tt x;
|
||||||
|
|
||||||
|
atest.set(&tt::test, &x);
|
||||||
|
atest1.set(&tt::test1, &x);
|
||||||
|
|
||||||
|
atest(1);
|
||||||
|
int a = atest1();
|
||||||
|
|
||||||
|
printf("%d\n", a);
|
||||||
|
//return 1 ;
|
||||||
/* make SIGFPE actually deliver signals on supoorted platforms */
|
/* make SIGFPE actually deliver signals on supoorted platforms */
|
||||||
plib::fpsignalenabler::global_enable(true);
|
plib::fpsignalenabler::global_enable(true);
|
||||||
plib::fpsignalenabler sigen(plib::FP_ALL & ~plib::FP_INEXACT & ~plib::FP_UNDERFLOW);
|
plib::fpsignalenabler sigen(plib::FP_ALL & ~plib::FP_INEXACT & ~plib::FP_UNDERFLOW);
|
||||||
|
Loading…
Reference in New Issue
Block a user