std.signals
シグナルとスロットは、Observer パターンの実装です。 一言で言うと、Signal が発行されると、接続された Observer (スロットと呼びます) の一覧が呼び出されるという仕組みです。D言語によるシグナルとスロットの実装は幾つか存在しました。 このバージョンは、Dの新しい機能を使うことで、 簡単に間違いなく使えるようになっています。 特に、スロットを明示的に作成する必要がなくなったのがポイントです。
References:
A Deeper Look at Signals and Slots
Observer pattern
Wikipedia
Boost Signals
Qt
Dのニュースグループで沢山の議論と、 幾つかの実装がありました:
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:
スロットとして使えるのは、クラスオブジェクトかクラスオブジェクトへのインターフェイスから 作ったdelegateのみです。他の delegate (構造体のメンバ関数、ネストした関数、 COMインターフェイス名など)が connect() に渡されると、 その時の動作は未定義です。
同じシグナルやスロットを複数のスレッドから同時に操作するのは、 安全ではありません。 Source:
std/signals.d
License:
Boost License 1.0. Authors:
Walter Bright
- クラスオブジェクトの中にシグナルを作るmixinです
異なるシグナルをセットしたいときは、mixinに名前をつけて使います。
Example:
import std.signals; import std.stdio; class Observer { // スロットとして使うメソッド void watch(string msg, int i) { writefln("Observed msg '%s' and value %s", msg, i); } } class Foo { int value() { return _value; } int value(int v) { if (v != _value) { _value = v; // 全てのスロットを二引数で呼び出す emit("setting new value", v); } return v; } // Fooをシグナルにするのに必要なコードを全てmixinする mixin Signal!(string, int); private : int _value; } void main() { Foo a = new Foo; Observer o = new Observer; a.value = 3; // o.watch() は呼ばれない a.connect(&o.watch); // o.watch がスロットとして登録される a.value = 4; // o.watch() が呼ばれる a.disconnect(&o.watch); // o.watch の登録解除 a.value = 5; // 従って o.watch() は呼ばれない a.connect(&o.watch); // 再度connect a.value = 6; // o.watch() は呼ばれる delete o; // oを破棄すると自動的にdisconnectされる a.value = 7; // o.watch() は呼ばれない }
表示はこうなります:Observed msg 'setting new value' and value 4 Observed msg 'setting new value' and value 6