The UI Engine is implemented in Java; you can easily extend its behavior through subclassing. Adding new widgets is possible if you follow the guidelines described in Implementing ULC objects. In the remainder of this section, we discuss the two ways the UI Engine can work in the deployment of your application.
In this case, the UI Engine is running as a multithreaded server process listening on a well known port; different applications connect to that server.
A listener thread accepts connections from applications and creates
connection objects for each application client. A thread in the
connection object receives requests from applications and posts them into an
Abstract Windowing Toolkit (AWT) event queue. Events and callbacks
returning from the UI Engine to the application are put into a write queue of
the associated connection object and processed inside a separate writer thread
(left side of the following illustration):
The AWT main thread reads and processes events from the AWT event queue. These requests either create objects that are registered for later reference in the connection's registry or call methods on already existing objects.
All manipulation of the widget tree is serialized, so explicit synchronization is not necessary. Because callbacks from the UI to the application never wait for results synchronously, blocking cannot occur in the main thread. Both design decisions simplify the architecture considerably and improve its robustness.
The architecture of the application side of ULC is similar to that of the UI Engine side. Every application has a connection object that handles asynchronous communication by means of two threads and maintains the faceless halves of objects in a registry (right side of the previous illustration).
In this case, the UI Engine and application switch roles: the UI
Engine becomes the client and connects to the application, which runs as a
server. In this case, the listener thread runs in the application
server and accepts connections from UI Engine components. For every
connection, a new connection object is created that establishes an independent
context for running the application.
This architecture is very similar to the one depicted previously. In fact, the connection objects are identical in both cases. The most significant difference is that in this case, the application code runs in parallel within a single address space. As a result, you must protect your data from synchronization problems arising from concurrent access. For more information, see ULC and Server Smalltalk.