comp.lang.ada
 help / color / mirror / Atom feed
From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Augmented active object pattern
Date: Wed, 18 Apr 2018 10:01:27 +0200
Date: 2018-04-18T10:01:27+02:00	[thread overview]
Message-ID: <pb6u0n$10q2$1@gioia.aioe.org> (raw)

The following is a way to have an encapsulated task (active object etc) 
which hopefully works around most of the language issues.

    type Object_Type;
    task type Worker_Task (Owner : not null access Object_Type'Class) is
       entry Quit;
       ... -- other entries
    end Worker_Task;
    type Worker_Ptr is access all Worker_Type;

    type Object_Type is new Ada.Finalization.Limited_Controlled with
       Worker : Worker_Ptr;
       ...
    end record;
    overriding procedure Finalize (Object : in out Object_Type);

This was the usual part.
----------------------------------------------------
    task body Worker_Task is
    begin
       while Is_Callable (Environment_Task) loop
          select
             accept Quit;
             exit;
          or ... -- other entries
          else   -- or delay
             null;
          end select;
          .. -- Doing a chunk of main job
       end loop;
    end Worker_Task;

    procedure Finalize (Object : in out Object_Type) is
       procedure Free is
          new Ada.Unchecked_Deallocation (Worker_Task, Worker_Ptr);
    begin
       if Object.Worker /= null then
          if Environment_Task /= Current_Task
             Object.Worker.Quit; -- Request exiting
          end if;
          while not Object.Worker'Terminated loop
             delay 0.001;
          end loop;
          Free (Object.Worker);
       end if;
       ...
    end Finalize;
-----------------------------------------------------
New here is handling the library level finalization deadlock. The task 
terminates itself when the environment task is not "callable" emulating 
forbidden terminate alternative for this special case. Below the library 
level this does not work, so the Quit entry is needed to handle these as 
before. In its part Quit does not work (deadlocks) at the master's level.

Within Finalize, we check if things happen on the library level. If not 
we request task termination the usual way via entry call to Quit. At the 
library level that would deadlock (thanks to RM 7.6.1(4)), so Quit is 
not called and task terminates itself recognizing the special case 
hidden in Annotated RM C.7.1(10) as a notice.

Note that when the pointer is declared below the library level the 
deadlock reemerges and there is no solution to that whatsoever, because 
the "callable trick" works exclusively for the environment task.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de


                 reply	other threads:[~2018-04-18  8:01 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox