15#include <shared_mutex>
17#include <unordered_map>
43 const std::unique_lock lock{mutex_};
44 register_unit_locked(d);
50 template <UnitLike Unit>
52 const auto d = Unit::descriptor();
53 const std::unique_lock lock{mutex_};
54 if (id_index_.contains(d.id)) {
57 register_unit_locked(d);
63 const std::shared_lock lock{mutex_};
64 if (
const auto it = id_index_.find(id_or_symbol); it != id_index_.end()) {
65 return &entries_[it->second];
67 if (
const auto it = symbol_index_.find(id_or_symbol); it != symbol_index_.end()) {
68 return &entries_[it->second];
74 [[nodiscard]] std::vector<UnitDescriptor>
list()
const {
75 const std::shared_lock lock{mutex_};
80 [[nodiscard]] std::vector<UnitDescriptor>
by_kind(
const std::string_view kind)
const {
81 const std::shared_lock lock{mutex_};
82 std::vector<UnitDescriptor> out;
83 for (
const auto& e : entries_) {
92 [[nodiscard]]
bool compatible(
const std::string_view a,
const std::string_view b)
const {
93 const std::shared_lock lock{mutex_};
94 const auto* da = find_locked(a);
95 const auto* db = find_locked(b);
96 return da !=
nullptr && db !=
nullptr && da->kind == db->kind;
100 [[nodiscard]] std::size_t
size()
const {
101 const std::shared_lock lock{mutex_};
102 return entries_.size();
106 [[nodiscard]]
const UnitDescriptor* find_locked(
const std::string_view key)
const {
107 if (
const auto it = id_index_.find(key); it != id_index_.end()) {
108 return &entries_[it->second];
110 if (
const auto it = symbol_index_.find(key); it != symbol_index_.end()) {
111 return &entries_[it->second];
116 void register_unit_locked(
const UnitDescriptor& d) {
117 if (
const auto it = id_index_.find(d.id); it != id_index_.end()) {
118 entries_[it->second] = d;
120 const auto idx = entries_.size();
121 entries_.push_back(d);
122 id_index_[d.id] = idx;
123 if (!d.symbol.empty() && d.symbol != d.id) {
124 symbol_index_[d.symbol] = idx;
129 mutable std::shared_mutex mutex_;
130 std::vector<UnitDescriptor> entries_;
131 std::unordered_map<std::string_view, std::size_t> id_index_;
132 std::unordered_map<std::string_view, std::size_t> symbol_index_;
153 const std::unique_lock lock{mutex_};
154 register_measure_locked(d);
159 template <MeasureLike Measure>
161 const auto d = Measure::descriptor();
162 const std::unique_lock lock{mutex_};
163 if (id_index_.contains(d.id)) {
166 register_measure_locked(d);
171 const std::shared_lock lock{mutex_};
172 if (
const auto it = id_index_.find(
id); it != id_index_.end()) {
173 return &entries_[it->second];
178 [[nodiscard]] std::vector<MeasureDescriptor> list()
const {
179 const std::shared_lock lock{mutex_};
185 [[nodiscard]]
bool compatible(
const std::string_view measure_id,
186 const std::string_view unit_id)
const {
187 const std::shared_lock lock{mutex_};
188 if (
const auto it = id_index_.find(measure_id); it != id_index_.end()) {
189 return entries_[it->second].base_unit_id == unit_id;
194 [[nodiscard]] std::size_t size()
const {
195 const std::shared_lock lock{mutex_};
196 return entries_.size();
200 void register_measure_locked(
const MeasureDescriptor& d) {
201 if (
const auto it = id_index_.find(d.id); it != id_index_.end()) {
202 entries_[it->second] = d;
204 const auto idx = entries_.size();
205 entries_.push_back(d);
206 id_index_[d.id] = idx;
210 mutable std::shared_mutex mutex_;
211 std::vector<MeasureDescriptor> entries_;
212 std::unordered_map<std::string_view, std::size_t> id_index_;
220template <UnitLike Unit>
221[[maybe_unused]]
inline int register_unit_tag() {
227template <MeasureLike Measure>
228[[maybe_unused]]
inline int register_measure_tag() {
Registry of measure descriptors.
Definition registry.hpp:136
static MeasureRegistry & global()
Process-wide singleton.
Definition registry.hpp:146
bool compatible(const std::string_view measure_id, const std::string_view unit_id) const
True iff measure_id and unit_id both resolve and the measure's declared base unit equals unit_id.
Definition registry.hpp:185
void register_measure(const MeasureDescriptor &d)
Register a descriptor. Existing entries with the same id are replaced.
Definition registry.hpp:152
bool register_measure()
Register a measure by tag — pulls the descriptor through Measure::descriptor().
Definition registry.hpp:160
Registry of unit descriptors.
Definition registry.hpp:26
const UnitDescriptor * find(const std::string_view id_or_symbol) const
Look up by id, then by symbol. Returns nullptr if not found.
Definition registry.hpp:62
std::vector< UnitDescriptor > list() const
Snapshot all registered descriptors.
Definition registry.hpp:74
std::size_t size() const
Number of registered descriptors.
Definition registry.hpp:100
bool compatible(const std::string_view a, const std::string_view b) const
True iff both ids resolve and share the same kind.
Definition registry.hpp:92
std::vector< UnitDescriptor > by_kind(const std::string_view kind) const
Snapshot all descriptors whose kind matches.
Definition registry.hpp:80
bool register_unit()
Register a unit by tag — pulls the descriptor through Unit::descriptor().
Definition registry.hpp:51
static UnitRegistry & global()
Process-wide singleton.
Definition registry.hpp:36
void register_unit(const UnitDescriptor &d)
Register a descriptor. Existing entries with the same id are replaced.
Definition registry.hpp:42
Runtime metadata structs for units and measures.
Runtime metadata for a measure (a semantic specialization of a unit).
Definition descriptor.hpp:54
Runtime metadata for a unit.
Definition descriptor.hpp:29
Concepts and helper accessors that drive the static side of dimval.