comp.lang.ada
 help / color / mirror / Atom feed
* Generic access type convention and aliasing
@ 2013-05-06  0:20 Yannick Duchêne (Hibou57)
  2013-05-06  5:55 ` Yannick Duchêne (Hibou57)
  0 siblings, 1 reply; 11+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-05-06  0:20 UTC (permalink / raw)


Hi people,

Things are working as expected, but I still wonder and welcome other's  
feeling on the topic.

I have a generic memory allocator, which is instantiated with a  
constrained object type (objects of an average size ranging from 10 to 20  
KB) and an access type to that object type. The object type is typically  
an array type with fixed bounds (statically known constraints).


     generic
        Element_Type is private;
        Element_Access is access Element_Type;
     package Allocators
        …
     end;


In the generic declaration, I'm not allowed to express the requirement on  
the access type to use the C convention.


     Element_Access is access Element_Type
        with Convention => C;
        -- Not allowed: generic types can't specify
        -- a representation clause.


An allocator returns the allocation result in a discriminated record  
looking like this:


     type Result_Type (Allocated : Boolean := False) is
        record
           case Allocated is
              when False =>
                 null;
              when True =>
                 Element : Element_Access
                    with Convention => C;
           end case;
        end record;


I'm not allowed to add a representation requirement to the generic access  
parameter type, but GNAT let me specify the C convention for a variable  
(*) of that type in the record type.

I don't want the variable in the record to be simply of type  
`Element_Access` as‑is, and so even if the type is fully constrained and  
there is no unavoidable technical needs for storing any constraint data at  
the address designated by the access variable; I prefer it to be explicit,  
so the `Convention => C`.

Do you believe it's enough to be safe? Is it enough for preventing any  
compiler to believe there may be constraints data stored at the address  
designated by the access type, and so even if the generic parameter does  
not enforce it?

Or should I also give the C convention to each access types used to  
instantiate this generic? That's an option, but I don't like it: there is  
no way to enforce it, so it is not safe to me; too much easy to forget  
without any way to make the compiler flag it.

(*) A variable which I would enjoy to force to be a constant after record  
initialization, but I can't; another story.


The second question I optionally wonder about. I initially created the  
access variable value using `Ada.Unchecked_Conversion` applied to a  
numeric type (as indeed, the result I retrieve is numeric, because it may  
be an error status instead of an address, depending on the range the  
result belongs to). But GNAT did not enjoyed this and complained the  
resulting access type returned by the unchecked conversion, may present  
aliasing problem. The memory is allocated with `mmap` using `MAP_PRIVATE`,  
so there is no risk of aliasing (except in case of nasty OS failure), but  
I could not make GNAT understand it (*). I worked around it using a  
two‑instructions assembly procedure to do the conversion from the numeric  
type to the access type (to an access variable with convention C). I don't  
really expect there exist a way to tell GNAT the access does not present  
aliasing issues, but still worth to ask for it if ever on the contrary  
there exist a way to tell it.


(*) It just stop complaining if I added `pragma No_Strict_Aliasing  
(Element_Access)`, but that's not a way to tell it there is no risk of  
aliasing with that access type: the contrary.


-- 
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University



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

* Re: Generic access type convention and aliasing
  2013-05-06  0:20 Generic access type convention and aliasing Yannick Duchêne (Hibou57)
@ 2013-05-06  5:55 ` Yannick Duchêne (Hibou57)
  2013-05-07  0:56   ` Randy Brukardt
  0 siblings, 1 reply; 11+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-05-06  5:55 UTC (permalink / raw)


Le Mon, 06 May 2013 02:20:03 +0200, Yannick Duchêne (Hibou57)  
<yannick_duchene@yahoo.fr> a écrit:
>
> (*) A variable which I would enjoy to force to be a constant after  
> record initialization, but I can't; another story.

I also wished I could specify it must be a limited access type. Out of  
curiosity, I searched the web on this topic, and found this was already  
proposed. See this AI:

http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai05s/ai05-0142-2.txt?rev=1.3

The status is “Work item”.

Although just a proposal, I wanted to try (even before I've seen this AI)  
in case GNAT may implement this proposal, but it seems to not (it just  
complains “subtype indication expected” when it sees “limited”).


-- 
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University



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

* Re: Generic access type convention and aliasing
  2013-05-06  5:55 ` Yannick Duchêne (Hibou57)
@ 2013-05-07  0:56   ` Randy Brukardt
  2013-05-07  6:02     ` Yannick Duchêne (Hibou57)
  0 siblings, 1 reply; 11+ messages in thread
From: Randy Brukardt @ 2013-05-07  0:56 UTC (permalink / raw)


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

"Yannick Duchêne (Hibou57)" <yannick_duchene@yahoo.fr> wrote in message 
news:op.wwneq7xtule2fv@cardamome...
>I also wished I could specify it must be a limited access type. Out of 
>curiosity, I searched the web on this topic, and found this was already 
>proposed. See this AI:
>
>http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai05s/ai05-0142-2.txt?rev=1.3
>
>The status is "Work item".

No, it's "No Action". This was a discarded alternative to what eventually 
was implemented with explicitly aliased parameters and generalized 
references. We eventually realized that access discriminants already had the 
correct semantics so we didn't need a new feature for that.

So I wouldn't wait for any implementation of this proposal. :-)

                                     Randy.




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

* Re: Generic access type convention and aliasing
  2013-05-07  0:56   ` Randy Brukardt
@ 2013-05-07  6:02     ` Yannick Duchêne (Hibou57)
  2013-05-07  6:42       ` Yannick Duchêne (Hibou57)
  2013-05-07 17:34       ` AdaMagica
  0 siblings, 2 replies; 11+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-05-07  6:02 UTC (permalink / raw)


Le Tue, 07 May 2013 02:56:34 +0200, Randy Brukardt <randy@rrsoftware.com>  
a écrit:
> We eventually realized that access discriminants already had the correct  
> semantics so we didn't need a new feature for that.

I don't see how:


     package Storages is

        type Element_Type …; -- With the real case, a generic parameter.

        type Element_Access is access Element_Type;

        type Instance_Type
          (Element : Element_Access := null) is
           limited
           private;

        function Create
           return Instance_Type;

     private

        type Instance_Type
          (Element : Element_Access := null) is
           null record; -- With the real case, management data.

        function Create
           return Instance_Type
           is (Instance_Type'(Element => null));

     end Storages;

     S1 : Storages.Instance_Type  := Storages.Create;
     S2 : Storages.Instance_Type  := S1; -- Illegal.
     A  : Storages.Element_Access := S1.Element; -- However still legal.


That makes the `Element` member constant (one of the thing I wanted); that  
does not prevent from copying it. Implicit deference, even if it avoids  
direct use of the access member (syntactic sugar, not added safety,  
although a good idea), does not prevent copying it neither, as it requires  
to expose the access discriminant in the public part. I know no way to  
prevent copying this member, except wrapping every use of the access  
member in many functions and procedures or using reader/updater callbacks,  
which is something I prefer to avoid; that's why I was looking at this AI  
about limited access types (didn't care enough for its status, sorry, I  
note this is indeed “No action”).

By the way as a side note, even if using a boolean discriminant for the  
storage allocation status is expressive, using null for the access and  
that access as a discriminant, is more resilient, as an error with it when  
null, will be more surely caught at runtime whenever compiled without  
validity checking, where a not‑really existing member, thus returning  
probably not‑null garbage, may have enough time to break something before  
being caught.


-- 
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University


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

* Re: Generic access type convention and aliasing
  2013-05-07  6:02     ` Yannick Duchêne (Hibou57)
@ 2013-05-07  6:42       ` Yannick Duchêne (Hibou57)
  2013-05-07 17:34       ` AdaMagica
  1 sibling, 0 replies; 11+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-05-07  6:42 UTC (permalink / raw)


Le Tue, 07 May 2013 08:02:58 +0200, Yannick Duchêne (Hibou57)  
<yannick_duchene@yahoo.fr> a écrit:
> Implicit deference, even if it avoids direct use of the access member  
> (syntactic sugar, not added safety, although a good idea)

If it was a function return a view (either read, read/write or write),  
that would not be only syntactic sugar any‑more.

I forget too much about C++, so I will request help from C++ gurus if  
there are some here: I feel to remember something similar existed with  
C++, where a function could return an object by reference instead of  
returning a pointer to it. I am wrong or not? If I'm not wrong, I however  
don't remember if it was safe enough: did it allow to get a pointer from  
that returned reference? (if so, that's not safe and so not worth).

If the implicit deference could specify a discriminant only visible in the  
private part, that would be OK (the public declaration would just have to  
tell what the type is).

-- 
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University

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

* Re: Generic access type convention and aliasing
  2013-05-07  6:02     ` Yannick Duchêne (Hibou57)
  2013-05-07  6:42       ` Yannick Duchêne (Hibou57)
@ 2013-05-07 17:34       ` AdaMagica
  2013-05-07 19:08         ` Yannick Duchêne (Hibou57)
  1 sibling, 1 reply; 11+ messages in thread
From: AdaMagica @ 2013-05-07 17:34 UTC (permalink / raw)


RM 3.7(9/2) A discriminant that is defined by an access_definition is called an access discriminant and is of an anonymous access type.

This is not an access discriminant:

        type Element_Access is access Element_Type;
        type Instance_Type
          (Element: Element_Access := null) is limited private; 

Access disciminants are uncopiable.

For an example of use see (shameless plug):
http://www.christ-usch-grein.homepage.t-online.de/Ada/Smart_Pointers.html

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

* Re: Generic access type convention and aliasing
  2013-05-07 17:34       ` AdaMagica
@ 2013-05-07 19:08         ` Yannick Duchêne (Hibou57)
  2013-05-07 21:03           ` Jacob Sparre Andersen news
  0 siblings, 1 reply; 11+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-05-07 19:08 UTC (permalink / raw)


Le Tue, 07 May 2013 19:34:58 +0200, AdaMagica  
<christ-usch.grein@t-online.de> a écrit:
>
> This is not an access discriminant:

Oops someone flagged…, yes, sorry, I made multiple tests and did not  
notice when I posted (only later and too late).

>
> Access disciminants are uncopiable.

If so, that's *very easily defeated*:


     procedure Foo is

        package Storages is

           type Element_Type is new Integer;

           type Instance_Type
             (Element : access Element_Type := null) is
              limited
              private;

           function Create
              return Instance_Type;

        private

           I : aliased Element_Type;

           type Instance_Type
             (Element : access Element_Type := null) is
              null record;

           function Create
              return Instance_Type
              is (Instance_Type'(Element => I'Access));

        end Storages;

        type Pool_Specific_Access is access Storages.Element_Type;
        type General_Access is access all Storages.Element_Type;

        S  : Storages.Instance_Type  := Storages.Create;
        A1 : Pool_Specific_Access := S.Element; -- Illegal.
        A2 : access Storages.Element_Type := S.Element; -- However still  
legal.
        A3 : General_Access := S.Element; -- And the same.

     begin -- Foo

        A2.all := 2;

     end Foo;


Far from what limited access type would be.


-- 
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University

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

* Re: Generic access type convention and aliasing
  2013-05-07 19:08         ` Yannick Duchêne (Hibou57)
@ 2013-05-07 21:03           ` Jacob Sparre Andersen news
  2013-05-07 22:13             ` Yannick Duchêne (Hibou57)
  0 siblings, 1 reply; 11+ messages in thread
From: Jacob Sparre Andersen news @ 2013-05-07 21:03 UTC (permalink / raw)


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

"Yannick Duchêne (Hibou57)" <yannick_duchene@yahoo.fr> wrote in message 
news:op.wwp94yh5ule2fv@cardamome...
...
> Access disciminants are uncopiable.
>
>If so, that's *very easily defeated*:

The issue isn't really whether they can be copied, but rather whether their 
lifetime can be extended beyond that of the enclosing object. And the answer 
to this latter question is no. (This allows the enclosing object to include 
tracking for when the access exists, as in the containers with their 
tampering checks.)

So while you can copy them into a dynamic accessibility context, this 
doesn't change their lifetime. So your program doesn't work at runtime. This 
can't be a purely static check simply because of the existence of access 
parameters and stand-alone access objects (both of which have dynamic rather 
than static accessibility checks).

>     procedure Foo is
...
>       S  : Storages.Instance_Type  := Storages.Create;
>       A1 : Pool_Specific_Access := S.Element; -- Illegal.
   because it fails a static accessibility check.
>       A2 : access Storages.Element_Type := S.Element; -- However still 
> legal.
   I'm not certain about this (SAOAATs require the accessibility lifetime to 
be at least as long as the object itself, and this isn't). But let's assume 
this is legal for the sake of argument.
>       A3 : General_Access := S.Element; -- And the same.
   Yes, of course this is legal, but it also includes a dynamic 
accessibility check which will fail for this example. (S.Element is much 
shorter lives than type General_Access). So it will raise Program_Error. You 
will not have accomplished copying with this code.

>Far from what limited access type would be.

Not really, because we have to allow some copying of limited access values 
or you wouldn't be able to use them at all. At least for initialization (you 
need to be able to initialize one limited access value with the result of a 
function returning such a thing). You also may want to pass the value into a 
subprogram for further processing (which is safe, as the subprogram has to 
return before the access is destroyed). In cases like these, "limited" is 
too much.

Moreover, the use of access parameters and SAOAATs should be avoided unless 
you really need dynamic accessibility. It's just one of the many reasons 
that these things are dangerous and probably never should have been added to 
Ada in the first place. If you don't use the dangerous constructs (say by 
using AdaControl to flag them), you won't have the problem you illustrate 
here.

                          Randy.




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

* Re: Generic access type convention and aliasing
  2013-05-07 21:03           ` Jacob Sparre Andersen news
@ 2013-05-07 22:13             ` Yannick Duchêne (Hibou57)
  2013-05-08 11:28               ` Yannick Duchêne (Hibou57)
  2013-05-08 20:44               ` Randy Brukardt
  0 siblings, 2 replies; 11+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-05-07 22:13 UTC (permalink / raw)


Le Tue, 07 May 2013 23:03:17 +0200, Jacob Sparre Andersen news  
<randy@rrsoftware.com> a écrit:
>>       A3 : General_Access := S.Element; -- And the same.
>    Yes, of course this is legal, but it also includes a dynamic
> accessibility check which will fail for this example. (S.Element is much
> shorter lives than type General_Access). So it will raise Program_Error.

Right, but I badly wish static check/static failure (may be I want too  
much, I believe Ada should have this with the hot area of access value).

> Moreover, the use of access parameters and SAOAATs should be avoided

What is “SAOAATs”?

> unless
> you really need dynamic accessibility.

What I'm trying to achieve, is to have access to the object storage  
designated by the access, while preventing manipulation (including copying  
at any life‑time scope) of this access value, only dereference. The only  
way I know to achieve this, is by passing `Element.all` to an  
out/in‑out/in parameter of a callback, but I would like to avoid control  
inversion (this breaks the flow).

I feel there is no way to solve it or I want too much, and I should stop  
searching and go with the storage specific access discriminant (so no  
implicit dereference), and use some kind of external static check. At  
least storage specific access type offers a tiny bit more protection than  
general access, being a discriminant it can't be modified, and being an  
access value, use of a not allocated or deallocated element will be always  
caught at runtime, even with check disabled… the most I can get, so I will  
go with it.


-- 
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University


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

* Re: Generic access type convention and aliasing
  2013-05-07 22:13             ` Yannick Duchêne (Hibou57)
@ 2013-05-08 11:28               ` Yannick Duchêne (Hibou57)
  2013-05-08 20:44               ` Randy Brukardt
  1 sibling, 0 replies; 11+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-05-08 11:28 UTC (permalink / raw)


Le Wed, 08 May 2013 00:13:23 +0200, Yannick Duchêne (Hibou57)  
<yannick_duchene@yahoo.fr> a écrit:

> I feel there is no way to solve it or I want too much, and I should stop  
> searching and go with the storage specific access discriminant (so no  
> implicit dereference), and use some kind of external static check. At  
> least storage specific access type offers a tiny bit more protection  
> than general access, […]

Not just “a tiny bit”, rather enough finally: I may simply disallow the  
use of any general access type and also disallow instantiation of this  
pool specific access type outside of the package which declares it, and  
that will be a job for AdaControl :) With that check made aside of the  
compilation, I'm sure no copy of an access of this type is ever made, as a  
pool specific access type cannot be converted to another pool specific  
access type, except if can be converted to a general access type, and  
that's why I will disallow general access types (any way, won't need  
this). With these two restrictions, I'm sure I can assert no copy is made,  
except in the [generic] package which “own” this type.

-- 
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University



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

* Re: Generic access type convention and aliasing
  2013-05-07 22:13             ` Yannick Duchêne (Hibou57)
  2013-05-08 11:28               ` Yannick Duchêne (Hibou57)
@ 2013-05-08 20:44               ` Randy Brukardt
  1 sibling, 0 replies; 11+ messages in thread
From: Randy Brukardt @ 2013-05-08 20:44 UTC (permalink / raw)


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

"Yannick Duch�ne (Hibou57)" <yannick_duchene@yahoo.fr> wrote in message 
news:op.wwqiolpeule2fv@cardamome...
>Le Tue, 07 May 2013 23:03:17 +0200, Jacob Sparre Andersen news 
><randy@rrsoftware.com> a �crit:
...
>> Moreover, the use of access parameters and SAOAATs should be avoided
>
>What is "SAOAATs"?

A Baird-ism that the ARG has adopted: "Stand-Alone Object of an Anonymous 
Access Type". There's no shorter way to refer to it (I did write it out at 
the beginning of my message, but I wan't going to repeat that over and over 
...)

>> unless you really need dynamic accessibility.

>What I'm trying to achieve, is to have access to the object storage 
>designated by the access, while preventing manipulation (including copying 
>at any life-time scope) of this access value, only dereference. The only 
>way I know to achieve this, is by passing `Element.all` to an 
>out/in-out/in parameter of a callback, but I would like to avoid control 
>inversion (this breaks the flow).

My point was that you get the static checks you want so long as no access 
parameters and SAOAATs exist in your program. (They're accessibility checks, 
but are required to be made at compile-time.) You could use AdaControl or 
even restrictions pragmas to enforce that.

That's probably better than trying to "roll-your-own" checks. OTOH, the 
strategy you laid out after the above quote might be better for other 
reasons.

                                             Randy.






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

end of thread, other threads:[~2013-05-08 20:44 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-06  0:20 Generic access type convention and aliasing Yannick Duchêne (Hibou57)
2013-05-06  5:55 ` Yannick Duchêne (Hibou57)
2013-05-07  0:56   ` Randy Brukardt
2013-05-07  6:02     ` Yannick Duchêne (Hibou57)
2013-05-07  6:42       ` Yannick Duchêne (Hibou57)
2013-05-07 17:34       ` AdaMagica
2013-05-07 19:08         ` Yannick Duchêne (Hibou57)
2013-05-07 21:03           ` Jacob Sparre Andersen news
2013-05-07 22:13             ` Yannick Duchêne (Hibou57)
2013-05-08 11:28               ` Yannick Duchêne (Hibou57)
2013-05-08 20:44               ` Randy Brukardt

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