Menu

- Learn
- Documentation
  - Language Reference
  - Library Reference
  - Command-line Reference
  - Feature Overview
  - Articles
- Downloads
- Packages
- Community
  - Blog
  - Orgs using D
  - Twitter
  - Forums
  - IRC
  - Community Discord
  - Wiki
  - GitHub
  - Issues
  - Get involved
  - Contributors
  - Foundation
  - Security Team
  - Donate
  - Sponsors
- Resources
  - Tour
  - Books
  - Tutorials
  - Tools
  - Editors
  - IDEs
  - run.dlang.io
  - Visual D
  - Acknowledgments
  - D Style
  - Glossary
  - Sitemap

Search
Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

# std.signals

Signals and Slots are an implementation of the Observer Pattern. Essentially, when a Signal is emitted, a list of connected Observers (called slots) are called.
There have been several D implementations of Signals and Slots. This version makes use of several new features in D, which make using it simpler and less error prone. In particular, it is no longer necessary to instrument the slots.

References A Deeper Look at Signals and Slots
Observer pattern
Wikipedia
Boost Signals
Qt

There has been a great deal of discussion in the D newsgroups over this, and several implementations:
signal slots library
Signals and Slots in D
Dynamic binding -- Qt's Signals and Slots vs Objective-C
Dissecting the SS
about harmonia
Another event handling module
Suggestion: signal/slot mechanism
Signals and slots?
Signals and slots ready for evaluation
Signals & Slots for Walter
Signal/Slot mechanism?
Modern Features?
Delegates vs interfaces
The importance of component programming (properties, signals and slots, etc)
signals and slots
Bugs:
Slots can only be delegates referring directly to class or interface member functions. If a delegate to something else is passed to connect(), such as a struct member function, a nested function, a COM interface, a closure, undefined behavior will result.
Not safe for multiple threads operating on the same signals or slots.
License:
Boost License 1.0.
Authors:
Walter Bright

Source std/signals.d

template `Signal`(T1...)
  Mixin to create a signal within a class object.
  Different signals can be added to a class by naming the mixins.
  Examples:

      import std.signals;

      int observedMessageCounter = 0;

      class Observer
      {   // our slot
          void watch(string msg, int value)
          {
              switch (observedMessageCounter++)
              {
                  case 0:
                      writeln(msg); // "setting new value"
                      writeln(value); // 4
                      break;
                  case 1:
                      writeln(msg); // "setting new value"
                      writeln(value); // 6
                      break;
                  default:
                      assert(0, "Unknown observation");
              }
          }
      }

      class Observer2
      {   // our slot
          void watch(string msg, int value)
          {
          }
      }

      class Foo
      {
          int value() { return _value; }

          int value(int v)
          {
              if (v != _value)
              {   _value = v;
                  // call all the connected slots with the two parameters
                  emit("setting new value", v);
              }
              return v;
          }

          // Mix in all the code we need to make Foo into a signal
          mixin Signal!(string, int);

        private :
          int _value;
      }

      Foo a = new Foo;
      Observer o = new Observer;
      auto o2 = new Observer2;
      auto o3 = new Observer2;
      auto o4 = new Observer2;
      auto o5 = new Observer2;

      a.value = 3;                // should not call o.watch()
      a.connect(&o.watch);        // o.watch is the slot
      a.connect(&o2.watch);
      a.connect(&o3.watch);
      a.connect(&o4.watch);
      a.connect(&o5.watch);
      a.value = 4;                // should call o.watch()
      a.disconnect(&o.watch);     // o.watch is no longer a slot
      a.disconnect(&o3.watch);
      a.disconnect(&o5.watch);
      a.disconnect(&o4.watch);
      a.disconnect(&o2.watch);
      a.value = 5;                // so should not call o.watch()
      a.connect(&o2.watch);
      a.connect(&o.watch);        // connect again
      a.value = 6;                // should call o.watch()
      destroy(o);                 // destroying o should automatically disconnect it
      a.value = 7;                // should not call o.watch()

      writeln(observedMessageCounter); // 2

  alias `slot_t` = void delegate(T1);
    A slot is implemented as a delegate. The slot_t is the type of the delegate. The delegate must be to an instance of a class or an interface to a class instance. Delegates to struct instances or nested functions must not be used as slots. This applies even if the nested function does not access it's parent function variables.
  final void `emit`(T1 `i`);
    Call each of the connected slots, passing the argument(s) i to them. Nested call will be ignored.
  final void `connect`(slot_t `slot`);
    Add a slot to the list of slots to be called when emit() is called.
  final void `disconnect`(slot_t `slot`);
    Remove a slot from the list of slots to be called when emit() is called.
  final void `disconnectAll`();
    Disconnect all the slots.

Copyright © 1999-2023 by the D Language Foundation | Page generated by Ddoc on Mon May 1 15:50:44 2023