\input text.sty \paragraph{\paragraphfont{title: Event-handling with active objects -- dealing with non-determinism in high-performance applications}} \section*{\sectionfont{fragments (in construction)}} \paragraph{\paragraphfont{abstract}} The non-determinism inherent in event-driven systems, encompassing both networked applications and interactive applications, makes these applications difficult to develop and maintain, despite the availability of powerful libraries. One reason for this is the so-called {\em inversion of control} needed to dispatch events to listeners provided by the application. In this paper we will argue that event-handling with (passive) listener objects lead to problems in high-performance applications, which require non-blocking actions on the occurrence of events. Active objects provide a uniform approach to robust event-handling, both with respect to the registration and (de)activation of listener objects, as well as the (non-blocking) dispatching of events. We will illustrate our approach by discussing how to develop a graphical user interface for anapplication that must access a remote database. We will also indicate that as a benefit, from a software engineering perspective, our approach allows for a more modular approach to event-based systems and better insight in the flow of control between listeners and the application. \subsection*{\subsectionfont{1 Introduction}} The majority of applications fall within the class of event-driven systems, encompassing both networked applications and interactive applications with a graphical user interface. The non-determinism inherent in such systems makes these applications difficult to develop and maintain, despite the availability of powerful libraries. The problem is aggravated when multithreading is needed, for example to service multiple clients or preventing the application to block when accessing a remote resource. In this paper we propose an approach to event-handling based on active object and synchronous rendez-vous. The structure of the paper is as follows. In section 2, we will reconsider the various way event-handling is approached, and we will indicate the problems that may occur with respect to modular code development and multithreading. In section 3, we will provide a brief description of sJava, an extension of Java\index{programming languages!Java} that supports active objects and synchronous communication by rendez-vous. In section 4, we will proved an example that illustrates how synchronousn communication allows for a more direct approach to event-handling. In section 5, we will discuss the benefits of our approach from a software engineering perspective. And in section 6, we will draw some conclusions. \paragraph{\paragraphfont{related work}} Our approach is related to JCSP, a Java\index{programming languages!Java} extension based on CSP\index{programming languages!CSP} (Concurrent Sequential\index{sequential} Processes). However, JSP uses channels for communication by rendez-vous, whereas sJava uses synchronous method calls. Channels require explicit data coding Hence, our approach fits in more naturally with an object paradigm, where communication between objects is statically characterized by method interfaces. \subsection*{\subsectionfont{2 Event-handling reconsidered}} Event-driven computation underlies many applications, ranging from graphical user interfaces to systems for discrete event simulation and business process modeling. An important characteristic of event-driven computation is that control is relinquished to an environment that waits for events to occur. Handler function or handler objects are then invoked for an appropriate response. When we reconsider how events may be handled, we can distinguish between: {\small \begin{itemize} \item event loops -- explicit dispatching on type of event \item callback functions -- implicit (table-based) dispatching \item listener objects -- callback on objects with hook methods \end{itemize} } \noindent Event loops are typically the most primitive way to deal with events. Within the event loop an explicit dispatch on the type of the event is needed to invoke the appropriate application code. Callback functions are a significant improvement over plain event loops. The dispatching is implicit, based on an association between a callback function and the type of event. Note that this approach is more modular and allows for extensions since new callback functions may be associated with the events. Listener objects, as for example used in the Java\index{programming languages!Java} AWT and Swing GUI libraries, may be regarded as an extension of callback functions, providing an object and a hook method that is invoked on the occurrence of an event. Since listener objects can maintain state inbetween (hook) method invocations, listener objects are strictly more powerful then callback functions that must rely on ad hoc mechanisms to take the history of event occurrences into account. The {\em Reactor\index{patterns!Reactor}} pattern\index{pattern}, described in [Schmidt95], provides a good example of an approach to handling a multitude of events. Operationally, the {\em Reactor\index{patterns!Reactor}} approach amounts to the following steps: {\small \begin{enumerate} \item register handlers for particular event types \item start event loop and dispatch incoming events \item for each event, locate handler and invoke hook method \item within handler, take action based on state and event information \end{enumerate} } \noindent Characteristic for both callback functions and listener objects is an {\em inversion of control}, that is the application code must await until it is invoked by the (event) dispatching mechanism. Although this induces an additional complexity with regard to the program structure, it is definitely an improvement over the explicit dispatching in basic event loops. For example, when we implement a drawing application that enables us to draw objects on a screen, button press and move events are delegated to a handler (or listener) that decides based on the type of the event and its state what actions to take. Typically we may distinguish between two states, a state where no object is being drawn and a state where the object is being drawn, which is initiated with a button press. Dependent on the state the listener may ignore events. For example button moves are only meaningful when an object is being drawn. Even in a simple listener object as the drawing object sketched above, an explicit branching on both object state and event type is necessary. This seems to be inherent in an approach based on passive listeners. The {\em Reactor\index{patterns!Reactor}} pattern\index{pattern} provides a solution for event-based systems in general, including networking and interactive applications. In networking applicatations it is evident that we may wish to introduce multithreading to serve multiple clients. However, also in interactive applications the need for multithreading may occur, for example when we must connect to a remote database. Since the network connections may be unreliable, we do not wish to block the entire application while waiting for an answer. Using passive listeners, multithreading must be introduced in an ad hoc fashion, by creating threads when reacting to an event. In the following, we will propose an approach based on active objects that allows for multithreading in a more natural and robust way. Our approach which is based on an extension of Java\index{programming languages!Java}, that is described in the next section, also reduces the need for explicit branching on state and event type, since the invocation of listeners does not need the inversion of control, due to the semantics\index{semantics} of rendex-vous communication. \subsection*{\subsectionfont{5. Software engineering perspectives}} Non-determinism is an essential ingredient of event-based system. From a software engineering perspective the problem is not to suppress this non-determinism but to develop modular and robust code, that may easily be maintained and extended when the application requirements change. Explicit switch statements are rightfully called a {\em maintenance nightmare}, and are consequently made obsolete by the inheritance mechanism that is characteristic of object-oriented technology, [Eliens2000]. As we have argued in section 2, listener objects may be regarded as another way to suppress explicit dispatching or switch statements. However, there is a price to pay, namely we need to accept an {\em inversion of control}. Although listeners allow for a modular approach, that is an indefinite number of listeners may be created and registered to deal with events, it is not always easy to get insight in the flow of control, that is to know what part of the program is being activated in response to an event. This problem is aggravated by the need to do explicit branching on the state of the listener object and the type of the event. Our approach, described in the previous sections, actually undoes the {\em inversion of control}, due to the semantics\index{semantics} of active objects and synchronous communication by rendez-vous. As a consequence, it becomes more easy to analyze the flow of control and the patterns\index{pattern} of activity displayed by the program in response to events. \subsection*{\subsectionfont{Conclusions}} This paper has present