ColdFrame: Initialization

ColdFrame initializes a domain when you call the generated operation Domain.Initialize. This operation takes a single parameter, defaulted to null, that designates the event queue to be used by the domain.

Only the first call to Initialize (after the program has been started or, if you're testing, after the domain has been torn down) has any effect. In particular, this supports cascade initialization.

Sequence of actions

The domain is initialized by

  1. initializing the domain's Event Queue (Dispatcher) with the supplied Event Queue, or (if it's null) by calling Domain.Events.Initialize,
  2. calling the domain setup operation,
  3. and then initializing all class attributes with default values and creating all singletons.

Everything is done in alphabetical order by class.

Event queues

By default, standard event queues start running as soon as they're created, while test event queues don't. When building a large program, it's best to use one event queue for all the domains and not to let it start until you've finished initialization.

You can create an unstarted standard event queue in your main program (or AUnit setup) by:

Q : constant ColdFrame.Project.Events.Event_Queue_P
  := new ColdFrame.Project.Events.Standard.Event_Queue_Base
     (Start_Started => False,
      Priority => System.Default_Priority,
      Storage_Size => 20_000);

(constant because you don't alter the access value; you can set the priority if you want, though there's no obvious benefit to doing so; and you can alter the stack size of the task context within which all the state machine actions are executed from the default, but it may indicate a problem with your design if you need to).

After you've initialized all the domains with Q, start it by

ColdFrame.Project.Events.Start (Q);

Domain setup operation

ColdFrame creates a procedure

private procedure Domain.Setup;

(private means it can't be called from outside the domain).

A null body is generated, to be replaced if necessary by appropriate code in the .impl directory.

The intended purpose of this operation is to set up the initial instances and associations. At the point it's called, there are no instances of any class, including singletons, and class variables with initial values haven't been set up.

«Singleton» classes

At the point where a singleton class instance is created, no «init» operations have been called. This means that the initial instances of other classes, and the associations between them, don't exist yet.

This will only matter if any of the singleton's code gets executed at this point; this can happen if the singleton has a state machine or is active. Or, of course, both, for added flavour.

Singletons with state machines

If a state machine has a completion transition (one which doesn't need an event to trigger it) from its initial state, ColdFrame performs that transition synchronously during instance creation.

This results in the entry actions in the next state being called during creation (if there aren't any, why do you have the completion transition?).

This is always problematic, but especially so for a singleton since the rest of the domain doesn't exist yet. The canonical solution is not to use completion transitions from initial states; instead, use an actual event posted by class initialization (called start, perhaps).

«Active» singletons

The task associated with an instance of an active class begins execution during instance creation. This is always likely to lead to difficulty, but it's especially so with singletons since the rest of the domain isn't initialized yet.

The standard solution for non-singleton tasks is to have an initial «entry», again called start perhaps, called at an appropriate point (again, you can use an event posted by class initialization).

An alternative for singletons is to have the task loop (with a short delay, please!) until the variable Domain_Initialized becomes True:

begin
   while not Domain_Initialized loop
      delay 0.01;
   end loop;
   ...

Class initialization

Classes are initialized in alphabetical order.

If you have a class attribute which is an access type (maybe a counterpart), the language will initialize it at elaboration but it won't be automatically re-initialized after teardown unless you give a default value (= null) in the model.

Class Timers may not be reinitialized properly after teardown.

After class attributes have been initialized, any operations stereotyped «init» are called, again in alphabetical order within the class.

This ordering means that, for most purposes, you'll probably only want to have one «init» operation in the domain.