VLink  2.0.0
A high-performance communication middleware
sys_semaphore.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 sys_semaphore.h
26  * @brief Cross-process named semaphore backed by the host kernel.
27  *
28  * @details
29  * @c vlink::SysSemaphore wraps the platform IPC primitive that is closest to a counting
30  * semaphore: a POSIX named semaphore on Linux-like targets, a named Win32 semaphore on
31  * Windows, and a dispatch semaphore on macOS. Cross-process synchronisation works on
32  * every backend that exposes a kernel name; the macOS dispatch backend is process-local
33  * because Apple deprecated the named POSIX API.
34  *
35  * Comparison with the in-process @c vlink::Semaphore:
36  *
37  * | Aspect | @c Semaphore (in-process) | @c SysSemaphore (kernel) |
38  * | ---------------------- | --------------------------- | ------------------------------------------- |
39  * | Scope | Single process | Cross-process via OS name |
40  * | Backing primitive | @c std::condition_variable | @c sem_open / @c CreateSemaphore |
41  * | Naming | None (object handle only) | UTF-8 name (POSIX requires @c "/x") |
42  * | Signal-safe @c release | No | Yes on POSIX |
43  * | Persistence | Bound to process lifetime | Persists in kernel namespace until unlinked |
44  *
45  * Lifecycle:
46  * -# Construct with the initial count for the @b creator process.
47  * -# Call @c attach(name) to create the kernel object or open an existing one.
48  * -# Use @c acquire and @c release for P/V.
49  * -# Call @c detach(force) explicitly, or rely on the destructor (force=@c false).
50  *
51  * @note
52  * - The initial count is honoured only on first creation. Subsequent @c attach() calls
53  * on a pre-existing kernel object inherit its current value.
54  * - macOS ignores @p name and produces an in-process dispatch semaphore.
55  *
56  * @par Example
57  * @code
58  * // Process A (server)
59  * vlink::SysSemaphore sem(0);
60  * sem.attach("/vlink_ready");
61  * do_init();
62  * sem.release();
63  *
64  * // Process B (client)
65  * vlink::SysSemaphore sem;
66  * sem.attach("/vlink_ready");
67  * sem.acquire();
68  * @endcode
69  */
70 
71 #pragma once
72 
73 #include <memory>
74 #include <string>
75 
76 #include "./macros.h"
77 
78 namespace vlink {
79 
80 /**
81  * @class SysSemaphore
82  * @brief Counting semaphore that can be shared across processes through an OS name.
83  *
84  * @details
85  * Resolves to a POSIX named semaphore, a Win32 named semaphore or a macOS dispatch
86  * semaphore depending on the host platform.
87  */
89  public:
90  /**
91  * @brief Sentinel value for @c acquire() meaning wait indefinitely.
92  */
93  static constexpr int kInfinite{-1};
94 
95  /**
96  * @brief Constructs the wrapper with the initial count used when @c attach() creates the kernel object.
97  *
98  * @param count Initial permit count for first creation. Default: @c 0.
99  */
100  explicit SysSemaphore(size_t count = 0);
101 
102  /**
103  * @brief Destructor. Invokes @c detach(false) when the wrapper is still attached.
104  */
106 
107  /**
108  * @brief Creates or opens the kernel object identified by @p name.
109  *
110  * @details
111  * When the kernel object already exists the constructor-supplied initial count is
112  * ignored. POSIX backends require @p name to begin with @c '/'. macOS ignores @p name
113  * and produces a fresh in-process dispatch semaphore.
114  *
115  * @param name Platform-specific semaphore name.
116  * @return @c true on success, @c false otherwise.
117  */
118  bool attach(const std::string& name);
119 
120  /**
121  * @brief Releases the kernel handle and optionally unlinks the named object.
122  *
123  * @param force When @c true, POSIX backends unlink the name so it disappears from the
124  * kernel namespace. Ignored on Windows and macOS. Default: @c true.
125  * @return @c true on success.
126  */
127  bool detach(bool force = true);
128 
129  /**
130  * @brief Decrements the kernel counter by @p n, blocking when permits are unavailable.
131  *
132  * @param n Number of permits requested. Default: @c 1.
133  * @param timeout_ms Maximum wait in milliseconds; @c kInfinite waits forever.
134  * @return @c true when the permits were acquired; @c false on timeout or error.
135  *
136  * @pre @c is_attached() must be @c true.
137  */
138  bool acquire(size_t n = 1, int timeout_ms = kInfinite);
139 
140  /**
141  * @brief Increments the kernel counter by @p n, waking blocked acquirers.
142  *
143  * @param n Number of permits to add. Default: @c 1.
144  *
145  * @pre @c is_attached() must be @c true.
146  */
147  void release(size_t n = 1);
148 
149  /**
150  * @brief Reports whether the wrapper currently owns a kernel handle.
151  *
152  * @return @c true when @c attach() succeeded and @c detach() has not been called yet.
153  */
154  [[nodiscard]] bool is_attached() const;
155 
156  /**
157  * @brief Returns a non-atomic snapshot of the current counter value.
158  *
159  * @details
160  * Some backends (notably macOS dispatch) do not expose the counter; @c 0 is returned
161  * in that case.
162  *
163  * @return Current permit count snapshot.
164  */
165  [[nodiscard]] size_t get_count() const;
166 
167  private:
168  struct Impl;
169  std::unique_ptr<Impl> impl_;
170 
172 };
173 
174 } // namespace vlink
Cross-platform macros for visibility, branch hints, copy prevention, singletons and string helpers.
#define VLINK_EXPORT
Definition: macros.h:81
#define VLINK_DISALLOW_COPY_AND_ASSIGN(classname)
Deletes the copy constructor and copy-assignment operator of classname.
Definition: macros.h:174