Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#ifndef MP_UTIL_H6#define MP_UTIL_H8#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>24#if __has_include(<cxxabi.h>)25#include <cxxabi.h>26#include <memory>27#endif29namespace mp {31//! Generic utility functions used by capnp code.33//! Type holding a list of types.34//!35//! Example:36//! TypeList<int, bool, void>37template <typename... Types>38struct TypeList39{40static constexpr size_t size = sizeof...(Types);41};43//! Construct a template class value by deducing template arguments from the44//! types of constructor arguments, so they don't need to be specified manually.45//!46//! Uses of this can go away with class template deduction in C++1747//! (https://en.cppreference.com/w/cpp/language/class_template_argument_deduction)48//!49//! Example:50//! Make<std::pair>(5, true) // Constructs std::pair<int, bool>(5, true);51template <template <typename...> class Class, typename... Types, typename... Args>52Class<Types..., std::remove_reference_t<Args>...> Make(Args&&... args)53{54return Class<Types..., std::remove_reference_t<Args>...>{std::forward<Args>(args)...};55}57//! Type helper splitting a TypeList into two halves at position index.58//!59//! Example:60//! is_same<TypeList<int, double>, Split<2, TypeList<int, double, float, bool>>::First>61//! is_same<TypeList<float, bool>, Split<2, TypeList<int, double, float, bool>>::Second>62template <std::size_t index, typename List, typename _First = TypeList<>, bool done = index == 0>63struct Split;65//! Specialization of above (base case)66template <typename _Second, typename _First>67struct Split<0, _Second, _First, true>68{69using First = _First;70using Second = _Second;71};73//! Specialization of above (recursive case)74template <std::size_t index, typename Type, typename... _Second, typename... _First>75struct Split<index, TypeList<Type, _Second...>, TypeList<_First...>, false>76{77using _Next = Split<index - 1, TypeList<_Second...>, TypeList<_First..., Type>>;78using First = typename _Next::First;79using Second = typename _Next::Second;80};82//! Type helper giving return type of a callable type.83template <typename Callable>84using ResultOf = decltype(std::declval<Callable>()());86//! Substitutue for std::remove_cvref_t87template <typename T>88using RemoveCvRef = std::remove_cv_t<std::remove_reference_t<T>>;90//! Type helper abbreviating std::decay.91template <typename T>92using Decay = std::decay_t<T>;94//! SFINAE helper, see using Require below.95template <typename SfinaeExpr, typename Result_>96struct _Require97{98using Result = Result_;99};101//! SFINAE helper, basically the same as to C++17's void_t, but allowing types other than void to be returned.102template <typename SfinaeExpr, typename Result = void>103using Require = typename _Require<SfinaeExpr, Result>::Result;105//! Function parameter type for prioritizing overloaded function calls that106//! would otherwise be ambiguous.107//!108//! Example:109//! auto foo(Priority<1>) -> std::enable_if<>;110//! auto foo(Priority<0>) -> void;111//!112//! foo(Priority<1>()); // Calls higher priority overload if enabled.113template <int priority>114struct Priority : Priority<priority - 1>115{116};118//! Specialization of above (base case)119template <>120struct Priority<0>121{122};124//! Return capnp type name with filename prefix removed.125template <typename T>126const char* TypeName()127{128// DisplayName string looks like129// "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 away133// the object name, which is useful.134const char* display_name = ::capnp::Schema::from<T>().getProto().getDisplayName().cStr();135const char* short_name = strchr(display_name, ':');136return short_name ? short_name + 1 : display_name;137}139//! Convenient wrapper around std::variant<T*, T>140template <typename T>141struct PtrOrValue {142std::variant<T*, T> data;144template <typename... Args>145PtrOrValue(T* ptr, Args&&... args) : data(ptr ? ptr : std::variant<T*, T>{std::in_place_type<T>, std::forward<Args>(args)...}) {}147T& operator*() { return data.index() ? std::get<T>(data) : *std::get<T*>(data); }148T* operator->() { return &**this; }149T& operator*() const { return data.index() ? std::get<T>(data) : *std::get<T*>(data); }150T* operator->() const { return &**this; }151};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#else157#define MP_TSA(x) // no-op158#endif160#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)169class MP_CAPABILITY("mutex") Mutex {170public:171void lock() MP_ACQUIRE() { m_mutex.lock(); }172void unlock() MP_RELEASE() { m_mutex.unlock(); }174std::mutex m_mutex;175};177class MP_SCOPED_CAPABILITY Lock {178public:179explicit Lock(Mutex& m) MP_ACQUIRE(m) : m_lock(m.m_mutex) {}180~Lock() MP_RELEASE() = default;181void unlock() MP_RELEASE() { m_lock.unlock(); }182void lock() MP_ACQUIRE() { m_lock.lock(); }183void assert_locked(Mutex& mutex) MP_ASSERT_CAPABILITY() MP_ASSERT_CAPABILITY(mutex)184{185assert(m_lock.mutex() == &mutex.m_mutex);186assert(m_lock);187}189std::unique_lock<std::mutex> m_lock;190};192template<typename T>193struct GuardedRef194{195Mutex& mutex;196T& ref MP_GUARDED_BY(mutex);197};199// CTAD for Clang 16: GuardedRef{mutex, x} -> GuardedRef<decltype(x)>200template <class U>201GuardedRef(Mutex&, U&) -> GuardedRef<U>;203//! Analog to std::lock_guard that unlocks instead of locks.204template <typename Lock>205struct UnlockGuard206{207UnlockGuard(Lock& lock) : m_lock(lock) { m_lock.unlock(); }208~UnlockGuard() { m_lock.lock(); }209Lock& m_lock;210};212template <typename Lock, typename Callback>213void Unlock(Lock& lock, Callback&& callback)214{215const UnlockGuard<Lock> unlock(lock);216callback();217}219//! Invoke a function and run a follow-up action before returning the original220//! result.221//!222//! This can be used similarly to KJ_DEFER to run cleanup code, but works better223//! if the cleanup function can throw because it avoids clang bug224//! https://github.com/llvm/llvm-project/issues/12658 which skips calling225//! destructors in that case and can lead to memory leaks. Also, if both226//! functions throw, this lets one exception take precedence instead of227//! terminating due to having two active exceptions.228template <typename Fn, typename After>229decltype(auto) TryFinally(Fn&& fn, After&& after)230{231bool success{false};232using R = std::invoke_result_t<Fn>;233try {234if constexpr (std::is_void_v<R>) {235std::forward<Fn>(fn)();236success = true;237std::forward<After>(after)();238return;239} else {240decltype(auto) result = std::forward<Fn>(fn)();241success = true;242std::forward<After>(after)();243return result;244}245} catch (...) {246if (!success) std::forward<After>(after)();247throw;248}249}
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.