comp.lang.ada
 help / color / mirror / Atom feed
From: Adam Beneschan <adam@irvine.com>
Subject: Re: Problem in "X (1).Re := X (1).Re + 1"
Date: Mon, 7 May 2012 14:28:52 -0700 (PDT)
Date: 2012-05-07T14:28:52-07:00	[thread overview]
Message-ID: <10294366.7.1336426132700.JavaMail.geo-discussion-forums@yngg23> (raw)
In-Reply-To: <5749033.1275.1336416838264.JavaMail.geo-discussion-forums@pbchd7>

On Monday, May 7, 2012 11:53:58 AM UTC-7, ytomino wrote:
> On Tuesday, May 8, 2012 12:37:44 AM UTC+9, Adam Beneschan wrote:
> > 
> > No.  But if you change the 1 to 1.0 then I think it will be OK.
> 
> Oops!
> 1.0 is correct.
> 
> > I'm not yet really familiar with the ins and outs of user-defined references
> > and user-defined indexing.  But my guess is that the phrase in A.18.2(147.17)
> > that says "Reference returns an object whose discriminant is an access value
> > that designates the element designated by Position" means that Reference
> > can't return an object whose discriminant designates a *copy* of the element.
> > If I understand your question correctly, this means that the scenario you're
> > concerned about can't happen.
> 
> Imagine an implementation of an reference-counted container.
> Probably, it's like below:
> 
> function Reference (Container : Vector; Position : Cursor) return Ref_Type is
> begin
>    --  if data is shared, do copy-on-write to prepare for change
>    --  (memory management and exclusive control is omitted in this pseudo-code)
>    if Container.Data_Block.Ref_Count > 1 then
>       Container.Data_Block.Ref_Count := Container.Data_Block.Ref_Count - 1;
>       Container.Data_Block := new Data_Block_Type'(
>          Length => Container.Data_Block.Length,
>          Elements => (1 .. Length => Container.Data_Block.Elements (1 .. Length)),
>          Ref_Count => 1);
>    end if;
>    -- return access value designated by Position
>    return (Element => Container.Data_Block.Elements (To_Index (Cursor))'Access);
> end Reference;
> 
> And, similar copy-on-write is inserted into Replace_Element and Update_Element.
> 
> In this container, Reference copies its elements as your saying. But the container comes to own copied elements, and Reference returns an access value that designates the element in same area. I hope that this is allowed for effective implementations.
> Besides, if this is disallowed in Ada.Containers.Vectors, please assume my original container.
> Surely you don't think that all reference-counted containers written by user are forbidden to implement user-defined indexing.

OK, I think I figured out what you were talking about.  Sorry, but your original post seemed to use a few words (like "implemented by reference-counting") and expect that readers would fill in the rest of the details.  Unfortunately, I'm not a mind-reader, so it took me a lot of effort to figure it out.  Maybe others here are better mind-readers than I am.  I don't know.

But I'm guessing that you're referring to an implementation where, when a copy of an element is made, the implementation doesn't make a copy immediately, but rather waits until somebody tries to modify either the original or the copy and *then* splits off a copy.  So in your example:

  X(1).Re := X(1).Re + 1.0;

you're assuming that X(1) was earlier created as a copy of something else--or that something else was created as a copy of X(1).  The main ways I can see that this could be done are by using the Copy or Assign operations of vectors, e.g.

  X := Copy(W);
  X(1).Re := X(1).Re + 1.0;

so that when X is created, it's done by creating references to all the elements in W rather than by copying the elements of W; and then making a new copy of an individual element when it needs to be modified.  Of course, it's silly to do this if the element type is Complex, since it's surely easier to copy two floats than to implement all the overhead needed to deal with references.  But I can imagine that it might make sense if the element type is ... um, more complex than Complex.  Or a whole lot bigger.

I'm still dubious that it can work, though.  Consider:

  X := V.Copy(W);                        -- (A)
  Ref1 := V.Constant_Reference (W, 1);   -- (B)
  Ref2 := V.Constant_Reference (X, 1);   -- (C)
  X(1).Re := X(1).Re + 1.0;              -- (D)

If the Copy function did not create any new copies of elements, then Ref1.Element and Ref2.Element will end up being accesses to the same element, after (C) is performed.  If the new copy of the element is not created until Reference is evaluated by the left side of statement (D), the result is that either Ref2.Element (or possibly Ref1.Element) will be pointing at the wrong thing.  

So it looks to me like the method you suggest shouldn't be allowed, even in your own container, since it would make it impossible to implement Constant_Reference  correctly.

My caveat still applies, though; this involves issues that I'm not yet completely familiar with, so it's possible that I made a serious error.  I'm hoping someone will come to my rescue if I did ... :)

                        -- Adam




  reply	other threads:[~2012-05-07 21:28 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-05 12:55 Problem in "X (1).Re := X (1).Re + 1" ytomino
2012-05-07 15:37 ` Adam Beneschan
2012-05-07 18:53   ` ytomino
2012-05-07 21:28     ` Adam Beneschan [this message]
2012-05-08  1:14       ` Randy Brukardt
2012-05-08 17:14         ` Adam Beneschan
2012-05-08 22:29           ` Randy Brukardt
2012-05-09  8:41             ` ytomino
2012-05-10  0:52               ` Randy Brukardt
2012-05-10  5:23                 ` ytomino
2012-05-09  9:29           ` ytomino
2012-05-10  0:58             ` Randy Brukardt
2012-05-10  4:26               ` ytomino
2012-05-15  6:09                 ` Randy Brukardt
2012-05-15 20:17                   ` ytomino
2012-05-16  0:01                     ` Randy Brukardt
2012-05-15 22:12               ` Simon Wright
2012-05-16  7:14                 ` Dmitry A. Kazakov
2012-05-09  8:05       ` ytomino
2012-05-09 11:03         ` ytomino
replies disabled

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