// Observable Library // Copyright (c) 2016 David Capello // // This file is released under the terms of the MIT license. // Read LICENSE.txt for more information. #ifndef OBS_SIGNAL_H_INCLUDED #define OBS_SIGNAL_H_INCLUDED #pragma once #include "obs/connection.h" #include "obs/safe_list.h" #include "obs/slot.h" #include #include namespace obs { class signal_base { public: virtual ~signal_base() { } virtual void disconnect_slot(slot_base* slot) = 0; }; // Signal for any kind of functions template class signal { }; template class signal : public signal_base { public: typedef R result_type; typedef slot slot_type; typedef safe_list slot_list; signal() { } ~signal() { for (auto slot : m_slots) delete slot; } signal(const signal&) { } signal& operator=(const signal&) { return *this; } connection add_slot(slot_type* s) { m_slots.push_back(s); return connection(this, s); } template connection connect(Function&& f) { return add_slot(new slot_type(std::forward(f))); } template connection connect(result_type (Class::*m)(Args...args), Class* t) { return add_slot(new slot_type( [=](Args...args) -> result_type { return (t->*m)(std::forward(args)...); })); } virtual void disconnect_slot(slot_base* slot) override { m_slots.erase(static_cast(slot)); } template typename std::enable_if::value, R>::type operator()(Args2&&...args) { R result = R(); for (auto slot : m_slots) if (slot) result = (*slot)(std::forward(args)...); return result; } protected: slot_list m_slots; }; template class signal : public signal_base { public: typedef slot slot_type; typedef safe_list slot_list; signal() { } ~signal() { for (auto slot : m_slots) delete slot; } signal(const signal&) { } signal& operator=(const signal&) { return *this; } connection add_slot(slot_type* s) { m_slots.push_back(s); return connection(this, s); } template connection connect(Function&& f) { return add_slot(new slot_type(std::forward(f))); } template connection connect(void (Class::*m)(Args...args), Class* t) { return add_slot(new slot_type( [=](Args...args) { (t->*m)(std::forward(args)...); })); } virtual void disconnect_slot(slot_base* slot) override { m_slots.erase(static_cast(slot)); } template void operator()(Args2&&...args) { for (auto slot : m_slots) if (slot) (*slot)(std::forward(args)...); } protected: slot_list m_slots; }; } // namespace obs #endif