84template<
class E,
class V,
class K>
98 typedef V* (*RefVehicleFactory)(
const K*, int);
162 for (
int i = 0; i < 2; i++) {
165 myAppliedEffort[i].assign(space, std::numeric_limits<double>::quiet_NaN());
172 delete c->refVehicle;
176 delete item.second.refVehicle;
203 const std::pair<const K*, int> mapKey(key, period);
219 return it->second.metric.get();
255 std::vector<LiveMetric*>& slots =
myByKey[key];
265 const int id = e->getNumericalID();
269 for (
int i = 0; i < 2; i++) {
283 const int id = e->getNumericalID();
309 if (
myQueried.exchange(
false, std::memory_order_acq_rel)
334 const int backShared = 1 -
myLiveMetrics.front()->frontIndex;
339 bool forceFull =
false;
347 std::vector<const E*> accepted;
348 if (!forceFull &&
myLiveMetrics.front()->metric[backShared] !=
nullptr) {
349 std::vector<const E*> stillPending;
351 const int id = e->getNumericalID();
355 if (!std::isnan(effApplied) && effApplied > 0. && effNow > 0.) {
356 const double hi =
MAX2(effNow, effApplied);
357 const double lo =
MIN2(effNow, effApplied);
361 accepted.push_back(e);
365 stillPending.push_back(e);
371 const int back = 1 - c->frontIndex;
381 if (c->metric[back] ==
nullptr) {
390 c->metric[back] = std::make_shared<RoutingKit::CustomizableContractionHierarchyMetric>(
392 c->metric[back]->customize();
393 }
else if (forceFull) {
401 c->metric[back]->customize();
409 std::vector<unsigned>& applied = c->weight[back];
411 unsigned changed = 0;
412 for (
const E* e : accepted) {
415 if (newW != applied[a]) {
417 c->partial->update_arc(a);
423 c->partial->customize(*c->metric[back]);
428 c->frontIndex = back;
429 c->front.store(c->metric[back].get(), std::memory_order_release);
443 std::numeric_limits<double>::quiet_NaN());
452 std::memory_order_release);
460 const auto it =
myByKey.find(key);
468 myQueried.store(
true, std::memory_order_relaxed);
475 if (!
myQueried.load(std::memory_order_relaxed)) {
476 myQueried.store(
true, std::memory_order_relaxed);
501 return c->
front.load(std::memory_order_acquire);
515 std::shared_ptr<RoutingKit::CustomizableContractionHierarchyMetric>
metric[2];
516 std::atomic<const RoutingKit::CustomizableContractionHierarchyMetric*>
front{
nullptr};
523 std::shared_ptr<RoutingKit::CustomizableContractionHierarchyPartialCustomization>
partial;
531 std::unique_ptr<RoutingKit::CustomizableContractionHierarchyMetric>
metric;
540 std::vector<std::pair<unsigned, unsigned> >
patched;
568 const std::vector<unsigned> unpatched(sm.
weights);
570 for (
unsigned a = 0; a < (unsigned)sm.
weights.size(); a++) {
571 if (sm.
weights[a] != unpatched[a]) {
577 for (
const auto& p : sm.
patched) {
578 sm.
weights[p.first] = p.second;
584 static uint64_t
fnv1a(
const std::string& s) {
585 uint64_t h = 1469598103934665603ull;
586 for (
const char ch : s) {
587 h = (h ^ (
unsigned char)ch) * 1099511628211ull;
600 c->
partial = std::make_shared<RoutingKit::CustomizableContractionHierarchyPartialCustomization>(
myGraph->
cch());
639 std::map<const K*, std::vector<LiveMetric*> >
myByKey;
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
Metric-independent RoutingKit CCH topology over the PURE road graph.
unsigned edgeIdSpace() const
size of the edge numerical-id space the graph was built over (for callers keeping per-edge-id side ar...
unsigned arcCount() const
number of input arcs (== number of mapped connections)
double(* EffortOperation)(const E *const, const V *const, double)
effort callback signature, matching SUMOAbstractRouter::Operation
void fillInputWeights(EffortOperation effort, SUMOVehicleClass maskClass, const V *veh, double time, std::vector< unsigned > &weight) const
Fill a centisecond input-weight buffer for one vehicle class.
const RoutingKit::CustomizableContractionHierarchy & cch() const
the immutable CCH (share const& across clones)
const std::vector< unsigned > & arcsOfEdge(const E *e) const
the arcs whose weight depends on the given edge (arcs it heads plus arcs whose folded via chain conta...
unsigned computeArcWeight(unsigned a, EffortOperation effort, SUMOVehicleClass maskClass, const V *veh, double time) const
Recompute the input weight of one arc – the exact per-arc body of fillInputWeights (same masking,...
per-vehicle-type CCH metric store over a shared CCHGraph
std::map< const K *, std::vector< LiveMetric * > > myByKey
bool myStale
the efforts changed behind the cached metrics: refill and re-customize them all on the next get() (se...
std::vector< const E * > myPendingList[2]
MetricPtr get(const K *key, SUMOVehicleClass vClass, SUMOTime time, const V *veh)
the metric for (type key, period of time), built on the first query of the pair; nullptr before init....
void seedKey(const K *key)
allocate the metric state (all ensemble slots) for one type; call only while no query is in flight (s...
const Graph * myGraph
the immutable shared topology
EffortOperation myFillEffort
the effort the metrics are filled from
std::map< std::pair< const K *, int >, StaticMetric > myStaticMetrics
int periodOf(SUMOTime time) const
the weight period containing time: 0 is everything before begin and the whole run when the weights ar...
WeightPatch myPatch
post-fill weight hook (STATIC)
const bool myLive
LIVE or STATIC (fixed at construction)
std::vector< LiveMetric * > myLiveMetrics
every type's state, in creation order (barrier iteration) and by key (query lookup; only mutated whil...
void atBarrier(double now, bool effortsMoved)
the owner's customization barrier: bump the speed epoch when an effort moved and re-customize when it...
int myFullFillsPending
how many customize passes must run a FULL refill after a permission flip: 2 = both ping-pong buffers ...
std::atomic< bool > myQueried
whether a query arrived since the last barrier (bootstraps type creation and re-arms after resets – s...
RefVehicleFactory myFactory
reference-vehicle factory (required LIVE, optional STATIC)
std::atomic< uint64_t > myPublishedEpoch
void customize(double now)
refill + customize + publish every type's metric from the live efforts and permissions....
std::vector< const K * > myWantedKeys
types that queried but have no metric yet (demand streams, so types can appear after seeding); querie...
V *(* RefVehicleFactory)(const K *, int)
builds an OWNED effort-reference vehicle for a type: never registered, counted or inserted – it exist...
CCHMetricFamily(const Graph *graph, EffortOperation fillEffort, SUMOTime begin, SUMOTime weightPeriod, RefVehicleFactory factory, WeightPatch patch)
construct a STATIC family (lazy build per (type, period))
void fillStatic(StaticMetric &sm, int period, SUMOTime time, const V *ref, const V *veh)
(re)fill a STATIC metric's input weights from the live efforts. A weight-period grid evaluates at the...
CCHMetricFamily & operator=(const CCHMetricFamily &)=delete
bool empty() const
whether any type has live metric state yet
void flagStale()
the efforts behind the cached metrics changed – a runtime permission change in the simulation (the ca...
const RoutingKit::CustomizableContractionHierarchyMetric * MetricPtr
void invalidateEdge(const E *e)
a runtime permission change (closure / re-opening) hit this edge: queue it bypassing the deadband and...
std::atomic< uint64_t > mySpeedEpoch
barrier counter of the tracked efforts and the counter value the published metrics were customized fr...
CCHMetricFamily(const Graph *graph, EffortOperation fillEffort, EffortOperation gateEffort, double updateFactor, double updateConstant, RefVehicleFactory factory, int ensembleK=1)
construct a LIVE family (double-buffered, barrier-customized)
std::atomic< bool > myMetricStale
a permission flip has not yet been customized into the published metrics (queries divert to the exact...
SUMOTime periodEnd(SUMOTime time) const
the end of the weight period containing the given time (SUMOTime_MAX when the weights are static); CC...
int myEnsembleK
frozen random-factor realizations per type (see the LIVE ctor)
EffortOperation myGateEffort
the type-independent effort of the LIVE deadband
Graph::EffortOperation EffortOperation
MetricPtr published(const K *key, const std::string &vehID)
the published metric for a type key and querying vehicle id (the id picks the ensemble slot – see the...
void flagPermissionsStale()
flagStale() under the simulation's name for the permission case
std::vector< double > myAppliedEffort[2]
per-buffer edge state for the sparse path: the gate effort each edge's arcs were last filled from (Na...
static uint64_t fnv1a(const std::string &s)
stable 64-bit FNV-1a for the ensemble slot assignment
void markDirty(const E *e)
queue an edge whose gate effort changed (both buffers; the deadband applies later,...
void(* WeightPatch)(const Graph *, const V *, std::vector< unsigned > &)
post-fill hook on the input weights (STATIC mode), e.g. duarouter masking the edges that restrict a t...
LiveMetric * buildLiveMetric(const K *key, int slot)
allocate LIVE metric state for one (type, ensemble slot) (owner's thread only)
std::vector< char > myPendingFlag[2]
CCHMetricFamily(const CCHMetricFamily &)=delete
per-type LIVE metric state. Heap-owned: the atomic makes it non-movable, so it cannot live in a map b...
V * refVehicle
OWNED effort-reference vehicle (see RefVehicleFactory)
std::vector< unsigned > weight[2]
std::atomic< const RoutingKit::CustomizableContractionHierarchyMetric * > front
std::shared_ptr< RoutingKit::CustomizableContractionHierarchyPartialCustomization > partial
partial-customization worker (queue over the shared CCH); one per metric – its queue is drained by ev...
std::shared_ptr< RoutingKit::CustomizableContractionHierarchyMetric > metric[2]
per-(type, period) STATIC metric state. RoutingKit metrics BORROW their input-weight buffer,...
std::vector< unsigned > weights
V * refVehicle
OWNED reference vehicle (nullptr when filling with the querying vehicle)
std::vector< std::pair< unsigned, unsigned > > patched
the (arc, weight) pairs the patch wrote on the first fill, re-applied on every refill
bool filled
whether the first fill (which runs the patch) is done
std::unique_ptr< RoutingKit::CustomizableContractionHierarchyMetric > metric