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 <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
23namespace mp {
24
26
31template <typename... Types>
33{
34 static constexpr size_t size = sizeof...(Types);
35};
36
45template <template <typename...> class Class, typename... Types, typename... Args>
46Class<Types..., std::remove_reference_t<Args>...> Make(Args&&... args)
47{
48 return Class<Types..., std::remove_reference_t<Args>...>{std::forward<Args>(args)...};
49}
50
56template <std::size_t index, typename List, typename _First = TypeList<>, bool done = index == 0>
57struct Split;
58
60template <typename _Second, typename _First>
61struct Split<0, _Second, _First, true>
62{
63 using First = _First;
64 using Second = _Second;
65};
66
68template <std::size_t index, typename Type, typename... _Second, typename... _First>
69struct 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
77template <typename Callable>
78using ResultOf = decltype(std::declval<Callable>()());
79
81template <typename T>
82using RemoveCvRef = std::remove_cv_t<std::remove_reference_t<T>>;
83
85template <typename T>
86using Decay = std::decay_t<T>;
87
89template <typename SfinaeExpr, typename Result_>
91{
92 using Result = Result_;
93};
94
96template <typename SfinaeExpr, typename Result = void>
98
107template <int priority>
108struct Priority : Priority<priority - 1>
109{
110};
111
113template <>
114struct Priority<0>
115{
116};
117
119template <typename T>
120const 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 const char* display_name = ::capnp::Schema::from<T>().getProto().getDisplayName().cStr();
129 const char* short_name = strchr(display_name, ':');
130 return short_name ? short_name + 1 : display_name;
131}
132
134template <typename T>
136 std::variant<T*, T> data;
137
138 template <typename... Args>
139 PtrOrValue(T* ptr, Args&&... args) : data(ptr ? ptr : std::variant<T*, T>{std::in_place_type<T>, std::forward<Args>(args)...}) {}
140
141 T& operator*() { return data.index() ? std::get<T>(data) : *std::get<T*>(data); }
142 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
163class MP_CAPABILITY("mutex") Mutex {
164public:
165 void lock() MP_ACQUIRE() { m_mutex.lock(); }
166 void unlock() MP_RELEASE() { m_mutex.unlock(); }
167
168 std::mutex m_mutex;
169};
170
172public:
173 explicit Lock(Mutex& m) MP_ACQUIRE(m) : m_lock(m.m_mutex) {}
174 ~Lock() MP_RELEASE() = default;
175 void unlock() MP_RELEASE() { m_lock.unlock(); }
176 void lock() MP_ACQUIRE() { m_lock.lock(); }
178 {
179 assert(m_lock.mutex() == &mutex.m_mutex);
180 assert(m_lock);
181 }
182
183 std::unique_lock<std::mutex> m_lock;
184};
185
186template<typename T>
188{
191};
192
193// CTAD for Clang 16: GuardedRef{mutex, x} -> GuardedRef<decltype(x)>
194template <class U>
196
198template <typename Lock>
200{
201 UnlockGuard(Lock& lock) : m_lock(lock) { m_lock.unlock(); }
204};
205
206template <typename Lock, typename Callback>
207void Unlock(Lock& lock, Callback&& callback)
208{
209 const UnlockGuard<Lock> unlock(lock);
210 callback();
211}
212
222template <typename Fn, typename After>
223decltype(auto) TryFinally(Fn&& fn, After&& after)
224{
225 bool success{false};
226 using R = std::invoke_result_t<Fn>;
227 try {
228 if constexpr (std::is_void_v<R>) {
229 std::forward<Fn>(fn)();
230 success = true;
231 std::forward<After>(after)();
232 return;
233 } else {
234 decltype(auto) result = std::forward<Fn>(fn)();
235 success = true;
236 std::forward<After>(after)();
237 return result;
238 }
239 } catch (...) {
240 if (!success) std::forward<After>(after)();
241 throw;
242 }
243}
244
246std::string ThreadName(const char* exe_name);
247
250std::string LogEscape(const kj::StringTree& string, size_t max_size);
251
253using FdToArgsFn = std::function<std::vector<std::string>(int fd)>;
254
262int SpawnProcess(int& pid, FdToArgsFn&& fd_to_args);
263
267void ExecProcess(const std::vector<std::string>& args);
268
270int WaitProcess(int pid);
271
272inline char* CharCast(char* c) { return c; }
273inline char* CharCast(unsigned char* c) { return (char*)c; }
274inline const char* CharCast(const char* c) { return c; }
275inline const char* CharCast(const unsigned char* c) { return (const char*)c; }
276
278struct InterruptException final : std::exception {
279 explicit InterruptException(std::string message) : m_message(std::move(message)) {}
280 const char* what() const noexcept override { return m_message.c_str(); }
281 std::string m_message;
282};
283
284class CancelProbe;
285
293{
294public:
295 inline ~CancelMonitor();
296 inline void promiseDestroyed(CancelProbe& probe);
297
298 bool m_canceled{false};
299 std::function<void()> m_on_cancel;
301};
302
305{
306public:
307 CancelProbe(CancelMonitor& monitor) : m_monitor(&monitor)
308 {
309 assert(!monitor.m_probe);
310 monitor.m_probe = this;
311 }
313 {
315 }
317};
318
320{
321 if (m_probe) {
322 assert(m_probe->m_monitor == this);
323 m_probe->m_monitor = nullptr;
324 m_probe = nullptr;
325 }
326}
327
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 assert(m_probe == &probe);
336 m_canceled = true;
338 m_probe = nullptr;
339}
340} // namespace mp
341
342#endif // MP_UTIL_H
ArgsManager & args
Definition: bitcoind.cpp:277
Helper class that detects when a promise is canceled.
Definition: util.h:293
void promiseDestroyed(CancelProbe &probe)
Definition: util.h:328
bool m_canceled
Definition: util.h:298
std::function< void()> m_on_cancel
Definition: util.h:299
CancelProbe * m_probe
Definition: util.h:300
Helper object to attach to a promise and update a CancelMonitor.
Definition: util.h:305
CancelMonitor * m_monitor
Definition: util.h:316
~CancelProbe()
Definition: util.h:312
CancelProbe(CancelMonitor &monitor)
Definition: util.h:307
Definition: util.h:171
void assert_locked(Mutex &mutex) MP_ASSERT_CAPABILITY() MP_ASSERT_CAPABILITY(mutex)
Definition: util.h:177
void unlock() MP_RELEASE()
Definition: util.h:175
Lock(Mutex &m) MP_ACQUIRE(m)
Definition: util.h:173
~Lock() MP_RELEASE()=default
std::unique_lock< std::mutex > m_lock
Definition: util.h:183
void lock() MP_ACQUIRE()
Definition: util.h:176
#define T(expected, seed, data)
#define MP_RELEASE(...)
Definition: util.h:158
#define MP_SCOPED_CAPABILITY
Definition: util.h:155
#define MP_ACQUIRE(...)
Definition: util.h:157
#define MP_ASSERT_CAPABILITY(x)
Definition: util.h:159
Functions to serialize / deserialize common bitcoin types.
Definition: common-types.h:57
void Unlock(Lock &lock, Callback &&callback)
Definition: util.h:207
int WaitProcess(int pid)
Wait for a process to exit and return its exit code.
Definition: util.cpp:186
const char * TypeName()
Return capnp type name with filename prefix removed.
Definition: util.h:120
class MP_CAPABILITY("mutex") Mutex
Definition: util.h:163
decltype(auto) TryFinally(Fn &&fn, After &&after)
Invoke a function and run a follow-up action before returning the original result.
Definition: util.h:223
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:97
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:46
std::decay_t< T > Decay
Type helper abbreviating std::decay.
Definition: util.h:86
std::remove_cv_t< std::remove_reference_t< T > > RemoveCvRef
Substitutue for std::remove_cvref_t.
Definition: util.h:82
decltype(std::declval< Callable >()()) ResultOf
Type helper giving return type of a callable type.
Definition: util.h:78
char * CharCast(char *c)
Definition: util.h:272
std::function< std::vector< std::string >(int fd)> FdToArgsFn
Callback type used by SpawnProcess below.
Definition: util.h:253
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
Definition: common.h:29
SFINAE helper, see using Require below.
Definition: util.h:91
Result_ Result
Definition: util.h:92
T &ref MP_GUARDED_BY(mutex)
Mutex & mutex
Definition: util.h:189
Exception thrown from code executing an IPC call that is interrupted.
Definition: util.h:278
const char * what() const noexcept override
Definition: util.h:280
InterruptException(std::string message)
Definition: util.h:279
std::string m_message
Definition: util.h:281
Function parameter type for prioritizing overloaded function calls that would otherwise be ambiguous.
Definition: util.h:109
Convenient wrapper around std::variant<T*, T>
Definition: util.h:135
T & operator*()
Definition: util.h:141
T * operator->() const
Definition: util.h:144
std::variant< T *, T > data
Definition: util.h:136
T & operator*() const
Definition: util.h:143
T * operator->()
Definition: util.h:142
PtrOrValue(T *ptr, Args &&... args)
Definition: util.h:139
Type helper splitting a TypeList into two halves at position index.
Definition: util.h:57
Generic utility functions used by capnp code.
Definition: util.h:33
static constexpr size_t size
Definition: util.h:34
Analog to std::lock_guard that unlocks instead of locks.
Definition: util.h:200
UnlockGuard(Lock &lock)
Definition: util.h:201
~UnlockGuard()
Definition: util.h:202
Lock & m_lock
Definition: util.h:203
assert(!tx.IsCoinBase())