VLink 2.0.0
A high-performance communication middleware
Loading...
Searching...
No Matches
conf.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 conf.h
26 * @brief Abstract transport configuration base class and associated helper macros.
27 *
28 * @details
29 * @c Conf is the pure-virtual base for every transport backend configuration
30 * object (e.g. @c DdsConf, @c ShmConf, @c IntraConf). It acts as a bridge
31 * between the URL parsing layer and the concrete @c NodeImpl factories:
32 *
33 * -# A @c Url object parses the transport from the URL string and constructs
34 * the corresponding @c Conf subclass.
35 * -# When a @c Publisher<T> / @c Subscriber<T> / etc. calls @c init(), the
36 * node template calls @c Conf::parse(impl_type) followed by
37 * @c Conf::create_publisher() / @c create_subscriber() / etc. to obtain a
38 * transport-specific @c NodeImpl instance.
39 * -# The @c NodeImpl carries out the actual IPC/DDS/SHM operations.
40 *
41 * @par Macro Overview
42 * Several helper macros reduce boilerplate in concrete @c Conf subclasses:
43 *
44 * | Macro | Purpose |
45 * | ------------------------------ | -------------------------------------------------------------- |
46 * | VLINK_DECLARE_CONF_FRIEND() | Grants friendship to all six Node<> template specialisations. |
47 * | VLINK_CONF_IMPL(classname) | Declares the private Conf interface inside a concrete class. |
48 * | VLINK_ALLOW_IMPL_TYPE(type) | Declares which ImplType bitmask the Conf supports. |
49 * | VLINK_DECLARE_GLOBAL_PROPERTY()| Declares per-class thread count and global property storage. |
50 * | VLINK_DEFINE_GLOBAL_PROPERTY() | Defines the static members declared by the above macro. |
51 */
52
53#pragma once
54
55#include <map>
56#include <memory>
57#include <shared_mutex>
58#include <string>
59#include <utility>
60
61#include "../base/macros.h"
62#include "./types.h"
63
64namespace vlink {
65
66/**
67 * @struct Conf
68 * @brief Abstract base class for VLink transport configuration objects.
69 *
70 * @details
71 * Each supported transport backend has a corresponding @c Conf subclass that
72 * implements the virtual factory methods (@c create_publisher, @c create_server,
73 * etc.) to produce transport-specific @c NodeImpl instances. The base class
74 * provides default implementations that return @c nullptr / @c false, so
75 * subclasses only need to override the methods they support.
76 *
77 * @c Conf objects are held exclusively by @c Url and the six Node<> template
78 * classes; they are not intended for direct use by application code.
79 *
80 * @note The @c parse() method caches the @c ImplType so that subsequent
81 * factory calls know which node role is being requested.
82 */
84 /**
85 * @brief Key/value property map type.
86 *
87 * @details
88 * Used by transport conf subclasses and @c NodeImpl to store DDS QoS
89 * strings, IP addresses, buffer sizes, and other per-channel tuning
90 * parameters (e.g. @c "dds.ip" = @c "127.0.0.1").
91 */
92 using PropertiesMap = std::map<std::string, std::string>;
93
94 /**
95 * @brief Virtual destructor.
96 */
97 virtual ~Conf();
98
99 /**
100 * @brief Validates the conf for the given node role and caches the type.
101 *
102 * @details
103 * Called by the Node<> template before invoking any @c create_*() factory.
104 * The base implementation logs a fatal message and returns @c false for
105 * @c kUnknownImplType; otherwise it caches @p impl_type and returns @c true.
106 * Concrete subclasses typically call this base and then validate their own
107 * fields.
108 *
109 * @param impl_type The role being requested (e.g. @c kPublisher).
110 * @return @c true on success; @c false if the type is unknown.
111 */
112 [[nodiscard]] virtual bool parse(ImplType impl_type) const;
113
114 /**
115 * @brief Returns @c true when the configuration holds valid, usable data.
116 *
117 * @details
118 * The base implementation always returns @c false. Subclasses override
119 * this to perform transport-specific validation.
120 *
121 * @return @c true if the configuration is ready to create @c NodeImpl objects.
122 */
123 [[nodiscard]] virtual bool is_valid() const;
124
125 /**
126 * @brief Returns the most recently parsed @c ImplType.
127 *
128 * @return @c ImplType cached by the last call to @c parse(); @c kUnknownImplType
129 * before @c parse() is called.
130 */
131 [[nodiscard]] virtual ImplType get_impl_type() const;
132
133 /**
134 * @brief Returns the transport backend this configuration represents.
135 *
136 * @details
137 * The base implementation returns @c TransportType::kUnknown.
138 * Each subclass overrides this to return its own @c TransportType value.
139 *
140 * @return @c TransportType identifier for this conf.
141 */
142 [[nodiscard]] virtual TransportType get_transport_type() const;
143
144 uint32_t hash_code{0}; ///< Hash of the URL string; used for fast URL lookup in caches.
145
146 protected:
148
149 [[nodiscard]] virtual bool parse_protocol(struct Protocol* protocol);
150
151 [[nodiscard]] virtual std::unique_ptr<class ServerImpl> create_server() const;
152
153 [[nodiscard]] virtual std::unique_ptr<class ClientImpl> create_client() const;
154
155 [[nodiscard]] virtual std::unique_ptr<class PublisherImpl> create_publisher() const;
156
157 [[nodiscard]] virtual std::unique_ptr<class SubscriberImpl> create_subscriber() const;
158
159 [[nodiscard]] virtual std::unique_ptr<class SetterImpl> create_setter() const;
160
161 [[nodiscard]] virtual std::unique_ptr<class GetterImpl> create_getter() const;
162
163 private:
164 friend struct Url;
165 template <typename, typename, SecurityType>
166 friend class Server;
167 template <typename, typename, SecurityType>
168 friend class Client;
169 template <typename, SecurityType>
170 friend class Publisher;
171 template <typename, SecurityType>
172 friend class Subscriber;
173 template <typename, SecurityType>
174 friend class Setter;
175 template <typename, SecurityType>
176 friend class Getter;
177
178 mutable ImplType impl_type_{kUnknownImplType};
179};
180
181} // namespace vlink
182
183////////////////////////////////////////////////////////////////
184/// Macro Definitions
185////////////////////////////////////////////////////////////////
186
187/**
188 * @def VLINK_DECLARE_CONF_FRIEND
189 * @brief Declares all six VLink Node template specialisations as friends.
190 *
191 * @details
192 * Placed inside a concrete @c Conf subclass declaration to allow
193 * @c Server<>, @c Client<>, @c Publisher<>, @c Subscriber<>, @c Setter<>,
194 * and @c Getter<> to access the protected @c create_*() factory methods and
195 * @c parse_protocol(). Use @c VLINK_CONF_IMPL(classname) which already
196 * expands this macro; only include this macro directly when you need friend
197 * access without the full @c VLINK_CONF_IMPL boilerplate.
198 */
199#define VLINK_DECLARE_CONF_FRIEND() \
200 template <typename, typename, SecurityType> \
201 friend class Server; \
202 template <typename, typename, SecurityType> \
203 friend class Client; \
204 template <typename, SecurityType> \
205 friend class Publisher; \
206 template <typename, SecurityType> \
207 friend class Subscriber; \
208 template <typename, SecurityType> \
209 friend class Setter; \
210 template <typename, SecurityType> \
211 friend class Getter;
212
213/**
214 * @def VLINK_CONF_IMPL
215 * @brief Standard boilerplate for concrete @c Conf subclass declarations.
216 *
217 * @details
218 * Adds to the class:
219 * - @c VLINK_DECLARE_CONF_FRIEND() -- friend access for Node<> templates.
220 * - Overrides for all six protected @c Conf factory methods.
221 * - @c operator<<(ostream, classname) for debug printing.
222 * - A public default constructor.
223 * - @c bool is_valid() const override -- subclass must define the body.
224 *
225 * @param classname The name of the concrete @c Conf subclass.
226 */
227#define VLINK_CONF_IMPL(classname) \
228 private: \
229 VLINK_DECLARE_CONF_FRIEND() \
230 \
231 [[nodiscard]] bool parse_protocol(struct Protocol* protocol) override; \
232 \
233 [[nodiscard]] std::unique_ptr<class ServerImpl> create_server() const override; \
234 \
235 [[nodiscard]] std::unique_ptr<class ClientImpl> create_client() const override; \
236 \
237 [[nodiscard]] std::unique_ptr<class PublisherImpl> create_publisher() const override; \
238 \
239 [[nodiscard]] std::unique_ptr<class SubscriberImpl> create_subscriber() const override; \
240 \
241 [[nodiscard]] std::unique_ptr<class SetterImpl> create_setter() const override; \
242 \
243 [[nodiscard]] std::unique_ptr<class GetterImpl> create_getter() const override; \
244 \
245 VLINK_EXPORT friend std::ostream& operator<<(std::ostream& ostream, const classname& conf) noexcept; \
246 \
247 public: \
248 classname() = default; \
249 \
250 ~classname() = default; \
251 \
252 [[nodiscard]] bool is_valid() const override;
253
254/**
255 * @def VLINK_ALLOW_IMPL_TYPE
256 * @brief Declares a static constexpr bitmask of supported @c ImplType values.
257 *
258 * @details
259 * Expands to a public @c get_allow_impl_type() that returns @p type, allowing
260 * the Node<> template to assert at compile time that the conf supports the
261 * requested node role. Use bitwise-OR to combine multiple roles, e.g.:
262 * @code
263 * VLINK_ALLOW_IMPL_TYPE(kServer | kClient | kPublisher | kSubscriber | kSetter | kGetter)
264 * @endcode
265 *
266 * @param type Bitmask of @c ImplType values this conf supports.
267 */
268#define VLINK_ALLOW_IMPL_TYPE(type) \
269 public: \
270 [[nodiscard]] static constexpr int get_allow_impl_type() { return type; }
271
272/**
273 * @def VLINK_DECLARE_GLOBAL_PROPERTY
274 * @brief Declares per-transport global state: thread count and property storage.
275 *
276 * @details
277 * Intended for use inside a concrete @c Conf subclass body. Declares:
278 * - @c thread_count_ -- number of I/O threads for this transport.
279 * - @c global_properties_ -- default properties applied to every node of this transport.
280 * - @c global_mtx_ -- shared mutex protecting @c global_properties_.
281 *
282 * Also injects:
283 * - @c get_thread_count() -- retrieve current thread count.
284 * - @c set_thread_count() -- set thread count (must be called before @c global_init()).
285 * - @c set_global_property(prop, value) -- set a default property for all nodes.
286 * - @c get_global_property(prop) -- retrieve a default property.
287 * - @c get_global_all_properties() -- retrieve a snapshot of all properties.
288 * - @c global_init() declaration -- must be defined by the subclass.
289 *
290 * Pair with @c VLINK_DEFINE_GLOBAL_PROPERTY(classname) in the @c .cc file.
291 */
292#define VLINK_DECLARE_GLOBAL_PROPERTY() \
293 private: \
294 static size_t thread_count_; \
295 static PropertiesMap global_properties_; \
296 static std::shared_mutex global_mtx_; \
297 \
298 public: \
299 [[nodiscard]] static size_t get_thread_count() { return thread_count_; } \
300 \
301 static void set_thread_count(size_t thread_count) { thread_count_ = thread_count; } \
302 \
303 static void set_global_property(const std::string& prop, const std::string& value) { \
304 std::lock_guard lock(global_mtx_); \
305 global_properties_[prop] = value; \
306 } \
307 \
308 [[nodiscard]] static std::string get_global_property(const std::string& prop) { \
309 std::shared_lock lock(global_mtx_); \
310 auto iter = global_properties_.find(prop); \
311 return iter != global_properties_.end() ? iter->second : std::string(); \
312 } \
313 \
314 [[nodiscard]] static PropertiesMap get_global_all_properties() { \
315 std::shared_lock lock(global_mtx_); \
316 return global_properties_; \
317 } \
318 \
319 static void global_init();
320
321/**
322 * @def VLINK_DEFINE_GLOBAL_PROPERTY
323 * @brief Provides definitions for the static members declared by @c VLINK_DECLARE_GLOBAL_PROPERTY.
324 *
325 * @details
326 * Place once in the @c .cc file of the corresponding @c Conf subclass.
327 * Initialises @c thread_count_ to @c 1, @c global_properties_ to an empty map,
328 * and default-constructs @c global_mtx_.
329 *
330 * @param classname The name of the concrete @c Conf subclass.
331 */
332#define VLINK_DEFINE_GLOBAL_PROPERTY(classname) \
333 size_t classname::thread_count_{1}; \
334 Conf::PropertiesMap classname::global_properties_; \
335 std::shared_mutex classname::global_mtx_;
Platform-independent macro definitions for the VLink library.
#define VLINK_EXPORT
Definition macros.h:85
Core type definitions shared across all VLink node implementations.