voile.handler
Common Handler type
- template
DelegateTypeOf
(F) if (isCallable!F) - template
DelegateTypeOf
(alias F) if (isCallable!F) - template
isCastableDelegate
(aFunc, bFunc) - struct
Handler
(F) if (isCallable!F && (is(ReturnType!F == void) || is(ReturnType!F : bool))); - Generic
Handler
複数のコールバックを登録し、同じ引数でまとめて呼び出すことのできる構造体です。 コールバックには以下の種類のデータを使用できます。- 関数ポインタ
- デリゲート
- opCallを持つ集合型(class, struct, union, interface)のインスタンス
- core.thread.Fiber
- std.concurrency.Tid
- OutputRange
- 接続:connect関数または
~=
演算子にて、コールバックを追加することができます。- connect関数の戻り値はハンドラ内部でコールバックを管理しているプロシージャIDです。
- singleShotConnectで、一度だけ実行した後に自動で切断することも可能です。
- connectした順番で呼び出しが行われます。
- 切断:disconnect関数によって、コールバックを削除することができます。
- プロシージャIDを指定して切断することも可能です。
- 一度切断されたコールバックのプロシージャIDは使用できません。
- 実行:emit関数または
()
演算子にて、コールバックを一斉に呼び出すことができます。- 関数ポインタを接続した場合、関数ポインタを呼び出します。
- デリゲートを接続した場合、デリゲートを呼び出します。
- 集合型のインスタンスを接続した場合、インスタンスのopCallを呼び出します。
- Fiberを接続した場合、Fiberのcallを呼び出します。Fが
void delegate()
の場合だけ有効です。 - OutputRangeを接続した場合、OutputRangeのputを呼び出します。Fが
void delegate(T)
のとき、isOutputRange!(Range, T)
の場合だけ有効です。
Note:- 実行中に接続・切断ができますが、そのとき実行時にコールバックのリストを複製してから呼び出しているため、 途中操作での接続・切断は反映されません。
- ハンドラは複製することができません。複製したい場合は、スライスでコールバックへアクセスすることができますので、 明示的にディープコピーを行ってください。その際には、オブジェクトの寿命管理には注意して下さい。
- ハンドラでコールバックを保持し続ける限り、コールバックに関連するデータ(例えばデリゲートのコンテキスト)は GCで解放されなくなります。
- 一方でコールバックに関連するデータを手動で破棄した場合には、ハンドラの呼び出しで破棄済みのデータにアクセスする 恐れがあります。ハンドラからの切断を行ってからデータを破棄してください。
- emit関数は、ハンドラのテンプレートパラメータで指定したFの型により、属性を指定できます。
例えば
とすると、emit関数にもnothrow属性がつきます。Handler
!(void delegate() nothrow) - emit関数の戻り値は、ハンドラのテンプレートパラメータで指定したFの戻り値と同じです。ただし、以下の型限定です。
- void: 戻り値を返しません。
- bool: コールバックすべてがtrueを返した場合に、emit関数もtrueを返します。 コールバックが一つでもfalseを返した場合、それ以降コールバック呼び出しを行わず、emit関数もfalseを返します。
Examples: コピー禁止・ムーブ可import std.algorithm: move; Handler!(void delegate()) h1; Handler!(void delegate()) h2; static assert(!__traits(compiles, h2 = h1)); static assert(__traits(compiles, h2 = h1.move()));
Examples:int val; Handler!(void delegate(int test)) h; h.singleShotConnect((int test) { val = test; }); h(100); assert(val == 100); h(200); assert(val == 100);
- RetType
emit
(Args args);
const RetTypeemit
(Args args);
shared const RetTypeemit
(Args args);
aliasopCall
= emit; - Proc
toConnectable
(Func)(auto ref Func fn)
if(is(typeof(toDelegate(fn))) && isCastableDelegate!(Proc, DelegateTypeOf!Func)); - Proc
toConnectable
(Func)(Func tid)
if(is(Func == Tid)); - Proc
toConnectable
(Range)(Range r)
if(Args.length == 1 && isOutputRange!(Range, Args) && !isCallable!Range && (is(Range == class) || is(Range == interface) || isPointer!Range) && is(typeof(() { Range tmp; if (!tmp.empty) { } } ))); - Proc
toConnectable
(Func)(Func fib)
if(is(Func : Fiber)); - alias
HandlerProcId
= ProcList.Iterator; - HandlerProcId
connect
(Func)(auto ref Func fn)
if(is(typeof(toConnectable(fn)))); - ConnectParameters:
Func fn delegate, function, Tid, Object( has opCall ), Fiber, OutputRange(class or interface or T*, and has empty method) - HandlerProcId
singleShotConnect
(Func)(Func fn)
if(is(typeof(toConnectable(fn))));
voidopOpAssign
(string op, Func)(Func dg)
if(op == "~" && is(typeof(connect(dg))));
aliasput
= connect; - 一度だけ実行するハンドラを接続する
- HandlerProcId
connectedId
(Func)(Func fn)
if(is(typeof(toConnectable(fn)))); - void
opOpAssign
(string op, ProcContainer)(auto ref ProcContainer procs)
if(op == "~" && is(ForeachType!(typeof(ProcContainer.init[])) : Proc)); - ConcutParameters:
ProcContainer procs other Handler - auto
opSlice
(); - const pure nothrow bool
opCast
(T)()
if(is(T == bool)); - void
disconnect
(Func)(Func fn)
if(is(typeof(toConnectable(fn))));
voiddisconnect
(Func)(Func id)
if(is(Func == HandlerProcId));
voiddisconnect
(Func)(Func hnd)
if(is(Func == Handler));
aliasremove
= disconnect; - void
insertAfter
(Func)(ProcList.Range r, Func fn)
if(is(typeof(toConnectable(fn))));
voidinsertAfter
(Func)(HandlerProcId needleid, Func fn)
if(is(typeof(toConnectable(fn))));
voidinsertAfter
(Func)(Func needle, Func fn)
if(is(typeof(toConnectable(fn)))); - void
insertBefore
(Func)(ProcList.Range r, Func fn)
if(is(typeof(toConnectable(fn))));
voidinsertBefore
(Func)(HandlerProcId needleid, Func fn)
if(is(typeof(toConnectable(fn))));
voidinsertBefore
(Func)(Func needle, Func fn)
if(is(typeof(toConnectable(fn)))); - pure void
clear
();