| #pragma once
|
|
|
| #include "combiners.h"
|
| #include "connection.h"
|
| #include "function.h"
|
| #include "signal_impl.h"
|
| #include "type_traits.h"
|
| #include <type_traits>
|
|
|
|
|
| namespace fastsignals
|
| {
|
| template <class Signature, template <class T> class Combiner = optional_last_value>
|
| class signal;
|
|
|
| struct advanced_tag
|
| {
|
| };
|
|
|
|
|
|
|
|
|
| template <class Return, class... Arguments, template <class T> class Combiner>
|
| class signal<Return(Arguments...), Combiner> : private not_directly_callable
|
| {
|
| public:
|
| using signature_type = Return(signal_arg_t<Arguments>...);
|
| using slot_type = function<signature_type>;
|
| using combiner_type = Combiner<Return>;
|
| using result_type = typename combiner_type::result_type;
|
|
|
| signal()
|
| : m_slots(std::make_shared<detail::signal_impl>())
|
| {
|
| }
|
|
|
|
|
| signal(const signal&) = delete;
|
|
|
|
|
| signal(signal&& other) = default;
|
|
|
|
|
| signal& operator=(const signal&) = delete;
|
|
|
|
|
| signal& operator=(signal&& other) = default;
|
|
|
| |
| |
| |
| |
|
|
| connection connect(slot_type slot)
|
| {
|
| const uint64_t id = m_slots->add(slot.release());
|
| return connection(m_slots, id);
|
| }
|
|
|
| |
| |
| |
| |
| |
|
|
| advanced_connection connect(slot_type slot, advanced_tag)
|
| {
|
| static_assert(std::is_void_v<Return>, "Advanced connect can only be used with slots returning void (implementation limitation)");
|
| auto conn_impl = std::make_shared<advanced_connection::advanced_connection_impl>();
|
| slot_type slot_impl = [this, slot, weak_conn_impl = std::weak_ptr(conn_impl)](signal_arg_t<Arguments>... args) {
|
| (void)this;
|
| auto conn_impl = weak_conn_impl.lock();
|
| if (!conn_impl || !conn_impl->is_blocked())
|
| {
|
| slot(args...);
|
| }
|
| };
|
| auto conn = connect(std::move(slot_impl));
|
| return advanced_connection(std::move(conn), std::move(conn_impl));
|
| }
|
|
|
| |
| |
|
|
| void disconnect_all_slots() noexcept
|
| {
|
| m_slots->remove_all();
|
| }
|
|
|
| |
| |
|
|
| [[nodiscard]] std::size_t num_slots() const noexcept
|
| {
|
| return m_slots->count();
|
| }
|
|
|
| |
| |
|
|
| [[nodiscard]] bool empty() const noexcept
|
| {
|
| return m_slots->count() == 0;
|
| }
|
|
|
| |
| |
| |
|
|
| result_type operator()(signal_arg_t<Arguments>... args) const
|
| {
|
| return detail::signal_impl_ptr(m_slots)->invoke<combiner_type, result_type, signature_type, signal_arg_t<Arguments>...>(args...);
|
| }
|
|
|
| void swap(signal& other) noexcept
|
| {
|
| m_slots.swap(other.m_slots);
|
| }
|
|
|
| |
| |
|
|
| operator slot_type() const noexcept
|
| {
|
| return [weakSlots = detail::signal_impl_weak_ptr(m_slots)](signal_arg_t<Arguments>... args) {
|
| if (auto slots = weakSlots.lock())
|
| {
|
| return slots->invoke<combiner_type, result_type, signature_type, signal_arg_t<Arguments>...>(args...);
|
| }
|
| };
|
| }
|
|
|
| private:
|
| detail::signal_impl_ptr m_slots;
|
| };
|
|
|
| }
|
|
|
| namespace std
|
| {
|
|
|
|
|
| template <class Signature, template <class T> class Combiner>
|
| void swap(
|
| ::fastsignals::signal<Signature, Combiner>& sig1,
|
| ::fastsignals::signal<Signature, Combiner>& sig2)
|
| {
|
| sig1.swap(sig2);
|
| }
|
|
|
| }
|
|
|