冻结 Ada 任务
如何冻结任务?
我的意思是,如果我有一个任务
task body My_Task is
begin
accept Start;
loop
Put ("1");
Put ("2");
Put ("3");
...
Put ("n");
end loop;
end My_Task;
,有没有办法可以将任务“冻结”在当前状态?例如,如果执行完成了 Put ("2");
,我如何冻结它并稍后可以将其继续?我想从任务外部引发冻结,并从外部命令它继续。
更新
这样的规范,我肯定可以实现,
type State_Type is
(RUN,
FROZEN);
task type My_Task (State : State_Type) is
entry Start;
end My_Task;
如果我有像正文
task body My_Task is
begin
accept Start;
loop
Put ("1");
Put ("2");
Put ("3");
...
Put ("n");
loop
if State = RUN then exit; end if;
end loop;
end loop;
end My_Task;
但事实并非如此,因为我必须等待第 n 个 Put 指令行(即,任务实际上不会被冻结,因为内部循环将会运行)。
How can I freeze a task?
I mean, if I have a task
task body My_Task is
begin
accept Start;
loop
Put ("1");
Put ("2");
Put ("3");
...
Put ("n");
end loop;
end My_Task;
is there a way that I can "freeze" the task in its current state? If, for instance, the execution finished executing Put ("2");
, how can I freeze it and later I can turn it to continue? I want to provoque a freeze from outside the task, and also from outside, order it to continue.
Update
I could sure implement, if I had the spec like
type State_Type is
(RUN,
FROZEN);
task type My_Task (State : State_Type) is
entry Start;
end My_Task;
the body
task body My_Task is
begin
accept Start;
loop
Put ("1");
Put ("2");
Put ("3");
...
Put ("n");
loop
if State = RUN then exit; end if;
end loop;
end loop;
end My_Task;
but it would not be the case because I had to wait for the nth Put instruction line (i.e., the task would not be actually frozen, because the inside loop would be running).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您可以使用“选择性接受”来允许您的任务被外部调用者(另一个任务或主程序)中断。您不能(轻易)在任务执行过程中的任意时刻中断任务;相反,任务本身需要确定何时接受进入调用。
因此,您可能希望
用一个循环替换您的序列,该循环在每次迭代时调用一次
Put
,并每次都执行一个select
语句。这是我刚刚编写的一个演示程序。计数器每秒(大约)递增一次。如果
Running
为 true,则打印计数器值;否则循环会默默地进行。主程序每 3 秒交替调用 Pause 和 Resume。如果两个条目都没有被调用,
select
语句中的else
子句会导致它继续执行。可能还有比这更优雅的方法。已经很久没有真正使用过Ada了。
You can use a "selective accept" to allow your task to be interrupted by an external caller (another task or the main program). You can't (easily) interrupt a task at an arbitrary point in its execution; instead, the task itself needs to determine when it will accept entry calls.
So you'll probably want to replace your sequence
by a loop that calls
Put
once on each iteration, with aselect
statement that's executed each time.Here's a demo program that I just threw together. The counter increments once per second (approximately). The counter value is printed if
Running
is true; otherwise the loop proceeds silently. The main program alternatively calls Pause and Resume every 3 seconds.The
else
clause in theselect
statement cause it to continue executing if neither entry has been called.There may be a more elegant approach than this. It's been a long time since I've really used Ada.
哇,好久没看到艾达的问题了。无论如何,每当您需要暂停任务时,您都可以使用“延迟”或“延迟直到”保留字。
您可以指定要恢复执行的时间,然后说:
延迟<时间>
或
延迟直到<时间>
我不记得确切的细节,但是这是 Ada95 规范示例: http://www.adaic.org/resources/add_content/docs/95style/html/sec_6/6-1-7.html
Wow, haven't seen an Ada question in awhile. Anyway whenever you need to pause a task you use the
delay
ordelay until
reserved words.you would specify a time you want to resume execution, then say:
delay <time>
or
delay until <time>
I don't remember the exact details, but here is the Ada95 specification example: http://www.adaic.org/resources/add_content/docs/95style/html/sec_6/6-1-7.html
Ada 语言的设计意图之一是行为是明确的。一项正在执行的任务突然发现自己由于没有明显原因而“冻结”在任意点(任务中没有任何内容会导致该行为),充其量只会令人不安。如果任务的设计不允许意外的、任意的执行暂停,则可能是一个错误。 (我知道操作系统时间切片将这种行为强加于执行程序,但这是操作系统的功能,而不是编程语言的功能。)
简而言之,我会严重质疑依赖外部强加的任务暂停的设计方法。任务应该知道它自己的状态,从而知道何时可以安全地暂停,以及暂停时必须保持哪些不变量以确保正确恢复。
One aspect of the intent of the design underlying the Ada language is that behavior be explicit. An executing task that suddenly found itself "frozen" at an arbitrary point for no readily discernible reason--there being nothing in the task that would lead to that behavior--would be disconcerting at best. And possibly a bug if the task was not designed to allow for unexpected, arbitrary execution suspension. (I know OS time-slicing imposes this behavior on executing programs, but that's a function of the OS, not the programming language.)
In short, I would seriously question a design approach that relied on externally imposed task suspension. A task should know it's own state, thus know when it's safe to pause, and what invariants have to hold for pausing in order to ensure a proper resumption.
为了获得正确中断
put("x")
序列所需的粒度,您应该将其编写为一个过程,将其状态保存在task my_task
中(知道哪个原子指令已被执行)。那么我想你可以在你的
State_Typeguard code> 并且仅在未冻结时执行。当然,这不会停止任务,它只会保护 put("x") 序列不被执行(我认为这就是你想要的!)
To get the granularity you need to correctly interrupt your
put("x")
sequence, you should write that as a procedure that saves its state withintask my_task
(knowing which atomic instruction has been executed).Then I think you could then use a guard on your
State_Type
and only execute when not frozen. of course this will not stop the task, it will simply protect theput("x")
sequence from being executed (which is what you want, i think!)如果您总是希望任务在某一特定行等待,那么解决方案相当简单:只需在此处放置一条
accept
语句即可。该任务将挂起,直到其他任务调用该条目。如果你想推广这个想法(这样可以让多个任务等待,或者多个不同的任务可以安全地执行释放操作),最好将你的 State 变量封装在受保护的对象中(正如国家气象局建议的那样)。受保护对象的功能被专门放入语言中,以方便为此类任务创建同步对象。
If you have a specific line where you would always like your task to wait, the solution is fairly easy: Just put an
accept
statement there. The task will hang until some other task calls that entry.If you want to generalize this idea (so multiple tasks can be made to wait, or multiple different tasks can safely perform the release action), it might be better to encapsulate your
State
variable inside a protected object (as NWS suggested). The feature of protected objects was put in the language specifically to facilitate the creation of synchornization objects for tasks like this.您在回复其中一条评论时提到,您希望这样做是因为有一些共享资源。那么,答案似乎是您想要将该共享资源包装在受保护对象中,并从任务中调用该受保护对象的过程/条目;当任务在受保护对象调用上排队(或执行)时,它会进入“阻塞”状态,直到它返回,从而“冻结”进一步的处理。
编辑:添加了代码示例。
注意: put_line 的使用在技术上不是线程安全的,并且 [IIRC] 可能会阻塞......因此,虽然上述内容永远不会死锁,但实际上并不能保证。
You mentioned, in response to one of the comments, that you want this because of some shared resources. The answer, then, seems to be that you want to wrap that shared-resource in a protected-object and call that protected-object's procedures/entries from the task; while a task is queued up on (or executing) a protected-object call it is put into the 'blocked' state until it returns thereby 'freezing' the further processing.
Edit: Added a code example.
Note: The use of put_line is technically not thread-safe, and [IIRC] potentially blocking... so while the above should never deadlock such is not actually guaranteed.
我还从 Anh Vo in comp.lang.ada 得到了答案(冻结任务),其中还包括带有任务终止的 Rendevouz。经过一些调整,它得到:
我承认我认为这个解决方案非常优雅。
I got also an answer from Anh Vo in comp.lang.ada (Freezing a task), which includes the Rendevouz also with task termination. With some adjustments, it gets:
I confess I think this solution is very elegant.