mirror of
https://github.com/holub/mame
synced 2025-10-04 16:34:53 +03:00
Netlist: code maintenance and bug fixes. (nw)
- solver now uses dynamic allocation on systems larger than 512x512 - fixed osx build - moved nl_lists.h classes to plists.h - fixed netlist makefile clint section - readability and typos
This commit is contained in:
parent
da35541e84
commit
db318046c4
5
3rdparty/bgfx/src/renderer_gl.cpp
vendored
5
3rdparty/bgfx/src/renderer_gl.cpp
vendored
@ -5579,7 +5579,10 @@ BX_TRACE("%d, %d, %d, %s", _array, _srgb, _mipAutogen, getName(_format) );
|
|||||||
|
|
||||||
version = 0 == bx::strCmp(code, "#version 430", 12) ? 430 : version;
|
version = 0 == bx::strCmp(code, "#version 430", 12) ? 430 : version;
|
||||||
|
|
||||||
bx::write(&writer, &err, "#version %d\n", version);
|
if (version < 130)
|
||||||
|
bx::write(&writer, &err, "#version %d\n", 130);
|
||||||
|
else
|
||||||
|
bx::write(&writer, &err, "#version %d\n", version);
|
||||||
|
|
||||||
if (430 > version && usesTextureLod)
|
if (430 > version && usesTextureLod)
|
||||||
{
|
{
|
||||||
|
4
3rdparty/bgfx/src/renderer_vk.cpp
vendored
4
3rdparty/bgfx/src/renderer_vk.cpp
vendored
@ -3935,8 +3935,8 @@ VK_IMPORT_DEVICE
|
|||||||
{
|
{
|
||||||
attachments[mrt].colorAttachment = mrt;
|
attachments[mrt].colorAttachment = mrt;
|
||||||
attachments[mrt].aspectMask = 0;
|
attachments[mrt].aspectMask = 0;
|
||||||
attachments[mrt].aspectMask |= (_clear.m_flags & BGFX_CLEAR_DEPTH ) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0;
|
//attachments[mrt].aspectMask |= (_clear.m_flags & BGFX_CLEAR_DEPTH ) ? VK_IMAGE_ASPECT_DEPTH_BIT : 0;
|
||||||
attachments[mrt].aspectMask |= (_clear.m_flags & BGFX_CLEAR_STENCIL) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0;
|
//attachments[mrt].aspectMask |= (_clear.m_flags & BGFX_CLEAR_STENCIL) ? VK_IMAGE_ASPECT_STENCIL_BIT : 0;
|
||||||
|
|
||||||
attachments[mrt].clearValue.depthStencil.stencil = _clear.m_stencil;
|
attachments[mrt].clearValue.depthStencil.stencil = _clear.m_stencil;
|
||||||
attachments[mrt].clearValue.depthStencil.depth = _clear.m_depth;
|
attachments[mrt].clearValue.depthStencil.depth = _clear.m_depth;
|
||||||
|
@ -43,7 +43,6 @@ project "netlist"
|
|||||||
MAME_DIR .. "src/lib/netlist/nl_dice_compat.h",
|
MAME_DIR .. "src/lib/netlist/nl_dice_compat.h",
|
||||||
MAME_DIR .. "src/lib/netlist/nl_factory.cpp",
|
MAME_DIR .. "src/lib/netlist/nl_factory.cpp",
|
||||||
MAME_DIR .. "src/lib/netlist/nl_factory.h",
|
MAME_DIR .. "src/lib/netlist/nl_factory.h",
|
||||||
MAME_DIR .. "src/lib/netlist/nl_lists.h",
|
|
||||||
MAME_DIR .. "src/lib/netlist/nl_parser.cpp",
|
MAME_DIR .. "src/lib/netlist/nl_parser.cpp",
|
||||||
MAME_DIR .. "src/lib/netlist/nl_parser.h",
|
MAME_DIR .. "src/lib/netlist/nl_parser.h",
|
||||||
MAME_DIR .. "src/lib/netlist/nl_setup.cpp",
|
MAME_DIR .. "src/lib/netlist/nl_setup.cpp",
|
||||||
|
@ -23,10 +23,9 @@ TIDY_FLAGSX += -cppcoreguidelines-avoid-magic-numbers,
|
|||||||
TIDY_FLAGSX += -cppcoreguidelines-macro-usage,
|
TIDY_FLAGSX += -cppcoreguidelines-macro-usage,
|
||||||
TIDY_FLAGSX += -cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,
|
TIDY_FLAGSX += -cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,
|
||||||
TIDY_FLAGSX += -bugprone-macro-parentheses,-misc-macro-parentheses,
|
TIDY_FLAGSX += -bugprone-macro-parentheses,-misc-macro-parentheses,
|
||||||
TIDY_FLAGSX += -modernize-use-trailing-return-type
|
TIDY_FLAGSX += -bugprone-too-small-loop-variable,
|
||||||
TIDY_FLAGSX += -bugprone-too-small-loop-variable
|
TIDY_FLAGSX += -modernize-use-trailing-return-type,
|
||||||
TIDY_FLAGSX += -cppcoreguidelines-pro-bounds-array-to-pointer-decay
|
TIDY_FLAGSX += -cppcoreguidelines-pro-bounds-array-to-pointer-decay
|
||||||
TIDY_FLAGSX += -modernize-use-trailing-return-type
|
|
||||||
|
|
||||||
space :=
|
space :=
|
||||||
space +=
|
space +=
|
||||||
@ -60,7 +59,7 @@ LD = @g++
|
|||||||
MD = @mkdir
|
MD = @mkdir
|
||||||
RM = @rm
|
RM = @rm
|
||||||
DOXYGEN = @doxygen
|
DOXYGEN = @doxygen
|
||||||
CLANG_TIDY = clang-tidy-10
|
CLANG_TIDY = clang-tidy-9
|
||||||
|
|
||||||
TARGETS = nltool nlwav
|
TARGETS = nltool nlwav
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -16,15 +16,15 @@
|
|||||||
#include "plib/palloc.h" // owned_ptr
|
#include "plib/palloc.h" // owned_ptr
|
||||||
#include "plib/pdynlib.h"
|
#include "plib/pdynlib.h"
|
||||||
#include "plib/pfmtlog.h"
|
#include "plib/pfmtlog.h"
|
||||||
|
#include "plib/plists.h"
|
||||||
#include "plib/pmempool.h"
|
#include "plib/pmempool.h"
|
||||||
#include "plib/ppmf.h"
|
#include "plib/ppmf.h"
|
||||||
#include "plib/pstate.h"
|
#include "plib/pstate.h"
|
||||||
#include "plib/pstream.h"
|
#include "plib/pstream.h"
|
||||||
|
#include "plib/ptime.h"
|
||||||
|
|
||||||
#include "nl_errstr.h"
|
#include "nl_errstr.h"
|
||||||
#include "nl_lists.h"
|
|
||||||
#include "nltypes.h"
|
#include "nltypes.h"
|
||||||
#include "plib/ptime.h"
|
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -311,7 +311,6 @@ namespace netlist
|
|||||||
* state_var<unsigned> m_var;
|
* state_var<unsigned> m_var;
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct state_var
|
struct state_var
|
||||||
{
|
{
|
||||||
@ -591,14 +590,14 @@ namespace netlist
|
|||||||
|
|
||||||
nldelegate m_delegate;
|
nldelegate m_delegate;
|
||||||
#if USE_COPY_INSTEAD_OF_REFERENCE
|
#if USE_COPY_INSTEAD_OF_REFERENCE
|
||||||
void set_copied_input(netlist_sig_t val)
|
void set_copied_input(netlist_sig_t val) noexcept
|
||||||
{
|
{
|
||||||
m_Q = val;
|
m_Q = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
state_var_sig m_Q;
|
state_var_sig m_Q;
|
||||||
#else
|
#else
|
||||||
void set_copied_input(netlist_sig_t val) const { plib::unused_var(val); }
|
void set_copied_input(netlist_sig_t val) const noexcept { plib::unused_var(val); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -669,13 +668,13 @@ namespace netlist
|
|||||||
|
|
||||||
std::vector<core_terminal_t *> &core_terms() { return m_core_terms; }
|
std::vector<core_terminal_t *> &core_terms() { return m_core_terms; }
|
||||||
#if USE_COPY_INSTEAD_OF_REFERENCE
|
#if USE_COPY_INSTEAD_OF_REFERENCE
|
||||||
void update_inputs()
|
void update_inputs() noexcept
|
||||||
{
|
{
|
||||||
for (auto & term : m_core_terms)
|
for (auto & term : m_core_terms)
|
||||||
term->m_Q = m_cur_Q;
|
term->m_Q = m_cur_Q;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
void update_inputs() const
|
void update_inputs() const noexcept
|
||||||
{
|
{
|
||||||
/* nothing needs to be done */
|
/* nothing needs to be done */
|
||||||
}
|
}
|
||||||
@ -810,9 +809,9 @@ namespace netlist
|
|||||||
logic_t(core_device_t &dev, const pstring &aname,
|
logic_t(core_device_t &dev, const pstring &aname,
|
||||||
const state_e state, nldelegate delegate = nldelegate());
|
const state_e state, nldelegate delegate = nldelegate());
|
||||||
|
|
||||||
bool has_proxy() const { return (m_proxy != nullptr); }
|
bool has_proxy() const noexcept { return (m_proxy != nullptr); }
|
||||||
devices::nld_base_proxy *get_proxy() const { return m_proxy; }
|
devices::nld_base_proxy *get_proxy() const noexcept { return m_proxy; }
|
||||||
void set_proxy(devices::nld_base_proxy *proxy) { m_proxy = proxy; }
|
void set_proxy(devices::nld_base_proxy *proxy) noexcept { m_proxy = proxy; }
|
||||||
|
|
||||||
logic_net_t & net() NL_NOEXCEPT;
|
logic_net_t & net() NL_NOEXCEPT;
|
||||||
const logic_net_t & net() const NL_NOEXCEPT;
|
const logic_net_t & net() const NL_NOEXCEPT;
|
||||||
@ -901,13 +900,13 @@ namespace netlist
|
|||||||
|
|
||||||
analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr = nullptr);
|
analog_net_t(netlist_state_t &nl, const pstring &aname, detail::core_terminal_t *mr = nullptr);
|
||||||
|
|
||||||
nl_double Q_Analog() const NL_NOEXCEPT { return m_cur_Analog; }
|
nl_double Q_Analog() const noexcept { return m_cur_Analog; }
|
||||||
void set_Q_Analog(const nl_double v) NL_NOEXCEPT { m_cur_Analog = v; }
|
void set_Q_Analog(const nl_double v) noexcept { m_cur_Analog = v; }
|
||||||
nl_double *Q_Analog_state_ptr() NL_NOEXCEPT { return m_cur_Analog.ptr(); }
|
nl_double *Q_Analog_state_ptr() NL_NOEXCEPT { return m_cur_Analog.ptr(); }
|
||||||
|
|
||||||
//FIXME: needed by current solver code
|
//FIXME: needed by current solver code
|
||||||
devices::matrix_solver_t *solver() const NL_NOEXCEPT { return m_solver; }
|
devices::matrix_solver_t *solver() const noexcept { return m_solver; }
|
||||||
void set_solver(devices::matrix_solver_t *solver) NL_NOEXCEPT { m_solver = solver; }
|
void set_solver(devices::matrix_solver_t *solver) noexcept { m_solver = solver; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
state_var<nl_double> m_cur_Analog;
|
state_var<nl_double> m_cur_Analog;
|
||||||
@ -1200,9 +1199,9 @@ namespace netlist
|
|||||||
struct stats_t
|
struct stats_t
|
||||||
{
|
{
|
||||||
// NL_KEEP_STATISTICS
|
// NL_KEEP_STATISTICS
|
||||||
nperftime_t<true> m_stat_total_time;
|
plib::pperftime_t<true> m_stat_total_time;
|
||||||
nperfcount_t<true> m_stat_call_count;
|
plib::pperfcount_t<true> m_stat_call_count;
|
||||||
nperfcount_t<true> m_stat_inc_active;
|
plib::pperfcount_t<true> m_stat_inc_active;
|
||||||
};
|
};
|
||||||
|
|
||||||
unique_pool_ptr<stats_t> m_stats;
|
unique_pool_ptr<stats_t> m_stats;
|
||||||
@ -1245,8 +1244,8 @@ namespace netlist
|
|||||||
|
|
||||||
~device_t() noexcept override = default;
|
~device_t() noexcept override = default;
|
||||||
|
|
||||||
setup_t &setup();
|
setup_t &setup() noexcept;
|
||||||
const setup_t &setup() const;
|
const setup_t &setup() const noexcept;
|
||||||
|
|
||||||
template<class C, typename... Args>
|
template<class C, typename... Args>
|
||||||
void create_and_register_subdevice(const pstring &name, unique_pool_ptr<C> &dev, Args&&... args)
|
void create_and_register_subdevice(const pstring &name, unique_pool_ptr<C> &dev, Args&&... args)
|
||||||
@ -1283,6 +1282,16 @@ namespace netlist
|
|||||||
family_setter_t(core_device_t &dev, const logic_family_desc_t *desc);
|
family_setter_t(core_device_t &dev, const logic_family_desc_t *desc);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class T, bool TS>
|
||||||
|
using timed_queue = plib::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>
|
||||||
|
//using timed_queue = timed_queue_heap<T, TS>;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// queue_t
|
// queue_t
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -1292,13 +1301,13 @@ namespace netlist
|
|||||||
*/
|
*/
|
||||||
class detail::queue_t :
|
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, NL_KEEP_STATISTICS>,
|
||||||
public timed_queue<pqentry_t<net_t *, netlist_time>, false>,
|
public timed_queue<plib::pqentry_t<net_t *, netlist_time>, false>,
|
||||||
public detail::netlist_ref,
|
public detail::netlist_ref,
|
||||||
public plib::state_manager_t::callback_t
|
public plib::state_manager_t::callback_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using base_queue = timed_queue<pqentry_t<net_t *, netlist_time>, false>;
|
using base_queue = timed_queue<plib::pqentry_t<net_t *, netlist_time>, false>;
|
||||||
using entry_t = pqentry_t<net_t *, netlist_time>;
|
using entry_t = plib::pqentry_t<net_t *, netlist_time>;
|
||||||
explicit queue_t(netlist_state_t &nl);
|
explicit queue_t(netlist_state_t &nl);
|
||||||
virtual ~queue_t() noexcept = default;
|
virtual ~queue_t() noexcept = default;
|
||||||
|
|
||||||
@ -1342,7 +1351,7 @@ namespace netlist
|
|||||||
friend class netlist_t; // allow access to private members
|
friend class netlist_t; // allow access to private members
|
||||||
|
|
||||||
template<class C>
|
template<class C>
|
||||||
static bool check_class(core_device_t *p)
|
static bool check_class(core_device_t *p) noexcept
|
||||||
{
|
{
|
||||||
return dynamic_cast<C *>(p) != nullptr;
|
return dynamic_cast<C *>(p) != nullptr;
|
||||||
}
|
}
|
||||||
@ -1385,12 +1394,12 @@ namespace netlist
|
|||||||
|
|
||||||
/* logging and name */
|
/* logging and name */
|
||||||
|
|
||||||
pstring name() const { return m_name; }
|
pstring name() const noexcept { return m_name; }
|
||||||
|
|
||||||
log_type & log() { return m_log; }
|
log_type & log() noexcept { return m_log; }
|
||||||
const log_type &log() const { return m_log; }
|
const log_type &log() const noexcept { return m_log; }
|
||||||
|
|
||||||
plib::dynlib &lib() { return *m_lib; }
|
plib::dynlib &lib() const noexcept { return *m_lib; }
|
||||||
|
|
||||||
netlist_t &exec() { return m_netlist; }
|
netlist_t &exec() { return m_netlist; }
|
||||||
const netlist_t &exec() const { return m_netlist; }
|
const netlist_t &exec() const { return m_netlist; }
|
||||||
@ -1486,16 +1495,19 @@ namespace netlist
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_t &setup() NL_NOEXCEPT { return *m_setup; }
|
setup_t &setup() noexcept { return *m_setup; }
|
||||||
const setup_t &setup() const NL_NOEXCEPT { return *m_setup; }
|
const setup_t &setup() const noexcept { return *m_setup; }
|
||||||
|
|
||||||
// FIXME: make a postload member and include code there
|
// FIXME: make a postload member and include code there
|
||||||
void rebuild_lists(); /* must be called after post_load ! */
|
void rebuild_lists(); /* must be called after post_load ! */
|
||||||
|
|
||||||
static void compile_defines(std::vector<std::pair<pstring, pstring>> &defs);
|
static void compile_defines(std::vector<std::pair<pstring, pstring>> &defs);
|
||||||
|
|
||||||
nets_collection_type & nets() { return m_nets; }
|
nets_collection_type & nets() noexcept { return m_nets; }
|
||||||
devices_collection_type & devices() { return m_devices; }
|
const nets_collection_type & nets() const noexcept { return m_nets; }
|
||||||
|
|
||||||
|
devices_collection_type & devices() noexcept { return m_devices; }
|
||||||
|
const devices_collection_type & devices() const noexcept { return m_devices; }
|
||||||
|
|
||||||
/* sole use is to manage lifetime of family objects */
|
/* sole use is to manage lifetime of family objects */
|
||||||
std::unordered_map<pstring, plib::unique_ptr<logic_family_desc_t>> m_family_cache;
|
std::unordered_map<pstring, plib::unique_ptr<logic_family_desc_t>> m_family_cache;
|
||||||
@ -1549,12 +1561,13 @@ namespace netlist
|
|||||||
|
|
||||||
const detail::queue_t &queue() const NL_NOEXCEPT { return m_queue; }
|
const detail::queue_t &queue() const NL_NOEXCEPT { return m_queue; }
|
||||||
|
|
||||||
void qpush(detail::queue_t::entry_t && e) noexcept
|
template <typename E>
|
||||||
|
void qpush(E && e) noexcept
|
||||||
{
|
{
|
||||||
if (!USE_QUEUE_STATS || !m_use_stats)
|
if (!USE_QUEUE_STATS || !m_use_stats)
|
||||||
m_queue.push<false>(std::move(e)); // NOLINT(performance-move-const-arg)
|
m_queue.push<false>(std::forward<E>(e)); // NOLINT(performance-move-const-arg)
|
||||||
else
|
else
|
||||||
m_queue.push<true>(std::move(e)); // NOLINT(performance-move-const-arg)
|
m_queue.push<true>(std::forward<E>(e)); // NOLINT(performance-move-const-arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class R>
|
template <class R>
|
||||||
@ -1573,10 +1586,10 @@ namespace netlist
|
|||||||
|
|
||||||
/* state handling */
|
/* state handling */
|
||||||
|
|
||||||
plib::state_manager_t &run_state_manager() { return m_state->run_state_manager(); }
|
plib::state_manager_t &run_state_manager() noexcept { return m_state->run_state_manager(); }
|
||||||
|
|
||||||
/* only used by nltool to create static c-code */
|
/* only used by nltool to create static c-code */
|
||||||
devices::NETLIB_NAME(solver) *solver() const NL_NOEXCEPT { return m_solver; }
|
devices::NETLIB_NAME(solver) *solver() const noexcept { return m_solver; }
|
||||||
|
|
||||||
/* force late type resolution */
|
/* force late type resolution */
|
||||||
template <typename X = devices::NETLIB_NAME(solver)>
|
template <typename X = devices::NETLIB_NAME(solver)>
|
||||||
@ -1586,21 +1599,21 @@ namespace netlist
|
|||||||
return static_cast<X *>(m_solver)->gmin();
|
return static_cast<X *>(m_solver)->gmin();
|
||||||
}
|
}
|
||||||
|
|
||||||
netlist_state_t &nlstate() NL_NOEXCEPT { return *m_state; }
|
netlist_state_t &nlstate() noexcept { return *m_state; }
|
||||||
const netlist_state_t &nlstate() const { return *m_state; }
|
const netlist_state_t &nlstate() const noexcept { return *m_state; }
|
||||||
|
|
||||||
log_type & log() { return m_state->log(); }
|
log_type & log() NL_NOEXCEPT { return m_state->log(); }
|
||||||
const log_type &log() const { return m_state->log(); }
|
const log_type &log() const NL_NOEXCEPT { return m_state->log(); }
|
||||||
|
|
||||||
void print_stats() const;
|
void print_stats() const NL_NOEXCEPT;
|
||||||
|
|
||||||
bool stats_enabled() const { return m_use_stats; }
|
bool stats_enabled() const noexcept { return m_use_stats; }
|
||||||
void enable_stats(bool val) { m_use_stats = val; }
|
void enable_stats(bool val) noexcept { m_use_stats = val; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
template <bool KEEP_STATS>
|
template <bool KEEP_STATS, typename MCT>
|
||||||
void process_queue_stats(netlist_time delta) NL_NOEXCEPT;
|
void process_queue_stats(netlist_time delta, MCT *mainclock) NL_NOEXCEPT;
|
||||||
|
|
||||||
plib::unique_ptr<netlist_state_t> m_state;
|
plib::unique_ptr<netlist_state_t> m_state;
|
||||||
devices::NETLIB_NAME(solver) * m_solver;
|
devices::NETLIB_NAME(solver) * m_solver;
|
||||||
@ -1615,8 +1628,8 @@ namespace netlist
|
|||||||
bool m_use_stats;
|
bool m_use_stats;
|
||||||
|
|
||||||
// performance
|
// performance
|
||||||
nperftime_t<true> m_stat_mainloop;
|
plib::pperftime_t<true> m_stat_mainloop;
|
||||||
nperfcount_t<true> m_perf_out_processed;
|
plib::pperfcount_t<true> m_perf_out_processed;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@ -1782,7 +1795,7 @@ namespace netlist
|
|||||||
if (m_next_scheduled_time > exec().time())
|
if (m_next_scheduled_time > exec().time())
|
||||||
{
|
{
|
||||||
m_in_queue = queue_status::QUEUED; /* pending */
|
m_in_queue = queue_status::QUEUED; /* pending */
|
||||||
exec().qpush({m_next_scheduled_time, this});
|
exec().qpush(detail::queue_t::entry_t(m_next_scheduled_time, this));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1904,6 +1917,106 @@ namespace netlist
|
|||||||
for (std::size_t i=0; i<N; i++)
|
for (std::size_t i=0; i<N; i++)
|
||||||
(*this)[i] = value;
|
(*this)[i] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Hot section
|
||||||
|
//
|
||||||
|
// Any changes below will impact performance.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template <bool KEEP_STATS, typename T>
|
||||||
|
inline void detail::net_t::process(const T mask, netlist_sig_t sig)
|
||||||
|
{
|
||||||
|
m_cur_Q = sig;
|
||||||
|
|
||||||
|
if (KEEP_STATS)
|
||||||
|
{
|
||||||
|
for (auto & p : m_list_active)
|
||||||
|
{
|
||||||
|
p.set_copied_input(sig);
|
||||||
|
auto *stats = p.device().m_stats.get();
|
||||||
|
stats->m_stat_call_count.inc();
|
||||||
|
if ((p.terminal_state() & mask))
|
||||||
|
{
|
||||||
|
auto g(stats->m_stat_total_time.guard());
|
||||||
|
p.m_delegate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (auto &p : m_list_active)
|
||||||
|
{
|
||||||
|
p.set_copied_input(sig);
|
||||||
|
if ((p.terminal_state() & mask))
|
||||||
|
p.m_delegate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool KEEP_STATS>
|
||||||
|
inline void detail::net_t::update_devs() NL_NOEXCEPT
|
||||||
|
{
|
||||||
|
nl_assert(this->isRailNet());
|
||||||
|
|
||||||
|
m_in_queue = queue_status::DELIVERED; /* mark as taken ... */
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool KEEP_STATS, typename MCT>
|
||||||
|
inline void netlist_t::process_queue_stats(const netlist_time delta, MCT *mainclock) NL_NOEXCEPT
|
||||||
|
{
|
||||||
|
netlist_time stop(m_time + delta);
|
||||||
|
|
||||||
|
qpush(detail::queue_t::entry_t(stop, nullptr));
|
||||||
|
|
||||||
|
if (m_mainclock == nullptr)
|
||||||
|
{
|
||||||
|
detail::queue_t::entry_t e(m_queue.pop());
|
||||||
|
m_time = e.m_exec_time;
|
||||||
|
while (e.m_object != nullptr)
|
||||||
|
{
|
||||||
|
e.m_object->template update_devs<KEEP_STATS>();
|
||||||
|
if (KEEP_STATS)
|
||||||
|
m_perf_out_processed.inc();
|
||||||
|
e = m_queue.pop();
|
||||||
|
m_time = e.m_exec_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logic_net_t &mc_net(mainclock->m_Q.net());
|
||||||
|
const netlist_time inc(mainclock->m_inc);
|
||||||
|
netlist_time mc_time(mc_net.next_scheduled_time());
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
while (m_queue.top().m_exec_time > mc_time)
|
||||||
|
{
|
||||||
|
m_time = mc_time;
|
||||||
|
mc_net.toggle_new_Q();
|
||||||
|
mc_net.update_devs<KEEP_STATS>();
|
||||||
|
mc_time += inc;
|
||||||
|
}
|
||||||
|
|
||||||
|
detail::queue_t::entry_t e(m_queue.pop());
|
||||||
|
m_time = e.m_exec_time;
|
||||||
|
if (e.m_object != nullptr)
|
||||||
|
{
|
||||||
|
e.m_object->template update_devs<KEEP_STATS>();
|
||||||
|
if (KEEP_STATS)
|
||||||
|
m_perf_out_processed.inc();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
} while (true); //while (e.m_object != nullptr);
|
||||||
|
mc_net.set_next_scheduled_time(mc_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace netlist
|
} // namespace netlist
|
||||||
|
|
||||||
namespace plib
|
namespace plib
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
#define PERRMSG(name, str) \
|
#define PERRMSG(name, str) \
|
||||||
struct name \
|
struct name \
|
||||||
{ \
|
{ \
|
||||||
operator pstring() const { return str; } \
|
operator pstring() const noexcept { return str; } \
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PERRMSGV(name, narg, str) \
|
#define PERRMSGV(name, narg, str) \
|
||||||
@ -23,7 +23,7 @@
|
|||||||
template<typename... Args> name(Args&&... args) \
|
template<typename... Args> name(Args&&... args) \
|
||||||
: m_m(plib::pfmt(str)(std::forward<Args>(args)...)) \
|
: m_m(plib::pfmt(str)(std::forward<Args>(args)...)) \
|
||||||
{ static_assert(narg == sizeof...(args), "Argument count mismatch"); } \
|
{ static_assert(narg == sizeof...(args), "Argument count mismatch"); } \
|
||||||
operator pstring() const { return m_m; } \
|
operator pstring() const noexcept { return m_m; } \
|
||||||
pstring m_m; \
|
pstring m_m; \
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,335 +0,0 @@
|
|||||||
// license:GPL-2.0+
|
|
||||||
// copyright-holders:Couriersud
|
|
||||||
/*
|
|
||||||
* nllists.h
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifndef NLLISTS_H_
|
|
||||||
#define NLLISTS_H_
|
|
||||||
|
|
||||||
#include "plib/pchrono.h"
|
|
||||||
#include "plib/plists.h"
|
|
||||||
#include "plib/ptypes.h"
|
|
||||||
#include "plib/parray.h"
|
|
||||||
|
|
||||||
#include "nl_config.h"
|
|
||||||
#include "nltypes.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <atomic>
|
|
||||||
#include <mutex>
|
|
||||||
#include <thread>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------
|
|
||||||
// timed queue
|
|
||||||
// ----------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
namespace netlist
|
|
||||||
{
|
|
||||||
//FIXME: move to an appropriate place
|
|
||||||
template<bool enabled_ = true>
|
|
||||||
class pspin_mutex
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
pspin_mutex() noexcept = default;
|
|
||||||
void lock() noexcept{ while (m_lock.test_and_set(std::memory_order_acquire)) { } }
|
|
||||||
void unlock() noexcept { m_lock.clear(std::memory_order_release); }
|
|
||||||
private:
|
|
||||||
PALIGNAS_CACHELINE()
|
|
||||||
std::atomic_flag m_lock = ATOMIC_FLAG_INIT;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
class pspin_mutex<false>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void lock() const noexcept { }
|
|
||||||
void unlock() const noexcept { }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Element, class Time>
|
|
||||||
struct pqentry_t final
|
|
||||||
{
|
|
||||||
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) { }
|
|
||||||
#if 0
|
|
||||||
~pqentry_t() = default;
|
|
||||||
constexpr pqentry_t(const pqentry_t &e) noexcept = default;
|
|
||||||
constexpr pqentry_t(pqentry_t &&e) noexcept = default;
|
|
||||||
pqentry_t& operator=(pqentry_t && other) noexcept = default;
|
|
||||||
pqentry_t& operator=(const pqentry_t &other) noexcept = default;
|
|
||||||
|
|
||||||
void swap(pqentry_t &other) noexcept
|
|
||||||
{
|
|
||||||
std::swap(m_exec_time, other.m_exec_time);
|
|
||||||
std::swap(m_object, other.m_object);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
inline bool operator ==(const pqentry_t &rhs) const noexcept
|
|
||||||
{
|
|
||||||
return m_object == rhs.m_object;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator ==(const Element &rhs) const noexcept
|
|
||||||
{
|
|
||||||
return m_object == rhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool operator <=(const pqentry_t &rhs) const noexcept
|
|
||||||
{
|
|
||||||
return (m_exec_time <= rhs.m_exec_time);
|
|
||||||
}
|
|
||||||
|
|
||||||
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); }
|
|
||||||
|
|
||||||
Time m_exec_time;
|
|
||||||
Element m_object;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Use TS = true for a threadsafe queue */
|
|
||||||
template <class T, bool TS>
|
|
||||||
class timed_queue_linear : plib::nocopyassignmove
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit timed_queue_linear(const std::size_t list_size)
|
|
||||||
: m_list(list_size)
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (; *i < e; --i)
|
|
||||||
{
|
|
||||||
*(i+1) = *(i);
|
|
||||||
if (KEEPSTAT)
|
|
||||||
m_prof_sortmove.inc();
|
|
||||||
}
|
|
||||||
*(i+1) = std::move(e);
|
|
||||||
++m_end;
|
|
||||||
if (KEEPSTAT)
|
|
||||||
m_prof_call.inc();
|
|
||||||
}
|
|
||||||
|
|
||||||
T pop() noexcept { return *(--m_end); }
|
|
||||||
const T &top() const noexcept { return *(m_end-1); }
|
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
// == operator ignores time!
|
|
||||||
if (*i == elem)
|
|
||||||
{
|
|
||||||
std::copy(i+1, m_end--, i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool KEEPSTAT, class R>
|
|
||||||
void retime(R && elem) noexcept
|
|
||||||
{
|
|
||||||
/* Lock */
|
|
||||||
lock_guard_type lck(m_lock);
|
|
||||||
if (KEEPSTAT)
|
|
||||||
m_prof_retime.inc();
|
|
||||||
|
|
||||||
for (R * i = m_end - 1; i > &m_list[0]; --i)
|
|
||||||
{
|
|
||||||
if (*i == elem) // partial equal!
|
|
||||||
{
|
|
||||||
*i = std::move(elem);
|
|
||||||
while (*(i-1) < *i)
|
|
||||||
{
|
|
||||||
std::swap(*(i-1), *i);
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
while (i < m_end && *i < *(i+1))
|
|
||||||
{
|
|
||||||
std::swap(*(i+1), *i);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear() noexcept
|
|
||||||
{
|
|
||||||
lock_guard_type lck(m_lock);
|
|
||||||
m_end = &m_list[0];
|
|
||||||
/* put an empty element with maximum time into the queue.
|
|
||||||
* the insert algo above will run into this element and doesn't
|
|
||||||
* need a comparison with queue start.
|
|
||||||
*/
|
|
||||||
m_list[0] = T::never();
|
|
||||||
m_end++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// save state support & mame disasm
|
|
||||||
|
|
||||||
const T *listptr() const noexcept { return &m_list[1]; }
|
|
||||||
std::size_t size() const noexcept { return static_cast<std::size_t>(m_end - &m_list[1]); }
|
|
||||||
const T & operator[](const std::size_t index) const noexcept { return m_list[ 1 + index]; }
|
|
||||||
private:
|
|
||||||
using mutex_type = pspin_mutex<TS>;
|
|
||||||
using lock_guard_type = std::lock_guard<mutex_type>;
|
|
||||||
|
|
||||||
mutex_type m_lock;
|
|
||||||
PALIGNAS_CACHELINE()
|
|
||||||
T * m_end;
|
|
||||||
plib::aligned_vector<T> m_list;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// profiling
|
|
||||||
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>
|
|
||||||
class timed_queue_heap : plib::nocopyassignmove
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
struct compare
|
|
||||||
{
|
|
||||||
constexpr bool operator()(const T &a, const T &b) const { return b <= a; }
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit timed_queue_heap(const std::size_t list_size)
|
|
||||||
: m_list(list_size)
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
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());
|
|
||||||
if (KEEPSTAT)
|
|
||||||
m_prof_call.inc();
|
|
||||||
}
|
|
||||||
|
|
||||||
T pop() noexcept
|
|
||||||
{
|
|
||||||
T ret(m_list[0]);
|
|
||||||
std::pop_heap(&m_list[0], m_end, compare());
|
|
||||||
m_end--;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
const T &top() const noexcept { return m_list[0]; }
|
|
||||||
|
|
||||||
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 (*i == elem)
|
|
||||||
{
|
|
||||||
m_end--;
|
|
||||||
for (;i < m_end; i++)
|
|
||||||
*i = std::move(*(i+1));
|
|
||||||
std::make_heap(&m_list[0], m_end, compare());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (*i == elem) // partial equal!
|
|
||||||
{
|
|
||||||
*i = elem;
|
|
||||||
std::make_heap(&m_list[0], m_end, compare());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
lock_guard_type lck(m_lock);
|
|
||||||
m_list.clear();
|
|
||||||
m_end = &m_list[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// save state support & mame disasm
|
|
||||||
|
|
||||||
constexpr const T *listptr() const { return &m_list[0]; }
|
|
||||||
constexpr std::size_t size() const noexcept { return m_list.size(); }
|
|
||||||
constexpr const T & operator[](const std::size_t index) const { return m_list[ 0 + index]; }
|
|
||||||
private:
|
|
||||||
using mutex_type = pspin_mutex<TS>;
|
|
||||||
using lock_guard_type = std::lock_guard<mutex_type>;
|
|
||||||
|
|
||||||
mutex_type m_lock;
|
|
||||||
std::vector<T> m_list;
|
|
||||||
T *m_end;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// profiling
|
|
||||||
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>
|
|
||||||
//using timed_queue = timed_queue_heap<T, TS>;
|
|
||||||
|
|
||||||
} // namespace netlist
|
|
||||||
|
|
||||||
#endif /* NLLISTS_H_ */
|
|
@ -68,17 +68,6 @@ namespace netlist
|
|||||||
|
|
||||||
using log_type = plib::plog_base<callbacks_t, NL_DEBUG>;
|
using log_type = plib::plog_base<callbacks_t, NL_DEBUG>;
|
||||||
|
|
||||||
|
|
||||||
//============================================================
|
|
||||||
// Performance tracking
|
|
||||||
//============================================================
|
|
||||||
|
|
||||||
template<bool enabled_>
|
|
||||||
using nperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, enabled_>;
|
|
||||||
|
|
||||||
template<bool enabled_>
|
|
||||||
using nperfcount_t = plib::chrono::counter<enabled_>;
|
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// Types needed by various includes
|
// Types needed by various includes
|
||||||
//============================================================
|
//============================================================
|
||||||
|
@ -34,8 +34,10 @@ namespace plib {
|
|||||||
{
|
{
|
||||||
//using arena_storage_type = P *;
|
//using arena_storage_type = P *;
|
||||||
using arena_storage_type = typename std::conditional<P::is_stateless, P, P *>::type;
|
using arena_storage_type = typename std::conditional<P::is_stateless, P, P *>::type;
|
||||||
|
|
||||||
template <typename X, typename Y = void>
|
template <typename X, typename Y = void>
|
||||||
typename std::enable_if<!X::is_stateless, X&>::type getref(X *x) { return *x;}
|
typename std::enable_if<!X::is_stateless, X&>::type getref(X *x) { return *x;}
|
||||||
|
|
||||||
template <typename X, typename Y = void *>
|
template <typename X, typename Y = void *>
|
||||||
typename std::enable_if<std::remove_pointer<X>::type::is_stateless, X&>::type
|
typename std::enable_if<std::remove_pointer<X>::type::is_stateless, X&>::type
|
||||||
getref(X &x, Y y = nullptr)
|
getref(X &x, Y y = nullptr)
|
||||||
@ -44,13 +46,18 @@ namespace plib {
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr arena_deleter(arena_storage_type a = arena_storage_type()) noexcept
|
constexpr arena_deleter(arena_storage_type a = arena_storage_type())
|
||||||
: m_a(a) { }
|
: m_a(a) { }
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
template<typename U, typename = typename
|
||||||
|
std::enable_if<std::is_convertible< U*, T*>::value>::type>
|
||||||
|
arena_deleter(const arena_deleter<P, U> &rhs) : m_a(rhs.m_a) { }
|
||||||
|
#else
|
||||||
template<typename PU, typename U, typename = typename
|
template<typename PU, typename U, typename = typename
|
||||||
std::enable_if<std::is_convertible< U*, T*>::value>::type>
|
std::enable_if<std::is_convertible< U*, T*>::value>::type>
|
||||||
arena_deleter(const arena_deleter<PU, U> &rhs) noexcept : m_a(rhs.m_a) { }
|
arena_deleter(const arena_deleter<PU, U> &rhs) : m_a(rhs.m_a) { }
|
||||||
|
#endif
|
||||||
void operator()(T *p) //const
|
void operator()(T *p) //const
|
||||||
{
|
{
|
||||||
/* call destructor */
|
/* call destructor */
|
||||||
@ -80,11 +87,11 @@ namespace plib {
|
|||||||
template <typename, typename>
|
template <typename, typename>
|
||||||
friend class owned_ptr;
|
friend class owned_ptr;
|
||||||
|
|
||||||
owned_ptr(pointer p, bool owned) noexcept
|
owned_ptr(pointer p, bool owned)
|
||||||
: m_ptr(p), m_deleter(), m_is_owned(owned)
|
: m_ptr(p), m_deleter(), m_is_owned(owned)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
owned_ptr(pointer p, bool owned, D deleter) noexcept
|
owned_ptr(pointer p, bool owned, D deleter)
|
||||||
: m_ptr(p), m_deleter(deleter), m_is_owned(owned)
|
: m_ptr(p), m_deleter(deleter), m_is_owned(owned)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@ -93,7 +100,7 @@ namespace plib {
|
|||||||
owned_ptr & operator =(owned_ptr &r) = delete;
|
owned_ptr & operator =(owned_ptr &r) = delete;
|
||||||
|
|
||||||
template<typename DC, typename DC_D>
|
template<typename DC, typename DC_D>
|
||||||
owned_ptr & operator =(owned_ptr<DC, DC_D> &&r)
|
owned_ptr & operator =(owned_ptr<DC, DC_D> &&r) noexcept
|
||||||
{
|
{
|
||||||
if (m_is_owned && (m_ptr != nullptr))
|
if (m_is_owned && (m_ptr != nullptr))
|
||||||
//delete m_ptr;
|
//delete m_ptr;
|
||||||
@ -122,7 +129,7 @@ namespace plib {
|
|||||||
m_deleter(m_ptr);
|
m_deleter(m_ptr);
|
||||||
m_is_owned = r.m_is_owned;
|
m_is_owned = r.m_is_owned;
|
||||||
m_ptr = r.m_ptr;
|
m_ptr = r.m_ptr;
|
||||||
m_deleter = std::move(r.m_deleter);
|
m_deleter = r.m_deleter;
|
||||||
r.m_is_owned = false;
|
r.m_is_owned = false;
|
||||||
r.m_ptr = nullptr;
|
r.m_ptr = nullptr;
|
||||||
return *this;
|
return *this;
|
||||||
@ -197,18 +204,12 @@ namespace plib {
|
|||||||
|
|
||||||
~arena_allocator() noexcept = default;
|
~arena_allocator() noexcept = default;
|
||||||
|
|
||||||
arena_allocator(const arena_allocator &rhs) noexcept = default;
|
|
||||||
arena_allocator& operator=(const arena_allocator&) noexcept = delete;
|
|
||||||
|
|
||||||
arena_allocator(arena_allocator&&) noexcept = default;
|
|
||||||
arena_allocator& operator=(arena_allocator&&) = delete;
|
|
||||||
|
|
||||||
arena_allocator(arena_type & a) noexcept : m_a(a)
|
arena_allocator(arena_type & a) noexcept : m_a(a)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class U>
|
template <class U>
|
||||||
arena_allocator(const arena_allocator<ARENA, U, ALIGN>& rhs) noexcept
|
arena_allocator(const arena_allocator<ARENA, U, ALIGN>& rhs)
|
||||||
: m_a(rhs.m_a)
|
: m_a(rhs.m_a)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -223,7 +224,7 @@ namespace plib {
|
|||||||
return reinterpret_cast<T *>(m_a.allocate(ALIGN, sizeof(T) * n));
|
return reinterpret_cast<T *>(m_a.allocate(ALIGN, sizeof(T) * n));
|
||||||
}
|
}
|
||||||
|
|
||||||
void deallocate(T* p, std::size_t n) noexcept
|
void deallocate(T* p, std::size_t n)
|
||||||
{
|
{
|
||||||
unused_var(n);
|
unused_var(n);
|
||||||
m_a.deallocate(p);
|
m_a.deallocate(p);
|
||||||
|
@ -32,6 +32,7 @@ namespace plib {
|
|||||||
struct sizeabs<FT, 0>
|
struct sizeabs<FT, 0>
|
||||||
{
|
{
|
||||||
static constexpr std::size_t ABS() { return 0; }
|
static constexpr std::size_t ABS() { return 0; }
|
||||||
|
//using container = typename std::vector<FT, arena_allocator<mempool, FT, 64>>;
|
||||||
using container = typename std::vector<FT, aligned_allocator<FT, PALIGN_VECTOROPT>>;
|
using container = typename std::vector<FT, aligned_allocator<FT, PALIGN_VECTOROPT>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -75,6 +76,15 @@ namespace plib {
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// osx clang doesn't like COPYASSIGNMOVE(parray, default)
|
||||||
|
// it will generate some weird error messages about move assignment
|
||||||
|
// constructor having a different noexcept status.
|
||||||
|
|
||||||
|
parray(const parray &rhs) : m_a(rhs.m_a), m_size(rhs.m_size) {}
|
||||||
|
parray(parray &&rhs) noexcept : m_a(std::move(rhs.m_a)), m_size(std::move(rhs.m_size)) {}
|
||||||
|
parray &operator=(const parray &rhs) { m_a = rhs.m_a; m_size = rhs.m_size; return *this; }
|
||||||
|
parray &operator=(parray &&rhs) noexcept { std::swap(m_a,rhs.m_a); std::swap(m_size, rhs.m_size); return *this; }
|
||||||
|
|
||||||
template <int X = SIZE >
|
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)
|
: m_size(size)
|
||||||
@ -125,6 +135,8 @@ namespace plib {
|
|||||||
(*this)[i] = parray<FT, SIZE2>(size2);
|
(*this)[i] = parray<FT, SIZE2>(size2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
COPYASSIGNMOVE(parray2D, default)
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace plib
|
} // namespace plib
|
||||||
|
@ -15,245 +15,253 @@
|
|||||||
//#include <cstdint>
|
//#include <cstdint>
|
||||||
|
|
||||||
namespace plib {
|
namespace plib {
|
||||||
namespace chrono {
|
namespace chrono {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct sys_ticks
|
struct sys_ticks
|
||||||
{
|
|
||||||
using type = typename T::rep;
|
|
||||||
static inline type start() { return T::now().time_since_epoch().count(); }
|
|
||||||
static inline type stop() { return T::now().time_since_epoch().count(); }
|
|
||||||
static inline constexpr type per_second() { return T::period::den / T::period::num; }
|
|
||||||
};
|
|
||||||
|
|
||||||
using hires_ticks = sys_ticks<std::chrono::high_resolution_clock>;
|
|
||||||
using steady_ticks = sys_ticks<std::chrono::steady_clock>;
|
|
||||||
using system_ticks = sys_ticks<std::chrono::system_clock>;
|
|
||||||
|
|
||||||
#if defined(__x86_64__) && !defined(_clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
|
|
||||||
|
|
||||||
template <typename T, typename R>
|
|
||||||
struct base_ticks
|
|
||||||
{
|
|
||||||
using ret_type = R;
|
|
||||||
static ret_type per_second()
|
|
||||||
{
|
{
|
||||||
static ret_type persec = 0;
|
using type = typename T::rep;
|
||||||
if (persec == 0)
|
static inline constexpr type start() noexcept { return T::now().time_since_epoch().count(); }
|
||||||
|
static inline constexpr type stop() noexcept { return T::now().time_since_epoch().count(); }
|
||||||
|
static inline constexpr type per_second() noexcept { return T::period::den / T::period::num; }
|
||||||
|
};
|
||||||
|
|
||||||
|
using hires_ticks = sys_ticks<std::chrono::high_resolution_clock>;
|
||||||
|
using steady_ticks = sys_ticks<std::chrono::steady_clock>;
|
||||||
|
using system_ticks = sys_ticks<std::chrono::system_clock>;
|
||||||
|
|
||||||
|
#if defined(__x86_64__) && !defined(_clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
|
||||||
|
|
||||||
|
template <typename T, typename R>
|
||||||
|
struct base_ticks
|
||||||
|
{
|
||||||
|
using ret_type = R;
|
||||||
|
static ret_type per_second()
|
||||||
{
|
{
|
||||||
ret_type x = 0;
|
static ret_type persec = 0;
|
||||||
system_ticks::type t = system_ticks::start();
|
if (persec == 0)
|
||||||
system_ticks::type e;
|
{
|
||||||
x = - T :: start();
|
ret_type x = 0;
|
||||||
do {
|
system_ticks::type t = system_ticks::start();
|
||||||
e = system_ticks::stop();
|
system_ticks::type e;
|
||||||
} while (e - t < system_ticks::per_second() / 100 );
|
x = - T :: start();
|
||||||
x += T :: stop();
|
do {
|
||||||
persec = (ret_type)(double)((double) x * (double) system_ticks::per_second() / double (e - t));
|
e = system_ticks::stop();
|
||||||
|
} while (e - t < system_ticks::per_second() / 100 );
|
||||||
|
x += T :: stop();
|
||||||
|
persec = (ret_type)(double)((double) x * (double) system_ticks::per_second() / double (e - t));
|
||||||
|
}
|
||||||
|
return persec;
|
||||||
}
|
}
|
||||||
return persec;
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#if PHAS_RDTSCP
|
#if PHAS_RDTSCP
|
||||||
struct fast_ticks : public base_ticks<fast_ticks, int64_t>
|
struct fast_ticks : public base_ticks<fast_ticks, int64_t>
|
||||||
{
|
|
||||||
typedef int64_t type;
|
|
||||||
static inline type start()
|
|
||||||
{
|
{
|
||||||
int64_t v;
|
typedef int64_t type;
|
||||||
__asm__ __volatile__ (
|
static inline type start() noexcept
|
||||||
"rdtscp;"
|
{
|
||||||
"shl $32, %%rdx;"
|
int64_t v;
|
||||||
"or %%rdx, %%rax;"
|
__asm__ __volatile__ (
|
||||||
: "=a"(v) /* outputs */
|
"rdtscp;"
|
||||||
: /* inputs */
|
"shl $32, %%rdx;"
|
||||||
: "%rcx", "%rdx" /* clobbers */
|
"or %%rdx, %%rax;"
|
||||||
);
|
: "=a"(v) /* outputs */
|
||||||
return v;
|
: /* inputs */
|
||||||
}
|
: "%rcx", "%rdx" /* clobbers */
|
||||||
static inline type stop()
|
);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
static inline type stop() noexcept
|
||||||
|
{
|
||||||
|
return start();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
struct fast_ticks : public base_ticks<fast_ticks, int64_t>
|
||||||
{
|
{
|
||||||
return start();
|
typedef int64_t type;
|
||||||
}
|
static inline type start() noexcept
|
||||||
};
|
{
|
||||||
|
int64_t v;
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
"rdtsc;"
|
||||||
|
"shl $32, %%rdx;"
|
||||||
|
"or %%rdx, %%rax;"
|
||||||
|
: "=a"(v) /* outputs */
|
||||||
|
: /* inputs */
|
||||||
|
: "%rdx" /* clobbers */
|
||||||
|
);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
static inline type stop() noexcept
|
||||||
|
{
|
||||||
|
return start();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#else
|
#endif
|
||||||
struct fast_ticks : public base_ticks<fast_ticks, int64_t>
|
|
||||||
{
|
|
||||||
typedef int64_t type;
|
/* Based on "How to Benchmark Code Execution Times on Intel?? IA-32 and IA-64
|
||||||
static inline type start()
|
* Instruction Set Architectures", Intel, 2010
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#if PUSE_ACCURATE_STATS && PHAS_RDTSCP
|
||||||
|
/*
|
||||||
|
* kills performance completely, but is accurate
|
||||||
|
* cpuid serializes, but clobbers ebx and ecx
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct exact_ticks : public base_ticks<exact_ticks, int64_t>
|
||||||
{
|
{
|
||||||
int64_t v;
|
typedef int64_t type;
|
||||||
__asm__ __volatile__ (
|
|
||||||
"rdtsc;"
|
static inline type start() noexcept
|
||||||
"shl $32, %%rdx;"
|
{
|
||||||
"or %%rdx, %%rax;"
|
int64_t v;
|
||||||
: "=a"(v) /* outputs */
|
__asm__ __volatile__ (
|
||||||
: /* inputs */
|
"cpuid;"
|
||||||
: "%rdx" /* clobbers */
|
//"xor %%eax, %%eax\n\t"
|
||||||
);
|
"rdtsc;"
|
||||||
return v;
|
"shl $32, %%rdx;"
|
||||||
}
|
"or %%rdx, %%rax;"
|
||||||
static inline type stop()
|
: "=a"(v) /* outputs */
|
||||||
|
: "a"(0x0) /* inputs */
|
||||||
|
: "%ebx", "%ecx", "%rdx" /* clobbers*/
|
||||||
|
);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
static inline type stop() noexcept
|
||||||
|
{
|
||||||
|
int64_t v;
|
||||||
|
__asm__ __volatile__ (
|
||||||
|
"rdtscp;"
|
||||||
|
"shl $32, %%rdx;"
|
||||||
|
"or %%rax, %%rdx;"
|
||||||
|
"mov %%rdx, %%r10;"
|
||||||
|
"xor %%eax, %%eax\n\t"
|
||||||
|
"cpuid;"
|
||||||
|
"mov %%r10, %%rax;"
|
||||||
|
: "=a" (v)
|
||||||
|
:
|
||||||
|
: "%ebx", "%ecx", "%rdx", "%r10"
|
||||||
|
);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
using exact_ticks = fast_ticks;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
using fast_ticks = hires_ticks;
|
||||||
|
using exact_ticks = fast_ticks;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template<bool enabled_>
|
||||||
|
struct counter
|
||||||
{
|
{
|
||||||
return start();
|
counter() : m_count(0) { }
|
||||||
}
|
using type = uint_least64_t;
|
||||||
};
|
type operator()() const noexcept { return m_count; }
|
||||||
|
void inc() noexcept { ++m_count; }
|
||||||
#endif
|
void reset() noexcept { m_count = 0; }
|
||||||
|
constexpr static bool enabled = enabled_;
|
||||||
|
|
||||||
/* Based on "How to Benchmark Code Execution Times on Intel?? IA-32 and IA-64
|
|
||||||
* Instruction Set Architectures", Intel, 2010
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#if PUSE_ACCURATE_STATS && PHAS_RDTSCP
|
|
||||||
/*
|
|
||||||
* kills performance completely, but is accurate
|
|
||||||
* cpuid serializes, but clobbers ebx and ecx
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
struct exact_ticks : public base_ticks<exact_ticks, int64_t>
|
|
||||||
{
|
|
||||||
typedef int64_t type;
|
|
||||||
|
|
||||||
static inline type start()
|
|
||||||
{
|
|
||||||
int64_t v;
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
"cpuid;"
|
|
||||||
//"xor %%eax, %%eax\n\t"
|
|
||||||
"rdtsc;"
|
|
||||||
"shl $32, %%rdx;"
|
|
||||||
"or %%rdx, %%rax;"
|
|
||||||
: "=a"(v) /* outputs */
|
|
||||||
: "a"(0x0) /* inputs */
|
|
||||||
: "%ebx", "%ecx", "%rdx" /* clobbers*/
|
|
||||||
);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
static inline type stop()
|
|
||||||
{
|
|
||||||
int64_t v;
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
"rdtscp;"
|
|
||||||
"shl $32, %%rdx;"
|
|
||||||
"or %%rax, %%rdx;"
|
|
||||||
"mov %%rdx, %%r10;"
|
|
||||||
"xor %%eax, %%eax\n\t"
|
|
||||||
"cpuid;"
|
|
||||||
"mov %%r10, %%rax;"
|
|
||||||
: "=a" (v)
|
|
||||||
:
|
|
||||||
: "%ebx", "%ecx", "%rdx", "%r10"
|
|
||||||
);
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
using exact_ticks = fast_ticks;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
using fast_ticks = hires_ticks;
|
|
||||||
using exact_ticks = fast_ticks;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
template<bool enabled_>
|
|
||||||
struct counter
|
|
||||||
{
|
|
||||||
counter() : m_count(0) { }
|
|
||||||
using type = uint_least64_t;
|
|
||||||
type operator()() const { return m_count; }
|
|
||||||
void inc() { ++m_count; }
|
|
||||||
void reset() { m_count = 0; }
|
|
||||||
constexpr static bool enabled = enabled_;
|
|
||||||
private:
|
|
||||||
type m_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct counter<false>
|
|
||||||
{
|
|
||||||
using type = uint_least64_t;
|
|
||||||
constexpr type operator()() const { return 0; }
|
|
||||||
void inc() const { }
|
|
||||||
void reset() const { }
|
|
||||||
constexpr static bool enabled = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template< typename T, bool enabled_ = true>
|
|
||||||
struct timer
|
|
||||||
{
|
|
||||||
using type = typename T::type;
|
|
||||||
using ctype = uint_least64_t;
|
|
||||||
constexpr static bool enabled = enabled_;
|
|
||||||
|
|
||||||
struct guard_t
|
|
||||||
{
|
|
||||||
guard_t() = delete;
|
|
||||||
guard_t(timer &m) noexcept : m_m(m) { m_m.m_time -= T::start(); }
|
|
||||||
~guard_t() { m_m.m_time += T::stop(); ++m_m.m_count; }
|
|
||||||
|
|
||||||
COPYASSIGNMOVE(guard_t, default)
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
timer &m_m;
|
type m_count;
|
||||||
};
|
};
|
||||||
|
|
||||||
friend struct guard_t;
|
template<>
|
||||||
|
struct counter<false>
|
||||||
timer() : m_time(0), m_count(0) { }
|
|
||||||
|
|
||||||
type operator()() const { return m_time; }
|
|
||||||
|
|
||||||
void reset() { m_time = 0; m_count = 0; }
|
|
||||||
type average() const { return (m_count == 0) ? 0 : m_time / m_count; }
|
|
||||||
type total() const { return m_time; }
|
|
||||||
ctype count() const { return m_count; }
|
|
||||||
|
|
||||||
double as_seconds() const { return static_cast<double>(total())
|
|
||||||
/ static_cast<double>(T::per_second()); }
|
|
||||||
|
|
||||||
guard_t guard() { return guard_t(*this); }
|
|
||||||
private:
|
|
||||||
type m_time;
|
|
||||||
ctype m_count;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct timer<T, false>
|
|
||||||
{
|
|
||||||
using type = typename T::type;
|
|
||||||
using ctype = uint_least64_t;
|
|
||||||
|
|
||||||
struct guard_t
|
|
||||||
{
|
{
|
||||||
guard_t() = default;
|
using type = uint_least64_t;
|
||||||
COPYASSIGNMOVE(guard_t, default)
|
constexpr type operator()() const { return 0; }
|
||||||
/* using default constructor will trigger warning on
|
void inc() const { }
|
||||||
* unused local variable.
|
void reset() const { }
|
||||||
*/
|
constexpr static bool enabled = false;
|
||||||
// NOLINTNEXTLINE(modernize-use-equals-default)
|
|
||||||
~guard_t() { }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr type operator()() const { return 0; }
|
|
||||||
void reset() const { }
|
|
||||||
constexpr type average() const { return 0; }
|
|
||||||
constexpr type total() const { return 0; }
|
|
||||||
constexpr ctype count() const { return 0; }
|
|
||||||
constexpr double as_seconds() const { return 0.0; }
|
|
||||||
constexpr static bool enabled = false;
|
|
||||||
guard_t guard() { return guard_t(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
template< typename T, bool enabled_ = true>
|
||||||
|
struct timer
|
||||||
|
{
|
||||||
|
using type = typename T::type;
|
||||||
|
using ctype = uint_least64_t;
|
||||||
|
constexpr static bool enabled = enabled_;
|
||||||
|
|
||||||
|
struct guard_t
|
||||||
|
{
|
||||||
|
guard_t() = delete;
|
||||||
|
guard_t(timer &m) noexcept : m_m(m) { m_m.m_time -= T::start(); }
|
||||||
|
~guard_t() { m_m.m_time += T::stop(); ++m_m.m_count; }
|
||||||
|
|
||||||
|
COPYASSIGNMOVE(guard_t, default)
|
||||||
|
|
||||||
|
private:
|
||||||
|
timer &m_m;
|
||||||
|
};
|
||||||
|
|
||||||
|
friend struct guard_t;
|
||||||
|
|
||||||
|
timer() : m_time(0), m_count(0) { }
|
||||||
|
|
||||||
|
type operator()() const { return m_time; }
|
||||||
|
|
||||||
|
void reset() { m_time = 0; m_count = 0; }
|
||||||
|
type average() const { return (m_count == 0) ? 0 : m_time / m_count; }
|
||||||
|
type total() const { return m_time; }
|
||||||
|
ctype count() const { return m_count; }
|
||||||
|
|
||||||
|
double as_seconds() const { return static_cast<double>(total())
|
||||||
|
/ static_cast<double>(T::per_second()); }
|
||||||
|
|
||||||
|
guard_t guard() { return guard_t(*this); }
|
||||||
|
private:
|
||||||
|
type m_time;
|
||||||
|
ctype m_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct timer<T, false>
|
||||||
|
{
|
||||||
|
using type = typename T::type;
|
||||||
|
using ctype = uint_least64_t;
|
||||||
|
|
||||||
|
struct guard_t
|
||||||
|
{
|
||||||
|
guard_t() = default;
|
||||||
|
COPYASSIGNMOVE(guard_t, default)
|
||||||
|
/* using default constructor will trigger warning on
|
||||||
|
* unused local variable.
|
||||||
|
*/
|
||||||
|
// NOLINTNEXTLINE(modernize-use-equals-default)
|
||||||
|
~guard_t() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr type operator()() const { return 0; }
|
||||||
|
void reset() const { }
|
||||||
|
constexpr type average() const { return 0; }
|
||||||
|
constexpr type total() const { return 0; }
|
||||||
|
constexpr ctype count() const { return 0; }
|
||||||
|
constexpr double as_seconds() const { return 0.0; }
|
||||||
|
constexpr static bool enabled = false;
|
||||||
|
guard_t guard() { return guard_t(); }
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace chrono
|
} // namespace chrono
|
||||||
|
//============================================================
|
||||||
|
// Performance tracking
|
||||||
|
//============================================================
|
||||||
|
|
||||||
|
template<bool enabled_>
|
||||||
|
using pperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, enabled_>;
|
||||||
|
|
||||||
|
template<bool enabled_>
|
||||||
|
using pperfcount_t = plib::chrono::counter<enabled_>;
|
||||||
} // namespace plib
|
} // namespace plib
|
||||||
|
|
||||||
#endif /* PCHRONO_H_ */
|
#endif /* PCHRONO_H_ */
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// license:GPL-2.0+
|
// license:GPL-2.0+
|
||||||
// copyright-holders:Couriersud
|
// copyright-holders:Couriersud
|
||||||
/*
|
/*
|
||||||
* nl_string.c
|
* pfm_log.cpp
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -10,283 +10,506 @@
|
|||||||
#ifndef PLISTS_H_
|
#ifndef PLISTS_H_
|
||||||
#define PLISTS_H_
|
#define PLISTS_H_
|
||||||
|
|
||||||
|
#include "palloc.h"
|
||||||
|
#include "pchrono.h"
|
||||||
#include "pstring.h"
|
#include "pstring.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <atomic>
|
||||||
|
#include <mutex>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace plib {
|
namespace plib {
|
||||||
/* ----------------------------------------------------------------------------------------
|
|
||||||
* uninitialised_array_t:
|
|
||||||
* fixed size array allowing to override constructor and initialize
|
|
||||||
* members by placement new.
|
|
||||||
*
|
|
||||||
* Use with care. This template is provided to improve locality of storage
|
|
||||||
* in high frequency applications. It should not be used for anything else.
|
|
||||||
* ---------------------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
template <class C, std::size_t N>
|
/**! fixed size array allowing to override constructor and initialize members by placement new.
|
||||||
class uninitialised_array_t
|
*
|
||||||
{
|
* Use with care. This template is provided to improve locality of storage
|
||||||
public:
|
* in high frequency applications. It should not be used for anything else.
|
||||||
|
*
|
||||||
using iterator = C *;
|
*/
|
||||||
using const_iterator = const C *;
|
template <class C, std::size_t N>
|
||||||
|
class uninitialised_array_t
|
||||||
//uninitialised_array_t() noexcept = default;
|
|
||||||
uninitialised_array_t() noexcept
|
|
||||||
: m_initialized(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
COPYASSIGNMOVE(uninitialised_array_t, delete)
|
|
||||||
~uninitialised_array_t() noexcept
|
|
||||||
{
|
|
||||||
if (m_initialized>=N)
|
|
||||||
for (std::size_t i=0; i<N; i++)
|
|
||||||
(*this)[i].~C();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const { return N; }
|
|
||||||
|
|
||||||
C& operator[](const std::size_t &index) noexcept
|
|
||||||
{
|
|
||||||
return *reinterpret_cast<C *>(&m_buf[index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const C& operator[](const std::size_t &index) const noexcept
|
|
||||||
{
|
|
||||||
return *reinterpret_cast<const C *>(&m_buf[index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
void emplace(const std::size_t index, Args&&... args)
|
|
||||||
{
|
|
||||||
m_initialized++;
|
|
||||||
// allocate on buffer
|
|
||||||
new (&m_buf[index]) C(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
iterator begin() const noexcept { return reinterpret_cast<iterator>(&m_buf[0]); }
|
|
||||||
iterator end() const noexcept { return reinterpret_cast<iterator>(&m_buf[N]); }
|
|
||||||
|
|
||||||
iterator begin() noexcept { return reinterpret_cast<iterator>(&m_buf[0]); }
|
|
||||||
iterator end() noexcept { return reinterpret_cast<iterator>(&m_buf[N]); }
|
|
||||||
|
|
||||||
const_iterator cbegin() const noexcept { return reinterpret_cast<const_iterator>(&m_buf[0]); }
|
|
||||||
const_iterator cend() const noexcept { return reinterpret_cast<const_iterator>(&m_buf[N]); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
/* ensure proper alignment */
|
|
||||||
PALIGNAS_VECTOROPT()
|
|
||||||
std::array<typename std::aligned_storage<sizeof(C), alignof(C)>::type, N> m_buf;
|
|
||||||
unsigned m_initialized;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------------------
|
|
||||||
// plinkedlist_t: a simple linked list
|
|
||||||
// the list allows insertions / deletions if used properly
|
|
||||||
// ----------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
template <class LC>
|
|
||||||
class linkedlist_t
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
struct element_t
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
friend class linkedlist_t<LC>;
|
using iterator = C *;
|
||||||
|
using const_iterator = const C *;
|
||||||
|
|
||||||
constexpr element_t() : m_next(nullptr) {}
|
//uninitialised_array_t() noexcept = default;
|
||||||
constexpr element_t(const element_t &rhs) = delete;
|
uninitialised_array_t() noexcept
|
||||||
constexpr element_t(element_t &&rhs) = delete;
|
: m_initialized(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
constexpr LC *next() const noexcept { return m_next; }
|
COPYASSIGNMOVE(uninitialised_array_t, delete)
|
||||||
|
~uninitialised_array_t() noexcept
|
||||||
|
{
|
||||||
|
if (m_initialized>=N)
|
||||||
|
for (std::size_t i=0; i<N; i++)
|
||||||
|
(*this)[i].~C();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const { return N; }
|
||||||
|
|
||||||
|
C& operator[](const std::size_t &index) noexcept
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<C *>(&m_buf[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const C& operator[](const std::size_t &index) const noexcept
|
||||||
|
{
|
||||||
|
return *reinterpret_cast<const C *>(&m_buf[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void emplace(const std::size_t index, Args&&... args)
|
||||||
|
{
|
||||||
|
m_initialized++;
|
||||||
|
// allocate on buffer
|
||||||
|
new (&m_buf[index]) C(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator begin() const noexcept { return reinterpret_cast<iterator>(&m_buf[0]); }
|
||||||
|
iterator end() const noexcept { return reinterpret_cast<iterator>(&m_buf[N]); }
|
||||||
|
|
||||||
|
iterator begin() noexcept { return reinterpret_cast<iterator>(&m_buf[0]); }
|
||||||
|
iterator end() noexcept { return reinterpret_cast<iterator>(&m_buf[N]); }
|
||||||
|
|
||||||
|
const_iterator cbegin() const noexcept { return reinterpret_cast<const_iterator>(&m_buf[0]); }
|
||||||
|
const_iterator cend() const noexcept { return reinterpret_cast<const_iterator>(&m_buf[N]); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~element_t() = default;
|
|
||||||
private:
|
private:
|
||||||
LC * m_next;
|
|
||||||
|
/* ensure proper alignment */
|
||||||
|
PALIGNAS_VECTOROPT()
|
||||||
|
std::array<typename std::aligned_storage<sizeof(C), alignof(C)>::type, N> m_buf;
|
||||||
|
unsigned m_initialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iter_t final : public std::iterator<std::forward_iterator_tag, LC>
|
/**! a simple linked list.
|
||||||
{
|
*
|
||||||
private:
|
* the list allows insertions deletions whilst being processed.
|
||||||
LC* p;
|
*/
|
||||||
public:
|
template <class LC>
|
||||||
explicit constexpr iter_t(LC* x) noexcept : p(x) { }
|
class linkedlist_t
|
||||||
explicit constexpr iter_t(const iter_t &rhs) noexcept : p(rhs.p) { }
|
|
||||||
iter_t(iter_t &&rhs) noexcept { std::swap(*this, rhs); }
|
|
||||||
iter_t& operator=(const iter_t &rhs) { iter_t t(rhs); std::swap(*this, t); return *this; }
|
|
||||||
iter_t& operator=(iter_t &&rhs) { std::swap(*this, rhs); return *this; }
|
|
||||||
iter_t& operator++() noexcept {p = p->next();return *this;}
|
|
||||||
iter_t operator++(int) noexcept {iter_t tmp(*this); operator++(); return tmp;}
|
|
||||||
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*() const noexcept {return *p;}
|
|
||||||
constexpr LC* operator->() const noexcept {return p;}
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr linkedlist_t() : m_head(nullptr) {}
|
|
||||||
|
|
||||||
constexpr iter_t begin() const noexcept { return iter_t(m_head); }
|
|
||||||
constexpr iter_t end() const noexcept { return iter_t(nullptr); }
|
|
||||||
|
|
||||||
void push_front(LC *elem) noexcept
|
|
||||||
{
|
|
||||||
elem->m_next = m_head;
|
|
||||||
m_head = elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
void push_back(LC *elem) noexcept
|
|
||||||
{
|
|
||||||
LC **p = &m_head;
|
|
||||||
while (*p != nullptr)
|
|
||||||
{
|
|
||||||
p = &((*p)->m_next);
|
|
||||||
}
|
|
||||||
*p = elem;
|
|
||||||
elem->m_next = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove(const LC *elem) noexcept
|
|
||||||
{
|
|
||||||
auto p = &m_head;
|
|
||||||
while(*p != elem)
|
|
||||||
{
|
|
||||||
//nl_assert(*p != nullptr);
|
|
||||||
p = &((*p)->m_next);
|
|
||||||
}
|
|
||||||
(*p) = elem->m_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
LC *front() const noexcept { return m_head; }
|
|
||||||
void clear() noexcept { m_head = nullptr; }
|
|
||||||
constexpr bool empty() const noexcept { return (m_head == nullptr); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
LC *m_head;
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
template <class LC>
|
|
||||||
class linkedlist_t
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
struct element_t
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
friend class linkedlist_t<LC>;
|
struct element_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
friend class linkedlist_t<LC>;
|
||||||
|
|
||||||
constexpr element_t() : m_next(nullptr), m_prev(nullptr) {}
|
constexpr element_t() : m_next(nullptr), m_prev(nullptr) {}
|
||||||
~element_t() noexcept = default;
|
~element_t() noexcept = default;
|
||||||
|
|
||||||
COPYASSIGNMOVE(element_t, delete)
|
COPYASSIGNMOVE(element_t, delete)
|
||||||
|
|
||||||
|
constexpr LC *next() const noexcept { return m_next; }
|
||||||
|
constexpr LC *prev() const noexcept { return m_prev; }
|
||||||
|
private:
|
||||||
|
LC * m_next;
|
||||||
|
LC * m_prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct iter_t final : public std::iterator<std::forward_iterator_tag, LC>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
LC* p;
|
||||||
|
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 { if (this != &rhs) p = rhs.p; return *this; }
|
||||||
|
iter_t& operator=(iter_t &&rhs) noexcept { std::swap(*this, rhs); return *this; }
|
||||||
|
~iter_t() = default;
|
||||||
|
|
||||||
|
iter_t& operator++() noexcept { p = p->next();return *this; }
|
||||||
|
// NOLINTNEXTLINE(cert-dcl21-cpp)
|
||||||
|
iter_t operator++(int) & noexcept { const iter_t tmp(*this); operator++(); return tmp; }
|
||||||
|
|
||||||
|
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; }
|
||||||
|
C14CONSTEXPR LC& operator*() noexcept { return *p; }
|
||||||
|
C14CONSTEXPR LC* operator->() noexcept { return p; }
|
||||||
|
|
||||||
|
C14CONSTEXPR LC& operator*() const noexcept { return *p; }
|
||||||
|
C14CONSTEXPR LC* operator->() const noexcept { return p; }
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr linkedlist_t() : m_head(nullptr) {}
|
||||||
|
|
||||||
|
constexpr iter_t begin() const noexcept { return iter_t(m_head); }
|
||||||
|
constexpr iter_t end() const noexcept { return iter_t(nullptr); }
|
||||||
|
|
||||||
|
void push_front(LC *elem) noexcept
|
||||||
|
{
|
||||||
|
elem->m_next = m_head;
|
||||||
|
elem->m_prev = nullptr;
|
||||||
|
if (m_head)
|
||||||
|
m_head->m_prev = elem;
|
||||||
|
m_head = elem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(LC *elem) noexcept
|
||||||
|
{
|
||||||
|
LC ** p(&m_head);
|
||||||
|
LC * prev(nullptr);
|
||||||
|
while (*p != nullptr)
|
||||||
|
{
|
||||||
|
prev = *p;
|
||||||
|
p = &((*p)->m_next);
|
||||||
|
}
|
||||||
|
*p = elem;
|
||||||
|
elem->m_prev = prev;
|
||||||
|
elem->m_next = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(const LC *elem) noexcept
|
||||||
|
{
|
||||||
|
if (elem->m_prev)
|
||||||
|
elem->m_prev->m_next = elem->m_next;
|
||||||
|
else
|
||||||
|
m_head = elem->m_next;
|
||||||
|
if (elem->m_next)
|
||||||
|
elem->m_next->m_prev = elem->m_prev;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* update tail */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LC *front() const noexcept { return m_head; }
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr LC *next() const noexcept { return m_next; }
|
|
||||||
constexpr LC *prev() const noexcept { return m_prev; }
|
|
||||||
private:
|
private:
|
||||||
LC * m_next;
|
LC *m_head;
|
||||||
LC * m_prev;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iter_t final : public std::iterator<std::forward_iterator_tag, LC>
|
// ----------------------------------------------------------------------------------------
|
||||||
|
// FIXME: Move elsewhere
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<bool enabled_ = true>
|
||||||
|
class pspin_mutex
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
LC* p;
|
|
||||||
public:
|
public:
|
||||||
explicit constexpr iter_t(LC* x) noexcept : p(x) { }
|
pspin_mutex() noexcept = default;
|
||||||
constexpr iter_t(iter_t &rhs) noexcept : p(rhs.p) { }
|
void lock() noexcept{ while (m_lock.test_and_set(std::memory_order_acquire)) { } }
|
||||||
iter_t(iter_t &&rhs) noexcept { std::swap(*this, rhs); }
|
void unlock() noexcept { m_lock.clear(std::memory_order_release); }
|
||||||
iter_t& operator=(const iter_t &rhs) noexcept { p = rhs.p; return *this; }
|
private:
|
||||||
iter_t& operator=(iter_t &&rhs) noexcept { std::swap(*this, rhs); return *this; }
|
PALIGNAS_CACHELINE()
|
||||||
iter_t& operator++() noexcept {p = p->next();return *this;}
|
std::atomic_flag m_lock = ATOMIC_FLAG_INIT;
|
||||||
// NOLINTNEXTLINE(cert-dcl21-cpp)
|
|
||||||
iter_t operator++(int) & noexcept {const iter_t tmp(*this); operator++(); return tmp;}
|
|
||||||
|
|
||||||
~iter_t() = default;
|
|
||||||
|
|
||||||
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*() const noexcept {return *p;}
|
|
||||||
constexpr LC* operator->() const noexcept {return p;}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr linkedlist_t() : m_head(nullptr) {}
|
template<>
|
||||||
|
class pspin_mutex<false>
|
||||||
constexpr iter_t begin() const noexcept { return iter_t(m_head); }
|
|
||||||
constexpr iter_t end() const noexcept { return iter_t(nullptr); }
|
|
||||||
|
|
||||||
void push_front(LC *elem) noexcept
|
|
||||||
{
|
{
|
||||||
if (m_head)
|
public:
|
||||||
m_head->m_prev = elem;
|
void lock() const noexcept { }
|
||||||
elem->m_next = m_head;
|
void unlock() const noexcept { }
|
||||||
elem->m_prev = nullptr;
|
};
|
||||||
m_head = elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
void push_back(LC *elem) noexcept
|
// ----------------------------------------------------------------------------------------
|
||||||
|
// timed queue
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template <class Element, class Time>
|
||||||
|
struct pqentry_t final
|
||||||
{
|
{
|
||||||
LC ** p(&m_head);
|
constexpr pqentry_t() noexcept : m_exec_time(), m_object(nullptr) { }
|
||||||
LC * prev(nullptr);
|
constexpr pqentry_t(const Time t, const Element o) noexcept : m_exec_time(t), m_object(o) { }
|
||||||
while (*p != nullptr)
|
#if 0
|
||||||
|
~pqentry_t() = default;
|
||||||
|
constexpr pqentry_t(const pqentry_t &e) noexcept = default;
|
||||||
|
constexpr pqentry_t(pqentry_t &&e) noexcept = default;
|
||||||
|
pqentry_t& operator=(pqentry_t && other) noexcept = default;
|
||||||
|
pqentry_t& operator=(const pqentry_t &other) noexcept = default;
|
||||||
|
|
||||||
|
void swap(pqentry_t &other) noexcept
|
||||||
{
|
{
|
||||||
prev = *p;
|
std::swap(m_exec_time, other.m_exec_time);
|
||||||
p = &((*p)->m_next);
|
std::swap(m_object, other.m_object);
|
||||||
}
|
}
|
||||||
*p = elem;
|
|
||||||
elem->m_prev = prev;
|
|
||||||
elem->m_next = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void remove(const LC *elem) noexcept
|
|
||||||
{
|
|
||||||
if (elem->m_prev)
|
|
||||||
elem->m_prev->m_next = elem->m_next;
|
|
||||||
else
|
|
||||||
m_head = elem->m_next;
|
|
||||||
if (elem->m_next)
|
|
||||||
elem->m_next->m_prev = elem->m_prev;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* update tail */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LC *front() const noexcept { return m_head; }
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
#endif
|
#endif
|
||||||
|
inline bool operator ==(const pqentry_t &rhs) const noexcept
|
||||||
|
{
|
||||||
|
return m_object == rhs.m_object;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator ==(const Element &rhs) const noexcept
|
||||||
|
{
|
||||||
|
return m_object == rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator <=(const pqentry_t &rhs) const noexcept
|
||||||
|
{
|
||||||
|
return (m_exec_time <= rhs.m_exec_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
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); }
|
||||||
|
|
||||||
|
Time m_exec_time;
|
||||||
|
Element m_object;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Use TS = true for a threadsafe queue */
|
||||||
|
template <class T, bool TS>
|
||||||
|
class timed_queue_linear : nocopyassignmove
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit timed_queue_linear(const std::size_t list_size)
|
||||||
|
: m_list(list_size)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
/* Lock */
|
||||||
|
lock_guard_type lck(m_lock);
|
||||||
|
T * i(m_end-1);
|
||||||
|
for (; *i < e; --i)
|
||||||
|
{
|
||||||
|
*(i+1) = *(i);
|
||||||
|
if (KEEPSTAT)
|
||||||
|
m_prof_sortmove.inc();
|
||||||
|
}
|
||||||
|
*(i+1) = std::move(e);
|
||||||
|
++m_end;
|
||||||
|
#else
|
||||||
|
/* Lock */
|
||||||
|
lock_guard_type lck(m_lock);
|
||||||
|
T * i(m_end++);
|
||||||
|
*i = std::move(e);
|
||||||
|
for (; *(i-1) < *i; --i)
|
||||||
|
{
|
||||||
|
std::swap(*(i-1), *(i));
|
||||||
|
if (KEEPSTAT)
|
||||||
|
m_prof_sortmove.inc();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (KEEPSTAT)
|
||||||
|
m_prof_call.inc();
|
||||||
|
}
|
||||||
|
|
||||||
|
T pop() noexcept { return *(--m_end); }
|
||||||
|
const T &top() const noexcept { return *(m_end-1); }
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// == operator ignores time!
|
||||||
|
if (*i == elem)
|
||||||
|
{
|
||||||
|
std::copy(i+1, m_end--, i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool KEEPSTAT, class R>
|
||||||
|
void retime(R && elem) noexcept
|
||||||
|
{
|
||||||
|
/* Lock */
|
||||||
|
lock_guard_type lck(m_lock);
|
||||||
|
if (KEEPSTAT)
|
||||||
|
m_prof_retime.inc();
|
||||||
|
|
||||||
|
for (R * i = m_end - 1; i > &m_list[0]; --i)
|
||||||
|
{
|
||||||
|
if (*i == elem) // partial equal!
|
||||||
|
{
|
||||||
|
*i = std::forward<R>(elem);
|
||||||
|
while (*(i-1) < *i)
|
||||||
|
{
|
||||||
|
std::swap(*(i-1), *i);
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
while (i < m_end && *i < *(i+1))
|
||||||
|
{
|
||||||
|
std::swap(*(i+1), *i);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() noexcept
|
||||||
|
{
|
||||||
|
lock_guard_type lck(m_lock);
|
||||||
|
m_end = &m_list[0];
|
||||||
|
/* put an empty element with maximum time into the queue.
|
||||||
|
* the insert algo above will run into this element and doesn't
|
||||||
|
* need a comparison with queue start.
|
||||||
|
*/
|
||||||
|
m_list[0] = T::never();
|
||||||
|
m_end++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save state support & mame disasm
|
||||||
|
|
||||||
|
const T *listptr() const noexcept { return &m_list[1]; }
|
||||||
|
std::size_t size() const noexcept { return static_cast<std::size_t>(m_end - &m_list[1]); }
|
||||||
|
const T & operator[](const std::size_t index) const noexcept { return m_list[ 1 + index]; }
|
||||||
|
private:
|
||||||
|
using mutex_type = pspin_mutex<TS>;
|
||||||
|
using lock_guard_type = std::lock_guard<mutex_type>;
|
||||||
|
|
||||||
|
mutex_type m_lock;
|
||||||
|
PALIGNAS_CACHELINE()
|
||||||
|
T * m_end;
|
||||||
|
aligned_vector<T> m_list;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// profiling
|
||||||
|
pperfcount_t<true> m_prof_sortmove;
|
||||||
|
pperfcount_t<true> m_prof_call;
|
||||||
|
pperfcount_t<true> m_prof_remove;
|
||||||
|
pperfcount_t<true> m_prof_retime;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, bool TS>
|
||||||
|
class timed_queue_heap : nocopyassignmove
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
struct compare
|
||||||
|
{
|
||||||
|
constexpr bool operator()(const T &a, const T &b) const { return b <= a; }
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit timed_queue_heap(const std::size_t list_size)
|
||||||
|
: m_list(list_size)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
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());
|
||||||
|
if (KEEPSTAT)
|
||||||
|
m_prof_call.inc();
|
||||||
|
}
|
||||||
|
|
||||||
|
T pop() noexcept
|
||||||
|
{
|
||||||
|
T ret(m_list[0]);
|
||||||
|
std::pop_heap(&m_list[0], m_end, compare());
|
||||||
|
m_end--;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T &top() const noexcept { return m_list[0]; }
|
||||||
|
|
||||||
|
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 (*i == elem)
|
||||||
|
{
|
||||||
|
m_end--;
|
||||||
|
for (;i < m_end; i++)
|
||||||
|
*i = std::move(*(i+1));
|
||||||
|
std::make_heap(&m_list[0], m_end, compare());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (*i == elem) // partial equal!
|
||||||
|
{
|
||||||
|
*i = elem;
|
||||||
|
std::make_heap(&m_list[0], m_end, compare());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
lock_guard_type lck(m_lock);
|
||||||
|
m_list.clear();
|
||||||
|
m_end = &m_list[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
// save state support & mame disasm
|
||||||
|
|
||||||
|
constexpr const T *listptr() const { return &m_list[0]; }
|
||||||
|
constexpr std::size_t size() const noexcept { return m_list.size(); }
|
||||||
|
constexpr const T & operator[](const std::size_t index) const { return m_list[ 0 + index]; }
|
||||||
|
private:
|
||||||
|
using mutex_type = pspin_mutex<TS>;
|
||||||
|
using lock_guard_type = std::lock_guard<mutex_type>;
|
||||||
|
|
||||||
|
mutex_type m_lock;
|
||||||
|
std::vector<T> m_list;
|
||||||
|
T *m_end;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// profiling
|
||||||
|
pperfcount_t<true> m_prof_sortmove;
|
||||||
|
pperfcount_t<true> m_prof_call;
|
||||||
|
pperfcount_t<true> m_prof_remove;
|
||||||
|
pperfcount_t<true> m_prof_retime;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace plib
|
} // namespace plib
|
||||||
|
|
||||||
#endif /* PLISTS_H_ */
|
#endif /* PLISTS_H_ */
|
||||||
|
@ -123,6 +123,12 @@ namespace plib {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline mempool &instance()
|
||||||
|
{
|
||||||
|
static mempool s_mempool;
|
||||||
|
return s_mempool;
|
||||||
|
}
|
||||||
|
|
||||||
void *allocate(size_t align, size_t size)
|
void *allocate(size_t align, size_t size)
|
||||||
{
|
{
|
||||||
block *b = nullptr;
|
block *b = nullptr;
|
||||||
@ -220,6 +226,8 @@ namespace plib {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator ==(const mempool &rhs) { return this == &rhs; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace plib
|
} // namespace plib
|
||||||
|
@ -261,8 +261,8 @@ ptokenizer::token_t ptokenizer::get_token_internal()
|
|||||||
|
|
||||||
ppreprocessor::ppreprocessor(defines_map_type *defines)
|
ppreprocessor::ppreprocessor(defines_map_type *defines)
|
||||||
: std::istream(new readbuffer(this))
|
: std::istream(new readbuffer(this))
|
||||||
, m_ifflag(0)
|
, m_if_flag(0)
|
||||||
, m_level(0)
|
, m_if_level(0)
|
||||||
, m_lineno(0)
|
, m_lineno(0)
|
||||||
, m_pos(0)
|
, m_pos(0)
|
||||||
, m_state(PROCESS)
|
, m_state(PROCESS)
|
||||||
@ -473,34 +473,34 @@ pstring ppreprocessor::process_line(pstring line)
|
|||||||
std::vector<pstring> lti(psplit(lt, " ", true));
|
std::vector<pstring> lti(psplit(lt, " ", true));
|
||||||
if (lti[0] == "#if")
|
if (lti[0] == "#if")
|
||||||
{
|
{
|
||||||
m_level++;
|
m_if_level++;
|
||||||
std::size_t start = 0;
|
std::size_t start = 0;
|
||||||
lt = replace_macros(lt);
|
lt = replace_macros(lt);
|
||||||
std::vector<pstring> t(psplit(replace_all(lt.substr(3), " ", ""), m_expr_sep));
|
std::vector<pstring> t(psplit(replace_all(lt.substr(3), " ", ""), m_expr_sep));
|
||||||
auto val = static_cast<int>(expr(t, start, 255));
|
auto val = static_cast<int>(expr(t, start, 255));
|
||||||
if (val == 0)
|
if (val == 0)
|
||||||
m_ifflag |= (1 << m_level);
|
m_if_flag |= (1 << m_if_level);
|
||||||
}
|
}
|
||||||
else if (lti[0] == "#ifdef")
|
else if (lti[0] == "#ifdef")
|
||||||
{
|
{
|
||||||
m_level++;
|
m_if_level++;
|
||||||
if (get_define(lti[1]) == nullptr)
|
if (get_define(lti[1]) == nullptr)
|
||||||
m_ifflag |= (1 << m_level);
|
m_if_flag |= (1 << m_if_level);
|
||||||
}
|
}
|
||||||
else if (lti[0] == "#ifndef")
|
else if (lti[0] == "#ifndef")
|
||||||
{
|
{
|
||||||
m_level++;
|
m_if_level++;
|
||||||
if (get_define(lti[1]) != nullptr)
|
if (get_define(lti[1]) != nullptr)
|
||||||
m_ifflag |= (1 << m_level);
|
m_if_flag |= (1 << m_if_level);
|
||||||
}
|
}
|
||||||
else if (lti[0] == "#else")
|
else if (lti[0] == "#else")
|
||||||
{
|
{
|
||||||
m_ifflag ^= (1 << m_level);
|
m_if_flag ^= (1 << m_if_level);
|
||||||
}
|
}
|
||||||
else if (lti[0] == "#endif")
|
else if (lti[0] == "#endif")
|
||||||
{
|
{
|
||||||
m_ifflag &= ~(1 << m_level);
|
m_if_flag &= ~(1 << m_if_level);
|
||||||
m_level--;
|
m_if_level--;
|
||||||
}
|
}
|
||||||
else if (lti[0] == "#include")
|
else if (lti[0] == "#include")
|
||||||
{
|
{
|
||||||
@ -508,7 +508,7 @@ pstring ppreprocessor::process_line(pstring line)
|
|||||||
}
|
}
|
||||||
else if (lti[0] == "#pragma")
|
else if (lti[0] == "#pragma")
|
||||||
{
|
{
|
||||||
if (m_ifflag == 0 && lti.size() > 3 && lti[1] == "NETLIST")
|
if (m_if_flag == 0 && lti.size() > 3 && lti[1] == "NETLIST")
|
||||||
{
|
{
|
||||||
if (lti[2] == "warning")
|
if (lti[2] == "warning")
|
||||||
error("NETLIST: " + catremainder(lti, 3, " "));
|
error("NETLIST: " + catremainder(lti, 3, " "));
|
||||||
@ -516,7 +516,7 @@ pstring ppreprocessor::process_line(pstring line)
|
|||||||
}
|
}
|
||||||
else if (lti[0] == "#define")
|
else if (lti[0] == "#define")
|
||||||
{
|
{
|
||||||
if (m_ifflag == 0)
|
if (m_if_flag == 0)
|
||||||
{
|
{
|
||||||
if (lti.size() < 2)
|
if (lti.size() < 2)
|
||||||
error("PREPRO: define needs at least one argument: " + line);
|
error("PREPRO: define needs at least one argument: " + line);
|
||||||
@ -534,14 +534,14 @@ pstring ppreprocessor::process_line(pstring line)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_ifflag == 0)
|
if (m_if_flag == 0)
|
||||||
error(pfmt("unknown directive on line {1}: {2}")(m_lineno)(replace_macros(line)));
|
error(pfmt("unknown directive on line {1}: {2}")(m_lineno)(replace_macros(line)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lt = replace_macros(lt);
|
lt = replace_macros(lt);
|
||||||
if (m_ifflag == 0)
|
if (m_if_flag == 0)
|
||||||
ret += lt;
|
ret += lt;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -190,7 +190,7 @@ public:
|
|||||||
{
|
{
|
||||||
m_lineno++;
|
m_lineno++;
|
||||||
line = process_line(line);
|
line = process_line(line);
|
||||||
m_buf += decltype(m_buf)(line.c_str()) + static_cast<char>(10);
|
m_outbuf += decltype(m_outbuf)(line.c_str()) + static_cast<char>(10);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -202,10 +202,10 @@ public:
|
|||||||
: std::istream(new readbuffer(this))
|
: std::istream(new readbuffer(this))
|
||||||
, m_defines(std::move(s.m_defines))
|
, m_defines(std::move(s.m_defines))
|
||||||
, m_expr_sep(std::move(s.m_expr_sep))
|
, m_expr_sep(std::move(s.m_expr_sep))
|
||||||
, m_ifflag(s.m_ifflag)
|
, m_if_flag(s.m_if_flag)
|
||||||
, m_level(s.m_level)
|
, m_if_level(s.m_if_level)
|
||||||
, m_lineno(s.m_lineno)
|
, m_lineno(s.m_lineno)
|
||||||
, m_buf(std::move(s.m_buf))
|
, m_outbuf(std::move(s.m_outbuf))
|
||||||
, m_pos(s.m_pos)
|
, m_pos(s.m_pos)
|
||||||
, m_state(s.m_state)
|
, m_state(s.m_state)
|
||||||
, m_comment(s.m_comment)
|
, m_comment(s.m_comment)
|
||||||
@ -225,15 +225,14 @@ protected:
|
|||||||
|
|
||||||
int_type underflow() override
|
int_type underflow() override
|
||||||
{
|
{
|
||||||
//printf("here\n");
|
|
||||||
if (this->gptr() == this->egptr())
|
if (this->gptr() == this->egptr())
|
||||||
{
|
{
|
||||||
/* clang reports sign error - weird */
|
/* clang reports sign error - weird */
|
||||||
std::size_t bytes = pstring_mem_t_size(m_strm->m_buf) - static_cast<std::size_t>(m_strm->m_pos);
|
std::size_t bytes = pstring_mem_t_size(m_strm->m_outbuf) - static_cast<std::size_t>(m_strm->m_pos);
|
||||||
|
|
||||||
if (bytes > m_buf.size())
|
if (bytes > m_buf.size())
|
||||||
bytes = m_buf.size();
|
bytes = m_buf.size();
|
||||||
std::copy(m_strm->m_buf.c_str() + m_strm->m_pos, m_strm->m_buf.c_str() + m_strm->m_pos + bytes, m_buf.data());
|
std::copy(m_strm->m_outbuf.c_str() + m_strm->m_pos, m_strm->m_outbuf.c_str() + m_strm->m_pos + bytes, m_buf.data());
|
||||||
//printf("%ld\n", (long int)bytes);
|
//printf("%ld\n", (long int)bytes);
|
||||||
this->setg(m_buf.data(), m_buf.data(), m_buf.data() + bytes);
|
this->setg(m_buf.data(), m_buf.data(), m_buf.data() + bytes);
|
||||||
|
|
||||||
@ -268,10 +267,10 @@ private:
|
|||||||
defines_map_type m_defines;
|
defines_map_type m_defines;
|
||||||
std::vector<pstring> m_expr_sep;
|
std::vector<pstring> m_expr_sep;
|
||||||
|
|
||||||
std::uint_least64_t m_ifflag; // 31 if levels
|
std::uint_least64_t m_if_flag; // 31 if levels
|
||||||
int m_level;
|
int m_if_level;
|
||||||
int m_lineno;
|
int m_lineno;
|
||||||
pstring_t<pu8_traits> m_buf;
|
pstring_t<pu8_traits> m_outbuf;
|
||||||
std::istream::pos_type m_pos;
|
std::istream::pos_type m_pos;
|
||||||
state_e m_state;
|
state_e m_state;
|
||||||
pstring m_line;
|
pstring m_line;
|
||||||
|
@ -15,24 +15,24 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* NL_PMF_TYPE_GNUC_PMF
|
* PMF_TYPE_GNUC_PMF
|
||||||
* Use standard pointer to member function syntax C++11
|
* Use standard pointer to member function syntax C++11
|
||||||
*
|
*
|
||||||
* NL_PMF_TYPE_GNUC_PMF_CONV
|
* PMF_TYPE_GNUC_PMF_CONV
|
||||||
* Use gnu extension and convert the pmf to a function pointer.
|
* Use gnu extension and convert the pmf to a function pointer.
|
||||||
* This is not standard compliant and needs
|
* This is not standard compliant and needs
|
||||||
* -Wno-pmf-conversions to compile.
|
* -Wno-pmf-conversions to compile.
|
||||||
*
|
*
|
||||||
* NL_PMF_TYPE_INTERNAL
|
* PMF_TYPE_INTERNAL
|
||||||
* Use the same approach as MAME for deriving the function pointer.
|
* Use the same approach as MAME for deriving the function pointer.
|
||||||
* This is compiler-dependent as well
|
* This is compiler-dependent as well
|
||||||
*
|
*
|
||||||
* Benchmarks for ./nltool -c run -f src/mame/machine/nl_pong.cpp -t 10 -n pong_fast
|
* Benchmarks for ./nltool -c run -f src/mame/machine/nl_pong.cpp -t 10 -n pong_fast
|
||||||
*
|
*
|
||||||
* NL_PMF_TYPE_INTERNAL: 215% 215%
|
* PMF_TYPE_INTERNAL: 215% 215%
|
||||||
* NL_PMF_TYPE_GNUC_PMF: 163% 196%
|
* PMF_TYPE_GNUC_PMF: 163% 196%
|
||||||
* NL_PMF_TYPE_GNUC_PMF_CONV: 215% 215%
|
* PMF_TYPE_GNUC_PMF_CONV: 215% 215%
|
||||||
* NL_PMF_TYPE_VIRTUAL: 213% 209%
|
* PMF_TYPE_VIRTUAL: 213% 209%
|
||||||
*
|
*
|
||||||
* The whole exercise was done to avoid virtual calls. In prior versions of
|
* The whole exercise was done to avoid virtual calls. In prior versions of
|
||||||
* netlist, the INTERNAL and GNUC_PMF_CONV approach provided significant improvement.
|
* netlist, the INTERNAL and GNUC_PMF_CONV approach provided significant improvement.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// license:GPL-2.0+
|
// license:GPL-2.0+
|
||||||
// copyright-holders:Couriersud
|
// copyright-holders:Couriersud
|
||||||
/*
|
/*
|
||||||
* nl_string.c
|
* pstring.cpp
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -17,9 +17,9 @@
|
|||||||
// noexcept on move operator -> issue with macosx clang
|
// noexcept on move operator -> issue with macosx clang
|
||||||
#define COPYASSIGNMOVE(name, def) \
|
#define COPYASSIGNMOVE(name, def) \
|
||||||
name(const name &) = def; \
|
name(const name &) = def; \
|
||||||
name(name &&) /*noexcept*/ = def; \
|
name(name &&) noexcept = def; \
|
||||||
name &operator=(const name &) = def; \
|
name &operator=(const name &) = def; \
|
||||||
name &operator=(name &&) /*noexcept*/ = def;
|
name &operator=(name &&) noexcept = def;
|
||||||
|
|
||||||
#define COPYASSIGN(name, def) \
|
#define COPYASSIGN(name, def) \
|
||||||
name(const name &) = def; \
|
name(const name &) = def; \
|
||||||
@ -36,14 +36,14 @@ namespace plib
|
|||||||
template<> struct is_integral<INT128> { static constexpr bool value = true; };
|
template<> struct is_integral<INT128> { static constexpr bool value = true; };
|
||||||
template<> struct numeric_limits<UINT128>
|
template<> struct numeric_limits<UINT128>
|
||||||
{
|
{
|
||||||
static constexpr UINT128 max()
|
static constexpr UINT128 max() noexcept
|
||||||
{
|
{
|
||||||
return ~((UINT128)0);
|
return ~((UINT128)0);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<> struct numeric_limits<INT128>
|
template<> struct numeric_limits<INT128>
|
||||||
{
|
{
|
||||||
static constexpr INT128 max()
|
static constexpr INT128 max() noexcept
|
||||||
{
|
{
|
||||||
return (~((UINT128)0)) >> 1;
|
return (~((UINT128)0)) >> 1;
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ namespace plib
|
|||||||
// Avoid unused variable warnings
|
// Avoid unused variable warnings
|
||||||
//============================================================
|
//============================================================
|
||||||
template<typename... Ts>
|
template<typename... Ts>
|
||||||
inline void unused_var(Ts&&...) {}
|
inline void unused_var(Ts&&...) noexcept {}
|
||||||
|
|
||||||
//============================================================
|
//============================================================
|
||||||
// is_pow2
|
// is_pow2
|
||||||
@ -100,7 +100,7 @@ namespace plib
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr
|
constexpr
|
||||||
typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value, T>::type
|
typename std::enable_if<std::is_integral<T>::value && std::is_signed<T>::value, T>::type
|
||||||
abs(T v)
|
abs(T v) noexcept
|
||||||
{
|
{
|
||||||
return v < 0 ? -v : v;
|
return v < 0 ? -v : v;
|
||||||
}
|
}
|
||||||
@ -108,14 +108,14 @@ namespace plib
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr
|
constexpr
|
||||||
typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, T>::type
|
typename std::enable_if<std::is_integral<T>::value && std::is_unsigned<T>::value, T>::type
|
||||||
abs(T v)
|
abs(T v) noexcept
|
||||||
{
|
{
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename M, typename N>
|
template<typename M, typename N>
|
||||||
constexpr typename std::common_type<M, N>::type
|
constexpr typename std::common_type<M, N>::type
|
||||||
gcd(M m, N n)
|
gcd(M m, N n) noexcept
|
||||||
{
|
{
|
||||||
static_assert(std::is_integral<M>::value, "gcd: M must be an integer");
|
static_assert(std::is_integral<M>::value, "gcd: M must be an integer");
|
||||||
static_assert(std::is_integral<N>::value, "gcd: N must be an integer");
|
static_assert(std::is_integral<N>::value, "gcd: N must be an integer");
|
||||||
@ -127,7 +127,7 @@ namespace plib
|
|||||||
|
|
||||||
template<typename M, typename N>
|
template<typename M, typename N>
|
||||||
constexpr typename std::common_type<M, N>::type
|
constexpr typename std::common_type<M, N>::type
|
||||||
lcm(M m, N n)
|
lcm(M m, N n) noexcept
|
||||||
{
|
{
|
||||||
static_assert(std::is_integral<M>::value, "lcm: M must be an integer");
|
static_assert(std::is_integral<M>::value, "lcm: M must be an integer");
|
||||||
static_assert(std::is_integral<N>::value, "lcm: N must be an integer");
|
static_assert(std::is_integral<N>::value, "lcm: N must be an integer");
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
#pragma GCC optimize "ivopts"
|
#pragma GCC optimize "ivopts"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "netlist/nl_lists.h"
|
|
||||||
#include "netlist/nl_factory.h"
|
#include "netlist/nl_factory.h"
|
||||||
#include "nld_matrix_solver.h"
|
#include "nld_matrix_solver.h"
|
||||||
#include "nld_ms_direct.h"
|
#include "nld_ms_direct.h"
|
||||||
|
Loading…
Reference in New Issue
Block a user