From c04dcc2e7d834218ef2d4194331e383402495ae1 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 10 Apr 2024 20:07:22 +0200 Subject: Adding upstream version 2:20.4+dfsg. Signed-off-by: Daniel Baumann --- xbmc/windowing/wayland/Signals.h | 151 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 xbmc/windowing/wayland/Signals.h (limited to 'xbmc/windowing/wayland/Signals.h') diff --git a/xbmc/windowing/wayland/Signals.h b/xbmc/windowing/wayland/Signals.h new file mode 100644 index 0000000..59a1fdf --- /dev/null +++ b/xbmc/windowing/wayland/Signals.h @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2017-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#pragma once + +#include "threads/CriticalSection.h" + +#include +#include +#include + +namespace KODI +{ + +using RegistrationIdentifierType = int; + +class ISignalHandlerData +{ +protected: + ~ISignalHandlerData() = default; + +public: + virtual void Unregister(RegistrationIdentifierType id) = 0; +}; + +class CSignalRegistration +{ + std::weak_ptr m_list; + RegistrationIdentifierType m_registration; + + template + friend class CSignalHandlerList; + + CSignalRegistration(std::shared_ptr const& list, RegistrationIdentifierType registration) + : m_list{list}, m_registration{registration} + { + } + + CSignalRegistration(CSignalRegistration const& other) = delete; + CSignalRegistration& operator=(CSignalRegistration const& other) = delete; + +public: + CSignalRegistration() noexcept = default; + + CSignalRegistration(CSignalRegistration&& other) noexcept + { + *this = std::move(other); + } + + inline CSignalRegistration& operator=(CSignalRegistration&& other) noexcept + { + Unregister(); + std::swap(m_list, other.m_list); + m_registration = other.m_registration; + return *this; + } + + ~CSignalRegistration() noexcept + { + Unregister(); + } + + inline void Unregister() + { + if (auto list = m_list.lock()) + { + list->Unregister(m_registration); + list.reset(); + } + } +}; + +template +class CSignalHandlerList +{ + /** + * Internal storage for handler list + * + * Extra struct so memory handling with shared_ptr and weak_ptr can be done + * on this level + */ + struct Data final : public ISignalHandlerData + { + CCriticalSection m_handlerCriticalSection; + std::map m_handlers; + + void Unregister(RegistrationIdentifierType id) override + { + std::unique_lock lock(m_handlerCriticalSection); + m_handlers.erase(id); + } + }; + + std::shared_ptr m_data; + RegistrationIdentifierType m_lastRegistrationId{}; + + CSignalHandlerList(CSignalHandlerList const& other) = delete; + CSignalHandlerList& operator=(CSignalHandlerList const& other) = delete; + +public: + CSignalHandlerList() + : m_data{new Data} + {} + + CSignalRegistration Register(ManagedT const& handler) + { + std::unique_lock lock(m_data->m_handlerCriticalSection); + bool inserted{false}; + while(!inserted) + { + inserted = m_data->m_handlers.emplace(++m_lastRegistrationId, handler).second; + } + return {m_data, m_lastRegistrationId}; + } + + /** + * Invoke all registered signal handlers with the provided arguments + * when the signal type is a std::function or otherwise implements + * operator() + */ + template + void Invoke(ArgsT&&... args) + { + std::unique_lock lock(m_data->m_handlerCriticalSection); + for (auto const& handler : *this) + { + handler.second(std::forward(args)...); + } + } + + auto begin() const { return m_data->m_handlers.cbegin(); } + + auto end() const { return m_data->m_handlers.cend(); } + + /** + * Get critical section for accessing the handler list + * \note You must lock this yourself if you iterate through the handler + * list manually without using \ref Invoke or similar. + */ + CCriticalSection const& CriticalSection() const + { + return m_data->m_handlerCriticalSection; + } +}; + +} -- cgit v1.2.3