Aztec® Programming Language
Version 1.1 Alpha 2

Copyright © 2010-2017, Aztec Development Group, All Rights Reserved

Download Aztec

Search        Contact Us

You may say I'm a dreamer...

But I'm not the only one.

- John Lennon

 

Aztec Events

Events are an integral part of the Aztec Virtual Machine. The core Virtual Machine understands Aztec Event objects, and it provides services to setup event handlers with one or more Aztec VM Threads. The Virtual Machine will automatically wake up a Thread and invoke the appropriate event handler once it is setup. Setting up an event handler is easy, and it is a consistent process across the entire Aztec Class Framework.

There is a consistent naming convention and set of methods associated with all events and event handlers throughout the Aztec system. It is strongly recommended that used defined events and event handlers be modeled in exactly the same way. A simple framework is provided to help facilitate this. User defined events are discussed in more detail below.

Note: The following naming convention discussion might seem confusing at first, as syntax related discussions oftentimes do, but don't get lost in the details. Real examples (below) will help show how easy the naming convention is to define and to use. This naming convention defined here is also needed for further discussions below. The key takeway is that all Aztec events are handled in an identical way, and there are always three separate ways to setup or define handlers for each type of event.

Every Aztec event uses the following conventions for naming events, event handlers and event associated methods.

♦ The class which generates a particular event will have a virtual method named “OnXXX”, which is the default event handler for the XXX event within that class.

♦ This method is called when the XXX event occurs, and it handles the event based on how other event handler methods are setup as described below.

♦ There will be a handler data type named ‘XXXHandler’ which is a defined method reference type for the XXX event. The signature of the event handler method for this event  (which matches the XXXHandler type) must be as follows:

♦ method  XXXHandlerMethod(XXXEvent EventObject,Base ExtraObject) # Method name can be anything. Method signature is the important thing.

♦ The class will have a method with the following signature to add an event handler using a method reference.

♦ method AddXXXHandler(XXXHandler ,Base)

♦ The class will have a method with the following signature to add an event handler using an event interface object. “IYYYClass” is interface class associated with class in question, and it contains an abstract method for each event handler for the class it's associated with ('YYYClass' in this case).

♦ method AddXXXHandler(IYYYClass ,Base)

When a method call is made to add an event handler using either of the "AddXXXHandler" methods, the Virtual Machine not only registers the event handler and the "extra object", it also registers the VM Thread which made the call. When the event occurs and the default event handler is invoked, it sends the event to each VM thread that has one or more applicable event handlers registered with it. That VM Thread is then responsible for setting up and executing the appropriate event handler(s) within the context of that thread.The following diagram shows how this multiple thread event dispatching works.

Aztec Event Handling with Multiple Threads

There are three different ways to get control when an event occurs within an object of a specified class.

1) Derive a new class from the specified class and override the event handler method (OnXXX()). When the event occurs to this object, the derived event handler method will get invoked automatically due to polymorphism.

2) Add an event handler to the object in question by calling the “AddXXXHandler” method using a method reference. When the event occurs, the object’s event handler gets invoked, which in turn invokes ALL of the methods which are added to this event handler queue.

3) Add an event handler to the object in question by calling the “AddXXXHandler” method using an instance of the Interface version of the class in question. The “interface class” is an abstract class which contains virtual event handler methods for each of the event handlers in the class it mirrors. When the event occurs, the object’s event handler gets invoked, which in turn invokes ALL of the queued-up interface based event handlers.

For an Aztec thread to process events from the Virtual Machine, the Thread.EventMode() method must be invoked. This stops execution of the thread at that point and turns the thread into a perpetual event handling machine. The system efficiently waits for events to occur and then processes them with the event handlers that are set up to handle them. The thread’s execution never returns from the EventMode() call, it stays in event handling mode forever.

♦ The thread that creates the object associated with an event is the thread that is invoked by the VM to initially process the event (the default OnXXX method). However, when the OnXXX method is invoked, it in turn executes all of the handlers queued up using the “AddXXXHandler” methods.

♦ The Virtual Machine executes each queued event handler within the context of the thread that called “AddXXXHandler” method in the first place. This allows the base event handler to launch other handlers within multiple threads based on a single event occurrence, as shown in the above diagram.

♦ The event handlers which are queued up using “AddXXXHandler” methods will be executed automatically if the “OnXXX” method is not overridden in a derived class. If the OnXXX method is overridden, that derived virtual method must manually call the base class’s OnXXX method in order to make that happen. The derived class has the option of invoking them or not, which can sometimes be a useful debugging tool.

The Virtual Machine executes one event at a time within each thread. While the thread is executing one event, all events that get sent to that thread for execution get queued up until the current event handler is complete. The Virtual Machine keeps executing them until the list is empty. If one event handler takes a long time, the remaining events remain in the queue, which can cause the script to appear sluggish. The Thread.ProcessEvents() method provides a simple solution to this problem. The thread manually interrupts its own execution and allows events that are queued up to execute within that same thread. Once all of the queued up events are handled, the thread's execution contines immediately following the ProcessEvents() call. Oftentimes a separate Aztec thread may be the best solution for this type of situation, but the ProcessEvents() method provides a simple, effective solution to keep the thread responsive.

Every Aztec event is derived from the 'Event' class, either directly or indirectly. A subset of the Aztec Event Hierarchy is shown in the following diagram.

Sample of Aztec Event Framework

 

The Aztec Event framework also includes exception classes. There is a class named ExceptionEvent, which is the base class for all Aztec Exceptions. The compiler does verify that all classes used with the exceptions/handle construct are derived from ExceptionEvent. Standard exception handling within the thread where the exception occurred is a powerful error handling mechanism, and it is defined in detail in the Exception Handling web page. But Aztec also provides a new twist to exception handling. Every Exception class is derived from ExceptionEvent, which in turn is derived from Event. This makes an exception eligible for standard Aztec event handling as described on this page.

The Aztec Thread Class provides methods to register standard Aztec event handlers to get called when a specific type of exception occurs within a particular thread. If an exception event occurs within a thread, the standard exceptions/handle processing is followed in that thread. However, if an event handler is registered with the thread for that type of exception, and it was registered in a separate thread, the system will start up execution of that event handler in parallel with the exceptions/handle processing in the exception thread. This allows a script to monitor and track exceptions in the background, independent of the code that is actually handling the exception.

Interface Classes

Aztec uses the term “Interface Class” loosely to refer to a special class which contains nothing more than virtual event handlers which match events that the companion class supports.

♦ For instance, if the class “Door” supports one event named “DoorCloseEvent”, then the Door class will contain an “OnDoorClose ()” method, along with all the other support methods that the Door class may need. The “IDoor” class will contain a single virtual method named “OnDoorClose ()”.

♦ The Aztec class “Thread” contains methods for handling four different events – “OnException”, “OnTextMessage”, "OnBinaryMessage()" and “OnObjectMessage”. As such, the “IThread” class contains virtual forms of those same four methods, and there’s nothing else in the class. The interface class provides another Object Oriented alternative to using method references for event processing.

♦ The interface classes use virtual methods instead of abstract methods so the user does not have to override every one of the events that the class supports. A virtual method only has to be overridden if the script/application specifically wants to process the corresponding event. The virtual methods provided in each of the interface classes do nothing.

Event Handler Data Types

Aztec uses the term “Handler” to refer to a data type created with the “type<>” statement that refers to a method reference for a particular event handler method. Every event defined within the Aztec Class Framework has an associated “Handler” data type to make the use of the method reference easier.

♦ To steal the “Door” class example from the "Event Handling" Page with an “OnCloseDoor” event, the associated handler would be defined as follows:

♦ public type<method<CloseDoorEvent,Base>>  CloseDoorHandler

♦ The corresponding event handler method would have the following signature (method itself can have any name):

♦ public method  DoorCloseHandlerMethod(CloseDoorEvent e,Base extra)

The Aztec system defines a Handler data type for each event that it supports. The following list shows the Handler data types for each Event in the framework, and a similar list for special Exception Event handlers is shown on the Exception Handling page. Note the consistency between the handler names and the event names.

Aztec Event Handler Data Types

 

User Defined Events

Aztec provides a simple framework for creating user defined events with the same naming and handling conventions as system defined events.  Once registered with the Virtual Machine, they are handled automatically in the same way that system events are handled. Not only is it important to users to maintain consistency with the naming conventions for each event, it is also important to provide the expected event behavior, as described above with queueing, multi-threading, ProcessEvents() and EventMode() usage, etc.

The ‘Base’ class provides the following methods which work directly with the Virtual Machine to handle the user defined event in the same way that all framework events are handled.

♦ AddEventHandler()

♦ ProcessEvent()

The user creates the following items to support the new event class.

♦ The class which creates the event, which will also include the following methods.

♦ AddXXXHandler() - Two versions to setup handlers for XXXEvent - one takes an event handler data type, one takes an interface object. Uses Base.AddEventHandler() to work with VM.
♦ OnXXX() - Default event handler for XXXEvent. Uses Base.ProcessEvent() to work with VM and distribute to multiple threads as necessary.

♦ The event class itself, XXXEvent (must be derived from Event)

♦ The event handler data type, XXXHandler (type<method<XXXEvent,Base>> XXXHandler)

In addition to other event related items, the code below provides an example of a user defined event with all the trimmings.

The Aztec source code showing simple event handling is shown below.

#===================================================================================================
# Example Script: Aztec Simple Event Script
# Demonstrates creation of a simple window and timer with event processing. Uses WindowCloseEvent,
# WindowResizeEvent and TimerAlarmEvent.
#===================================================================================================

# Main class that is derived from Thread. VM automatically creates us and executes Run().
class Main from<Thread>
{
method Main()
{
}

method virtual Run()
{
# Create the simple window, a timer and then go into event mode.
CreateWindowAndTimer()
EventMode()
}

method CreateWindowAndTimer()
{
data<TimerInterface> MyTimerInterface = new<TimerInterface>

# Create the UI - a simple resizable Frame window and a single read-only Edit control.
MainFrame = new<Frame(null,0,0,400,180,"Sample Event Script",true)>
MainFrame.AddWindowCloseHandler(MainFrameCloseHandler)
MainFrame.AddWindowResizeHandler(MainFrameResizeHandler)

TimerResultWindow = new<Text(MainFrame,10,55,250,25,"")>

#-------------------------------------------------------------------------------------
# Create the Timer, setup the handler and start it up. The timer alarm event handler
# uses the ITimer interface. We must pass in this "Main" object as ExtraObject.
#-------------------------------------------------------------------------------------
MyTimer = new<Timer()>
MyTimer.AddTimerAlarmHandler(MyTimerInterface,self)
MyTimer.SetAlarm(1000,0)

# Dynamically position the text and then display the window.
UpdateUITextPosition()
MainFrame.Show()
}

method unique MainFrameCloseHandler(WindowCloseEvent MyWindow,Base ExtraObject)
{
# Close the window and shutdown the script.
MainFrame.Close()
exit
}

method unique MainFrameResizeHandler(WindowResizeEvent MyWindow,Base ExtraObject)
{
# Change the vertical position of the single text control based on frame height.
UpdateUITextPosition()
}

method UpdateUITextPosition()
{
data<int> XPos = 10
data<int> YPos

# Calculate Y position of the text control based on frame height and set it.
YPos = (MainFrame.Height() / 2) - 10
TimerResultWindow.SetPos(XPos,YPos)
}

method UpdateAlarmText()
{
data<int> shared Counter

# Increment the shared counter and then update the window.
Counter.Inc()
TimerResultWindow.SetWindowText("Timer alarm event counter is " + Counter.Str())
}

data<Frame> MainFrame
data<Text> TimerResultWindow
data<Timer> MyTimer
}

# Interface class to handle the Timer alarm event.
class TimerInterface from<ITimer>
{
method virtual OnTimerAlarm(TimerAlarmEvent MyEvent,Base ExtraObject)
{
# The "Main" object is passed in as ExtraObject. Convert and update alarm text window.
data<Main> MainObject = ExtraObject as type<Main>
MainObject.UpdateAlarmText()
}
}

Page UpPage DownCopyright © 2010-2017
Aztec Development Group
All Rights Reserved

Download Aztec