* Running a background task @ 2008-05-15 20:51 Bender 2008-05-15 22:31 ` Adam Beneschan 2008-05-16 0:16 ` Jeffrey R. Carter 0 siblings, 2 replies; 10+ messages in thread From: Bender @ 2008-05-15 20:51 UTC (permalink / raw) 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) end Poll_For_Status; type Task_Access is access Poll_For_Status; Status_Task : Task_Access; (body) task body Poll_For_Status is begin accept On_String (String : in SideAB) do loop delay 3.0 Send_Status_Req (String); end loop; end On_String; end Poll_For_Status; Calling procedure ------------------------ procedure Handle_Msg(...) is String : SideAB; ... begin ... Status_Task := new Poll_For_Status 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? ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Running a background task 2008-05-15 20:51 Running a background task Bender @ 2008-05-15 22:31 ` Adam Beneschan 2008-05-15 23:14 ` Adam Beneschan 2008-05-16 0:43 ` Bender 2008-05-16 0:16 ` Jeffrey R. Carter 1 sibling, 2 replies; 10+ messages in thread From: Adam Beneschan @ 2008-05-15 22:31 UTC (permalink / raw) On May 15, 1:51 pm, Bender <Jeffrey.S.Morri...@gmail.com> 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. When Handle_Msg calls on the On_String entry, this starts a rendezvous, and Handle_Msg stops when the rendezvous is done. Since the "accept" has a "do" part, the rendezvous will not be done until the "do" completes, which in your case never happens. Thus, Handle_Msg will never proceed past the entry call. It's hard for me to give a solution, since I don't know just what you're trying to accomplish; but you may want to move the loop out of the "accept". -- Adam > Task definition > --------------------- > (spec) > task type Poll_For_Status is > entry On_String (String : in SideAB) > end Poll_For_Status; > > type Task_Access is access Poll_For_Status; > Status_Task : Task_Access; > > (body) > task body Poll_For_Status is > begin > accept On_String (String : in SideAB) do > loop > delay 3.0 > Send_Status_Req (String); > end loop; > end On_String; > end Poll_For_Status; > > Calling procedure > ------------------------ > procedure Handle_Msg(...) is > String : SideAB; > ... > begin > ... > Status_Task := new Poll_For_Status > 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? ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Running a background task 2008-05-15 22:31 ` Adam Beneschan @ 2008-05-15 23:14 ` Adam Beneschan 2008-05-16 0:43 ` Bender 1 sibling, 0 replies; 10+ messages in thread From: Adam Beneschan @ 2008-05-15 23:14 UTC (permalink / raw) On May 15, 3:31 pm, Adam Beneschan <a...@irvine.com> wrote: > On May 15, 1:51 pm, Bender <Jeffrey.S.Morri...@gmail.com> 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. > > When Handle_Msg calls on the On_String entry, this starts a > rendezvous, and Handle_Msg stops when the rendezvous is done. That should be "Handle_Msg stops until the rendezvous is done". Sorry. > Since > the "accept" has a "do" part, the rendezvous will not be done until > the "do" completes, which in your case never happens. Thus, > Handle_Msg will never proceed past the entry call. -- Adam ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Running a background task 2008-05-15 22:31 ` Adam Beneschan 2008-05-15 23:14 ` Adam Beneschan @ 2008-05-16 0:43 ` Bender 2008-05-16 15:25 ` Adam Beneschan 1 sibling, 1 reply; 10+ messages in thread From: Bender @ 2008-05-16 0:43 UTC (permalink / raw) On May 15, 4:31 pm, Adam Beneschan <a...@irvine.com> wrote: > When Handle_Msg calls on the On_String entry, this starts a > rendezvous, and Handle_Msg stops when the rendezvous is done. Since > the "accept" has a "do" part, the rendezvous will not be done until > the "do" completes, which in your case never happens. Thus, > Handle_Msg will never proceed past the entry call. > > It's hard for me to give a solution, since I don't know just what > you're trying to accomplish; but you may want to move the loop out of > the "accept". > > -- Adam I need to poll the device every 3 seconds. If I move the loop outside of the accept, won't it just call Send_Status_Req procedure one time, then finish the task? Surely there must be a mechanism similar to C's pthread that allows me to start a thread and let it worry about itself, while the main thread continues processing. All I'm seeing here is that the task is run in parallel to the other code in the Handle_Msg procedure. I wan't that procedure to finish up, and let the rest of the program continue to run, all with Poll_For_Status running in the background. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Running a background task 2008-05-16 0:43 ` Bender @ 2008-05-16 15:25 ` Adam Beneschan 2008-05-16 15:29 ` Adam Beneschan 0 siblings, 1 reply; 10+ messages in thread From: Adam Beneschan @ 2008-05-16 15:25 UTC (permalink / raw) On May 15, 5:43 pm, Bender <Jeffrey.S.Morri...@gmail.com> wrote: > On May 15, 4:31 pm, Adam Beneschan <a...@irvine.com> wrote: > > > When Handle_Msg calls on the On_String entry, this starts a > > rendezvous, and Handle_Msg stops when the rendezvous is done. Since > > the "accept" has a "do" part, the rendezvous will not be done until > > the "do" completes, which in your case never happens. Thus, > > Handle_Msg will never proceed past the entry call. > > > It's hard for me to give a solution, since I don't know just what > > you're trying to accomplish; but you may want to move the loop out of > > the "accept". > > > -- Adam > > I need to poll the device every 3 seconds. If I move the loop outside > of the accept, won't it just call Send_Status_Req procedure one time, > then finish the task? No. If Send_Status_Req is in a loop, then it will call it in a loop. This is the same whether or not the loop is inside the accept or outside of it. The difference is that if it's inside the accept, it will hold up the task (which could be the main program, technically the "environment task") calling the entry being accepted, and if it's not inside the accept, it won't; but other than that, the behavior will be the same either way. I'm not clear on why you'd be confused about this (i.e. why you think it would call Send_Status_Req only once)---I suspect you may have some misconception about how tasks work, but I can't think what it might be, so if this is still confusing to you, you may need to explain a little more clearly what you're confused about, so that we can help clear up whatever misunderstanding you may have. > Surely there must be a mechanism similar to C's pthread that allows me > to start a thread and let it worry about itself, while the main thread > continues processing. That's pretty much what you're doing with tasks. Ada, however, doesn't specify whether tasking is implemented with threads or some other way---that's up to the implementor. I think threads is a popular way to implement tasks, though. > All I'm seeing here is that the task is run in > parallel to the other code in the Handle_Msg procedure. I'm not clear on what the difference is between this sentence and what you would *like* to happen. > I wan't that > procedure to finish up, and let the rest of the program continue to > run, all with Poll_For_Status running in the background. Did you try moving the loop out of the accept? If so, what happened? If it didn't work the way you anticipated, then how did it not work? -- Adam ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Running a background task 2008-05-16 15:25 ` Adam Beneschan @ 2008-05-16 15:29 ` Adam Beneschan 0 siblings, 0 replies; 10+ messages in thread From: Adam Beneschan @ 2008-05-16 15:29 UTC (permalink / raw) On May 16, 8:25 am, Adam Beneschan <a...@irvine.com> wrote: > No. If Send_Status_Req is in a loop, then it will call it in a loop. > This is the same whether or not the loop is inside the accept or > outside of it. The difference is that if it's inside the accept, it > will hold up the task (which could be the main program, technically > the "environment task") calling the entry being accepted, and if it's > not inside the accept, it won't; but other than that, the behavior > will be the same either way. I'm not clear on why you'd be confused > about this (i.e. why you think it would call Send_Status_Req only > once)---I suspect you may have some misconception about how tasks > work, but I can't think what it might be, so if this is still > confusing to you, you may need to explain a little more clearly what > you're confused about, so that we can help clear up whatever > misunderstanding you may have. Please note that I wrote all this before I saw your latest post where you had gotten things to work. So it looks like you've gotten everything figured out now---great! -- Adam ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Running a background task 2008-05-15 20:51 Running a background task Bender 2008-05-15 22:31 ` Adam Beneschan @ 2008-05-16 0:16 ` Jeffrey R. Carter 2008-05-16 0:49 ` Bender 1 sibling, 1 reply; 10+ messages in thread From: Jeffrey R. Carter @ 2008-05-16 0:16 UTC (permalink / raw) 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 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Running a background task 2008-05-16 0:16 ` Jeffrey R. Carter @ 2008-05-16 0:49 ` Bender 2008-05-16 4:32 ` Jeffrey R. Carter 0 siblings, 1 reply; 10+ messages in thread From: Bender @ 2008-05-16 0:49 UTC (permalink / raw) On May 15, 6:16 pm, "Jeffrey R. Carter" <spam.jrcarter....@spam.acm.org> wrote: > 1. You're missing the terminator semicolon. Ignore that. Just remnants of me hastily retyping my code in here. It all compiles fine. > 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. Got it. > 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. I believe I originally did it this way, but then changed to using the access stuff because it wasn't behaving the way I wanted it to. I thought using the new operator would hold the key to Handle_Msg not caring about whether the task had finished yet or not, but it didn't. > This infinite loop is inside the accept for On_String, which means the task that > calls On_String will be blocked indefinitely. That's my question in a nutshell. I need the task to run forever. I need the Handle_Msg procedure to end and start handling other incoming messages. > 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 > ... Will this solve my problem? Unfortunately I'm at home at the moment, but once I get into work I'll give it a shot. Once the 'end On_String' is reached, will Handle_Msg continue on, while the task continues to run? > 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. This is such a simple task that I think what's above should be simple enough to handle it, but I'll read up on it if necessary. > 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. Yeah, I had read something about this before. I'll look into it. Thanks for all your help. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Running a background task 2008-05-16 0:49 ` Bender @ 2008-05-16 4:32 ` Jeffrey R. Carter 2008-05-16 14:34 ` Bender 0 siblings, 1 reply; 10+ messages in thread From: Jeffrey R. Carter @ 2008-05-16 4:32 UTC (permalink / raw) Bender wrote: > > That's my question in a nutshell. I need the task to run forever. I > need the Handle_Msg procedure to end and start handling other incoming > messages. There are at least 2 tasks in your code: Status_Task and the task that calls Handle_Msg. In Ada, all execution is part of a task; a purely sequential program (without any explicit tasks) is the execution of an implicit task called the environment task. So "the task" is ambiguous, but I presume you mean Status_Task. As written, Status_Task does run forever. It's the other task that's blocked. > Will this solve my problem? Unfortunately I'm at home at the moment, > but once I get into work I'll give it a shot. Once the 'end > On_String' is reached, will Handle_Msg continue on, while the task > continues to run? Yes, IIUC. When the rendezvous ends, at "end On_String", both tasks continue (conceptually) in parallel. Handle_Msg will continue with the next statement after the call to Status_Task.On_String, and the Status_Task will continue into the loop. I think this is what Beneschan meant by 'move the loop out of the "accept"'. If you have fewer tasks than processors, it's possible to write code such that a task that is ready to run never executes ("starvation"), but that's probably not something that you need to worry about. -- Jeff Carter "Many times we're given rhymes that are quite unsingable." Monty Python and the Holy Grail 57 ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Running a background task 2008-05-16 4:32 ` Jeffrey R. Carter @ 2008-05-16 14:34 ` Bender 0 siblings, 0 replies; 10+ messages in thread From: Bender @ 2008-05-16 14:34 UTC (permalink / raw) On May 15, 10:32 pm, "Jeffrey R. Carter" <spam.jrcarter....@spam.acm.org> wrote: > Yes, IIUC. When the rendezvous ends, at "end On_String", both tasks continue > (conceptually) in parallel. Handle_Msg will continue with the next statement > after the call to Status_Task.On_String, and the Status_Task will continue into > the loop. I think this is what Beneschan meant by 'move the loop out of the > "accept"'. > > If you have fewer tasks than processors, it's possible to write code such that a > task that is ready to run never executes ("starvation"), but that's probably not > something that you need to worry about. Just wanted to confirm that moving the loop outside of the accept block did indeed work the way I needed it to. Thanks to everyone for your help. ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2008-05-16 15:29 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2008-05-15 20:51 Running a background task Bender 2008-05-15 22:31 ` Adam Beneschan 2008-05-15 23:14 ` Adam Beneschan 2008-05-16 0:43 ` Bender 2008-05-16 15:25 ` Adam Beneschan 2008-05-16 15:29 ` Adam Beneschan 2008-05-16 0:16 ` Jeffrey R. Carter 2008-05-16 0:49 ` Bender 2008-05-16 4:32 ` Jeffrey R. Carter 2008-05-16 14:34 ` Bender
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox