英語版
このページの英語版を見る

std.signals

シグナルとスロットはObserverパターンの実装である。 基本的に、シグナルが発信されると、接続されたオブザーバーのリスト(スロットと呼ばれる)が呼び出される。 (スロットと呼ばれる)が呼び出される。
シグナルとスロットの実装はこれまでにもいくつかあった。 このバージョンでは、D言語のいくつかの新機能を利用している。 のいくつかの新機能を利用している。特に 特に、スロットを計測する必要がなくなった。
Bugs:
スロットは、クラスやインターフェイスのメンバ関数を直接参照するデリゲートにしかなれない。 クラスまたはインターフェイスのメンバ関数を直接参照するデリゲートに限る。構造体メンバ関数のような へのデリゲートがconnect()に渡される場合(構造体メンバ関数など)、 構造体メンバ関数、ネストされた関数、COM インタフェース、クロージャなど。 が発生する。
同じシグナルやスロットを操作する複数のスレッドに対しては安全ではない。 またはスロットを操作する複数のスレッドでは安全ではない。
Authors:

ソース std/signals.d

template Signal(T1...)
クラスオブジェクトの中にシグナルを作成するミックスイン。
ミックスインに名前をつけることで、異なるシグナルをクラスに追加することができる。
Examples:
import std.signals;

int observedMessageCounter = 0;

class Observer
{   // 私たちのスロット
    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
{   // 私たちのスロット
    void watch(string msg, int value)
    {
    }
}

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

    int value(int v)
    {
        if (v != _value)
        {   _value = v;
            // 接続されているすべてのスロットを2つのパラメータで呼び出す
            emit("setting new value", v);
        }
        return v;
    }

    // Fooをシグナルにするために必要なすべてのコードを混ぜる
    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;                // o.watch()を呼んではいけない
a.connect(&o.watch);        // o.watchはスロットである
a.connect(&o2.watch);
a.connect(&o3.watch);
a.connect(&o4.watch);
a.connect(&o5.watch);
a.value = 4;                // o.watch()を呼び出す
a.disconnect(&o.watch);     // o.watchはもはやスロットではない
a.disconnect(&o3.watch);
a.disconnect(&o5.watch);
a.disconnect(&o4.watch);
a.disconnect(&o2.watch);
a.value = 5;                // なので、o.watch()を呼んではいけない
a.connect(&o2.watch);
a.connect(&o.watch);        // もう一度接続する
a.value = 6;                // o.watch()を呼び出す必要がある
destroy(o);                 // oをdestroyすると、自動的にdisconnectされるはずだ
a.value = 7;                // o.watch()を呼んではいけない

writeln(observedMessageCounter); // 2
alias slot_t = void delegate(T1);
スロットはデリゲートとして実装される。 slot_tはデリゲートの型である。 デリゲートはクラスのインスタンスに対するものでなければならない。 でなければならない。 構造体インスタンスやネストされた関数へのデリゲートはスロットとして使用してはならない。 をスロットとして使用してはならない。これは、入れ子関数が親関数の変数にアクセスしない場合でも同様である。 親関数の変数にアクセスしない場合でも同様である。
final void emit(T1 i);
接続された各スロットに引数iを渡して呼び出す。 入れ子になった呼び出しは無視される。
final void connect(slot_t slot);
emit()が呼び出されたときに呼び出されるスロットのリストにスロットを追加する。
final void disconnect(slot_t slot);
emit()が呼ばれたときに呼び出されるスロットのリストからスロットを削除する。
final void disconnectAll();
すべてのスロットを切断する。