Standard Event Driven Object Library for D

Christopher Wright dhasenan at gmail.com
Tue Apr 1 07:45:52 PDT 2008


Brian White wrote:
> What do others think of this?
> 
> -- Brian

% toc:
% events
% events in stdlib

\section{events}

I'm also interested in the subject, though I haven't had a chance to 
work on it. (I'm trying to get a full agile setup in D; I've done mock 
objects, an xUnit, and dependency injection system so far. Events are on 
my list, but not yet accomplished.) What sort of API would you want?

Jeremy Miller's event system (in C#) looks like:
interface IListener<T>
{
	void Handle(T subject);
}

class EventPublisher
{
	public void AddListener(object o){}
	public void Raise<T>(T subject){}
}

That does a simple O(n) loop on each event to see if any of the 
registered objects can be converted to an IListener<T>. This is 
convenient because any class can listen to an arbitrary number of 
events. It is inconvenient that publishing an event is linear in the 
number of total listeners rather than the number of listeners for that 
event. You probably could do some reflection to find which events an 
object listens to, though. (I wouldn't particularly want to do that in 
D1, though.) Also, you can't use structs to receive events, if you 
translate it to D.

The other issue is that you need to create a class (or probably struct) 
for every event you use.

CAB and Ayende Rahien's event broker both use strings to describe which 
event you care about. This means you have fewer UDTs, but then you're 
using strings, which have zero validation. It also makes it a bit more 
ugly to provide arguments. Jeremy Miller's system has the best 
validation -- it's your code that won't compile if you don't listen to 
the event properly. The worst you could do is send the wrong event and 
have the wrong stuff happen rather than send an event and have nothing 
happen -- the former is probably a bit easier to debug. Using strings as 
event URIs has a benefit that you can use hashing. However, it requires 
more configuration.

Events are easier to work with if you use hooks into a dependency 
injection tool to wire them up. There is, at last count, exactly one 
dependency injection library for D, and that's mine. Dconstructor 
doesn't currently support interceptors that run after the construction 
of an object. But for event listeners, you could still put a line in the 
constructor:

// if you're using dependency injection
this (EventRegistrar events)
{
	events ~= this;
}

// if you're using the singleton pattern
this ()
{
	EventRegistrar.instance() ~= this;
}


\section{events in stdlib}

I'm not sure that sockets with events are appropriate for the standard 
library. You'd need, at a minimum, one extra thread that the sockets 
operate on, unless you still had a socket set that you polled. This 
means that any application that used a socket would need to concern 
itself with thread safety.

This would be okay if you had two classes for sockets in the stdlib, say 
PollingSocket and EventSocket. But still, I would want to control my 
threads. You could instead have a static method on EventSocket that 
polls each EventSocket (or uses a SocketSet to do so), and if any socket 
that has something to report, it will publish the appropriate event.

Still, I'm not sure something like this belongs in the standard library 
quite yet.



More information about the Digitalmars-d mailing list