VLink 2.0.0
A high-performance communication middleware
Loading...
Searching...
No Matches
status.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2026 by Thun Lu. All rights reserved.
3 * Author: Thun Lu <thun.lu@zohomail.cn>
4 * Repo: https://github.com/thun-res/vlink
5 * _ __ __ _ __
6 * | | / / / / (_) ____ / /__
7 * | | / / / / / / / __ \ / //_/
8 * | |/ / / /___ / / / / / / / ,<
9 * |___/ /_____/ /_/ /_/ /_/ /_/|_|
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License");
12 * you may not use this file except in compliance with the License.
13 * You may obtain a copy of the License at
14 *
15 * http://www.apache.org/licenses/LICENSE-2.0
16 *
17 * Unless required by applicable law or agreed to in writing, software
18 * distributed under the License is distributed on an "AS IS" BASIS,
19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 * See the License for the specific language governing permissions and
21 * limitations under the License.
22 */
23
24/**
25 * @file status.h
26 * @brief DDS-compatible status type hierarchy for VLink publisher and subscriber callbacks.
27 *
28 * @details
29 * The @c Status namespace defines an event-driven status reporting model that mirrors the
30 * DDS status change notification system. When a transport-level event occurs (e.g., a
31 * new subscriber appears, a deadline is missed), the middleware creates a concrete
32 * @c Status::Base subclass and delivers it to the registered status callback.
33 *
34 * Status types are divided into two groups:
35 *
36 * Writer-side (DataWriter / Publisher / Server / Setter):
37 *
38 * | Type | Triggered when |
39 * | -------------------------- | ------------------------------------------------------- |
40 * | @c kPublicationMatched | A matching subscriber appeared or disappeared |
41 * | @c kOfferedDeadlineMissed | Writer failed to publish within its declared deadline |
42 * | @c kOfferedIncompatibleQos | A subscriber with incompatible QoS was discovered |
43 * | @c kLivelinessLost | Writer failed to assert liveliness within its duration |
44 *
45 * Reader-side (DataReader / Subscriber / Client / Getter):
46 *
47 * | Type | Triggered when |
48 * | -------------------------- | -------------------------------------------------------- |
49 * | @c kSubscriptionMatched | A matching publisher appeared or disappeared |
50 * | @c kRequestedDeadlineMissed| Reader did not receive data within its declared deadline |
51 * | @c kLivelinessChanged | A writer's liveliness status changed |
52 * | @c kSampleRejected | An incoming sample was rejected (resource limit hit) |
53 * | @c kRequestedIncompatibleQos | A publisher with incompatible QoS was discovered |
54 * | @c kSampleLost | A sample was lost before it could be delivered |
55 *
56 * Concrete status structs (counters, handles, etc.) are defined in @c status_detail.h.
57 *
58 * @par Usage
59 * @code
60 * auto sub = vlink::Subscriber<MyMsg>::create("dds://my_topic");
61 * sub->register_status_callback([](vlink::Status::BasePtr status) {
62 * if (status->get_type() == vlink::Status::kSubscriptionMatched) {
63 * auto matched = status->as<vlink::Status::SubscriptionMatched>();
64 * VLOG_I("Matched publishers: ", matched->current_count);
65 * }
66 * });
67 * @endcode
68 */
69
70#pragma once
71
72#include <cstdint>
73#include <iostream>
74#include <memory>
75#include <string>
76#include <type_traits>
77
78#include "../base/exception.h"
79#include "../base/macros.h"
80
81namespace vlink {
82
83/**
84 * @namespace vlink::Status
85 * @brief DDS-compatible status type enumeration, base class, and type-safe cast utilities.
86 */
87namespace Status { // NOLINT(readability-identifier-naming)
88
89/**
90 * @brief Discriminator for concrete status event types.
91 *
92 * @details
93 * Values below @c kSubscriptionMatched are writer-side events; values from
94 * @c kSubscriptionMatched onwards are reader-side events.
95 * Use @c is_for_writer() / @c is_for_reader() for category tests.
96 */
97enum Type : uint8_t {
98 kUnknown = 0, ///< Unknown or uninitialised status.
99 // -- For writer
100 kPublicationMatched = 1, ///< A matching subscriber appeared or was removed.
101 kOfferedDeadlineMissed = 2, ///< Writer missed its offered deadline.
102 kOfferedIncompatibleQos = 3, ///< Subscriber with incompatible QoS discovered.
103 kLivelinessLost = 4, ///< Writer liveliness assertion failed.
104 // -- For reader
105 kSubscriptionMatched = 5, ///< A matching publisher appeared or was removed.
106 kRequestedDeadlineMissed = 6, ///< Reader did not receive data within its deadline.
107 kLivelinessChanged = 7, ///< Publisher liveliness state changed.
108 kSampleRejected = 8, ///< Incoming sample was rejected (resource limit).
109 kRequestedIncompatibleQos = 9, ///< Publisher with incompatible QoS discovered.
110 kSampleLost = 10, ///< Sample was lost before delivery.
111};
112
113/**
114 * @brief Returns @c true if @p type is a writer-side status event.
115 *
116 * @param type Status type to classify.
117 * @return @c true for any type with a value below @c kSubscriptionMatched
118 * (excluding @c kUnknown, which returns @c false).
119 */
120[[nodiscard]] [[maybe_unused]] static constexpr bool is_for_writer(Type type) noexcept {
121 return type != kUnknown && type < kSubscriptionMatched;
122}
123
124/**
125 * @brief Returns @c true if @p type is a reader-side status event.
126 *
127 * @param type Status type to classify.
128 * @return @c true for types @c kSubscriptionMatched and above.
129 */
130[[nodiscard]] [[maybe_unused]] static constexpr bool is_for_reader(Type type) noexcept {
131 return type >= kSubscriptionMatched;
132}
133
134/**
135 * @brief Opaque handle type for DDS instance identifiers.
136 *
137 * @details
138 * Carries a transport-level pointer to the matched publication or subscription
139 * endpoint. The exact value is transport-specific and should be treated as opaque.
140 */
141using InstanceHandle = const void*;
142
143/**
144 * @struct Base
145 * @brief Abstract base class for all VLink status event objects.
146 *
147 * @details
148 * All concrete status types (PublicationMatched, SampleRejected, etc.) derive from
149 * @c Base and are delivered as @c std::shared_ptr<Status::Base> via status callbacks.
150 * Use @c as<T>() to safely downcast to a specific concrete type.
151 *
152 * Inherits @c std::enable_shared_from_this to support safe @c shared_ptr construction
153 * from within member functions.
154 */
155struct VLINK_EXPORT Base : public std::enable_shared_from_this<Base> {
156 protected:
158
159 virtual ~Base();
160
161 public:
162 /**
163 * @brief Returns the concrete status type discriminator.
164 *
165 * @return One of the @c Status::Type enum values.
166 */
167 [[nodiscard]] virtual Type get_type() const = 0;
168
169 /**
170 * @brief Returns a human-readable description of this status event.
171 *
172 * @return String representation of the status and its field values.
173 */
174 [[nodiscard]] virtual std::string get_string() const = 0;
175
176 /**
177 * @brief Safely downcasts this status to a concrete type @p T.
178 *
179 * @details
180 * Performs a @c dynamic_pointer_cast. If the status type is @c kUnknown,
181 * throws @c Exception::RuntimeError.
182 *
183 * @tparam T Concrete status struct type (e.g., @c Status::SubscriptionMatched).
184 * Must be derived from @c Base and not be @c Status::Unknown.
185 * @return @c shared_ptr<T> to the concrete status.
186 * @throws Exception::RuntimeError if the status type is @c kUnknown.
187 */
188 template <typename T>
189 [[nodiscard]] std::shared_ptr<T> as() const;
190
191 /**
192 * @brief Writes the human-readable status description to @p ostream.
193 *
194 * @param ostream Output stream.
195 * @param status Status object to print.
196 * @return Reference to @p ostream.
197 */
198 VLINK_EXPORT friend std::ostream& operator<<(std::ostream& ostream, const Base& status) noexcept;
199};
200
201/**
202 * @struct Unknown
203 * @brief Placeholder status returned when the transport reports an unrecognised event type.
204 *
205 * @details
206 * Callers should check @c get_type() == @c kUnknown and skip processing.
207 */
208struct VLINK_EXPORT Unknown final : public Base {
209 public:
210 /**
211 * @brief Returns @c kUnknown.
212 *
213 * @return Always @c kUnknown.
214 */
215 [[nodiscard]] Type get_type() const override;
216
217 /**
218 * @brief Returns "Unknown".
219 *
220 * @return Descriptive string.
221 */
222 [[nodiscard]] std::string get_string() const override;
223
224 /**
225 * @brief Writes "Unknown" to @p ostream.
226 *
227 * @param ostream Output stream.
228 * @param status This @c Unknown status.
229 * @return Reference to @p ostream.
230 */
231 VLINK_EXPORT friend std::ostream& operator<<(std::ostream& ostream, const Unknown& status) noexcept;
232};
233
234/**
235 * @brief Type alias for a shared pointer to a base status event.
236 *
237 * @details
238 * Used as the parameter type for status callbacks registered on publishers,
239 * subscribers, clients, servers, getters, and setters.
240 */
241using BasePtr = std::shared_ptr<Status::Base>;
242
243/**
244 * @brief Writes the human-readable description of @p status to @p ostream.
245 *
246 * @param ostream Output stream.
247 * @param status Shared pointer to a status event.
248 * @return Reference to @p ostream.
249 */
250VLINK_EXPORT std::ostream& operator<<(std::ostream& ostream, const BasePtr& status) noexcept;
251
252////////////////////////////////////////////////////////////////
253/// Details
254////////////////////////////////////////////////////////////////
255
256template <typename T>
257inline std::shared_ptr<T> Base::as() const {
258 static_assert(std::is_base_of_v<Base, T> && !std::is_same_v<struct Unknown, T>,
259 "Can not convert target status type.");
260 if VUNLIKELY (get_type() == kUnknown) {
261 throw Exception::RuntimeError("Target status is unknown");
262 }
263 return std::dynamic_pointer_cast<T>(const_cast<Base*>(this)->shared_from_this());
264}
265
266} // namespace Status
267
268} // namespace vlink
VLink-specific exception types wrapping the C++ standard exception hierarchy.
Platform-independent macro definitions for the VLink library.
#define VUNLIKELY(...)
Shorthand alias for VLINK_UNLIKELY. Hints that the expression is unlikely true.
Definition macros.h:302
#define VLINK_EXPORT
Definition macros.h:85