Jump to content

Statically-typed event sink


mindplay.dk
 Share

Recommended Posts

I just thought of a way to implement a statically-typed event sink in PHP - check it out:

http://www.tehplayground.com/#hh9WpisbY

This has a couple of interesting properties - primarily the fact that you can register listeners without passing a class-name or method-name as a string, but also the type-hints would get you IDE support, e.g. auto-complete and safe refactoring in PhpStorm.

I'm using a "hack" to delay auto-loading as well - it turns out, by parsing the type-hint with a regular expression applied to the string-representation of a ReflectionParameter (of the registered closure) you can avoid auto-loading until the registered closure actually gets called.

In other words, you can register listeners without auto-loading the class that implements the message it's listening for - that is, $sink->register(function(Foo $foo) {}) will not cause class Foo to auto-load, which means you could register all your global listeners of every module on start-up without the overhead of loading any additional classes.

I don't think this really fits with the existing concept or architecture in ProcessWire, but it seems like an extremely powerful idea, and I figured, if somebody is going to find this idea useful, this might be the right place to post it.

Anyhow, there it is :-)

  • Like 4
Link to comment
Share on other sites

I've written probably three dozen event sink prototypes over the past 6-7 years, and I think I may have finally found what I'm looking for.

Taking it one step further, check this out:

http://www.tehplayground.com/#dpQwxg8wF

The submit() method now (optionally) accepts a closure that produces the actual event - this allows for even more "laziness", since it can check if anybody is listening before the event is even created. (Because this is done by constructing the actual event object inside the event sink, this will only work for event objects with empty constructors, but I have the opinion that event constructors should always be empty, so I'm happy with that, and the performance advantage here could be huge.)

I also made it possible for listeners to return an event object, and the returned event will be broadcast immediately.

And above all, it's still simple :-)

  • Like 1
Link to comment
Share on other sites

Being able to return another event effectively makes it possible to write "recursive" events, as demonstrated in the example - with the added advantage that this happens in a do-while loop, which means it effectively works like recursion, but isn't... which means (potentially big) memory savings too, since the call-stack won't get any deeper from doing recursion - the call-stack will unwind after each "recursion", freeing up memory as it goes.

(That also potentially means it could be a lot harder to debug, and obviously there is much more work to do here - like an event history and call-stack for debugging purposes, but with the upshot of being able to turn it off in a production environment...)

Link to comment
Share on other sites

@mindplay

I've been hacking at this on "teh playground" and quite like it. Here is a hacked take at extending your idea (with more of an Événement naming scheme as I'm more familiar with it.)

- Functions return $this so you can chain calls.

- Event sinks have an invocation lifespan - (you can setup a one-shot sink, n-shot or infinite sink as required.)

- If a sink returns an event, it is stacked up for handling, allowing multiple sinks for an event.

I'm not sure what you intended to happen in the case of multiple sinks for an event but I found that when the first sink returned a new event, it was preventing the second sink getting a chance to handle the initial event.  That could be totally valid, effectively allowing the sink to mutate the event as it passes through but I decided to try it with a stack to give every sink the chance at seeing the event.

Either way. this is pretty interesting. Thanks!

  • Like 1
Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...