Ada中是否有“this”关键字?

3

具体而言,任务是否有办法获取自身的引用?

例如:

task type someTask; 
type someTaskAccessor is access someTask;

task body someTask is
    pointerToTask : someTaskAccessor;
begin
    pointerToTask = this;
end someTask;

你想要实现什么目标? - Adrien Plisson
我正在实现一个分散的互斥算法。每个进程(节点)只知道它的左右邻居(指向进程的指针)。这些进程形成一个双向链表,因此,删除和插入进程需要更新其邻居指针,因此当一个进程插入自身时,它必须将指向自己的指针发送给其邻居。我可以只传递整数/任务ID,但是那样指针就必须在表中查找,这会使实现更加分散。 - Landon
啊,好的。那么你可能最感兴趣的是我回答中的最后一段话。 - T.E.D.
5个回答

5
我能提供的最明显的解决方案是在你的任务开始时声明一个约会点(入口),并传递一个对刚创建的任务的引用。另一种可能性是使用区分子来确定任务类型,其作用是告诉新任务它位于何处(将访问权限传递到新任务中)。不幸的是,我手头没有Ada编译器,所以无法给您提供任何可行的示例。
总之,在您的评论基础上:在某个地方需要处理新任务的创建,在这一点上,您还需要确定这个新任务将进入您的双向链表中的哪个位置(在创建一个新任务时,您至少需要知道一个现有任务,以便它们进行通信:他们不会像魔术般自己发现)。利用这一时刻,当您拥有新创建的任务及其左右对等体时,再次使用约会点告诉每个人谁是他们的邻居。

1
这实际上是我在问了这个问题后不久得出的解决方案 :) - Landon

4

是的,我看到了,但你能通过ID检索指针吗? - Landon
请查看Ada 2005 LRM中的包Ada.Task_Attributes(C.7.2)。这让您将通用提供的属性(例如任务指针或句柄)与任务实例关联到用户定义数据块。注意:我个人从未使用过此软件包,我只是参考了LRM。 - Marc C

1
即使这个话题很旧,但我遇到了类似的问题(我的需求是允许任务将其句柄传递给受保护的哈希映射存储区,所有任务都可以访问,实现注册)。您可以在Ada 2005中实现此操作,但不建议使用,因为它会禁用访问检查,但这是我发现的唯一一种方法,可以让任务生成(或查找)自己的句柄以传递给回调函数(请注意,这并不排除Task_ID传递以检查终止或可调用性)。
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;

你也可以在Ada 95(和2012)中这样做。另外,pointerToTask 应该被声明为 constant - Simon Wright

1

这里有几件事情。

首先,Ada和C++的面向对象方式不同。语言中没有“this”指针。调度是基于参数完成的。这意味着可以基于多个参数进行调度,与C++不同。这是另一个讨论的话题。如果您不喜欢它,您可以随时将调度参数命名为“this”。

其次,面向对象的概念并不适用于像任务这样的并发对象。这不是Ada的错。这是一个众所周知的问题。可悲的是,它被称为“并发问题”,因此在谷歌搜索中,与编程问题相关的参考资料会淹没它。基本要点是,您可以使对象支持继承、动态调度和所有好东西,或者您可以使它们支持并发。在同一语言结构中同时实现两者非常困难。

实际上,如果您需要指向自己任务的指针,您可以将其设置为全局变量,或者让分配它的任务使用某种初始化约会传递指针。我以前见过这样做的情况,当工作任务堆栈中的任务完成时,将自己放回“空闲”堆栈。


0
如果我是你,我会重新组织你的代码。因此,有一些任务与其他任务交互,现在有两个任务。还有一个链表,负责存储任务并管理任务的插入/删除。这是一个全局对象,应该处理同步。
这就是为什么我建议你创建一个受保护的对象,并将任务列表存储在其中。受保护的对象通常用于被动对象,其中必须处理某些资源的同步。您可以拥有像插入、删除等过程。这将确保只有一个创建和删除将在同一时间运行,并且链接列表不会不一致。
每个任务都应该知道它的“伙伴”任务,这些任务可能会在插入或删除任务时更改。我建议在任务中创建一个条目,以更新其邻居。当任务进入或离开时,受保护的对象将更新邻居。
在这种情况下,无需访问“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;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接