具体来说,有没有办法让任务获得对自身的引用?
例如:
task type someTask;
type someTaskAccessor is access someTask;
task body someTask is
pointerToTask : someTaskAccessor;
begin
pointerToTask = this;
end someTask;
答案 0 :(得分:4)
包Ada.Task_Identification提供Current_Task函数来检索当前任务的Task_ID。
答案 1 :(得分:4)
我建议的最明显的解决方案是在任务的最开始声明一个rendez-vous(一个条目),并向其传递对刚刚创建的任务的引用。另一种可能性是对您的任务类型使用判别式,其作用是告诉新任务它位于何处(将新任务的访问权传递给判别式)。不幸的是,我手头没有Ada编译器,所以我不能给你任何有用的例子。
无论如何,根据你的评论:需要在某个地方处理新任务的创建,此时你还需要确定这个新任务将进入双向链接列表的位置(你至少需要知道)创建一个新任务时,一个现有的任务是为了让他们进行交流:他们不会神奇地发现自己)。你可以利用这个时刻,当你拥有新创建的任务及其左右同伴时,告诉每个人他们的邻居(再次使用rendez-vous)。
答案 2 :(得分:1)
这里有几件事。
首先,Ada的OO与C ++不同。语言中没有“这个”指针。调度是通过参数完成的。这样做的一个含义是,与C ++不同,可以分配多个参数。这是另一次讨论的另一次。如果您不喜欢它,您可以随时将调度参数命名为“this”。
其次,OO概念并不能很好地应用于诸如任务之类的并发对象。这不是阿达的错。这是一个众所周知的问题。可悲的是,它相当缺乏想象力地被称为“并发问题”,所以对它的引用在谷歌搜索中被编程问题所淹没。基本要点是,您可以使对象支持继承和动态分派以及所有好东西,或者您可以使它们支持并发。同时使用相同的语言结构非常困难。
作为一个实际问题,如果你需要一个指向你自己的任务的指针,你可以使它成为一个全局,或者让分配它的任务通过指针使用某种启动集合。我之前已经看过这个,在一堆工作任务中有一个任务在完成时将自己置于“空闲”堆栈中。
答案 3 :(得分:1)
即使这个主题很老,我也跑过来寻找类似的东西(我的需要是允许任务将句柄传递给自己的一个受保护的哈希映射存储区域,所有任务都可以访问,影响注册)
您可以在Ada 2005中执行此操作,认为不建议这样做,因为它会禁用访问检查,但这是我发现任务生成(或找到)它自己的句柄传递回调函数的唯一方法(请注意这并不妨碍Task_ID传递以检查Termination或Is_Callable):
task type someTask;
type someTaskAccessor is access someTask;
task body someTask is
-- Initialize the access type variable as pointing to the same task it's declared in.
pointerToTask : someTaskAccessor := someTask'Unchecked_Access; --equiv to "this" ptr
begin
-- pointerToTask = this; --this is unneeded, pointerToTask is already set!
end someTask;
答案 4 :(得分:0)
如果我是你,我会重新组织你的代码。因此,有些任务与其他任务交互,现在有2个任务。还有链表,负责存储任务和管理任务的插入/删除。这是一个应该处理synchronized的全局对象。
这就是为什么我建议你创建一个受保护的对象,并将任务列表存储在其中。 protected通常用于被动对象,其中某些资源必须处理同步。您可以使用插入,删除等程序。这将确保一次只运行一次创建和删除,并且链接列表不会不一致。
每个任务都应该知道它的“伙伴”任务,这些任务在插入或删除任务时可能会发生变化。我建议创建一个任务的入口,它将更新其邻居。当任务进入或离开时,受保护对象将更新邻居。
在这种情况下,不需要访问“this”指针,因为受保护对象将组织所有内容。只需要一个ID,可以识别任务(删除)。
我尝试编写代码,但我现在没有编译器:
task type computer;
type computer_ptr is access all computer;
task type computer is
entry init(id:integer);
entry set_neighbor(left,right:computer_ptr);
end computer;
protected comp_list is
procedure insert; -- called by organizer
procedure remove(from:integer); -- called by task
private
type comp_list is array(integer range<>) of computer_ptr;
comps:comp_list(1..MAX):=(others=>null); -- or use own structure
end comp_list;
task body computer is
id_:integer;
left_n,right_n:computer_ptr:=null;
begin
accept init(id:integer) do
id_:=id;
end init;
while true loop
select
accept set_neighbor(left,right:computer_ptr) do
left_n:=left;right_n:=right;
end set_neighbor;
or
-- do its work
end select;
if (some_condition) then
comp_list.remove(id_);
break;
end if;
end loop;
end task computer;
protected body comp_list is
procedure insert is
p:computer_ptr;
begin
p:=new computer;
-- add to list -> nr;
p.all.init(nr);
-- call set_neighbor to its left and itself
end insert;
procedure remove(from: integer) is
begin
-- remove from list and get its neighbors
-- call set_neighbor regarding new ones
end remove;
end comp_list;