Bitcoin Core 31.99.0
P2P Digital Currency
util.h
Go to the documentation of this file.
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 <cstdlib>
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 <typeinfo>
19#include <type_traits>
20#include <utility>
21#include <variant>
22#include <vector>
23
24#if __has_include(<cxxabi.h>)
25#include <cxxabi.h>
26#include <memory>
27#endif
28
29namespace mp {
30
32
37template <typename... Types>
39{
40 static constexpr size_t size = sizeof...(Types);
41};
42
51template <template <typename...> class Class, typename... Types, typename... Args>
52Class<Types..., std::remove_reference_t<Args>...> Make(Args&&... args)
53{
54 return Class<Types..., std::remove_reference_t<Args>...>{std::forward<Args>(args)...};
55}
56
62template <std::size_t index, typename List, typename _First = TypeList<>, bool done = index == 0>
63struct Split;
64
66template <typename _Second, typename _First>
67struct Split<0, _Second, _First, true>
68{
69 using First = _First;
70 using Second = _Second;
71};
72
74template <std::size_t index, typename Type, typename... _Second, typename... _First>
75struct Split<index, TypeList<Type, _Second...>, TypeList<_First...>, false>
76{
77 using _Next = Split<index - 1, TypeList<_Second...>, TypeList<_First..., Type>>;
78 using First = typename _Next::First;
79 using Second = typename _Next::Second;
80};
81
83template <typename Callable>
84using ResultOf = decltype(std::declval<Callable>()());
85
87template <typename T>
88using RemoveCvRef = std::remove_cv_t<std::remove_reference_t<T>>;
89
91template <typename T>
92using Decay = std::decay_t<T>;
93
95template <typename SfinaeExpr, typename Result_>
97{
98 using Result = Result_;
99};
100
102template <typename SfinaeExpr, typename Result = void>
104
113template <int priority>
114struct Priority : Priority<priority - 1>
115{
116};
117
119template <>
120struct Priority<0>
121{
122};
123
125template <typename T>
126const char* TypeName()
127{
128 // DisplayName string looks like
129 // "interfaces/capnp/common.capnp:ChainNotifications.resendWalletTransactions$Results"
130 // This discards the part of the string before the first ':' character.
131 // Another alternative would be to use the displayNamePrefixLength field,
132 // but this discards everything before the last '.' character, throwing away
133 // the object name, which is useful.
134 const char* display_name = ::capnp::Schema::from<T>().getProto().getDisplayName().cStr();
135 const char* short_name = strchr(display_name, ':');
136 return short_name ? short_name + 1 : display_name;
137}
138
140template <typename T>
142 std::variant<T*, T> data;
143
144 template <typename... Args>
145 PtrOrValue(T* ptr, Args&&... args) : data(ptr ? ptr : std::variant<T*, T>{std::in_place_type<T>, std::forward<Args>(args)...}) {}
146
147 T& operator*() { return data.index() ? std::get<T>(data) : *std::get<T*>(data); }
148 T* operator->() { return &**this; }
149 T& operator*() const { return data.index() ? std::get<T>(data) : *std::get<T*>(data); }
150 T* operator->() const { return &**this; }
151};
152
153// Annotated mutex and lock class (https://clang.llvm.org/docs/ThreadSafetyAnalysis.html)
154#if defined(__clang__) && (!defined(SWIG))
155#define MP_TSA(x) __attribute__((x))
156#else
157#define MP_TSA(x) // no-op
158#endif
159
160#define MP_CAPABILITY(x) MP_TSA(capability(x))
161#define MP_SCOPED_CAPABILITY MP_TSA(scoped_lockable)
162#define MP_REQUIRES(x) MP_TSA(requires_capability(x))
163#define MP_ACQUIRE(...) MP_TSA(acquire_capability(__VA_ARGS__))
164#define MP_RELEASE(...) MP_TSA(release_capability(__VA_ARGS__))
165#define MP_ASSERT_CAPABILITY(x) MP_TSA(assert_capability(x))
166#define MP_GUARDED_BY(x) MP_TSA(guarded_by(x))
167#define MP_NO_TSA MP_TSA(no_thread_safety_analysis)
168
169class MP_CAPABILITY("mutex") Mutex {
170public:
171 void lock() MP_ACQUIRE() { m_mutex.lock(); }
172 void unlock() MP_RELEASE() { m_mutex.unlock(); }
173
174 std::mutex m_mutex;
175};
176
178public:
179 explicit Lock(Mutex& m) MP_ACQUIRE(m) : m_lock(m.m_mutex) {}
180 ~Lock() MP_RELEASE() = default;
181 void unlock() MP_RELEASE() { m_lock.unlock(); }
182 void lock() MP_ACQUIRE() { m_lock.lock(); }
184 {
185 assert(m_lock.mutex() == &mutex.m_mutex);
186 assert(m_lock);
187 }
188
189 std::unique_lock<std::mutex> m_lock;
190};
191
192template<typename T>
194{
197};
198
199// CTAD for Clang 16: GuardedRef{mutex, x} -> GuardedRef<decltype(x)>
200template <class U>
202
204template <typename Lock>
206{
207 UnlockGuard(Lock& lock) : m_lock(lock) { m_lock.unlock(); }
210};
211
212template <typename Lock, typename Callback>
213void Unlock(Lock& lock, Callback&& callback)
214{
215 const UnlockGuard<Lock> unlock(lock);
216 callback();
217}
218
228template <typename Fn, typename After>
229decltype(auto) TryFinally(Fn&& fn, After&& after)
230{
231 bool success{false};
232 using R = std::invoke_result_t<Fn>;
233 try {
234 if constexpr (std::is_void_v<R>) {
235 std::forward<Fn>(fn)();
236 success = true;
237 std::forward<After>(after)();
238 return;
239 } else {
240 decltype(auto) result = std::forward<Fn>(fn)();
241 success = true;
242 std::forward<After>(after)();
243 return result;
244 }
245 } catch (...) {
246 if (!success) std::forward<After>(after)();
247 throw;
248 }
249}
250
252std::string ThreadName(const char* exe_name);
253
256std::string LogEscape(const kj::StringTree& string, size_t max_size);
257
259using FdToArgsFn = std::function<std::vector<std::string>(int fd)>;
260
268int SpawnProcess(int& pid, FdToArgsFn&& fd_to_args);
269
273void ExecProcess(const std::vector<std::string>& args);
274
276int WaitProcess(int pid);
277
278inline char* CharCast(char* c) { return c; }
279inline char* CharCast(unsigned char* c) { return (char*)c; }
280inline const char* CharCast(const char* c) { return c; }
281inline const char* CharCast(const unsigned char* c) { return (const char*)c; }
282
283#if __has_include(<cxxabi.h>) // GCC & Clang ─ use <cxxabi.h> to demangle
284inline std::string _demangle(const char* m)
285{
286 int status = 0;
287 std::unique_ptr<char, void(*)(void*)> p{
288 abi::__cxa_demangle(m, /*output_buffer=*/nullptr, /*length=*/nullptr, &status), std::free};
289 return (status == 0 && p) ? p.get() : m; // fall back on mangled if needed
290}
291#else // MSVC or other ─ no demangling available
292inline std::string _demangle(const char* m) { return m; }
293#endif
294
295template<class T>
296std::string CxxTypeName(const T& /*unused*/)
297{
298#ifdef __cpp_rtti
299 return _demangle(typeid(std::decay_t<T>).name());
300#else
301 return "<type information unavailable without rtti>";
302#endif
303}
304
306struct InterruptException final : std::exception {
307 explicit InterruptException(std::string message) : m_message(std::move(message)) {}
308 const char* what() const noexcept override { return m_message.c_str(); }
309 std::string m_message;
310};
311
312class CancelProbe;
313
321{
322public:
323 inline ~CancelMonitor();
324 inline void promiseDestroyed(CancelProbe& probe);
325
326 bool m_canceled{false};
327 std::function<void()> m_on_cancel;
329};
330
333{
334public:
335 CancelProbe(CancelMonitor& monitor) : m_monitor(&monitor)
336 {
337 assert(!monitor.m_probe);
338 monitor.m_probe = this;
339 }
341 {
343 }
345};
346
348{
349 if (m_probe) {
350 assert(m_probe->m_monitor == this);
351 m_probe->m_monitor = nullptr;
352 m_probe = nullptr;
353 }
354}
355
357{
358 // If promise is being destroyed, assume the promise has been canceled. In
359 // theory this method could be called when a promise was fulfilled or
360 // rejected rather than canceled, but it's safe to assume that's not the
361 // case because the CancelMonitor class is meant to be used inside code
362 // fulfilling or rejecting the promise and destroyed before doing so.
363 assert(m_probe == &probe);
364 m_canceled = true;
366 m_probe = nullptr;
367}
368} // namespace mp
369
370#endif // MP_UTIL_H
ArgsManager & args
Definition: bitcoind.cpp:280
Helper class that detects when a promise is canceled.
Definition: util.h:321
void promiseDestroyed(CancelProbe &probe)
Definition: util.h:356
bool m_canceled
Definition: util.h:326
std::function< void()> m_on_cancel
Definition: util.h:327
CancelProbe * m_probe
Definition: util.h:328
Helper object to attach to a promise and update a CancelMonitor.
Definition: util.h:333
CancelMonitor * m_monitor
Definition: util.h:344
~CancelProbe()
Definition: util.h:340
CancelProbe(CancelMonitor &monitor)
Definition: util.h:335
Definition: util.h:177
void assert_locked(Mutex &mutex) MP_ASSERT_CAPABILITY() MP_ASSERT_CAPABILITY(mutex)
Definition: util.h:183
void unlock() MP_RELEASE()
Definition: util.h:181
Lock(Mutex &m) MP_ACQUIRE(m)
Definition: util.h:179
~Lock() MP_RELEASE()=default
std::unique_lock< std::mutex > m_lock
Definition: util.h:189
void lock() MP_ACQUIRE()
Definition: util.h:182
#define T(expected, seed, data)
#define MP_RELEASE(...)
Definition: util.h:164
#define MP_SCOPED_CAPABILITY
Definition: util.h:161
#define MP_ACQUIRE(...)
Definition: util.h:163
#define MP_ASSERT_CAPABILITY(x)
Definition: util.h:165
Functions to serialize / deserialize common bitcoin types.
Definition: common-types.h:57
void Unlock(Lock &lock, Callback &&callback)
Definition: util.h:213
int WaitProcess(int pid)
Wait for a process to exit and return its exit code.
Definition: util.cpp:186
std::string CxxTypeName(const T &)
Definition: util.h:296
const char * TypeName()
Return capnp type name with filename prefix removed.
Definition: util.h:126
class MP_CAPABILITY("mutex") Mutex
Definition: util.h:169
std::string _demangle(const char *m)
Definition: util.h:292
decltype(auto) TryFinally(Fn &&fn, After &&after)
Invoke a function and run a follow-up action before returning the original result.
Definition: util.h:229
GuardedRef(Mutex &, U &) -> GuardedRef< U >
std::string ThreadName(const char *exe_name)
Format current thread name as "{exe_name}-{$pid}/{thread_name}-{$tid}".
Definition: util.cpp:64
typename _Require< SfinaeExpr, Result >::Result Require
SFINAE helper, basically the same as to C++17's void_t, but allowing types other than void to be retu...
Definition: util.h:103
int SpawnProcess(int &pid, FdToArgsFn &&fd_to_args)
Spawn a new process that communicates with the current process over a socket pair.
Definition: util.cpp:119
Class< Types..., std::remove_reference_t< Args >... > Make(Args &&... args)
Construct a template class value by deducing template arguments from the types of constructor argumen...
Definition: util.h:52
std::decay_t< T > Decay
Type helper abbreviating std::decay.
Definition: util.h:92
std::remove_cv_t< std::remove_reference_t< T > > RemoveCvRef
Substitutue for std::remove_cvref_t.
Definition: util.h:88
decltype(std::declval< Callable >()()) ResultOf
Type helper giving return type of a callable type.
Definition: util.h:84
char * CharCast(char *c)
Definition: util.h:278
std::function< std::vector< std::string >(int fd)> FdToArgsFn
Callback type used by SpawnProcess below.
Definition: util.h:259
void ExecProcess(const std::vector< std::string > &args)
Call execvp with vector args.
Definition: util.cpp:174
std::string LogEscape(const kj::StringTree &string, size_t max_size)
Escape binary string for use in log so it doesn't trigger unicode decode errors in python unit tests.
Definition: util.cpp:95
const char * name
Definition: rest.cpp:50
SFINAE helper, see using Require below.
Definition: util.h:97
Result_ Result
Definition: util.h:98
T &ref MP_GUARDED_BY(mutex)
Mutex & mutex
Definition: util.h:195
Exception thrown from code executing an IPC call that is interrupted.
Definition: util.h:306
const char * what() const noexcept override
Definition: util.h:308
InterruptException(std::string message)
Definition: util.h:307
std::string m_message
Definition: util.h:309
Function parameter type for prioritizing overloaded function calls that would otherwise be ambiguous.
Definition: util.h:115
Convenient wrapper around std::variant<T*, T>
Definition: util.h:141
T & operator*()
Definition: util.h:147
T * operator->() const
Definition: util.h:150
std::variant< T *, T > data
Definition: util.h:142
T & operator*() const
Definition: util.h:149
T * operator->()
Definition: util.h:148
PtrOrValue(T *ptr, Args &&... args)
Definition: util.h:145
Type helper splitting a TypeList into two halves at position index.
Definition: util.h:63
Generic utility functions used by capnp code.
Definition: util.h:39
static constexpr size_t size
Definition: util.h:40
Analog to std::lock_guard that unlocks instead of locks.
Definition: util.h:206
UnlockGuard(Lock &lock)
Definition: util.h:207
~UnlockGuard()
Definition: util.h:208
Lock & m_lock
Definition: util.h:209
assert(!tx.IsCoinBase())