13: Event Programming

Lecture



Event, message, demon

The quality mentioned above (statement (5.2))

Preparation of information for actions in recognition of the conditions of applicability of actions, (13.1)

Perhaps, it is critical to separate the cases of using sentence and event programming. Prioritization checking and selecting the action with the highest priority as the active one, just like identifying meta expressions in the probable case, is hidden in the atomic actions of the program system, but when checking priorities the programmer does not receive any useful information for performing the selected action. If some useful information is obtained by a future action, then it is set separately and imperatively, in the parameters of the message causing the event. In turn, the presence or absence of such information determines the difference between the two aspects of event programming: programming of events and priorities.

It should be noted that there is one more feature common to two styles: sentence and event.

Separation of conditional checks from performing actions (13.2)

This seems to be a general characteristic of technological solutions for styles where conditions are global.

Until now, we have not said anything about what events are possible with event-oriented programming. Historically, this style as a certain artistic technique has been formed in the field of developing operating systems, where it is natural to associate the concept of an event with interruptions. An interrupt is a signal from one of the devices (maybe from the processor itself), which indicates that something happened that you should pay attention to. When an interrupt occurs, the operating system recognizes which cause caused it, and then generates an event as an information object that triggers a reaction from the software system. There are various ways of responding to events, including sending it to handle the program that caused the interrupt that generated this event.

As a matter of fact, an event-oriented programming style has emerged from the need for such processing. The most obvious area of ​​its adequate use is the implementation of interactive program interactions with the user and the solution of other similar tasks (for example, those that require polling the state sensors of any technological processes).

In particular, when interacting with the user, such events as pressing the key, moving the mouse cursor, specifying the light button, etc. are most often enough. It is not by chance that the interruptions that the operating system can redirect to the user program level became the basis for the development of event systems, the reaction to which is specified in an event-oriented style. Events of this kind can be transferred from one handler to another without violating the conditions for the adequate application of this style: to do this, it is enough to declare such a redirection of an event to be the creation of a new event.

But the generation of non-interrupt events is also required. For example, when programming in an event-oriented style, it is natural to declare an event a situation when the value of one variable becomes greater than another. However, such properties of the computational process are not reflected in any way in the interrupt system, and therefore the usual language means of event-oriented programming (for example, in Delphi), which are often proclaimed as universal, will not help here. Other mechanisms are needed that lead a programmer away from the area of ​​project templates that standardize event processing.

This circumstance, which limits the applicability of the approach, is preferred to be silent, and, as usually happens in such situations, a cursory acquaintance with the appropriate means may lead to unfounded expectations with subsequent disappointments and even rejection of a style that works well in its place.

An example of a language that is to some degree oriented to event-oriented programming is Perl.

Event style is convenient not only at the level of specific programming. It is often useful to carry out a conceptual understanding of the problem in terms of an event system, and then decide how to implement the system: directly use events as a means of control, simulate event interaction with available means, or abandon this mechanism altogether in this development.

To illustrate this thesis, from the standpoint of an event-based programming style, we describe the relationship between syntactic analysis and program semantics calculations. The realization of these relationships is a common task solved in the development of any translator. In the event description of this task, it is natural to consider the recognition of syntactic units in the input stream (translated text), that is, language constructs, as system events. Such an event requires as a handler a semantic subroutine associated with a recognizable construct. Consequently, two autonomous processes have been identified: syntactic analysis , which defines the generation of events, and semantic processing , carried out as a sequence of calls to semantic subroutines-reactions, ordered by events. If there is a conceptual separation of processes, it can be embodied in a real system in an event style. This decision entails the following.

  • The need to consider two events as events: the beginning and the end of the recognition of a construct, since it is with them, and not the construct as a whole, that semantic actions are associated.
  • For the problem under discussion, it is essential that events do not arise in an arbitrary order, their set has a well-defined structure. It is not surprising that this structure exactly corresponds to the syntactic structure of the text: for example, a construction recognition completion event cannot occur before a construction start event occurs.
  • The consequence of this structure is the notion of waiting for well-defined, rather than arbitrary events. If the wait did not come true, then this can be considered an event of another kind: an erroneous situation . The number of such events is exactly equal to the number of sets of expected events.

In event-based programming, the separation of the generation and processing of events entails their complete independence. In the practice of programming broadcasting systems, this quality is considered not very convenient, and instead of the event mechanism, the co-ordinate interaction with the so-called syntactic control is usually used: the parser itself calls the necessary semantic programs when it recognizes the need to do this (in the event style, this means generating the corresponding event) . There is no contradiction between the two schemes, and the only difference between them is that with syntactic control, it was possible to replace the expectation of an event with a direct subroutine call. In other words, in the translation scheme, it is possible statically, before the execution of the program, to calculate events, the occurrence of which requires calling their handlers (semantic subroutines). In general, the coroutine interaction can be interpreted as a statically calculated eventfulness 1 .

Of course, the scope of event programming is much wider than those cases where it is possible to statically determine the need to activate the handler. Combining the generation of events with their processing is useful, and due to it, events can be dissolved in the program. In particular, and for this reason, event programming should be considered as an independent style. But there are interesting cases when the union, although possible, is not done. A specific example is XML / XSL technology, for which the separation of the structure and interpretation of the text is considered fundamental: it allows you to build removable processing systems, to have several independent such systems for different purposes. In its field of application, multivariance has great advantages, but, as always, the transfer of the principles of this technology anywhere fraught with more than once marked inadequacy.

Programming from priorities

Discussing event programming, we mentioned that when programming in this style, it may be necessary to streamline the execution of several competing reactions to events. A fairly universal means of satisfying this need is to assign priorities to reactions: first, those reactions that have a higher priority are performed. This technique, as revealed in practice, is suitable for solving a fairly wide range of tasks. It became the basis for the formation of an independent version of the event style: programming from priorities.

This hypostasis of style is generated by practical needs. It is designed to organize the work of many interacting processes, dynamically generated and disappearing. There are almost no fundamental theoretical studies in the field of programming priorities. In particular, in the classic paper by Hoare [29], which deals with the control of interacting processes, it is assumed that the program is written in the traditional structural style and there are no attempts to adapt it to an environment where there are many processes 2 .

The prioritized programming style is not implemented systematically in the form of a complete language (for some attempt, the Joule project can be cited, see http://www.agorics.com/Library/joule.html), but it is often used in applied scripting languages for process management. or events either in distributed systems, or at the semi-hardware level (the so-called embedded programs, which are part of a specialized device or device).

In programming from priorities, as well as in sentential programming, the order of statements in the program does not play a fundamental role, but the operator’s priority is important, that is, a certain value that belongs to the partially ordered set in the most general case and is almost always considered elementary. After the completion of the next operator, the operator with the highest priority is selected among the remaining ones. If there are several such operators with equal or incomparable priorities, then, generally speaking, ideally, one of them would have to be chosen nondeterministic.

It is possible to speak about operators having priorities, when programming from priorities is implemented in a language specifically designed for this style. If it is necessary to model programming from priorities in ordinary language, then other structural units of the program text can act as such operators. In an object-oriented language, as a rule, these are object methods. For the sake of brevity, in the framework of this section we will speak about operators, meaning the remark just made.

When assigning priorities, it is important to distinguish cases when they are set for operators as elements of the program text and when priorities are introduced for dynamic structural units, that is, for those elements of the calculation process that arise during the execution of the program but are associated with one or another operator whose priority within a specific instance (for example, an object). Thus, different systems of priorities are built, and in the second case, the system of priorities is inevitably dynamic.

In practice, they usually use rigid discipline based on the order of operators in the program. Often, the management of priorities is connected with the so-called system of demons, that is, procedures that are called when a certain condition is fulfilled, but not at the moment when moving through the program text we approached their explicit call (such a demon sits in ambush and waits for the moment when will start to be executed). Both the current "normal" process and the awakened demons have their own priorities, and the demon will start to execute, even if it is activated, only if there is no process left among the active ones with a higher priority than the demon. This scheme is implemented, in particular, in the UNIX system.

It is worth noting that event-oriented programming can sometimes be viewed as a degenerate case of programming style from priorities: for each instance of a structural unit capable of reacting to events, an (infinitely large) priority is set if this instance should actually activate the reaction, and no priority is set an infinitesimal priority is set) if the instance does not have to react to the event. The general case of event-oriented programming style is also close to the programming style of priorities, if we assume that all event handlers to be executed when it appears, are assigned priorities that correspond to the actual order of their execution. When this order is unknown, we can assume that all activated handlers are assigned equal priorities.

The fundamental difference between programming from events and from priorities is in the principles of the task of control. In the case of programming from an event, a direct connection is established between the event and the response: if the trigger condition opens up the opportunity for the handler to be fulfilled, then it will necessarily be fulfilled in response to the corresponding event. When programming from priorities, the situation is different: by giving the daemon even the highest priority, we can only hope that it will work before the others, and, possibly, even without the occurrence of any kind of event. If we abstract from the control mechanism when operating with priorities and events, then we can consider these two styles as variants of the same entity.

Variants of event programming from events and priorities are well combined, mutually complementing each other when the following architectural scheme for developing a software project is appropriate. From events, fragments of the system are built, which are responsible for the reaction to each of the events implemented by different handlers, and the programming of these handlers is done by priorities.

Consider written in two versions in two conditional languages ​​an example of a program with priorities.

  3: The cycle is not all done
     {
     5: Data preparation;
     10: Handle current changes;
     }
 4: Daemon {If Data Received That
     Receive routine data};
 8: Daemon {If Emergency Data Received Then
     Remembering emergency changes};
 12: Demon {If Accident That Disaster Act}; 
13.2.1.

  a: PRIO 3 {Prepare Data;  SLEEP};
 b: PRIO 10 {Process Changes;  SLEEP};
 c: PRIO 8 DAEMON IF Extra Data
     THEN Store Extra Data;
     AWAKE b FI;
 d: PRIO 12 DAEMON IF Alert
     THEN Emergency;  FI;
 e: PRIO 2 DAEMON IF Idle 
     THEN AWAKE a;  FI; 
13.2.2.

It can be seen that in this example, all priorities were set statically. This is precisely what is being pursued in almost all cases of contemporary practice of computing with priorities. However, complete static can be achieved only in the simplest cases. For example, if a process waits for its turn for a long time, then it is natural to gradually raise its priority. At the same time, the priority of such a "user" action can exceed the priority of the system process, and it remains to either statically set the permissible maximum priority for each process, and we again fall into the same trap, or set priorities to different classes of processes that are not comparable in order, so that What a normal execution, the priority of the process user demons did not reach, say, up to 10 9 .

Note that the prioritization of the operating system, "from above", does not fundamentally change anything in this picture. From the point of view of user programs, these priorities are still static.

Let us consider theoretically which classes of programs can be described using static and dynamic priorities. It turns out that with the help of static priorities, which are natural numbers, it is impossible to describe even the primitive-recursive compositions of the original actions 3 .

Thus, conceptually natural numbers are not enough to describe priorities, but it turns out that there are enough ordinals for them (see the course of mathematical logic). Since ordinals to   13: Event Programming 0 have a good computational model (see, for example, [20]); we can consider integer priorities as a concrete implementation of an abstract class of such ordinals.

In the case of really distributed or parallel actions, the problem of priorities is more important and more complicated. Often, managing priorities is the only chance to cope with the complexity of such a non-linear system in time. There is already a linearly ordered set of priorities is not enough.

In general, programming from priorities is a powerful but specific tool for describing global collaborative, parallel, or distributed processes. Its elements also penetrate traditional programming systems in the form of handling exceptional situations in programs. Here, as well as in programming from events with isolated reactions, there are only two priorities that are imposed on the structure using the construct. The inconsistency of this tool with structured programming is only in the fact that it is not always clear what is done next when the exception handling ends.


Comments


To leave a comment
If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

Programming Styles and Techniques

Terms: Programming Styles and Techniques