Sophie

Sophie

distrib > Mandriva > 9.1 > ppc > by-pkgid > 51f7de0838007e2876221e819c82d833 > files > 582

sketch-0.6.13-2mdk.ppc.rpm

<html>
<head>
<title>Developer's Guide: Message Passing</title>
</head>
<body bgcolor=white text=black link=blue vlink=navy alink=red>
<TABLE WIDTH="100%">
<TR>
<TH ALIGN="left" WIDTH="33%"><img SRC="Images/arrow-left.png" WIDTH="16" HEIGHT="16" ALIGN="top" ALT="Prev"></TH>
<TH ALIGN="center" WIDTH="33%"><img SRC="Images/arrow-up.png" WIDTH="16" HEIGHT="16" ALIGN="top" ALT="Up"></TH>
<TH ALIGN="right" WIDTH="33%"><img SRC="Images/arrow-right.png" WIDTH="16" HEIGHT="16" ALIGN="top" ALT="Next"></TH>
</TR>
<TR>
<TD ALIGN="left"><A HREF="devguide-25.html">User Interface
</A></TD>
<TD ALIGN="center"><A HREF="devguide.html">Developer's Guide</A></TD>
<TD ALIGN="right"><A HREF="devguide-27.html">File Format</A></TD>
</TR>
</TABLE>
<HR NOSHADE>
<H1><FONT face="Helvetica,Arial"><A NAME="N1"></A>Message Passing</font></H1>

<P>In a Model-View-Controller architecture like the one used in Sketch,
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 </P>
<P>The connector provides a generic message passing mechanism similar to
the signals used in Qt or GTK.</P>


<H2><FONT face="Helvetica,Arial"><A NAME="N2"></A>Concepts</font></H2>

<P><EM>Messages</EM> are generated by <EM>publishers</EM> and consist of a
<EM>message type</EM> represented by a string and an arbitrary number of
arguments. The message type is also called a <i>channel</i>.</P>
<P>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.</P>
<P>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.</P>

<P>The heart of this mechanism is the <A HREF="#N4"><tt>Connector</tt></A> class,
whose instances manage all connections between publishers and
subscribers. This way, a publisher that has no subscribers does not use
any resources.</P>
<P>The connector module has one global <tt>Connector</tt> instance and some
of its methods are available as globals.</P>
<P>There are two additional classes for publisher objects. <A HREF="#N11"><tt>Publisher</tt></A> provides methods to subscribe to and unsubscribe from
channels of the object. <A HREF="#N18"><tt>QueueingPublisher</tt></A> allows the
publisher to accumulate messages in a queue with identical messages
queued only once and release them all at once.</P>
<P>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.</P>


<H2><FONT face="Helvetica,Arial"><A NAME="N3"></A>The Class <A NAME="N4"></A><tt>Connector</tt></font></H2>

<P>
<DL>
<DT><B><A NAME="N5"></A><tt>Connect(<i>publisher</i>, <i>channel</i>, <i>subscriber</i>, <i>args</i>)</tt></B><DD>
<P>Connect the <i>subscriber</i>, i.e. a callable object and
additional arguments <i>args</i>, to a <i>channel</i> of a
<i>publisher</i>.</P>
<P>The <i>publisher</i> can be any object, though most of the time
it's a <A HREF="#N11"><tt>Publisher</tt></A> instance. Sketch uses the
<CODE>None</CODE> object as a publisher for global messages.</P>
<P><i>args</i> are subscriber specific arguments as a tuple.</P>
<P>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.</P>


<DT><B><A NAME="N6"></A><tt>Disconnect(<i>publisher</i>, <i>channel</i>, <i>subscriber</i>,
<i>args</i>)</tt></B><DD>
<P>Disconnect <i>subscriber</i> from <i>publisher</i>'s <i>channel</i>.</P>
<P>The arguments have the same meaning as in <A HREF="#N5"><tt>Connect</tt></A> and again the combination of <i>subscriber</i>
and <i>args</i> is used to identify one particular subscriber.</P>
<P>If the subscriber isn't connected to the channel, raise a
<CODE>ConnectorError</CODE> exception.</P>


<DT><B><A NAME="N7"></A><tt>Issue(<i>publisher</i>, <i>channel</i>, *<i>args</i>)</tt></B><DD>
<P>Issue a message on a <i>channel</i> of <i>publisher</i>.</P>
<P>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.</P>


<DT><B><A NAME="N8"></A><tt>RemovePublisher(<i>publisher</i>)</tt></B><DD>
<P>Remove all subscribers from all channels of <EM>publisher</EM>. It
is safe to call this in a __del__ method.</P>


<DT><B><A NAME="N9"></A><tt>HasSubscribers(<i>publisher</i>)</tt></B><DD>
<P>Return true iff <i>publisher</i> has any subscribers.</P>


</DL>

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.</P>


<H2><FONT face="Helvetica,Arial"><A NAME="N10"></A>The Class <A NAME="N11"></A><tt>Publisher</tt></font></H2>

<P>The class <tt>Publisher</tt> 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 <CODE>__del__</CODE>
method.</P>
<P>
<DL>
<DT><B><A NAME="N12"></A><tt>Subscribe(<i>channel</i>, <i>subscriber</i>, *<i>args</i>)</tt></B><DD>
<P>Subscribe <i>subscriber</i> to self's <i>channel</i> with the rest
of the positional arguments as the subscriber specific
parameters. See <A HREF="#N5"><tt>Connect</tt></A> for more details.</P>

<DT><B><A NAME="N13"></A><tt>Unsubscribe(<i>channel</i>, <i>subscriber</i>, *<i>args</i>)</tt></B><DD>
<P>Unsubscribe <i>subscriber</i> to self's <i>channel</i> with the
rest of the positional arguments as the subscriber specific
parameters. See <A HREF="#N6"><tt>Disconnect</tt></A> for more details.</P>

<DT><B><A NAME="N14"></A><tt>issue(<i>channel</i>, *<i>args</i>)</tt></B><DD>
<P>If the instance variable <tt>ignore_issue</tt> is false, issue the
message described by the second and the following arguments on
channel <i>channel</i>, otherwise, do nothing.</P>
<P><tt>ignore_issue</tt> defaults to false. <tt>ignore_issue</tt> will be
removed in 0.8.</P>

<DT><B><A NAME="N15"></A><tt>Destroy()</tt></B><DD>
<P>Remove all subscribers of all of self's channels. See <A HREF="#N8"><tt>RemovePublisher</tt></A> for more details.</P>

<DT><B><A NAME="N16"></A><tt>__del__()</tt></B><DD>
<P>Remove all subscribers of all of self's channels. See <A HREF="#N8"><tt>RemovePublisher</tt></A> for more details.</P>

</DL>
</P>



<H2><FONT face="Helvetica,Arial"><A NAME="N17"></A>The Class <A NAME="N18"></A><tt>QueueingPublisher</tt></font></H2>

<P>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
<tt>QueueingPublisher</tt> provides such a queue and the following
methods:</P>
<P>
<DL>

<DT><B><A NAME="N19"></A><tt>queue_message(<i>channel</i>, *<i>args</i>)</tt></B><DD>
<P>Put message for channel <i>channel</i> in the queue. The rest of the
arguments are treated just as in <A HREF="#N14"><tt>issue</tt></A></P>
<P>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.</P>
<P>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.</P>

<DT><B><A NAME="N20"></A><tt>flush_message_queue()</tt></B><DD>
<P>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.</P>


<DT><B><A NAME="N21"></A><tt>clear_message_queue()</tt></B><DD>
<P>Discard all queued messages.</P>

</DL>
</P>



<HR NOSHADE>
<TABLE WIDTH="100%">
<TR>
<TD ALIGN="left"><A HREF="devguide-25.html">User Interface
</A></TD>
<TD ALIGN="center"><A HREF="devguide.html">Developer's Guide</A></TD>
<TD ALIGN="right"><A HREF="devguide-27.html">File Format</A></TD>
</TR>
<TR>
<TH ALIGN="left" WIDTH="33%"><img SRC="Images/arrow-left.png" WIDTH="16" HEIGHT="16" ALIGN="top" ALT="Prev"></TH>
<TH ALIGN="center" WIDTH="33%"><img SRC="Images/arrow-up.png" WIDTH="16" HEIGHT="16" ALIGN="top" ALT="Up"></TH>
<TH ALIGN="right" WIDTH="33%"><img SRC="Images/arrow-right.png" WIDTH="16" HEIGHT="16" ALIGN="top" ALT="Next"></TH>
</TR>
</TABLE>
</body>
</html>