Branch data Line data Source code
1 : : // Copyright (c) The Bitcoin Core developers
2 : : // Distributed under the MIT software license, see the accompanying
3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 : :
5 : : #ifndef MP_UTIL_H
6 : : #define MP_UTIL_H
7 : :
8 : : #include <capnp/schema.h>
9 : : #include <cassert>
10 : : #include <cstddef>
11 : : #include <cstring>
12 : : #include <exception>
13 : : #include <functional>
14 : : #include <kj/string-tree.h>
15 : : #include <mutex>
16 : : #include <string>
17 : : #include <tuple>
18 : : #include <type_traits>
19 : : #include <utility>
20 : : #include <variant>
21 : : #include <vector>
22 : :
23 : : namespace mp {
24 : :
25 : : //! Generic utility functions used by capnp code.
26 : :
27 : : //! Type holding a list of types.
28 : : //!
29 : : //! Example:
30 : : //! TypeList<int, bool, void>
31 : : template <typename... Types>
32 : : struct TypeList
33 : : {
34 : : static constexpr size_t size = sizeof...(Types);
35 : : };
36 : :
37 : : //! Construct a template class value by deducing template arguments from the
38 : : //! types of constructor arguments, so they don't need to be specified manually.
39 : : //!
40 : : //! Uses of this can go away with class template deduction in C++17
41 : : //! (https://en.cppreference.com/w/cpp/language/class_template_argument_deduction)
42 : : //!
43 : : //! Example:
44 : : //! Make<std::pair>(5, true) // Constructs std::pair<int, bool>(5, true);
45 : : template <template <typename...> class Class, typename... Types, typename... Args>
46 : 185 : Class<Types..., std::remove_reference_t<Args>...> Make(Args&&... args)
47 : : {
48 : 185 : return Class<Types..., std::remove_reference_t<Args>...>{std::forward<Args>(args)...};
49 : : }
50 : :
51 : : //! Type helper splitting a TypeList into two halves at position index.
52 : : //!
53 : : //! Example:
54 : : //! is_same<TypeList<int, double>, Split<2, TypeList<int, double, float, bool>>::First>
55 : : //! is_same<TypeList<float, bool>, Split<2, TypeList<int, double, float, bool>>::Second>
56 : : template <std::size_t index, typename List, typename _First = TypeList<>, bool done = index == 0>
57 : : struct Split;
58 : :
59 : : //! Specialization of above (base case)
60 : : template <typename _Second, typename _First>
61 : : struct Split<0, _Second, _First, true>
62 : : {
63 : : using First = _First;
64 : : using Second = _Second;
65 : : };
66 : :
67 : : //! Specialization of above (recursive case)
68 : : template <std::size_t index, typename Type, typename... _Second, typename... _First>
69 : : struct Split<index, TypeList<Type, _Second...>, TypeList<_First...>, false>
70 : : {
71 : : using _Next = Split<index - 1, TypeList<_Second...>, TypeList<_First..., Type>>;
72 : : using First = typename _Next::First;
73 : : using Second = typename _Next::Second;
74 : : };
75 : :
76 : : //! Type helper giving return type of a callable type.
77 : : template <typename Callable>
78 : : using ResultOf = decltype(std::declval<Callable>()());
79 : :
80 : : //! Substitutue for std::remove_cvref_t
81 : : template <typename T>
82 : : using RemoveCvRef = std::remove_cv_t<std::remove_reference_t<T>>;
83 : :
84 : : //! Type helper abbreviating std::decay.
85 : : template <typename T>
86 : : using Decay = std::decay_t<T>;
87 : :
88 : : //! SFINAE helper, see using Require below.
89 : : template <typename SfinaeExpr, typename Result_>
90 : : struct _Require
91 : : {
92 : : using Result = Result_;
93 : : };
94 : :
95 : : //! SFINAE helper, basically the same as to C++17's void_t, but allowing types other than void to be returned.
96 : : template <typename SfinaeExpr, typename Result = void>
97 : : using Require = typename _Require<SfinaeExpr, Result>::Result;
98 : :
99 : : //! Function parameter type for prioritizing overloaded function calls that
100 : : //! would otherwise be ambiguous.
101 : : //!
102 : : //! Example:
103 : : //! auto foo(Priority<1>) -> std::enable_if<>;
104 : : //! auto foo(Priority<0>) -> void;
105 : : //!
106 : : //! foo(Priority<1>()); // Calls higher priority overload if enabled.
107 : : template <int priority>
108 : : struct Priority : Priority<priority - 1>
109 : : {
110 : : };
111 : :
112 : : //! Specialization of above (base case)
113 : : template <>
114 : : struct Priority<0>
115 : : {
116 : : };
117 : :
118 : : //! Return capnp type name with filename prefix removed.
119 : : template <typename T>
120 : 120 : const char* TypeName()
121 : : {
122 : : // DisplayName string looks like
123 : : // "interfaces/capnp/common.capnp:ChainNotifications.resendWalletTransactions$Results"
124 : : // This discards the part of the string before the first ':' character.
125 : : // Another alternative would be to use the displayNamePrefixLength field,
126 : : // but this discards everything before the last '.' character, throwing away
127 : : // the object name, which is useful.
128 [ + - ]: 120 : const char* display_name = ::capnp::Schema::from<T>().getProto().getDisplayName().cStr();
129 : 120 : const char* short_name = strchr(display_name, ':');
130 [ + - ]: 120 : return short_name ? short_name + 1 : display_name;
131 : : }
132 : :
133 : : //! Convenient wrapper around std::variant<T*, T>
134 : : template <typename T>
135 : 426 : struct PtrOrValue {
136 : : std::variant<T*, T> data;
137 : :
138 : : template <typename... Args>
139 [ + + + + ]: 426 : PtrOrValue(T* ptr, Args&&... args) : data(ptr ? ptr : std::variant<T*, T>{std::in_place_type<T>, std::forward<Args>(args)...}) {}
140 : :
141 [ + + - + ]: 431 : T& operator*() { return data.index() ? std::get<T>(data) : *std::get<T*>(data); }
142 [ + - + - : 431 : T* operator->() { return &**this; }
+ - + - ]
143 : : T& operator*() const { return data.index() ? std::get<T>(data) : *std::get<T*>(data); }
144 : : T* operator->() const { return &**this; }
145 : : };
146 : :
147 : : // Annotated mutex and lock class (https://clang.llvm.org/docs/ThreadSafetyAnalysis.html)
148 : : #if defined(__clang__) && (!defined(SWIG))
149 : : #define MP_TSA(x) __attribute__((x))
150 : : #else
151 : : #define MP_TSA(x) // no-op
152 : : #endif
153 : :
154 : : #define MP_CAPABILITY(x) MP_TSA(capability(x))
155 : : #define MP_SCOPED_CAPABILITY MP_TSA(scoped_lockable)
156 : : #define MP_REQUIRES(x) MP_TSA(requires_capability(x))
157 : : #define MP_ACQUIRE(...) MP_TSA(acquire_capability(__VA_ARGS__))
158 : : #define MP_RELEASE(...) MP_TSA(release_capability(__VA_ARGS__))
159 : : #define MP_ASSERT_CAPABILITY(x) MP_TSA(assert_capability(x))
160 : : #define MP_GUARDED_BY(x) MP_TSA(guarded_by(x))
161 : : #define MP_NO_TSA MP_TSA(no_thread_safety_analysis)
162 : :
163 : 10 : class MP_CAPABILITY("mutex") Mutex {
164 : : public:
165 : : void lock() MP_ACQUIRE() { m_mutex.lock(); }
166 : : void unlock() MP_RELEASE() { m_mutex.unlock(); }
167 : :
168 : : std::mutex m_mutex;
169 : : };
170 : :
171 : : class MP_SCOPED_CAPABILITY Lock {
172 : : public:
173 [ + - + - : 774 : explicit Lock(Mutex& m) MP_ACQUIRE(m) : m_lock(m.m_mutex) {}
+ - + - +
- + - + -
+ - + - +
- + - + -
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ][ # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ][ + -
+ - + - +
- # # # #
# # # # ]
[ - - - -
- - - - +
- + - + -
+ - # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
[ # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
[ + - + -
- - + - +
- + - - +
+ - + + +
- + - - +
+ - + - +
- ][ # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ][ # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ][ #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
174 [ + - - - : 1453 : ~Lock() MP_RELEASE() = default;
- - + - -
- + - - -
- - + - -
- + - - -
- - + - -
- + - - -
- - + - -
- + - - -
- - + - -
- + - - -
- - + - -
- # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ][ # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ][ + -
- - - - +
- - - + -
- - - - +
- - - # #
# # ][ + -
- - + - -
- + - + -
- + - - +
- + - - +
- - # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ][ -
- - - - -
- - - - -
- - - - -
- - - - +
- - - - -
+ - - - +
- - - - -
+ - - - #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
[ # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ][ + + +
- - - + -
+ - - - -
- + - + +
- - + - +
- - - + -
- - + - +
- + - + -
+ - + - +
- - - - -
+ - - - +
- + - - -
+ - - - ]
[ # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ][ #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
[ # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
175 [ + - ]: 144 : void unlock() MP_RELEASE() { m_lock.unlock(); }
176 [ + - ]: 143 : void lock() MP_ACQUIRE() { m_lock.lock(); }
177 : 426 : void assert_locked(Mutex& mutex) MP_ASSERT_CAPABILITY() MP_ASSERT_CAPABILITY(mutex)
178 : : {
179 [ - + ]: 426 : assert(m_lock.mutex() == &mutex.m_mutex);
180 [ - + ]: 426 : assert(m_lock);
181 : 426 : }
182 : :
183 : : std::unique_lock<std::mutex> m_lock;
184 : : };
185 : :
186 : : template<typename T>
187 : : struct GuardedRef
188 : : {
189 : : Mutex& mutex;
190 : : T& ref MP_GUARDED_BY(mutex);
191 : : };
192 : :
193 : : // CTAD for Clang 16: GuardedRef{mutex, x} -> GuardedRef<decltype(x)>
194 : : template <class U>
195 : : GuardedRef(Mutex&, U&) -> GuardedRef<U>;
196 : :
197 : : //! Analog to std::lock_guard that unlocks instead of locks.
198 : : template <typename Lock>
199 : : struct UnlockGuard
200 : : {
201 : 566 : UnlockGuard(Lock& lock) : m_lock(lock) { m_lock.unlock(); }
202 : 142 : ~UnlockGuard() { m_lock.lock(); }
203 : : Lock& m_lock;
204 : : };
205 : :
206 : : template <typename Lock, typename Callback>
207 : 283 : void Unlock(Lock& lock, Callback&& callback)
208 : : {
209 [ + - ]: 283 : const UnlockGuard<Lock> unlock(lock);
210 [ + - ]: 283 : callback();
211 : 283 : }
212 : :
213 : : //! Invoke a function and run a follow-up action before returning the original
214 : : //! result.
215 : : //!
216 : : //! This can be used similarly to KJ_DEFER to run cleanup code, but works better
217 : : //! if the cleanup function can throw because it avoids clang bug
218 : : //! https://github.com/llvm/llvm-project/issues/12658 which skips calling
219 : : //! destructors in that case and can lead to memory leaks. Also, if both
220 : : //! functions throw, this lets one exception take precedence instead of
221 : : //! terminating due to having two active exceptions.
222 : : template <typename Fn, typename After>
223 : 24 : decltype(auto) TryFinally(Fn&& fn, After&& after)
224 : : {
225 [ + - ]: 24 : bool success{false};
226 : : using R = std::invoke_result_t<Fn>;
227 : : try {
228 : : if constexpr (std::is_void_v<R>) {
229 [ # # ]: 6 : std::forward<Fn>(fn)();
230 : 6 : success = true;
231 [ + - ]: 6 : std::forward<After>(after)();
232 : 6 : return;
233 : : } else {
234 [ + - ]: 18 : decltype(auto) result = std::forward<Fn>(fn)();
235 : 18 : success = true;
236 [ + - ]: 18 : std::forward<After>(after)();
237 : 18 : return result;
238 : 0 : }
239 : 0 : } catch (...) {
240 [ - - - - ]: 0 : if (!success) std::forward<After>(after)();
241 : 0 : throw;
242 : : }
243 : : }
244 : :
245 : : //! Format current thread name as "{exe_name}-{$pid}/{thread_name}-{$tid}".
246 : : std::string ThreadName(const char* exe_name);
247 : :
248 : : //! Escape binary string for use in log so it doesn't trigger unicode decode
249 : : //! errors in python unit tests.
250 : : std::string LogEscape(const kj::StringTree& string, size_t max_size);
251 : :
252 : : //! Callback type used by SpawnProcess below.
253 : : using FdToArgsFn = std::function<std::vector<std::string>(int fd)>;
254 : :
255 : : //! Spawn a new process that communicates with the current process over a socket
256 : : //! pair. Returns pid through an output argument, and file descriptor for the
257 : : //! local side of the socket.
258 : : //! The fd_to_args callback is invoked in the parent process before fork().
259 : : //! It must not rely on child pid/state, and must return the command line
260 : : //! arguments that should be used to execute the process. Embed the remote file
261 : : //! descriptor number in whatever format the child process expects.
262 : : int SpawnProcess(int& pid, FdToArgsFn&& fd_to_args);
263 : :
264 : : //! Call execvp with vector args.
265 : : //! Not safe to call in a post-fork child of a multi-threaded process.
266 : : //! Currently only used by mpgen at build time.
267 : : void ExecProcess(const std::vector<std::string>& args);
268 : :
269 : : //! Wait for a process to exit and return its exit code.
270 : : int WaitProcess(int pid);
271 : :
272 : : inline char* CharCast(char* c) { return c; }
273 : : inline char* CharCast(unsigned char* c) { return (char*)c; }
274 : : inline const char* CharCast(const char* c) { return c; }
275 : : inline const char* CharCast(const unsigned char* c) { return (const char*)c; }
276 : :
277 : : //! Exception thrown from code executing an IPC call that is interrupted.
278 : : struct InterruptException final : std::exception {
279 : 0 : explicit InterruptException(std::string message) : m_message(std::move(message)) {}
280 [ # # # # : 0 : const char* what() const noexcept override { return m_message.c_str(); }
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
[ # # # # ]
[ # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
281 : : std::string m_message;
282 : : };
283 : :
284 : : class CancelProbe;
285 : :
286 : : //! Helper class that detects when a promise is canceled. Used to detect
287 : : //! canceled requests and prevent potential crashes on unclean disconnects.
288 : : //!
289 : : //! In the future, this could also be used to support a way for wrapped C++
290 : : //! methods to detect cancellation (like approach #4 in
291 : : //! https://github.com/bitcoin/bitcoin/issues/33575).
292 : 18 : class CancelMonitor
293 : : {
294 : : public:
295 : : inline ~CancelMonitor();
296 : : inline void promiseDestroyed(CancelProbe& probe);
297 : :
298 : : bool m_canceled{false};
299 : : std::function<void()> m_on_cancel;
300 : : CancelProbe* m_probe{nullptr};
301 : : };
302 : :
303 : : //! Helper object to attach to a promise and update a CancelMonitor.
304 : : class CancelProbe
305 : : {
306 : : public:
307 : 18 : CancelProbe(CancelMonitor& monitor) : m_monitor(&monitor)
308 : : {
309 [ - + ]: 18 : assert(!monitor.m_probe);
310 : 18 : monitor.m_probe = this;
311 : 18 : }
312 : 18 : ~CancelProbe()
313 : : {
314 [ - + ]: 18 : if (m_monitor) m_monitor->promiseDestroyed(*this);
315 : 18 : }
316 : : CancelMonitor* m_monitor;
317 : : };
318 : :
319 : 18 : CancelMonitor::~CancelMonitor()
320 : : {
321 [ + - ]: 18 : if (m_probe) {
322 [ - + ]: 18 : assert(m_probe->m_monitor == this);
323 : 18 : m_probe->m_monitor = nullptr;
324 : 18 : m_probe = nullptr;
325 : : }
326 : 18 : }
327 : :
328 : 0 : void CancelMonitor::promiseDestroyed(CancelProbe& probe)
329 : : {
330 : : // If promise is being destroyed, assume the promise has been canceled. In
331 : : // theory this method could be called when a promise was fulfilled or
332 : : // rejected rather than canceled, but it's safe to assume that's not the
333 : : // case because the CancelMonitor class is meant to be used inside code
334 : : // fulfilling or rejecting the promise and destroyed before doing so.
335 [ # # ]: 0 : assert(m_probe == &probe);
336 : 0 : m_canceled = true;
337 [ # # ]: 0 : if (m_on_cancel) m_on_cancel();
338 : 0 : m_probe = nullptr;
339 : 0 : }
340 : : } // namespace mp
341 : :
342 : : #endif // MP_UTIL_H
|