comp.lang.ada
 help / color / mirror / Atom feed
From: Martin <martin.dowie@btopenworld.com>
Subject: Re: Breaking a circularity
Date: Mon, 28 Mar 2011 04:06:26 -0700 (PDT)
Date: 2011-03-28T04:06:26-07:00	[thread overview]
Message-ID: <0477ecf8-3ff0-4511-82af-f38587704ca3@l11g2000yqb.googlegroups.com> (raw)
In-Reply-To: dd0c7179-9e48-4366-9b1f-c5586b2c6e3c@e21g2000yqe.googlegroups.com

On Mar 28, 5:11 am, Gene <gene.ress...@gmail.com> wrote:
> Need some expert help here with a circularity in the data structures
> for a discrete event simulation.
>
> We need event queues and an arbitrary number of event types.  The
> handlers for events must have access to a simulation state record, so
> used a generic thus:
>
> generic
>    type State_Type is private;
> package Event_Queues is
>
>    type Event_Type is abstract tagged limited private;
>
>    procedure Handle(State : in out State_Type;
>                     Event : access Event_Type) is abstract;
>
>    type Event_Ptr_Type is access all Event_Type'Class;
>
>    procedure Add(Event_Queue : in out Event_Queue_Type;
>                  Time : in Time_Type;
>                  Event : access Event_Type'Class);
>
>    -- other methods not shown.
> private
>
>    type Event_Type is abstract record
>       Id : Positive;
>       Time : Time_Type;
>    end record;
>
>    function Sooner_Than(A, B : in Event_Ptr_Type) return Boolean;
>
>    -- We are just going to put a thin wrapper around Ada ordered sets
> to
>    -- implement our event queue.
>    package Event_Queues is
>      new Ada.Containers.Ordered_Sets(Event_Ptr_Type, Sooner_Than,
> "=");
>    type Event_Queue_Type is new Event_Queues.Set with null record;
>
> end Event_Queues;
>
> Here's the circularity:  Instantiating an event queue requires the
> simulation state type, but the simulation state must contain an event
> queue (of the instantiated type).
>
> This is the best I've come up with so far:
>
> private
>    type Event_Queue_Wrapper_Type;
>
>    type State_Type is
>       record
>          Future_Events : access Event_Queue_Wrapper_Type;
>          -- other stuff not shown
>       end record;
>
>    package Simulation_Events is
>      new Event_Queues(State_Type);
>
>    -- Now we can define the wrapper to contain the event queue.
>    type Event_Queue_Wrapper_Type is
>       record
>          Queue : Simulation_Events.Event_Queue_Type;
>       end record;
>
> Is there a cleaner way to do this?  The painful part is introducing a
> pointer to the event queue in State_Type just to break the
> circularity, when this seems superfluous and means I should make
> State_Type controlled to release the queue.


Not sure you can do better in the sense of removing the access but
perhaps you can bundle all that up into a generic wrapper? e.g.

package States is
   type State is record
      I : Integer;
   end record;
end States;

with Ada.Containers.Ordered_Sets;
generic
   type State_Type is private;
package Event_Queues is
   subtype Time_Type is Duration;
   type Event_Type is abstract tagged limited private;
   procedure Handle (State : in out State_Type;
                     Event : access Event_Type) is abstract;
   type Event_Ptr_Type is access all Event_Type'Class;
   type Event_Queue_Type is private;
   procedure Add (Event_Queue : in out Event_Queue_Type;
                  Time        : in     Time_Type;
                  Event       : access Event_Type'Class);
private
   type Event_Type is abstract tagged limited record
      Id   : Positive;
      Time : Time_Type;
   end record;
   function Sooner_Than (A, B : in Event_Ptr_Type) return Boolean;
   package Event_Queues is new Ada.Containers.Ordered_Sets
(Event_Ptr_Type, Sooner_Than, "=");
   type Event_Queue_Type is new Event_Queues.Set with null record;
end Event_Queues;

with Event_Queues;
generic
   type State_Type is private;
package Event_Queue_Wrappers is
   type Event_Queue_Wrapper_Type is private;
private
   type EQW_State_Type is
      record
         State         : State_Type;
         Future_Events : access Event_Queue_Wrapper_Type;
      end record;
   package Simulation_Events is new Event_Queues (EQW_State_Type);
   type Event_Queue_Wrapper_Type is record
         Queue : Simulation_Events.Event_Queue_Type;
      end record;
end Event_Queue_Wrappers;

with Event_Queue_Wrappers;
with States;

procedure Temp is
   package EQW is new Event_Queue_Wrappers (State_Type =>
States.State);
   EQ : EQW.Event_Queue_Wrapper_Type;
begin
   null;
end Temp;


At least that decouples the state your interested in from the queue
mechanism.

Better names might help too, why expose that it is a 'wrapper' to the
user? I'd probably call what I have a '_Wrapper' as 'Event_Queue' and
then find a better name for the Event_Queues - Event_Queues_With_State
perhaps.

-- Martin



  parent reply	other threads:[~2011-03-28 11:06 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-03-28  4:11 Breaking a circularity Gene
2011-03-28  9:59 ` Ludovic Brenta
2011-03-28 11:37   ` Simon Wright
2011-03-28 22:38     ` Gene
2011-03-29  3:01       ` Randy Brukardt
2011-03-28 19:47   ` Gene
2011-03-28 10:15 ` Simon Wright
2011-03-28 21:31   ` Gene
2011-03-28 11:06 ` Martin [this message]
2011-03-28 22:26   ` Gene
2011-03-29 16:28     ` Martin
replies disabled

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