diff --git a/external/avast/avast/async_mutex.hpp b/external/avast/avast/async_mutex.hpp new file mode 100644 index 0000000..aff70f1 --- /dev/null +++ b/external/avast/avast/async_mutex.hpp @@ -0,0 +1,429 @@ +// SPDX-FileCopyrightText: 2023 Daniel Vrátil +// SPDX-FileCopyrightText: 2023 Martin Beran +// +// SPDX-License-Identifier: BSL-1.0 + +#pragma once + +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef ASIO_STANDALONE +#define ASIO_NS ::asio +#else +#define ASIO_NS boost::asio +#endif + +namespace avast::asio { + +class async_mutex_lock; +class async_mutex; + +/** \internal **/ +namespace detail { + +/** + * \brief Represents a suspended coroutine that is awaiting lock acquisition. + **/ +struct locked_waiter { + /** + * \brief Constructs a new locked_waiter. + * \param next_waiter Pointer to the waiter to prepend this locked_waiter to. + **/ + explicit locked_waiter(locked_waiter *next_waiter): next(next_waiter) {} + locked_waiter(locked_waiter &&) = delete; + locked_waiter(const locked_waiter &) = delete; + locked_waiter &operator=(locked_waiter &&) = delete; + locked_waiter &operator=(const locked_waiter &) = delete; + /** + * \brief Destructor. + **/ + virtual ~locked_waiter() = default; + + /** + * \brief Completes the pending asynchronous operation. + * + * Resumes the currently suspended coroutine with the acquired lock. + **/ + virtual void completion() = 0; + + /** + * The waiters are held in a linked list. This is a pointer to the next member of the list. + **/ + locked_waiter *next = nullptr; +}; + +/** + * \brief Locked waiter that used `async_mutex::async_lock()` to acquire the lock. + **/ +template +struct async_locked_waiter final: public locked_waiter { + /** + * \brief Constructs a new async_locked_waiter. + * \param mutex A mutex that the waiter is trying to acquire a lock for. + * \param next_waiter Pointer to the head of the waiters linked list to prepend this waiter to. + * \param token The complention token to call when the asynchronous operation is completed. + **/ + async_locked_waiter([[maybe_unused]] async_mutex *mutex, locked_waiter *next_waiter, Token &&token): + locked_waiter(next_waiter), m_token(std::move(token)) {} + + void completion() override { + auto executor = ASIO_NS::get_associated_executor(m_token); + ASIO_NS::post(std::move(executor), [token = std::move(m_token)]() mutable { token(); }); + } + +private: + Token m_token; //!< The completion token to invoke when the lock is acquired. +}; + +/** + * \brief Locked waiter that used `async_mutex::async_scoped_lock()` to acquire the lock. + **/ +template +struct scoped_async_locked_waiter final: public locked_waiter { + /** + * \brief Constructs a new scoped_async_locked_waiter. + * \param mutex A mutex that the waiter is trying to acquire a lock for. + * \param next_waiter Pointer to the head of the waiters linked list to prepend this waiter to. + * \param token The complention token to call when the asynchronous operation is completed. + **/ + scoped_async_locked_waiter(async_mutex *mutex, locked_waiter *next_waiter, Token &&token): + locked_waiter(next_waiter), m_mutex(mutex), m_token(std::move(token)) {} + + void completion() override; + +private: + async_mutex *m_mutex; //!< The mutex whose lock is being awaited. + Token m_token; //!< The completion token to invoke when the lock is acquired. +}; + +/** + * \brief An initiator for asio::async_initiate(). + **/ +template