diff --git a/include/xrpl/basics/Mutex.hpp b/include/xrpl/basics/Mutex.hpp new file mode 100644 index 0000000000..18c57370b1 --- /dev/null +++ b/include/xrpl/basics/Mutex.hpp @@ -0,0 +1,155 @@ +/* + This file is part of clio: https://github.com/XRPLF/clio + Copyright (c) 2024, the clio developers. + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. +*/ + +#pragma once + +#include +#include + +namespace xrpl { + +template +class Mutex; + +/** + * @brief A lock on a mutex that provides access to the protected data. + * + * @tparam ProtectedDataType data type to hold + * @tparam LockType type of lock + * @tparam MutexType type of mutex + */ +template typename LockType, typename MutexType> +class Lock +{ + LockType lock_; + ProtectedDataType& data_; + +public: + /** @cond */ + ProtectedDataType const& + operator*() const + { + return data_; + } + + ProtectedDataType& + operator*() + { + return data_; + } + + ProtectedDataType const& + get() const + { + return data_; + } + + ProtectedDataType& + get() + { + return data_; + } + + ProtectedDataType const* + operator->() const + { + return &data_; + } + + ProtectedDataType* + operator->() + { + return &data_; + } + + operator LockType&() & + { + return lock_; + } + + operator LockType const&() const& + { + return lock_; + } + /** @endcond */ + +private: + friend class Mutex, MutexType>; + + Lock(MutexType& mutex, ProtectedDataType& data) : lock_(mutex), data_(data) + { + } +}; + +/** + * @brief A container for data that is protected by a mutex. Inspired by Mutex in Rust. + * + * @tparam ProtectedDataType data type to hold + * @tparam MutexType type of mutex + */ +template +class Mutex +{ + mutable MutexType mutex_; + ProtectedDataType data_{}; + +public: + Mutex() = default; + + /** + * @brief Construct a new Mutex object with the given data + * + * @param data The data to protect + */ + explicit Mutex(ProtectedDataType data) : data_(std::move(data)) + { + } + + /** + * @brief Make a new Mutex object with the given data + * + * @tparam Args The types of the arguments to forward to the constructor of the protected data + * @param args The arguments to forward to the constructor of the protected data + * @return The Mutex object that protects the given data + */ + template + static Mutex + make(Args&&... args) + { + return Mutex{ProtectedDataType{std::forward(args)...}}; + } + + /** + * @brief Lock the mutex and get a lock object allowing access to the protected data + * + * @tparam LockType The type of lock to use + * @return A lock on the mutex and a reference to the protected data + */ + template