Synchronization 等待项目到达受保护对象

Synchronization 等待项目到达受保护对象,synchronization,task,blocking,ada,Synchronization,Task,Blocking,Ada,好吧,Ada的任务对我来说是一个新的、令人困惑的问题。我有一个典型的问题,就是一个受保护的对象将事件按ID存储为密钥。其思想是生产者任务用传入事件填充它,而一个或多个使用者任务需要等待,直到给定id的事件到达,也就是说,它们应该阻止,直到它存储在映射中,然后返回该事件 以下是迄今为止的结构: package Reply\u存储是新的Ada.Containers.unfinite\u Ordered\u映射 (键类型=>命令Id类型, 元素类型=>事件类型); 受保护类型的应答队列为 程序Put(

好吧,Ada的任务对我来说是一个新的、令人困惑的问题。我有一个典型的问题,就是一个受保护的对象将事件按ID存储为密钥。其思想是生产者任务用传入事件填充它,而一个或多个使用者任务需要等待,直到给定id的事件到达,也就是说,它们应该阻止,直到它存储在映射中,然后返回该事件

以下是迄今为止的结构:

package Reply\u存储是新的Ada.Containers.unfinite\u Ordered\u映射
(键类型=>命令Id类型,
元素类型=>事件类型);
受保护类型的应答队列为
程序Put(事件:事件类型);
条目获取(Id:Command\u Id\u Type;Event:out Event\u Type);
私有的
存储:Reply_Storage.Map;
结束应答队列;
受保护的主体应答队列为
程序Put(事件:事件类型)为
Id:Command\u Id\u Type:=事件\u Command\u Id(事件);
开始
存储。插入(Id、事件);
端置;
条目获取(Id:Command\u Id\u Type;Event:out Event\u Type)
非存储时,存储为空
开始
如果Storage.Contains(Id)则
事件:=存储.元素(Id);
存储。删除(Id);
如果结束;
收尾;
结束应答队列;
基本上,当Storage.Contains(Id)位于条目的主体中时,我需要一个屏障,而不是Storage.Is_为空。当然,这是不允许的,因为障碍是独立于进入呼叫进行检查的


但是如何实现所需的同步呢?

因此,您需要的是一个条目族(仅适用于离散类型),如下所示:

package Reply\u存储是新的Ada.Containers.unfinite\u Ordered\u映射
(键类型=>命令Id类型,
元素类型=>事件类型);
受保护类型的应答队列为
程序Put(事件:事件类型);
条目获取(命令Id类型)(事件:输出事件类型);--入门族
私有的
存储:Reply_Storage.Map;
结束应答队列;
受保护的主体应答队列为
程序Put(事件:事件类型)为
Id:Command\u Id\u Type:=事件\u Command\u Id(事件);
开始
存储。插入(Id、事件);
端置;
条目获取(用于命令中的Id_Id_类型)(事件:输出事件_类型)--条目族
当Storage.Contains(Id)为——屏障中的族指示符(条目索引)时
开始
事件:=存储.元素(Id);
存储。删除(Id);
收尾;
结束应答队列;

听起来你需要一个条目族(),它有点像一个条目数组(我认为至少GNAT实现了它们),IIRC屏障是在完成过程/条目后评估的,所以你的问题不是它们是独立评估的,但不能在屏障条件下使用参数Id。按enter键太快。我想补充一点,如果您只有一个消费者,您可能可以通过重新查询来管理一些解决方法。有关入门系列和Ada 95的“更强大”重新查询(在c.l.Ada中提到)之间的比较,请参阅,解释“偏好控制”。这部分的基本原理将继续讨论这个问题。非常感谢!这似乎有效,但有一种奇怪的好奇心。Command_Id_Type最初是Natural的一个简单子类型,由于静态约束检查失败,它拒绝编译。将其定义为命令\u Id\u类型是新的整数范围0。。整数'Last-1;工作正常,但gcc发出了许多奇怪的消息:在函数
bham\uu connection\u handlerTKB中:bham.adb:(.text+0x1300a):根据
.bss'和其他许多地方,重新定位被截断以适应:R_X86\u 64\u 32。它们意味着什么?而不是探索实现大量队列的实现方式(也许是实现者的工作),我会考虑实际问题ID的数量,并定义一种反映这一问题的类型。使用
Natural
Integer'Last-1
,使其(a)依赖于实现(
2**15
2**31
,或2**63),以及(b)失去上述精确性。因此,也许
范围为1000。。1450
或类似的建议?这是个好建议。不幸的是,在这种情况下,命令ID是连续的数字,我需要一个大的空间,而不是一个小的固定数字集。在当前GNAT中,模块化2**24整数类型适用于条目族。对于我的应用程序来说,这可能已经足够了,但是这个解决方案的实现依赖性确实让我感到困扰,当我有时间的时候,我将探索一个重新排队的解决方案。无论如何,egilhh的回答完全回答了我的问题,因为我不清楚实际有多少个命令ID。