Bitcoin Core  31.0.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 
23 namespace mp {
24 
26 
31 template <typename... Types>
32 struct TypeList
33 {
34  static constexpr size_t size = sizeof...(Types);
35 };
36 
45 template <template <typename...> class Class, typename... Types, typename... Args>
46 Class<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 
56 template <std::size_t index, typename List, typename _First = TypeList<>, bool done = index == 0>
57 struct Split;
58 
60 template <typename _Second, typename _First>
61 struct Split<0, _Second, _First, true>
62 {
63  using First = _First;
64  using Second = _Second;
65 };
66 
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 
77 template <typename Callable>
78 using ResultOf = decltype(std::declval<Callable>()());
79 
81 template <typename T>
82 using RemoveCvRef = std::remove_cv_t<std::remove_reference_t<T>>;
83 
85 template <typename T>
86 using Decay = std::decay_t<T>;
87 
89 template <typename SfinaeExpr, typename Result_>
90 struct _Require
91 {
92  using Result = Result_;
93 };
94 
96 template <typename SfinaeExpr, typename Result = void>
98 
107 template <int priority>
108 struct Priority : Priority<priority - 1>
109 {
110 };
111 
113 template <>
114 struct Priority<0>
115 {
116 };
117 
119 template <typename T>
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  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 
134 template <typename T>
135 struct PtrOrValue {
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 
163 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 
172 public:
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 
186 template<typename T>
188 {
190  T& ref MP_GUARDED_BY(mutex);
191 };
192 
193 // CTAD for Clang 16: GuardedRef{mutex, x} -> GuardedRef<decltype(x)>
194 template <class U>
196 
198 template <typename Lock>
200 {
201  UnlockGuard(Lock& lock) : m_lock(lock) { m_lock.unlock(); }
204 };
205 
206 template <typename Lock, typename Callback>
207 void Unlock(Lock& lock, Callback&& callback)
208 {
209  const UnlockGuard<Lock> unlock(lock);
210  callback();
211 }
212 
222 template <typename Fn, typename After>
223 decltype(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 
246 std::string ThreadName(const char* exe_name);
247 
250 std::string LogEscape(const kj::StringTree& string, size_t max_size);
251 
253 using FdToArgsFn = std::function<std::vector<std::string>(int fd)>;
254 
262 int SpawnProcess(int& pid, FdToArgsFn&& fd_to_args);
263 
267 void ExecProcess(const std::vector<std::string>& args);
268 
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 
278 struct 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 
284 class CancelProbe;
285 
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 
305 {
306 public:
307  CancelProbe(CancelMonitor& monitor) : m_monitor(&monitor)
308  {
309  assert(!monitor.m_probe);
310  monitor.m_probe = this;
311  }
313  {
314  if (m_monitor) m_monitor->promiseDestroyed(*this);
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;
337  if (m_on_cancel) m_on_cancel();
338  m_probe = nullptr;
339 }
340 } // namespace mp
341 
342 #endif // MP_UTIL_H
Convenient wrapper around std::variant<T*, T>
Definition: util.h:135
assert(!tx.IsCoinBase())
Function parameter type for prioritizing overloaded function calls that would otherwise be ambiguous...
Definition: util.h:108
InterruptException(std::string message)
Definition: util.h:279
std::remove_cv_t< std::remove_reference_t< T > > RemoveCvRef
Substitutue for std::remove_cvref_t.
Definition: util.h:82
T & operator*() const
Definition: util.h:143
std::variant< T *, T > data
Definition: util.h:136
std::string ThreadName(const char *exe_name)
Format current thread name as "{exe_name}-{$pid}/{thread_name}-{$tid}".
Definition: util.cpp:64
~CancelProbe()
Definition: util.h:312
static constexpr size_t size
Definition: util.h:34
Definition: common.h:29
#define MP_RELEASE(...)
Definition: util.h:158
Exception thrown from code executing an IPC call that is interrupted.
Definition: util.h:278
#define MP_ACQUIRE(...)
Definition: util.h:157
char * CharCast(char *c)
Definition: util.h:272
Generic utility functions used by capnp code.
Definition: util.h:32
T &ref MP_GUARDED_BY(mutex)
const char * what() const noexcept override
Definition: util.h:280
Functions to serialize / deserialize common bitcoin types.
Definition: common-types.h:57
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
PtrOrValue(T *ptr, Args &&... args)
Definition: util.h:139
void promiseDestroyed(CancelProbe &probe)
Definition: util.h:328
CancelProbe(CancelMonitor &monitor)
Definition: util.h:307
UnlockGuard(Lock &lock)
Definition: util.h:201
Lock & m_lock
Definition: util.h:203
ArgsManager & args
Definition: bitcoind.cpp:277
Helper object to attach to a promise and update a CancelMonitor.
Definition: util.h:304
typename _Require< SfinaeExpr, Result >::Result Require
SFINAE helper, basically the same as to C++17&#39;s void_t, but allowing types other than void to be retu...
Definition: util.h:97
T * operator->()
Definition: util.h:142
void ExecProcess(const std::vector< std::string > &args)
Call execvp with vector args.
Definition: util.cpp:174
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
#define MP_ASSERT_CAPABILITY(x)
Definition: util.h:159
SFINAE helper, see using Require below.
Definition: util.h:90
Type helper splitting a TypeList into two halves at position index.
Definition: util.h:57
CancelProbe * m_probe
Definition: util.h:300
const char * TypeName()
Return capnp type name with filename prefix removed.
Definition: util.h:120
GuardedRef(Mutex &, U &) -> GuardedRef< U >
std::function< void()> m_on_cancel
Definition: util.h:299
CancelMonitor * m_monitor
Definition: util.h:316
class MP_CAPABILITY("mutex") Mutex
Definition: util.h:163
std::unique_lock< std::mutex > m_lock
Definition: util.h:183
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
decltype(std::declval< Callable >()()) ResultOf
Type helper giving return type of a callable type.
Definition: util.h:78
auto result
Definition: common-types.h:74
std::string LogEscape(const kj::StringTree &string, size_t max_size)
Escape binary string for use in log so it doesn&#39;t trigger unicode decode errors in python unit tests...
Definition: util.cpp:95
T * operator->() const
Definition: util.h:144
std::decay_t< T > Decay
Type helper abbreviating std::decay.
Definition: util.h:86
Analog to std::lock_guard that unlocks instead of locks.
Definition: util.h:199
#define MP_SCOPED_CAPABILITY
Definition: util.h:155
void assert_locked(Mutex &mutex) MP_ASSERT_CAPABILITY() MP_ASSERT_CAPABILITY(mutex)
Definition: util.h:177
std::function< std::vector< std::string >(int fd)> FdToArgsFn
Callback type used by SpawnProcess below.
Definition: util.h:253
Definition: util.h:171
void unlock() MP_RELEASE()
Definition: util.h:175
Result_ Result
Definition: util.h:92
Mutex & mutex
Definition: util.h:189
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::string m_message
Definition: util.h:281
~UnlockGuard()
Definition: util.h:202
T & operator*()
Definition: util.h:141
Lock(Mutex &m) MP_ACQUIRE(m)
Definition: util.h:173
bool m_canceled
Definition: util.h:298
#define T(expected, seed, data)
void lock() MP_ACQUIRE()
Definition: util.h:176
Helper class that detects when a promise is canceled.
Definition: util.h:292