comp.lang.ada
 help / color / mirror / Atom feed
* Chunks of finalized
@ 1997-10-03  0:00 Richard A. O'Keefe
  1997-10-03  0:00 ` Stephen Leake
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Richard A. O'Keefe @ 1997-10-03  0:00 UTC (permalink / raw)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 2693 bytes --]


Let's consider a stack, that might grow very large, or might be quite
small.  This is not an actual application, it's just the context for
what I want to understand.

One way to implement a stack like that is as a linked list of arrays,
plus a counter:

    type Stack_Chunk is array (0 .. Chunk_Size - 1) of Stack_Element;

    type Stack_Node;
    type Stack_Link is access Stack_Node;
    type Stack_Node is
       record
          Data: Stack_Chunk;
          Next: Stack_Link;
       end record;

    type Stack is
       record
          Count: Natural;
          List : Stack_Link;
          Spare: Stack_Link;
       end record;

Why the Spare?  Because a well known thing about implementing a stack
this way is that if you keep on pushing and popping just at the boundary
of a chunk, you can spend an awful lot of time allocating and freeing.
By keeping just one spare chunk, you can eliminate that problem.

The problem is, what if the stack elements are derived from
Ada.Finalization.Controlled?

The lifetime of an object contains at least the following steps:

    1. allocate raw storage
    2. initialise
    3. use
    4. finalise
    5. release raw storage.

In this stack example, if Chunk_Size is 10 and Count is 25, we might
have 3 records in the List and 1 Spare, for a total of 40 Stack_Elements
that have been _allocated_, but only 25 of which are _in use_.

I have some old Pascal code, using an intricate and rather fragile set
of M4 macros, that provided generic code doing this sort of thing.  In
that code, my framework ensured there were operations
	T$make(X)	convert raw storage to a valid T
	T$free(X)	convert a valid T back to raw storage
	T$reset(X)	make a valid T empty (release resources as far
			as possible while leaving the object valid)
for each type.  When a chunk is allocated, I'd call T$make() on the
elements.  When a chunk is freed, I'd call T$free() on the elements
first.  And when an element is popped from the stack, I'd call T$reset()
on the element.  (Obviously integer$reset and integer$free expanded to
nothing.)

I've been trying to figure out how to do this in Ada, and I don't think
I can.  If one is trying to implement a generic container data structure,
there is nothing one can do to tell the elements 'stay alive but forget
everything', except include such an operation as one of the generic
parameters.

What have I missed?

How is it that people using the Booch components don't find this
a problem?  (I haven't understood anything in the current Booch-95
components as doing this.)

-- 
John �neas Byron O'Keefe; 1921/02/04-1997/09/27; TLG,TLTA,BBTNOTL.
Richard A. O'Keefe; http://www.cs.rmit.edu.au/%7Eok; RMIT Comp.Sci.




^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~1997-10-07  0:00 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-10-03  0:00 Chunks of finalized Richard A. O'Keefe
1997-10-03  0:00 ` Stephen Leake
1997-10-04  0:00   ` Robert A Duff
1997-10-06  0:00     ` Tucker Taft
1997-10-07  0:00       ` Richard A. O'Keefe
1997-10-03  0:00 ` Robert A Duff
1997-10-05  0:00 ` Matthew Heaney

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