diff options
Diffstat (limited to 'src/lib/netlist/nl_lists.h')
-rw-r--r-- | src/lib/netlist/nl_lists.h | 168 |
1 files changed, 79 insertions, 89 deletions
diff --git a/src/lib/netlist/nl_lists.h b/src/lib/netlist/nl_lists.h index 8417d1231dc..61fb03d3ec9 100644 --- a/src/lib/netlist/nl_lists.h +++ b/src/lib/netlist/nl_lists.h @@ -49,43 +49,64 @@ namespace netlist void unlock() const noexcept { } }; -#if !USE_HEAP template <class Element, class Time> - class timed_queue : plib::nocopyassignmove + struct pqentry_t final { - public: + constexpr pqentry_t() noexcept : m_exec_time(), m_object(nullptr) { } + constexpr pqentry_t(const Time &t, const Element &o) noexcept : m_exec_time(t), m_object(o) { } + constexpr pqentry_t(const pqentry_t &e) noexcept : m_exec_time(e.m_exec_time), m_object(e.m_object) { } + pqentry_t(pqentry_t &&e) noexcept { swap(e); } + ~pqentry_t() = default; + + pqentry_t& operator=(pqentry_t && other) noexcept + { + swap(other); + return *this; + } + + pqentry_t& operator=(const pqentry_t &other) noexcept + { + pqentry_t t(other); + swap(t); + return *this; + } - struct entry_t final + void swap(pqentry_t &other) noexcept { - constexpr entry_t() noexcept : m_exec_time(), m_object(nullptr) { } - constexpr entry_t(const Time &t, const Element &o) noexcept : m_exec_time(t), m_object(o) { } - constexpr entry_t(const entry_t &e) noexcept : m_exec_time(e.m_exec_time), m_object(e.m_object) { } - entry_t(entry_t &&e) noexcept { swap(e); } - ~entry_t() = default; + std::swap(m_exec_time, other.m_exec_time); + std::swap(m_object, other.m_object); + } - entry_t& operator=(entry_t && other) noexcept + struct QueueOp + { + static constexpr bool less(const pqentry_t &lhs, const pqentry_t &rhs) noexcept { - swap(other); - return *this; + return (lhs.m_exec_time < rhs.m_exec_time); } - entry_t& operator=(const entry_t &other) noexcept + static constexpr bool equal(const pqentry_t &lhs, const pqentry_t &rhs) noexcept { - entry_t t(other); - swap(t); - return *this; + return lhs.m_object == rhs.m_object; } - void swap(entry_t &other) noexcept + static constexpr bool equal(const pqentry_t &lhs, const Element &rhs) noexcept { - std::swap(m_exec_time, other.m_exec_time); - std::swap(m_object, other.m_object); + return lhs.m_object == rhs; } - Time m_exec_time; - Element m_object; + static constexpr pqentry_t never() noexcept { return pqentry_t(Time::never(), nullptr); } }; + Time m_exec_time; + Element m_object; + }; + +#if !USE_HEAP + template <class T, class QueueOp = typename T::QueueOp> + class timed_queue : plib::nocopyassignmove + { + public: + timed_queue(const std::size_t list_size) : m_list(list_size) { @@ -95,12 +116,12 @@ namespace netlist constexpr std::size_t capacity() const noexcept { return m_list.capacity() - 1; } constexpr bool empty() const noexcept { return (m_end == &m_list[1]); } - void push(entry_t &&e) noexcept + void push(T &&e) noexcept { /* Lock */ tqlock lck(m_lock); - entry_t * i = m_end; - for (; e.m_exec_time > (i - 1)->m_exec_time; --i) + T * i = m_end; + for (; QueueOp::less(*(i - 1), e); --i) { *(i) = *(i-1); m_prof_sortmove.inc(); @@ -110,16 +131,17 @@ namespace netlist m_prof_call.inc(); } - entry_t pop() noexcept { return *(--m_end); } - const entry_t &top() const noexcept { return *(m_end-1); } + void pop() noexcept { --m_end; } + const T &top() const noexcept { return *(m_end-1); } - void remove(const Element &elem) noexcept + template <class R> + void remove(const R &elem) noexcept { /* Lock */ tqlock lck(m_lock); - for (entry_t * i = m_end - 1; i > &m_list[0]; i--) + for (T * i = m_end - 1; i > &m_list[0]; i--) { - if (i->m_object == elem) + if (QueueOp::equal(*i, elem)) { m_end--; for (;i < m_end; i++) @@ -129,21 +151,21 @@ namespace netlist } } - void retime(const Element &elem, const Time t) noexcept + void retime(const T &elem) noexcept { /* Lock */ tqlock lck(m_lock); - for (entry_t * i = m_end - 1; i > &m_list[0]; i--) + for (T * i = m_end - 1; i > &m_list[0]; i--) { - if (i->m_object == elem) + if (QueueOp::equal(*i, elem)) // partial equal! { - i->m_exec_time = t; - while ((i-1)->m_exec_time < i->m_exec_time) + *i = elem; + while (QueueOp::less(*(i-1), *i)) { std::swap(*(i-1), *i); i--; } - while (i < m_end && (i+1)->m_exec_time > i->m_exec_time) + while (i < m_end && QueueOp::less(*i, *(i+1))) { std::swap(*(i+1), *i); i++; @@ -161,15 +183,15 @@ namespace netlist * the insert algo above will run into this element and doesn't * need a comparison with queue start. */ - m_list[0] = { Time::never(), Element(0) }; + m_list[0] = QueueOp::never(); m_end++; } // save state support & mame disasm - constexpr const entry_t *listptr() const { return &m_list[1]; } + constexpr const T *listptr() const { return &m_list[1]; } constexpr std::size_t size() const noexcept { return static_cast<std::size_t>(m_end - &m_list[1]); } - constexpr const entry_t & operator[](const std::size_t index) const { return m_list[ 1 + index]; } + constexpr const T & operator[](const std::size_t index) const { return m_list[ 1 + index]; } private: #if HAS_OPENMP && USE_OPENMP using tqmutex = pspin_mutex<true>; @@ -179,8 +201,8 @@ namespace netlist using tqlock = std::lock_guard<tqmutex>; tqmutex m_lock; - entry_t * m_end; - std::vector<entry_t> m_list; + T * m_end; + std::vector<T> m_list; public: // profiling @@ -188,45 +210,14 @@ namespace netlist nperfcount_t m_prof_call; }; #else - template <class Element, class Time> + template <class T, class QueueOp = typename T::QueueOp> class timed_queue : plib::nocopyassignmove { public: - struct entry_t final - { - constexpr entry_t() noexcept : m_exec_time(), m_object(nullptr) { } - constexpr entry_t(const Time &t, const Element &o) noexcept : m_exec_time(t), m_object(o) { } - constexpr entry_t(const entry_t &e) noexcept : m_exec_time(e.m_exec_time), m_object(e.m_object) { } - entry_t(entry_t &&e) noexcept { swap(e); } - ~entry_t() = default; - - entry_t& operator=(entry_t && other) noexcept - { - swap(other); - return *this; - } - - entry_t& operator=(const entry_t &other) noexcept - { - entry_t t(other); - swap(t); - return *this; - } - - void swap(entry_t &other) noexcept - { - std::swap(m_exec_time, other.m_exec_time); - std::swap(m_object, other.m_object); - } - - Time m_exec_time; - Element m_object; - }; - struct compare { - bool operator()(const entry_t &a, const entry_t &b) { return a.m_exec_time > b.m_exec_time; } + bool operator()(const T &a, const T &b) { return QueueOp::less(b,a); } }; timed_queue(const std::size_t list_size) @@ -238,7 +229,7 @@ namespace netlist constexpr std::size_t capacity() const noexcept { return m_list.capacity(); } constexpr bool empty() const noexcept { return &m_list[0] == m_end; } - void push(entry_t &&e) noexcept + void push(T &&e) noexcept { /* Lock */ tqlock lck(m_lock); @@ -247,23 +238,22 @@ namespace netlist m_prof_call.inc(); } - entry_t pop() noexcept + void pop() noexcept { - entry_t t(m_list[0]); std::pop_heap(&m_list[0], m_end, compare()); m_end--; - return t; } - const entry_t &top() const noexcept { return m_list[0]; } + const T &top() const noexcept { return m_list[0]; } - void remove(const Element &elem) noexcept + template <class R> + void remove(const R &elem) noexcept { /* Lock */ tqlock lck(m_lock); - for (entry_t * i = m_end - 1; i >= &m_list[0]; i--) + for (T * i = m_end - 1; i >= &m_list[0]; i--) { - if (i->m_object == elem) + if (QueueOp::equal(*i, elem)) { m_end--; for (;i < m_end; i++) @@ -274,15 +264,15 @@ namespace netlist } } - void retime(const Element &elem, const Time t) noexcept + void retime(const T &elem) noexcept { /* Lock */ tqlock lck(m_lock); - for (entry_t * i = m_end - 1; i >= &m_list[0]; i--) + for (T * i = m_end - 1; i >= &m_list[0]; i--) { - if (i->m_object == elem) + if (QueueOp::equal(*i, elem)) // partial equal! { - i->m_exec_time = t; + *i = elem; std::make_heap(&m_list[0], m_end, compare()); return; } @@ -298,9 +288,9 @@ namespace netlist // save state support & mame disasm - constexpr const entry_t *listptr() const { return &m_list[0]; } + constexpr const T *listptr() const { return &m_list[0]; } constexpr std::size_t size() const noexcept { return m_list.size(); } - constexpr const entry_t & operator[](const std::size_t index) const { return m_list[ 0 + index]; } + constexpr const T & operator[](const std::size_t index) const { return m_list[ 0 + index]; } private: #if HAS_OPENMP && USE_OPENMP using tqmutex = pspin_mutex<true>; @@ -310,8 +300,8 @@ namespace netlist using tqlock = std::lock_guard<tqmutex>; tqmutex m_lock; - std::vector<entry_t> m_list; - entry_t *m_end; + std::vector<T> m_list; + T *m_end; public: // profiling |