• Stars
    star
    14
  • Rank 1,438,076 (Top 29 %)
  • Language
    C++
  • License
    MIT License
  • Created about 5 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Lightweight C++ Signals and Slots implementation

sling

MIT license GitHub issues Buy me a coffee

sling is a lightweight C++ implementation of signals and slots. A slot is essentially a callback wrapper which can be created from different kinds of callable entities. Slots can be connected to a signal, and they get notified when the signal is emitted.

Installation

Being a header-only library, you can just include it in your project. Requires compiler support for C++11 or later.

Usage

Creating signals

sl::Signal<> sig0;            // signal without parameters.
sl::Signal<std::string> sig1; // signal with one parameter (std::string).
sl::Signal<double, int> sig2; // signal with two parameters (double and int).

Connecting slots

sl::Signal<int> sig;

Connect slots created from lambda expressions.

sig.connect(sl::Slot<int>([](int x) {}));

Connect slots created from regular functions.

void foo(int x) {}
sig.connect(sl::Slot<int>(foo));

Connect slots created from object member functions.

class Foo
{
public:
    void bar(int x) {}
    void baz(int x) const {}
    virtual void qux(int x) {}
    static void corge(int x) {}
};

Foo foo;
sig.connect(sl::Slot<int>(&foo, &Foo::bar));
sig.connect(sl::Slot<int>(&foo, &Foo::baz));
sig.connect(sl::Slot<int>(&foo, &Foo::qux));
sig.connect(sl::Slot<int>(Foo::corge));

Connect slots created from object instances implementing operator ().

struct Bar
{
    void operator () (int x) const {}
};

sig.connect(sl::Slot<int>(Bar()));

Disconnecting slots

void foo(int x) {}
sl::Signal<int> sig;

Disconnect using the slot interface.

sl::Slot<int> slot(foo);
sig.connect(slot);
slot.disconnect();

Disconnect by passing a reference or a pointer to the slot.

sl::Slot<int> slot(foo);
sig.connect(slot);
sig.disconnect(slot); // or sig.disconnect(&slot);

Disconnect by passing the slot key returned on signal connection.

sl::SlotKey key = sig.connect(sl::Slot<int>(foo));
sig.disconnect(key);

Disconnect all slots.

sig.clear();

All slots are automatically disconnected when the signal they are connected to goes out of scope. Similarly, slots are automatically disconnected from signals when they go out of scope.

Slots are suitable as public class members, as they are automatically disconnected when the class instance they belong to goes out of scope. In addition, this allows private member functions to be specified as slot callbacks.

class Baz
{
private:
    void bar(int x) {}
public:
    sl::Slot<int> onBar{this, &Baz::bar};
};

Baz b;
sig.connect(b.onBar);

Emitting signals

sl::Signal<int> sig;
sig(1); // or sig.emit(1);

Copying and moving

Signal copying is disabled as I have not found an intuitive behaviour for this operation. Moving signals is allowed and it transfers all connected slots to the new signal. The moved signal is left in a valid state, as if newly constructed.

Slot copying is permitted and the result of the operation is a slot having a copy of the source slot callback. However, the new slot is not connected to the signal the original slot is connected to, if any. When moving slots, the new slot basically replaces the old one. If the moved slot is connected to a signal, it is disconnected first, and the new one is connected to that signal. The moved slot is left in a valid state, having no callback. A new callback can be assigned using the setCallback method.

Thread safety

The library does not guarantee thread safety in its current state. I am considering making it thread safe in the future.

Contributing

Contributions in the form of pull requests, issues or just general feedback, are always welcome.
See CONTRIBUTING.MD.

License

Copyright (c) 2019 Adrian-George Bostan.

This project is licensed under the MIT license. See LICENSE for more details.