From: herwin@gmu.edu (Harry Erwin)
Subject: Re: Safety of the Booch Ada 95 Components
Date: 1999/12/12
Date: 1999-12-12T21:57:13+00:00 [thread overview]
Message-ID: <1e2pl97.97q6v6s9u4jkN%herwin@gmu.edu> (raw)
In-Reply-To: x7vk8mmwjd0.fsf@pogner.demon.co.uk
Simon Wright <simon@pogner.demon.co.uk> wrote:
> herwin@gmu.edu (Harry Erwin) writes:
>
> > In C++, the equate operation for a container class C<T> is preferably
> > defined as follows (Sutter, Exceptional C++, Addison-Wesley, 2000):
> >
> > template <typename T>
> > C<T>& operator=(const C<T>& c)
> > {
> > if(&c == this) return *this; // not required; done for efficiency
> > C temp(c); // uses the copy constructor, may throw
> > swap(temp, *this); // swaps the guts of this container with
> > // temp. May not throw.
> > return *this; // May not throw.
> > } // the destructor for temp releases the memory originally in this
> > // container, and destructors may not throw
> >
> > This is strongly exception-safe and exception-neutral, since only the
> > copy constructor can throw, and that occurs before the guts are swapped.
> > Hence the container remains useable, and no objects are lost from it.
> > Now I've been looking at the Booch components for Ada 95, and have
> > noticed that the Copy function typically starts by clearing the To
> > container. That immediately implies that they are not exception-safe,
> > but I'm concerned that they may not be safe under self-assignment as
> > well. Is there something about the Ada 95 standard that guarantees that
> > there will be no aliasing of container args?
>
> (1) the Copy subprogram -- in this case
>
> procedure Copy (From : Queue'Class; To : in out Queue'Class);
>
> is used for copying queues using the same element type but different
> storage allocation strategies (Bounded, Unbounded). It's the
> equivalent of the C++
>
> virtual BC_TQueue<Item>& operator=(const BC_TQueue<Item>&);
In C++ 99, we'd use:
C1<T> source; // assume initialized
C2<T> destination(source.begin(), source.end()); // strongly safe
This uses the copy constructor with two iterator arguments.
Or we'd use:
destination.insert(position, source.begin(), source.edu());
which, like your Copy, is not strongly safe.
>
> in the abstract class template<class Item> class BC_TQueue.
>
> (2) I'm not quite sure what should occur if an exception happened in
> the middle of copying a queue; it would be reasonable to expect the
> data structure to be uncorrupted, but you couldn't expect any
> particular subset of the elements in the queue to have been copied.
>
> Nevertheless, I need to look at this one ..
>
> (3) The deep copy you expect on normal assignment of one Queue to
> another (Second := First;) is managed by having them be Controlled:
>
> type Container is abstract new Ada.Finalization.Controlled with private;
> type Queue is abstract new Container with private;
> type Bounded_Queue is new Queue with private;
>
> and (ALRM 7.6(17)):
>
> For an assignment_statement, after the name and expression have been
> evaluated, and any conversion (including constraint checking) has
> been done, an anonymous object is created, and the value is assigned
> into it; that is, the assignment operation is applied. (Assignment
> includes value adjustment.) The target of the assignment_statement
> is then finalized. The value of the anonymous object is then
> assigned into the target of the assignment_statement. Finally, the
> anonymous object is finalized. As explained below, the
> implementation may eliminate the intermediate anonymous object, so
> this description subsumes the one given in 5.2, ``Assignment
> Statements''.
Thanks. I'll nose around into this. It looks like the Ada language
hides a lot of the detail that a C++ 99 student has to learn to be anal
about.
>
> GNAT 3.11p not only eliminates the intermediate anonymous object, it
> special-cases the "A := A;" case; well, in the quick check I've just
> run:
>
> ...
> Queue_B_P1, Queue_B_P2 : Queue_Finalization_Test.Queue;
>
> begin
>
> Append (Queue_B_P2, '1');
> Append (Queue_B_P2, '2');
> Append (Queue_B_P2, '3');
> Append (Queue_B_P2, '4');
>
> Put_Line ("Queue_B_P2:");
> Print (Queue_B_P2);
>
> Queue_B_P1 := Queue_B_P2;
> Put_Line ("Queue_B_P1:");
> Print (Queue_B_P1);
>
> Queue_B_P1 := Queue_B_P1;
> Put_Line ("Queue_B_P1:");
> Print (Queue_B_P1);
> ...
>
> outputs
>
> initializing a Queue
> initializing a Queue
> Queue_B_P2:
> Item: 1
> Item: 2
> Item: 3
> Item: 4
> finalizing a Queue
> adjusting a Queue
> Queue_B_P1:
> Item: 1
> Item: 2
> Item: 3
> Item: 4
> Queue_B_P1:
> Item: 1
> Item: 2
> Item: 3
> Item: 4
> finalizing a Queue
> finalizing a Queue
Good, so self-assignment works.
--
Harry Erwin, PhD, <http://mason.gmu.edu/~herwin>
next prev parent reply other threads:[~1999-12-12 0:00 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
1999-12-10 0:00 Safety of the Booch Ada 95 Components Harry Erwin
1999-12-10 0:00 ` Simon Wright
1999-12-12 0:00 ` Harry Erwin [this message]
1999-12-13 0:00 ` Simon Wright
1999-12-12 0:00 ` Simon Wright
1999-12-12 0:00 ` Matthew Heaney
1999-12-10 0:00 ` Matthew Heaney
1999-12-10 0:00 ` Harry Erwin
1999-12-12 0:00 ` Simon Wright
1999-12-12 0:00 ` Harry Erwin
1999-12-13 0:00 ` Simon Wright
1999-12-10 0:00 ` Hyman Rosen
1999-12-10 0:00 ` Matthew Heaney
1999-12-11 0:00 ` Harry Erwin
1999-12-12 0:00 ` Robert Dewar
1999-12-12 0:00 ` Harry Erwin
1999-12-13 0:00 ` Kent Paul Dolan
1999-12-13 0:00 ` Robert I. Eachus
1999-12-13 0:00 ` Simon Wright
1999-12-13 0:00 ` Ted Dennison
1999-12-13 0:00 ` Hyman Rosen
1999-12-13 0:00 ` Robert I. Eachus
1999-12-14 0:00 ` Simon Wright
1999-12-15 0:00 ` Mats Weber
1999-12-17 0:00 ` Simon Wright
1999-12-15 0:00 ` Harry Erwin
1999-12-14 0:00 ` Matthew Heaney
1999-12-10 0:00 ` Harry Erwin
1999-12-13 0:00 ` Tucker Taft
replies disabled
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox