/*! \mainpage NOTE: Due to incomplete support for the D programming language in Doxygen, the documentation behind the links above is both incomplete and incorrect. If you want to be sure, consult the source code. This page contains manually generated documentation to make up for that.

Contents

  1. \ref intro
  2. \ref management
  3. \ref connections
  4. \ref signals
    1. \ref blockingsignals
    2. \ref freesignals
  5. \ref slots
    1. \ref private
    2. \ref freeslots
  6. \ref bothplease
  7. \ref interfacesmixins
  8. \ref examples
  9. \ref status
  10. \ref changelog
\section intro Introduction The "signal and slot" mechanism is a type-safe alternative to using call-back functions through function pointers. It can be used to equip objects and program components with an interface through which the components can be tied together into systems that were not envisioned at the time of design of the components. The mechanism has its widest application in GUI programming. For further information see the file Resources.txt. \section management The Point of Management Obviously a signal can be implemented as a class or struct with a container for delegates. Connections can then be made by adding delegates (pointers to member functions) to the container, and when the signal is called to emit, it calls all the member functions registered with the signal. The member functions are behaving like slots, and there is no distinction between slots and member functions. The connection can be made from any place where both the signal and the slot are in scope. Breaking (disconnecting) an existing connection happens by removing the appropriate delegate from the container in the appropriate signal, so the same information is needed as at the time when the connection was established. An implementation of this design is provided by Andy Friesen in listener.d. The problem is, that when an object to which signals are connected is destructed, the connection must be broken in order to prevent an access violation. So slots need to be aware of existing connections just as well as signals are. The matter of disconnection and destruction is delicate in D, because the general rule is that no references to other objects may appear in destructors (see the specs) because finalisation is non-deterministic. In other words, the referred to objects may not exist any more, again resulting in an access violation. Apart from gracefull destruction, there are other situations in which the receiving end may want to break a connection. One of them is that in D, objects that are not in use anymore will not be garbage collected if it still has connections to it, because they count as a reference. So you may want to give objects that contain signals and/or slots a method that shuts down all connections to and from it when you no longer need it. In the following, we will cover different aspects of this implementation of managed signals and slots. We will start with making connections, because signals and slots are connected more often than they are defined. \section connections Connections Both Signals and Slots have a method called connect(), and it does not matter which one you call. So if there is a signal in okButton called pressed and a slot in areYouSure called yes, the following are equivalent: \code okButton.pressed.connect(areYouSure.yes); areYouSure.yes.connect(okButton.pressed); \endcode Multiple identical connections may exist, which causes a slot to receive the same signal as many times per emission as connections were made. This is in accordance with the behaviour of Qt. As they say at Trolltech: "syntax matters". We can mimmic the syntax for making a connection that Trolltech advocates. In fact our syntax is even less verbose than theirs, and thanks to the (limited) support for real-time type information (RTTI) in D, we can do without template functions. By not using a macro, our users need not bother about the order of arguments either. Again, the following are equivalent, to each other as well as to the above calls: \code import dcouple.connect; connect(okButton.pressed, areYouSure.yes); connect(areYouSure.yes, okButton.pressed); \endcode Signals and slots may have arguments, by which information can be transmitted between program components. When trying to establish a connection, the signal and slot must be compatible in the number and types of their arguments. When calling the connect() member function on incompatible signals and slots, compilation will not succeed. When calling the free connect() function this way, a run-time warning will be given, and no connection will be made. For example, if there is a counter with a signal called contentsChanged with an int argument, and areYouSure.yes has no arguments, \code counter.contentsChanged.connect(areYouSure.yes); \endcode will result in a compile error along the lines of test.d(87): function connect (Slot s) does not match argument types (Slot ) and \code connect(counter.contentsChanged, areYouSure.yes); \endcode will complain during program execution like dcouple WARNING: %CounterWidget.Signal!(int) is incompatible with %DialogWidget.Slot!(); not connected. (Sorry, no line number...) The indication of argument mis-match works with build-in types as well as custom classes, at least in this run-time case. We would have liked to provide a file and line number and use object names in stead of class names, but currently this is the best we can do. Connections can be removed by calling one of the disconnect() functions analogously. This is taken care of automatically when a signal or slot is destructed. \section signals Signals When a class is to be equipped with a signal, it is advised to make it inherit the SignalManager interface, and mix in its implementation. \code class Widget : SignalManager { mixin SignalManagement; \endcode This provides better run-time warnings when an incompatible connection is attempted to be made, and, more importantly, allows the object to be deleted in a controlled way, including its signals. The signal itself is defined by a templated member like so: \code Signal!(int) contentsChanged; \endcode Naturally, it must be newed in the constructor. \code this() { contentsChanged = new Signal!(int)(this); } \endcode By passing the this pointer in the signal constructor, the signal marks itself as being owned by the manager (Widget in this case) and registers itself with it. The signal can then be emitted by calling \code /*...*/ contentsChanged.emit(myVal); /*...*/ } \endcode \subsection blockingsignals Blocking Signals An object that is a SignalManager can temporarily be made to turn off its ordinary signals by means of the signalsBlocked(bool) property. \code Widget w = new Widget; /* Set connections etc. */ w.signalsBlocked = true; contentsChanged.emit(myVal); // The signal is not emitted. \endcode For the rare occasion that a signal must ignore the block of its owner, it can be defined as a NonBlockingSignal. Such a signal can be used to emit a destroyed signal in the destructor, for example. \code class Widget : SignalManager { mixin SignalManagement; NonBlockingSignal!() destroyed; this() { destroyed = new NonBlockingSignal!(this); } ~this() { destroyed.emit(); deleteSignals(); // See below. } } \endcode \note When you provide a destructor in a managing class, you are replacing the one that SignalManagement provides. You must therefore duplicate the contents from that destructor (with \c deleteSignals(); something like SM.~this(), where \c SM identifies the mixin, does not seem to work yet.). \warning One should be careful to rely on signals in a destructor to be emitted. Garbage collected objects have no deterministic finalisation, and therefore the signal (\c destroyed in this case) may have been deleted before the owner gets deleted (\c Widget in this case). It will work as intended if you delete the owner explicitly however. \subsection freesignals Free Signals A signal does not need to be owned, for example if it lives outside a class. \code Signal!() freeSignal = new Signal!()(null); \endcode A free signal can not be blocked through its owner of course. Blocking signals individually is not supported yet. \section slots Slots Slots are managed as well. \code class Widget : SlotManager { mixin SlotManagement; \endcode \anchor careful_free_slots The importance of a managing owner is more apparent for slots than for signals. If a slot outlives its owner (due to the non-deterministic finalisation of garbage collected objects) they still receive signals and it has been shown that the member functions with which they are associated may still be operational despite the object having been destructed. SlotManagement takes care that connections are broken and that all relevant actors leave the scene at the right moment. A slot is defined in the same way as signals are: \code Slot!(int) set; \endcode The slot should be related to one of the member functions at the time of initialisation: \code this() { set = new Slot!(int)(this, &setVal); } \endcode where \c setVal is the member function that you want to be called when a signal arrives, \code void setVal(int i) { my_int = i; } private: int my_int; } \endcode The function reference on which a slot is created may be to any of the following \warning It is important that the slot object does not outlive the function that it references. Although you will be able to construct a slot that references a non-static nested function, it is not safe to do so. A segmentation fault will be the result if a slot attempts to call a function that has been garbage collected. For the same reason, when constructing a slot on a member function, that slot must be owned by the object (implementing a SlotManager) that has the member function. The destructor of the owner will remove the slot before the member function becomes garbage. When the nested function goes out of scope, it may be collected as garbage before the slot is destructed, which will result in a segmentation fault if the slot receives a signal at this moment. \subsection private Removing Duplicate Functionality in the API In the above example, the class interface has two methods for accomplishing the same thing. Calling setVal(5) is equivalent to calling set(5). To simplify the API, \c setVal() may be made private. \subsection freeslots Free Slots (Experimental) Analogous to free signals, a slot can live outside a class. \code void message() { printf("You can turn a free function into a slot as well.\n"); } void main() { Slot!() freeSlot = new Slot!()(null,&message); Signal!() freeSig = new Signal!()(null); connect(freeSig, freeSlot); freeSig.emit(); } \endcode As mentioned \ref careful_free_slots "above", there is reason to be carefull with free slots, because their destruction is not linked with the life span of the function that they reference. It is best to disconnect free slots before their referenced function goes out of scope. There is one scenario in which a segmentation fault will happen even when only static functions are referenced. Suppose a special signal has been implemented (inheriting from some Signal template) that is guaranteed to emit when its owner (or itself) is being destructed. When such a signal remains alive until the program terminates, it will emit during the final garbage collection. Connected slots that are still alive will receive the signal, and call their referenced functions. But, even static functions are being collected at this point, and may have been collected before the signals and slots. As a result, the program may terminate with a segmentation fault. In the future, free slots may automatically register with a global static SlotManager. Before termination of the program, this manager may be called to disconnect all "free" slots, and thus prevent the segmentation fault. \section bothplease Both Signals and Slots Classes that own both signals and slots should inherit from \c SignalSlotManager and mix in the \c SignalSlotManagement implementation. Currently, dcouple supports signals and slots with up to seven arguments. More can easily be added, although their practicality can be questioned. \section interfacesmixins Extending Legacy Classes \note Currently there is a bug in dmd involving interfaces. The following will be possible in the future. Courtecy the concepts of interfaces and mixins of the D programming language, this implementation has the interesting property that existing (probably third-party) classes can be equipped with signals and slots without interfering with their inheritance tree. Given the following legacy class \code class ImportantClass : DeepInheritanceHierarchy { /*...*/ P importantProperty() { return _prop; } void importantProperty(P prop) { _prop = prop; } private: P _prop; } \endcode A class like this can be extended in a straight forward manner, for example \code class ExtendedClass : ImportantClass, SignalSlotManager { mixin SignalSlotManagement; Signal!() propertyChanged; Slot!(P) updateProperty; this() { propertyChanged = new Signal!()(this); updateProperty = new Slot!(P)(this,&importantProperty); } void importantProperty(P prop) { super.importantProperty(prop); propertyChanged.emit(); } } \endcode Without (working) interfaces, SignalSlotManager must be a class, and therefore positioned at the root of the inheritance tree. \section examples Examples More examples can be found in the examples directory. \section status Project Status This framework is in early development. One of the aspects that have not been considered is thread-safety. Feedback is appreciated! Any volunteers to benchmark against other implementations? \section changelog Changelog */