PrevUpNext devguide-25.htmlUser Interface
devguide.htmlDeveloper's Guide devguide-27.htmlFile Format Message Passing
In a Model-View-Controller architecture like the one used in Skencil,
the model has to inform the views when the data has changed and the
views have to be updated. Often there can be several views for one model
object and it is desirable to implement the model in such a way that it
doesn't have to know how many and what types of view there actually are
at any one point in time. Still, the views have to be informed by the
model that they should update themselves whenever the model changes. In
Skencil this is achieved through a generic message passing mechanism
similar to the signals used in Qt or GTK.
Concepts
Messages are generated by publishers and consist of a
message type represented by a string and an arbitrary number of
arguments. The message type is also called a 
channel.
Program parts that want to receive messages subscribe to a channel of a
particular publisher by passing a callable object, often a bound
instance method, and optionally some additional arguments to the
publisher.
When the publisher issues a message all subscribers of the relevat
channel of the publisher all called with the message arguments and the
additional subscriber specific arguments.
The heart of this mechanism is the #N4Connector  class,
whose instances manage all connections between publishers and
subscribers. This way, a publisher that has no subscribers does not use
any resources.
The connector module has one global Connector instance and some
of its methods are available as globals.
There are two additional classes for publisher objects. #N11Publisher  provides methods to subscribe to and unsubscribe from
channels of the object. 
#N18QueueingPublisher  allows the
publisher to accumulate messages in a queue with identical messages
queued only once and release them all at once.
Most objects that send messages are derived from one of these publisher
objects and in most circumstances their methods are used to connect to
their channels. The connector is rarely used directly.
The Class Connector
Connect(publisher, channel, subscriber, args)Connect the subscriber, i.e. a callable object and
additional arguments 
args, to a channel of a
publisher.
The publisher can be any object, though most of the time
it's a 
#N11Publisher  instance. Skencil uses the
None object as a publisher for global messages.
args are subscriber specific arguments as a tuple.
The same subscriber may be registered multiple times but it is
only stored once in the list of subscribers. Two subscribers are
considered equal if the callable object and the arguments are
equal.
Disconnect(publisher, channel, subscriber,
args)Disconnect subscriber from publisher's channel.
The arguments have the same meaning as in #N5Connect  and again the combination of subscriberand 
args is used to identify one particular subscriber.
If the subscriber isn't connected to the channel, raise a
ConnectorError exception.
Issue(publisher, channel, *args)Issue a message on a channel of publisher.
The third and all following arguments are passed through to all
subscribers as message arguments. The arguments the subscribers
are called with is the concatenation of the message arguments
and the subscriber specific arguments.
RemovePublisher(publisher)Remove all subscribers from all channels of publisher. It
is safe to call this in a __del__ method.
HasSubscribers(publisher)Return true iff publisher has any subscribers.
Note that the connector does not hold references to the publisher.
Publishers are identified by their id. This makes it possible to
automatically disconnect all subscribers of a publisher in a publisher's
__del__ method. This does not work however, if e.g. the publisher is
itself a subscriber because the connector has to own the references to
the subcribers.
The Class Publisher
The class Publisher serves as a base class for classes that send
messages. It provides convenience methods to subscribe to and
unsubscribe from channels. It also removes all subscriptions
automatically when instances are deleted through the 
__del__method.
Subscribe(channel, subscriber, *args)Subscribe subscriber to self's channel with the rest
of the positional arguments as the subscriber specific
parameters. See 
#N5Connect  for more details.
Unsubscribe(channel, subscriber, *args)Unsubscribe subscriber to self's channel with the
rest of the positional arguments as the subscriber specific
parameters. See 
#N6Disconnect  for more details.
issue(channel, *args)If the instance variable ignore_issue is false, issue the
message described by the second and the following arguments on
channel 
channel, otherwise, do nothing.
ignore_issue defaults to false. ignore_issue will be
removed in 0.8.
Destroy()Remove all subscribers of all of self's channels. See #N8RemovePublisher  for more details.
__del__()Remove all subscribers of all of self's channels. See #N8RemovePublisher  for more details.
The Class QueueingPublisher
Sometimes it's useful to put messages in a queue and issue them all in
one go after a complex operation is finished. The class
QueueingPublisher provides such a queue and the following
methods:
queue_message(channel, *args)Put message for channel channel in the queue. The rest of the
arguments are treated just as in 
#N14issue 
If the messge is already queued remove it and put it at the end.
This is done to make certain that no channel gets called twice
between two calls to flush_message_queue. If the order of channel
invocation is important two or more queues should be used.
Note, that this can be very inefficient if a lot of different
messages are queued before the queue is flushed because each new
message is compared with all messages in the queue sequentiually. A
dictionary could speed this up considerably if the order in which
the messages are issued isn't important and if the messages can be
used as dictionary keys. Especially the latter is not always the
case, so this isn't done by defalt.
flush_message_queue()Issue all queued messages until the queue is empty. The process is
repeated because issueing messages might result in new messages
being queued. This can theoretically result in an infinite loop.
clear_message_queue()Discard all queued messages.
devguide-25.htmlUser Interface
devguide.htmlDeveloper's Guide devguide-27.htmlFile Format PrevUpNext