Back to Home

Oberon is dead, long live Oberon! Part 1. Some love more active

Oberon · Oberon technology · programming language · multi-threaded programming · oberon

Oberon is dead, long live Oberon! Part 1. Some love more active

The programming languages ​​of the Oberon family were not destined to break into the mainstream, although they left a noticeable mark in the IT industry. However, both the operating systems written in these languages ​​(being both the software frameworks of various solutions and development environments) and the programming languages ​​themselves are used in the educational, research and industrial fields to this day, forcing creativity and experimentation, developing and absorbing new the trend of industry and influencing it.

With this review article, I open a series of articles on the Active Oberon language and the A2 operating system written in this language.

So, meet - Active Oberon


The first publication on Active Oberon appeared in 1997, but it is clear that the language and its implementation appeared earlier. Over the years, there have been many changes in the language, the runtime environment has been revised, the operating system A2 has been written ...

A feature of the language that distinguishes it from other programming languages ​​is the concept of Active Objects - objects that encapsulate the flow of execution. Active Oberon extends the Oberon language by introducing the object type Object, the concept of Activity associated with an object (stream), as well as synchronization and protection mechanisms from simultaneous access. The implementation of such mechanisms at the language level makes it possible to simplify the development and implementation of multithreaded applications and reduces the number of errors associated with the protection and synchronization problem.

In the import section, plug-ins can have aliases, different modules can have the same alias, forming from some modules a kind of namespace. In such modules, the names of exported entities must not overlap.

For instance:
IMPORT Example := Example1, Example := Example2;

Active Oberon implements improved arrays (mathematical and tensor), structural arrays (objects compatible with improved arrays), complex types, operations for objects, improved arrays and complex types, delegates compatible with both module procedures and object methods. Instead of multiple inheritance, the concept of multiple inheritance of interfaces is used.

The syntax of the language in the process of development practically does not change - instead, semantic modifiers are introduced, changing the semantics of the syntactic structures present in the language. The list of modifiers is enclosed in braces {}.

So, to describe the delegate, the DELEGATE procedure modifier is used:
Example1 : PROCEDURE{DELEGATE, REALTIME} ( VAR parameter : LONGINT ) : BOOLEAN;

The example describes the procedure variable Example1, pointing to a delegate - a procedure or a real-time method that takes a variable of type a long integer by reference and returns a value of a logical type.

Methods are described inside the object. All methods in Active Oberon are virtual. Methods preceded by the & sign are constructors and are called automatically when the object is created. The compiler selects the required constructor based on the call signature of the NEW built-in procedure, designed to create entities of a reference type. Objects and methods can also have ABSTRACT and FINAL modifiers with clear semantics. Operations (operators) can be described both at the object level and at the module level, with the exception of some operators described only at the object level (at least in the current implementation).

Active Objects and Multithreading Model

An object can have a body - the final block of statements executed after the object is initialized. If the body of the object is marked with the ACTIVE modifier (possibly with priority), then such an object is called active. As already mentioned, the activity (stream) is encapsulated in the object and is created at the time of the instantiation of the active object. Activity exists while the body of the active object is running. An active object continues to exist as long as its activity exists, even if there are no links to it, after which it becomes passive and can be disposed of in the usual way.

Communication between activities is carried out through calls to methods of active and inactive objects.

Protection against simultaneous access to object states is provided by support at the language level of exclusive regions (exclusive regions) - a sequence of statements enclosed in BEGIN ... END statement brackets marked with the EXCLUSIVE modifier - corresponding to the concept of critical Brinch Hansen areas. If a monopoly region covers the entire body of an object, it is called a monopoly region and combines the concept of Hansen's critical regions with the concept of the Hoare monitor procedure. Unlike Hoar’s monitor procedures, object methods are not required to be exclusive and can observe non-synchronized state of the object. A module is considered an object with a single instance. The compiler and runtime environment ensure that no more than one activity can be in a monopoly area at a time.

Thus, the protection model in Active Oberon is a monitor located in an instance of an object (instance-based monitor).

The main idea of ​​the monitor is that an invariant is associated with it - an expression that defines the internal, consistent state and proves the correctness of its behavior. Object initializers establish an invariant, and monopoly methods support it.

For synchronization in Active Oberon, the AWAIT operator is used, while most monitor implementations use Hoare conditional variables based on Hansen queues. The AWAIT operator takes as argument the logical condition for the continuation of execution, in case of non-compliance with which the activity is suspended, and the captured exclusive region is freed until the expression condition becomes true. The activity will continue to work when it can again enter the previously released monopoly section. Continuation conditions are recounted only when any activity leaves the monopoly section.

An example of the description of the active object and the use of the exclusive section:

TYPE
    Timer* = OBJECT
        VAR
            timer: Objects.Timer;
            handler: Objects.EventHandler;
            timeout, running: BOOLEAN;
        PROCEDURE &Init*;
        BEGIN
            NEW(timer);
            timeout := FALSE;
            running := TRUE;
        END Init;
        PROCEDURE SetTimeout*(h: Objects.EventHandler; ms: LONGINT);
        BEGIN
            handler := h;
            Objects.SetTimeout(timer, HandleTimeout, ms)
        END SetTimeout;
        PROCEDURE CancelTimeout*;
        BEGIN
            Objects.CancelTimeout(timer);
        END CancelTimeout;
        PROCEDURE HandleTimeout;
        BEGIN {EXCLUSIVE}
            timeout := TRUE
        END HandleTimeout;
        PROCEDURE Finalize*;
        BEGIN {EXCLUSIVE}
            Objects.CancelTimeout(timer);
            running := FALSE
        END Finalize;
    BEGIN {ACTIVE}
        WHILE running DO
            LOOP
                BEGIN {EXCLUSIVE}
                    AWAIT(timeout OR ~running);
                    IF ~running THEN
                        EXIT
                    END;
                    timeout := FALSE
                END;
                handler()
            END
        END
    END Timer;

Memory management.

Active Oberon applies automatic memory management using a real-time garbage collector. This means that real-time activity can stop the garbage collection process. In areas of real-time code, memory allocation operations are prohibited by the compiler. Real-time procedures, methods, and activities are marked with the REALTIME modifier. Not all compiler and runtime implementations support real-time processes.

Variables marked with the UNTRACED modifier are untracked pointers and are not tracked by automatic memory management mechanisms.

The DISPOSE statement is syntactically supported in the language, but its implementation may be absent.

This concludes the review article of Active Oberon, I recommend starting dating with the classic Oberon.

References:



Series Content


Read Next