3 Module Managers

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].

3.1 Overview

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:

  1. If U is already in the module table, the module manager returns the entry in the module table.

  2. 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:

  1. The pickled functor stored at U is loaded.

  2. The module manager computes the full module urls for its imports. This step is detailed in Section 3.3 and Section 3.4.

  3. It recursively links all functors with the full module urls computed before. This yields the argument modules.

  4. It applies the functor body to the argument modules, which returns the module M.

3.2 Lazy Linking

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.

3.3 Import Specifications

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:

  1. If the import clause features a module url U, the full module name is U.

  2. 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/.

  3. 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

Application

Command processing and application termination

Chapter 1 of ``System Modules''

Module

Module managers

Chapter 2 of ``System Modules''

Constraint Programming

Search

Search engines

Chapter 4 of ``System Modules''

FD

Finite domain propagators and distributors

Chapter 5 of ``System Modules''

Schedule

Scheduling propagators and distributors

Chapter 6 of ``System Modules''

FS

Finite set propagators and distributors

Chapter 7 of ``System Modules''

RecordC

Feature constraints (record constraints with open arities)

Chapter 8 of ``System Modules''

Combinator

Deep-guard combinators

Chapter 9 of ``System Modules''

Space

First-class computation spaces

Chapter 10 of ``System Modules''

Distributed Programming

Connection

Connecting to running Oz processes

Chapter 12 of ``System Modules''

Remote

Remote module managers

Chapter 13 of ``System Modules''

URL

URL parsing and resolution routines

Chapter 14 of ``System Modules''

Resolve

URL resolving

Chapter 15 of ``System Modules''

Fault

Handling faults in distributed programs

Chapter 17 of ``System Modules''

Open Programming

Open

Support for files, sockets, and pipes

Chapter 20 of ``System Modules''

OS

POSIX compliant operating system support

Chapter 21 of ``System Modules''

System Programming

Pickle

Saving and loading of persistant values

Chapter 22 of ``System Modules''

Property

Querying and configuring engine properties

Chapter 23 of ``System Modules''

Error

Error handling routines

Chapter 24 of ``System Modules''

Finalize

Automatic garbage collection for native entities

Chapter 26 of ``System Modules''

System

Miscellaneous system related procedures (printing)

Chapter 27 of ``System Modules''

Window Programming

Tk

Classes and procedures for window programming

Chapter 28 of ``System Modules''

TkTools

Predefined abstractions to handle menus, dialogs, and so on

Chapter 29 of ``System Modules''

Graphical Tools

Browser

Incremental display of Oz values

``The Oz Browser''

Panel

Monitor and configure the running engine

``Oz Panel''

Explorer

Visual constraint programming tool

``Oz Explorer - Visual Constraint Programming Support''

Ozcar

Interactive debugger

``The Mozart Debugger''

Profiler

Profiling of Oz programs

``The Mozart Profiler''

Miscellaneous

ObjectSupport

Generic classes for object oriented applications

Chapter 30 of ``System Modules''

Table 3.1: System modules.


3.4 Url Resolution

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

A

/home/schulte/A.ozf

import  
   B at 'down/B.ozf' 
   C at 'http://www.foo.org/C.ozf'

B

/home/schulte/down/B.ozf

empty

C

http://www.foo.org/C.ozf

import D at 'D.ozf'

D

http://www.foo.org/D.ozf

empty

Figure 3.1: Example for resolving urls.


3.5 User-defined Module Managers

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''.

3.6 Functors in the Oz Programming Environment

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+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''.


Denys Duchier, Leif Kornstaedt and Christian Schulte
Version 1.4.0 (20080702)