Skip to content

Instantly share code, notes, and snippets.

@Alia5
Last active May 24, 2022 12:09

Revisions

  1. Alia5 revised this gist Dec 14, 2016. 1 changed file with 10 additions and 6 deletions.
    16 changes: 10 additions & 6 deletions Signals.h
    Original file line number Diff line number Diff line change
    @@ -89,27 +89,31 @@ template<typename... Args>
    class SConnection
    {
    typedef Connection<Args...> Connection;

    public:

    SConnection()
    SConnection() : signal_(nullptr)
    {

    }

    SConnection(Connection connection) : connection_(connection)
    SConnection(Signal<Args...>& signal, Connection connection) : signal_(&signal), connection_(connection)
    {
    hasConnection = true;
    }

    ~SConnection()
    {
    if (hasConnection)
    connection_.disconnect();
    if (hasConnection && signal_)
    {
    signal_->disconnect(connection_);
    }
    }

    private:
    bool hasConnection = false;
    Connection connection_;
    Signal<Args...> *signal_;
    };

    template <typename... Args>
    @@ -163,7 +167,7 @@ class Signal
    }
    }

    bool disconnect(Connection connection)
    bool disconnect(Connection &connection)
    {

    for (const auto & item : items_)
    @@ -200,7 +204,7 @@ Signal sig;
    void stuff()
    {
    auto conn = Signal::ScopedConnection(sig.connect([](std::string s, int a){
    auto conn = Signal::ScopedConnection(sig, sig.connect([](std::string s, int a){
    std::cout << s << a << "\n";
    }));
    sig("stuff", 0);
  2. Alia5 revised this gist Dec 14, 2016. 1 changed file with 33 additions and 5 deletions.
    38 changes: 33 additions & 5 deletions Signals.h
    Original file line number Diff line number Diff line change
    @@ -5,7 +5,6 @@
    #include <list>
    #include <memory>


    template <typename... Args>
    class ConnectionItem
    {
    @@ -42,9 +41,15 @@ class ConnectionItem
    bool connected_ = false;

    Slot slot_;


    };

    template<typename... Args>
    class Signal;

    template<typename... Args>
    class SConnection;

    template<typename... Args>
    class Connection
    @@ -62,13 +67,22 @@ class Connection
    return item_->connected_;
    }

    private:
    Item item_;

    void disconnect()
    {
    item_->disconnect();
    }

    private:
    Item item_;
    bool operator==(const Item &item)
    {
    return item == item_;
    }

    friend class Signal<Args...>;
    friend class SConnection<Args...>;

    };

    template<typename... Args>
    @@ -143,12 +157,26 @@ class Signal

    void operator()(Args... args)
    {
    removeDisconnected();
    for (const auto & item : items_)
    {
    (*item)(args...);
    }
    }

    bool disconnect(Connection connection)
    {

    for (const auto & item : items_)
    {
    if (connection == item)
    {
    connection.disconnect();
    removeDisconnected();
    return true;
    }

    }
    return false;
    }

    private:
    @@ -191,7 +219,7 @@ int main()
    sig("The answer: ", 42);
    conn.disconnect();
    sig.disconnect(conn);
    return 0;
  3. Alia5 revised this gist Dec 14, 2016. 1 changed file with 5 additions and 0 deletions.
    5 changes: 5 additions & 0 deletions Signals.h
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,11 @@
    #ifndef SIGNALS_H
    #define SIGNALS_H

    #include <functional>
    #include <list>
    #include <memory>


    template <typename... Args>
    class ConnectionItem
    {
  4. Alia5 created this gist Dec 14, 2016.
    195 changes: 195 additions & 0 deletions Signals.h
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,195 @@
    #ifndef SIGNALS_H
    #define SIGNALS_H

    template <typename... Args>
    class ConnectionItem
    {
    typedef std::function<void(Args...)> Slot;
    public:
    ConnectionItem(Slot slot) : slot_(slot)
    {
    connected_ = true;
    }

    ~ConnectionItem()
    {
    connected_ = false;
    }

    void operator()(Args... args)
    {
    if (connected_ && slot_)
    slot_(args...);
    }

    bool isConnected() const
    {
    return connected_;
    }

    void disconnect()
    {
    connected_ = false;
    }

    private:

    bool connected_ = false;

    Slot slot_;

    };


    template<typename... Args>
    class Connection
    {
    typedef std::shared_ptr<ConnectionItem<Args...>> Item;
    public:

    Connection(Item item) : item_(item)
    {

    }

    bool isConnected() const
    {
    return item_->connected_;
    }

    void disconnect()
    {
    item_->disconnect();
    }

    private:
    Item item_;
    };

    template<typename... Args>
    class SConnection
    {
    typedef Connection<Args...> Connection;
    public:

    SConnection()
    {

    }

    SConnection(Connection connection) : connection_(connection)
    {
    hasConnection = true;
    }

    ~SConnection()
    {
    if (hasConnection)
    connection_.disconnect();
    }

    private:
    bool hasConnection = false;
    Connection connection_;
    };

    template <typename... Args>
    class Signal
    {
    typedef std::shared_ptr<ConnectionItem<Args...>> Item;

    public:

    typedef std::function<void(Args...)> Slot;
    typedef Connection<Args...> Connection;
    typedef SConnection<Args...> ScopedConnection;

    Signal()
    {

    }

    ~Signal()
    {
    for (const auto & item : items_)
    {
    item->disconnect();
    }
    items_.clear();
    }

    template <typename SlotF>
    Connection connect(SlotF&& slot)
    {
    Item item = std::make_shared<ConnectionItem<Args...>>(std::forward<SlotF>(slot));
    items_.push_back(item);
    return Connection(item);
    }

    //Binding with placeholders is tedious...
    //Don't want i.e. this: sig.Connect(std::bind(&DummyObject::test, this, std::placeholders::_1, std::placeholders::_2));
    template<class O, typename R, typename ... A>
    Connection connect(O* o, R(O::*f)(A...))
    {
    Item item = std::make_shared<ConnectionItem<Args...>>(std::forward<Slot>([=](A... args) { return (o->*f)(args...); }));
    items_.push_back(item);
    return Connection(item);
    }

    void operator()(Args... args)
    {
    removeDisconnected();
    for (const auto & item : items_)
    {
    (*item)(args...);
    }

    }

    private:
    std::list<Item> items_;

    void removeDisconnected()
    {
    items_.erase(std::remove_if(items_.begin(), items_.end(), [](Item &item) {
    return !item->isConnected();
    }), items_.end());
    }
    };

    #endif // !SIGNALS_H

    /* EXAMPLE USAGE
    typedef Signal<std::string, int> Signal;
    Signal sig;
    void stuff()
    {
    auto conn = Signal::ScopedConnection(sig.connect([](std::string s, int a){
    std::cout << s << a << "\n";
    }));
    sig("stuff", 0);
    }
    void differentStuff(std::string s, int a)
    {
    std::cout "differentStuff: " << s << a << "\n";
    }
    int main()
    {
    Signal::Connection conn = sig.connect(differentStuff);
    stuff();
    sig("The answer: ", 42);
    conn.disconnect();
    return 0;
    }
    */