77 InterProcessPortalImplementation<InnerTransporter, PortalBase, ImplementationTag>,
78 InnerTransporter, ImplementationTag>
83 InnerTransporter, ImplementationTag>;
92 :
Base(inner), cfg_(cfg)
100 subscribers_.clear();
101 wildcard_subscriber_.reset();
102 liveliness_subscriber_.reset();
103 ready_token_.reset();
116 "announce readiness to any peer holding for it"
121 LocalDeliveryScope scope(local_delivery_thread_);
123 std::make_unique<::zenoh::LivelinessToken>(session_->liveliness_declare_token(
131 friend typename Base::Base;
132 friend typename Base::Common;
139 session_ = std::make_unique<::zenoh::Session>(
open_session(cfg_));
148 ::zenoh::Session::LivelinessSubscriberOptions options;
150 options.history =
true;
152 liveliness_subscriber_ =
153 std::make_unique<::zenoh::Subscriber<void>>(session_->liveliness_declare_subscriber(
154 ::zenoh::KeyExpr(hold_root_ +
"/**"), [
this](const ::zenoh::Sample& sample)
155 { _on_liveliness(sample); }, ::zenoh::closures::none, std::move(options)));
160 void _on_liveliness(const ::zenoh::Sample& sample)
162 const std::string key(sample.get_keyexpr().as_string_view());
163 const auto last = key.find_last_of(
'/');
164 if (last == std::string::npos)
169 std::lock_guard<std::mutex> lock(rx_mutex_);
170 if (sample.get_kind() == ::zenoh::SampleKind::Z_SAMPLE_KIND_PUT)
171 ready_clients_.insert(client);
173 ready_clients_.erase(client);
182 std::set<std::string>
ready;
184 std::lock_guard<std::mutex> lock(rx_mutex_);
185 ready = ready_clients_;
188 for (
const auto& client : cfg_.hold().required_client())
189 if (!
ready.count(client))
194 std::this_thread::sleep_for(std::chrono::duration<double>(cfg_.
hold().
settle_seconds()));
199 for (
auto& queued : publish_queue_) _put(queued.first, queued.second);
200 publish_queue_.clear();
203 void _do_publish(
const std::string& identifier,
const std::vector<char>& bytes)
207 publish_queue_.emplace_back(identifier, bytes);
210 _put(identifier, bytes);
213 void _put(
const std::string& identifier,
const std::vector<char>& bytes)
220 ::zenoh::Session::PutOptions options;
221 options.congestion_control =
223 ? ::zenoh::CongestionControl::Z_CONGESTION_CONTROL_DROP
224 : ::zenoh::CongestionControl::Z_CONGESTION_CONTROL_BLOCK;
225 options.is_express = cfg_.
express();
227 LocalDeliveryScope scope(local_delivery_thread_);
228 session_->put(::zenoh::KeyExpr(key),
229 ::zenoh::Bytes(std::string(bytes.begin(), bytes.end())), std::move(options));
232 void _do_portal_subscribe(
const std::string& identifier)
234 portal_identifiers_.insert(identifier);
237 if (!wildcard_subscriber_)
238 _declare(identifier);
241 void _do_portal_unsubscribe(
const std::string& identifier)
243 portal_identifiers_.erase(identifier);
244 subscribers_.erase(identifier);
247 void _do_portal_wildcard_subscribe()
249 subscribers_.clear();
250 wildcard_subscriber_ =
251 std::make_unique<::zenoh::Subscriber<void>>(_make_subscriber(key_root_ +
"/**"));
254 void _do_portal_wildcard_unsubscribe()
256 wildcard_subscriber_.reset();
257 for (
const auto& identifier : portal_identifiers_) _declare(identifier);
260 void _declare(
const std::string& identifier)
263 subscribers_.erase(identifier);
264 subscribers_.emplace(identifier, _make_subscriber(key));
267 ::zenoh::Subscriber<void> _make_subscriber(
const std::string& key)
271 return session_->declare_subscriber(
272 ::zenoh::KeyExpr(key), [
this](const ::zenoh::Sample& sample) { _on_sample(sample); },
273 ::zenoh::closures::none);
277 void _on_sample(const ::zenoh::Sample& sample)
280 key_root_, std::string(sample.get_keyexpr().as_string_view()));
281 if (identifier.empty())
284 << sample.get_keyexpr().as_string_view()
291 identifier += sample.get_payload().as_string();
294 std::lock_guard<std::mutex>
lock(rx_mutex_);
295 rx_.push_back(std::move(identifier));
302 class LocalDeliveryScope
305 LocalDeliveryScope(std::atomic<std::thread::id>& thread) : thread_(thread)
307 thread_ = std::this_thread::get_id();
309 ~LocalDeliveryScope() { thread_ = std::thread::id(); }
312 std::atomic<std::thread::id>& thread_;
319 if (std::this_thread::get_id() == local_delivery_thread_.load())
324 int _poll(std::unique_ptr<std::unique_lock<std::mutex>>& lock)
329 std::deque<std::string> received;
331 std::lock_guard<std::mutex> rx_lock(rx_mutex_);
336 for (
const auto& data : received)
339 this->_handle_received_data(lock, data);
345 const protobuf::InterProcessPortalConfig cfg_;
346 std::string key_root_;
347 std::unique_ptr<::zenoh::Session> session_;
350 std::set<std::string> portal_identifiers_;
351 std::unordered_map<std::string, ::zenoh::Subscriber<void>> subscribers_;
352 std::unique_ptr<::zenoh::Subscriber<void>> wildcard_subscriber_;
354 std::string hold_root_;
356 std::unique_ptr<::zenoh::LivelinessToken> ready_token_;
357 std::unique_ptr<::zenoh::Subscriber<void>> liveliness_subscriber_;
358 std::deque<std::pair<std::string, std::vector<char>>> publish_queue_;
359 std::atomic<std::thread::id> local_delivery_thread_{std::thread::id()};
362 std::mutex rx_mutex_;
363 std::deque<std::string> rx_;
364 std::set<std::string> ready_clients_;