### 8.3 Most Features in One Example

The example shown on the following figure highlights most of the features of DSA. The system is based on a set of factories and workers and a storage. Each entity is a partition itself. A factory hires a worker from a pool of workers (hire - 1) and assigns a job (query - 2) to him. The worker performs the job and saves the result (reply - 3) in a storage common to all the factories. The worker notifies the factory of the end of his job (notify - 4).

When a worker has completed his job, the result must be saved in a common storage. To do this, we define a protected area in SP package Storage (see following code). An entryless protected object ensures atomic access to this area.

         package Storage is
            pragma Shared_Passive;

            protected Queue is
               procedure Insert (Q, R : Integer);
               procedure Remove
                 (Q : in Integer;
                  R : out Integer);
            private
            --  implementation removed
         end Storage;

Common is a Remote_Types package that defines most of the remote services of the above system (see following code). First, we define a way for the workers to signal the completion of his job. This callback mechanism is implemented using RAS Notify.

         with Storage; use Storage;
         package Common is
            pragma Remote_Types;

            type Notify is
               access procedure (Q : Integer);
            pragma Asynchronous (Notify);

            type Worker is
               abstract tagged limited private;
            procedure Assign
              (W : access Worker;
               Q : in Integer;
               N : in Notify) is abstract;

            type Any_Worker is
               access all Worker'Class;
            pragma Asynchronous (Any_Worker);

         private
            --  implementation removed
         end Common;

We define an abstract tagged type Worker which is intended to be the root type of the whole distributed objects hierarchy. Assign allows a factory to specify a job to a worker and a way for the worker to signal its employer the completion of this job. Any_Worker is a remote access to class wide type (RACW). In other words, it is a reference to a distributed object of any derived type from Worker class. Note that the two remote access types (Any_Worker and Notify) are declared as asynchronous. Therefore, any override of Assign will be executed asynchronously. To be asynchronous, an object of type Notify has to be a reference to an asynchronous procedure.

NewWorker is derived from type Worker and Assign is overridden.

         with Common, Storage; use Common, Storage;
         package NewWorkers is
            pragma Remote_Types;

            type NewWorker is new Worker with private;

            procedure Assign
              (W : access NewWorker;
               Q : Integer;
               N : Notify);
         private
            --  implementation removed
         end NewWorkers;

The following code shows how to derive a second generation of workers NewNewWorker from the first generation NewWorker. As mentioned above, this RT package can be duplicated on several partitions to produce several types of workers and also several remote workers.

         with Common, Storage, NewWorkers; use Common, Storage, NewWorkers;
         package NewNewWorkers is
            pragma Remote_Types;

            type NewNewWorker is new NewWorker with private;

            procedure Assign
              (W : access NewNewWorker;
               Q : Integer;
               N : Notify);
         private
            --  implementation removed
         end NewNewWorkers;

In the following code, we define a unique place where workers wait for jobs. WorkerCity is a Remote_Call_Interface package with services to hire and free workers. Unlike Remote_Types packages, Remote_Call_Interface packages cannot be duplicated, and are assigned to one specific partition.

         with Common; use Common;
         package WorkerCity is
            pragma Remote_Call_Interface;

            procedure Insert (W : in  Any_Worker);
            procedure Remove (W : out Any_Worker);
         end WorkerCity;

In order to use even more DSA features, Factory is defined as a generic RCI package (see sample above). Any instantiation defines a new factory (see sample above). To be RCI, this instantiation has to be categorized once again.

         with Storage; use Storage;
         generic
         package Factory is
            pragma Remote_Call_Interface;

            procedure Notify (Q : Integer);
            pragma Asynchronous (Notify);
         end Factory;

         with Factory;
         package NewFactory is new Factory;
         pragma Remote_Call_Interface (NewFactory);