// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Core module" // For conditions of distribution and use, see copyright notice in Config.hpp #pragma once #ifndef NAZARA_SIGNAL_HPP #define NAZARA_SIGNAL_HPP #include #include #include #define NazaraSignal(SignalName, ...) using SignalName ## Type = NzSignal<__VA_ARGS__>; \ mutable SignalName ## Type SignalName #define NazaraSlotType(Class, SignalName) Class::SignalName ## Type::ConnectionGuard #define NazaraSlot(Class, SignalName, SlotName) NazaraSlotType(Class, SignalName) SlotName template class NzSignal { public: using Callback = std::function; class Connection; class ConnectionGuard; NzSignal(); NzSignal(const NzSignal&) = delete; NzSignal(NzSignal&& signal); ~NzSignal() = default; void Clear(); Connection Connect(const Callback& func); Connection Connect(Callback&& func); template Connection Connect(O& object, void (O::*method)(Args...)); template Connection Connect(O* object, void (O::*method)(Args...)); template Connection Connect(const O& object, void (O::*method)(Args...) const); template Connection Connect(const O* object, void (O::*method)(Args...) const); void operator()(Args... args) const; NzSignal& operator=(const NzSignal&) = delete; NzSignal& operator=(NzSignal&& signal); private: struct Slot; using SlotPtr = std::shared_ptr; using SlotList = std::vector; using SlotListIndex = typename SlotList::size_type; struct Slot { Slot(NzSignal* me) : signal(me) { } Callback callback; NzSignal* signal; SlotListIndex index; }; void Disconnect(const SlotPtr& slot); SlotList m_slots; mutable SlotListIndex m_slotIterator; }; template class NzSignal::Connection { using BaseClass = NzSignal; friend BaseClass; public: Connection() = default; Connection(const Connection& connection) = default; Connection(Connection&& connection) = default; ~Connection() = default; template void Connect(BaseClass& signal, ConnectArgs&&... args); void Disconnect(); bool IsConnected() const; Connection& operator=(const Connection& connection) = default; Connection& operator=(Connection&& connection) = default; private: Connection(const SlotPtr& slot); std::weak_ptr m_ptr; }; template class NzSignal::ConnectionGuard { using BaseClass = NzSignal; using Connection = typename BaseClass::Connection; public: ConnectionGuard() = default; ConnectionGuard(const Connection& connection); ConnectionGuard(const ConnectionGuard& connection) = delete; ConnectionGuard(Connection&& connection); ConnectionGuard(ConnectionGuard&& connection) = default; ~ConnectionGuard(); template void Connect(BaseClass& signal, ConnectArgs&&... args); void Disconnect(); Connection& GetConnection(); bool IsConnected() const; ConnectionGuard& operator=(const Connection& connection); ConnectionGuard& operator=(const ConnectionGuard& connection) = delete; ConnectionGuard& operator=(Connection&& connection); ConnectionGuard& operator=(ConnectionGuard&& connection); private: Connection m_connection; }; #include #endif // NAZARA_SIGNAL_HPP