Introduction to Processes
The Inq Process Environment
This section introduces the Inq process environment. Further detail on creating processes and how they can cooperate using Inq concurrency features is covered in Processes and Concurrency.
Inq applications comprise a number of clients that cooperate for shared resources via their connected server. Inq supports the concept of a process in both the server and client environments, where a process is a thread of execution with its own node space, rooted at the node given by the path $root. On initialisation a client makes a long-lived connection to its server. When the server accepts the connection it creates a process to handle all interaction with the client.
A process is idle until it receives an event, such as a service request sent by another process. A client and its associated server-side process are able to make service requests of one-another. Within the server, the Inq run-time arbitrates between competing processes for shared resources such as database usage and mutation of shared application data objects.
The client runs a single process that handles events from the graphics system as well as service requests and other events received from the server, for example those raised when application data are updated. The following diagram depicts this relationship:
The server-side process associated with a connected client is known as a User Process. In addition to these processes, Inq script supports the creation of child processes and detached processes. A detached process may, itself, create child processes.
A process has an input channel and may have an output channel. These are available at $process.ichannel and $process.ochannel, although in the case of the Client and User processes it is not usually necessary to directly access these.
A process receives service requests and other events at its input channel. The input and output channels of the Client and User processes are connected to each other, so the Client process invokes services in its associated User process by sending the invocation requests to its output channel and vice-versa.
The Process Event Model
A process waits for events at its input channel. An event can be a service invocation, a data modification notice, a timer or any of the explicit events that a process can arrange to listen for. When an event arrives the process wakes, handles the event and then returns to wait at its input channel:
When a process handles an event it uses its own thread. There are two other mechanisms by which threads external to Inq can safely occupy a process's environment.
- A process can handle asynchronous JMS broker messages. The message broker implementation provides the thread on which the message is delivered.
- A process may start one or more plugins. A plugin is an extension of com.inqwell.any.AbstractPlugin and allows a system external to the Inq environment to maintain typedef instances by calling its create(), modify() or delete() methods and to use the process's transaction if required by calling the begin() and end() methods.
For broker messages there are implications for automatic message acknowledgement that require the message to be processed in the receiving thread; it cannot be dispatched to the process's thread in this case.
The plugin model expects the implementation to start its own thread but warrants that calls back to any of the above methods complete synchronously.
Inq guarantees that these threads interleave their execution inside the process context with the process's own thread. The function to handle a broker message will run to completion. The plugin callbacks create(), modify() and delete() will do likewise; furthermore if the implementation calls begin() to open a transaction then all callbacks are completed. Not until end() is called can the process's thread run again.
The Client Process
The Client process handles events received from the User process in the server and so acts as the thread for executing requests made by the server. The client is also running the Java graphics thread and therefore separately handles those events arising from user input and other aspects of the host graphics system.
These two threads of execution share the node space of the Client process. To achieve thread safety surrounding access to the node space these threads run to their natural completion before allowing the other to run. The Client process is allowed to access graphical elements directly and the Inq runtime ensures that the necessary thread safety issues surrounding access to Java graphical components is obeyed. This may mean that sections of Inq script that appear to be executing in a single thread may swap between the Client process and Java graphics threads as needs demand, however this is never something that the Inq programmer needs to handle or even be aware of.
Detached and Child Processes
In the server, it is possible to create detached processes. These are processes that are not associated with a connected client and can be used to perform service requests invoked within the server itself, for example from a User process that is not willing to wait for the (presumably lengthy) processing to complete.
A detached process has its own node space and is completely unrelated to the process that created it. However, any process can create child processes. In this case a parent and child process are related, in that if the parent terminates all its children will terminate also. A child process still has its own node space and competes on equal terms with any other process in the server for shared resources.
When a detached or child process is created it may be use the same input channel as the process that created it. Otherwise a new one is created for that process. The usual combination of detached vs. child and exclusive vs. shared input channels is to create a detached process with its own input channel and have that process create any number of child processes that share its input channel. This process group then forms a set of threads that can accept events on a single input channel and have them dispatched to any available process with a fixed maximum running simultaneously.
Detached and child processes are not connected to any sort of peer process like the Client and User processes are, so they don't have an output channel.
Event Flows Between Processes
In later sections we will see how instances of application entities, called managed instances and defined by an Inq typedef block, cooperate with the Inq transaction model to raise events as they move through the life-cycle of creation, mutation and destruction. Further, within the server, Inq controls how references to managed instances are shared between all processes that acquire them.
This system gives rise to an event flow that outlined here. Events can be captured and processed by scripted functions, a topic that we cover in the section on Events. As well as this, Inq itself processes these events in the following ways:
- Inq propagates events arising from a managed instance to all observers of that instance, regardless of who (that is which process) is holding the reference.
- If the process is a User process, the event is propagated to the connected Client process.
- Propagated events received at a client process are mirrored in the client's node space, that is updates and structure alterations are replicated in the Client.
- Events in the Client (whether occurring because of propagation from the User process or arising from local processing) are dispatched to any observing GUI components. This topic is covered further in the section GUI Basics.
All events are received at a process's input channel and processed sequentially. Only when this processing is complete is the next event in the channel then dispatched.
Server-Side Event Flow
Suppose, within the server, processes A and B are both holding a reference to a managed instance that A then updates. With process B also referring to the same managed instance, the event flow is as depicted below:
For this flow to occur, process A and B must have assembled a structure that is event-live, something that is discussed in the section Building Event Structures.
Process Event Types
The table below summarises the types of event each process type can receive and what, if anything, the Inq environment does with them.
|Service Request||Dispatched by Inq to the specified service|
|Timer||Dispatched by Inq to the specified function|
- A User process has a connected Client peer. Events marked are forwarded by Inq to the Client process.
- Corresponding events are mirrored by Inq in the Client process node space, creating them where appropriate and causing the same event to be raised. Depending on the prevailing GUI configuration the event may be dispatched by the graphics thread also.
- All events marked may
be dispatched to an Inq scripted function by use of the listen
NoteTypedef Instance events are propagated by the process that raised them through all node spaces that hold a reference to the instance. A node space structure is only manipulated by its owning process, so while these events can be listened for, this is less common than dispatching Typedef Instance events.
- Function Execution events are raised when a function is entered or returned from and offer a way of batching the events raised by a transaction into a single dispatch. This is covered in the Events section.
- Timers offer a way for a process to awaken itself at regular intervals or at some future time. These are also covered in Events.