Advanced

Here are some optional details if you’re curious about how Siglot works.

Implementing Emitter interface

Siglot stores all connections in an Internal\SignalManager that is stored in the emitter instance. The goal of the Emitter interface is to expose signals of the Internal\SignalManager without exposing a way to emit them from outside the class. This design ensures that signals are only emitted from the class that defines them and its subclasses. The EmitterHelper trait already includes everything needed to implement the Emitter interface. However, if more control is needed, one can refer to the trait’s implementation to manually implement the interface.

Classes in the Internal namespace are not meant to be used directly and may be removed or changed without notice.

Storage of connections

All connections must be stored in the emitter instance in order to share its lifetime. This is transparently achieved by the EmitterHelper trait, but you may need to keep this in mind when dealing with some serialization functions for your emitter class.

Performance

In theory, there is a certain amount of overhead associated with calling a slot function from a signal. This overhead depends on the number of signals in the object and the number of slots connected to the called signal. In practice, this overhead should be less than 10 microseconds and is usually negligible. You can see the benchmark example to try it yourself.

When a slot is called directly, there is no overhead even if it is connected to several signals.

Connecting closures

In order to connect signals to slots, Siglot utilizes closure objects to access related instances and methods through reflection. It is best to use first class callable syntax, as it ensures that the method exists and is visible, resulting in more readable code. Additionally, your favorite IDE will be able to offer autocompletion and static analysis. While it is possible to use the \Closure::fromCallable([$emitter, 'signal']) syntax, it is discouraged due to being less readable.

Providing a closure that does not match a signal or slot function will result in a runtime error.