comp.lang.ada
 help / color / mirror / Atom feed
* Select then abort can fail to abort the abortable part
@ 2014-11-20 21:08 Jean François Martinez
  2014-11-20 21:35 ` Dmitry A. Kazakov
  2014-11-20 21:36 ` Adam Beneschan
  0 siblings, 2 replies; 7+ messages in thread
From: Jean François Martinez @ 2014-11-20 21:08 UTC (permalink / raw)


Context:  Gnat x86_64 on Linux


Let's have that simple loop

for Ind in 1..6
loop
    Start:=Clock;
    select
        delay Ind * 10.0
    then abort 
       Ultimate_Prime;
    end select; 
    My_Duration:= Clock - Start;
end loop;

Ultimate_Prime is function containing a nearly infinite loop trying to 
find prime numbers.  

First version stores primes found.  This mandates a linked list but that 
would create an unacceptable overhead so I use big chunks

     type Big_Array is array (Positive range 1..100_000) of Long_Mod;
     type Chunk is record
          Position: Positive  range Big_Array'Range;
          Payload: Big_Array;
     end record;
     type T_Ptr_Chunk is access  T;

     package P_List_Chunks is
       new Ada.Containers.Doubly_Linked_Lists(T_Ptr_Chunk);
     use P_List_Chunks;

     List_Chunks: List;


So this first version is "dumb": it tries every odd number until 
Divisor * Divisor > Candidate.  If it is a prime it is stored in the 
Payload array though an access variable ie _without_ even looking at the 
List.  The List is only accessed for concatenating a new Chunk.
Now when I run it I notice that the select then abort can take over 1 
second or even two seconds more than the delay and the number of
Primes found is ever a multiple of 100_000 ie the function was only 
aborted when it entered code provided by AdaCore in order to allocate a 
new Chunk and to add a new element to the List.

The second version is "smart". It only tries to divide by prime numbers.  
This means we have to use the numbers previously stored in our list so

for An_Element in List_Chunks
loop 
    for Ind in 1..Position
    loop

In this version we are constantly traversing List_Chunks and using 
Adacore's code.  Here the function is aborted very close after the 
expiration of the delay (from memory 0.05 at most after expiration) and 
the number of prime numbers found is not a multiple of 100_000.

Third version is tries very odd number as divisor but stores only the 
last prime found.  Ie no lists, no nothing.  Just user code, nothing from 
the run time or AdaCore's libraries.   In this version the delay expires 
but the there is no abort _at all_.  Function will run until it leaves 
voluntarily in, according my estimations, something like five hundred 
thousand years.

Is this incorrect behavior?

---
Jean-François Martinez

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

* Re: Select then abort can fail to abort the abortable part
  2014-11-20 21:08 Select then abort can fail to abort the abortable part Jean François Martinez
@ 2014-11-20 21:35 ` Dmitry A. Kazakov
  2014-11-20 22:19   ` Jean François Martinez
  2014-11-20 21:36 ` Adam Beneschan
  1 sibling, 1 reply; 7+ messages in thread
From: Dmitry A. Kazakov @ 2014-11-20 21:35 UTC (permalink / raw)


On 20 Nov 2014 21:08:50 GMT, Jean François Martinez wrote:

> Context:  Gnat x86_64 on Linux
> 
> 
> Let's have that simple loop
> 
> for Ind in 1..6
> loop
>     Start:=Clock;
>     select
>         delay Ind * 10.0
>     then abort 
>        Ultimate_Prime;
>     end select; 
>     My_Duration:= Clock - Start;
> end loop;
> 
> Ultimate_Prime is function containing a nearly infinite loop trying to 
> find prime numbers.  
> 
> First version stores primes found.  This mandates a linked list but that 
> would create an unacceptable overhead so I use big chunks
> 
>      type Big_Array is array (Positive range 1..100_000) of Long_Mod;
>      type Chunk is record
>           Position: Positive  range Big_Array'Range;
>           Payload: Big_Array;
>      end record;
>      type T_Ptr_Chunk is access  T;
> 
>      package P_List_Chunks is
>        new Ada.Containers.Doubly_Linked_Lists(T_Ptr_Chunk);

You certainly should not abort any code changing dynamically allocated
structures. I don't know the implementation of
Ada.Containers.Doubly_Linked_Lists, but it is not protected against abort
in the middle of changing list links, you may get garbage in the result.

You should almost never use the asynchronous transfer of control. A clean
method of aborting a lengthy computation is by inserting inspection points
within loops and raising an exception when abort was requested or time was
expired.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: Select then abort can fail to abort the abortable part
  2014-11-20 21:08 Select then abort can fail to abort the abortable part Jean François Martinez
  2014-11-20 21:35 ` Dmitry A. Kazakov
@ 2014-11-20 21:36 ` Adam Beneschan
  2014-11-20 22:55   ` Jean François Martinez
  1 sibling, 1 reply; 7+ messages in thread
From: Adam Beneschan @ 2014-11-20 21:36 UTC (permalink / raw)


On Thursday, November 20, 2014 1:08:51 PM UTC-8, Jean François Martinez wrote:

> Is this incorrect behavior?

I believe it's incorrect behavior only if a compiler supports Annex D (because then section D.6 about Preemptive Abort must apply).  If a compiler doesn't support Annex D, then an abortable part must be aborted only at certain "abort completion points" as defined by 9.8(16-19); if the code keeps running without reaching any of those points, it doesn't have to abort.  

My understanding is that Windows native compilers can't really support Annex D because the OS makes it difficult to abort a thread in the needed way.  On Unix/Linux, a timer could be set up that causes a signal; however, my experience with Unix/Linux signals is that it's easy to get yourself hosed, if a signal happens to occur at an inopportune time, or another signal happens while one signal is being handled so that there's a danger that the signal might get lost.  So while I have no idea whether GNAT for Linux claims to support Annex D, it would be understandable to me that it wouldn't.

A workaround is to put "delay 0.0" at strategic points in your code, since that's an abort completion point.  It would essentially poll to see if the delay in the SELECT has expired.  GNAT also has a Polling pragma, at least for Windows, but maybe it works on Linux too.

See this earlier thread: https://groups.google.com/forum/?hl=en#!searchin/comp.lang.ada/D.6$20AND$20after$3A2013$2F01$2F01$20AND$20before$3Atoday%7Csort:relevance/comp.lang.ada/748DRqqa7v0/llYfPx731ucJ

                                -- Adam


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

* Re: Select then abort can fail to abort the abortable part
  2014-11-20 21:35 ` Dmitry A. Kazakov
@ 2014-11-20 22:19   ` Jean François Martinez
  2014-11-21  8:37     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 7+ messages in thread
From: Jean François Martinez @ 2014-11-20 22:19 UTC (permalink / raw)


On Thu, 20 Nov 2014 22:35:27 +0100, Dmitry A. Kazakov wrote:


> 
> You certainly should not abort any code changing dynamically allocated
> structures. I don't know the implementation of
> Ada.Containers.Doubly_Linked_Lists, but it is not protected against
> abort in the middle of changing list links, you may get garbage in the
> result.
> 

Actually Lists are Controlled Objects and an exception is raised if 
you try to abort a task at the time it is trying to modify the List

> You should almost never use the asynchronous transfer of control. A
> clean method of aborting a lengthy computation is by inserting
> inspection points within loops and raising an exception when abort was
> requested or time was expired.

I was just kicking the tires of something (select then abort) I have 
never used.  

---
Jean-François Martinez

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

* Re: Select then abort can fail to abort the abortable part
  2014-11-20 21:36 ` Adam Beneschan
@ 2014-11-20 22:55   ` Jean François Martinez
  0 siblings, 0 replies; 7+ messages in thread
From: Jean François Martinez @ 2014-11-20 22:55 UTC (permalink / raw)


On Thu, 20 Nov 2014 13:36:25 -0800, Adam Beneschan wrote:

> On Thursday, November 20, 2014 1:08:51 PM UTC-8, Jean François Martinez
> wrote:
> 
>> Is this incorrect behavior?
> 
> I believe it's incorrect behavior only if a compiler supports Annex D
> (because then section D.6 about Preemptive Abort must apply).  If a
> compiler doesn't support Annex D, then an abortable part must be aborted
> only at certain "abort completion points" as defined by 9.8(16-19); if
> the code keeps running without reaching any of those points, it doesn't
> have to abort.
> 

Actually Gnat is supposed to support Annex D but in Linux there are 
several units of it marked as non implementable on Linux.

I have looked in the ARM both for delay and select then abort and there 
is nothing or at least I have seen nothing.

> My understanding is that Windows native compilers can't really support
> Annex D because the OS makes it difficult to abort a thread in the
> needed way.  On Unix/Linux, a timer could be set up that causes a
> signal; however, my experience with Unix/Linux signals is that it's easy
> to get yourself hosed, if a signal happens to occur at an inopportune
> time, or another signal happens while one signal is being handled so
> that there's a danger that the signal might get lost.  So while I have
> no idea whether GNAT for Linux claims to support Annex D, it would be
> understandable to me that it wouldn't.
> 
> A workaround is to put "delay 0.0" at strategic points in your code,
> since that's an abort completion point.  It would essentially poll to
> see if the delay in the SELECT has expired.  GNAT also has a Polling
> pragma, at least for Windows, but maybe it works on Linux too.
> 

Actually I was thinking about using timing events: inserting delays in 
the code is difficult: simple solutions like checking every N prime 
numbers found do not work since finding an new one is far longer at 100 
million than at ten thousand.  Checking every N tests is ugly and heavy.

---
Jean-François Martinez


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

* Re: Select then abort can fail to abort the abortable part
  2014-11-20 22:19   ` Jean François Martinez
@ 2014-11-21  8:37     ` Dmitry A. Kazakov
  2014-11-21 15:26       ` Jean François Martinez
  0 siblings, 1 reply; 7+ messages in thread
From: Dmitry A. Kazakov @ 2014-11-21  8:37 UTC (permalink / raw)


On 20 Nov 2014 22:19:30 GMT, Jean François Martinez wrote:

> On Thu, 20 Nov 2014 22:35:27 +0100, Dmitry A. Kazakov wrote:
> 
>> You certainly should not abort any code changing dynamically allocated
>> structures. I don't know the implementation of
>> Ada.Containers.Doubly_Linked_Lists, but it is not protected against
>> abort in the middle of changing list links, you may get garbage in the
>> result.
> 
> Actually Lists are Controlled Objects and an exception is raised if 
> you try to abort a task at the time it is trying to modify the List

I don't see how being controlled (or tagged) were related. Primitive
operations are not abort-deferred except for Initialize and Finalize (and
only under certain conditions). RM 9.8.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

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

* Re: Select then abort can fail to abort the abortable part
  2014-11-21  8:37     ` Dmitry A. Kazakov
@ 2014-11-21 15:26       ` Jean François Martinez
  0 siblings, 0 replies; 7+ messages in thread
From: Jean François Martinez @ 2014-11-21 15:26 UTC (permalink / raw)


On Friday, November 21, 2014 9:37:33 AM UTC+1, Dmitry A. Kazakov wrote:

> I don't see how being controlled (or tagged) were related. Primitive
> operations are not abort-deferred except for Initialize and Finalize (and
> only under certain conditions). RM 9.8.
> 

Actually while playing with asynchronous select I got an exception from  Ada.Containers.Doubly_Linked_Lists telling me I was trying to abort at the wrong time and about a controlled object.

I think somewhere in the code there is 

procedure Must_be_atomic is
  A: My_controlled_type;
begin

end My_Atomic

and the Finalize of My_Controled_Type raising an exception
---
Jean-Frannçois Martinez


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

end of thread, other threads:[~2014-11-21 15:26 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-20 21:08 Select then abort can fail to abort the abortable part Jean François Martinez
2014-11-20 21:35 ` Dmitry A. Kazakov
2014-11-20 22:19   ` Jean François Martinez
2014-11-21  8:37     ` Dmitry A. Kazakov
2014-11-21 15:26       ` Jean François Martinez
2014-11-20 21:36 ` Adam Beneschan
2014-11-20 22:55   ` Jean François Martinez

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