# signals-rt **Repository Path**: mirrors_GerHobbelt/signals-rt ## Basic Information - **Project Name**: signals-rt - **Description**: General purpose modern C++ Signal-Slot providing ease of use, flexibility and extremely high performance aiming to replace traditional interfaces in real-time applications - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-10-23 - **Last Updated**: 2026-05-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Signals For design choices see [this blog post](https://dreamdota.com/c-17-signals/) ## Why Yet Another Signal-Slot Library? This library is optimized for video games (and probably other low-latency applications as well). Interestingly, even though the observer pattern is generally useful, it has never been standardized in C++, which leads to the never-ending attempts at improvements by curious people. Many signal-slot libraries do not focus on performance, e.g. `boost::signals2` [invocation can be 90x more expensive than a simple function call](https://stackoverflow.com/questions/22416860/is-boostsignals2-overkill-for-simple-applications). There are many similar libraries - such as [jl_signal](http://hoyvinglavin.com/2012/08/06/jl_signal/), [nuclex signal/slots](http://blog.nuclex-games.com/2019/10/nuclex-signal-slot-benchmarks/) and [several dozens more](https://github.com/NoAvailableAlias/signal-slot-benchmarks). My work is based on a previous [research](https://github.com/TheWisp/ImpossiblyFastEventCPP17) which focused on the syntax and performance improvements brought by a C++17 feature - `template`. This library is a combination of modern C++ exploration, system programming and data-structure design. It aims to become feature-complete like `boost::signals`, yet extremely light-weight - both run time and memory footprint - in order to replace _interface_ or `std::function` based callbacks. `signal` emission is **faster** than virtual function calls. Compared to virtual calls, `signal` calls only take between 22% and 77% of the time, depending on the number and the level of randomness of classes and objects. ## Design Choices ### Direct (Blocking) Calls In game systems, the logic flow often consists of many fast and weakly ordered function calls. Asynchronous calls are rather the exceptions than the default. Thread-safe calls add additional costs, thus should be the exceptions rather than the default. ### Optimized for Emission Latency is the bottleneck. ### O(1) Connection and Disconnection In a dynamic world, slots (receivers) are often frequently created and destroyed. A linear search removal algorithm can easily become the performance bottleneck, especially when a large number of slots all disconnect at the same time. Removing by swapping with the end mitigates the problem, but the overall time spent removing N slots with a linear search would still be O(N^2). In this library, a slot is removed by marking its index unused, which then gets skipped and cleaned up in the next emission. Benchmarks have shown that the overhead is dominated by memory accessing (cache misses), rather than checking for null (pipeline stalling). ### Safe Recursion and Modification While Iterating Just like direct function calls, recursions can naturally emerge from complex and dynamic behaviors. Furthermore, the signals and slots may be side-effected by their own results! ## Usage Simply include the single header, `signals.hpp`. A C++17 compliant compiler is necessary. Give it a try on [Godbolt](https://godbolt.org/z/_N2_5P)! ### Basics The following example demonstrates how to define, connect and emit a signal. ```cpp // A function callback void on_update(float delta) { } // A member function callback class my_class{ void on_update(float delta) { } }; int main() { // A signal specifying its signature in the template parameter fteng::signal update; // Connects to a function callback update.connect(on_update); // Connects to an object's member function my_class* my_obj = new my_class; update.connect<&my_class::on_update>(my_obj); // Connects to a lambda callback update.connect([](float delta) { }); // Connects to a generic lambda callback update.connect([](auto&&... as) { }); // Emits the signal update(3.14f); delete my_obj; } ``` Signals automatically disconnect from their slots (receivers) upon destruction. ```cpp class button{ public: fteng::signal pressed; }; class my_special_frame { std::vector