From 15ea16e1497bcd28168f5c8ba2e53d3a8da8350c Mon Sep 17 00:00:00 2001 From: couriersud Date: Fri, 25 Sep 2020 21:44:39 +0200 Subject: netlist: minor code cleanup. * a number of minor fixes leading to an increase of 570% to 588% on pongf. * admittedly micro optimization. * Includes some comments why certain decisions have been taken. --- src/lib/netlist/core/base_objects.h | 10 +-- src/lib/netlist/core/core_device.h | 16 +++-- src/lib/netlist/core/exec.h | 2 +- src/lib/netlist/core/logic.h | 10 +-- src/lib/netlist/core/nets.h | 106 +++++++++++++--------------- src/lib/netlist/core/param.h | 4 +- src/lib/netlist/core/state_var.h | 7 +- src/lib/netlist/devices/nld_7448.cpp | 2 +- src/lib/netlist/devices/nld_7493.cpp | 2 +- src/lib/netlist/devices/nld_log.cpp | 4 +- src/lib/netlist/devices/nld_system.cpp | 2 +- src/lib/netlist/devices/nlid_proxy.cpp | 2 +- src/lib/netlist/devices/nlid_truthtable.cpp | 24 ++++--- src/lib/netlist/nl_base.cpp | 10 +-- src/lib/netlist/nl_setup.cpp | 11 ++- src/lib/netlist/plib/pgsl.h | 22 ++++-- src/lib/netlist/plib/pmulti_threading.h | 2 - src/lib/netlist/plib/ptimed_queue.h | 6 +- 18 files changed, 131 insertions(+), 111 deletions(-) diff --git a/src/lib/netlist/core/base_objects.h b/src/lib/netlist/core/base_objects.h index 1a7cd44da2f..edde9fa0f0f 100644 --- a/src/lib/netlist/core/base_objects.h +++ b/src/lib/netlist/core/base_objects.h @@ -239,9 +239,9 @@ namespace netlist void set_net(net_t *anet) noexcept { m_net = anet; } void clear_net() noexcept { m_net = nullptr; } - bool has_net() const noexcept { return (m_net != nullptr); } + constexpr bool has_net() const noexcept { return (m_net != nullptr); } - constexpr net_t & net() const noexcept { return *m_net;} + net_t & net() const noexcept { return *m_net;} bool is_logic() const noexcept; bool is_logic_input() const noexcept; @@ -251,8 +251,8 @@ namespace netlist bool is_analog_input() const noexcept; bool is_analog_output() const noexcept; - bool is_state(state_e astate) const noexcept { return (m_state == astate); } - state_e terminal_state() const noexcept { return m_state; } + constexpr bool is_state(state_e astate) const noexcept { return (m_state == astate); } + constexpr const state_e &terminal_state() const noexcept { return m_state; } void set_state(state_e astate) noexcept { m_state = astate; } void reset() noexcept { set_state(is_type(terminal_type::OUTPUT) ? STATE_OUT : STATE_INP_ACTIVE); } @@ -265,7 +265,7 @@ namespace netlist state_var_sig m_Q; #else - void set_copied_input(netlist_sig_t val) const noexcept { plib::unused_var(val); } // NOLINT: static means more message elsewhere + void set_copied_input(const netlist_sig_t &val) const noexcept { plib::unused_var(val); } // NOLINT: static means more message elsewhere #endif void set_delegate(const nldelegate &delegate) noexcept { m_delegate = delegate; } diff --git a/src/lib/netlist/core/core_device.h b/src/lib/netlist/core/core_device.h index 2e511ce6c9b..edfe25b6ec0 100644 --- a/src/lib/netlist/core/core_device.h +++ b/src/lib/netlist/core/core_device.h @@ -31,23 +31,27 @@ namespace netlist void do_inc_active() noexcept { - if (m_hint_deactivate) + gsl_Expects(m_active_outputs >= 0); + + if (m_activate && m_hint_deactivate) { if (++m_active_outputs == 1) { if (m_stats) m_stats->m_stat_inc_active.inc(); - inc_active(); + m_activate(true);//inc_active(); } } } void do_dec_active() noexcept { - if (m_hint_deactivate) + gsl_Expects(m_active_outputs >= 1); + + if (m_activate && m_hint_deactivate) if (--m_active_outputs == 0) { - dec_active(); + m_activate(false); //dec_active(); } } @@ -74,9 +78,9 @@ namespace netlist } protected: + using activate_delegate = plib::pmfp; - virtual void inc_active() noexcept { } - virtual void dec_active() noexcept { } + activate_delegate m_activate; log_type & log(); diff --git a/src/lib/netlist/core/exec.h b/src/lib/netlist/core/exec.h index 15a753593df..be796ab95fd 100644 --- a/src/lib/netlist/core/exec.h +++ b/src/lib/netlist/core/exec.h @@ -33,7 +33,7 @@ namespace netlist // run functions - netlist_time_ext time() const noexcept { return m_time; } + const netlist_time_ext &time() const noexcept { return m_time; } void process_queue(netlist_time_ext delta) noexcept; void abort_current_queue_slice() noexcept diff --git a/src/lib/netlist/core/logic.h b/src/lib/netlist/core/logic.h index 149af1a2efb..7bbcf5811d7 100644 --- a/src/lib/netlist/core/logic.h +++ b/src/lib/netlist/core/logic.h @@ -32,11 +32,11 @@ namespace netlist logic_t(device_t &dev, const pstring &aname, state_e terminal_state, nldelegate delegate); - constexpr logic_net_t & net() noexcept + logic_net_t & net() noexcept { return plib::downcast(core_terminal_t::net()); } - constexpr const logic_net_t & net() const noexcept + const logic_net_t & net() const noexcept { return plib::downcast(core_terminal_t::net()); } @@ -52,9 +52,9 @@ namespace netlist logic_input_t(device_t &dev, const pstring &aname, nldelegate delegate); - constexpr const netlist_sig_t &operator()() const noexcept + const netlist_sig_t &operator()() const noexcept { - nl_assert(terminal_state() != STATE_INP_PASSIVE); + gsl_Expects(terminal_state() != STATE_INP_PASSIVE); #if NL_USE_COPY_INSTEAD_OF_REFERENCE return m_Q; #else @@ -122,6 +122,8 @@ namespace netlist void push(const netlist_sig_t &newQ, const netlist_time &delay) noexcept { + gsl_Expects(delay >= netlist_time::zero()); + m_my_net.set_Q_and_push(newQ, delay); // take the shortcut } diff --git a/src/lib/netlist/core/nets.h b/src/lib/netlist/core/nets.h index 2d17ebd8e04..8b1e81e7e24 100644 --- a/src/lib/netlist/core/nets.h +++ b/src/lib/netlist/core/nets.h @@ -72,51 +72,76 @@ namespace netlist if (!!is_queued()) exec().qremove(this); - const auto nst(exec().time() + delay); - m_next_scheduled_time = nst; + m_next_scheduled_time = exec().time() + delay; #if (AVOID_NOOP_QUEUE_PUSHES) m_in_queue = (m_list_active.empty() ? queue_status::DELAYED_DUE_TO_INACTIVE : (m_new_Q != m_cur_Q ? queue_status::QUEUED : queue_status::DELIVERED)); if (m_in_queue == queue_status::QUEUED) - exec().qpush(nst, this); + exec().qpush(m_next_scheduled_time, this); else update_inputs(); #else - if (!m_list_active.empty()) - { - m_in_queue = queue_status::QUEUED; - exec().qpush(nst, this); - } + m_in_queue = m_list_active.empty() ? queue_status::DELAYED_DUE_TO_INACTIVE : queue_status::QUEUED; + if (m_in_queue == queue_status::QUEUED) + exec().qpush(m_next_scheduled_time, this); else - { - m_in_queue = queue_status::DELAYED_DUE_TO_INACTIVE; update_inputs(); - } #endif } } - NVCC_CONSTEXPR bool is_queued() const noexcept { return m_in_queue == queue_status::QUEUED; } + bool is_queued() const noexcept { return m_in_queue == queue_status::QUEUED; } + + // ----------------------------------------------------------------------------- + // Very hot + // ----------------------------------------------------------------------------- template void update_devs() noexcept { - nl_assert(this->is_rail_net()); + gsl_Expects(this->is_rail_net()); m_in_queue = queue_status::DELIVERED; // mark as taken ... + const netlist_sig_t new_Q(m_new_Q); + const netlist_sig_t cur_Q(m_cur_Q); #if (!AVOID_NOOP_QUEUE_PUSHES) - if (m_new_Q ^ m_cur_Q) + if (new_Q ^ cur_Q) #endif { - process((m_new_Q << core_terminal_t::INP_LH_SHIFT) - | (m_cur_Q << core_terminal_t::INP_HL_SHIFT), m_new_Q); + const auto mask = (new_Q << core_terminal_t::INP_LH_SHIFT) + | (cur_Q << core_terminal_t::INP_HL_SHIFT); + m_cur_Q = new_Q; + + if (!KEEP_STATS) + { + for (auto &p : m_list_active) + { + p.set_copied_input(new_Q); + if ((p.terminal_state() & mask) != 0) + p.run_delegate(); + } + } + else + { + for (auto & p : m_list_active) + { + p.set_copied_input(new_Q); + auto *stats(p.device().stats()); + stats->m_stat_call_count.inc(); + if ((p.terminal_state() & mask)) + { + auto g(stats->m_stat_total_time.guard()); + p.run_delegate(); + } + } + } } } - netlist_time_ext next_scheduled_time() const noexcept { return m_next_scheduled_time; } + const netlist_time_ext &next_scheduled_time() const noexcept { return m_next_scheduled_time; } void set_next_scheduled_time(netlist_time_ext ntime) noexcept { m_next_scheduled_time = ntime; } - NVCC_CONSTEXPR bool is_rail_net() const noexcept { return !(m_railterminal == nullptr); } + bool is_rail_net() const noexcept { return !(m_railterminal == nullptr); } core_terminal_t & railterminal() const noexcept { return *m_railterminal; } bool has_connections() const noexcept { return !m_core_terms.empty(); } @@ -196,7 +221,7 @@ namespace netlist protected: // only used for logic nets - NVCC_CONSTEXPR const netlist_sig_t &Q() const noexcept { return m_cur_Q; } + const netlist_sig_t &Q() const noexcept { return m_cur_Q; } // only used for logic nets void initial(netlist_sig_t val) noexcept @@ -208,6 +233,8 @@ namespace netlist // only used for logic nets void set_Q_and_push(const netlist_sig_t &newQ, const netlist_time &delay) noexcept { + gsl_Expects(delay >= netlist_time::zero()); + if (newQ != m_new_Q) { m_new_Q = newQ; @@ -218,6 +245,8 @@ namespace netlist // only used for logic nets void set_Q_time(const netlist_sig_t &newQ, const netlist_time_ext &at) noexcept { + gsl_Expects(at >= netlist_time_ext::zero()); + if (newQ != m_new_Q) { m_in_queue = queue_status::DELAYED_DUE_TO_INACTIVE; @@ -236,45 +265,12 @@ namespace netlist state_var m_new_Q; state_var m_cur_Q; state_var m_in_queue; + plib::linkedlist_t m_list_active; state_var m_next_scheduled_time; core_terminal_t * m_railterminal; - plib::linkedlist_t m_list_active; std::vector m_core_terms; // save post-start m_list ... - // ----------------------------------------------------------------------------- - // Very hot - // ----------------------------------------------------------------------------- - - template - void process(const T &mask, const S &sig) noexcept - { - m_cur_Q = sig; - - if (KEEP_STATS) - { - for (auto & p : m_list_active) - { - p.set_copied_input(sig); - auto *stats(p.device().stats()); - stats->m_stat_call_count.inc(); - if ((p.terminal_state() & mask)) - { - auto g(stats->m_stat_total_time.guard()); - p.run_delegate(); - } - } - } - else - { - for (auto &p : m_list_active) - { - p.set_copied_input(sig); - if ((p.terminal_state() & mask) != 0) - p.run_delegate(); - } - } - } }; } // namespace detail @@ -286,10 +282,10 @@ namespace netlist void reset() noexcept override; - nl_fptype Q_Analog() const noexcept { return m_cur_Analog; } + const nl_fptype &Q_Analog() const noexcept { return m_cur_Analog; } void set_Q_Analog(nl_fptype v) noexcept { m_cur_Analog = v; } // used by solver code ... - nl_fptype *Q_Analog_state_ptr() noexcept { return &m_cur_Analog(); } + nl_fptype *Q_Analog_state_ptr() noexcept { return *m_cur_Analog; } //FIXME: needed by current solver code solver::matrix_solver_t *solver() const noexcept { return m_solver; } diff --git a/src/lib/netlist/core/param.h b/src/lib/netlist/core/param.h index 2007d1f844d..dbabef073e7 100644 --- a/src/lib/netlist/core/param.h +++ b/src/lib/netlist/core/param.h @@ -79,8 +79,8 @@ namespace netlist param_num_t(core_device_t &device, const pstring &name, T val) noexcept(false); - T operator()() const noexcept { return m_param; } - operator T() const noexcept { return m_param; } + constexpr const T &operator()() const noexcept { return m_param; } + constexpr operator const T& () const noexcept { return m_param; } void set(const T ¶m) noexcept { set_and_update_param(m_param, param); } diff --git a/src/lib/netlist/core/state_var.h b/src/lib/netlist/core/state_var.h index 55db73c1ac2..5839de26748 100644 --- a/src/lib/netlist/core/state_var.h +++ b/src/lib/netlist/core/state_var.h @@ -61,7 +61,8 @@ namespace netlist //! Assignment operator to assign value of type T. constexpr state_var &operator=(const T &rhs) noexcept { m_value = rhs; return *this; } //! Assignment move operator to assign value of type T. - constexpr state_var &operator=(T &&rhs) noexcept { std::swap(m_value, rhs); return *this; } + //constexpr state_var &operator=(T &&rhs) noexcept { std::swap(m_value, rhs); return *this; } + constexpr state_var &operator=(T &&rhs) noexcept { m_value = std::move(rhs); return *this; } //! Return non-const value of state variable. constexpr operator T & () noexcept { return m_value; } //! Return const value of state variable. @@ -78,6 +79,10 @@ namespace netlist constexpr T * operator->() noexcept { return &m_value; } //! Access state variable by const ->. constexpr const T * operator->() const noexcept{ return &m_value; } + //! Access state variable by *. + constexpr T * operator *() noexcept { return &m_value; } + //! Access state variable by const *. + constexpr const T * operator *() const noexcept{ return &m_value; } private: T m_value; diff --git a/src/lib/netlist/devices/nld_7448.cpp b/src/lib/netlist/devices/nld_7448.cpp index 992caf9d814..f4acbc432bd 100644 --- a/src/lib/netlist/devices/nld_7448.cpp +++ b/src/lib/netlist/devices/nld_7448.cpp @@ -54,7 +54,7 @@ namespace netlist private: void update_outputs(unsigned v) noexcept { - nl_assert(v<16); + gsl_Expects(v<16); if (v != m_state) { // max transfer time is 100 NS */ diff --git a/src/lib/netlist/devices/nld_7493.cpp b/src/lib/netlist/devices/nld_7493.cpp index 1f22ce27fe8..54d44dc1fea 100644 --- a/src/lib/netlist/devices/nld_7493.cpp +++ b/src/lib/netlist/devices/nld_7493.cpp @@ -62,7 +62,7 @@ namespace netlist namespace devices { - static const std::array out_delay { NLTIME_FROM_NS(18), NLTIME_FROM_NS(36), NLTIME_FROM_NS(54) }; + static constexpr std::array out_delay { NLTIME_FROM_NS(18), NLTIME_FROM_NS(36), NLTIME_FROM_NS(54) }; NETLIB_OBJECT(7493) { diff --git a/src/lib/netlist/devices/nld_log.cpp b/src/lib/netlist/devices/nld_log.cpp index 75a22ddca32..c2a6523f64a 100644 --- a/src/lib/netlist/devices/nld_log.cpp +++ b/src/lib/netlist/devices/nld_log.cpp @@ -116,8 +116,8 @@ namespace netlist netlist_time_ext t; nl_fptype v; }; - static const std::size_t BUF_SIZE=16384; - static const std::size_t BUFFERS=4; + static constexpr std::size_t BUF_SIZE=16384; + static constexpr std::size_t BUFFERS=4; analog_input_t m_I; plib::ofstream m_strm; plib::putf8_writer m_writer; diff --git a/src/lib/netlist/devices/nld_system.cpp b/src/lib/netlist/devices/nld_system.cpp index c3f4cd5d270..36ae9bc6e35 100644 --- a/src/lib/netlist/devices/nld_system.cpp +++ b/src/lib/netlist/devices/nld_system.cpp @@ -62,7 +62,7 @@ namespace devices NETLIB_RESETI() { m_cnt = 0; - m_off = netlist_time::from_fp(m_offset()); + m_off = netlist_time::from_fp(m_offset()); m_feedback.set_delegate(NETLIB_DELEGATE(first)); } //NETLIB_UPDATE_PARAMI(); diff --git a/src/lib/netlist/devices/nlid_proxy.cpp b/src/lib/netlist/devices/nlid_proxy.cpp index 51eb0fbf5cd..fb93d642a79 100644 --- a/src/lib/netlist/devices/nlid_proxy.cpp +++ b/src/lib/netlist/devices/nlid_proxy.cpp @@ -21,7 +21,7 @@ namespace netlist // nld_base_proxy // ----------------------------------------------------------------------------- - static const std::array, 3> power_syms = {{ {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}}}; + static constexpr std::array, 3> power_syms = {{ {"VCC", "VEE"}, {"VCC", "GND"}, {"VDD", "VSS"}}}; nld_base_proxy::nld_base_proxy(netlist_state_t &anetlist, const pstring &name, const logic_t *inout_proxied) diff --git a/src/lib/netlist/devices/nlid_truthtable.cpp b/src/lib/netlist/devices/nlid_truthtable.cpp index 8b5e3a937c2..74e0f37c92b 100644 --- a/src/lib/netlist/devices/nlid_truthtable.cpp +++ b/src/lib/netlist/devices/nlid_truthtable.cpp @@ -52,6 +52,8 @@ namespace devices /* FIXME: the family should provide the names of the power-terminals! */ , m_power_pins(*this) { + m_activate = activate_delegate(& NETLIB_NAME(truthtable_t) :: incdec_active, this); + set_hint_deactivate(true); init(desc); } @@ -100,16 +102,18 @@ namespace devices } #endif - void inc_active() noexcept override + void incdec_active(bool a) noexcept { - process(); - } - - void dec_active() noexcept override - { - for (std::size_t i = 0; i< m_NI; i++) - m_I[i].inactivate(); - m_ign = (1<(); + } + else + { + for (std::size_t i = 0; i< m_NI; i++) + m_I[i].inactivate(); + m_ign = (1< @@ -371,8 +375,6 @@ namespace devices template void NETLIB_NAME(truthtable_t)::init(const std::vector &desc) { - set_hint_deactivate(true); - pstring header = desc[0]; std::vector io(plib::psplit(header,'|')); diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp index d0a0e707aaf..10dc7cf635c 100644 --- a/src/lib/netlist/nl_base.cpp +++ b/src/lib/netlist/nl_base.cpp @@ -1029,12 +1029,14 @@ namespace netlist } m_time = top->exec_time(); - auto *const obj(top->object()); + detail::net_t *const obj(top->object()); m_queue.pop(); - if (obj != nullptr) - obj->template update_devs(); - else + + if (!!(obj == nullptr)) break; + + obj->template update_devs(); + if (KEEP_STATS) m_perf_out_processed.inc(); } while (true); diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp index 3a2ba38d921..11584bceb48 100644 --- a/src/lib/netlist/nl_setup.cpp +++ b/src/lib/netlist/nl_setup.cpp @@ -716,7 +716,7 @@ param_ref_t setup_t::find_param(const pstring ¶m_in) const //NOLINTNEXTLINE(misc-no-recursion) devices::nld_base_proxy *setup_t::get_d_a_proxy(const detail::core_terminal_t &out) { - nl_assert(out.is_logic()); + gsl_Expects(out.is_logic()); const auto &out_cast = dynamic_cast(out); auto iter_proxy(m_proxies.find(&out)); @@ -759,7 +759,7 @@ devices::nld_base_proxy *setup_t::get_d_a_proxy(const detail::core_terminal_t &o //NOLINTNEXTLINE(misc-no-recursion) devices::nld_base_proxy *setup_t::get_a_d_proxy(detail::core_terminal_t &inp) { - nl_assert(inp.is_logic()); + gsl_Expects(inp.is_logic()); const auto &incast = dynamic_cast(inp); @@ -1607,13 +1607,10 @@ void setup_t::prepare_to_run() if (p != m_abstract.m_hints.end()) { p->second = true; // mark as used - if (use_deactivate) - d.second->set_hint_deactivate(false); - else - d.second->set_hint_deactivate(true); + d.second->set_hint_deactivate(false); } else - d.second->set_hint_deactivate(true); + d.second->set_hint_deactivate(use_deactivate); } if (errcnt > 0) diff --git a/src/lib/netlist/plib/pgsl.h b/src/lib/netlist/plib/pgsl.h index 1ea8622d19c..4ddc957b9ac 100644 --- a/src/lib/netlist/plib/pgsl.h +++ b/src/lib/netlist/plib/pgsl.h @@ -36,10 +36,24 @@ #define gsl_Expects(e) ((e) ? static_cast(0) : static_cast(0)) #endif -#if 0 +#if 1 +// FIXME: __builtin_unreachable contrary to google sources does not seem to be of +// any use and decreases performance slightly. Convert gsl_Expects to a noop +// and revisit in the future. #undef gsl_Expects #define gsl_Expects(e) do {} while (0) + +#if 0 +// Alternative and c++ style implementation. Suffers from the same drawbacks +// like __builtin_unreachable +static constexpr inline void gsl_Expects(const bool &e) +{ + if (!e) + __builtin_unreachable(); +} #endif +#endif + #define gsl_Ensures(e) gsl_Expects(e) namespace plib { @@ -56,7 +70,7 @@ namespace plib { /// \brief perform a narrowing cast without checks /// template - inline constexpr T narrow_cast(O && v) noexcept + constexpr T narrow_cast(O && v) noexcept { static_assert(plib::is_arithmetic::value && std::is_convertible, T>::value, "narrow cast expects conversion between arithmetic types"); return static_cast(std::forward(v)); @@ -66,7 +80,7 @@ namespace plib { /// /// The c++ core guidelines require the narrow function to raise an error /// This will make narrow noexcept(false). This has shown to have a - /// measurable impact on performance and thus we deviate we deviate from + /// measurable impact on performance and thus we deviate from /// the standard here. /// template @@ -86,7 +100,7 @@ namespace plib { } // namespace pgsl - /// \brief downcast from base tpye to derived type + /// \brief downcast from base type to derived type /// /// The cpp core guidelines require a very careful use of static cast /// for downcast operations. This template is used to identify these uses diff --git a/src/lib/netlist/plib/pmulti_threading.h b/src/lib/netlist/plib/pmulti_threading.h index c844086313c..7c58a936636 100644 --- a/src/lib/netlist/plib/pmulti_threading.h +++ b/src/lib/netlist/plib/pmulti_threading.h @@ -24,7 +24,6 @@ namespace plib { { public: inline pspin_mutex() noexcept = default; - inline ~pspin_mutex() noexcept = default; inline void lock() noexcept{ while (m_lock.test_and_set(std::memory_order_acquire)) { } } inline void unlock() noexcept { m_lock.clear(std::memory_order_release); } private: @@ -37,7 +36,6 @@ namespace plib { { public: inline pspin_mutex() noexcept = default; - inline ~pspin_mutex() noexcept = default; static inline void lock() /*const*/ noexcept { } static inline void unlock() /*const*/ noexcept { } }; diff --git a/src/lib/netlist/plib/ptimed_queue.h b/src/lib/netlist/plib/ptimed_queue.h index 13631dfe20a..9df8a8fcd83 100644 --- a/src/lib/netlist/plib/ptimed_queue.h +++ b/src/lib/netlist/plib/ptimed_queue.h @@ -36,7 +36,7 @@ namespace plib { struct pqentry_t final { constexpr pqentry_t() noexcept : m_exec_time(), m_object(nullptr) { } - constexpr pqentry_t(Time t, Element o) noexcept : m_exec_time(t), m_object(o) { } + constexpr pqentry_t(const Time &t, const Element &o) noexcept : m_exec_time(t), m_object(o) { } PCOPYASSIGNMOVE(pqentry_t, default) @@ -64,8 +64,8 @@ namespace plib { static constexpr pqentry_t never() noexcept { return pqentry_t(Time::never(), nullptr); } - constexpr Time exec_time() const noexcept { return m_exec_time; } - constexpr Element object() const noexcept { return m_object; } + constexpr const Time &exec_time() const noexcept { return m_exec_time; } + constexpr const Element &object() const noexcept { return m_object; } private: Time m_exec_time; Element m_object; -- cgit v1.2.3