[compiz] object framework design, part II: COMMUNICATION
davidr at novell.com
Sun Dec 2 21:37:04 PST 2007
The most common form of communication between an object and one of its
descendants is done by invoking one of the descendant's member
functions. Values can be passed to the descendant using function
arguments and values can be passed back to the ancestor using the return
value of the member function or one of its arguments. It's a regular
function call, hence also very efficient.
As member functions can't access members or children provided by
interfaces that are part of derived types or loaded after the member
functions own interface, some other form of communication interface is
required as well.
Signals are basically just member functions for which invocation can be
connected to a member function of one of its descendants. It's also
possible to connect invocation to a member function of the object itself
but the function must then be part the interface with signal, a
base-type interface or one of the interfaces that became available
before the interface with signal. A member function can only be
connected to member functions with a matching prototype.
Computational time to emit a signal is linear to the number of connected
member functions, so in theory just as an efficient form of
communication as method invocation.
A unique handle is created for every function that is connected to a
signal. This handle can be used to break the connection. However, this
rarely needs to be done thanks to the hierarchical object model used,
which allow signal connections to be broken automatically as interfaces
and objects are removed from the object tree.
Method invocation and the signals mechanism described here are both
forms of communication that needs to be initiated by an ancestor object.
It's quite common that you want processing done in a descendant's member
function to trigger invocation of an ancestor member function.
Signed signals allow this form of communication. Signed signals are
simply signals for which a signature has been provided. Just like a
signature can be provided for a member function so it can be
introspected and invoked safely.
Signed signals are emitted and can be connected to just like all other
signals. However, a chunk of data that describe the signal is also
created and stored in a queue within the object tree's root node each
time a signed signal is emitted. This queue is processed asynchronously
from the main loop. During processing of a queued signal, the signal
named "signal" which is part of the interface also named "signal"
implemented by the base object type is invoked for the object that
emitted the original signed signal and all of its ancestors. The data
describing the signed signal is passed as an argument to the "signal"
So by connecting to an objects "signal" signal, it's possible to monitor
an invoke appropriate member functions for each signed signal emitted by
the object and all its descendants.
The object system itself is designed to promote creation of interfaces
that are well suited for IPC.
The communication interfaces provided within the object system makes it
easy for modules with access to an object tree or part of an object tree
to safely invoke any member function with a signature as a response to
some IO event and send notifications to interested destinations when any
signed signal has been emitted.
More information about the compiz