June 20, 2005

WCB: Notifications

One of the things planned for parrot was a full notification system. That is, Parrot would support being able to register code that could be called when a PMC was read from, written to, destroyed, when a class instantiated a new PMC, or when an element was inserted into or removed from an aggregate. (Along with a few other things -- methods being added or removed from a class, the MMD tables changing, a PMC being invoked...) Once you register a notification for an action on a thing or class of thing, your notification code gets called whenever that action happens.

The whole point of notifications is to allow you a chance to get your code into the guts of parrot and get access to events you might not otherwise see, and do things in response to those events. There were three big drivers for this one.

First, there's some perl history. One of the common requests in perl 5 (well, not entirely uncommon, at least) is to be able to make the symbol table a tied variable. While there are a number of reasons people want to do this, the biggest is for debugging and monitoring -- they want to know when variables are added or accessed. This is not an unreasonable thing to want to do. Unfortunately it can't be done in perl 5.

Second, there's ruby. Ruby has a number of hooks wedged into it that allow you to install callback functions (well, methods) into a variety of places. These callbacks aren't special-cased -- they're just spots in the various classes that someone added a "Hey, it'd be nice to be notified if X happens" spot you could override. Useful things, and I wanted more.

Finally, there's the issue of instance variables (or slot variables, or attributes, or properties, depending on your language of choice). You know, those things that every object of a particular class has which every language calls by the name some other language uses for something completely different? Right, them. The problem with those is that, to be efficient, you really want to allocate them all as one big wad at the time your object is created, so you can access the instance variables as an array. That's great, until you find that you've added a new instance variable to a class with instantiated objects. With fully static, compiled languages that just can't happen, but with perl, python, and ruby, well... you can do all sorts of things to classes. When code adds (or removes) an instance variable from a class, you need to stop the world and rejig all the instantiated objects.

So... three general cases wherein something happens in the engine and some sort of watching code needs to do something. Three separate systems is awfully wasteful, and leaving people to bodge up an ad-hoc solution (or, more likely, a dozen or so ad-hoc solutions, if history is any guide) goes against one of Parrot's basic philosophies: "If everyone's going to reinvent a wheel, we might as well just provide the damn wheel as part of the stock system"

Hence the notification system. One global system that all this funnels through. If you do X, for any one of a myriad of values of X, then all the watching functions for X get called. The nice thing here is that you can have one unified system with a single interface so you don't need to call functions to register some callbacks, subclass classes for other callbacks, and set global symbols for other callbacks. Instead, one big system, one way to deal with it, fewer hassles to worry about.

Since we're integrating this all together I'll add that this is all was to done, on the callback side of things, with parrot's event handling system. That is, when a notification happened it just fired off an event (potentially a very high priority event) and probably put into the event queue for later processing. Some notifications would be handled immediately, either because they were very high priority (altering object structures, for example), or could be refused (I can't think of anything in particular here, but there's no reason that a callback couldn't decide that some internal notification wasn't allowed), or had to be finished before the notification could be processed (if you were monitoring an object for destruction) so notifications aren't just a set of internal events, but pretty darned close.

On the end of the world doing the monitoring there were going to be a number of different means of monitoring, depending on what was getting watched. A lot of it would be done with vtable method overrides, some with a set of permanent monitoring queues, and a handful with special-purpose checking code.

It would've been pretty darned swell. Ah, well, maybe next time.

Posted by Dan at June 20, 2005 10:35 AM | TrackBack (0)


Why do you say "maybe next time"? Has something changed that makes this impossible to add? Or do you just mean that you haven't added it yet?


Posted by: Matt Fowles at June 20, 2005 05:25 PM

What I mean is maybe on the next VM I'm involved with. I'm done with parrot, so it's not going in there unless I fork the sourcebase, and even then it wouldn't be parrot, it'd be something else.

Posted by: Dan at June 20, 2005 05:37 PM