<< Prev | - Up - | Next >> |
So far we only dicussed how functor definitions can be developed in a modular fashion. This chapter explains how modular applications are executed.
The chapter is kept informal, a more detailed explanation of module managers and how module managers link applications can be found in [DKSS98].
A module manager maintains a module table. The module table maps urls (or to be more precise, full module urls) to modules or futures to modules.
A module manager links a module at url U as follows:
If U is already in the module table, the module manager returns the entry in the module table.
If U is not yet in the module table, the module manager creates a new future M and stores M under key U in the module table. As soon as the value of future M gets requested, the module manager installs a module from the url U.
Linking is done lazily: only when the value of the module is requested (usually implicitly, when the application attempts to access an exported feature), the module gets installed. A module with full module url U is installed as follows, where the installation procedure returns a module M:
The pickled functor stored at U is loaded.
The module manager computes the full module urls for its imports. This step is detailed in Section 3.3 and Section 3.4.
It recursively links all functors with the full module urls computed before. This yields the argument modules.
It applies the functor body to the argument modules, which returns the module M.
In the above section we have discussed that modules are subject to lazy linking: Only when a module is requested, the functor to compute that module gets loaded.
Lazy linking has dramatic effect on the startup time of an application: applications can start small in a fraction of a second and load additional functionality on demand. And all this happens completely transparently.
System modules are also subject to dynamic linking. Even though module managers give the impression that the system modules are always there, they are also loaded on demand. An application that takes good advantage of that fact is for example the Oz Programming Interface which starts quickly even though it imports all system modules.
The entire import part of a functor is called the import specification. Each import specification consists of several import clauses. Each import clause consists of a mandatory module name and an optional module url that must be preceded by the at
keyword.
For example, in the import specification
import
DB
MyForm at 'Form.ozf'
the first import clause is DB
which just consists of the module name DB
and does not provide a module url. The second import clause is MyForm at 'Form.ozf'
which consists of the module name MyForm
and the module url 'Form.ozf'
.
The first step in linking a functor is that the module manager computes for each import clause the full module url. This is done according to the following rules:
If the import clause features a module url U, the full module name is U.
If the import clause consists of a module name M only, where M is the name of a system module, the full url is x-oz://system/
M, that is the module name prefixed by x-oz://system/
.
If the import clause consists of a module name M only and M is not the name of system module, the full url is M.ozf
, that is the module name suffixed by .ozf
.
All currently defined system modules are listed in Table 3.1.
Name | Description | Documentation |
---|---|---|
Application Programming | ||
| Command processing and application termination | |
| Module managers | |
Constraint Programming | ||
| Search engines | |
| Finite domain propagators and distributors | |
| Scheduling propagators and distributors | |
| Finite set propagators and distributors | |
| Feature constraints (record constraints with open arities) | |
| Deep-guard combinators | |
| First-class computation spaces | |
Distributed Programming | ||
| Connecting to running Oz processes | |
| Remote module managers | |
| URL parsing and resolution routines | |
| URL resolving | |
| Handling faults in distributed programs | |
Open Programming | ||
| Support for files, sockets, and pipes | |
| POSIX compliant operating system support | |
System Programming | ||
| Saving and loading of persistant values | |
| Querying and configuring engine properties | |
| Error handling routines | |
| Automatic garbage collection for native entities | |
| Miscellaneous system related procedures (printing) | |
Window Programming | ||
| Classes and procedures for window programming | |
| Predefined abstractions to handle menus, dialogs, and so on | |
Graphical Tools | ||
| Incremental display of Oz values | |
| Monitor and configure the running engine | |
| Visual constraint programming tool | |
| Interactive debugger | |
| Profiling of Oz programs | |
Miscellaneous | ||
| Generic classes for object oriented applications |
Given the full url names for each import clause, the module manager determines the urls from which functors are to be loaded by url resolution. Url resolution takes two urls (one is called the base url and the other is called the local url) as input and computes a new resolved url. The process of url resolution you already know from organizing your html-pages: a url for a relative href-link is resolved with respect to the base url of the containing document.
In this respect, a module manager will behave similarly to a web-browser. When it installs a module that was loaded from url U, the latter's full import urls are resolved with respect to U. Figure 3.1 shows a small example, where the root functor has the absolute filename /home/schulte/A.ozf
.
Name | Resolved url | Import specification |
---|---|---|
|
|
|
|
| empty |
|
|
|
|
| empty |
When the engine starts it has the root module manager that executes the root functor and subsequently links imported functors. However, in many cases it is desirable that applications can create private module managers that just link particular functors.
As an example, suppose we want to use more than a single data base as implemented by the functor DB.ozf
as shown in Section 2.3
In the Oz Programming Interface, we can link DB.ozf
twice with two new and different module managers as follows:
[DBA]={Module.link ['DB.ozf']}
[DBB]={Module.link ['DB.ozf']}
Both DBA
and DBB
refer to two independent data bases.
You can observe lazy linking easily. Browsing DBA
as follows
{Browse DBA}
shows DBA<Future>
, which means that DBA
still refers to a future. Requesting the module by, for example, adding an entry to the data base is also reflected in the Browser: the display of DBA<Future>
is replaced by a representation of the module's value.
That both module managers work independently can be verified by browsing DBB
.
Module.link
takes a list of urls, creates a new module manager and maps each url U to the module created by linking the functor at U. Reference documentation can be found in Chapter 2 of ``System Modules''.
Functors are first class entities in the language that can of course also be created in the Oz Programming Interface. This eases development of functors considerably.
Suppose the following demo functor definition
declare
functor F
export Pam
define
fun {DoPam Xs P Ys}
case Xs of nil then Ys
[] X|Xr then {DoPam Xr P {P X}|Ys}
end
end
fun {Pam Xs P}
{DoPam Xs P nil}
end
end
After feeding the definition, the defined functor can be applied as follows:
[M]={Module.apply [F]}
The module M
can be used in the OPI as usual, that is
{Browse {M.pam [1 2 3] fun {$ I} I+1 end}}
displays the list [4 3 2]
.
Module.apply
takes a list of functors as argument, creates a new module manager, applies each functor element and returns the resulting list of modules. It is also possible to specify the base url used in linking the argument modules of the applied functor. For more information see Chapter 2 of ``System Modules''.
Of course, also other situations allow to take advantage of first-class functors and that they can be applied by module managers. In particular they are useful for remote module managers that create new Oz processes on networked computers. You can learn more on this issue in ``Distributed Programming in Mozart - A Tutorial Introduction''.
<< Prev | - Up - | Next >> |