VLink 2.0.0
A high-performance communication middleware
载入中...
搜索中...
未找到
macros.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 macros.h
26 * @brief Platform-independent macro definitions for the VLink library.
27 *
28 * @details
29 * This header provides a unified set of macros used throughout VLink to handle
30 * platform differences, visibility control, branch prediction hints, and common
31 * class-level utilities such as singleton enforcement and copy-prevention.
32 *
33 * The macros are grouped as follows:
34 *
35 * | Group | Macros | Purpose |
36 * | ------------------ | ---------------------------------------------- | ---------------------------------- |
37 * | Symbol visibility | VLINK_EXPORT, VLINK_EXPORT_AND_ALIGNED | DLL export / visibility control |
38 * | Branch hints | VLINK_LIKELY, VLINK_UNLIKELY, VLIKELY, ... | Branch prediction optimization |
39 * | Copy prevention | VLINK_DISALLOW_COPY_AND_ASSIGN | Disable copy constructor/operator |
40 * | Singleton guard | VLINK_SINGLETON_CHECK, VLINK_SINGLETON_DECLARE | Enforce single-instance classes |
41 * | String utilities | VLINK_MACRO_STRING_IFY, VLINK_MACRO_STRING_GET | Stringify macro tokens |
42 * | Constant check | VLINK_ASSERT_CONSTANT | Static-assert constant string args |
43 *
44 * @note
45 * - All macros are designed to be no-ops when the relevant feature is unavailable
46 * (e.g., VLINK_LIKELY falls back to a plain cast on platforms without __builtin_expect).
47 * - The VLINK_EXPORT macro must be included before any class or function declaration
48 * that needs to be part of the public ABI.
49 * - VLINK_SINGLETON_CHECK enforces that a class can only ever be instantiated once
50 * per process via a static atomic flag; any second instantiation will throw
51 * std::runtime_error.
52 *
53 * @par Example
54 * @code
55 * // Marking a class as exported:
56 * class VLINK_EXPORT MyClass final { ... };
57 *
58 * // Preventing copy and assignment:
59 * class MyClass {
60 * VLINK_DISALLOW_COPY_AND_ASSIGN(MyClass)
61 * };
62 *
63 * // Branch prediction hint:
64 * if VLIKELY(ptr != nullptr) {
65 * ptr->do_something();
66 * }
67 * @endcode
68 */
69
70#pragma once
71
72// export
73#undef VLINK_EXPORT
74#ifdef VLINK_LIBRARY_STATIC
75#define VLINK_EXPORT
76#elif defined(_WIN32) || defined(__CYGWIN__)
77#ifdef VLINK_LIBRARY
78/// @cond INTERNAL
79#define VLINK_EXPORT __declspec(dllexport)
80#else
81#define VLINK_EXPORT __declspec(dllimport)
82/// @endcond
83#endif
84#else
85#define VLINK_EXPORT __attribute__((visibility("default")))
86#endif
87
88// align
89#undef VLINK_EXPORT_AND_ALIGNED
90#ifdef _MSC_VER
91#define VLINK_EXPORT_AND_ALIGNED(align_num) VLINK_EXPORT __declspec(align(align_num))
92#else
93/**
94 * @def VLINK_EXPORT_AND_ALIGNED(align_num)
95 * @brief Marks a class or variable as both exported and aligned to the given byte boundary.
96 *
97 * @details
98 * On MSVC this expands to @c __declspec(align(align_num));
99 * on GCC/Clang it expands to @c __attribute__((aligned(align_num))).
100 *
101 * @param align_num The required alignment in bytes (must be a power of two).
102 */
103#define VLINK_EXPORT_AND_ALIGNED(align_num) VLINK_EXPORT __attribute__((aligned(align_num)))
104#endif
105
106// win32
107#if defined(_WIN32) && !defined(WIN32_LEAN_AND_MEAN)
108#define WIN32_LEAN_AND_MEAN
109#endif
110
111// msvc
112#ifdef _MSC_VER
113#ifndef _CRT_SECURE_NO_WARNINGS
114#define _CRT_SECURE_NO_WARNINGS // NOLINT(bugprone-reserved-identifier, readability-identifier-naming)
115#endif
116#pragma warning(disable : 4065)
117#pragma warning(disable : 4251)
118#pragma warning(disable : 4244)
119#pragma warning(disable : 4267)
120#pragma warning(disable : 4324)
121#pragma warning(disable : 4702)
122#pragma warning(disable : 4819)
123#pragma warning(disable : 4840)
124#pragma warning(disable : 4996)
125#endif
126
127// __has_builtin
128#ifndef __has_builtin
129#define __has_builtin(x) 0
130#endif
131
132#ifdef __cplusplus
133#if __cplusplus >= 202002L
134/**
135 * @def VLINK_LIKELY(x)
136 * @brief Hints to the compiler that expression @p x is very likely to be true.
137 *
138 * @details
139 * Under C++20 this expands to the @c [[likely]] attribute; under earlier standards
140 * on GCC/Clang it uses @c __builtin_expect; on MSVC it is a no-op.
141 *
142 * @param x A boolean expression.
143 */
144#define VLINK_LIKELY(x) (x) [[likely]]
145/**
146 * @def VLINK_UNLIKELY(x)
147 * @brief Hints to the compiler that expression @p x is very unlikely to be true.
148 *
149 * @details
150 * Under C++20 this expands to the @c [[unlikely]] attribute; under earlier standards
151 * on GCC/Clang it uses @c __builtin_expect; on MSVC it is a no-op.
152 *
153 * @param x A boolean expression.
154 */
155#define VLINK_UNLIKELY(x) (x) [[unlikely]]
156#else
157#ifdef _WIN32
158#define VLINK_LIKELY(x) (x)
159#define VLINK_UNLIKELY(x) (x)
160#else
161#define VLINK_LIKELY(x) (__builtin_expect(!!(x), 1))
162#define VLINK_UNLIKELY(x) (__builtin_expect(!!(x), 0))
163#endif
164#endif
165#else
166#define VLINK_LIKELY(x) (x)
167#define VLINK_UNLIKELY(x) (x)
168#endif
169
170/**
171 * @def VLINK_DISALLOW_COPY_AND_ASSIGN(classname)
172 * @brief Deletes the copy constructor and copy-assignment operator of @p classname.
173 *
174 * @details
175 * Place this macro in the private section of a class to prevent accidental copying.
176 * It expands to:
177 * @code
178 * classname(const classname&) = delete;
179 * classname& operator=(const classname&) = delete;
180 * @endcode
181 *
182 * @param classname The unqualified name of the enclosing class.
183 */
184#define VLINK_DISALLOW_COPY_AND_ASSIGN(classname) \
185 classname(const classname&) = delete; \
186 classname& operator=(const classname&) = delete;
187
188/**
189 * @def VLINK_SINGLETON_CHECK(classname)
190 * @brief Injects a compile-time and run-time singleton enforcement guard.
191 *
192 * @details
193 * This macro:
194 * - Uses @c static_assert to verify that @p classname is @c final and has a
195 * private (non-default-constructible-from-outside) constructor.
196 * - Uses a @c std::atomic_flag to guarantee that the constructor is only invoked
197 * once per process. A second instantiation throws @c std::runtime_error.
198 *
199 * @note Must be placed in the @c private section of the class body.
200 *
201 * @param classname The unqualified name of the class being protected.
202 */
203#define VLINK_SINGLETON_CHECK(classname) \
204 private: \
205 struct ConstructorChecker { \
206 inline ConstructorChecker() { \
207 static_assert(std::is_final_v<classname>, "Constructor must be final."); \
208 static_assert(!std::is_default_constructible_v<classname>, "Constructor must be private."); \
209 \
210 static std::atomic_flag flag; \
211 \
212 if VLINK_UNLIKELY (flag.test_and_set()) { \
213 throw std::runtime_error("Constructor has been instantiated."); \
214 } \
215 } \
216 }; \
217 \
218 ConstructorChecker constructor_checker_;
219
220/**
221 * @def VLINK_SINGLETON_DECLARE(classname)
222 * @brief Declares a complete Meyer's-singleton @c get() method with safety guards.
223 *
224 * @details
225 * Combines VLINK_SINGLETON_CHECK with a public static @c get() accessor that
226 * returns a reference to the single static instance. The constructor must be
227 * @c private and @c final, otherwise the embedded @c static_assert will fail.
228 *
229 * @param classname The unqualified name of the singleton class.
230 *
231 * @par Example
232 * @code
233 * class MyService final {
234 * VLINK_SINGLETON_DECLARE(MyService)
235 * public:
236 * void do_work();
237 * private:
238 * MyService() = default;
239 * };
240 *
241 * MyService::get().do_work();
242 * @endcode
243 */
244#define VLINK_SINGLETON_DECLARE(classname) \
245 public: \
246 inline static classname& get() { \
247 static classname singleton = classname(); \
248 return singleton; \
249 } \
250 \
251 private: \
252 VLINK_SINGLETON_CHECK(classname) \
253 VLINK_DISALLOW_COPY_AND_ASSIGN(classname)
254
255/**
256 * @def VLINK_MACRO_STRING_IFY(name)
257 * @brief Converts @p name to a C string literal using the preprocessor stringification operator.
258 *
259 * @param name A macro token (not a string literal) to stringify.
260 */
261#define VLINK_MACRO_STRING_IFY(name) #name
262
263/**
264 * @def VLINK_MACRO_STRING_GET(name)
265 * @brief Stringifies the expanded value of macro @p name (two-level expansion).
266 *
267 * @details
268 * This two-step macro ensures that @p name is fully expanded before
269 * stringification. Use this instead of VLINK_MACRO_STRING_IFY when @p name
270 * is itself a macro that should be expanded first.
271 *
272 * @param name A macro whose expansion will be converted to a string literal.
273 */
274#define VLINK_MACRO_STRING_GET(name) VLINK_MACRO_STRING_IFY(name)
275
276#if __has_builtin(__builtin_constant_p)
277/**
278 * @def VLINK_ASSERT_CONSTANT(msg)
279 * @brief Asserts (at compile time) that @p msg is a constant string literal.
280 *
281 * @details
282 * On compilers that support @c __builtin_constant_p this expands to a
283 * @c static_assert; on others it is a no-op.
284 *
285 * @param msg The expression to check for compile-time constancy.
286 */
287#define VLINK_ASSERT_CONSTANT(msg) static_assert(__builtin_constant_p(msg), "Must be a constant string literal.");
288#else
289#define VLINK_ASSERT_CONSTANT(msg)
290#endif
291
292#if !defined(VLIKELY) && !defined(VUNLIKELY)
293/**
294 * @def VLIKELY(...)
295 * @brief Shorthand alias for VLINK_LIKELY. Hints that the expression is likely true.
296 */
297#define VLIKELY(...) VLINK_LIKELY(__VA_ARGS__)
298/**
299 * @def VUNLIKELY(...)
300 * @brief Shorthand alias for VLINK_UNLIKELY. Hints that the expression is unlikely true.
301 */
302#define VUNLIKELY(...) VLINK_UNLIKELY(__VA_ARGS__)
303#endif