VLink  2.0.0
A high-performance communication middleware
conf.h
浏览该文件的文档.
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 Transport-configuration base contract and the supporting boilerplate macros.
27  *
28  * @details
29  * This is an internal implementation header used by the public node templates and
30  * by every transport-specific @c *Conf class; user code should never include it
31  * directly. The @c Conf base struct is the bridge between the URL parsing layer
32  * and the concrete factories that produce @c NodeImpl instances. A typical node
33  * construction follows the chain
34  * @c Url -> concrete @c Conf -> @c Conf::create_xxx() -> @c NodeImpl subclass.
35  *
36  * @par Inheritance hierarchy
37  * @code
38  * +--------+
39  * | Conf |
40  * +---+----+
41  * |
42  * +---------+--------+--------+---------+----------+--------------+-----------+
43  * | | | | | | | |
44  * IntraConf ShmConf Shm2Conf ZenohConf DdsConf DdscConf MqttConf ...etc
45  * (DdsrConf, DdstConf, SomeipConf,
46  * FdbusConf, QnxConf, plugin Conf)
47  * @endcode
48  *
49  * @par Virtual interface contract
50  * | Method | Default behaviour | Subclass responsibility |
51  * | ---------------------------- | --------------------------------------------- | ---------------------------------- |
52  * | @c parse(impl_type) | Caches @p impl_type; rejects @c kUnknown. | Validate transport-specific data. |
53  * | @c is_valid() | Returns @c false. | Report readiness for factories. |
54  * | @c get_impl_type() | Returns the cached value from @c parse(). | Usually inherited unchanged. |
55  * | @c get_transport_type() | Returns @c TransportType::kUnknown. | Return the backend identifier. |
56  * | @c parse_protocol(protocol) | Returns @c false. | Pull URL fields into the conf. |
57  * | @c create_publisher() / etc. | Returns @c nullptr. | Allocate the matching @c NodeImpl. |
58  *
59  * @par Macro reference
60  * | Macro | Purpose |
61  * | -------------------------------- | -------------------------------------------------------------------- |
62  * | @c VLINK_DECLARE_CONF_FRIEND | Grants friend access to all six public Node<> templates. |
63  * | @c VLINK_CONF_IMPL(classname) | Bundles friend grant + standard override declarations + ostream op. |
64  * | @c VLINK_ALLOW_IMPL_TYPE(type) | Records which @c ImplType bits a conf may serve, for compile checks. |
65  * | @c VLINK_DECLARE_GLOBAL_PROPERTY | Declares static thread-count and global-property storage in a conf. |
66  * | @c VLINK_DEFINE_GLOBAL_PROPERTY | Provides the storage definitions for the declaration above. |
67  *
68  * @par Example
69  * @code
70  * // include/myapp/my_conf.h
71  * struct MyConf final : public vlink::Conf {
72  * VLINK_CONF_IMPL(MyConf)
73  * VLINK_ALLOW_IMPL_TYPE(vlink::kPublisher | vlink::kSubscriber)
74  * VLINK_DECLARE_GLOBAL_PROPERTY()
75  *
76  * std::string host;
77  * uint16_t port{0};
78  * };
79  *
80  * // src/myapp/my_conf.cc
81  * VLINK_DEFINE_GLOBAL_PROPERTY(MyConf)
82  *
83  * void MyConf::global_init() { setup_shared_transport_state(); }
84  * bool MyConf::is_valid() const { return !host.empty() && port != 0; }
85  * @endcode
86  */
87 
88 #pragma once
89 
90 #include <map>
91 #include <memory>
92 #include <shared_mutex>
93 #include <string>
94 #include <utility>
95 
96 #include "../base/macros.h"
97 #include "./types.h"
98 
99 namespace vlink {
100 
101 /**
102  * @struct Conf
103  * @brief Abstract base for every transport-specific configuration aggregate.
104  *
105  * @details
106  * Holds the cached @c ImplType selected by @c parse() and declares the protected
107  * factory hooks that the public node templates use to instantiate @c NodeImpl
108  * peers. Default implementations of the factory hooks return @c nullptr so
109  * subclasses only need to override the roles they actually support; combine
110  * with @c VLINK_ALLOW_IMPL_TYPE to make the compile-time guard explicit.
111  *
112  * @note Instances are never owned by application code; they are produced by
113  * @c Url and live as long as the node that references them.
114  */
116  /**
117  * @brief Key/value property map shared between confs and node implementations.
118  *
119  * @details
120  * Stores transport tuning entries (e.g. @c "dds.ip" = @c "127.0.0.1") that
121  * are read by backends during @c init() and by helpers such as @c SslOptions.
122  */
123  using PropertiesMap = std::map<std::string, std::string>;
124 
125  /**
126  * @brief Virtual destructor.
127  */
128  virtual ~Conf();
129 
130  /**
131  * @brief Validates the conf for @p impl_type and caches it for subsequent factories.
132  *
133  * @details
134  * The base implementation rejects @c kUnknownImplType (the underlying logger
135  * call is configured to abort the process) and stores any other value into
136  * @c impl_type_ so that follow-up @c create_*() calls know the requested role.
137  * Subclasses typically chain @c Conf::parse() and then run their own checks.
138  *
139  * @param impl_type Role the caller intends to instantiate.
140  * @return @c true on success; the unknown-type fatal path never returns.
141  */
142  [[nodiscard]] virtual bool parse(ImplType impl_type) const;
143 
144  /**
145  * @brief Indicates whether the conf currently holds usable data.
146  *
147  * @details
148  * The base implementation returns @c false; concrete confs override it to
149  * verify that mandatory fields have been populated.
150  *
151  * @return @c true once the conf is ready to drive @c create_*() factories.
152  */
153  [[nodiscard]] virtual bool is_valid() const;
154 
155  /**
156  * @brief Returns the @c ImplType cached by the most recent @c parse() call.
157  *
158  * @return Cached @c ImplType, or @c kUnknownImplType before @c parse() runs.
159  */
160  [[nodiscard]] virtual ImplType get_impl_type() const;
161 
162  /**
163  * @brief Returns the transport backend this conf wraps.
164  *
165  * @details
166  * Default implementation returns @c TransportType::kUnknown; concrete confs
167  * (and dynamic plugins) override it to advertise their backend.
168  *
169  * @return Matching @c TransportType identifier.
170  */
171  [[nodiscard]] virtual TransportType get_transport_type() const;
172 
173  uint32_t hash_code{0}; ///< Channel / topic hash assigned by concrete backends.
174 
175  protected:
176  Conf();
177 
178  [[nodiscard]] virtual bool parse_protocol(struct Protocol* protocol);
179 
180  [[nodiscard]] virtual std::unique_ptr<class ServerImpl> create_server() const;
181 
182  [[nodiscard]] virtual std::unique_ptr<class ClientImpl> create_client() const;
183 
184  [[nodiscard]] virtual std::unique_ptr<class PublisherImpl> create_publisher() const;
185 
186  [[nodiscard]] virtual std::unique_ptr<class SubscriberImpl> create_subscriber() const;
187 
188  [[nodiscard]] virtual std::unique_ptr<class SetterImpl> create_setter() const;
189 
190  [[nodiscard]] virtual std::unique_ptr<class GetterImpl> create_getter() const;
191 
192  private:
193  friend struct Url;
194  template <typename, typename, SecurityType>
195  friend class Server;
196  template <typename, typename, SecurityType>
197  friend class Client;
198  template <typename, SecurityType>
199  friend class Publisher;
200  template <typename, SecurityType>
201  friend class Subscriber;
202  template <typename, SecurityType>
203  friend class Setter;
204  template <typename, SecurityType>
205  friend class Getter;
206 
207  mutable ImplType impl_type_{kUnknownImplType};
208 };
209 
210 } // namespace vlink
211 
212 ////////////////////////////////////////////////////////////////
213 /// Macro Definitions
214 ////////////////////////////////////////////////////////////////
215 
216 /**
217  * @def VLINK_DECLARE_CONF_FRIEND
218  * @brief Grants the six public Node<> templates friend access to the conf.
219  *
220  * @details
221  * Inject this macro into a concrete @c Conf subclass to expose the protected
222  * factory methods to @c Server, @c Client, @c Publisher, @c Subscriber,
223  * @c Setter and @c Getter. @c VLINK_CONF_IMPL already expands it; use this
224  * macro on its own only when @c VLINK_CONF_IMPL is not suitable.
225  */
226 #define VLINK_DECLARE_CONF_FRIEND() \
227  template <typename, typename, SecurityType> \
228  friend class Server; \
229  template <typename, typename, SecurityType> \
230  friend class Client; \
231  template <typename, SecurityType> \
232  friend class Publisher; \
233  template <typename, SecurityType> \
234  friend class Subscriber; \
235  template <typename, SecurityType> \
236  friend class Setter; \
237  template <typename, SecurityType> \
238  friend class Getter;
239 
240 /**
241  * @def VLINK_CONF_IMPL
242  * @brief Convenience macro that emits the standard concrete conf boilerplate.
243  *
244  * @details
245  * Expands to the friend grant, the six factory overrides, an ostream insertion
246  * operator declaration, the default constructor / destructor and an
247  * @c is_valid() override declaration whose body the subclass must provide.
248  *
249  * @param classname Subclass name being declared.
250  */
251 #define VLINK_CONF_IMPL(classname) \
252  private: \
253  VLINK_DECLARE_CONF_FRIEND() \
254  \
255  [[nodiscard]] bool parse_protocol(struct Protocol* protocol) override; \
256  \
257  [[nodiscard]] std::unique_ptr<class ServerImpl> create_server() const override; \
258  \
259  [[nodiscard]] std::unique_ptr<class ClientImpl> create_client() const override; \
260  \
261  [[nodiscard]] std::unique_ptr<class PublisherImpl> create_publisher() const override; \
262  \
263  [[nodiscard]] std::unique_ptr<class SubscriberImpl> create_subscriber() const override; \
264  \
265  [[nodiscard]] std::unique_ptr<class SetterImpl> create_setter() const override; \
266  \
267  [[nodiscard]] std::unique_ptr<class GetterImpl> create_getter() const override; \
268  \
269  VLINK_EXPORT friend std::ostream& operator<<(std::ostream& ostream, const classname& conf) noexcept; \
270  \
271  public: \
272  classname() = default; \
273  \
274  ~classname() = default; \
275  \
276  [[nodiscard]] bool is_valid() const override;
277 
278 /**
279  * @def VLINK_ALLOW_IMPL_TYPE
280  * @brief Records the bitmask of @c ImplType values supported by a conf.
281  *
282  * @details
283  * Expands to a public @c get_allow_impl_type() that returns @p type so the
284  * @c Node<> template can validate at compile time that the conf supports the
285  * requested node role. Combine roles with bitwise OR, e.g.
286  * @code
287  * VLINK_ALLOW_IMPL_TYPE(kServer | kClient | kPublisher | kSubscriber | kSetter | kGetter)
288  * @endcode
289  *
290  * @param type Bitmask of @c ImplType values supported by the conf.
291  */
292 #define VLINK_ALLOW_IMPL_TYPE(type) \
293  public: \
294  [[nodiscard]] static constexpr int get_allow_impl_type() { return type; }
295 
296 /**
297  * @def VLINK_DECLARE_GLOBAL_PROPERTY
298  * @brief Declares per-transport static configuration storage and access helpers.
299  *
300  * @details
301  * Inject into a concrete @c Conf subclass body to expose:
302  * - @c thread_count_, @c global_properties_ and @c global_mtx_ static members.
303  * - @c get_thread_count() / @c set_thread_count() accessors.
304  * - @c set_global_property() / @c get_global_property() / @c get_global_all_properties().
305  * - A @c global_init() declaration whose definition the subclass supplies.
306  *
307  * Pair with @c VLINK_DEFINE_GLOBAL_PROPERTY in the matching translation unit.
308  */
309 #define VLINK_DECLARE_GLOBAL_PROPERTY() \
310  private: \
311  static size_t thread_count_; \
312  static PropertiesMap global_properties_; \
313  static std::shared_mutex global_mtx_; \
314  \
315  public: \
316  [[nodiscard]] static size_t get_thread_count() { return thread_count_; } \
317  \
318  static void set_thread_count(size_t thread_count) { thread_count_ = thread_count; } \
319  \
320  static void set_global_property(const std::string& prop, const std::string& value) { \
321  std::lock_guard lock(global_mtx_); \
322  global_properties_[prop] = value; \
323  } \
324  \
325  [[nodiscard]] static std::string get_global_property(const std::string& prop) { \
326  std::shared_lock lock(global_mtx_); \
327  auto iter = global_properties_.find(prop); \
328  return iter != global_properties_.end() ? iter->second : std::string(); \
329  } \
330  \
331  [[nodiscard]] static PropertiesMap get_global_all_properties() { \
332  std::shared_lock lock(global_mtx_); \
333  return global_properties_; \
334  } \
335  \
336  static void global_init();
337 
338 /**
339  * @def VLINK_DEFINE_GLOBAL_PROPERTY
340  * @brief Provides storage for the statics declared by @c VLINK_DECLARE_GLOBAL_PROPERTY.
341  *
342  * @details
343  * Place once in the @c .cc file of the matching subclass. Sets
344  * @c thread_count_ to @c 1, default-constructs the property map, and
345  * default-initialises the shared mutex.
346  *
347  * @param classname Subclass that owns the static members.
348  */
349 #define VLINK_DEFINE_GLOBAL_PROPERTY(classname) \
350  size_t classname::thread_count_{1}; \
351  Conf::PropertiesMap classname::global_properties_; \
352  std::shared_mutex classname::global_mtx_;
#define VLINK_EXPORT
Definition: macros.h:81
Core enumerations and small value types shared by the entire VLink implementation layer.