SigSlot
Tags: cpp
Published: 2019-01-29 09:57:08

---
title: SigSlot
published: true
description: A C++ library for signalling and slotting
tags: cpp
---
## SigSlot Introduction

SigSlot is a library I adopted several years ago as a solid implemention of the "[Observer Pattern](https://en.wikipedia.org/wiki/Observer_pattern)" in C++.

It's available on [GitHub](https://github.com/dwd/sigslot), is free to use, and consists of a single small header file. It supports classical observer patterns with lambda and pointer-to-member connections, and also has support for use as awaitable objects in coroutines.

## A little history

Originally, such things were difficult if not impossible to write in C++, and the most common implementations were either non-standard or relied on specialist preprocessors.

The essential concept is that you have a signal object:

```c++
sigslot::signal0<> my_signal;
```

... which other things can listen to:

```c++
my_signal.connect(this, &MyListener::slot);
```

... and the signal can then emit:

```c++
my_signal.emit(); // Calls its listeners.
```

Sarah Thompson wrote the original SigSlot, having decided that the new "ISO C++" standard had sufficient flexibility in the templating language to support the concept - and indeed, it did. She was, as I understand it, explicitly trying to mirror Qt's signal and slot preprocessor.

But ISO C++ - that's C++03, in modern terms - lacked a number of useful features that would make the programmer's life smoother. Sarah's design gave signals parameters - a useful and common feature - but while she could use templates so the type of the parameters didn't matter, she had to use a different template for the different numbers of parameters.

Lambdas didn't exist either, which made for a much more natural fit.

Finally, while Sarah had made the library thread-safe, thread primitives were not covered in C++03, and so several different models needed to be provided for.

Nevertheless, when I came across the library I was pretty impressed with the simplicity - a single header file contains the entire library, and it's simple to use. So I updated things a bit - in no small part in order to learn the new (to me) C++11.

## SigSlot C++11

When C++11 was widely available (in 2014), I took Sarah's SigSlot library and updated it with several features from the newer standard.

First, I used "variadic templates", which meant that there was now a single "signal" template no matter what the number or type of arguments the signal took.

Second, I gave it support for lambdas as well as the (somewhat obscure) pointer-to-member syntax.

I didn't do threading, and I later noticed other things could have been improved too. Still, it was handy, and the library shrank a lot. While the library was always a single header file, by using a bit of C++11, I shrank it from 2,500 to just over 500 lines of code.

## And Now, C++17...

My last changes have been to introduce features from C++14 and C++17, as well as go over and polish some of the C++11 bits I'd missed.

The first thing to go was the different threading models - I'm now using C++11 thread primitives, and as a result, the last remaining wart in the usage has gone. So, too, did some of the templates - without the different threading models, there was no need for some of the template hierarchy (and if fact I'd missed some simplifications back in 2014).

I also added some coroutine support - this runs on both Windows using MSVC, and UNIXes using CLang. Despite adding about 100 lines of coroutine support, the library is still smaller - just 430 lines now.

Using the library hasn't really changed much since Sarah's version - indeed, this version is closer to hers than to my C++11 version in usage in some ways. In others, though, it's markedly different.

```c++
// Only one template, parameters are signal arguments:
sigslot::signal<int> my_signal;

// ...using lambdas, for example:
my_signal.connect(this, [this](int i){
  std::cout << "I was signalled with " << i << std::endl;
});

// Emitting is by either emit(...) or simply calling the signal:
my_signal(4);

// Or, do a coroutine:

coroutine_type<int> coroutine() {
  int i = co_await my_signal;
  co_return i;
}

auto c = coroutine();
// This awaits, so stops immediately.
my_signal.emit(5);
// Now it's continued and is ready to return its value:
std::cout << "I was signalled with " << c.get() << std::endl;

```

There are more extensive examples in the source tree, including examples for both classical and coroutine based signals which compile clean on both UNIX and Windows.

## Why?

Other signal/slot libraries exist - Boost has one, for example. So why do I persist with this one? Partly, it's the small, neat implementation - a design which predates any of my involvement.

But a small library like this is great for me to learn the newer features of C++. It's a fun playground for me, and one that yields useful code. I use SigSlot extensively in my XMPP Thing, Metre.

Feel free to play with it - or use it, even better - it has copyright disclaimed (ie, it's as close to "public domain" as it's possible to get in modern copyright law), and it's available at [GitHub](https://github.com/dwd/sigslot).