Events in D
bitwise via Digitalmars-d
digitalmars-d at puremagic.com
Thu Aug 31 09:55:04 PDT 2017
On Tuesday, 29 August 2017 at 05:10:25 UTC, bitwise wrote:
> I needed some C# style events, so I rolled my own.
The following is my current event implementation. I was able to
make it thread safe by including an optional spin-lock. Of
course, that extra spinlock has to be included in every single
event, which has a pointlessly high memory cost, even when no
handlers are attached to the event. Also, having this event call
it's host class back when events are added/removed would require
even MORE wasted memory by storing extra delegates. I've
thoroughly explored the idea of a library-implemented event, and
the downsides are not fixable.
struct Event(Handler, bool atomic = false)
if(is(Handler == delegate) && is(ReturnType!Handler == void))
{
Handler[] _handlers;
static if(atomic)
{
Spinlock _lock;
@disable this(this);
}
ref auto opOpAssign(string op, H)(H handler)
if(op == "+")
{
static if(atomic) auto lk = lock(_lock);
_handlers ~= toDelegate(handler);
return this;
}
ref auto opOpAssign(string op, H)(H handler)
if(op == "-")
{
static if(atomic) auto lk = lock(_lock);
auto del = toDelegate(handler);
foreach(ref handler; _handlers)
{
if(handler == del) {
_handlers = _handlers.remove(&handler -
_handlers.ptr);
break;
}
}
return this;
}
void opCall()(Parameters!Handler args)
{
static if(atomic)
{
Handler[] tmp;
if(_handlers.length <= 64)
{
auto lk = lock(_lock);
size_t sz = _handlers.length * Handler.sizeof;
tmp = cast(Handler[])(alloca(sz)[0..sz]);
tmp[] = _handlers[];
}
else
{
auto lk = lock(_lock);
tmp = _handlers.dup;
}
foreach(ref handler; tmp)
handler(args);
}
else
{
foreach(ref handler; _handlers)
handler(args);
}
}
bool opCast(T : bool)() {
static if(atomic) auto lk = lock(_lock);
return _handlers.length != 0;
}
void clear() {
static if(atomic) auto lk = lock(_lock);
_handlers.length = 0;
}
bool empty() {
static if(atomic) auto lk = lock(_lock);
return _handlers.length == 0;
}
}
More information about the Digitalmars-d
mailing list