mirror of
https://github.com/holub/mame
synced 2025-04-18 22:49:58 +03:00
Netlist: code maintenance and bug fixes. [Couriersud]
- optimized the core queue dispatching logic. Minor performance increase. - fixed a number of bugs in parray. Now parray<double, 0> will be purely dynamic allocation with the number of elements passed in the constructor. - Added noexpr where appropriate. - Simplified the queue Checked with gcc-7 (ubuntu), gcc-9, clang-10, macosx clang 10, mingw cross compile on linux.
This commit is contained in:
parent
88f544f02f
commit
e5cceda218
@ -1184,7 +1184,7 @@ ATTR_COLD void netlist_mame_device::device_pre_save()
|
||||
netlist().run_state_manager().pre_save();
|
||||
}
|
||||
|
||||
void netlist_mame_device::update_icount(netlist::netlist_time time)
|
||||
void netlist_mame_device::update_icount(netlist::netlist_time time) noexcept
|
||||
{
|
||||
const netlist::netlist_time newt(time);
|
||||
const netlist::netlist_time delta(newt - m_old + m_rem);
|
||||
@ -1194,7 +1194,7 @@ void netlist_mame_device::update_icount(netlist::netlist_time time)
|
||||
m_icount -= d;
|
||||
}
|
||||
|
||||
void netlist_mame_device::check_mame_abort_slice()
|
||||
void netlist_mame_device::check_mame_abort_slice() noexcept
|
||||
{
|
||||
if (m_icount <= 0)
|
||||
netlist().abort_current_queue_slice();
|
||||
|
@ -72,11 +72,11 @@ public:
|
||||
|
||||
void set_setup_func(func_type &&func) { m_setup_func = std::move(func); }
|
||||
|
||||
ATTR_HOT inline netlist::setup_t &setup();
|
||||
ATTR_HOT inline netlist_mame_t &netlist() { return *m_netlist; }
|
||||
netlist::setup_t &setup();
|
||||
netlist_mame_t &netlist() noexcept { return *m_netlist; }
|
||||
|
||||
ATTR_HOT void update_icount(netlist::netlist_time time);
|
||||
ATTR_HOT void check_mame_abort_slice();
|
||||
void update_icount(netlist::netlist_time time) noexcept;
|
||||
void check_mame_abort_slice() noexcept;
|
||||
|
||||
static void register_memregion_source(netlist::nlparse_t &setup, device_t &dev, const char *name);
|
||||
|
||||
|
@ -26,6 +26,7 @@ TIDY_FLAGSX += -bugprone-macro-parentheses,-misc-macro-parentheses,
|
||||
TIDY_FLAGSX += -modernize-use-trailing-return-type
|
||||
TIDY_FLAGSX += -bugprone-too-small-loop-variable
|
||||
TIDY_FLAGSX += -cppcoreguidelines-pro-bounds-array-to-pointer-decay
|
||||
TIDY_FLAGSX += -modernize-use-trailing-return-type
|
||||
|
||||
space :=
|
||||
space +=
|
||||
|
@ -34,7 +34,7 @@ namespace netlist
|
||||
NETLIB_UPDATEI();
|
||||
|
||||
public:
|
||||
void update_outputs(const unsigned cnt);
|
||||
void update_outputs(const unsigned cnt) NL_NOEXCEPT;
|
||||
|
||||
logic_input_t m_IP;
|
||||
object_array_t<logic_output_t, 14> m_Q;
|
||||
|
@ -36,7 +36,7 @@ namespace netlist
|
||||
NETLIB_UPDATEI();
|
||||
|
||||
public:
|
||||
void update_outputs(unsigned v);
|
||||
void update_outputs(unsigned v) NL_NOEXCEPT;
|
||||
|
||||
logic_input_t m_A;
|
||||
logic_input_t m_B;
|
||||
|
@ -34,7 +34,7 @@ namespace netlist
|
||||
NETLIB_UPDATEI();
|
||||
NETLIB_RESETI();
|
||||
|
||||
void update_outputs();
|
||||
void update_outputs() NL_NOEXCEPT;
|
||||
|
||||
logic_input_t m_A;
|
||||
logic_input_t m_B;
|
||||
|
@ -27,7 +27,7 @@ namespace netlist
|
||||
NETLIB_UPDATEI();
|
||||
|
||||
public:
|
||||
void shift();
|
||||
void shift() NL_NOEXCEPT;
|
||||
|
||||
logic_input_t m_RC;
|
||||
logic_input_t m_IN;
|
||||
|
@ -107,7 +107,7 @@ const logic_family_desc_t *family_CD4XXX()
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
detail::queue_t::queue_t(netlist_state_t &nl)
|
||||
: timed_queue<pqentry_t<net_t *, netlist_time>, false, true>(512)
|
||||
: timed_queue<pqentry_t<net_t *, netlist_time>, false>(512)
|
||||
, netlist_ref(nl)
|
||||
, m_qsize(0)
|
||||
, m_times(512)
|
||||
@ -142,7 +142,7 @@ void detail::queue_t::on_post_load(plib::state_manager_t &manager)
|
||||
for (std::size_t i = 0; i < m_qsize; i++ )
|
||||
{
|
||||
detail::net_t *n = state().nets()[m_net_ids[i]].get();
|
||||
this->push(queue_t::entry_t(netlist_time::from_raw(m_times[i]),n));
|
||||
this->push<false>(queue_t::entry_t(netlist_time::from_raw(m_times[i]),n));
|
||||
}
|
||||
}
|
||||
|
||||
@ -740,7 +740,7 @@ void detail::net_t::update_devs() NL_NOEXCEPT
|
||||
{
|
||||
case core_terminal_t::STATE_INP_HL:
|
||||
case core_terminal_t::STATE_INP_LH:
|
||||
process<KEEP_STATS>(mask | core_terminal_t::STATE_INP_ACTIVE, new_Q);
|
||||
process<KEEP_STATS>(mask, new_Q);
|
||||
break;
|
||||
default:
|
||||
/* do nothing */
|
||||
@ -749,20 +749,10 @@ void detail::net_t::update_devs() NL_NOEXCEPT
|
||||
#else
|
||||
nl_assert(this->isRailNet());
|
||||
|
||||
const unsigned int mask((m_new_Q << core_terminal_t::INP_LH_SHIFT)
|
||||
| (m_cur_Q << core_terminal_t::INP_HL_SHIFT));
|
||||
|
||||
m_in_queue = queue_status::DELIVERED; /* mark as taken ... */
|
||||
switch (mask)
|
||||
{
|
||||
case core_terminal_t::STATE_INP_HL:
|
||||
case core_terminal_t::STATE_INP_LH:
|
||||
process<KEEP_STATS>(mask | core_terminal_t::STATE_INP_ACTIVE, m_new_Q);
|
||||
break;
|
||||
default:
|
||||
/* do nothing */
|
||||
break;
|
||||
}
|
||||
if (m_new_Q ^ m_cur_Q)
|
||||
process<KEEP_STATS>((m_new_Q << core_terminal_t::INP_LH_SHIFT)
|
||||
| (m_cur_Q << core_terminal_t::INP_HL_SHIFT), m_new_Q);
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -791,7 +781,7 @@ void detail::net_t::reset()
|
||||
}
|
||||
}
|
||||
|
||||
void detail::net_t::add_terminal(detail::core_terminal_t &terminal)
|
||||
void detail::net_t::add_terminal(detail::core_terminal_t &terminal) NL_NOEXCEPT
|
||||
{
|
||||
for (auto &t : m_core_terms)
|
||||
if (t == &terminal)
|
||||
@ -802,7 +792,7 @@ void detail::net_t::add_terminal(detail::core_terminal_t &terminal)
|
||||
m_core_terms.push_back(&terminal);
|
||||
}
|
||||
|
||||
void detail::net_t::remove_terminal(detail::core_terminal_t &terminal)
|
||||
void detail::net_t::remove_terminal(detail::core_terminal_t &terminal) NL_NOEXCEPT
|
||||
{
|
||||
if (plib::container::contains(m_core_terms, &terminal))
|
||||
{
|
||||
@ -1002,7 +992,7 @@ param_t::param_type_t param_t::param_type() const
|
||||
}
|
||||
|
||||
|
||||
void param_t::update_param()
|
||||
void param_t::update_param() NL_NOEXCEPT
|
||||
{
|
||||
device().update_param();
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ class NETLIB_NAME(name) : public device_t
|
||||
* device a dynamic device if parameter m_func is set.
|
||||
*/
|
||||
#define NETLIB_IS_DYNAMIC(expr) \
|
||||
public: virtual bool is_dynamic() const override { return expr; }
|
||||
public: virtual bool is_dynamic() const NL_NOEXCEPT override { return expr; }
|
||||
|
||||
/*! Add this to a device definition to mark the device as a time-stepping device.
|
||||
*
|
||||
@ -122,26 +122,26 @@ class NETLIB_NAME(name) : public device_t
|
||||
*
|
||||
*/
|
||||
#define NETLIB_IS_TIMESTEP(expr) \
|
||||
public: virtual bool is_timestep() const override { return expr; }
|
||||
public: virtual bool is_timestep() const NL_NOEXCEPT override { return expr; }
|
||||
|
||||
/*! Used to implement the time stepping code.
|
||||
*
|
||||
* Please see NETLIB_IS_TIMESTEP for an example.
|
||||
*/
|
||||
#define NETLIB_TIMESTEPI() \
|
||||
public: virtual void timestep(const nl_double step) override
|
||||
public: virtual void timestep(const nl_double step) NL_NOEXCEPT override
|
||||
|
||||
#define NETLIB_FAMILY(family) , m_famsetter(*this, family)
|
||||
|
||||
#define NETLIB_DELEGATE(chip, name) nldelegate(&NETLIB_NAME(chip) :: name, this)
|
||||
|
||||
#define NETLIB_UPDATE_TERMINALSI() virtual void update_terminals() override
|
||||
#define NETLIB_UPDATE_TERMINALSI() virtual void update_terminals() NL_NOEXCEPT override
|
||||
#define NETLIB_HANDLERI(name) virtual void name() NL_NOEXCEPT
|
||||
#define NETLIB_UPDATEI() virtual void update() NL_NOEXCEPT override
|
||||
#define NETLIB_UPDATE_PARAMI() virtual void update_param() override
|
||||
#define NETLIB_UPDATE_PARAMI() virtual void update_param() NL_NOEXCEPT override
|
||||
#define NETLIB_RESETI() virtual void reset() override
|
||||
|
||||
#define NETLIB_TIMESTEP(chip) void NETLIB_NAME(chip) :: timestep(const nl_double step)
|
||||
#define NETLIB_TIMESTEP(chip) void NETLIB_NAME(chip) :: timestep(nl_double step) NL_NOEXCEPT
|
||||
|
||||
#define NETLIB_SUB(chip) nld_ ## chip
|
||||
#define NETLIB_SUBXX(ns, chip) unique_pool_ptr< ns :: nld_ ## chip >
|
||||
@ -151,10 +151,10 @@ class NETLIB_NAME(name) : public device_t
|
||||
|
||||
#define NETLIB_RESET(chip) void NETLIB_NAME(chip) :: reset(void)
|
||||
|
||||
#define NETLIB_UPDATE_PARAM(chip) void NETLIB_NAME(chip) :: update_param()
|
||||
#define NETLIB_FUNC_VOID(chip, name, params) void NETLIB_NAME(chip) :: name params
|
||||
#define NETLIB_UPDATE_PARAM(chip) void NETLIB_NAME(chip) :: update_param() NL_NOEXCEPT
|
||||
#define NETLIB_FUNC_VOID(chip, name, params) void NETLIB_NAME(chip) :: name params NL_NOEXCEPT
|
||||
|
||||
#define NETLIB_UPDATE_TERMINALS(chip) void NETLIB_NAME(chip) :: update_terminals()
|
||||
#define NETLIB_UPDATE_TERMINALS(chip) void NETLIB_NAME(chip) :: update_terminals() NL_NOEXCEPT
|
||||
|
||||
//============================================================
|
||||
// Asserts
|
||||
@ -254,13 +254,13 @@ namespace netlist
|
||||
virtual unique_pool_ptr<devices::nld_base_a_to_d_proxy> create_a_d_proxy(netlist_state_t &anetlist, const pstring &name,
|
||||
logic_input_t *proxied) const = 0;
|
||||
|
||||
double fixed_V() const { return m_fixed_V; }
|
||||
double low_thresh_V(const double VN, const double VP) const { return VN + (VP - VN) * m_low_thresh_PCNT; }
|
||||
double high_thresh_V(const double VN, const double VP) const { return VN + (VP - VN) * m_high_thresh_PCNT; }
|
||||
double low_offset_V() const { return m_low_VO; }
|
||||
double high_offset_V() const { return m_high_VO; }
|
||||
double R_low() const { return m_R_low; }
|
||||
double R_high() const { return m_R_high; }
|
||||
double fixed_V() const noexcept{ return m_fixed_V; }
|
||||
double low_thresh_V(const double VN, const double VP) const noexcept{ return VN + (VP - VN) * m_low_thresh_PCNT; }
|
||||
double high_thresh_V(const double VN, const double VP) const noexcept{ return VN + (VP - VN) * m_high_thresh_PCNT; }
|
||||
double low_offset_V() const noexcept{ return m_low_VO; }
|
||||
double high_offset_V() const noexcept{ return m_high_VO; }
|
||||
double R_low() const noexcept{ return m_R_low; }
|
||||
double R_high() const noexcept{ return m_R_high; }
|
||||
|
||||
double m_fixed_V; //!< For variable voltage families, specify 0. For TTL this would be 5. */
|
||||
double m_low_thresh_PCNT; //!< low input threshhold offset. If the input voltage is below this value times supply voltage, a "0" input is signalled
|
||||
@ -285,11 +285,9 @@ namespace netlist
|
||||
class logic_family_t
|
||||
{
|
||||
public:
|
||||
|
||||
logic_family_t() : m_logic_family(nullptr) {}
|
||||
COPYASSIGNMOVE(logic_family_t, delete)
|
||||
|
||||
|
||||
const logic_family_desc_t *logic_family() const { return m_logic_family; }
|
||||
void set_logic_family(const logic_family_desc_t *fam) { m_logic_family = fam; }
|
||||
|
||||
@ -321,7 +319,7 @@ namespace netlist
|
||||
template <typename O>
|
||||
//! Constructor.
|
||||
state_var(O &owner, //!< owner must have a netlist() method.
|
||||
const pstring &name, //!< identifier/name for this state variable
|
||||
const pstring &name, //!< identifier/name for this state variable
|
||||
const T &value //!< Initial value after construction
|
||||
);
|
||||
|
||||
@ -332,7 +330,7 @@ namespace netlist
|
||||
//! Move Constructor.
|
||||
constexpr state_var(state_var &&rhs) noexcept = default;
|
||||
//! Assignment operator to assign value of a state var.
|
||||
C14CONSTEXPR state_var &operator=(const state_var &rhs) = default;
|
||||
C14CONSTEXPR state_var &operator=(const state_var &rhs) /*noexcept*/ = default; // OSX doesn't like noexcept
|
||||
//! Assignment move operator to assign value of a state var.
|
||||
C14CONSTEXPR state_var &operator=(state_var &&rhs) noexcept = default;
|
||||
//! Assignment operator to assign value of type T.
|
||||
@ -355,7 +353,7 @@ namespace netlist
|
||||
* Please refer to \ref state_var.
|
||||
*/
|
||||
template <typename T, std::size_t N>
|
||||
struct state_array
|
||||
struct state_array : public std::array<T, N>
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
@ -372,12 +370,6 @@ namespace netlist
|
||||
state_array(state_array &&rhs) noexcept = default;
|
||||
state_array &operator=(const state_array &rhs) noexcept = default;
|
||||
state_array &operator=(state_array &&rhs) noexcept = default;
|
||||
|
||||
state_array &operator=(const T &rhs) noexcept { m_value = rhs; return *this; }
|
||||
T & operator[](const std::size_t i) noexcept { return m_value[i]; }
|
||||
constexpr const T & operator[](const std::size_t i) const noexcept { return m_value[i]; }
|
||||
private:
|
||||
std::array<T, N> m_value;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -401,22 +393,22 @@ namespace netlist
|
||||
template <typename C, typename T>
|
||||
struct property_store_t
|
||||
{
|
||||
static void add(const C *obj, const T &aname)
|
||||
static void add(const C *obj, const T &aname) noexcept
|
||||
{
|
||||
store().insert({obj, aname});
|
||||
}
|
||||
|
||||
static const T get(const C *obj)
|
||||
static const T get(const C *obj) noexcept
|
||||
{
|
||||
return store().find(obj)->second;
|
||||
}
|
||||
|
||||
static void remove(const C *obj)
|
||||
static void remove(const C *obj) noexcept
|
||||
{
|
||||
store().erase(store().find(obj));
|
||||
}
|
||||
|
||||
static std::unordered_map<const C *, T> &store()
|
||||
static std::unordered_map<const C *, T> &store() noexcept
|
||||
{
|
||||
static std::unordered_map<const C *, T> lstore;
|
||||
return lstore;
|
||||
@ -453,7 +445,7 @@ namespace netlist
|
||||
*
|
||||
* \returns name of the object.
|
||||
*/
|
||||
pstring name() const
|
||||
pstring name() const noexcept
|
||||
{
|
||||
return props::get(this);
|
||||
}
|
||||
@ -549,17 +541,14 @@ namespace netlist
|
||||
{
|
||||
public:
|
||||
|
||||
using list_t = std::vector<core_terminal_t *>;
|
||||
|
||||
static constexpr const unsigned int INP_HL_SHIFT = 0;
|
||||
static constexpr const unsigned int INP_LH_SHIFT = 1;
|
||||
static constexpr const unsigned int INP_ACTIVE_SHIFT = 2;
|
||||
|
||||
enum state_e {
|
||||
STATE_INP_PASSIVE = 0,
|
||||
STATE_INP_HL = (1 << INP_HL_SHIFT),
|
||||
STATE_INP_LH = (1 << INP_LH_SHIFT),
|
||||
STATE_INP_ACTIVE = (1 << INP_ACTIVE_SHIFT),
|
||||
STATE_INP_ACTIVE = STATE_INP_HL | STATE_INP_LH,
|
||||
STATE_OUT = 128,
|
||||
STATE_BIDIR = 256
|
||||
};
|
||||
@ -669,8 +658,8 @@ namespace netlist
|
||||
|
||||
/* setup stuff */
|
||||
|
||||
void add_terminal(core_terminal_t &terminal);
|
||||
void remove_terminal(core_terminal_t &terminal);
|
||||
void add_terminal(core_terminal_t &terminal) NL_NOEXCEPT;
|
||||
void remove_terminal(core_terminal_t &terminal) NL_NOEXCEPT;
|
||||
|
||||
bool is_logic() const NL_NOEXCEPT;
|
||||
bool is_analog() const NL_NOEXCEPT;
|
||||
@ -730,7 +719,7 @@ namespace netlist
|
||||
* FIXME: get rid of this and implement export/import in MAME
|
||||
*/
|
||||
/* only used for logic nets */
|
||||
netlist_sig_t *Q_state_ptr() { return m_cur_Q.ptr(); }
|
||||
netlist_sig_t *Q_state_ptr() noexcept { return m_cur_Q.ptr(); }
|
||||
|
||||
private:
|
||||
state_var<netlist_sig_t> m_new_Q;
|
||||
@ -989,12 +978,12 @@ namespace netlist
|
||||
protected:
|
||||
virtual ~param_t() noexcept = default; /* not intended to be destroyed */
|
||||
|
||||
void update_param();
|
||||
void update_param() NL_NOEXCEPT;
|
||||
|
||||
pstring get_initial(const device_t &dev, bool *found);
|
||||
|
||||
template<typename C>
|
||||
void set(C &p, const C v)
|
||||
void set(C &p, const C v) noexcept
|
||||
{
|
||||
if (p != v)
|
||||
{
|
||||
@ -1018,7 +1007,7 @@ namespace netlist
|
||||
T operator()() const NL_NOEXCEPT { return m_param; }
|
||||
operator T() const NL_NOEXCEPT { return m_param; }
|
||||
|
||||
void setTo(const T ¶m) { set(m_param, param); }
|
||||
void setTo(const T ¶m) noexcept { set(m_param, param); }
|
||||
private:
|
||||
T m_param;
|
||||
};
|
||||
@ -1031,7 +1020,7 @@ namespace netlist
|
||||
|
||||
T operator()() const NL_NOEXCEPT { return T(m_param); }
|
||||
operator T() const NL_NOEXCEPT { return T(m_param); }
|
||||
void setTo(const T ¶m) { set(m_param, static_cast<int>(param)); }
|
||||
void setTo(const T ¶m) noexcept { set(m_param, static_cast<int>(param)); }
|
||||
private:
|
||||
int m_param;
|
||||
};
|
||||
@ -1050,7 +1039,7 @@ namespace netlist
|
||||
public:
|
||||
param_ptr_t(device_t &device, const pstring &name, std::uint8_t* val);
|
||||
std::uint8_t * operator()() const NL_NOEXCEPT { return m_param; }
|
||||
void setTo(std::uint8_t *param) { set(m_param, param); }
|
||||
void setTo(std::uint8_t *param) noexcept { set(m_param, param); }
|
||||
private:
|
||||
std::uint8_t* m_param;
|
||||
};
|
||||
@ -1200,10 +1189,10 @@ namespace netlist
|
||||
}
|
||||
}
|
||||
|
||||
void set_hint_deactivate(bool v) { m_hint_deactivate = v; }
|
||||
bool get_hint_deactivate() { return m_hint_deactivate; }
|
||||
void set_hint_deactivate(bool v) noexcept { m_hint_deactivate = v; }
|
||||
bool get_hint_deactivate() const noexcept { return m_hint_deactivate; }
|
||||
/* Has to be set in device reset */
|
||||
void set_active_outputs(int n) { m_active_outputs = n; }
|
||||
void set_active_outputs(int n) noexcept { m_active_outputs = n; }
|
||||
|
||||
void set_default_delegate(detail::core_terminal_t &term);
|
||||
|
||||
@ -1229,12 +1218,12 @@ namespace netlist
|
||||
log_type & log();
|
||||
|
||||
public:
|
||||
virtual void timestep(const nl_double st) { plib::unused_var(st); }
|
||||
virtual void update_terminals() { }
|
||||
virtual void timestep(const nl_double st) NL_NOEXCEPT { plib::unused_var(st); }
|
||||
virtual void update_terminals() NL_NOEXCEPT { }
|
||||
|
||||
virtual void update_param() {}
|
||||
virtual bool is_dynamic() const { return false; }
|
||||
virtual bool is_timestep() const { return false; }
|
||||
virtual void update_param() NL_NOEXCEPT {}
|
||||
virtual bool is_dynamic() const NL_NOEXCEPT { return false; }
|
||||
virtual bool is_timestep() const NL_NOEXCEPT { return false; }
|
||||
|
||||
private:
|
||||
bool m_hint_deactivate;
|
||||
@ -1303,12 +1292,12 @@ namespace netlist
|
||||
*/
|
||||
class detail::queue_t :
|
||||
//public timed_queue<pqentry_t<net_t *, netlist_time>, false, NL_KEEP_STATISTICS>,
|
||||
public timed_queue<pqentry_t<net_t *, netlist_time>, false, true>,
|
||||
public timed_queue<pqentry_t<net_t *, netlist_time>, false>,
|
||||
public detail::netlist_ref,
|
||||
public plib::state_manager_t::callback_t
|
||||
{
|
||||
public:
|
||||
using base_queue = timed_queue<pqentry_t<net_t *, netlist_time>, false, true>;
|
||||
using base_queue = timed_queue<pqentry_t<net_t *, netlist_time>, false>;
|
||||
using entry_t = pqentry_t<net_t *, netlist_time>;
|
||||
explicit queue_t(netlist_state_t &nl);
|
||||
virtual ~queue_t() noexcept = default;
|
||||
@ -1550,25 +1539,31 @@ namespace netlist
|
||||
netlist_time time() const NL_NOEXCEPT { return m_time; }
|
||||
|
||||
void process_queue(netlist_time delta) NL_NOEXCEPT;
|
||||
void abort_current_queue_slice() NL_NOEXCEPT { m_queue.retime(detail::queue_t::entry_t(m_time, nullptr)); }
|
||||
void abort_current_queue_slice() NL_NOEXCEPT
|
||||
{
|
||||
if (!USE_QUEUE_STATS || !m_use_stats)
|
||||
m_queue.retime<false>(detail::queue_t::entry_t(m_time, nullptr));
|
||||
else
|
||||
m_queue.retime<true>(detail::queue_t::entry_t(m_time, nullptr));
|
||||
}
|
||||
|
||||
const detail::queue_t &queue() const NL_NOEXCEPT { return m_queue; }
|
||||
|
||||
void qpush(detail::queue_t::entry_t && e) noexcept
|
||||
{
|
||||
if (!USE_QUEUE_STATS || !m_use_stats)
|
||||
m_queue.push_nostats(std::move(e)); // NOLINT(performance-move-const-arg)
|
||||
m_queue.push<false>(std::move(e)); // NOLINT(performance-move-const-arg)
|
||||
else
|
||||
m_queue.push(std::move(e)); // NOLINT(performance-move-const-arg)
|
||||
m_queue.push<true>(std::move(e)); // NOLINT(performance-move-const-arg)
|
||||
}
|
||||
|
||||
template <class R>
|
||||
void qremove(const R &elem) noexcept
|
||||
{
|
||||
if (!USE_QUEUE_STATS || !m_use_stats)
|
||||
m_queue.remove_nostats(elem);
|
||||
m_queue.remove<false>(elem);
|
||||
else
|
||||
m_queue.remove(elem);
|
||||
m_queue.remove<true>(elem);
|
||||
}
|
||||
|
||||
/* Control functions */
|
||||
@ -1905,9 +1900,9 @@ namespace netlist
|
||||
template <typename O>
|
||||
state_array<T,N>::state_array(O &owner, const pstring &name, const T & value)
|
||||
{
|
||||
owner.state().save(owner, m_value, owner.name(), name);
|
||||
owner.state().save(owner, *static_cast<std::array<T, N> *>(this), owner.name(), name);
|
||||
for (std::size_t i=0; i<N; i++)
|
||||
m_value[i] = value;
|
||||
(*this)[i] = value;
|
||||
}
|
||||
} // namespace netlist
|
||||
|
||||
|
@ -50,7 +50,7 @@
|
||||
* This approach is stricter and should identify bugs in
|
||||
* the netlist core faster.
|
||||
* By default it is disabled since it is not as fast as
|
||||
* the default approach. It is up to 5% slower.
|
||||
* the default approach. It is up to 10% slower.
|
||||
*
|
||||
*/
|
||||
#ifndef USE_COPY_INSTEAD_OF_REFERENCE
|
||||
|
@ -125,9 +125,6 @@ namespace netlist
|
||||
|
||||
// nld_solver.cpp
|
||||
|
||||
//PERRMSGV(MF_UNKNOWN_SOLVER_TYPE, 1, "Unknown solver type: {1}")
|
||||
PERRMSGV(MF_NETGROUP_SIZE_EXCEEDED_1, 1, "Encountered netgroup with > {1} nets")
|
||||
|
||||
PERRMSGV(MI_NO_SPECIFIC_SOLVER, 1, "No specific solver found for netlist of size {1}")
|
||||
|
||||
// nld_mm5837.cpp
|
||||
|
@ -69,37 +69,34 @@ namespace netlist
|
||||
std::swap(m_object, other.m_object);
|
||||
}
|
||||
#endif
|
||||
struct QueueOp
|
||||
inline bool operator ==(const pqentry_t &rhs) const noexcept
|
||||
{
|
||||
inline static constexpr bool less(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
|
||||
{
|
||||
return (lhs.m_exec_time < rhs.m_exec_time);
|
||||
}
|
||||
return m_object == rhs.m_object;
|
||||
}
|
||||
|
||||
inline static constexpr bool lessequal(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
|
||||
{
|
||||
return (lhs.m_exec_time <= rhs.m_exec_time);
|
||||
}
|
||||
inline bool operator ==(const Element &rhs) const noexcept
|
||||
{
|
||||
return m_object == rhs;
|
||||
}
|
||||
|
||||
inline static constexpr bool equal(const pqentry_t &lhs, const pqentry_t &rhs) noexcept
|
||||
{
|
||||
return lhs.m_object == rhs.m_object;
|
||||
}
|
||||
inline bool operator <=(const pqentry_t &rhs) const noexcept
|
||||
{
|
||||
return (m_exec_time <= rhs.m_exec_time);
|
||||
}
|
||||
|
||||
inline static constexpr bool equal(const pqentry_t &lhs, const Element &rhs) noexcept
|
||||
{
|
||||
return lhs.m_object == rhs;
|
||||
}
|
||||
inline bool operator <(const pqentry_t &rhs) const noexcept
|
||||
{
|
||||
return (m_exec_time < rhs.m_exec_time);
|
||||
}
|
||||
|
||||
inline static constexpr pqentry_t never() noexcept { return pqentry_t(Time::never(), nullptr); }
|
||||
};
|
||||
inline static constexpr pqentry_t never() noexcept { return pqentry_t(Time::never(), nullptr); }
|
||||
|
||||
Time m_exec_time;
|
||||
Element m_object;
|
||||
};
|
||||
|
||||
/* Use TS = true for a threadsafe queue */
|
||||
template <class T, bool TS, bool KEEPSTAT, class QueueOp = typename T::QueueOp>
|
||||
template <class T, bool TS>
|
||||
class timed_queue_linear : plib::nocopyassignmove
|
||||
{
|
||||
public:
|
||||
@ -113,28 +110,31 @@ namespace netlist
|
||||
std::size_t capacity() const noexcept { return m_list.capacity() - 1; }
|
||||
bool empty() const noexcept { return (m_end == &m_list[1]); }
|
||||
|
||||
template<bool KEEPSTAT>
|
||||
void push(T && e) noexcept
|
||||
{
|
||||
/* Lock */
|
||||
lock_guard_type lck(m_lock);
|
||||
T * i(m_end-1);
|
||||
for (; QueueOp::less(*(i), e); --i)
|
||||
for (; *i < e; --i)
|
||||
{
|
||||
*(i+1) = *(i);
|
||||
m_prof_sortmove.inc();
|
||||
if (KEEPSTAT)
|
||||
m_prof_sortmove.inc();
|
||||
}
|
||||
*(i+1) = std::move(e);
|
||||
++m_end;
|
||||
m_prof_call.inc();
|
||||
if (KEEPSTAT)
|
||||
m_prof_call.inc();
|
||||
}
|
||||
|
||||
void push_nostats(T && e) noexcept
|
||||
void push_nostatsx(T && e) noexcept
|
||||
{
|
||||
/* Lock */
|
||||
lock_guard_type lck(m_lock);
|
||||
#if 1
|
||||
T * i(m_end-1);
|
||||
for (; QueueOp::less(*(i), e); --i)
|
||||
for (; *i < e; --i)
|
||||
{
|
||||
*(i+1) = *(i);
|
||||
}
|
||||
@ -153,22 +153,18 @@ namespace netlist
|
||||
T pop() noexcept { return *(--m_end); }
|
||||
const T &top() const noexcept { return *(m_end-1); }
|
||||
|
||||
template <class R>
|
||||
template <bool KEEPSTAT, class R>
|
||||
void remove(const R &elem) noexcept
|
||||
{
|
||||
m_prof_remove.inc();
|
||||
remove_nostats(elem);
|
||||
}
|
||||
|
||||
template <class R>
|
||||
void remove_nostats(const R &elem) noexcept
|
||||
{
|
||||
/* Lock */
|
||||
lock_guard_type lck(m_lock);
|
||||
if (KEEPSTAT)
|
||||
m_prof_remove.inc();
|
||||
#if 1
|
||||
for (T * i = m_end - 1; i > &m_list[0]; --i)
|
||||
{
|
||||
if (QueueOp::equal(*i, elem))
|
||||
// == operator ignores time!
|
||||
if (*i == elem)
|
||||
{
|
||||
std::copy(i+1, m_end--, i);
|
||||
return;
|
||||
@ -186,23 +182,25 @@ namespace netlist
|
||||
#endif
|
||||
}
|
||||
|
||||
void retime(T && elem) noexcept
|
||||
template <bool KEEPSTAT, class R>
|
||||
void retime(R && elem) noexcept
|
||||
{
|
||||
/* Lock */
|
||||
lock_guard_type lck(m_lock);
|
||||
m_prof_retime.inc();
|
||||
if (KEEPSTAT)
|
||||
m_prof_retime.inc();
|
||||
|
||||
for (T * i = m_end - 1; i > &m_list[0]; --i)
|
||||
for (R * i = m_end - 1; i > &m_list[0]; --i)
|
||||
{
|
||||
if (QueueOp::equal(*i, elem)) // partial equal!
|
||||
if (*i == elem) // partial equal!
|
||||
{
|
||||
*i = std::move(elem);
|
||||
while (QueueOp::less(*(i-1), *i))
|
||||
while (*(i-1) < *i)
|
||||
{
|
||||
std::swap(*(i-1), *i);
|
||||
--i;
|
||||
}
|
||||
while (i < m_end && QueueOp::less(*i, *(i+1)))
|
||||
while (i < m_end && *i < *(i+1))
|
||||
{
|
||||
std::swap(*(i+1), *i);
|
||||
++i;
|
||||
@ -220,7 +218,7 @@ namespace netlist
|
||||
* the insert algo above will run into this element and doesn't
|
||||
* need a comparison with queue start.
|
||||
*/
|
||||
m_list[0] = QueueOp::never();
|
||||
m_list[0] = T::never();
|
||||
m_end++;
|
||||
}
|
||||
|
||||
@ -241,20 +239,20 @@ namespace netlist
|
||||
|
||||
public:
|
||||
// profiling
|
||||
nperfcount_t<KEEPSTAT> m_prof_sortmove;
|
||||
nperfcount_t<KEEPSTAT> m_prof_call;
|
||||
nperfcount_t<KEEPSTAT> m_prof_remove;
|
||||
nperfcount_t<KEEPSTAT> m_prof_retime;
|
||||
nperfcount_t<true> m_prof_sortmove;
|
||||
nperfcount_t<true> m_prof_call;
|
||||
nperfcount_t<true> m_prof_remove;
|
||||
nperfcount_t<true> m_prof_retime;
|
||||
};
|
||||
|
||||
template <class T, bool TS, bool KEEPSTAT, class QueueOp = typename T::QueueOp>
|
||||
template <class T, bool TS>
|
||||
class timed_queue_heap : plib::nocopyassignmove
|
||||
{
|
||||
public:
|
||||
|
||||
struct compare
|
||||
{
|
||||
constexpr bool operator()(const T &a, const T &b) const { return QueueOp::lessequal(b,a); }
|
||||
constexpr bool operator()(const T &a, const T &b) const { return b <= a; }
|
||||
};
|
||||
|
||||
explicit timed_queue_heap(const std::size_t list_size)
|
||||
@ -266,13 +264,15 @@ namespace netlist
|
||||
std::size_t capacity() const noexcept { return m_list.capacity(); }
|
||||
bool empty() const noexcept { return &m_list[0] == m_end; }
|
||||
|
||||
template <bool KEEPSTAT>
|
||||
void push(T &&e) noexcept
|
||||
{
|
||||
/* Lock */
|
||||
lock_guard_type lck(m_lock);
|
||||
*m_end++ = e;
|
||||
std::push_heap(&m_list[0], m_end, compare());
|
||||
m_prof_call.inc();
|
||||
if (KEEPSTAT)
|
||||
m_prof_call.inc();
|
||||
}
|
||||
|
||||
T pop() noexcept
|
||||
@ -285,14 +285,16 @@ namespace netlist
|
||||
|
||||
const T &top() const noexcept { return m_list[0]; }
|
||||
|
||||
template <class R>
|
||||
template <bool KEEPSTAT, class R>
|
||||
void remove(const R &elem) noexcept
|
||||
{
|
||||
/* Lock */
|
||||
lock_guard_type lck(m_lock);
|
||||
if (KEEPSTAT)
|
||||
m_prof_remove.inc();
|
||||
for (T * i = m_end - 1; i >= &m_list[0]; i--)
|
||||
{
|
||||
if (QueueOp::equal(*i, elem))
|
||||
if (*i == elem)
|
||||
{
|
||||
m_end--;
|
||||
for (;i < m_end; i++)
|
||||
@ -303,13 +305,16 @@ namespace netlist
|
||||
}
|
||||
}
|
||||
|
||||
template <bool KEEPSTAT>
|
||||
void retime(const T &elem) noexcept
|
||||
{
|
||||
/* Lock */
|
||||
lock_guard_type lck(m_lock);
|
||||
if (KEEPSTAT)
|
||||
m_prof_retime.inc();
|
||||
for (T * i = m_end - 1; i >= &m_list[0]; i--)
|
||||
{
|
||||
if (QueueOp::equal(*i, elem)) // partial equal!
|
||||
if (*i == elem) // partial equal!
|
||||
{
|
||||
*i = elem;
|
||||
std::make_heap(&m_list[0], m_end, compare());
|
||||
@ -340,18 +345,23 @@ namespace netlist
|
||||
|
||||
public:
|
||||
// profiling
|
||||
nperfcount_t<KEEPSTAT> m_prof_sortmove;
|
||||
nperfcount_t<KEEPSTAT> m_prof_call;
|
||||
nperfcount_t<true> m_prof_sortmove;
|
||||
nperfcount_t<true> m_prof_call;
|
||||
nperfcount_t<true> m_prof_remove;
|
||||
nperfcount_t<true> m_prof_retime;
|
||||
};
|
||||
|
||||
template <class T, bool TS>
|
||||
using timed_queue = timed_queue_linear<T, TS>;
|
||||
|
||||
/*
|
||||
* Use timed_queue_heap to use stdc++ heap functions instead of linear processing.
|
||||
*
|
||||
* This slows down processing by about 25% on a Kaby Lake.
|
||||
*/
|
||||
|
||||
template <class T, bool TS, bool KEEPSTAT, class QueueOp = typename T::QueueOp>
|
||||
using timed_queue = timed_queue_linear<T, TS, KEEPSTAT, QueueOp>;
|
||||
//template <class T, bool TS>
|
||||
//using timed_queue = timed_queue_heap<T, TS>;
|
||||
|
||||
} // namespace netlist
|
||||
|
||||
|
@ -223,6 +223,8 @@ namespace plib
|
||||
gmres_t(std::size_t size)
|
||||
: residual(size)
|
||||
, Ax(size)
|
||||
, m_ht(RESTART +1, RESTART)
|
||||
, m_v(RESTART + 1, size)
|
||||
, m_size(size)
|
||||
, m_use_more_precise_stop_condition(false)
|
||||
{
|
||||
@ -416,12 +418,12 @@ namespace plib
|
||||
|
||||
plib::parray<float_type, RESTART + 1> m_c; /* mr + 1 */
|
||||
plib::parray<float_type, RESTART + 1> m_g; /* mr + 1 */
|
||||
plib::parray<plib::parray<float_type, RESTART>, RESTART + 1> m_ht; /* (mr + 1), mr */
|
||||
plib::parray2D<float_type, RESTART + 1, RESTART> m_ht; /* (mr + 1), mr */
|
||||
plib::parray<float_type, RESTART + 1> m_s; /* mr + 1 */
|
||||
plib::parray<float_type, RESTART + 1> m_y; /* mr + 1 */
|
||||
|
||||
//plib::parray<float_type, SIZE> m_v[RESTART + 1]; /* mr + 1, n */
|
||||
plib::parray<plib::parray<float_type, storage_N>, RESTART + 1> m_v; /* mr + 1, n */
|
||||
//plib::parray<plib::parray<float_type, storage_N>, RESTART + 1> m_v; /* mr + 1, n */
|
||||
plib::parray2D<float_type, RESTART + 1, SIZE> m_v; /* mr + 1, n */
|
||||
|
||||
std::size_t m_size;
|
||||
|
||||
|
@ -36,7 +36,7 @@ namespace plib
|
||||
using index_type = C;
|
||||
using value_type = T;
|
||||
|
||||
static constexpr const int NSQ = (N > 0 ? -N * N : N * N);
|
||||
static constexpr const int NSQ = (N < 0 ? -N * N : N * N);
|
||||
static constexpr const int Np1 = (N == 0) ? 0 : (N < 0 ? N - 1 : N + 1);
|
||||
|
||||
COPYASSIGNMOVE(pmatrix_cr_t, default)
|
||||
@ -64,7 +64,9 @@ namespace plib
|
||||
, m_size(n)
|
||||
{
|
||||
for (index_type i=0; i<n+1; i++)
|
||||
{
|
||||
row_idx[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
~pmatrix_cr_t() = default;
|
||||
@ -495,19 +497,18 @@ namespace plib
|
||||
{
|
||||
index_type p(0);
|
||||
/* build ilu_rows */
|
||||
for (index_type i=1; i < fill.size(); i++)
|
||||
for (decltype(fill.size()) i=1; i < fill.size(); i++)
|
||||
{
|
||||
bool found(false);
|
||||
for (index_type k = 0; k < i; k++)
|
||||
for (decltype(fill.size()) k = 0; k < i; k++)
|
||||
{
|
||||
// if (fill[i][k] < base::FILL_INFINITY)
|
||||
if (fill[i][k] <= ilup)
|
||||
{
|
||||
// assume A[k][k]!=0
|
||||
for (index_type j=k+1; j < fill.size(); j++)
|
||||
for (decltype(fill.size()) j=k+1; j < fill.size(); j++)
|
||||
{
|
||||
auto f = std::min(fill[i][j], 1 + fill[i][k] + fill[k][j]);
|
||||
//if (f < base::FILL_INFINITY)
|
||||
if (f <= ilup)
|
||||
{
|
||||
#if 0
|
||||
@ -522,7 +523,7 @@ namespace plib
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
ilu_rows[p++] = i;
|
||||
ilu_rows[p++] = static_cast<index_type>(i);
|
||||
}
|
||||
ilu_rows[p] = 0; // end of array
|
||||
this->build_from_fill_mat(fill, ilup); //, m_band_width); // ILU(2)
|
||||
|
@ -30,8 +30,9 @@ namespace plib {
|
||||
template <typename FT>
|
||||
struct sizeabs<FT, 0>
|
||||
{
|
||||
static constexpr const std::size_t ABS = 0;
|
||||
using container = typename std::vector<FT, aligned_allocator<FT, PALIGN_VECTOROPT>>;
|
||||
static constexpr std::size_t ABS() { return 0; }
|
||||
//using container = typename std::vector<FT, aligned_allocator<FT, PALIGN_VECTOROPT>>;
|
||||
using container = typename std::vector<FT>;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -63,27 +64,35 @@ namespace plib {
|
||||
using value_type = typename base_type::value_type;
|
||||
|
||||
template <int X = SIZE >
|
||||
parray(size_type size, typename std::enable_if<X==0, int>::type = 0)
|
||||
parray(size_type size, typename std::enable_if<(X==0), int>::type = 0)
|
||||
: m_a(size), m_size(size)
|
||||
{
|
||||
}
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
struct tag {};
|
||||
/* allow construction in fixed size arrays */
|
||||
template <int X = SIZE >
|
||||
parray(typename std::enable_if<(X > 0), int>::type = 0)
|
||||
parray(tag A = tag(), typename std::enable_if<(X >= 0), int>::type = 0)
|
||||
: m_size(X)
|
||||
{
|
||||
}
|
||||
#else
|
||||
/* allow construction in fixed size arrays */
|
||||
parray()
|
||||
: m_size(SIZEABS())
|
||||
{
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
template <int X = SIZE >
|
||||
parray(size_type size, typename std::enable_if<X!=0, int>::type = 0)
|
||||
parray(size_type size, typename std::enable_if<(X != 0), int>::type = 0)
|
||||
: m_size(size)
|
||||
{
|
||||
if (SIZE < 0 && size > SIZEABS())
|
||||
throw plib::pexception("parray: size error " + plib::to_string(size) + ">" + plib::to_string(SIZEABS()));
|
||||
else if (SIZE > 0 && size != SIZEABS())
|
||||
throw plib::pexception("parray: size error");
|
||||
if ((SIZE < 0 && size > SIZEABS())
|
||||
|| (SIZE > 0 && size != SIZEABS()))
|
||||
throw plib::pexception("parray: size error " + plib::to_string(size) + ">" + plib::to_string(SIZE));
|
||||
}
|
||||
|
||||
inline size_type size() const noexcept { return SIZE <= 0 ? m_size : SIZEABS(); }
|
||||
@ -122,6 +131,27 @@ namespace plib {
|
||||
PALIGNAS_CACHELINE()
|
||||
size_type m_size;
|
||||
};
|
||||
|
||||
template <typename FT, int SIZE1, int SIZE2>
|
||||
struct parray2D : public parray<parray<FT, SIZE2>, SIZE1>
|
||||
{
|
||||
public:
|
||||
|
||||
using size_type = std::size_t;
|
||||
|
||||
parray2D(size_type size1, size_type size2)
|
||||
: parray<parray<FT, SIZE2>, SIZE1>(size1)
|
||||
{
|
||||
if (SIZE2 <= 0)
|
||||
{
|
||||
for (size_type i=0; i < this->size(); i++)
|
||||
(*this)[i] = parray<FT, SIZE2>(size2);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace plib
|
||||
|
||||
|
||||
|
||||
#endif /* PARRAY_H_ */
|
||||
|
@ -209,7 +209,7 @@ public:
|
||||
explicit constexpr iter_t(LC* x) noexcept : p(x) { }
|
||||
constexpr iter_t(iter_t &rhs) noexcept : p(rhs.p) { }
|
||||
iter_t(iter_t &&rhs) noexcept { std::swap(*this, rhs); }
|
||||
iter_t& operator=(const iter_t &rhs) noexcept { iter_t t(rhs); std::swap(*this, t); return *this; }
|
||||
iter_t& operator=(const iter_t &rhs) noexcept { p = rhs.p; return *this; }
|
||||
iter_t& operator=(iter_t &&rhs) noexcept { std::swap(*this, rhs); return *this; }
|
||||
iter_t& operator++() noexcept {p = p->next();return *this;}
|
||||
// NOLINTNEXTLINE(cert-dcl21-cpp)
|
||||
@ -219,8 +219,8 @@ public:
|
||||
|
||||
constexpr bool operator==(const iter_t& rhs) const noexcept {return p == rhs.p;}
|
||||
constexpr bool operator!=(const iter_t& rhs) const noexcept {return p != rhs.p;}
|
||||
/* constexpr */ LC& operator*() noexcept {return *p;}
|
||||
/* constexpr */ LC* operator->() noexcept {return p;}
|
||||
constexpr LC& operator*() noexcept {return *p;}
|
||||
constexpr LC* operator->() noexcept {return p;}
|
||||
|
||||
constexpr LC& operator*() const noexcept {return *p;}
|
||||
constexpr LC* operator->() const noexcept {return p;}
|
||||
@ -269,8 +269,19 @@ public:
|
||||
}
|
||||
|
||||
LC *front() const noexcept { return m_head; }
|
||||
void clear() noexcept { m_head = nullptr; }
|
||||
constexpr bool empty() const noexcept { return (m_head == nullptr); }
|
||||
void clear() noexcept
|
||||
{
|
||||
LC *p(m_head);
|
||||
while (p != nullptr)
|
||||
{
|
||||
LC *n(p->m_next);
|
||||
p->m_next = nullptr;
|
||||
p->m_prev = nullptr;
|
||||
p = n;
|
||||
}
|
||||
m_head = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
LC *m_head;
|
||||
|
@ -176,13 +176,13 @@ namespace plib {
|
||||
*reinterpret_cast<function_ptr *>(&m_func) = t;
|
||||
}
|
||||
template<typename O>
|
||||
inline R call(O *obj, Targs... args)
|
||||
inline R call(O *obj, Targs... args) const noexcept(true)
|
||||
{
|
||||
using function_ptr = R (O::*)(Targs...);
|
||||
function_ptr t = *reinterpret_cast<function_ptr *>(&m_func);
|
||||
return (obj->*t)(std::forward<Targs>(args)...);
|
||||
}
|
||||
bool is_set() {
|
||||
bool is_set() const {
|
||||
#if defined(_MSC_VER) || (defined (__INTEL_COMPILER) && defined (_M_X64))
|
||||
int *p = reinterpret_cast<int *>(&m_func);
|
||||
int *e = p + sizeof(generic_function) / sizeof(int);
|
||||
@ -225,12 +225,12 @@ namespace plib {
|
||||
#endif
|
||||
}
|
||||
template<typename O>
|
||||
R call(O *obj, Targs... args) const
|
||||
R call(O *obj, Targs... args) const noexcept(true)
|
||||
{
|
||||
using function_ptr = MEMBER_ABI R (*)(O *obj, Targs... args);
|
||||
return (reinterpret_cast<function_ptr>(m_func))(obj, std::forward<Targs>(args)...);
|
||||
}
|
||||
bool is_set() noexcept { return m_func != nullptr; }
|
||||
bool is_set() const noexcept { return m_func != nullptr; }
|
||||
generic_function get_function() const noexcept { return m_func; }
|
||||
private:
|
||||
generic_function m_func;
|
||||
@ -244,7 +244,7 @@ namespace plib {
|
||||
class generic_class;
|
||||
|
||||
template <class C>
|
||||
using MemberFunctionType = R (C::*)(Targs...);
|
||||
using MemberFunctionType = R (C::*)(Targs...); // noexcept(true) --> c++-17
|
||||
|
||||
pmfp() : pmfp_base<R, Targs...>(), m_obj(nullptr) {}
|
||||
|
||||
@ -263,7 +263,7 @@ namespace plib {
|
||||
m_obj = reinterpret_cast<generic_class *>(object);
|
||||
}
|
||||
|
||||
inline R operator()(Targs ... args)
|
||||
inline R operator()(Targs ... args) const noexcept(true)
|
||||
{
|
||||
return this->call(m_obj, std::forward<Targs>(args)...);
|
||||
}
|
||||
|
@ -319,8 +319,7 @@ namespace devices
|
||||
}
|
||||
else
|
||||
{
|
||||
log().fatal(MF_NETGROUP_SIZE_EXCEEDED_1(128));
|
||||
return; /* tease compilers */
|
||||
ms = create_solver<double, 0>(net_count, sname);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user