CARLA
Loading...
Searching...
No Matches
sensorStreamRegistry.cpp
Go to the documentation of this file.
1// Copyright (c) 2026 Computer Vision Center (CVC) at the Universitat Autonoma de Barcelona (UAB).
2// This work is licensed under the terms of the MIT license.
3// For a copy, see <https://opensource.org/licenses/MIT>.
4
6
7#include "carla/Logging.h"
8
9#include <utility>
10
11namespace carla {
12namespace multigpu {
13
14std::optional<SensorStreamRegistry::token_type> SensorStreamRegistry::Resolve(
17 stream_id_type primary_stream_id) {
18 std::scoped_lock<std::mutex> lock(_mutex);
19
20 auto it = _entries.find(actor_id);
21 std::optional<token_type> token;
22 if (it != _entries.end()) {
23 token = server.FindToken(it->second.stream_id);
24 if (!token) {
25 log_warning("multigpu: stream ", it->second.stream_id, " of actor ", actor_id, " no longer exists");
26 Forget(server, it->second);
27 _entries.erase(it);
28 it = _entries.end();
29 }
30 }
31
32 if (it == _entries.end()) {
33 auto stream = server.MakeStream();
34 const auto stream_id = token_type(stream.token()).get_stream_id();
35 token = server.FindToken(stream_id);
36 if (!token) {
37 return std::nullopt;
38 }
39 it = _entries.emplace(actor_id, Entry{stream_id, std::move(stream), std::nullopt}).first;
40 log_info("multigpu: reserved stream ", stream_id, " for actor ", actor_id, " until it spawns");
41 }
42
43 auto &entry = it->second;
44 if (entry.primary_stream_id && (*entry.primary_stream_id != primary_stream_id)) {
45 server.RemoveStreamAlias(*entry.primary_stream_id);
46 }
47 entry.primary_stream_id = primary_stream_id;
48 server.SetStreamAlias(primary_stream_id, entry.stream_id);
49
50 token->set_stream_id(primary_stream_id);
51 return token;
52}
53
54std::optional<carla::streaming::Stream> SensorStreamRegistry::Bind(
57 stream_id_type sensor_stream_id,
58 bool can_adopt) {
59 std::scoped_lock<std::mutex> lock(_mutex);
60 if (!_bindable) {
61 return std::nullopt;
62 }
63
64 for (const auto &[other_actor_id, other] : _entries) {
65 if ((other_actor_id != actor_id) && (other.stream_id == sensor_stream_id)) {
67 "multigpu: actor ", actor_id, " replayed onto the sensor of actor ", other_actor_id, "; not binding it");
68 return std::nullopt;
69 }
70 }
71
72 auto it = _entries.find(actor_id);
73 if (it == _entries.end()) {
74 _entries.emplace(actor_id, Entry{sensor_stream_id, std::nullopt, std::nullopt});
75 return std::nullopt;
76 }
77
78 auto &entry = it->second;
79 if (entry.reserved && (entry.stream_id != sensor_stream_id) && can_adopt) {
80 return std::exchange(entry.reserved, std::nullopt);
81 }
82
83 if (entry.stream_id != sensor_stream_id) {
84 if (entry.primary_stream_id) {
85 server.SetStreamAlias(*entry.primary_stream_id, sensor_stream_id);
86 }
87 // Early subscribers get disconnected and reconnect through the alias.
88 if (entry.reserved) {
89 server.CloseStream(entry.stream_id);
90 }
91 entry.stream_id = sensor_stream_id;
92 }
93 entry.reserved.reset();
94 return std::nullopt;
95}
96
98 std::scoped_lock<std::mutex> lock(_mutex);
99 // Destroy events replayed before the new episode opens belong to the
100 // previous one, whose actor ids may collide with the current reservations.
101 if (!_bindable) {
102 return;
103 }
104 auto it = _entries.find(actor_id);
105 if (it == _entries.end()) {
106 return;
107 }
108 Forget(server, it->second);
109 _entries.erase(it);
110}
111
113 std::scoped_lock<std::mutex> lock(_mutex);
114 for (const auto &item : _entries) {
115 Forget(server, item.second);
116 }
117 _entries.clear();
118 _bindable = false;
119 return ++_epoch;
120}
121
123 std::scoped_lock<std::mutex> lock(_mutex);
124 _bindable = (epoch == _epoch);
125}
126
128 std::scoped_lock<std::mutex> lock(_mutex);
129 _bindable = false;
130}
131
133 std::scoped_lock<std::mutex> lock(_mutex);
134 return _bindable;
135}
136
138 if (entry.primary_stream_id) {
140 }
141 if (entry.reserved) {
142 server.CloseStream(entry.stream_id);
143 }
144}
145
146} // namespace multigpu
147} // namespace carla
long long first
Definition LaneGraph.cpp:34
carla::streaming::detail::stream_id_type stream_id_type
static void Forget(carla::streaming::Server &server, const Entry &entry)
std::optional< token_type > Resolve(carla::streaming::Server &server, actor_id_type actor_id, stream_id_type primary_stream_id)
Token that serves primary actor actor_id under primary_stream_id, reserving a local stream if the sen...
epoch_type BeginEpisodeChange(carla::streaming::Server &server)
The primary switched episode: forgets every actor and returns the epoch the secondary must pass to Op...
bool IsEpisodeOpen()
Whether Bind()/Unbind() are accepted, i.e.
carla::streaming::detail::token_type token_type
void OpenEpisode(epoch_type epoch)
Accepts binding if epoch is the latest one BeginEpisodeChange() issued.
std::optional< carla::streaming::Stream > Bind(carla::streaming::Server &server, actor_id_type actor_id, stream_id_type sensor_stream_id, bool can_adopt)
Returns the stream reserved for actor_id if can_adopt (the sensor has never ticked) and the sensor mu...
std::unordered_map< actor_id_type, Entry > _entries
void Unbind(carla::streaming::Server &server, actor_id_type actor_id)
Forgets actor_id, closing its reserved stream if no sensor adopted it.
A streaming server.
void RemoveStreamAlias(stream_id alias)
std::optional< token_type > FindToken(stream_id id)
Token of an existing stream, or std::nullopt if id is unknown.
void CloseStream(carla::streaming::detail::stream_id_type id)
void SetStreamAlias(stream_id alias, stream_id target)
carla::streaming::detail::stream_id_type stream_id
This file contains definitions of common data structures used in traffic manager.
static void log_info(Args &&... args)
Definition Logging.h:82
static void log_warning(Args &&... args)
Definition Logging.h:96
std::optional< carla::streaming::Stream > reserved
std::optional< stream_id_type > primary_stream_id