VM Interface for message oriented programming operations.
Class VMSlot( [name] )
name | The name of the mesasge managed by this VMSlot. |
The VMSlot instance is a direct interface to the messaging facility of the VM creating it. It is implicitly created by the getSlot function, but it can be directly created by the user.
If a slot with the given name didn't previously exist, a new message slot is created in the virtual machine, otherwise the already existing slot is wrapped in the returned instance.
// create a message slot x = VMSlot( "message" ) x.subscribe( handler ) ... y = VMSlot( "message" ) y.broadcast( "value" ) // handler is called.
Same happens if the VMSlot is created via getSlot, or implicitly referenced via subscribe function. Slots are considered unique by name, so that comparisons on slots are performed on their names.
If the name parameter is not given, the slot will be created as "anonymous", and won't be registered with this virtual machine. It will be possible to use it only through its methods.
An anonymous slot can be created using an empty call to the VMSlot class constructor. This will make the slot private for the users that can access it; in other words, the slot won't be published to the VM and it won't be possible to broadcast on it using the standard functions broadcast or assert functions.
If a listener subscribed to a slot is a callable item, then it's called in case of broadcasts. If it's a non-callable property provider (class instances, blessed dictionaries, non-callable arrays) then a callable property named like "on_
If the "on_event" method is found, it's called with the first parameter containing the broadcast name. Otherwise, an access error is raised.
Events are "named broadcasts". They are issued on slots and excite all the listeners that are subscribed to that slot. The main difference is that automatic marshalling is directed to the name of the event rather to the name of the slot.
See the following code:
object Receiver _count = 0 function display(): > "Count is now ", self._count function on_add(): self._count++ function on_sub(): self._count-- function __on_event( evname ): > "Received an unknown event: ", evname end s = VMSlot() // creates an anonymous slot s.subscribe( Receiver ) s.send( "add" ) // Instead of sending a broadcast ... s.send( "add" ) // ... generate some events via send() s.send( "A strange event", "some param" ) // will complain Receiver.display() // show the count
The VMSlot.send method works similarly to the VMSlot.broadcast method, but it allows to specify an arbitrary event name. Callbacks subscribed to this slot would be called for every event, be it generated through a broadcast or via a send call.
While callbacks subscribed to the slot will be excited no matter what kind of event is generated, it is possible to register callbacks to respond only to particular events via the VMSlot.register method.
See the following example:
slot = VMSlot() // creates an anonymous slot slot.register( "first", { param => printl( "First called with ", param ) } ) slot.register( "second", { param => printl( "Second called with ", param ) } ) // send "first" and "second" events slot.send( "first", "A parameter" ) slot.send( "second", "Another parameter" ) // this will actually do nothing slot.broadcast( "A third parameter" )
As no callback is subscribed to the slot, but some are just register to some events, a generic broadcast will have no effect.
An interesting thing about registering to events is that a slot keeps tracks of callbacks and items registered to a specific event via a named slot. For example, to know who is currently subscribed to the "first" event, it's possible to call the VMSlot.getEvent method and inspect the returned slot. Any change in that returned slot will cause the event registration to change.
For example, continuing the above code...
//... fevt = slot.getEvent( "first" ) // display each subscribed item for elem in fevt: > elem.toString() // and broadcast on the event first fevt.broadcast( "The parameter" )
As seen, a broadcast on a sub-slot is equivalent to an event send on the parent slot.
Note: It is then possible to cache repeatedly broadcast slots, so that the virtual machine is not forced to search across the subscribed events.
This structure can be freely replicated at any level. In the above example, fevt may be subject of send() and register() method application, and its own events can be retrieved trough its VMSlot.getEvent method.
Methods | |
assert | Creates a message assertion on this certain message slot. |
broadcast | Performs broadcast on this slot. |
first | Gets an iterator to the first subscriber. |
getAssert | Gets the item asserted for this slot. |
getEvent | Returns an event (as a child VMSlot) handled by this slot. |
last | Gets an iterator to the last subscriber. |
name | Returns the name of this slot |
prepend | Registers a callback handler that will be called before the others. |
register | Registers a listener for a specific event. |
retract | Removes a previous assertion on a message. |
send | Performs an event generation on this slot. |
subscribe | Registers a callback handler on this slot. |
unsubscribe | Unregisters a callback handler from this slot. |
Creates a message assertion on this certain message slot.
VMSlot.assert( data )
data | The value of the assertion. |
If there are already subscribed callbacks for this message a broadcast on them is performed now.
Performs broadcast on this slot.
VMSlot.broadcast( ... )
... | Extra parameters to be sent to listeners. |
Gets an iterator to the first subscriber.
VMSlot.first()
Return | An iterator to the first subscriber of this message slot. |
Gets the item asserted for this slot.
VMSlot.getAssert( [default] )
default | If given, instead of raising in case the essartion is not found, return this item. | ||
Raise |
|
Returns an event (as a child VMSlot) handled by this slot.
VMSlot.getEvent( event, [force] )
event | A string representing the event name. |
force | Pass true to create the event if it is not existing. |
Return | a VMSlot representing the given event in this slot, or nil if not found. |
This method returns a named VMSlot that will be excited by VMSlot.send applied on this slot with the same event name.
In other words, subscribing or unsubscribing items from the returned slot would add or remove listeners for a VMSlot.send call on this slot.
Also, a broadcast on the returned VMSlot has the same effect of a VMSlot.send with the same name as the event passed.
See also: VMSlot.
Gets an iterator to the last subscriber.
VMSlot.last()
Return | An iterator to the last subscriber of this message slot. |
Returns the name of this slot
VMSlot.name()
Return | The name of the event bind to this slot (as a string). |
Registers a callback handler that will be called before the others.
VMSlot.prepend( handler )
handler | The callable that must be unregistered. |
Registers a listener for a specific event.
VMSlot.register( event, handler )
event | A string representing the event name. |
handler | Handler to associate to this event. |
This function associates the given handler to a sub-slot named after the event parameter. This operation is equivalent to call VMSlot.getEvent() to create the desired sub-slot, and then call VMSlot.subscribe() on that named slot.
See also: VMSlot.
Removes a previous assertion on a message.
VMSlot.retract()
Performs an event generation on this slot.
VMSlot.send( event, ... )
event | Event name. |
... | Extra parameters to be sent to listeners. |
The send method works as broadcast, with two major differences;
Registers a callback handler on this slot.
VMSlot.subscribe( handler, [prio] )
handler | A callable item or instance providing callback support. |
prio | Set to true to have this handler called before the previous ones. |
Unregisters a callback handler from this slot.
VMSlot.unsubscribe( handler )
handler | The callable that must be unregistered. | ||
Raise |
|