comp.lang.ada
 help / color / mirror / Atom feed
* Interrupts handling in ADA
@ 2011-12-10 20:43 Ada @ BRL
  2011-12-10 21:13 ` Vinzent Hoefler
                   ` (6 more replies)
  0 siblings, 7 replies; 46+ messages in thread
From: Ada @ BRL @ 2011-12-10 20:43 UTC (permalink / raw)


Hello,
I'm an Erasmus student at the University of Bristol - UK and I'm carrying out the work for my master thesis in Computer Engineering.

I'm programming a multithreading application in C / C++ and ADA.
The latter is a completely new language for me...

The environment of ADA applcation is:
I have 4 tasks that execute at the same time:
one is the main task,
the other three execute a "read" from network (socket) function inside their bodies (on the other side there's the C/C++ application with 3 network sockets).
[I decided to use the sockets instead of dll/lib import because this approach hasn't worked... =( ]

I want that when new data is available on one or more socket threads, this / these threads somehow notify the main thread that data is arrived and then safely send the data to it.

I've thought to use the interrupts...because I haven't found any references about the use of "events" in ADA.
I've thought to attach three different handler of interrupts into the main task and then to generate the interrupt from the socket task with ada.interrupts.signal.generate_interrupt.
Socket 1 will generate interrupt #1, socket 2 -> interrupt #2 and so on.

May you tell me please if this is the right way to face the problem?
I'm not skilled in ada and so there could be other better methods...

I've used the pragmas attach_handler and interrupt_handler but unfortunately I'm still not able to get all the stuff working...

I think it's a problem of ADA implementation because:
even if I call pragma unreserve_all_interrupts I've found that the function Is_Reserved(Interr_ID) returns FALSE only for this signals IDs: 2(SIGINT), 4(SIGILL), 8(SIGFPE), 11(SISEGV), 15(SIGTERM), 22(SIGABRT).

I guess that this is the opposite behaviour as I expected...
If I try to set an handler to the interrupt say 9, the program cannot start due to this error:

raised PROGRAM_ERROR : adjust/finalize raised PROGRAM_ERROR: s-interr.adb:343 explicit raise

If I call the function Is_Attached the program suddenly exits:
Program exited with code 01.
(gdb) 

Do you know if is it possible to generate user defined interrupts?

Can you help me please to find out what's the problem?
Unfortunately there's not so much documentation about ADA  =( and I'm late for my thesis...

Thank you very much in advance for your help,
Ada @ BRL



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

* Re: Interrupts handling in ADA
  2011-12-10 20:43 Interrupts handling in ADA Ada @ BRL
@ 2011-12-10 21:13 ` Vinzent Hoefler
  2011-12-10 22:09 ` Niklas Holsti
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 46+ messages in thread
From: Vinzent Hoefler @ 2011-12-10 21:13 UTC (permalink / raw)


Ada @ BRL wrote:

> The environment of ADA applcation is:
> I have 4 tasks that execute at the same time:
> one is the main task,
> the other three execute a "read" from network (socket) function inside their bodies (on the other side there's the C/C++ application with 3 network sockets).
> [I decided to use the sockets instead of dll/lib import because this approach hasn't worked... =( ]
>
> I want that when new data is available on one or more socket threads, this / these threads somehow notify the main thread that data is arrived and then safely send the data to it.
>
> I've thought to use the interrupts...because I haven't found any references about the use of "events" in ADA.

You probably haven't seen references to protected types, then.
(Although I am not sure, if a task rendezvous wouldn't even be more fit
for your purpose...)

> May you tell me please if this is the right way to face the problem?

Well, not in Ada, no. ;)

A quick and dirty approach (I'm missing the specs about what precisely you
are trying to achieve, but then again, it's /your/ thesis.) But I sure hope,
it gives you an idea at least...

-- 8< --

type Source_Id     is (Task_1, Task_2, Task_3);
type Arrived_Flags is array (Source_Id) of Boolean;

protected type Event is

     procedure Signal_Event (Source : in Source_Id);
     entry Wait (Source : out Source_Id);

private

     Arrived       : Arrived_Flags := (others => False);
     Event_Pending : Boolean       := False;

end Event;

protected body Event is

     procedure Signal_Event (Source : in Source_Id) is
     begin
        --  Set flag for available source.
        Arrived_Flags (Source) := True;

        --  And set the barrier condition.
        Event_Pending := True;
     end Signal_Event;

     entry Wait (Source : out Source_Id) when Event_Pending is
     begin
        Find_Event:
        for S in Arrived'Range loop
           --  If event is marked as arrived, clear it and
           --  return the source id.
           if Arrived (S) then
              Source := S;
              Arrived (S) := False;
              exit Find_Event;
           end if;
        end loop;

        --  Paranoid thoughts: Shall we protect against uninitialized
        --                     values of Source here or can we assume
        --                     that at least one bit in the array was
        --                     set if Event_Pending was actually True?

        --  No more events in Arrived? Lower the barrier again.
        Event_Pending := Arrived /= Arrived_Flags'(others => False);
     end Wait;

end Event;

(Haven't compiled it, so any errors are mine.)

Now your main task could suspend on the wait entry of such a protected
object whilst your communication task indicate their readiness via the
Signal_Event protected procedure.

How to exchange the data between the threads, well ... it could be done
in the Wait entry, too, but that's something I'd like to be "left as an
exercise for the reader". ;)


Vinzent.

-- 
f u cn rd ths, u cn gt a gd jb n cmptr prgrmmng.



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

* Re: Interrupts handling in ADA
  2011-12-10 20:43 Interrupts handling in ADA Ada @ BRL
  2011-12-10 21:13 ` Vinzent Hoefler
@ 2011-12-10 22:09 ` Niklas Holsti
  2011-12-10 22:27 ` Simon Wright
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 46+ messages in thread
From: Niklas Holsti @ 2011-12-10 22:09 UTC (permalink / raw)


On 11-12-10 22:43 , Ada @ BRL wrote:
> Hello,
> I'm an Erasmus student at the University of Bristol - UK and I'm
> carrying out the work for my master thesis in Computer Engineering.
>
> I'm programming a multithreading application in C / C++ and ADA.
> The latter is a completely new language for me...
>
> The environment of ADA applcation is:
> I have 4 tasks that execute at the same time:
> one is the main task,
> the other three execute a "read" from network (socket) function inside
> their bodies (on the other side there's the C/C++ application with 3 network sockets).
> [I decided to use the sockets instead of dll/lib import because this
> approach hasn't worked... =( ]
>
> I want that when new data is available on one or more socket threads, this
> / these threads somehow notify the main thread that data is arrived and
> then safely send the data to it.
>
> I've thought to use the interrupts...because I haven't found any references
> about the use of "events" in ADA.
> I've thought to attach three different handler of interrupts into the main
> task and then to generate the interrupt from the socket task with
> ada.interrupts.signal.generate_interrupt.
> Socket 1 will generate interrupt #1, socket 2 ->  interrupt #2 and so on.
>
> May you tell me please if this is the right way to face the problem?

I wouldn't say so -- better use the Ada features intended for 
task-to-task communication. There are basically two such features:

- rendezvous, an older method, and
- protected objects, a newer method.

The rendezvous method resembles sockets, in a way: one task acts as a 
server and exports an "entry" that other client tasks can call. When the 
server task is ready to accept a call on an entry, it executes an 
"accept" statement; typically, the accept statement suspends the server 
task until some client task calls the entry. Symmetrically, if a client 
task calls the entry, and the server is not waiting in an accept 
statement for that entry, the client task is suspended until the server 
accepts the call. (You can also avoid these suspension, if you want.) 
When the server is accepting, and some client is calling, the 
"rendezvous" (French for "meeting") happens, and the statements defined 
for the entry (in the accept statement) are executed. The parameters of 
the entry can transfer data from client to server and server to client. 
When the entry statements are completed, the rendezvous ends and both 
tasks continue in parallel again.

In your case, the main task would act as the server task and the other 
three tasks would be client tasks. If the data ("events") that the three 
client tasks send to the main task are of different types, the main task 
could export three different entries, one for each client task, with the 
corresponding types of parameters. If all client tasks send the same 
kind of data to the main task, a single entry that is called by all 
client tasks would be enough (perhaps it needs a parameter that tells 
which client is calling, too).

The "protected object" method is like a "monitor" or a "mailbox": You 
define an object that has some public operations and some private data. 
The "protected" property means that the public operations are associated 
with a mutex that enforces mutual exclusion between the calling tasks 
(well, to be precise, the synchronization allows multiple concurrent 
readers, or one exclusive writer). Some public operations can be 
labelled "entries" which means that there is a Boolean "guard" 
expression, similar to a "condition variable": if a task calls an entry 
subprogram, and the guard is false, the task is suspended until the 
guard becomes true (thanks to some other task calling some other 
operation of the same protected object).

In your case, you could define a protected object that has internal 
buffers to hold data ("events") from the three socket tasks. The socket 
tasks would call operations of this object to store data in the buffers; 
the main task would call an operation to extract data from the buffers; 
the latter operation could be defined as an entry, with a guard that 
makes the main task wait until there is some data in the buffers.

> Unfortunately there's not so much documentation about ADA  =(

Sure there is... for example, the Wikibook at 
http://en.wikibooks.org/wiki/Ada_Programming. You should look at the 
chapter on tasking, at http://en.wikibooks.org/wiki/Ada_Programming/Tasking.

HTH!

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



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

* Re: Interrupts handling in ADA
  2011-12-10 20:43 Interrupts handling in ADA Ada @ BRL
  2011-12-10 21:13 ` Vinzent Hoefler
  2011-12-10 22:09 ` Niklas Holsti
@ 2011-12-10 22:27 ` Simon Wright
  2011-12-11 20:21   ` Martin Dowie
  2011-12-13 12:47   ` Ada BRL
  2011-12-11  0:15 ` Jeffrey Carter
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 46+ messages in thread
From: Simon Wright @ 2011-12-10 22:27 UTC (permalink / raw)


"Ada @ BRL" <ada.brl.2011@gmail.com> writes:

> The environment of ADA applcation is:

Ada, please!

> I have 4 tasks that execute at the same time:
> one is the main task,
> the other three execute a "read" from network (socket) function inside
> their bodies (on the other side there's the C/C++ application with 3
> network sockets).
[...]
> I want that when new data is available on one or more socket threads,
> this / these threads somehow notify the main thread that data is
> arrived and then safely send the data to it.

First off, I'd use a Queue.

The new Ada2012 standard includes a synchronised Queue, which would be
just what you want out of the box, but you won't find that in the
current compilers, so you'll need to roll your own.

Starting from Ada.Containers.Vectors[1], the Queue abstraction would
come from using Append to put new mesages on the queue, Is_Empty to
check whether there's something to get from the queue, and First_Element
followed by Delete_First to fetch the front element.

You then need to wrap this container in a protected object[2], so that
the updates from the different input tasks don't corrupt each other, and
so that the main task can block until there's something to read. Use a
Put procedure to post messages onto the queue, and a Get entry to read
the next message or block if there isn't one.

The spec might look like

   with Ada.Containers.Vectors;
   package Queueing is
      type Message is new Integer;
      package Queue_Data
      is new Ada.Containers.Vectors (Index_Type => Natural,
                                     Element_Type => Message);
      protected Queue is
         procedure Put (M : Message);
         entry Get (M : out Message);
      private
         Buffer : Queue_Data.Vector;
      end Queue;
   end Queueing;

and (as a hint) the body of the Get entry might start like

      entry Get (M : out Message) when not Buffer.Is_Empty is
      begin

If your input messages are not all the same type (in Ada-speak, type
Message is indefinite), things get more complicated; but let's cross
that bridge only if we need to.

[1]http://www.adaic.org/resources/add_content/standards/05rm/html/RM-A-18-2.html
[2]http://en.wikibooks.org/wiki/Ada_Programming/Tasking#Protected_types



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

* Re: Interrupts handling in ADA
  2011-12-10 20:43 Interrupts handling in ADA Ada @ BRL
                   ` (2 preceding siblings ...)
  2011-12-10 22:27 ` Simon Wright
@ 2011-12-11  0:15 ` Jeffrey Carter
  2011-12-13 12:53   ` Ada BRL
  2011-12-11  9:23 ` Dmitry A. Kazakov
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 46+ messages in thread
From: Jeffrey Carter @ 2011-12-11  0:15 UTC (permalink / raw)


On 12/10/2011 01:43 PM, Ada @ BRL wrote:
>
> ADA.

Is that the American Dental Association, the Americans with Disabilities Act, or 
is there a British acronym I'm not aware of?

Ada is named for Augusta Ada King, n�e Byron, Countess of Lovelace, born on this 
date in 1815, who wrote programs for Babbage's analytical engine and so may be 
the first programmer. It's not an acronym.

As others have pointed out, when using a high-level language like Ada, one 
should use high-level mechanisms provided by the language, not the low-level 
mechanisms you'd use when using a low-level language like C or its descendants.

-- 
Jeff Carter
"You've got the brain of a four-year-old boy,
and I bet he was glad to get rid of it."
Horse Feathers
47

--- Posted via news://freenews.netfront.net/ - Complaints to news@netfront.net ---



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

* Re: Interrupts handling in ADA
  2011-12-10 20:43 Interrupts handling in ADA Ada @ BRL
                   ` (3 preceding siblings ...)
  2011-12-11  0:15 ` Jeffrey Carter
@ 2011-12-11  9:23 ` Dmitry A. Kazakov
  2011-12-13 13:11   ` Ada BRL
  2011-12-11 12:04 ` Georg Bauhaus
  2011-12-12  3:19 ` anon
  6 siblings, 1 reply; 46+ messages in thread
From: Dmitry A. Kazakov @ 2011-12-11  9:23 UTC (permalink / raw)


On Sat, 10 Dec 2011 12:43:58 -0800 (PST), Ada @ BRL wrote:

> The environment of ADA applcation is:
> I have 4 tasks that execute at the same time:
> one is the main task,
> the other three execute a "read" from network (socket) function inside
> their bodies (on the other side there's the C/C++ application with 3
> network sockets).
> [I decided to use the sockets instead of dll/lib import because this approach hasn't worked... =( ]

What dll import has to do with sockets, except that sockets usually are
provided by a library? 

> I want that when new data is available on one or more socket threads, this
> / these threads somehow notify the main thread that data is arrived and
> then safely send the data to it.

If you have many sockets, you should probably use select on them rather
than blocking calls from many tasks. The maximal number of tasks supported
by the OS is usually much lower than the maximal number of sockets.
 
> I've thought to use the interrupts...

Interrupt in Ada is meant more like "hardware interrupt." It is possible
but unlikely that your network stack generates such interrupts or that you
could have an access to them under the OS you are running.

Software interrupt, also called asynchronous system trap (AST) is a
different thing. What you had in mind is probably a software interrupt. The
corresponding Ada mechanism is "Asynchronous Transfer of Control" (ATC).
But there are much better ways.

> because I haven't found any
> references about the use of "events" in ADA.

Events are low-level synchronization objects easily implemented using Ada
protected objects, e.g.:

http://www.dmitry-kazakov.de/ada/components.htm#Events

Events are rarely used in Ada, because for inter task communication you
have higher-level means.

> I've thought to attach three different handler of interrupts into the main
> task and then to generate the interrupt from the socket task with

There are many ways to implement things like this:

1. One task + socket select

2. "Monitor": multiple socket readers do rendezvous to the main task, which
accept the rendezvous.

3. "Queue": socket readers enqueue some data (the queue is implemented
using a protected object). Other tasks (there could be many) dequeue data
and do something meaningful with them. There are many kinds of queues for
different purposes and of different behavior.

4. Single rank co-workers. Each socket reader processes data by themselves.
In order to interlock processing there is a semaphore/mutex (implemented by
a protected object), which is seized when processing starts and released
afterwards.

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



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

* Re: Interrupts handling in ADA
  2011-12-10 20:43 Interrupts handling in ADA Ada @ BRL
                   ` (4 preceding siblings ...)
  2011-12-11  9:23 ` Dmitry A. Kazakov
@ 2011-12-11 12:04 ` Georg Bauhaus
  2011-12-13 14:08   ` Ada BRL
  2011-12-12  3:19 ` anon
  6 siblings, 1 reply; 46+ messages in thread
From: Georg Bauhaus @ 2011-12-11 12:04 UTC (permalink / raw)


On 10.12.11 21:43, Ada @ BRL wrote:
> Hello,
> I'm an Erasmus student at the University of Bristol - UK and I'm carrying out the work for my master thesis in Computer Engineering.
>
> I'm programming a multithreading application in C / C++ and ADA.
> The latter is a completely new language for me...
>
> The environment of ADA applcation is:
> I have 4 tasks that execute at the same time:
> one is the main task,
> the other three execute a "read" from network (socket) function inside their bodies (on the other side there's the C/C++ application with 3 network sockets).
> [I decided to use the sockets instead of dll/lib import because this approach hasn't worked... =( ]

Just to make sure: Do you have 4 Ada tasks that should
communicate, or do you have an Ada program and 3 programs
or pthread style functions written in C or C++ that should
communicate with the Ada program?

In the first case, simply look for "entry", "select", and "accept",
These means of inter-task communications have been built into Ada
since day 1.

(That's
http://en.wikibooks.org/wiki/Ada_Programming/Tasking#Rendezvous
on the page mentioned by Niklas Holsti. There is also
http://www.adaic.org/learn/materials/ )

Say I have two task objects A and B, and B should accept calls from other
tasks at an entry named "Data_Available". The notification is written
in the body the calling task, A in this case. It could look like

    ...
    B.Data_Available;  --  A notifies B
    ...

Done. That's all. If A also wishes to send data directly, then
B would accept them simply in a parameter. Then, "Data_Available"
would have been declared with a parameter instead of without one
as in the case above.
The notification, which then includes data to be sent, could look like

    ...
    B.Data_Available (Data_To_Be_Sent);
    ...

It is also possible to combine the first, simple notification (without
data) with employing a third object, a mailbox style object, as outlined
in other answers in this thread.  The mailbox can be a protected object
(language defined term, roughly clever type for shared variables with mutex
and conditional waiting), or another dedicated task object. The model
in either case  is:

    -- body of A:
    Mailbox.Add_Data (Data_for_B);  -- make data available
    B.Data_Available;   -- notify B of data available, as before
    ...

    -- body of B:
    accept Data_Available;  -- be notified of data available in mailbox
    Mailbox.Get_Data (Storage => Room_for_Data);
       -- load from mailbox and store into a variable local to B

Or you could have B wait at the mailbox until A makes data
available in the mailbox. The tasks would not have to communicate
directly, then.  For this to work, the Mailbox object will
a procedure for tasks that wish to add data to the mailbox, and
an entry for tasks that wish to get data out of the mailbox,
"E" say. The entry is guarded by a barrier. The barrier
will get lifted as soon as a task such as a A has supplied data
to the box. The effect is then that a task like B, having waited
in the queue of entry "E", will be "notified" of the presence
of data and continues, i.e., loads data from the mailbox.



- HTH Georg



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

* Re: Interrupts handling in ADA
  2011-12-10 22:27 ` Simon Wright
@ 2011-12-11 20:21   ` Martin Dowie
  2011-12-13 13:51     ` Ada BRL
  2011-12-13 14:11     ` Niklas Holsti
  2011-12-13 12:47   ` Ada BRL
  1 sibling, 2 replies; 46+ messages in thread
From: Martin Dowie @ 2011-12-11 20:21 UTC (permalink / raw)


Simon Wright <simon@pushface.org> wrote:
> "Ada @ BRL" <ada.brl.2011@gmail.com> writes:
> 
>> The environment of ADA applcation is:
> 
> Ada, please!

Here, here! :-)


> The new Ada2012 standard includes a synchronised Queue, which would be
> just what you want out of the box, but you won't find that in the
> current compilers, so you'll need to roll your own.

Just a thought but perhaps the OP would qualify for the GNAT Academic
Edition? In which case, they might get access to GNAT 7.0 pre-release which
does have the new standard queue libraries.

http://www.adacore.com/home/academia/

-- Martin



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

* Re: Interrupts handling in ADA
  2011-12-10 20:43 Interrupts handling in ADA Ada @ BRL
                   ` (5 preceding siblings ...)
  2011-12-11 12:04 ` Georg Bauhaus
@ 2011-12-12  3:19 ` anon
  2011-12-12  9:12   ` Niklas Holsti
                     ` (2 more replies)
  6 siblings, 3 replies; 46+ messages in thread
From: anon @ 2011-12-12  3:19 UTC (permalink / raw)


--  Interrupts are not necessary. From you description a simple set of 
--  tasks is all that is needed.
--
--  This program outline uses three task to read three sockets and
--  after pre-processing and verifing data (if needed) passes this
--  data to a main task. The main task then can continue processing 
--  this data.
--
--  Exception handling is limited to Socket error which will cause 
--  that task to die and after reporting to the Main task. Then Main 
--  task uses the abort statement to kill other tasks.
--  

with Ada.Text_IO ;
with Interfaces ;
with GNAT.Sockets ;

use  Ada.Text_IO ;
use  Interfaces ;
use  GNAT.Sockets ;

procedure v is

  localhost : constant Inet_Addr_Type := Inet_Addr ( "127.0.0.1" ) ;
  localport : constant Port_Type      := 16#FFF0# ;

  task One is
      entry Start ; -- to insure network is operational
  end One ;

  task Two is
      entry Start ;
  end Two ;

  task Three is
      entry Start ;
  end Three ;

  task Main is
      --  accept data from first two tasks. 

      entry Acknowledge_1 ( Data : Unsigned_32 ) ;
      entry Acknowledge_2 ( Data : Unsigned_32 ) ;

      --  accept data from third task only

      entry Control ( Data : Character ) ;

      --  denotes that network exception has ocurred from one of 
      --  the three tasks. The ( 1 .. 3 ) sets a range for 
      --  identifing the calling task. Where ( 1 ) is task One,
      --  ( 2 ) is task Two and ( 3 ) is task Three.

      entry Dead ( 1 .. 3 ) ;
  end Main ;

  --
  --  Task bodies
  --
  task body One is

      Socket  : Socket_Type    ;
      Address : Sock_Addr_Type ;
      Channel : Stream_Access  ;

      Data    : Unsigned_32 ;

  begin
    -- Initialize Sockect

    Create_Socket ( Socket, Family_Inet, Socket_Datagram ) ;
    Address.Addr := localhost ;
    Address.Port := localport + 1 ;
    Connect_Socket ( Socket, Address ) ;
    Channel := Stream ( Socket ) ;

    accept Start ;

        -- Wait for controller to activate
        loop

          -- Wait for data.

          Unsigned_32'Read ( Channel, Data ) ;

          -- Verify or Pre-process data, if needed

          -- Send data to main task.

          Main.Acknowledge_1 ( Data ) ;
        end loop ;

  exception
    when Socket_Error =>
        if Main'Callable then
          Main.Dead ( 1 ) ;
        end if ;
        Close_Socket ( Socket ) ;
  end One ;

  task body Two is

      Socket  : Socket_Type    ;
      Address : Sock_Addr_Type ;
      Channel : Stream_Access  ;

      Data    : Unsigned_32 ;

  begin
    -- Initialize Sockect

    Create_Socket ( Socket, Family_Inet, Socket_Datagram ) ;
    Address.Addr := localhost ;
    Address.Port := localport + 2 ;
    Connect_Socket ( Socket, Address ) ;
    Channel := Stream ( Socket ) ;

    accept Start ;

        -- Wait for controller to activate
        loop

          -- Wait for data.

          Unsigned_32'Read ( Channel, Data ) ;

          -- Verify or Pre-process data, if needed

          -- Send data to main task.

          Main.Acknowledge_2 ( Data ) ;
        end loop ;

  exception
    when Socket_Error =>
        if Main'Callable then
          Main.Dead ( 2 ) ;
        end if ;
        Close_Socket ( Socket ) ;
  end Two ;


  task body Three is

      Socket  : Socket_Type    ;
      Address : Sock_Addr_Type ;
      Channel : Stream_Access  ;

      Data    : Character ;

  begin
    -- Initialize Sockect

    Create_Socket ( Socket, Family_Inet, Socket_Datagram ) ;
    Address.Addr := localhost ;
    Address.Port := localport + 3 ;
    Connect_Socket ( Socket, Address ) ;
    Channel := Stream ( Socket ) ;

    accept Start ;

        -- Wait for controller to activate
        loop

          -- Wait for data.

          Character'Read ( Channel, Data ) ;

          -- Verify or Pre-process data, if needed

          -- Send data to main task.

          Main.Control ( Data ) ;
        end loop ;

  exception
    when Socket_Error =>
        if Main'Callable then
          Main.Dead ( 3 ) ;
        end if ;
        Close_Socket ( Socket ) ;
  end Three ;

  --
  --  Main Task body
  --
  task body Main is

    Task_1_Data : Unsigned_32 ;
    Task_2_Data : Unsigned_32 ;
    Task_3_Data : Character ;
    --
    Task_Error : exception ;

  begin
    -- preform any initialize
    loop
      select
        accept Acknowledge_1 ( Data : Unsigned_32 ) do
          Task_1_Data := Data ;
          -- process data from task 1
        end Acknowledge_1 ;
      or  
        accept Acknowledge_2 ( Data : Unsigned_32 ) do
          Task_2_Data := Data ;
          -- process data from task 2
        end Acknowledge_2 ;
      or
        accept Control ( Data : Character ) do
          Task_3_Data := Data ;
          -- process data from task 3
        end Control ;
      or
        accept Dead ( 1 ) ;
          Put_Line ( "Error has ocurred in Task One" ) ;
          raise Task_Error ;
      or
        accept Dead ( 2 ) ;
          Put_Line ( "Error has ocurred in Task Two" ) ;
          raise Task_Error ;
      or
        accept Dead ( 3 ) ;
          Put_Line ( "Error has ocurred in Task Three" ) ;
          raise Task_Error ;
      end select ;

      -- Continue processing with Data from all tasks 

    end loop ;

  exception    
    when Task_Error =>
      Put_Line ( "Error has cause this program to die" ) ;
       -- abort all tasks
      abort One ;
      abort Two ;
      abort Three ;
  end Main ;


--
-- The Main task could start the three child task 
--

begin

  -- Verify all task are operational

  if not One'Callable then
    Put_Line ( "Error in Task One" ) ;
    abort Two ;
    abort Three ;
    abort Main  ;

  elsif not Two'Callable then
    Put_Line ( "Error in Task Two" ) ;
    abort One ;
    abort Three ;
    abort Main  ;

  elsif not Three'Callable then
    Put_Line ( "Error in Task Three" ) ;
    abort One ;
    abort Two ;
    abort Main  ;

  else
    One.Start ;
    Two.Start ;
    Three.Start ;
  end if ;

exception
  when others =>
    null ;  
end v ;



In <30143086.6.1323549838421.JavaMail.geo-discussion-forums@vbbfq24>, "Ada @ BRL" <ada.brl.2011@gmail.com> writes:
>Hello,
>I'm an Erasmus student at the University of Bristol - UK and I'm carrying out the work for my master thesis in Computer Engineering.
>
>I'm programming a multithreading application in C / C++ and ADA.
>The latter is a completely new language for me...
>
>The environment of ADA applcation is:
>I have 4 tasks that execute at the same time:
>one is the main task,
>the other three execute a "read" from network (socket) function inside their bodies (on the other side there's the C/C++ application with 3 network sockets).
>[I decided to use the sockets instead of dll/lib import because this approach hasn't worked... =( ]
>
>I want that when new data is available on one or more socket threads, this / these threads somehow notify the main thread that data is arrived and then safely send the data to it.
>
>I've thought to use the interrupts...because I haven't found any references about the use of "events" in ADA.
>I've thought to attach three different handler of interrupts into the main task and then to generate the interrupt from the socket task with ada.interrupts.signal.generate_interrupt.
>Socket 1 will generate interrupt #1, socket 2 -> interrupt #2 and so on.
>
>May you tell me please if this is the right way to face the problem?
>I'm not skilled in ada and so there could be other better methods...
>
>I've used the pragmas attach_handler and interrupt_handler but unfortunately I'm still not able to get all the stuff working...
>
>I think it's a problem of ADA implementation because:
>even if I call pragma unreserve_all_interrupts I've found that the function Is_Reserved(Interr_ID) returns FALSE only for this signals IDs: 2(SIGINT), 4(SIGILL), 8(SIGFPE), 11(SISEGV), 15(SIGTERM), 22(SIGABRT).
>
>I guess that this is the opposite behaviour as I expected...
>If I try to set an handler to the interrupt say 9, the program cannot start due to this error:
>
>raised PROGRAM_ERROR : adjust/finalize raised PROGRAM_ERROR: s-interr.adb:343 explicit raise
>
>If I call the function Is_Attached the program suddenly exits:
>Program exited with code 01.
>(gdb) 
>
>Do you know if is it possible to generate user defined interrupts?
>
>Can you help me please to find out what's the problem?
>Unfortunately there's not so much documentation about ADA  =( and I'm late for my thesis...
>
>Thank you very much in advance for your help,
>Ada @ BRL




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

* Re: Interrupts handling in ADA
  2011-12-12  3:19 ` anon
@ 2011-12-12  9:12   ` Niklas Holsti
  2011-12-13 13:36     ` Ada BRL
  2011-12-12 15:23   ` björn lundin
  2011-12-13 13:31   ` Ada BRL
  2 siblings, 1 reply; 46+ messages in thread
From: Niklas Holsti @ 2011-12-12  9:12 UTC (permalink / raw)


On 11-12-12 05:19 , anon@att.net wrote:
> --  Interrupts are not necessary. From you description a simple set of
> --  tasks is all that is needed.
> --
> --  This program outline uses three task to read three sockets and
> --  after pre-processing and verifing data (if needed) passes this
> --  data to a main task. The main task then can continue processing
> --  this data.

Just a small comment on a detail in the example:

>    task body Main is
...
>    begin
...
>          accept Acknowledge_1 ( Data : Unsigned_32 ) do
>            Task_1_Data := Data ;
>            -- process data from task 1
>          end Acknowledge_1 ;

The rendezvous between the Main task and task 1 continues until the "end 
Acknowledge_1". If the Main task processes the data from task 1 before 
the "end Acknowledge_1", as above, task 1 cannot do anything else during 
this processing. The program may be more responsive if the processing is 
done after the rendezvous, in this way:

         accept Acknowledge_1 ( Data : Unsigned_32 ) do
           Task_1_Data := Data ;
         end Acknowledge_1 ;
         -- process data from task 1

In this form, the call of Acknowledge_1 from task 1 returns before the 
processing, which means that task 1 can go on to do other things, while 
the Main task is processing the data in Task_1_Data.

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



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

* Re: Interrupts handling in ADA
  2011-12-12  3:19 ` anon
  2011-12-12  9:12   ` Niklas Holsti
@ 2011-12-12 15:23   ` björn lundin
  2011-12-13 13:38     ` Ada BRL
  2011-12-13 13:31   ` Ada BRL
  2 siblings, 1 reply; 46+ messages in thread
From: björn lundin @ 2011-12-12 15:23 UTC (permalink / raw)


On 12 Dec, 04:19, a...@att.net wrote:

>   exception
>     when Socket_Error =>
>         if Main'Callable then
>           Main.Dead ( 1 ) ;
>         end if ;
>         Close_Socket ( Socket ) ;
>   end One ;
>

Another small nit-picking note.
The call to Main.Dead may still cause Tasking_Error,
since the result of Main'Callable may have changed
during the time between the check and the call.
Unlikely yes, but still.

     when Socket_Error =>
         begin
           Main.Dead ( 1 ) ;
         exception
           when Tasking_Error => null; -- or printout
         end;
         Close_Socket ( Socket ) ;
   end One ;

This way the call to Main.Dead will succeed or not,
but Close_Socket will always be called

--
Björn Lundin










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

* Re: Interrupts handling in ADA
  2011-12-10 22:27 ` Simon Wright
  2011-12-11 20:21   ` Martin Dowie
@ 2011-12-13 12:47   ` Ada BRL
  2011-12-13 15:07     ` Simon Wright
  1 sibling, 1 reply; 46+ messages in thread
From: Ada BRL @ 2011-12-13 12:47 UTC (permalink / raw)


On 10 Dic, 22:27, Simon Wright <si...@pushface.org> wrote:
> "Ada @ BRL" <ada.brl.2...@gmail.com> writes:
>
> > The environment of ADA applcation is:
>
> Ada, please!
>
>
>
> > I have 4 tasks that execute at the same time:
> > one is the main task,
> > the other three execute a "read" from network (socket) function inside
> > their bodies (on the other side there's the C/C++ application with 3
> > network sockets).
> [...]
> > I want that when new data is available on one or more socket threads,
> > this / these threads somehow notify the main thread that data is
> > arrived and then safely send the data to it.
>
> First off, I'd use a Queue.
>
> The new Ada2012 standard includes a synchronised Queue, which would be
> just what you want out of the box, but you won't find that in the
> current compilers, so you'll need to roll your own.
>
> Starting from Ada.Containers.Vectors[1], the Queue abstraction would
> come from using Append to put new mesages on the queue, Is_Empty to
> check whether there's something to get from the queue, and First_Element
> followed by Delete_First to fetch the front element.
>
> You then need to wrap this container in a protected object[2], so that
> the updates from the different input tasks don't corrupt each other, and
> so that the main task can block until there's something to read. Use a
> Put procedure to post messages onto the queue, and a Get entry to read
> the next message or block if there isn't one.
>
> The spec might look like
>
>    with Ada.Containers.Vectors;
>    package Queueing is
>       type Message is new Integer;
>       package Queue_Data
>       is new Ada.Containers.Vectors (Index_Type => Natural,
>                                      Element_Type => Message);
>       protected Queue is
>          procedure Put (M : Message);
>          entry Get (M : out Message);
>       private
>          Buffer : Queue_Data.Vector;
>       end Queue;
>    end Queueing;
>
> and (as a hint) the body of the Get entry might start like
>
>       entry Get (M : out Message) when not Buffer.Is_Empty is
>       begin
>
> If your input messages are not all the same type (in Ada-speak, type
> Message is indefinite), things get more complicated; but let's cross
> that bridge only if we need to.
>
> [1]http://www.adaic.org/resources/add_content/standards/05rm/html/RM-A-1...
> [2]http://en.wikibooks.org/wiki/Ada_Programming/Tasking#Protected_types

Thank you for the reply!

Please tell me if I'm wrong:

- inside the main task I must use an accept statement "Get": by doing
it, this means that the main task wait on this "barrier" until there
is something inside the protected object queue; when entry Get is
available (due to the incoming data), the main task is automatically
notified and it executes the Get function, isnt' it? So the entry /
accept paradigm is something like events in C?
So the main task doesn't has to constantly poll the queue; the entry /
accept statement do it by itself. Am I right?

Thank everyone for the help!!!



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

* Re: Interrupts handling in ADA
  2011-12-11  0:15 ` Jeffrey Carter
@ 2011-12-13 12:53   ` Ada BRL
  0 siblings, 0 replies; 46+ messages in thread
From: Ada BRL @ 2011-12-13 12:53 UTC (permalink / raw)


On 11 Dic, 00:15, Jeffrey Carter <spam.jrcarter....@spam.not.acm.org>
wrote:
> On 12/10/2011 01:43 PM, Ada @ BRL wrote:
>
>
>
> > ADA.
>
> Is that the American Dental Association, the Americans with Disabilities Act, or
> is there a British acronym I'm not aware of?
>
> Ada is named for Augusta Ada King, née Byron, Countess of Lovelace, born on this
> date in 1815, who wrote programs for Babbage's analytical engine and so may be
> the first programmer. It's not an acronym.
>
> As others have pointed out, when using a high-level language like Ada, one
> should use high-level mechanisms provided by the language, not the low-level
> mechanisms you'd use when using a low-level language like C or its descendants.
>
> --
> Jeff Carter
> "You've got the brain of a four-year-old boy,
> and I bet he was glad to get rid of it."
> Horse Feathers
> 47
>
> --- Posted via news://freenews.netfront.net/ - Complaints to n...@netfront.net ---

Sorry...I haven't paid much attention on it... =) I know that's the
name of Ada (not ADA) Lovelace =).

You know, english people like very much acronyms, so I've found
somewhere ADA instead of Ada as well...

Bye!



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

* Re: Interrupts handling in ADA
  2011-12-11  9:23 ` Dmitry A. Kazakov
@ 2011-12-13 13:11   ` Ada BRL
  2011-12-13 14:04     ` Dmitry A. Kazakov
  0 siblings, 1 reply; 46+ messages in thread
From: Ada BRL @ 2011-12-13 13:11 UTC (permalink / raw)


On 11 Dic, 09:23, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Sat, 10 Dec 2011 12:43:58 -0800 (PST), Ada @ BRL wrote:
> > The environment of ADA applcation is:
> > I have 4 tasks that execute at the same time:
> > one is the main task,
> > the other three execute a "read" from network (socket) function inside
> > their bodies (on the other side there's the C/C++ application with 3
> > network sockets).
> > [I decided to use the sockets instead of dll/lib import because this approach hasn't worked... =( ]
>
> What dll import has to do with sockets, except that sockets usually are
> provided by a library?

I would have liked to use dll import to exchange data between C stuff
and Ada program instead of using two programs (C and Ada)
communicating through sockets...
but the dll import hasn't worked even with dummy and correct dll...
So, in order to overcome the problem, I've decided to use sockets.

>
> > I want that when new data is available on one or more socket threads, this
> > / these threads somehow notify the main thread that data is arrived and
> > then safely send the data to it.
>
> If you have many sockets, you should probably use select on them rather
> than blocking calls from many tasks. The maximal number of tasks supported
> by the OS is usually much lower than the maximal number of sockets.

I have a maximum of 5 sockets so I guess there will be no problems
onto the OS side...I hope so =).

What's the "select" you have just mentioned?

>
> > I've thought to use the interrupts...
>
> Interrupt in Ada is meant more like "hardware interrupt." It is possible
> but unlikely that your network stack generates such interrupts or that you
> could have an access to them under the OS you are running.

Ok, now I've figured out that the Ada interrupts are only HW and not
SW.
The software interrupts are implemented with entry / accept paradigm
(like events in C++? ).


>
> Software interrupt, also called asynchronous system trap (AST) is a
> different thing. What you had in mind is probably a software interrupt.


YES!


> The corresponding Ada mechanism is "Asynchronous Transfer of Control" (ATC).
> But there are much better ways.
>
> > because I haven't found any
> > references about the use of "events" in ADA.
>
> Events are low-level synchronization objects easily implemented using Ada
> protected objects, e.g.:
>
> http://www.dmitry-kazakov.de/ada/components.htm#Events
>
> Events are rarely used in Ada, because for inter task communication you
> have higher-level means.
>
> > I've thought to attach three different handler of interrupts into the main
> > task and then to generate the interrupt from the socket task with
>
> There are many ways to implement things like this:
>
> 1. One task + socket select

See above: what's select?

>
> 2. "Monitor": multiple socket readers do rendezvous to the main task, which
> accept the rendezvous.

In rendez-vous paradigm, is the main task forced to wait for ALL the
socket tasks or only for a subset of them?
Eg: only socket #2 has received some data, can the main task execute
or does it have to wait also for the other sockets?

>
> 3. "Queue": socket readers enqueue some data (the queue is implemented
> using a protected object). Other tasks (there could be many) dequeue data
> and do something meaningful with them. There are many kinds of queues for
> different purposes and of different behavior.
>
> 4. Single rank co-workers. Each socket reader processes data by themselves.
> In order to interlock processing there is a semaphore/mutex (implemented by
> a protected object), which is seized when processing starts and released
> afterwards.


In your opinion, what's the most effective and at the same time
simplest way to sort out my problem?
Simon Wright has posted an example of Protected queue and entry /
accept statements and it seems to be simple but effective as well.

>
> --
> Regards,
> Dmitry A. Kazakovhttp://www.dmitry-kazakov.de




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

* Re: Interrupts handling in ADA
  2011-12-12  3:19 ` anon
  2011-12-12  9:12   ` Niklas Holsti
  2011-12-12 15:23   ` björn lundin
@ 2011-12-13 13:31   ` Ada BRL
  2 siblings, 0 replies; 46+ messages in thread
From: Ada BRL @ 2011-12-13 13:31 UTC (permalink / raw)


On 12 Dic, 03:19, a...@att.net wrote:
> --  Interrupts are not necessary. From you description a simple set of
> --  tasks is all that is needed.
> --
> --  This program outline uses three task to read three sockets and
> --  after pre-processing and verifing data (if needed) passes this
> --  data to a main task. The main task then can continue processing
> --  this data.
> --
> --  Exception handling is limited to Socket error which will cause
> --  that task to die and after reporting to the Main task. Then Main
> --  task uses the abort statement to kill other tasks.
> --
>
> with Ada.Text_IO ;
> with Interfaces ;
> with GNAT.Sockets ;
>
> use  Ada.Text_IO ;
> use  Interfaces ;
> use  GNAT.Sockets ;
>
> procedure v is
>
>   localhost : constant Inet_Addr_Type := Inet_Addr ( "127.0.0.1" ) ;
>   localport : constant Port_Type      := 16#FFF0# ;
>
>   task One is
>       entry Start ; -- to insure network is operational
>   end One ;
>
>   task Two is
>       entry Start ;
>   end Two ;
>
>   task Three is
>       entry Start ;
>   end Three ;
>
>   task Main is
>       --  accept data from first two tasks.
>
>       entry Acknowledge_1 ( Data : Unsigned_32 ) ;
>       entry Acknowledge_2 ( Data : Unsigned_32 ) ;
>
>       --  accept data from third task only
>
>       entry Control ( Data : Character ) ;
>
>       --  denotes that network exception has ocurred from one of
>       --  the three tasks. The ( 1 .. 3 ) sets a range for
>       --  identifing the calling task. Where ( 1 ) is task One,
>       --  ( 2 ) is task Two and ( 3 ) is task Three.
>
>       entry Dead ( 1 .. 3 ) ;
>   end Main ;
>
>   --
>   --  Task bodies
>   --
>   task body One is
>
>       Socket  : Socket_Type    ;
>       Address : Sock_Addr_Type ;
>       Channel : Stream_Access  ;
>
>       Data    : Unsigned_32 ;
>
>   begin
>     -- Initialize Sockect
>
>     Create_Socket ( Socket, Family_Inet, Socket_Datagram ) ;
>     Address.Addr := localhost ;
>     Address.Port := localport + 1 ;
>     Connect_Socket ( Socket, Address ) ;
>     Channel := Stream ( Socket ) ;
>
>     accept Start ;
>
>         -- Wait for controller to activate
>         loop
>
>           -- Wait for data.
>
>           Unsigned_32'Read ( Channel, Data ) ;
>
>           -- Verify or Pre-process data, if needed
>
>           -- Send data to main task.
>
>           Main.Acknowledge_1 ( Data ) ;
>         end loop ;
>
>   exception
>     when Socket_Error =>
>         if Main'Callable then
>           Main.Dead ( 1 ) ;
>         end if ;
>         Close_Socket ( Socket ) ;
>   end One ;
>
>   task body Two is
>
>       Socket  : Socket_Type    ;
>       Address : Sock_Addr_Type ;
>       Channel : Stream_Access  ;
>
>       Data    : Unsigned_32 ;
>
>   begin
>     -- Initialize Sockect
>
>     Create_Socket ( Socket, Family_Inet, Socket_Datagram ) ;
>     Address.Addr := localhost ;
>     Address.Port := localport + 2 ;
>     Connect_Socket ( Socket, Address ) ;
>     Channel := Stream ( Socket ) ;
>
>     accept Start ;
>
>         -- Wait for controller to activate
>         loop
>
>           -- Wait for data.
>
>           Unsigned_32'Read ( Channel, Data ) ;
>
>           -- Verify or Pre-process data, if needed
>
>           -- Send data to main task.
>
>           Main.Acknowledge_2 ( Data ) ;
>         end loop ;
>
>   exception
>     when Socket_Error =>
>         if Main'Callable then
>           Main.Dead ( 2 ) ;
>         end if ;
>         Close_Socket ( Socket ) ;
>   end Two ;
>
>   task body Three is
>
>       Socket  : Socket_Type    ;
>       Address : Sock_Addr_Type ;
>       Channel : Stream_Access  ;
>
>       Data    : Character ;
>
>   begin
>     -- Initialize Sockect
>
>     Create_Socket ( Socket, Family_Inet, Socket_Datagram ) ;
>     Address.Addr := localhost ;
>     Address.Port := localport + 3 ;
>     Connect_Socket ( Socket, Address ) ;
>     Channel := Stream ( Socket ) ;
>
>     accept Start ;
>
>         -- Wait for controller to activate
>         loop
>
>           -- Wait for data.
>
>           Character'Read ( Channel, Data ) ;
>
>           -- Verify or Pre-process data, if needed
>
>           -- Send data to main task.
>
>           Main.Control ( Data ) ;
>         end loop ;
>
>   exception
>     when Socket_Error =>
>         if Main'Callable then
>           Main.Dead ( 3 ) ;
>         end if ;
>         Close_Socket ( Socket ) ;
>   end Three ;
>
>   --
>   --  Main Task body
>   --
>   task body Main is
>
>     Task_1_Data : Unsigned_32 ;
>     Task_2_Data : Unsigned_32 ;
>     Task_3_Data : Character ;
>     --
>     Task_Error : exception ;
>
>   begin
>     -- preform any initialize
>     loop
>       select
>         accept Acknowledge_1 ( Data : Unsigned_32 ) do
>           Task_1_Data := Data ;
>           -- process data from task 1
>         end Acknowledge_1 ;
>       or
>         accept Acknowledge_2 ( Data : Unsigned_32 ) do
>           Task_2_Data := Data ;
>           -- process data from task 2
>         end Acknowledge_2 ;
>       or
>         accept Control ( Data : Character ) do
>           Task_3_Data := Data ;
>           -- process data from task 3
>         end Control ;
>       or
>         accept Dead ( 1 ) ;
>           Put_Line ( "Error has ocurred in Task One" ) ;
>           raise Task_Error ;
>       or
>         accept Dead ( 2 ) ;
>           Put_Line ( "Error has ocurred in Task Two" ) ;
>           raise Task_Error ;
>       or
>         accept Dead ( 3 ) ;
>           Put_Line ( "Error has ocurred in Task Three" ) ;
>           raise Task_Error ;
>       end select ;
>
>       -- Continue processing with Data from all tasks
>
>     end loop ;
>
>   exception
>     when Task_Error =>
>       Put_Line ( "Error has cause this program to die" ) ;
>        -- abort all tasks
>       abort One ;
>       abort Two ;
>       abort Three ;
>   end Main ;
>
> --
> -- The Main task could start the three child task
> --
>
> begin
>
>   -- Verify all task are operational
>
>   if not One'Callable then
>     Put_Line ( "Error in Task One" ) ;
>     abort Two ;
>     abort Three ;
>     abort Main  ;
>
>   elsif not Two'Callable then
>     Put_Line ( "Error in Task Two" ) ;
>     abort One ;
>     abort Three ;
>     abort Main  ;
>
>   elsif not Three'Callable then
>     Put_Line ( "Error in Task Three" ) ;
>     abort One ;
>     abort Two ;
>     abort Main  ;
>
>   else
>     One.Start ;
>     Two.Start ;
>     Three.Start ;
>   end if ;
>
> exception
>   when others =>
>     null ;
> end v ;
>
> In <30143086.6.1323549838421.JavaMail.geo-discussion-forums@vbbfq24>, "Ada @ BRL" <ada.brl.2...@gmail.com> writes:
>
>
>
>
>
>
>
> >Hello,
> >I'm an Erasmus student at the University of Bristol - UK and I'm carrying out the work for my master thesis in Computer Engineering.
>
> >I'm programming a multithreading application in C / C++ and ADA.
> >The latter is a completely new language for me...
>
> >The environment of ADA applcation is:
> >I have 4 tasks that execute at the same time:
> >one is the main task,
> >the other three execute a "read" from network (socket) function inside their bodies (on the other side there's the C/C++ application with 3 network sockets).
> >[I decided to use the sockets instead of dll/lib import because this approach hasn't worked... =( ]
>
> >I want that when new data is available on one or more socket threads, this / these threads somehow notify the main thread that data is arrived and then safely send the data to it.
>
> >I've thought to use the interrupts...because I haven't found any references about the use of "events" in ADA.
> >I've thought to attach three different handler of interrupts into the main task and then to generate the interrupt from the socket task with ada.interrupts.signal.generate_interrupt.
> >Socket 1 will generate interrupt #1, socket 2 -> interrupt #2 and so on.
>
> >May you tell me please if this is the right way to face the problem?
> >I'm not skilled in ada and so there could be other better methods...
>
> >I've used the pragmas attach_handler and interrupt_handler but unfortunately I'm still not able to get all the stuff working...
>
> >I think it's a problem of ADA implementation because:
> >even if I call pragma unreserve_all_interrupts I've found that the function Is_Reserved(Interr_ID) returns FALSE only for this signals IDs: 2(SIGINT), 4(SIGILL), 8(SIGFPE), 11(SISEGV), 15(SIGTERM), 22(SIGABRT).
>
> >I guess that this is the opposite behaviour as I expected...
> >If I try to set an handler to the interrupt say 9, the program cannot start due to this error:
>
> >raised PROGRAM_ERROR : adjust/finalize raised PROGRAM_ERROR: s-interr.adb:343 explicit raise
>
> >If I call the function Is_Attached the program suddenly exits:
> >Program exited with code 01.
> >(gdb)
>
> >Do you know if is it possible to generate user defined interrupts?
>
> >Can you help me please to find out what's the problem?
> >Unfortunately there's not so much documentation about ADA  =( and I'm late for my thesis...
>
> >Thank you very much in advance for your help,
> >Ada @ BRL

Thank you for your complete example!



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

* Re: Interrupts handling in ADA
  2011-12-12  9:12   ` Niklas Holsti
@ 2011-12-13 13:36     ` Ada BRL
  0 siblings, 0 replies; 46+ messages in thread
From: Ada BRL @ 2011-12-13 13:36 UTC (permalink / raw)


On 12 Dic, 09:12, Niklas Holsti <niklas.hol...@tidorum.invalid> wrote:
> On 11-12-12 05:19 , a...@att.net wrote:
>
> > --  Interrupts are not necessary. From you description a simple set of
> > --  tasks is all that is needed.
> > --
> > --  This program outline uses three task to read three sockets and
> > --  after pre-processing and verifing data (if needed) passes this
> > --  data to a main task. The main task then can continue processing
> > --  this data.
>
> Just a small comment on a detail in the example:
>
>
>
> >    task body Main is
> ...
> >    begin
> ...
> >          accept Acknowledge_1 ( Data : Unsigned_32 ) do
> >            Task_1_Data := Data ;
> >            -- process data from task 1
> >          end Acknowledge_1 ;
>
> The rendezvous between the Main task and task 1 continues until the "end
> Acknowledge_1". If the Main task processes the data from task 1 before
> the "end Acknowledge_1", as above, task 1 cannot do anything else during
> this processing. The program may be more responsive if the processing is
> done after the rendezvous, in this way:
>
>          accept Acknowledge_1 ( Data : Unsigned_32 ) do
>            Task_1_Data := Data ;
>          end Acknowledge_1 ;
>          -- process data from task 1
>
> In this form, the call of Acknowledge_1 from task 1 returns before the
> processing, which means that task 1 can go on to do other things, while
> the Main task is processing the data in Task_1_Data.
>
> --
> Niklas Holsti
> Tidorum Ltd
> niklas holsti tidorum fi
>        .      @       .

Thank you very much!

You have replied to my question even before I asked!
I don't want that the sockets are blocked at any time, they must be
responsive to the incoming data from C side in every moment!!!
I must not miss any data because, in this case, I would incur in a
safety violation of the system.



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

* Re: Interrupts handling in ADA
  2011-12-12 15:23   ` björn lundin
@ 2011-12-13 13:38     ` Ada BRL
  2011-12-13 13:56       ` Ludovic Brenta
  0 siblings, 1 reply; 46+ messages in thread
From: Ada BRL @ 2011-12-13 13:38 UTC (permalink / raw)


On 12 Dic, 15:23, björn lundin <b.f.lun...@gmail.com> wrote:
> On 12 Dec, 04:19, a...@att.net wrote:
>
> >   exception
> >     when Socket_Error =>
> >         if Main'Callable then
> >           Main.Dead ( 1 ) ;
> >         end if ;
> >         Close_Socket ( Socket ) ;
> >   end One ;
>
> Another small nit-picking note.
> The call to Main.Dead may still cause Tasking_Error,
> since the result of Main'Callable may have changed
> during the time between the check and the call.
> Unlikely yes, but still.
>
>      when Socket_Error =>
>          begin
>            Main.Dead ( 1 ) ;
>          exception
>            when Tasking_Error => null; -- or printout
>          end;
>          Close_Socket ( Socket ) ;
>    end One ;
>
> This way the call to Main.Dead will succeed or not,
> but Close_Socket will always be called
>
> --
> Björn Lundin

Thanks for the refinements!

Everyone was very helpful...this was the first time for me on Google
Groups and I would say it's far better than any other forum!!!



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

* Re: Interrupts handling in ADA
  2011-12-11 20:21   ` Martin Dowie
@ 2011-12-13 13:51     ` Ada BRL
  2011-12-13 23:18       ` Martin Dowie
  2011-12-13 14:11     ` Niklas Holsti
  1 sibling, 1 reply; 46+ messages in thread
From: Ada BRL @ 2011-12-13 13:51 UTC (permalink / raw)


On 11 Dic, 20:21, Martin Dowie <mar...@re.mo.ve.thedowies.com> wrote:
> Simon Wright <si...@pushface.org> wrote:
> > "Ada @ BRL" <ada.brl.2...@gmail.com> writes:
>
> >> The environment of ADA applcation is:
>
> > Ada, please!
>
> Here, here! :-)
>
> > The new Ada2012 standard includes a synchronised Queue, which would be
> > just what you want out of the box, but you won't find that in the
> > current compilers, so you'll need to roll your own.
>
> Just a thought but perhaps the OP would qualify for the GNAT Academic
> Edition? In which case, they might get access to GNAT 7.0 pre-release which
> does have the new standard queue libraries.
>
> http://www.adacore.com/home/academia/
>
> -- Martin

I've made a mistake and I have replied only to you instead of the
group.

What's the difference between synchronized queue and mailbox?
May I obtain the same result using mailbox (that I guess is a
protected object) instead of creating my own protected queue?

I've tried to qualify for an academic version of GNAT but I need the
University support.
This will be in act only if the program would be used by several
people (or even an academic taught course), and not just by me ... =)



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

* Re: Interrupts handling in ADA
  2011-12-13 13:38     ` Ada BRL
@ 2011-12-13 13:56       ` Ludovic Brenta
  2011-12-13 14:10         ` Ada BRL
  0 siblings, 1 reply; 46+ messages in thread
From: Ludovic Brenta @ 2011-12-13 13:56 UTC (permalink / raw)


Ada BRL writes on comp.lang.ada:
> Everyone was very helpful...this was the first time for me on Google
> Groups and I would say it's far better than any other forum!!!

Actually, this is Usenet.  This group has been in existence much longer
than Google; there are archives dating back to 1986.

-- 
Ludovic Brenta.



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

* Re: Interrupts handling in ADA
  2011-12-13 13:11   ` Ada BRL
@ 2011-12-13 14:04     ` Dmitry A. Kazakov
  2011-12-13 14:51       ` Ada BRL
  0 siblings, 1 reply; 46+ messages in thread
From: Dmitry A. Kazakov @ 2011-12-13 14:04 UTC (permalink / raw)


On Tue, 13 Dec 2011 05:11:14 -0800 (PST), Ada BRL wrote:

> On 11 Dic, 09:23, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>> On Sat, 10 Dec 2011 12:43:58 -0800 (PST), Ada @ BRL wrote:
>>> The environment of ADA applcation is:
>>> I have 4 tasks that execute at the same time:
>>> one is the main task,
>>> the other three execute a "read" from network (socket) function inside
>>> their bodies (on the other side there's the C/C++ application with 3
>>> network sockets).
>>> [I decided to use the sockets instead of dll/lib import because this approach hasn't worked... =( ]
>>
>> What dll import has to do with sockets, except that sockets usually are
>> provided by a library?
> 
> I would have liked to use dll import to exchange data between C stuff
> and Ada program instead of using two programs (C and Ada)
> communicating through sockets...

You can link to an import library from Ada without any problems. Which OS
are you using?

> I have a maximum of 5 sockets so I guess there will be no problems
> onto the OS side...I hope so =).

Yep.

> What's the "select" you have just mentioned?

E.g. under Windows:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141%28v=vs.85%29.aspx

> The software interrupts are implemented with entry / accept paradigm
> (like events in C++? ).

No, OS event objects and entry calls assume that the recipient is inactive
and thus is ready to accept the notification. That is a non-preemptive
model.

Software interrupts are preemptive. An interrupt breaks the execution of
the recipient. Like with exceptions there are two models of what happens
after interrupt has been serviced: continuation back from the point where
the task was interrupted vs. winding up the stack and aborting some stuff
with continuation from a definite point. AST's are usually like former,
Ada's ATC are like latter.

>> 2. "Monitor": multiple socket readers do rendezvous to the main task, which
>> accept the rendezvous.
> 
> In rendez-vous paradigm, is the main task forced to wait for ALL the
> socket tasks or only for a subset of them?

It is an asymmetric model. The subscriber does not know the publishers. It
waits for any entry call, services it, and then wait for another.

> Eg: only socket #2 has received some data, can the main task execute
> or does it have to wait also for the other sockets?

One by one, if you need something like synchronization at the checkpoint,
that would possible to implement using monitors, but it would be a bit
hairy. I would use arrays of events instead.

>> 3. "Queue": socket readers enqueue some data (the queue is implemented
>> using a protected object). Other tasks (there could be many) dequeue data
>> and do something meaningful with them. There are many kinds of queues for
>> different purposes and of different behavior.
>>
>> 4. Single rank co-workers. Each socket reader processes data by themselves.
>> In order to interlock processing there is a semaphore/mutex (implemented by
>> a protected object), which is seized when processing starts and released
>> afterwards.
> 
> In your opinion, what's the most effective and at the same time
> simplest way to sort out my problem?

Efficiency depends on the network stack you are using. In general,
protected objects could be more efficient where context switching is
expensive. This is because in some cases protected entries can be serviced
without switching tasks (threads). On the architectures with many cores,
where switching is relatively cheap and locking is relatively expensive,
tasks rendezvous might become preferable. However, if you care about
performance, you have always measure, never guess.

> Simon Wright has posted an example of Protected queue and entry /
> accept statements and it seems to be simple but effective as well.

See above, speculations about efficiency are dangerous. I would refrain
copying socket data, but if it works for you, why not?

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



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

* Re: Interrupts handling in ADA
  2011-12-11 12:04 ` Georg Bauhaus
@ 2011-12-13 14:08   ` Ada BRL
  0 siblings, 0 replies; 46+ messages in thread
From: Ada BRL @ 2011-12-13 14:08 UTC (permalink / raw)



Sorry, I replied you privately before, instead of the group.


On 11 Dic, 12:04, Georg Bauhaus <rm.dash-bauh...@futureapps.de> wrote:
> On 10.12.11 21:43, Ada @ BRL wrote:
>
> > Hello,
> > I'm an Erasmus student at the University of Bristol - UK and I'm carrying out the work for my master thesis in Computer Engineering.
>
> > I'm programming a multithreading application in C / C++ and ADA.
> > The latter is a completely new language for me...
>
> > The environment of ADA applcation is:
> > I have 4 tasks that execute at the same time:
> > one is the main task,
> > the other three execute a "read" from network (socket) function inside their bodies (on the other side there's the C/C++ application with 3 network sockets).
> > [I decided to use the sockets instead of dll/lib import because this approach hasn't worked... =( ]
>
> Just to make sure: Do you have 4 Ada tasks that should
> communicate, or do you have an Ada program and 3 programs
> or pthread style functions written in C or C++ that should
> communicate with the Ada program?

I have several tasks:

Ada side:
3 sockets communicating with C/C++ sockets plus main task,

C/C++ side:
lots of threads, 3 of these are sockets communicating with Ada
sockets.

>
> In the first case, simply look for "entry", "select", and "accept",
> These means of inter-task communications have been built into Ada
> since day 1.

As I asked in another post, what's the select statement? :-)

>
> (That'shttp://en.wikibooks.org/wiki/Ada_Programming/Tasking#Rendezvous
> on the page mentioned by Niklas Holsti. There is alsohttp://www.adaic.org/learn/materials/)
>
> Say I have two task objects A and B, and B should accept calls from other
> tasks at an entry named "Data_Available". The notification is written
> in the body the calling task, A in this case. It could look like
>
>     ...
>     B.Data_Available;  --  A notifies B
>     ...
>
> Done. That's all. If A also wishes to send data directly, then
> B would accept them simply in a parameter. Then, "Data_Available"
> would have been declared with a parameter instead of without one
> as in the case above.
> The notification, which then includes data to be sent, could look like
>
>     ...
>     B.Data_Available (Data_To_Be_Sent);
>     ...
>
> It is also possible to combine the first, simple notification (without
> data) with employing a third object, a mailbox style object, as outlined
> in other answers in this thread.  The mailbox can be a protected object
> (language defined term, roughly clever type for shared variables with mutex
> and conditional waiting), or another dedicated task object. The model
> in either case  is:
>
>     -- body of A:
>     Mailbox.Add_Data (Data_for_B);  -- make data available
>     B.Data_Available;   -- notify B of data available, as before
>     ...
>
>     -- body of B:
>     accept Data_Available;  -- be notified of data available in mailbox
>     Mailbox.Get_Data (Storage => Room_for_Data);
>        -- load from mailbox and store into a variable local to B
>
> Or you could have B wait at the mailbox until A makes data
> available in the mailbox. The tasks would not have to communicate
> directly, then.  For this to work, the Mailbox object will
> a procedure for tasks that wish to add data to the mailbox, and
> an entry for tasks that wish to get data out of the mailbox,
> "E" say. The entry is guarded by a barrier. The barrier
> will get lifted as soon as a task such as a A has supplied data
> to the box. The effect is then that a task like B, having waited
> in the queue of entry "E", will be "notified" of the presence
> of data and continues, i.e., loads data from the mailbox.
>
> - HTH Georg

Using Mailbox, is the socket task  - that has received the data and
called the accept event - blocked while the main task runs?

Eg:
Socket1.data_arrived;

Inside main task: accept data_arrived;

Is at this point Socket1 blocked or not?

Another question:

Inside the main task, do I have to specify different entries for all
the sockets like:
E.g.:
entry data_arrived_1; -- for socket #1
entry data_arrived_2; -- for socket #2
entry data_arrived_3; -- for socket #3

and then
accept data_arrived_1;
accept data_arrived_2; etc...

or I have to specify just one entry and I call it from different
socket tasks?
E.g.:
socket1.data_arrived;
socket2.data_arrived; etc...

I guess it's the second option because in the first case for example
the accept data_arrived_2 cannot be executed until data_arrived_1 is
called.

Thanks!





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

* Re: Interrupts handling in ADA
  2011-12-13 13:56       ` Ludovic Brenta
@ 2011-12-13 14:10         ` Ada BRL
  0 siblings, 0 replies; 46+ messages in thread
From: Ada BRL @ 2011-12-13 14:10 UTC (permalink / raw)


On 13 Dic, 13:56, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote:
> Ada BRL writes on comp.lang.ada:
>
> > Everyone was very helpful...this was the first time for me on Google
> > Groups and I would say it's far better than any other forum!!!
>
> Actually, this is Usenet.  This group has been in existence much longer
> than Google; there are archives dating back to 1986.
>
> --
> Ludovic Brenta.

Cool!



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

* Re: Interrupts handling in ADA
  2011-12-11 20:21   ` Martin Dowie
  2011-12-13 13:51     ` Ada BRL
@ 2011-12-13 14:11     ` Niklas Holsti
  2011-12-13 14:54       ` Simon Wright
  2011-12-13 23:18       ` Martin Dowie
  1 sibling, 2 replies; 46+ messages in thread
From: Niklas Holsti @ 2011-12-13 14:11 UTC (permalink / raw)


On 11-12-11 22:21 , Martin Dowie wrote:
> Simon Wright<simon@pushface.org>  wrote:
>> "Ada @ BRL"<ada.brl.2011@gmail.com>  writes:
>>
>>> The environment of ADA applcation is:
>>
>> Ada, please!
>
> Here, here! :-)

I believe that should be "Hear, hear!"
... if we are going to quibble about spelling ;-/

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



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

* Re: Interrupts handling in ADA
  2011-12-13 14:04     ` Dmitry A. Kazakov
@ 2011-12-13 14:51       ` Ada BRL
  2011-12-13 15:02         ` Ada BRL
  2011-12-13 15:39         ` Dmitry A. Kazakov
  0 siblings, 2 replies; 46+ messages in thread
From: Ada BRL @ 2011-12-13 14:51 UTC (permalink / raw)


On 13 Dic, 14:04, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Tue, 13 Dec 2011 05:11:14 -0800 (PST), Ada BRL wrote:
> > On 11 Dic, 09:23, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> > wrote:
> >> On Sat, 10 Dec 2011 12:43:58 -0800 (PST), Ada @ BRL wrote:
> >>> The environment of ADA applcation is:
> >>> I have 4 tasks that execute at the same time:
> >>> one is the main task,
> >>> the other three execute a "read" from network (socket) function inside
> >>> their bodies (on the other side there's the C/C++ application with 3
> >>> network sockets).
> >>> [I decided to use the sockets instead of dll/lib import because this approach hasn't worked... =( ]
>
> >> What dll import has to do with sockets, except that sockets usually are
> >> provided by a library?
>
> > I would have liked to use dll import to exchange data between C stuff
> > and Ada program instead of using two programs (C and Ada)
> > communicating through sockets...
>
> You can link to an import library from Ada without any problems. Which OS
> are you using?

Windows 7 64 bit, Home Premium SP1 ...
I have tried in many ways to import symbols but it was impossible...
I had a linker error: couldn't find exported symbols...

I've copied the dll into all the possible folder of my project.
I've even undecorated the exported symbols of my dll created by Visual
Studio 2010 but it hasn't solved the issue.
I've downloaded a dummy dll written without Visual Studio, with
exported dummy function and variable but it hasn't worked.
I've inspected the names of the exported symbols and inside the pragma
import I've used correct ones (I've tried either __my_func_name,
_my_func_name and my_fun_name)...

>
> > I have a maximum of 5 sockets so I guess there will be no problems
> > onto the OS side...I hope so =).
>
> Yep.
>
> > What's the "select" you have just mentioned?
>
> E.g. under Windows:
>
> http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141%28v=...
>
> > The software interrupts are implemented with entry / accept paradigm
> > (like events in C++? ).
>
> No, OS event objects and entry calls assume that the recipient is inactive
> and thus is ready to accept the notification. That is a non-preemptive
> model.

Does this means that the main task has to be in wait for event state
(blocked and so NOT running)?

>
> Software interrupts are preemptive. An interrupt breaks the execution of
> the recipient. Like with exceptions there are two models of what happens
> after interrupt has been serviced: continuation back from the point where
> the task was interrupted vs. winding up the stack and aborting some stuff
> with continuation from a definite point. AST's are usually like former,
> Ada's ATC are like latter.

Sorry what does ATC stand for?

continuation back from the point where
> the task was interrupted vs. winding up the stack and aborting some stuff
> with continuation from a definite point. AST's are usually like former,
> Ada's ATC are like latter.

I haven't understood well...

With entry / accept will I use AST or ATC?

if I have this piece of code inside main task body:

do stuff before;
accept event;
do stuff after;

The main thread is blocked onto "event" barrier, when socket calls
Main.event it can continue and perform "do stuff after".

Code of socket body:

do stuff before;
Main.event;
do stuff after;

Does the socket continue its execution after calling to Main.event, in
parallel with main task or will it be blocked until the main task
blocks itself again onto a barrier?

>
> >> 2. "Monitor": multiple socket readers do rendezvous to the main task, which
> >> accept the rendezvous.
>
> > In rendez-vous paradigm, is the main task forced to wait for ALL the
> > socket tasks or only for a subset of them?
>
> It is an asymmetric model. The subscriber does not know the publishers. It
> waits for any entry call, services it, and then wait for another.

Perfect!

>
> > Eg: only socket #2 has received some data, can the main task execute
> > or does it have to wait also for the other sockets?
>
> One by one, if you need something like synchronization at the checkpoint,
> that would possible to implement using monitors, but it would be a bit
> hairy. I would use arrays of events instead.

I don't want to wait the reception of messages by every socket (for
example socket 3 may not receive any data at all), I want that
everytime some data is available on a socket (could be 1,2,3 socket(s)
at the same time) the main task receives data and performs some
elaboration on it.

Please tell me if I'm not right: every task append it's event
(data_arrived event) onto the queue.
For this reason the main task enters the running state and pops all
the elements of the queue (events); after having processed all the
events it will enter the blocked state again. Am I right?

>
> >> 3. "Queue": socket readers enqueue some data (the queue is implemented
> >> using a protected object). Other tasks (there could be many) dequeue data
> >> and do something meaningful with them. There are many kinds of queues for
> >> different purposes and of different behavior.

Is it the same of using Mailbox?


>
> >> 4. Single rank co-workers. Each socket reader processes data by themselves.
> >> In order to interlock processing there is a semaphore/mutex (implemented by
> >> a protected object), which is seized when processing starts and released
> >> afterwards.
>
> > In your opinion, what's the most effective and at the same time
> > simplest way to sort out my problem?
>
> Efficiency depends on the network stack you are using. In general,
> protected objects could be more efficient where context switching is
> expensive. This is because in some cases protected entries can be serviced
> without switching tasks (threads). On the architectures with many cores,
> where switching is relatively cheap and locking is relatively expensive,
> tasks rendezvous might become preferable. However, if you care about
> performance, you have always measure, never guess.
>
> > Simon Wright has posted an example of Protected queue and entry /
> > accept statements and it seems to be simple but effective as well.
>
> See above, speculations about efficiency are dangerous. I would refrain
> copying socket data, but if it works for you, why not?

You said:
I would refrain
> copying socket data,

Roughly speaking, are you suggesting me not to copy the data from
sockets but accessing the same data through "pointers"?
Or, are you suggesting me to avoid context switching?

Thank you!

>
> --
> Regards,
> Dmitry A. Kazakovhttp://www.dmitry-kazakov.de




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

* Re: Interrupts handling in ADA
  2011-12-13 14:11     ` Niklas Holsti
@ 2011-12-13 14:54       ` Simon Wright
  2011-12-13 15:06         ` Ada BRL
  2011-12-13 23:18       ` Martin Dowie
  1 sibling, 1 reply; 46+ messages in thread
From: Simon Wright @ 2011-12-13 14:54 UTC (permalink / raw)


Niklas Holsti <niklas.holsti@tidorum.invalid> writes:

> On 11-12-11 22:21 , Martin Dowie wrote:
>> Simon Wright<simon@pushface.org>  wrote:
>>> "Ada @ BRL"<ada.brl.2011@gmail.com>  writes:
>>>
>>>> The environment of ADA applcation is:
>>>
>>> Ada, please!
>>
>> Here, here! :-)
>
> I believe that should be "Hear, hear!"
> ... if we are going to quibble about spelling ;-/

Exactly so!



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

* Re: Interrupts handling in ADA
  2011-12-13 14:51       ` Ada BRL
@ 2011-12-13 15:02         ` Ada BRL
  2011-12-13 15:39         ` Dmitry A. Kazakov
  1 sibling, 0 replies; 46+ messages in thread
From: Ada BRL @ 2011-12-13 15:02 UTC (permalink / raw)


On 13 Dic, 14:51, Ada BRL <ada.brl.2...@gmail.com> wrote:
> On 13 Dic, 14:04, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>
>
>
>
>
>
>
>
>
> > On Tue, 13 Dec 2011 05:11:14 -0800 (PST), Ada BRL wrote:
> > > On 11 Dic, 09:23, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> > > wrote:
> > >> On Sat, 10 Dec 2011 12:43:58 -0800 (PST), Ada @ BRL wrote:
> > >>> The environment of ADA applcation is:
> > >>> I have 4 tasks that execute at the same time:
> > >>> one is the main task,
> > >>> the other three execute a "read" from network (socket) function inside
> > >>> their bodies (on the other side there's the C/C++ application with 3
> > >>> network sockets).
> > >>> [I decided to use the sockets instead of dll/lib import because this approach hasn't worked... =( ]
>
> > >> What dll import has to do with sockets, except that sockets usually are
> > >> provided by a library?
>
> > > I would have liked to use dll import to exchange data between C stuff
> > > and Ada program instead of using two programs (C and Ada)
> > > communicating through sockets...
>
> > You can link to an import library from Ada without any problems. Which OS
> > are you using?
>
> Windows 7 64 bit, Home Premium SP1 ...
> I have tried in many ways to import symbols but it was impossible...
> I had a linker error: couldn't find exported symbols...
>
> I've copied the dll into all the possible folder of my project.
> I've even undecorated the exported symbols of my dll created by Visual
> Studio 2010 but it hasn't solved the issue.
> I've downloaded a dummy dll written without Visual Studio, with
> exported dummy function and variable but it hasn't worked.
> I've inspected the names of the exported symbols and inside the pragma
> import I've used correct ones (I've tried either __my_func_name,
> _my_func_name and my_fun_name)...
>
>
>
>
>
>
>
>
>
>
>
> > > I have a maximum of 5 sockets so I guess there will be no problems
> > > onto the OS side...I hope so =).
>
> > Yep.
>
> > > What's the "select" you have just mentioned?
>
> > E.g. under Windows:
>
> >http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141%28v=...
>
> > > The software interrupts are implemented with entry / accept paradigm
> > > (like events in C++? ).
>
> > No, OS event objects and entry calls assume that the recipient is inactive
> > and thus is ready to accept the notification. That is a non-preemptive
> > model.
>
> Does this means that the main task has to be in wait for event state
> (blocked and so NOT running)?
>
>
>
> > Software interrupts are preemptive. An interrupt breaks the execution of
> > the recipient. Like with exceptions there are two models of what happens
> > after interrupt has been serviced: continuation back from the point where
> > the task was interrupted vs. winding up the stack and aborting some stuff
> > with continuation from a definite point. AST's are usually like former,
> > Ada's ATC are like latter.
>
> Sorry what does ATC stand for?
>
> continuation back from the point where
>
> > the task was interrupted vs. winding up the stack and aborting some stuff
> > with continuation from a definite point. AST's are usually like former,
> > Ada's ATC are like latter.
>
> I haven't understood well...
>
> With entry / accept will I use AST or ATC?
>
> if I have this piece of code inside main task body:
>
> do stuff before;
> accept event;
> do stuff after;
>
> The main thread is blocked onto "event" barrier, when socket calls
> Main.event it can continue and perform "do stuff after".
>
> Code of socket body:
>
> do stuff before;
> Main.event;
> do stuff after;
>
> Does the socket continue its execution after calling to Main.event, in
> parallel with main task or will it be blocked until the main task
> blocks itself again onto a barrier?
>
>
>
> > >> 2. "Monitor": multiple socket readers do rendezvous to the main task, which
> > >> accept the rendezvous.
>
> > > In rendez-vous paradigm, is the main task forced to wait for ALL the
> > > socket tasks or only for a subset of them?
>
> > It is an asymmetric model. The subscriber does not know the publishers. It
> > waits for any entry call, services it, and then wait for another.
>
> Perfect!
>
>
>
> > > Eg: only socket #2 has received some data, can the main task execute
> > > or does it have to wait also for the other sockets?
>
> > One by one, if you need something like synchronization at the checkpoint,
> > that would possible to implement using monitors, but it would be a bit
> > hairy. I would use arrays of events instead.
>
> I don't want to wait the reception of messages by every socket (for
> example socket 3 may not receive any data at all), I want that
> everytime some data is available on a socket (could be 1,2,3 socket(s)
> at the same time) the main task receives data and performs some
> elaboration on it.
>
> Please tell me if I'm not right: every task append it's event
> (data_arrived event) onto the queue.
> For this reason the main task enters the running state and pops all
> the elements of the queue (events); after having processed all the
> events it will enter the blocked state again. Am I right?
>
>
>
> > >> 3. "Queue": socket readers enqueue some data (the queue is implemented
> > >> using a protected object). Other tasks (there could be many) dequeue data
> > >> and do something meaningful with them. There are many kinds of queues for
> > >> different purposes and of different behavior.
>
> Is it the same of using Mailbox?
>
>
>
>
>
>
>
>
>
>
>
> > >> 4. Single rank co-workers. Each socket reader processes data by themselves.
> > >> In order to interlock processing there is a semaphore/mutex (implemented by
> > >> a protected object), which is seized when processing starts and released
> > >> afterwards.
>
> > > In your opinion, what's the most effective and at the same time
> > > simplest way to sort out my problem?
>
> > Efficiency depends on the network stack you are using. In general,
> > protected objects could be more efficient where context switching is
> > expensive. This is because in some cases protected entries can be serviced
> > without switching tasks (threads). On the architectures with many cores,
> > where switching is relatively cheap and locking is relatively expensive,
> > tasks rendezvous might become preferable. However, if you care about
> > performance, you have always measure, never guess.
>
> > > Simon Wright has posted an example of Protected queue and entry /
> > > accept statements and it seems to be simple but effective as well.
>
> > See above, speculations about efficiency are dangerous. I would refrain
> > copying socket data, but if it works for you, why not?
>
> You said:
> I would refrain
>
> > copying socket data,
>
> Roughly speaking, are you suggesting me not to copy the data from
> sockets but accessing the same data through "pointers"?
> Or, are you suggesting me to avoid context switching?
>
> Thank you!
>
>
>
>
>
>
>
>
>
> > --
> > Regards,
> > Dmitry A. Kazakovhttp://www.dmitry-kazakov.de

I've found out what's ATC: http://jalada.co.uk/2010/02/09/asynchronous-notification-and-atc-in-ada.html

Basically it's a software interrupt...

Now I have another question:
Will my program perform ATC or AST? Sorry but I haven't it clear in my
mind...
You have told:

> > Software interrupts are preemptive:
> > An interrupt breaks the execution of
> > the recipient. Like with exceptions there are two models of what happens
> > after interrupt has been serviced: continuation back from the point where
> > the task was interrupted vs. winding up the stack and aborting some stuff
> > with continuation from a definite point. AST's are usually like former,
> > Ada's ATC are like latter.

When I use entry / accept paradigm am I implementing software
interrupts? I don't think so...I guess I'm using AST and not ATC...
I guess that I'm using sw interrupts (aka ATC?) only with select
statement.

Help... =(



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

* Re: Interrupts handling in ADA
  2011-12-13 14:54       ` Simon Wright
@ 2011-12-13 15:06         ` Ada BRL
  2011-12-13 21:49           ` Niklas Holsti
  0 siblings, 1 reply; 46+ messages in thread
From: Ada BRL @ 2011-12-13 15:06 UTC (permalink / raw)


On 13 Dic, 14:54, Simon Wright <si...@pushface.org> wrote:
> Niklas Holsti <niklas.hol...@tidorum.invalid> writes:
> > On 11-12-11 22:21 , Martin Dowie wrote:
> >> Simon Wright<si...@pushface.org>  wrote:
> >>> "Ada @ BRL"<ada.brl.2...@gmail.com>  writes:
>
> >>>> The environment of ADA applcation is:
>
> >>> Ada, please!
>
> >> Here, here! :-)
>
> > I believe that should be "Hear, hear!"
> > ... if we are going to quibble about spelling ;-/
>
> Exactly so!

Maybe you were referring to my English....I know it's not very correct
but I'm not a native speaker of English ... =) I'm trying to do my
best!



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

* Re: Interrupts handling in ADA
  2011-12-13 12:47   ` Ada BRL
@ 2011-12-13 15:07     ` Simon Wright
  2011-12-13 15:23       ` Ada BRL
  2011-12-13 15:34       ` Simon Wright
  0 siblings, 2 replies; 46+ messages in thread
From: Simon Wright @ 2011-12-13 15:07 UTC (permalink / raw)


Ada BRL <ada.brl.2011@gmail.com> writes:

> On 10 Dic, 22:27, Simon Wright <si...@pushface.org> wrote:

>> The spec might look like
>>
>>    with Ada.Containers.Vectors;
>>    package Queueing is
>>       type Message is new Integer;
>>       package Queue_Data
>>       is new Ada.Containers.Vectors (Index_Type => Natural,
>>                                      Element_Type => Message);
>>       protected Queue is
>>          procedure Put (M : Message);
>>          entry Get (M : out Message);
>>       private
>>          Buffer : Queue_Data.Vector;
>>       end Queue;
>>    end Queueing;
>>
>> and (as a hint) the body of the Get entry might start like
>>
>>       entry Get (M : out Message) when not Buffer.Is_Empty is
>>       begin

> Thank you for the reply!
>
> Please tell me if I'm wrong:
>
> - inside the main task I must use an accept statement "Get": by doing

Nitpicks: I said 'main task', but you might not need an explicit task,
because the main program runs in the context of the 'environment task'
so can make tasking calls, be blocked etc just like any other task.

Also, this isn't called an accept statement; it's an entry call. The way
a task indicates it's prepared to accept an entry call is by an accept
statement; protected objects are different. So if instead of Queue being
protected it was a task (not something I'd recommend) the corresponding
body part would have looked like

   accept Get (M : out Message) when not Buffer.Is_Empty do

> it, this means that the main task wait on this "barrier" until there
> is something inside the protected object queue; when entry Get is
> available (due to the incoming data), the main task is automatically
> notified and it executes the Get function, isnt' it? So the entry /
> accept paradigm is something like events in C?
> So the main task doesn't has to constantly poll the queue; the entry /
> accept statement do it by itself. Am I right?

That's right (no comment on the 'events in C' part, though).



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

* Re: Interrupts handling in ADA
  2011-12-13 15:07     ` Simon Wright
@ 2011-12-13 15:23       ` Ada BRL
  2011-12-13 18:14         ` Simon Wright
  2011-12-13 22:15         ` Niklas Holsti
  2011-12-13 15:34       ` Simon Wright
  1 sibling, 2 replies; 46+ messages in thread
From: Ada BRL @ 2011-12-13 15:23 UTC (permalink / raw)


On 13 Dic, 15:07, Simon Wright <si...@pushface.org> wrote:
> Ada BRL <ada.brl.2...@gmail.com> writes:
> > On 10 Dic, 22:27, Simon Wright <si...@pushface.org> wrote:
> >> The spec might look like
>
> >>    with Ada.Containers.Vectors;
> >>    package Queueing is
> >>       type Message is new Integer;
> >>       package Queue_Data
> >>       is new Ada.Containers.Vectors (Index_Type => Natural,
> >>                                      Element_Type => Message);
> >>       protected Queue is
> >>          procedure Put (M : Message);
> >>          entry Get (M : out Message);
> >>       private
> >>          Buffer : Queue_Data.Vector;
> >>       end Queue;
> >>    end Queueing;
>
> >> and (as a hint) the body of the Get entry might start like
>
> >>       entry Get (M : out Message) when not Buffer.Is_Empty is
> >>       begin
> > Thank you for the reply!
>
> > Please tell me if I'm wrong:
>
> > - inside the main task I must use an accept statement "Get": by doing
>
> Nitpicks: I said 'main task', but you might not need an explicit task,
> because the main program runs in the context of the 'environment task'
> so can make tasking calls, be blocked etc just like any other task.

Ok, it's clear, the main function it's a task itself...

>
> Also, this isn't called an accept statement; it's an entry call. The way
> a task indicates it's prepared to accept an entry call is by an accept
> statement; protected objects are different. So if instead of Queue being
> protected it was a task (not something I'd recommend) the corresponding
> body part would have looked like
>
>    accept Get (M : out Message) when not Buffer.Is_Empty do

I haven't understood you...
What does it mean "declaring a protected task"? You would not
recommend it, ok, but what does it mean?
In the example above is the Buffer (member of main) the unique
protected object or the main function itself has to be declared as
protected?

Sorry but I'm beginning to loose the thread...



>
> > it, this means that the main task wait on this "barrier" until there
> > is something inside the protected object queue; when entry Get is
> > available (due to the incoming data), the main task is automatically
> > notified and it executes the Get function, isnt' it? So the entry /
> > accept paradigm is something like events in C?
> > So the main task doesn't has to constantly poll the queue; the entry /
> > accept statement do it by itself. Am I right?
>
> That's right (no comment on the 'events in C' part, though).




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

* Re: Interrupts handling in ADA
  2011-12-13 15:07     ` Simon Wright
  2011-12-13 15:23       ` Ada BRL
@ 2011-12-13 15:34       ` Simon Wright
  2011-12-13 17:55         ` Ada BRL
  1 sibling, 1 reply; 46+ messages in thread
From: Simon Wright @ 2011-12-13 15:34 UTC (permalink / raw)


Simon Wright <simon@pushface.org> writes:

> Also, this isn't called an accept statement; it's an entry call. The way
> a task indicates it's prepared to accept an entry call is by an accept
> statement; protected objects are different. So if instead of Queue being
> protected it was a task (not something I'd recommend) the corresponding
> body part would have looked like
>
>    accept Get (M : out Message) when not Buffer.Is_Empty do

:blush: I can't believe I said that!

The relevant section of the ARM is 9.7.1, Selective Accept, and it'd
have looked like

   select
      when not Buffer.Is_Empty =>
         accept Get (M : out Message) do
            M := ...
         end Get;
      or
         accept Put ...



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

* Re: Interrupts handling in ADA
  2011-12-13 14:51       ` Ada BRL
  2011-12-13 15:02         ` Ada BRL
@ 2011-12-13 15:39         ` Dmitry A. Kazakov
  2011-12-13 18:51           ` Ada BRL
  1 sibling, 1 reply; 46+ messages in thread
From: Dmitry A. Kazakov @ 2011-12-13 15:39 UTC (permalink / raw)


On Tue, 13 Dec 2011 06:51:25 -0800 (PST), Ada BRL wrote:

> On 13 Dic, 14:04, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>> On Tue, 13 Dec 2011 05:11:14 -0800 (PST), Ada BRL wrote:
>>> On 11 Dic, 09:23, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
>>> wrote:
>>>> On Sat, 10 Dec 2011 12:43:58 -0800 (PST), Ada @ BRL wrote:
>>>>> The environment of ADA applcation is:
>>>>> I have 4 tasks that execute at the same time:
>>>>> one is the main task,
>>>>> the other three execute a "read" from network (socket) function inside
>>>>> their bodies (on the other side there's the C/C++ application with 3
>>>>> network sockets).
>>>>> [I decided to use the sockets instead of dll/lib import because this approach hasn't worked... =( ]
>>
>>>> What dll import has to do with sockets, except that sockets usually are
>>>> provided by a library?
>>
>>> I would have liked to use dll import to exchange data between C stuff
>>> and Ada program instead of using two programs (C and Ada)
>>> communicating through sockets...
>>
>> You can link to an import library from Ada without any problems. Which OS
>> are you using?
> 
> Windows 7 64 bit, Home Premium SP1 ...
> I have tried in many ways to import symbols but it was impossible...
> I had a linker error: couldn't find exported symbols...
> I've copied the dll into all the possible folder of my project.

No, you link to the import library, that is *.lib, not *.dll. It is also
possible to load dynamically using LoadLibrary etc. Both works perfectly
well and simple with GNAT.

The simplest way is to create a gpr-file for the external library and
include it into your Ada project using "with." GNAT knows what to do next.

>> No, OS event objects and entry calls assume that the recipient is inactive
>> and thus is ready to accept the notification. That is a non-preemptive
>> model.
> 
> Does this means that the main task has to be in wait for event state
> (blocked and so NOT running)?

Yes, if the main task is the subscriber.

If you look at how GUI's are built, they do exactly this: run the
messages/events/signal processing loop, which does nothing when there is no
messages/events/signals.

>> Software interrupts are preemptive. An interrupt breaks the execution of
>> the recipient. Like with exceptions there are two models of what happens
>> after interrupt has been serviced: continuation back from the point where
>> the task was interrupted vs. winding up the stack and aborting some stuff
>> with continuation from a definite point. AST's are usually like former,
>> Ada's ATC are like latter.
> 
> Sorry what does ATC stand for?

Asynchronous Transfer of Control.

>> the task was interrupted vs. winding up the stack and aborting some stuff
>> with continuation from a definite point. AST's are usually like former,
>> Ada's ATC are like latter.
> 
> I haven't understood well...
> 
> With entry / accept will I use AST or ATC?

ATC in Ada is like this (example from the language manual):

    select
        Terminal.Wait_For_Interrupt;
        Put_Line("Interrupted");
    then abort
        -- This will be abandoned upon terminal interrupt
        Put_Line("-> ");
        Get_Line(Command, Last);
        Process_Command (Command (1..Last));
    end select;

You have some piece of code executing (between abort and end select) while
waiting for some event (the entry call right after select). When event
happens, the code is aborted and you go to the part
Put_Line("Interrupted");

BUT: Just don't worry about ATC, it is not a good idea to use it, almost
always.

> if I have this piece of code inside main task body:
> 
> do stuff before;
> accept event;
> do stuff after;

A more complete picture is:

   do stuff before;
   accept event do
      do stuff upon rendezvous;
   end;
   do stuff after;

> The main thread is blocked onto "event" barrier, when socket calls
> Main.event it can continue and perform "do stuff after".
> 
> Code of socket body:
> 
> do stuff before;
> Main.event;
> do stuff after;
> 
> Does the socket continue its execution after calling to Main.event, in
> parallel with main task or will it be blocked until the main task
> blocks itself again onto a barrier?

When the socket task calls an entry of the main task, it is blocked until
the main task accepts the call. There is a queue of calls to each entry, so
multiple tasks can await there for a rendezvous. At a time only one
rendezvous is accepted and the corresponding task call is removed from the
queue. Then both tasks engage the rendezvous. Upon the rendezvous the code
"do stuff upon rendezvous" is executed. Any exceptions in this code
propagate into both tasks. When the code completes this or that way the
rendezvous ends, and both tasks continue their execution independently on
each other. I.e. concurrently executing "do stuff after." Here is a
diagram:

    Main             Socket task
      |                  |
do stuff before   do stuff before;
      |                  |
    accept             call
       \                /
      do stuff upon rendezvous (synchronously)
       /                \
do stuff after;    do stuff after
      |                  |

Consider the rendezvous code executed as if both tasks were one.

> Please tell me if I'm not right: every task append it's event
> (data_arrived event) onto the queue.

Rendezvous are better than that, because the queue contains the tasks
themselves. No data are actually copied. If you want to copy data from one
task to another, you simply pass them as a parameter of the call and make a
copy of the parameter during the rendezvous.

> For this reason the main task enters the running state and pops all
> the elements of the queue (events); after having processed all the
> events it will enter the blocked state again. Am I right?

Yes. A task can wait for multiple entries (see the select statement). If
all alternatives of the select are closed, the task is blocked. The
simplest case is just one accept. The task is blocked until nobody calls to
the entry.

>>>> 3. "Queue": socket readers enqueue some data (the queue is implemented
>>>> using a protected object). Other tasks (there could be many) dequeue data
>>>> and do something meaningful with them. There are many kinds of queues for
>>>> different purposes and of different behavior.
> 
> Is it the same of using Mailbox?

Yes, mailbox is a sort of queue. But there are queues of different flavors.
E.g. blocking, non-blocking, waitable on the ends, queues of different
policies at their ends, blackboards etc.

> Roughly speaking, are you suggesting me not to copy the data from
> sockets but accessing the same data through "pointers"?

Not necessarily pointers. I don't know why socket tasks cannot process
their data concurrently. If they need to be synchronized at certain points
why not to do just this. It is a balance which depends on the problem at
hand. In some cases monitors are preferable in other cases they are not.

> Or, are you suggesting me to avoid context switching?

That is the next step. The worst case is both to copy data and to switch
the context. This is what a queue-based solution [*] would do. The best
case is same data same context. BUT, as always, "premature optimization is
the root ..." etc. Solve the problem in the simplest way, only if the
performance is poor consider other solutions.

-----
* Which does not do processing at the context of a protected action.

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



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

* Re: Interrupts handling in ADA
  2011-12-13 15:34       ` Simon Wright
@ 2011-12-13 17:55         ` Ada BRL
  2011-12-13 18:18           ` Dmitry A. Kazakov
  2011-12-13 18:24           ` Simon Wright
  0 siblings, 2 replies; 46+ messages in thread
From: Ada BRL @ 2011-12-13 17:55 UTC (permalink / raw)


On 13 Dic, 15:34, Simon Wright <si...@pushface.org> wrote:
> Simon Wright <si...@pushface.org> writes:
> > Also, this isn't called an accept statement; it's an entry call. The way
> > a task indicates it's prepared to accept an entry call is by an accept
> > statement; protected objects are different. So if instead of Queue being
> > protected it was a task (not something I'd recommend) the corresponding
> > body part would have looked like
>
> >    accept Get (M : out Message) when not Buffer.Is_Empty do
>
> :blush: I can't believe I said that!
>
> The relevant section of the ARM is 9.7.1, Selective Accept, and it'd
> have looked like
>
>    select
>       when not Buffer.Is_Empty =>
>          accept Get (M : out Message) do
>             M := ...
>          end Get;
>       or
>          accept Put ...

Does this means that if the Buffer is empty I will accept the Put
instead of Get? So the "or" refers to the condition before "=>"



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

* Re: Interrupts handling in ADA
  2011-12-13 15:23       ` Ada BRL
@ 2011-12-13 18:14         ` Simon Wright
  2011-12-13 18:56           ` Ada BRL
  2011-12-13 19:56           ` Bill Findlay
  2011-12-13 22:15         ` Niklas Holsti
  1 sibling, 2 replies; 46+ messages in thread
From: Simon Wright @ 2011-12-13 18:14 UTC (permalink / raw)


Ada BRL <ada.brl.2011@gmail.com> writes:

> On 13 Dic, 15:07, Simon Wright <si...@pushface.org> wrote:

>> Also, this isn't called an accept statement; it's an entry call. The
>> way a task indicates it's prepared to accept an entry call is by an
>> accept statement; protected objects are different. So if instead of
>> Queue being protected it was a task (not something I'd recommend) the
>> corresponding body part would have looked like
>>
>>    accept Get (M : out Message) when not Buffer.Is_Empty do
>
> I haven't understood you...
> What does it mean "declaring a protected task"? You would not
> recommend it, ok, but what does it mean?
> In the example above is the Buffer (member of main) the unique
> protected object or the main function itself has to be declared as
> protected?
>
> Sorry but I'm beginning to loose the thread...

Not surprised, it seems to me we're giving you answers well above your
current level of knowledge of Ada. Sorry about that.

[1] is a better explanation of tasking & protected types than I can
provide quickly (maybe at all!)

[2] contains two implementations; queueing_po* are the files for a
protected object implementation, queueing_task* for a task
implementation. You will see that the structures of the two main
programs (queueing_po_main, queueing_task_main) are identical.

One of the reasons I wouldn't use a task here is that you have to manage
the active thread of the task. An example of the sort of thing I mean is
that when you run queueing_po_main it stops after 20 ines of output, but
when you run queueing_task_main it hangs at that point and you have to
stop it from the outside (by Crtl-C, for example). The reason is that
the task Queue has no reason to stop and just waits forever (in this
simple case you could probably fix that fairly simply, but in general
it's not easy at all; best to avoid the problem).

[1] http://en.wikibooks.org/wiki/Ada_Programming/Tasking (sections 1, 2)
[2] http://dl.dropbox.com/u/34783908/Ada/queueing.zip



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

* Re: Interrupts handling in ADA
  2011-12-13 17:55         ` Ada BRL
@ 2011-12-13 18:18           ` Dmitry A. Kazakov
  2011-12-13 19:01             ` Ada BRL
  2011-12-13 18:24           ` Simon Wright
  1 sibling, 1 reply; 46+ messages in thread
From: Dmitry A. Kazakov @ 2011-12-13 18:18 UTC (permalink / raw)


On Tue, 13 Dec 2011 09:55:54 -0800 (PST), Ada BRL wrote:

> On 13 Dic, 15:34, Simon Wright <si...@pushface.org> wrote:
>> Simon Wright <si...@pushface.org> writes:

>> The relevant section of the ARM is 9.7.1, Selective Accept, and it'd
>> have looked like
>>
>> � �select
>> � � � when not Buffer.Is_Empty =>
>> � � � � �accept Get (M : out Message) do
>> � � � � � � M := ...
>> � � � � �end Get;
>> � � � or
>> � � � � �accept Put ...
> 
> Does this means that if the Buffer is empty I will accept the Put
> instead of Get? So the "or" refers to the condition before "=>"

When Buffer is empty, only Put is accepted. It is said that Get is
"closed." When Get is "open" (Put is always "open") then either Put or Get
is accepted in an unspecified order (when both have queued tasks).

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



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

* Re: Interrupts handling in ADA
  2011-12-13 17:55         ` Ada BRL
  2011-12-13 18:18           ` Dmitry A. Kazakov
@ 2011-12-13 18:24           ` Simon Wright
  1 sibling, 0 replies; 46+ messages in thread
From: Simon Wright @ 2011-12-13 18:24 UTC (permalink / raw)


Ada BRL <ada.brl.2011@gmail.com> writes:

> On 13 Dic, 15:34, Simon Wright <si...@pushface.org> wrote:
>> Simon Wright <si...@pushface.org> writes:
>> > Also, this isn't called an accept statement; it's an entry call. The way
>> > a task indicates it's prepared to accept an entry call is by an accept
>> > statement; protected objects are different. So if instead of Queue being
>> > protected it was a task (not something I'd recommend) the corresponding
>> > body part would have looked like
>>
>> >    accept Get (M : out Message) when not Buffer.Is_Empty do
>>
>> :blush: I can't believe I said that!
>>
>> The relevant section of the ARM is 9.7.1, Selective Accept, and it'd
>> have looked like
>>
>>    select
>>       when not Buffer.Is_Empty =>
>>          accept Get (M : out Message) do
>>             M := ...
>>          end Get;
>>       or
>>          accept Put ...
>
> Does this means that if the Buffer is empty I will accept the Put
> instead of Get? So the "or" refers to the condition before "=>"

When the compiled code gets to 'select' it looks at the 'open select
alternatives'. If the Buffer is empty, that would be just Put; if not,
they would be Get and Put. It then (under the hood!) checks to see if
any task is waiting on any of the open select alternatives; if there are
any, it chooses one and executes the accept statement; if there are
none, it sets up a conditional event of some sort involving any of the
open select alternatives and waits.

Note that nothing will happen if Buffer.Is_Empty changes during this
wait; the select alternatives are only evaluated at the 'select'.

http://en.wikibooks.org/wiki/Ada_Programming/Tasking#Selective_Wait
http://en.wikibooks.org/wiki/Ada_Programming/Tasking#Guards 



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

* Re: Interrupts handling in ADA
  2011-12-13 15:39         ` Dmitry A. Kazakov
@ 2011-12-13 18:51           ` Ada BRL
  2011-12-13 19:51             ` Dmitry A. Kazakov
  2011-12-13 23:32             ` georg bauhaus
  0 siblings, 2 replies; 46+ messages in thread
From: Ada BRL @ 2011-12-13 18:51 UTC (permalink / raw)


On 13 Dic, 15:39, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Tue, 13 Dec 2011 06:51:25 -0800 (PST), Ada BRL wrote:
> > On 13 Dic, 14:04, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> > wrote:
> >> On Tue, 13 Dec 2011 05:11:14 -0800 (PST), Ada BRL wrote:
> >>> On 11 Dic, 09:23, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> >>> wrote:
> >>>> On Sat, 10 Dec 2011 12:43:58 -0800 (PST), Ada @ BRL wrote:
> >>>>> The environment of ADA applcation is:
> >>>>> I have 4 tasks that execute at the same time:
> >>>>> one is the main task,
> >>>>> the other three execute a "read" from network (socket) function inside
> >>>>> their bodies (on the other side there's the C/C++ application with 3
> >>>>> network sockets).
> >>>>> [I decided to use the sockets instead of dll/lib import because this approach hasn't worked... =( ]
>
> >>>> What dll import has to do with sockets, except that sockets usually are
> >>>> provided by a library?
>
> >>> I would have liked to use dll import to exchange data between C stuff
> >>> and Ada program instead of using two programs (C and Ada)
> >>> communicating through sockets...
>
> >> You can link to an import library from Ada without any problems. Which OS
> >> are you using?
>
> > Windows 7 64 bit, Home Premium SP1 ...
> > I have tried in many ways to import symbols but it was impossible...
> > I had a linker error: couldn't find exported symbols...
> > I've copied the dll into all the possible folder of my project.
>
> No, you link to the import library, that is *.lib, not *.dll. It is also
> possible to load dynamically using LoadLibrary etc. Both works perfectly
> well and simple with GNAT.

I've tried either with dll and lib but it hasn't worked...I've used
pragma Import(Convention, Entity, External_name) because I've read to
do so to link libraries into the Ada 95 programming book...
I prefer to load a static library (lib) instead of a dll (I've read
it's better for efficiency reasons); what I have to do, without pragma
Import(...)?
>
> The simplest way is to create a gpr-file for the external library and
> include it into your Ada project using "with." GNAT knows what to do next.

How can I create a gpr file for the external library?
What I have to code inside? I suppose it will be a .ads file that I'll
link to the other ads and adb files.
[Ok, it's clear the use of "with" and "use"]

>
> >> No, OS event objects and entry calls assume that the recipient is inactive
> >> and thus is ready to accept the notification. That is a non-preemptive
> >> model.
>
> > Does this means that the main task has to be in wait for event state
> > (blocked and so NOT running)?
>
> Yes, if the main task is the subscriber.

If subscriber means the task that has defined inside its declaration
"entry data_available", and inside its body "accept data_available"
it's clear.

>
> If you look at how GUI's are built, they do exactly this: run the
> messages/events/signal processing loop, which does nothing when there is no
> messages/events/signals.
>
> >> Software interrupts are preemptive. An interrupt breaks the execution of
> >> the recipient. Like with exceptions there are two models of what happens
> >> after interrupt has been serviced: continuation back from the point where
> >> the task was interrupted vs. winding up the stack and aborting some stuff
> >> with continuation from a definite point. AST's are usually like former,
> >> Ada's ATC are like latter.
>
> > Sorry what does ATC stand for?
>
> Asynchronous Transfer of Control.
>
> >> the task was interrupted vs. winding up the stack and aborting some stuff
> >> with continuation from a definite point. AST's are usually like former,
> >> Ada's ATC are like latter.
>
> > I haven't understood well...
>
> > With entry / accept will I use AST or ATC?
>
> ATC in Ada is like this (example from the language manual):
>
>     select
>         Terminal.Wait_For_Interrupt;
>         Put_Line("Interrupted");
>     then abort
>         -- This will be abandoned upon terminal interrupt
>         Put_Line("-> ");
>         Get_Line(Command, Last);
>         Process_Command (Command (1..Last));
>     end select;
>
> You have some piece of code executing (between abort and end select) while
> waiting for some event (the entry call right after select). When event
> happens, the code is aborted and you go to the part
> Put_Line("Interrupted");
>
> BUT: Just don't worry about ATC, it is not a good idea to use it, almost
> always.

Ok, but I've understood how it works =) thanks!
The thing is that the "then abort" statement is not very evocative and
it has lead me to a misunderstanding...

The high level strucure roughly is:

while (!event){

 do stuff

}

exit program

but in addition with "select" structure I guess you can exit from the
while at any time, just after the event occurs (asynchronous
behaviour).
It's like to check, before executing every atomic action, if the event
is active or not. If it's so exit from the while.


>
> > if I have this piece of code inside main task body:
>
> > do stuff before;
> > accept event;
> > do stuff after;
>
> A more complete picture is:
>
>    do stuff before;
>    accept event do
>       do stuff upon rendezvous;
>    end;
>    do stuff after;

Yes, you are definitely right =)

>
> > The main thread is blocked onto "event" barrier, when socket calls
> > Main.event it can continue and perform "do stuff after".
>
> > Code of socket body:
>
> > do stuff before;
> > Main.event;
> > do stuff after;
>
> > Does the socket continue its execution after calling to Main.event, in
> > parallel with main task or will it be blocked until the main task
> > blocks itself again onto a barrier?
>
> When the socket task calls an entry of the main task, it is blocked until
> the main task accepts the call.

This could be a problem...read at the bottom of this post...

> There is a queue of calls to each entry, so
> multiple tasks can await there for a rendezvous. At a time only one
> rendezvous is accepted and the corresponding task call is removed from the
> queue.

Does this means that it can be resumed and continue its execution or
does it must wait until all the calls to the entry are removed?

Eg:

Queue of entry calls:

123

After the "pop" of the first event, can the fist socket continue its
execution or does it have to wait until the queue is empty?

In my program I can have for example this situation of the event
queue:

1121321

Is it possible to deal with it using rendez vous / accept - entry?

See bottom for more details.

> Then both tasks engage the rendezvous. Upon the rendezvous the code
> "do stuff upon rendezvous" is executed. Any exceptions in this code
> propagate into both tasks. When the code completes this or that way the
> rendezvous ends, and both tasks continue their execution independently on
> each other. I.e. concurrently executing "do stuff after." Here is a
> diagram:
>
>     Main             Socket task
>       |                  |
> do stuff before   do stuff before;
>       |                  |
>     accept             call
>        \                /
>       do stuff upon rendezvous (synchronously)
>        /                \
> do stuff after;    do stuff after
>       |                  |
>
> Consider the rendezvous code executed as if both tasks were one.

OK! So in this phase do they share objects?
May you plase make a very simple code example?

>
> > Please tell me if I'm not right: every task append it's event
> > (data_arrived event) onto the queue.
>
> Rendezvous are better than that, because the queue contains the tasks
> themselves. No data are actually copied. If you want to copy data from one
> task to another, you simply pass them as a parameter of the call and make a
> copy of the parameter during the rendezvous.
>
> > For this reason the main task enters the running state and pops all
> > the elements of the queue (events); after having processed all the
> > events it will enter the blocked state again. Am I right?
>
> Yes. A task can wait for multiple entries (see the select statement). If
> all alternatives of the select are closed, the task is blocked. The
> simplest case is just one accept. The task is blocked until nobody calls to
> the entry.
>
> >>>> 3. "Queue": socket readers enqueue some data (the queue is implemented
> >>>> using a protected object). Other tasks (there could be many) dequeue data
> >>>> and do something meaningful with them. There are many kinds of queues for
> >>>> different purposes and of different behavior.
>
> > Is it the same of using Mailbox?
>
> Yes, mailbox is a sort of queue. But there are queues of different flavors.
> E.g. blocking, non-blocking, waitable on the ends, queues of different
> policies at their ends, blackboards etc.
>
> > Roughly speaking, are you suggesting me not to copy the data from
> > sockets but accessing the same data through "pointers"?
>
> Not necessarily pointers. I don't know why socket tasks cannot process
> their data concurrently. If they need to be synchronized at certain points
> why not to do just this. It is a balance which depends on the problem at
> hand. In some cases monitors are preferable in other cases they are not.
>
> > Or, are you suggesting me to avoid context switching?
>
> That is the next step. The worst case is both to copy data and to switch
> the context. This is what a queue-based solution [*] would do. The best
> case is same data same context. BUT, as always, "premature optimization is
> the root ..." etc. Solve the problem in the simplest way, only if the
> performance is poor consider other solutions.

I think it's better to explain the environment:

The socket tasks are not synchronized each other,
they don't have to wait for the completion of another,
they are completely disjoint,
they just have to:
- notify the main task that data is arrived,
- let data be available to the main task in order be elaborated,
- don't be blocked at any time (even when main task is executing)
because they are receiving data from other sockets, so they must be
able to read data from the network at any time.

The main task has to:
- wait until some data (from any of the sockets) is available, so wait
for the event generated by the sockets,
- don't miss any "incoming new data" event generated by the sockets
(must append all the new data events into a queue...)
- process the data until the queue of events is empty,
- come back to "wait event" state.

I hope to have been clearer and to have you helped to better
understand my problem :-)!

The sockets have an input buffer for data from the network and for
every message coming from the network they have to generate a
"data_available" event.
The elaboration of the data must be done inside the main task, the
sockets are just a way to connect two programs.

Thank you very much for your help!

>
> -----
> * Which does not do processing at the context of a protected action.
>
> --
> Regards,
> Dmitry A. Kazakovhttp://www.dmitry-kazakov.de




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

* Re: Interrupts handling in ADA
  2011-12-13 18:14         ` Simon Wright
@ 2011-12-13 18:56           ` Ada BRL
  2011-12-13 19:56           ` Bill Findlay
  1 sibling, 0 replies; 46+ messages in thread
From: Ada BRL @ 2011-12-13 18:56 UTC (permalink / raw)


On 13 Dic, 18:14, Simon Wright <si...@pushface.org> wrote:
> Ada BRL <ada.brl.2...@gmail.com> writes:
> > On 13 Dic, 15:07, Simon Wright <si...@pushface.org> wrote:
> >> Also, this isn't called an accept statement; it's an entry call. The
> >> way a task indicates it's prepared to accept an entry call is by an
> >> accept statement; protected objects are different. So if instead of
> >> Queue being protected it was a task (not something I'd recommend) the
> >> corresponding body part would have looked like
>
> >>    accept Get (M : out Message) when not Buffer.Is_Empty do
>
> > I haven't understood you...
> > What does it mean "declaring a protected task"? You would not
> > recommend it, ok, but what does it mean?
> > In the example above is the Buffer (member of main) the unique
> > protected object or the main function itself has to be declared as
> > protected?
>
> > Sorry but I'm beginning to loose the thread...
>
> Not surprised, it seems to me we're giving you answers well above your
> current level of knowledge of Ada. Sorry about that.
>
> [1] is a better explanation of tasking & protected types than I can
> provide quickly (maybe at all!)
>
> [2] contains two implementations; queueing_po* are the files for a
> protected object implementation, queueing_task* for a task
> implementation. You will see that the structures of the two main
> programs (queueing_po_main, queueing_task_main) are identical.
>
> One of the reasons I wouldn't use a task here is that you have to manage
> the active thread of the task. An example of the sort of thing I mean is
> that when you run queueing_po_main it stops after 20 ines of output, but
> when you run queueing_task_main it hangs at that point and you have to
> stop it from the outside (by Crtl-C, for example). The reason is that
> the task Queue has no reason to stop and just waits forever (in this
> simple case you could probably fix that fairly simply, but in general
> it's not easy at all; best to avoid the problem).
>
> [1]http://en.wikibooks.org/wiki/Ada_Programming/Tasking(sections 1, 2)
> [2]http://dl.dropbox.com/u/34783908/Ada/queueing.zip

Yes, I have never worked with Ada...but it's good for me to have
people explaining real world programs instead of dummy ones... :-), it
makes me learning more!
I have to read carefully the wikibook about Ada, this will be useful!



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

* Re: Interrupts handling in ADA
  2011-12-13 18:18           ` Dmitry A. Kazakov
@ 2011-12-13 19:01             ` Ada BRL
  2011-12-13 19:58               ` Dmitry A. Kazakov
  0 siblings, 1 reply; 46+ messages in thread
From: Ada BRL @ 2011-12-13 19:01 UTC (permalink / raw)


On 13 Dic, 18:18, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
wrote:
> On Tue, 13 Dec 2011 09:55:54 -0800 (PST), Ada BRL wrote:
> > On 13 Dic, 15:34, Simon Wright <si...@pushface.org> wrote:
> >> Simon Wright <si...@pushface.org> writes:
> >> The relevant section of the ARM is 9.7.1, Selective Accept, and it'd
> >> have looked like
>
> >>    select
> >>       when not Buffer.Is_Empty =>
> >>          accept Get (M : out Message) do
> >>             M := ...
> >>          end Get;
> >>       or
> >>          accept Put ...
>
> > Does this means that if the Buffer is empty I will accept the Put
> > instead of Get? So the "or" refers to the condition before "=>"
>
> When Buffer is empty, only Put is accepted. It is said that Get is
> "closed." When Get is "open" (Put is always "open") then either Put or Get
> is accepted in an unspecified order (when both have queued tasks).
>
> --
> Regards,
> Dmitry A. Kazakovhttp://www.dmitry-kazakov.de

So, when buffer is NOT empty I will execute Get AND Put if both have
queued tasks (I cannot know a-priori the order of execution) or Get OR
Put if only one of the two has queued tasks.



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

* Re: Interrupts handling in ADA
  2011-12-13 18:51           ` Ada BRL
@ 2011-12-13 19:51             ` Dmitry A. Kazakov
  2011-12-13 23:32             ` georg bauhaus
  1 sibling, 0 replies; 46+ messages in thread
From: Dmitry A. Kazakov @ 2011-12-13 19:51 UTC (permalink / raw)


On Tue, 13 Dec 2011 10:51:03 -0800 (PST), Ada BRL wrote:

> On 13 Dic, 15:39, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
> wrote:
>> On Tue, 13 Dec 2011 06:51:25 -0800 (PST), Ada BRL wrote:
>>> On 13 Dic, 14:04, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
>>> wrote:
>>>> On Tue, 13 Dec 2011 05:11:14 -0800 (PST), Ada BRL wrote:
>>>>> On 11 Dic, 09:23, "Dmitry A. Kazakov" <mail...@dmitry-kazakov.de>
>>>>> wrote:
>>>>>> On Sat, 10 Dec 2011 12:43:58 -0800 (PST), Ada @ BRL wrote:
>>>>>>> The environment of ADA applcation is:
>>>>>>> I have 4 tasks that execute at the same time:
>>>>>>> one is the main task,
>>>>>>> the other three execute a "read" from network (socket) function inside
>>>>>>> their bodies (on the other side there's the C/C++ application with 3
>>>>>>> network sockets).
>>>>>>> [I decided to use the sockets instead of dll/lib import because this approach hasn't worked... =( ]
>>
>>>>>> What dll import has to do with sockets, except that sockets usually are
>>>>>> provided by a library?
>>
>>>>> I would have liked to use dll import to exchange data between C stuff
>>>>> and Ada program instead of using two programs (C and Ada)
>>>>> communicating through sockets...
>>
>>>> You can link to an import library from Ada without any problems. Which OS
>>>> are you using?
>>
>>> Windows 7 64 bit, Home Premium SP1 ...
>>> I have tried in many ways to import symbols but it was impossible...
>>> I had a linker error: couldn't find exported symbols...
>>> I've copied the dll into all the possible folder of my project.
>>
>> No, you link to the import library, that is *.lib, not *.dll. It is also
>> possible to load dynamically using LoadLibrary etc. Both works perfectly
>> well and simple with GNAT.
> 
> I've tried either with dll and lib but it hasn't worked...I've used
> pragma Import(Convention, Entity, External_name) because I've read to
> do so to link libraries into the Ada 95 programming book...

That is correct:

   pragma Import (C, Ada-Name, External-Name");

> I prefer to load a static library (lib) instead of a dll (I've read
> it's better for efficiency reasons); what I have to do, without pragma
> Import(...)?

The pragma must stay. You must add instruction to the linker to use your
import library.  You can describe your library as a project and make your
project dependent on it. Or you can add/modify the linker section of your
project:

   package Linker is
      for Linker_Options use ("-luser32");
         -- Link to the Windows' user32 library
   end Linker;

You can also build everything without any project files using raw gnatmake:

   gnatmake your-file.adb -largs -luser32

>> The simplest way is to create a gpr-file for the external library and
>> include it into your Ada project using "with." GNAT knows what to do next.
> 
> How can I create a gpr file for the external library?

notepad.exe? (:-))

project My_Library is
   for Externally_Built use "true";
   for Source_Files use ();
   for Library_Dir use "<path-to-my-library>";
   for Library_Name use "<my-library-name>";
   for Library_Kind use "dynamic";
end My_Library;

> What I have to code inside?

Nothing, as the library already exists.

> I suppose it will be a .ads file that I'll
> link to the other ads and adb files.
> [Ok, it's clear the use of "with" and "use"]

In the gpr file of your Ada program you write:

   with "my_library"; -- Use my_library defined above

   project My_Wonderful_Ada_Project is
      ...
 
>>>> No, OS event objects and entry calls assume that the recipient is inactive
>>>> and thus is ready to accept the notification. That is a non-preemptive
>>>> model.
>>
>>> Does this means that the main task has to be in wait for event state
>>> (blocked and so NOT running)?
>>
>> Yes, if the main task is the subscriber.
> 
> If subscriber means the task that has defined inside its declaration
> "entry data_available", and inside its body "accept data_available"
> it's clear.

Subscriber is the recipient of data/messages/notifications. In the
rendezvous model it is the task accepting calls, the callee. Publisher is
the caller.

> The high level strucure roughly is:
> 
> while (!event){
> 
>  do stuff
> 
> }
> 
> exit program
> 
> but in addition with "select" structure I guess you can exit from the
> while at any time, just after the event occurs (asynchronous
> behaviour).

Almost at any time. The language defines so-called "abort-deferred" things,
which cannot be jumped out. E.g. assignment, object
initialization/finalization.

> It's like to check, before executing every atomic action, if the event
> is active or not. If it's so exit from the while.

Yes, abort-deferred actions are "atomic" to abort.

>> There is a queue of calls to each entry, so
>> multiple tasks can await there for a rendezvous. At a time only one
>> rendezvous is accepted and the corresponding task call is removed from the
>> queue.
> 
> Does this means that it can be resumed and continue its execution or
> does it must wait until all the calls to the entry are removed?
> 
> Eg:
> 
> Queue of entry calls:
> 
> 123
> 
> After the "pop" of the first event, can the fist socket continue its
> execution or does it have to wait until the queue is empty?

It continues once serviced.

> In my program I can have for example this situation of the event
> queue:
> 
> 1121321

No, you cannot have this, because a task can wait in exactly one queue. So
the task 1 cannot queue itself 4 times as above.

A call to an entry point is no different from the caller's view as a call
to a subprogram. Anything below is executed after return (serviced
rendezvous).

It is important to understand that rendezvous is a synchronous call. It
does not marshal data. The caller itself is queued. This is why rendezvous
are so efficient. If you want asynchronous calls, you need a queue for the
messages, then the callee could be released as soon it posts the message.
This model is far less effective and is exposed to the problems like
flooding the queue with too many messages. Which in turn causes publisher
blocked when the queue is full, while subscriber keeps on chewing outdated
messages. If messages are not so important, e.g. could be dropped when
cannot be serviced, you can use a blackboard queue instead. The blackboard
is a queue which never blocks publishers at the cost of losing some old
messages by lazy subscribers.

>> Then both tasks engage the rendezvous. Upon the rendezvous the code
>> "do stuff upon rendezvous" is executed. Any exceptions in this code
>> propagate into both tasks. When the code completes this or that way the
>> rendezvous ends, and both tasks continue their execution independently on
>> each other. I.e. concurrently executing "do stuff after." Here is a
>> diagram:
>>
>> � � Main � � � � � � Socket task
>> � � � | � � � � � � � � �|
>> do stuff before � do stuff before;
>> � � � | � � � � � � � � �|
>> � � accept � � � � � � call
>> � � � �\ � � � � � � � �/
>> � � � do stuff upon rendezvous (synchronously)
>> � � � �/ � � � � � � � �\
>> do stuff after; � �do stuff after
>> � � � | � � � � � � � � �|
>>
>> Consider the rendezvous code executed as if both tasks were one.
> 
> OK! So in this phase do they share objects?

They share parameters of the entry call.

> May you plase make a very simple code example?

   task Printer is
      entry Print (Line : String);
   end Printer;

   task body Printer is
   begin
       loop
         select
            accept Print (Line : String) do
               Put_Line (File, Line);
            end Print;
         or terminate; -- accept task completion request
      end loop;
   end Printer;

   -- A caller may pass some string expression to the printer:

   for Count in 1..3_000 loop
      My_Printer.Print ("Say" & Integer'Image (Count));
   end loop;

This is no problem, because calling to Print blocks the caller and thus
keeps all temporary objects alive until the rendezvous gets accepted and
serviced. After that the objects can be destroyed, exactly like when you
call a subprogram. It is a very efficient and safe mechanism comparing to
the methods used in the languages having no concurrency support.

> I think it's better to explain the environment:
> 
> The socket tasks are not synchronized each other,
> they don't have to wait for the completion of another,
> they are completely disjoint,
> they just have to:
> - notify the main task that data is arrived,
> - let data be available to the main task in order be elaborated,
> - don't be blocked at any time (even when main task is executing)
> because they are receiving data from other sockets, so they must be
> able to read data from the network at any time.

You cannot read data faster than you process them. If this precondition is
satisfied, you need not to worry about delayed socket reads. The OS's
network stack buffers data, so does the network adapter.

There could be issues with reading raw Ethernet frames. But they are solved
differently because it is normally impossible to catch such packets however
quickly your socket task might take the packet and toss it further. If that
is your case, you should use overlapped I/O (under Windows) and keep on
multiple read requests (3-5) queued to the driver at any time. 

The bottom line, don't worry about doing more stuff in a socket task.
 
> The main task has to:
> - wait until some data (from any of the sockets) is available, so wait
> for the event generated by the sockets,
> - don't miss any "incoming new data" event generated by the sockets
> (must append all the new data events into a queue...)
> - process the data until the queue of events is empty,
> - come back to "wait event" state.

This does not explain why packet processing should be routed to the main
task. Or putting it otherwise, why processing of incoming packets must be
serialized?

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



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

* Re: Interrupts handling in ADA
  2011-12-13 18:14         ` Simon Wright
  2011-12-13 18:56           ` Ada BRL
@ 2011-12-13 19:56           ` Bill Findlay
  1 sibling, 0 replies; 46+ messages in thread
From: Bill Findlay @ 2011-12-13 19:56 UTC (permalink / raw)


On 13/12/2011 18:14, in article m27h209w5c.fsf@pushface.org, "Simon Wright"
<simon@pushface.org> wrote:
 
> [1] is a better explanation of tasking & protected types than I can
> provide quickly (maybe at all!)

Why thank you, kind sir.

I've corrected the first paragraph, which had had an egregious untruth
inserted into it by an /anonymous/ hand. I entertain certain suspicions.

> 
> [1] http://en.wikibooks.org/wiki/Ada_Programming/Tasking (sections 1, 2)
> [2] http://dl.dropbox.com/u/34783908/Ada/queueing.zip

-- 
Bill Findlay
with blueyonder.co.uk;
use  surname & forename;





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

* Re: Interrupts handling in ADA
  2011-12-13 19:01             ` Ada BRL
@ 2011-12-13 19:58               ` Dmitry A. Kazakov
  0 siblings, 0 replies; 46+ messages in thread
From: Dmitry A. Kazakov @ 2011-12-13 19:58 UTC (permalink / raw)


On Tue, 13 Dec 2011 11:01:00 -0800 (PST), Ada BRL wrote:

> So, when buffer is NOT empty I will execute Get AND Put if both have
> queued tasks (I cannot know a-priori the order of execution) or Get OR
> Put if only one of the two has queued tasks.

You always execute Get or Put. Select accepts only one alternative. If more
than one alternatives are open and have tasks awaiting, select chooses one
of them, just one.

Normally select is placed in an enclosing loop:

   loop
      select
         accept This;
      or
         accept That;
      or
         terminate;
      end select;
   end loop;

Once an alternative is selected and serviced the loop reiterates the select
statement and the next alternative is selected.

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



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

* Re: Interrupts handling in ADA
  2011-12-13 15:06         ` Ada BRL
@ 2011-12-13 21:49           ` Niklas Holsti
  0 siblings, 0 replies; 46+ messages in thread
From: Niklas Holsti @ 2011-12-13 21:49 UTC (permalink / raw)


On 11-12-13 17:06 , Ada BRL wrote:
> On 13 Dic, 14:54, Simon Wright<si...@pushface.org>  wrote:
>> Niklas Holsti<niklas.hol...@tidorum.invalid>  writes:
>>> On 11-12-11 22:21 , Martin Dowie wrote:
>>>> Simon Wright<si...@pushface.org>    wrote:
>>>>> "Ada @ BRL"<ada.brl.2...@gmail.com>    writes:
>>
>>>>>> The environment of ADA applcation is:
>>
>>>>> Ada, please!
>>
>>>> Here, here! :-)
>>
>>> I believe that should be "Hear, hear!"
>>> ... if we are going to quibble about spelling ;-/
>>
>> Exactly so!
>
> Maybe you were referring to my English....I know it's not very correct
> but I'm not a native speaker of English ... =) I'm trying to do my
> best!

You are doing OK, don't worry. We Ada-fans just have a compulsion to 
make everyone spell the name of the language correctly. The wrong 
spelling, with all capitals, is common among non-experts, and it is no 
great sin for a new Ada user to use it -- once :-)

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



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

* Re: Interrupts handling in ADA
  2011-12-13 15:23       ` Ada BRL
  2011-12-13 18:14         ` Simon Wright
@ 2011-12-13 22:15         ` Niklas Holsti
  1 sibling, 0 replies; 46+ messages in thread
From: Niklas Holsti @ 2011-12-13 22:15 UTC (permalink / raw)


On 11-12-13 17:23 , Ada BRL wrote:

> Sorry but I'm beginning to loose the thread...

No wonder, the discussion has spread out a bit. Basically Ada has two 
ways to pass data from one task to another, with synchronization: 
"rendezvous", in which two tasks interact directly with each other, and 
"protected objects", in which some tasks puts data into a buffer or 
queue (the protected object), and other tasks take data out. Both ways 
use some of the same terminology ("entry", "entry call") for things that 
are similar but not exactly the same. The discussion has tried to cover 
both ways, which perhaps explains the confusion.

Since you seem familiar with socket communication, perhaps it would be 
easier for you to use a single-threaded Ada program, where the single 
thread reads all the sockets. In that case, the Ada side would call the 
Windows "select" function, 
http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141%28v=vs.85%29.aspx, 
to wait for some data to arrive on some socket. When the "select" call 
returns, it indicates which socket or sockets have data available, so 
the Ada program can read and process that data, and then call "select" 
again to wait for the next data.

I think that Dmitry also mentioned this solution in an earlier answer.

Note that the "select" function is not the same as the Ada "select 
statement", but they have a common goal: to wait for events or data from 
several possible sources, without knowing which source will be first to 
deliver.

Perhaps the socket library that you are using in your Ada code already 
has an Ada binding to the "select" function.

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



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

* Re: Interrupts handling in ADA
  2011-12-13 14:11     ` Niklas Holsti
  2011-12-13 14:54       ` Simon Wright
@ 2011-12-13 23:18       ` Martin Dowie
  1 sibling, 0 replies; 46+ messages in thread
From: Martin Dowie @ 2011-12-13 23:18 UTC (permalink / raw)


Niklas Holsti <niklas.holsti@tidorum.invalid> wrote:
> On 11-12-11 22:21 , Martin Dowie wrote:
>> Simon Wright<simon@pushface.org>  wrote:
>>> "Ada @ BRL"<ada.brl.2011@gmail.com>  writes:
>>> 
>>>> The environment of ADA applcation is:
>>> 
>>> Ada, please!
>> 
>> Here, here! :-)
> 
> I believe that should be "Hear, hear!"
> ... if we are going to quibble about spelling ;-/

Whoops...my bad! :-)

-- Martin
-- 
-- Sent from my iPad



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

* Re: Interrupts handling in ADA
  2011-12-13 13:51     ` Ada BRL
@ 2011-12-13 23:18       ` Martin Dowie
  0 siblings, 0 replies; 46+ messages in thread
From: Martin Dowie @ 2011-12-13 23:18 UTC (permalink / raw)


Ada BRL <ada.brl.2011@gmail.com> wrote:
> On 11 Dic, 20:21, Martin Dowie <mar...@re.mo.ve.thedowies.com> wrote:
>> Simon Wright <si...@pushface.org> wrote:
>>> "Ada @ BRL" <ada.brl.2...@gmail.com> writes:
>> 
>>>> The environment of ADA applcation is:
>> 
>>> Ada, please!
>> 
>> Here, here! :-)
>> 
>>> The new Ada2012 standard includes a synchronised Queue, which would be
>>> just what you want out of the box, but you won't find that in the
>>> current compilers, so you'll need to roll your own.
>> 
>> Just a thought but perhaps the OP would qualify for the GNAT Academic
>> Edition? In which case, they might get access to GNAT 7.0 pre-release which
>> does have the new standard queue libraries.
>> 
>> http://www.adacore.com/home/academia/
>> 
>> -- Martin
> 
> I've made a mistake and I have replied only to you instead of the
> group.
> 
> What's the difference between synchronized queue and mailbox?
> May I obtain the same result using mailbox (that I guess is a
> protected object) instead of creating my own protected queue?

Possibly "not a lot" - but an out-the-box solution is a simpler solution,
if rarely a more (CPU) efficient solution.

> I've tried to qualify for an academic version of GNAT but I need the
> University support.
> This will be in act only if the program would be used by several
> people (or even an academic taught course), and not just by me ... =)

Best of luck with that. I think it would be worth it to get the support
AdaCore can offer as well as the latest gnat.

-- Martin
-- 
-- Sent from my iPad



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

* Re: Interrupts handling in ADA
  2011-12-13 18:51           ` Ada BRL
  2011-12-13 19:51             ` Dmitry A. Kazakov
@ 2011-12-13 23:32             ` georg bauhaus
  1 sibling, 0 replies; 46+ messages in thread
From: georg bauhaus @ 2011-12-13 23:32 UTC (permalink / raw)


Ada BRL <ada.brl.2011@gmail.com> wrote:

> I've tried either with dll and lib but it hasn't worked...I've used
> pragma Import(Convention, Entity, External_name) because I've read to
> do so to link libraries into the Ada 95 programming book...
> I prefer to load a static library (lib) instead of a dll (I've read
> it's better for efficiency reasons); what I have to do, without pragma
> Import(...)?
>> 
>> The simplest way is to create a gpr-file for the external library and
>> include it into your Ada project using "with." GNAT knows what to do next.
> 
> How can I create a gpr file for the external library?
> What I have to code inside? I suppose it will be a .ads file that I'll
> link to the other ads and adb files.

Two notes about issues that are
different, really,linking and rendezvous.

1. Your GNAT installation includes a
User's guide. There is a section on
how to use DLLs, or, more generally,
parts of programs not written in Ada.
If you still want to try, it will explain
how to find link names in a Windows(TM)
environment.

2. Some imagery for rendezvous. Task
Client goes shopping, needing bread
and meat. So Client enters the queue
at the baker's or enters the queue at the
butcher's, but cannot enter both queues
at the same time.

Many clients may want bread. All of
them are at the baker's. This is why
there are queues. Staff will usually
serve clients one by one, in order of
arrival. Notice that while a client is
waiting at the baker's, he or she is
not at the same time waiting at the
butcher's.

Both the baker and the butcher may
have more than one queue and,
correspondingly, more entries: they
may meet persons other than customers.
For example, they may need to accept
delivery of an extra supply of flour, or
accept the newly sharpened knives,
usually at the back entrance.
Sales staff may also accept delivery
of daily mail. They will selectively 
accept orders or letters.



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

end of thread, other threads:[~2011-12-13 23:32 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-12-10 20:43 Interrupts handling in ADA Ada @ BRL
2011-12-10 21:13 ` Vinzent Hoefler
2011-12-10 22:09 ` Niklas Holsti
2011-12-10 22:27 ` Simon Wright
2011-12-11 20:21   ` Martin Dowie
2011-12-13 13:51     ` Ada BRL
2011-12-13 23:18       ` Martin Dowie
2011-12-13 14:11     ` Niklas Holsti
2011-12-13 14:54       ` Simon Wright
2011-12-13 15:06         ` Ada BRL
2011-12-13 21:49           ` Niklas Holsti
2011-12-13 23:18       ` Martin Dowie
2011-12-13 12:47   ` Ada BRL
2011-12-13 15:07     ` Simon Wright
2011-12-13 15:23       ` Ada BRL
2011-12-13 18:14         ` Simon Wright
2011-12-13 18:56           ` Ada BRL
2011-12-13 19:56           ` Bill Findlay
2011-12-13 22:15         ` Niklas Holsti
2011-12-13 15:34       ` Simon Wright
2011-12-13 17:55         ` Ada BRL
2011-12-13 18:18           ` Dmitry A. Kazakov
2011-12-13 19:01             ` Ada BRL
2011-12-13 19:58               ` Dmitry A. Kazakov
2011-12-13 18:24           ` Simon Wright
2011-12-11  0:15 ` Jeffrey Carter
2011-12-13 12:53   ` Ada BRL
2011-12-11  9:23 ` Dmitry A. Kazakov
2011-12-13 13:11   ` Ada BRL
2011-12-13 14:04     ` Dmitry A. Kazakov
2011-12-13 14:51       ` Ada BRL
2011-12-13 15:02         ` Ada BRL
2011-12-13 15:39         ` Dmitry A. Kazakov
2011-12-13 18:51           ` Ada BRL
2011-12-13 19:51             ` Dmitry A. Kazakov
2011-12-13 23:32             ` georg bauhaus
2011-12-11 12:04 ` Georg Bauhaus
2011-12-13 14:08   ` Ada BRL
2011-12-12  3:19 ` anon
2011-12-12  9:12   ` Niklas Holsti
2011-12-13 13:36     ` Ada BRL
2011-12-12 15:23   ` björn lundin
2011-12-13 13:38     ` Ada BRL
2011-12-13 13:56       ` Ludovic Brenta
2011-12-13 14:10         ` Ada BRL
2011-12-13 13:31   ` Ada BRL

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