如何在Ada中创建别名任务?
考虑下面的代码。如何使任务如何在Ada中创建别名任务?,ada,multitasking,Ada,Multitasking,考虑下面的代码。如何使任务MainTask可别名,并通过access类型进行访问 private with Ada.Text_IO; private with Interfaces.C; private with Interfaces.C.Strings; procedure Main is package Text_IO renames Ada.Text_IO; package C renames Interfaces.C; package CStrings
MainTask
可别名,并通过access
类型进行访问
private with Ada.Text_IO;
private with Interfaces.C;
private with Interfaces.C.Strings;
procedure Main is
package Text_IO renames Ada.Text_IO;
package C renames Interfaces.C;
package CStrings renames Interfaces.C.Strings;
function Puts(S : C.Char_Array) return C.Int;
pragma Import (C, Puts, "puts");
package WriteListener is
type Object is task interface;
procedure WriteDone (This : in Object; Result : C.Int) is abstract;
end WriteListener;
task type Writer (Receiver : access WriteListener.Object'Class) is
entry Write (Str : in String);
end Writer;
task body Writer is
Result : C.Int;
begin
loop
select
accept Write (Str : in String) do
Result := Puts(C.To_C(Str));
end Write;
Receiver.WriteDone(Result);
or
terminate;
end select;
end loop;
end Writer;
task MainTask is new WriteListener.Object with
entry WriteDone (Result : C.Int);
end MainTask;
task body MainTask is
MyWriter : Writer := new Writer (Receiver => MainTask'Access);
R : C.Int;
begin
R := Puts(C.To_C("Starting asynchronous write"));
MyWriter.Write("Hello, world!");
EventLoop: loop
declare
TimeToExit : Boolean := False;
begin
accept WriteDone (Result : C.Int) do
R := Puts(C.To_C("Asynchronous write completed"));
TimeToExit := True;
end WriteDone;
exit EventLoop when TimeToExit;
end;
end loop EventLoop;
end MainTask;
begin
null;
end Main;
一种常见的解决方法是声明任务类型,如下所示。也许还有一种方法可以在不分配堆的情况下构造writer任务,但我不知道它的语法
private with Ada.Text_IO;
private with Interfaces.C;
private with Interfaces.C.Strings;
procedure Main is
package Text_IO renames Ada.Text_IO;
package C renames Interfaces.C;
package CStrings renames Interfaces.C.Strings;
function Puts(S : C.Char_Array) return C.Int;
pragma Import (C, Puts, "puts");
package WriteListener is
type Object is task interface;
procedure WriteDone (This : in Object; Result : C.Int) is abstract;
end WriteListener;
task type Writer (Receiver : not null access WriteListener.Object'Class) is
entry Write (Str : in String);
end Writer;
task body Writer is
Result : C.Int;
begin
loop
select
accept Write (Str : in String) do
Result := Puts(C.To_C(Str));
end Write;
Receiver.WriteDone(Result);
or
terminate;
end select;
end loop;
end Writer;
task type MainTask is new WriteListener.Object with
entry WriteDone (Result : C.Int);
end MainTask;
MyMainTask : aliased MainTask;
task body MainTask is
MyWriter : not null access Writer := new Writer (Receiver => MyMainTask'Access);
R : C.Int;
begin
R := Puts(C.To_C("Starting asynchronous write"));
MyWriter.Write("Hello, world!");
EventLoop: loop
declare
TimeToExit : Boolean := False;
begin
accept WriteDone (Result : C.Int) do
R := Puts(C.To_C("Asynchronous write completed"));
TimeToExit := True;
end WriteDone;
exit EventLoop when TimeToExit;
end;
end loop EventLoop;
end MainTask;
begin
null;
end Main;
一种常见的解决方法是声明任务类型,如下所示。也许还有一种方法可以在不分配堆的情况下构造writer任务,但我不知道它的语法
private with Ada.Text_IO;
private with Interfaces.C;
private with Interfaces.C.Strings;
procedure Main is
package Text_IO renames Ada.Text_IO;
package C renames Interfaces.C;
package CStrings renames Interfaces.C.Strings;
function Puts(S : C.Char_Array) return C.Int;
pragma Import (C, Puts, "puts");
package WriteListener is
type Object is task interface;
procedure WriteDone (This : in Object; Result : C.Int) is abstract;
end WriteListener;
task type Writer (Receiver : not null access WriteListener.Object'Class) is
entry Write (Str : in String);
end Writer;
task body Writer is
Result : C.Int;
begin
loop
select
accept Write (Str : in String) do
Result := Puts(C.To_C(Str));
end Write;
Receiver.WriteDone(Result);
or
terminate;
end select;
end loop;
end Writer;
task type MainTask is new WriteListener.Object with
entry WriteDone (Result : C.Int);
end MainTask;
MyMainTask : aliased MainTask;
task body MainTask is
MyWriter : not null access Writer := new Writer (Receiver => MyMainTask'Access);
R : C.Int;
begin
R := Puts(C.To_C("Starting asynchronous write"));
MyWriter.Write("Hello, world!");
EventLoop: loop
declare
TimeToExit : Boolean := False;
begin
accept WriteDone (Result : C.Int) do
R := Puts(C.To_C("Asynchronous write completed"));
TimeToExit := True;
end WriteDone;
exit EventLoop when TimeToExit;
end;
end loop EventLoop;
end MainTask;
begin
null;
end Main;
使您的
Main_任务
对象成为类型为Main_任务
的别名对象
还有,;不要在Writer
任务上浪费堆分配
还有一件事;记得每次调用时都要检查
put
的结果。将您的Main\u任务
对象设置为类型为Main\u任务
的别名对象
还有,;不要在Writer
任务上浪费堆分配
还有一件事;记住每次调用时都要检查来自Puts的结果。以这种方式实现该模式可能会让一些人觉得有点折磨语言。但是,无论如何,如果需要单任务声明类型的别名任务单元,则不需要,因为别名声明需要类型名称,而单任务声明是匿名类型。因此,提出的解决方案使用了一种类型,并将
SomeMainTask
声明为该类型,并使用了别名。这实现了访问
更一般地说,解决要解决的问题时,如果只有一个任务MainTask
,那么所有调用方(有限多个)都可以简单地通过它的名称来引用它,从而避免了指向它的需要。关键是在需要的地方使用包含此单一任务的包
另一个要考虑的任务是用ID互相参照的任务;例如,每个任务都可以向某个注册表提供其ID
但是,如果出于其他原因需要某个命名类型的单例任务,则可以完成该任务。一种方法是包装单个任务,并在所有包装对象中使用requeue。但是,OTOH,如果这些任务应该实现一个同步接口,那么它们也必须是任务,所以可能得不到什么好处 下面的大纲重用了原始程序来演示如何进行,尽管只强调了单例性,而不是通信和控制的结构。更可能产生类似于Ada的解决方案的替代方案需要从Ada的消息传递设施的角度重新思考这个问题package Task_Singleton is
type TaskWrapper is synchronized new WriteListener.Object with private;
private
task type TaskWrapper is new WriteListener.Object with
entry WriteDone (Result : C.Int);
end TaskWrapper;
task MainTask is new WriteListener.Object with
entry WriteDone (Result : C.Int);
end MainTask;
end Task_Singleton;
package body Task_Singleton is
task body MainTask is
R : C.Int;
begin
EventLoop: loop
declare
TimeToExit : Boolean := False;
begin
accept WriteDone (Result : C.Int) do
R := Puts(C.To_C("Asynchronous write completed"));
TimeToExit := True;
end WriteDone;
exit EventLoop when TimeToExit;
end;
end loop EventLoop;
end MainTask;
MainWrapper: aliased TaskWrapper;
task body TaskWrapper is
MyWriter : Writer (Receiver => MainWrapper'Access);
R : C.Int;
begin
R := Puts(C.To_C("Starting asynchronous write"));
MyWriter.Write("Hello, world!");
loop
select
accept WriteDone (Result : C.Int) do
requeue MainTask.WriteDone;
end WriteDone;
or
terminate;
end select;
end loop;
end Taskwrapper;
end Task_Singleton;
以这种方式实现模式可能会让一些人觉得有点折磨语言。但是,无论如何,如果需要单任务声明类型的别名任务单元,则不需要,因为别名声明需要类型名称,而单任务声明是匿名类型。因此,提出的解决方案使用了一种类型,并将
SomeMainTask
声明为该类型,并使用了别名。这实现了访问
更一般地说,解决要解决的问题时,如果只有一个任务MainTask
,那么所有调用方(有限多个)都可以简单地通过它的名称来引用它,从而避免了指向它的需要。关键是在需要的地方使用包含此单一任务的包
另一个要考虑的任务是用ID互相参照的任务;例如,每个任务都可以向某个注册表提供其ID
但是,如果出于其他原因需要某个命名类型的单例任务,则可以完成该任务。一种方法是包装单个任务,并在所有包装对象中使用requeue。但是,OTOH,如果这些任务应该实现一个同步接口,那么它们也必须是任务,所以可能得不到什么好处 下面的大纲重用了原始程序来演示如何进行,尽管只强调了单例性,而不是通信和控制的结构。更可能产生类似于Ada的解决方案的替代方案需要从Ada的消息传递设施的角度重新思考这个问题package Task_Singleton is
type TaskWrapper is synchronized new WriteListener.Object with private;
private
task type TaskWrapper is new WriteListener.Object with
entry WriteDone (Result : C.Int);
end TaskWrapper;
task MainTask is new WriteListener.Object with
entry WriteDone (Result : C.Int);
end MainTask;
end Task_Singleton;
package body Task_Singleton is
task body MainTask is
R : C.Int;
begin
EventLoop: loop
declare
TimeToExit : Boolean := False;
begin
accept WriteDone (Result : C.Int) do
R := Puts(C.To_C("Asynchronous write completed"));
TimeToExit := True;
end WriteDone;
exit EventLoop when TimeToExit;
end;
end loop EventLoop;
end MainTask;
MainWrapper: aliased TaskWrapper;
task body TaskWrapper is
MyWriter : Writer (Receiver => MainWrapper'Access);
R : C.Int;
begin
R := Puts(C.To_C("Starting asynchronous write"));
MyWriter.Write("Hello, world!");
loop
select
accept WriteDone (Result : C.Int) do
requeue MainTask.WriteDone;
end WriteDone;
or
terminate;
end select;
end loop;
end Taskwrapper;
end Task_Singleton;
可能会提供一些见解。
private with
对一个过程没有意义。您实际上只使用了with
的三个软件包中的一个。可能会提供一些见解。private with
对于一个过程来说没有意义。您实际上只使用了with
的三个包中的一个MainTask
是匿名类型,因此无法在类型系统中引用它,就像Receiver
需要做的那样。我想。(可能就像前一个对象不能重命名一样,参见LRM 8.5(5))。这是很容易更改的。MainTask
是匿名类型,因此无法在类型系统中引用它,就像Receiver
需要做的那样。我想。(可能就像前一个对象不能重命名一样,参见LRM 8.5(5))。这是很容易改变的。