* 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