comp.lang.ada
 help / color / mirror / Atom feed
* Elaboration Question
@ 2015-01-02  3:27 Hubert
  2015-01-02  7:56 ` Simon Wright
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Hubert @ 2015-01-02  3:27 UTC (permalink / raw)


For a newcomer to Ada, elaboration is one of the toughest things to 
understand. My understanding is so, that if you have for instance a 
variable in the package body, say :

A : Integer := 0;

then this variable must be initialized at some point and that's what 
elaboration does.
The problem then occurs with the order in which elaboration occurs in 
different package that depend on each other etc.
There are pragmas for the programmer to take control of the elaboration 
sequence but I have the feeling that may complicate things. especially 
when you want to make a library that should be independent and that's 
supposed to be be released to others at some point.

So may question is, is it better to just leave those variables 
unitialized and then initialize them later for instance:

A : Integer;

PROCEDURE Initialize IS
BEGIN
    A:= 0;
END Initialize;

Would that be generally better?


Thanks






---
This email has been checked for viruses by Avast antivirus software.
http://www.avast.com

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

* Re: Elaboration Question
  2015-01-02  3:27 Elaboration Question Hubert
@ 2015-01-02  7:56 ` Simon Wright
  2015-01-02 22:16   ` Randy Brukardt
  2015-01-02 14:49 ` Brad Moore
  2015-01-03  9:45 ` Jean François Martinez
  2 siblings, 1 reply; 16+ messages in thread
From: Simon Wright @ 2015-01-02  7:56 UTC (permalink / raw)


Hubert <herrdoktor@fumanchu.com> writes:

> For a newcomer to Ada, elaboration is one of the toughest things to
> understand. My understanding is so, that if you have for instance a
> variable in the package body, say :
>
> A : Integer := 0;
>
> then this variable must be initialized at some point and that's what
> elaboration does.
> The problem then occurs with the order in which elaboration occurs in
> different package that depend on each other etc.
> There are pragmas for the programmer to take control of the
> elaboration sequence but I have the feeling that may complicate
> things. especially when you want to make a library that should be
> independent and that's supposed to be be released to others at some
> point.

The GNAT User Manual has a section on elaboration[1].

The ARM's elaboration model is what GNAT calls the dynamic model, and
does indeed (in general) require that you insert elaboration
pragmas. GNAT's default elaboration uses the static model, where the
compiler works out the elaboration order for itself.

Sometimes the static model is over-pessimistic; in my experience,
usually because of library level tasks (which start running, and may
make calls, during elaboration). This is rare, and most GNAT programmers
forget about elaboration issues.

See the "Default Behavior in GNAT - Ensuring Safety" section of [1] for
how to get GNAT to tell you what elaboration pragmas to insert;
especially useful if you're considering porting to a different compiler.

> So may question is, is it better to just leave those variables
> unitialized and then initialize them later for instance:
>
> A : Integer;
>
> PROCEDURE Initialize IS
> BEGIN
>    A:= 0;
> END Initialize;
>
> Would that be generally better?

I would say not. There might, after all, be a chain of Initialize calls
required; very complicated to manage.

[1] https://gcc.gnu.org/onlinedocs/gnat_ugn_unw/Elaboration-Order-Handling-in-GNAT.html


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

* Re: Elaboration Question
  2015-01-02 14:49 ` Brad Moore
@ 2015-01-02 11:08   ` Mark Lorenzen
  2015-01-02 13:35     ` David Botton
  2015-01-02 15:11     ` sbelmont700
  0 siblings, 2 replies; 16+ messages in thread
From: Mark Lorenzen @ 2015-01-02 11:08 UTC (permalink / raw)


On Friday, January 2, 2015 8:49:15 AM UTC+1, Brad Moore wrote:
 
> No, that's definitely worse, and really doesn't fix anything. There is 
> nothing preventing someone from attempting to reference A, before 
> Initialize is called. Initializing during elaboration is safer also 
> because it happens only once, and via the environment task. Relying on 
> programmers to initialize globals via explicit calls is error prone, and 
> can even lead to concurrency problems if Initialize is called from more 
> than one place.

What strategy would you use when writing a library in Ada, that is to be called from e.g. a program written in C? In that case I think that using an initialization subprogram is the preferred method. If gprbuild is used to build the library, then a stand-alone library project can be used to ensure that the necessary elaboration code is called, but I have never used such a project type.

Regards,

Mark L

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

* Re: Elaboration Question
  2015-01-02 11:08   ` Mark Lorenzen
@ 2015-01-02 13:35     ` David Botton
  2015-01-02 15:11     ` sbelmont700
  1 sibling, 0 replies; 16+ messages in thread
From: David Botton @ 2015-01-02 13:35 UTC (permalink / raw)


> What strategy would you use when writing a library in Ada

You wouldn't change a thing since you have to first initialize the Ada environment anyways from C, i.e. (adainit, adafinal)

David Botton


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

* Re: Elaboration Question
  2015-01-02  3:27 Elaboration Question Hubert
  2015-01-02  7:56 ` Simon Wright
@ 2015-01-02 14:49 ` Brad Moore
  2015-01-02 11:08   ` Mark Lorenzen
  2015-01-03  9:45 ` Jean François Martinez
  2 siblings, 1 reply; 16+ messages in thread
From: Brad Moore @ 2015-01-02 14:49 UTC (permalink / raw)


On 2015-01-01 8:27 PM, Hubert wrote:
> For a newcomer to Ada, elaboration is one of the toughest things to
> understand. My understanding is so, that if you have for instance a
> variable in the package body, say :
>
> A : Integer := 0;
>
> then this variable must be initialized at some point and that's what
> elaboration does.
> The problem then occurs with the order in which elaboration occurs in
> different package that depend on each other etc.
> There are pragmas for the programmer to take control of the elaboration
> sequence but I have the feeling that may complicate things. especially
> when you want to make a library that should be independent and that's
> supposed to be be released to others at some point.
>
> So may question is, is it better to just leave those variables
> unitialized and then initialize them later for instance:
>
> A : Integer;
>
> PROCEDURE Initialize IS
> BEGIN
>     A:= 0;
> END Initialize;
>
> Would that be generally better?

No, that's definitely worse, and really doesn't fix anything. There is 
nothing preventing someone from attempting to reference A, before 
Initialize is called. Initializing during elaboration is safer also 
because it happens only once, and via the environment task. Relying on 
programmers to initialize globals via explicit calls is error prone, and 
can even lead to concurrency problems if Initialize is called from more 
than one place.

It's generally best to initialize global variables upon declaration, and 
usually you don't even need to think about elaboration. If there is a 
problem with elaboration, the compiler should tell you, and then you can 
think about how to resolve the elaboration issue, via the pragmas.
Usually the error message from the compiler should give a good clue 
about the cause of the problem, and how to resolve it.
Otherwise, typically the compiler does a good job of sorting out 
elaboration order all on its own.

Brad



>
>
> Thanks
>
>
>
>
>
>
> ---
> This email has been checked for viruses by Avast antivirus software.
> http://www.avast.com
>

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

* Re: Elaboration Question
  2015-01-02 11:08   ` Mark Lorenzen
  2015-01-02 13:35     ` David Botton
@ 2015-01-02 15:11     ` sbelmont700
  2015-01-02 21:57       ` Niklas Holsti
  1 sibling, 1 reply; 16+ messages in thread
From: sbelmont700 @ 2015-01-02 15:11 UTC (permalink / raw)


On Friday, January 2, 2015 6:08:24 AM UTC-5, Mark Lorenzen wrote:
> 
> What strategy would you use when writing a library in Ada, that is to be called from e.g. a program written in C?
>

The onus is on the calling code to ensure elaboration happens correctly.  The best strategy to use from the library-side is to just make sure all your code is Preelaborate (or Pure), and the problem solves itself.

-sb

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

* Re: Elaboration Question
  2015-01-02 15:11     ` sbelmont700
@ 2015-01-02 21:57       ` Niklas Holsti
  2015-01-06  2:33         ` Randy Brukardt
  0 siblings, 1 reply; 16+ messages in thread
From: Niklas Holsti @ 2015-01-02 21:57 UTC (permalink / raw)


On 15-01-02 17:11 , sbelmont700@gmail.com wrote:
> On Friday, January 2, 2015 6:08:24 AM UTC-5, Mark Lorenzen wrote:
>>
>> What strategy would you use when writing a library in Ada, that is
>> to be called from e.g. a program written in C?
>>
>
> The onus is on the calling code to ensure elaboration happens
> correctly.  The best strategy to use from the library-side is to just
> make sure all your code is Preelaborate (or Pure), and the problem
> solves itself.

This advice probably works in practice, but formally speaking, I cannot 
find a promise in the Ada RM (2012 version) that a Preelaborable library 
unit is free of elaboration code. RM 10.2.1(11/3) promises that all 
preelaborated library units are elaborated before any non-preelaborated 
library units, but formally, even the preelaborated units are still 
"elaborated" in some sense.

Even the implementation advice the RM gives for preelaboration 
(10.2.1(12)) speaks of elaborations of the preelaborable units that 
"occur in distinct executions of the same program", which sounds very 
much like some elaboration code being executed at execution time.

So to me it appears safest to ensure that the C main program calls the 
Ada elaboration and finalisation operations, as David Botton suggested, 
and then it is not necessary to follow the strong restrictions of 
Preelaborable or Pure units.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .

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

* Re: Elaboration Question
  2015-01-02  7:56 ` Simon Wright
@ 2015-01-02 22:16   ` Randy Brukardt
  0 siblings, 0 replies; 16+ messages in thread
From: Randy Brukardt @ 2015-01-02 22:16 UTC (permalink / raw)


"Simon Wright" <simon@pushface.org> wrote in message 
news:lywq55pqej.fsf@pushface.org...
> Hubert <herrdoktor@fumanchu.com> writes:
...
>> So may question is, is it better to just leave those variables
>> unitialized and then initialize them later for instance:
>>
>> A : Integer;
>>
>> PROCEDURE Initialize IS
>> BEGIN
>>    A:= 0;
>> END Initialize;
>>
>> Would that be generally better?
>
> I would say not. There might, after all, be a chain of Initialize calls
> required; very complicated to manage.

I agree. Plus you have the possibility of forgetting to call Initialize for 
some package, in which case weird things probably will happen.

Having said that, it's not always practical to get packages to elaborate in 
a particular order. If initialization is significant, it may make sense to 
use an explicit routine. For instance, in Janus/Ada, temporary files have to 
be read in a particular order, so we ended up using Initialize subprograms 
to do that (otherwise, packages that don't need to know about each other for 
any other reason end up coupled).

But for smaller initializing (like setting things to an empty state), I 
think you should always use elaboration.

                             Randy.




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

* Re: Elaboration Question
  2015-01-02  3:27 Elaboration Question Hubert
  2015-01-02  7:56 ` Simon Wright
  2015-01-02 14:49 ` Brad Moore
@ 2015-01-03  9:45 ` Jean François Martinez
  2015-01-03  9:50   ` Hubert
  2 siblings, 1 reply; 16+ messages in thread
From: Jean François Martinez @ 2015-01-03  9:45 UTC (permalink / raw)


On Friday, January 2, 2015 4:27:52 AM UTC+1, Hubert wrote:
> For a newcomer to Ada, elaboration is one of the toughest things to 
> understand. My understanding is so, that if you have for instance a 
> variable in the package body, say :
> 
> A : Integer := 0;
> 


In your example this is no problem since at compile time the compiler will put a zero in the corresponding emplacement in the generated file.  When program is loaded by the OS the corresponding memory will get the adequate value. 

The problems arise when, with My_Function and My_Var belong to another package
A: Integer:= My_Function;
or when A: Integer:=My_Var;  with My_Var not being static but being the product of some calculation.  

Jean-François Martinez

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

* Re: Elaboration Question
  2015-01-03  9:45 ` Jean François Martinez
@ 2015-01-03  9:50   ` Hubert
  2015-01-03 18:43     ` Jean François Martinez
  0 siblings, 1 reply; 16+ messages in thread
From: Hubert @ 2015-01-03  9:50 UTC (permalink / raw)


>
> In your example this is no problem since at compile time the compiler will put a zero in the corresponding emplacement in the generated file.  When program is loaded by the OS the corresponding memory will get the adequate value.
>
> The problems arise when, with My_Function and My_Var belong to another package
> A: Integer:= My_Function;
> or when A: Integer:=My_Var;  with My_Var not being static but being the product of some calculation.
>
> Jean-François Martinez
>
Ok, makes sense.

Thanks also to all the other posters, it's not an easy topic it seems. 
Personally I prefer the initialization call to a library simply because 
it gives the programmer the liberty of determining the place in the 
sequence of initializations of a potential longer list of libraries 
which may interfere with each other's initialization if the sequence is 
not under program control.
I am forced to use a graphics library currently which calls your program 
as a DLL and controls your program and boy is that a pain in the butt.


---
This email has been checked for viruses by Avast antivirus software.
http://www.avast.com

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

* Re: Elaboration Question
  2015-01-03  9:50   ` Hubert
@ 2015-01-03 18:43     ` Jean François Martinez
  2015-01-04  1:57       ` Hubert
  2015-01-04 12:05       ` Simon Wright
  0 siblings, 2 replies; 16+ messages in thread
From: Jean François Martinez @ 2015-01-03 18:43 UTC (permalink / raw)


On Sat, 03 Jan 2015 01:50:31 -0800, Hubert wrote:


> 
> Thanks also to all the other posters, it's not an easy topic it seems.
> Personally I prefer the initialization call to a library simply because
> it gives the programmer the liberty of determining the place in the
> sequence of initializations of a potential longer list of libraries
> which may interfere with each other's initialization if the sequence is
> not under program control.

You can do this in Ada or you can just declare variables and constants 
and let elaboration take care of them.  You cannot do the latter in C 
unless you like playing Russian roulette.

Declaring data entities and letting elaboration ie the runtime take care  
allows you to do things like

Start_Time: constant Time:=Clock; 

This a constant whose value is determined when Ada is initialized.  So 
the constant changes from run to run but you will be safe of accidental 
modifications through Start_Time:=   or through  My_Access_Var.all:=.  
Unlike statically determined constants the operating system will not 
place it in read only memory so unlike them it _can_ be modified through 
use of machine addresses.   But most of the time you don't need them so 
you are safe


> I am forced to use a graphics library currently which calls your program
> as a DLL and controls your program and boy is that a pain in the butt.
> 
> 

If using Gnat then when main program is in another language it must call 
adainit.  This will take care of elaboration.  Since this graphics 
library is not under your control you must trick it.  For instance if yur 
library calls mymain() then you must a mymain() in C consisting in a call 
to adainit.  Read Gnat's documentation for details

Jean-François Martinez

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

* Re: Elaboration Question
  2015-01-03 18:43     ` Jean François Martinez
@ 2015-01-04  1:57       ` Hubert
  2015-01-04 12:05       ` Simon Wright
  1 sibling, 0 replies; 16+ messages in thread
From: Hubert @ 2015-01-04  1:57 UTC (permalink / raw)



> If using Gnat then when main program is in another language it must call
> adainit.  This will take care of elaboration.  Since this graphics
> library is not under your control you must trick it.  For instance if yur
> library calls mymain() then you must a mymain() in C consisting in a call
> to adainit.  Read Gnat's documentation for details

Thanks, that was just an example of why I prefere manual initialization. 
I wouldn't dream of using the C4 engine under Ada, it is bad enough in 
C++. You can do really bad things there. Let's not go there or I start 
crying about the lost months of my life this engine cost me already :)




---
This email has been checked for viruses by Avast antivirus software.
http://www.avast.com

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

* Re: Elaboration Question
  2015-01-03 18:43     ` Jean François Martinez
  2015-01-04  1:57       ` Hubert
@ 2015-01-04 12:05       ` Simon Wright
  1 sibling, 0 replies; 16+ messages in thread
From: Simon Wright @ 2015-01-04 12:05 UTC (permalink / raw)


Jean François Martinez <darkquark99@gmail.com> writes:

> If using Gnat then when main program is in another language it must
> call adainit.  This will take care of elaboration.

If you can build your Ada library as a stand-alone library[1], adainit
and adafinal (or equivalent; I think they're named {lib-name}_init,
_final) get called automagically.

[1] https://gcc.gnu.org/onlinedocs/gnat_ugn_unw/Stand-alone-Library-Projects.html

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

* Re: Elaboration Question
  2015-01-02 21:57       ` Niklas Holsti
@ 2015-01-06  2:33         ` Randy Brukardt
  2015-01-06  8:17           ` Niklas Holsti
  0 siblings, 1 reply; 16+ messages in thread
From: Randy Brukardt @ 2015-01-06  2:33 UTC (permalink / raw)


"Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message 
news:cgoihuF7sr6U1@mid.individual.net...
...
>> The onus is on the calling code to ensure elaboration happens
>> correctly.  The best strategy to use from the library-side is to just
>> make sure all your code is Preelaborate (or Pure), and the problem
>> solves itself.
>
> This advice probably works in practice, but formally speaking, I cannot 
> find a promise in the Ada RM (2012 version) that a Preelaborable library 
> unit is free of elaboration code.

You need to look in Annex C, specifically C.4 Preelaboration Requirements

But notice that just because a package is preelaborable doesn't 
automatically mean that no code is generated. That's only true in a limited 
set of circumstances (as outlined in C.4), and moreover, Annex C is optional 
so a compiler might not follow this subclause at all.

                                        Randy.



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

* Re: Elaboration Question
  2015-01-06  2:33         ` Randy Brukardt
@ 2015-01-06  8:17           ` Niklas Holsti
  2015-01-06 20:06             ` Randy Brukardt
  0 siblings, 1 reply; 16+ messages in thread
From: Niklas Holsti @ 2015-01-06  8:17 UTC (permalink / raw)


On 15-01-06 04:33 , Randy Brukardt wrote:
> "Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message
> news:cgoihuF7sr6U1@mid.individual.net...
> ...
>>> The onus is on the calling code to ensure elaboration happens
>>> correctly.  The best strategy to use from the library-side is to just
>>> make sure all your code is Preelaborate (or Pure), and the problem
>>> solves itself.
>>
>> This advice probably works in practice, but formally speaking, I cannot
>> find a promise in the Ada RM (2012 version) that a Preelaborable library
>> unit is free of elaboration code.
>
> You need to look in Annex C, specifically C.4 Preelaboration Requirements

Ah yes, thanks for the correction. I missed C.4 because I was scanning 
the RM Index for "preelabo", and the only reference to C.4 in the Index 
seems to be for the term "load time".

Kudos to you for making the Index so good that it is my preferred way to 
search for RM info. Demerits to me for not searching in other ways, such 
as by reading the table of contents :-)

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .


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

* Re: Elaboration Question
  2015-01-06  8:17           ` Niklas Holsti
@ 2015-01-06 20:06             ` Randy Brukardt
  0 siblings, 0 replies; 16+ messages in thread
From: Randy Brukardt @ 2015-01-06 20:06 UTC (permalink / raw)


"Niklas Holsti" <niklas.holsti@tidorum.invalid> wrote in message 
news:ch1k1hFicnqU1@mid.individual.net...
> On 15-01-06 04:33 , Randy Brukardt wrote:
...
>>> This advice probably works in practice, but formally speaking, I cannot
>>> find a promise in the Ada RM (2012 version) that a Preelaborable library
>>> unit is free of elaboration code.
>>
>> You need to look in Annex C, specifically C.4 Preelaboration Requirements
>
> Ah yes, thanks for the correction. I missed C.4 because I was scanning the 
> RM Index for "preelabo", and the only reference to C.4 in the Index seems 
> to be for the term "load time".
>
> Kudos to you for making the Index so good that it is my preferred way to 
> search for RM info. Demerits to me for not searching in other ways, such 
> as by reading the table of contents :-)

Most of the credit for the index goes to Bob Duff, who originally created 
the index for the Ada 95 RM. I've just kept it up to date following his 
lead.

One thing we didn't index was the Table of Contents. The presumption was 
that people would look there first, but as you've proved, that's not always 
true.

I just added an index entry "preelaborated, implementation requirements, 
C.4(2)", which should help the next person that does as you did.

                                          Randy.



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

end of thread, other threads:[~2015-01-06 20:06 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-02  3:27 Elaboration Question Hubert
2015-01-02  7:56 ` Simon Wright
2015-01-02 22:16   ` Randy Brukardt
2015-01-02 14:49 ` Brad Moore
2015-01-02 11:08   ` Mark Lorenzen
2015-01-02 13:35     ` David Botton
2015-01-02 15:11     ` sbelmont700
2015-01-02 21:57       ` Niklas Holsti
2015-01-06  2:33         ` Randy Brukardt
2015-01-06  8:17           ` Niklas Holsti
2015-01-06 20:06             ` Randy Brukardt
2015-01-03  9:45 ` Jean François Martinez
2015-01-03  9:50   ` Hubert
2015-01-03 18:43     ` Jean François Martinez
2015-01-04  1:57       ` Hubert
2015-01-04 12:05       ` Simon Wright

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