From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, T_FILL_THIS_FORM_SHORT autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,2fa4069595cb9ef7 X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII Path: g2news2.google.com!postnews.google.com!l11g2000yqb.googlegroups.com!not-for-mail From: Martin Newsgroups: comp.lang.ada Subject: Re: Breaking a circularity Date: Mon, 28 Mar 2011 04:06:26 -0700 (PDT) Organization: http://groups.google.com Message-ID: <0477ecf8-3ff0-4511-82af-f38587704ca3@l11g2000yqb.googlegroups.com> References: NNTP-Posting-Host: 20.133.0.8 Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-Trace: posting.google.com 1301310388 2223 127.0.0.1 (28 Mar 2011 11:06:28 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Mon, 28 Mar 2011 11:06:28 +0000 (UTC) Complaints-To: groups-abuse@google.com Injection-Info: l11g2000yqb.googlegroups.com; posting-host=20.133.0.8; posting-account=g4n69woAAACHKbpceNrvOhHWViIbdQ9G User-Agent: G2/1.0 X-HTTP-UserAgent: Mozilla/5.0 (Windows NT 5.1; rv:2.0) Gecko/20100101 Firefox/4.0,gzip(gfe) Xref: g2news2.google.com comp.lang.ada:19509 Date: 2011-03-28T04:06:26-07:00 List-Id: On Mar 28, 5:11=A0am, Gene 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. =A0The > handlers for events must have access to a simulation state record, so > used a generic thus: > > generic > =A0 =A0type State_Type is private; > package Event_Queues is > > =A0 =A0type Event_Type is abstract tagged limited private; > > =A0 =A0procedure Handle(State : in out State_Type; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 Event : access Event_Type) is abs= tract; > > =A0 =A0type Event_Ptr_Type is access all Event_Type'Class; > > =A0 =A0procedure Add(Event_Queue : in out Event_Queue_Type; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Time : in Time_Type; > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Event : access Event_Type'Class); > > =A0 =A0-- other methods not shown. > private > > =A0 =A0type Event_Type is abstract record > =A0 =A0 =A0 Id : Positive; > =A0 =A0 =A0 Time : Time_Type; > =A0 =A0end record; > > =A0 =A0function Sooner_Than(A, B : in Event_Ptr_Type) return Boolean; > > =A0 =A0-- We are just going to put a thin wrapper around Ada ordered sets > to > =A0 =A0-- implement our event queue. > =A0 =A0package Event_Queues is > =A0 =A0 =A0new Ada.Containers.Ordered_Sets(Event_Ptr_Type, Sooner_Than, > "=3D"); > =A0 =A0type Event_Queue_Type is new Event_Queues.Set with null record; > > end Event_Queues; > > Here's the circularity: =A0Instantiating 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 > =A0 =A0type Event_Queue_Wrapper_Type; > > =A0 =A0type State_Type is > =A0 =A0 =A0 record > =A0 =A0 =A0 =A0 =A0Future_Events : access Event_Queue_Wrapper_Type; > =A0 =A0 =A0 =A0 =A0-- other stuff not shown > =A0 =A0 =A0 end record; > > =A0 =A0package Simulation_Events is > =A0 =A0 =A0new Event_Queues(State_Type); > > =A0 =A0-- Now we can define the wrapper to contain the event queue. > =A0 =A0type Event_Queue_Wrapper_Type is > =A0 =A0 =A0 record > =A0 =A0 =A0 =A0 =A0Queue : Simulation_Events.Event_Queue_Type; > =A0 =A0 =A0 end record; > > Is there a cleaner way to do this? =A0The 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, "=3D"); 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 =3D> 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