Re: Running a background task



Bender wrote:
Hi, I'm pretty new to Ada, and need to figure out a way to kick off a
background task that runs more or less forever, while normal execution
of the program continues.

Thus far I've figured out how to create a task and start it, but the
procedure calling it requires the task to finish before continuing
on. I'm sure I just must be using the wrong mechanisms, but I can't
really figure out the answer.

Task definition
---------------------
(spec)
task type Poll_For_Status is
entry On_String (String : in SideAB)

1. You're missing the terminator semicolon.
2. It's generally not a good idea to reuse the identifier "String", since it hides the predefined type String, which will cause confusing error msgs if you ever try to use that type.

end Poll_For_Status;

type Task_Access is access Poll_For_Status;
Status_Task : Task_Access;

You have no need for the access type. You can simply say

Status_Task : Poll_For_Status;

Status_Task won't do anything, since it waits for a call to On_String.

You can simplify this even more by saying

task Status_Task is
entry On_String (...);
end Status_Task;

This assumes that Status_Task is the only instance of Poll_For_Status.


(body)
task body Poll_For_Status is
begin
accept On_String (String : in SideAB) do
loop
delay 3.0

Another missing terminator semicolon.

Send_Status_Req (String);
end loop;

This infinite loop is inside the accept for On_String, which means the task that calls On_String will be blocked indefinitely.

end On_String;
end Poll_For_Status;

Calling procedure
------------------------
procedure Handle_Msg(...) is
String : SideAB;
...
begin
...
Status_Task := new Poll_For_Status

As mentioned above, this is unneeded. And it's missing the terminator semicolon.

Status_Task.On_String (String);
...

If I remove the loop in the task body, it works fine. Putting it in
seems to halt execution.

Am I missing anything?

My comment on the loop inside the accept is what's confusing you. A rendezvous (when a task calls another task's entry) blocks the calling task until it completes. Since you have an infinite loop inside the accept, the rendezvous never completes and Handle_Msg never returns from the call to On_String.

Possible solutions include

1. Having the task store the value passed to it:

Side : Sideab;
begin -- Poll_For_Status;
accept On_String (String : in Sideab) do
Side := String;
end On_String;

loop
...

2. Communicating via a protected object rather than a rendezvous. This is a bigger change, but depending on your needs might result in a better design.

It may not be important to you, but your loop does not execute every 3 seconds. There may be some time after the delay expires before the task starts executing again, and using "delay" allows those times to accumulate; there's also the time to call the subprogram. If you want it to be as close to every 3 seconds as you can get, you should use the "delay until" statement.

--
Jeff Carter
"Many times we're given rhymes that are quite unsingable."
Monty Python and the Holy Grail
57
.



Relevant Pages

  • Re: On Error GoTo stops working
    ... To properly run an On Error GoTo trap, you need a Resume statement inside the code the error sends execution to in order for it to take you out of the error code and back into your main code... ... you cannot do that from inside a loop. ... Dim stName As String ...
    (microsoft.public.excel.programming)
  • Running a background task
    ... entry On_String (String: in SideAB) ... end loop; ... If I remove the loop in the task body, ...
    (comp.lang.ada)
  • extension_pack
    ... It is used to set upper loop -- limits for non-deterministic values thus avoiding the use of access -- types and enabling the functions to be used for synthesizeable code. ... DivisorVal: integer) return std_logic_vector; function "/"(DividendVal: string; DivisorVal: integer) return std_logic_vector; ... for loopVar in 0 to slvVal'length/4-1 loop ... end loop; if then return not resultVar; -- "width mismatch" errors here are due to improper sizing of the vector that this function is assigned to else return resultVar; -- "width mismatch" errors here are due to improper sizing of the vector that this function is assigned to end if; ...
    (comp.lang.vhdl)
  • extension_pack
    ... It is used to set upper loop -- limits for non-deterministic values thus avoiding the use of access -- types and enabling the functions to be used for synthesizeable code. ... DivisorVal: integer) return std_logic_vector; function "/"(DividendVal: string; DivisorVal: integer) return std_logic_vector; ... for loopVar in 0 to slvVal'length/4-1 loop ... end loop; if then return not resultVar; -- "width mismatch" errors here are due to improper sizing of the vector that this function is assigned to else return resultVar; -- "width mismatch" errors here are due to improper sizing of the vector that this function is assigned to end if; ...
    (comp.lang.vhdl)
  • extension_pack
    ... It is used to set upper loop -- limits for non-deterministic values thus avoiding the use of access -- types and enabling the functions to be used for synthesizeable code. ... DivisorVal: integer) return std_logic_vector; function "/"(DividendVal: string; DivisorVal: integer) return std_logic_vector; ... for loopVar in 0 to slvVal'length/4-1 loop ... end loop; if then return not resultVar; -- "width mismatch" errors here are due to improper sizing of the vector that this function is assigned to else return resultVar; -- "width mismatch" errors here are due to improper sizing of the vector that this function is assigned to end if; ...
    (comp.lang.vhdl)