David Reveman
2007-Dec-03 05:37 UTC
[compiz] object framework design, part II: COMMUNICATION
COMMUNICATION Method Invocation 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 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. Signed signals 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" 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. Inter-Process Communication 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. --------------- -David