File param-ref.hpp¶
File List > epiworld > param-ref.hpp
Go to the documentation of this file
#ifndef EPIWORLD_PARAM_REF_HPP
#define EPIWORLD_PARAM_REF_HPP
struct ParamId {
size_t idx;
};
inline uint32_t new_param_layout_id()
{
static std::atomic< uint32_t > counter{0u};
uint32_t id = ++counter;
while (id == 0u)
id = ++counter;
return id;
}
class ParamRef {
private:
std::string pname;
// (layout id << 32) | position; 0 means not resolved.
mutable std::atomic< uint64_t > cache{0u};
public:
explicit ParamRef(std::string name) : pname(std::move(name)) {};
ParamRef(const ParamRef & other) :
pname(other.pname),
cache(other.cache.load(std::memory_order_relaxed)) {};
ParamRef & operator=(const ParamRef & other)
{
pname = other.pname;
cache.store(
other.cache.load(std::memory_order_relaxed),
std::memory_order_relaxed
);
return *this;
};
const std::string & name() const { return pname; };
template< typename TModel >
ParamId id(const TModel & model) const
{
const uint32_t layout = model.get_param_layout_id();
const uint64_t c = cache.load(std::memory_order_relaxed);
if (static_cast< uint32_t >(c >> 32) == layout)
return ParamId{static_cast< size_t >(c & 0xffffffffu)};
ParamId res = model.get_param_id(pname);
if (res.idx > 0xffffffffu)
return res;
cache.store(
(static_cast< uint64_t >(layout) << 32) |
static_cast< uint64_t >(res.idx),
std::memory_order_relaxed
);
return res;
};
template< typename TModel >
epiworld_double operator()(const TModel & model) const
{
return model.par_at(id(model));
};
};
#endif