等待一个项目到达受保护的对象
Waiting until an item arrives in a protected object
好的,Ada 任务分配对我来说很新而且很困惑。我有一个受保护对象的经典问题,该对象按 ID 作为键存储事件。这个想法是生产者任务用传入的事件填充它,一个或多个消费者任务需要等待 直到 给定 id 的事件到达,即它们应该阻塞直到它存储在地图,然后 return 那个事件。
目前的结构如下:
package Reply_Storage is new Ada.Containers.Indefinite_Ordered_Maps
(Key_Type => Command_Id_Type,
Element_Type => Event_Type);
protected type Reply_Queue is
procedure Put (Event : Event_Type);
entry Take (Id : Command_Id_Type; Event : out Event_Type);
private
Storage : Reply_Storage.Map;
end Reply_Queue;
protected body Reply_Queue is
procedure Put (Event : Event_Type) is
Id : Command_Id_Type := Event_Command_Id (Event);
begin
Storage.Insert (Id, Event);
end Put;
entry Take (Id : Command_Id_Type; Event : out Event_Type)
when not Storage.Is_Empty is
begin
if Storage.Contains(Id) then
Event := Storage.Element (Id);
Storage.Delete (Id);
end if;
end Take;
end Reply_Queue;
基本上,当 Storage.Is_Empty 时,我需要一个屏障 when Storage.Contains(Id)[=23=,而不是 ] 在条目正文中 Take。当然,这是不允许的,因为屏障的检查独立于入口调用。
但是如何实现想要的同步呢?
所以,你需要的是一个入口族(只适用于离散类型),像这样:
package Reply_Storage is new Ada.Containers.Indefinite_Ordered_Maps
(Key_Type => Command_Id_Type,
Element_Type => Event_Type);
protected type Reply_Queue is
procedure Put (Event : Event_Type);
entry Take (Command_Id_Type) (Event : out Event_Type); -- entry family
private
Storage : Reply_Storage.Map;
end Reply_Queue;
protected body Reply_Queue is
procedure Put (Event : Event_Type) is
Id : Command_Id_Type := Event_Command_Id (Event);
begin
Storage.Insert (Id, Event);
end Put;
entry Take (for Id in Command_Id_Type) (Event : out Event_Type) -- entry family
when Storage.Contains(Id) is -- family designator (entry index) in barrier
begin
Event := Storage.Element (Id);
Storage.Delete (Id);
end Take;
end Reply_Queue;
好的,Ada 任务分配对我来说很新而且很困惑。我有一个受保护对象的经典问题,该对象按 ID 作为键存储事件。这个想法是生产者任务用传入的事件填充它,一个或多个消费者任务需要等待 直到 给定 id 的事件到达,即它们应该阻塞直到它存储在地图,然后 return 那个事件。
目前的结构如下:
package Reply_Storage is new Ada.Containers.Indefinite_Ordered_Maps
(Key_Type => Command_Id_Type,
Element_Type => Event_Type);
protected type Reply_Queue is
procedure Put (Event : Event_Type);
entry Take (Id : Command_Id_Type; Event : out Event_Type);
private
Storage : Reply_Storage.Map;
end Reply_Queue;
protected body Reply_Queue is
procedure Put (Event : Event_Type) is
Id : Command_Id_Type := Event_Command_Id (Event);
begin
Storage.Insert (Id, Event);
end Put;
entry Take (Id : Command_Id_Type; Event : out Event_Type)
when not Storage.Is_Empty is
begin
if Storage.Contains(Id) then
Event := Storage.Element (Id);
Storage.Delete (Id);
end if;
end Take;
end Reply_Queue;
基本上,当 Storage.Is_Empty 时,我需要一个屏障 when Storage.Contains(Id)[=23=,而不是 ] 在条目正文中 Take。当然,这是不允许的,因为屏障的检查独立于入口调用。
但是如何实现想要的同步呢?
所以,你需要的是一个入口族(只适用于离散类型),像这样:
package Reply_Storage is new Ada.Containers.Indefinite_Ordered_Maps
(Key_Type => Command_Id_Type,
Element_Type => Event_Type);
protected type Reply_Queue is
procedure Put (Event : Event_Type);
entry Take (Command_Id_Type) (Event : out Event_Type); -- entry family
private
Storage : Reply_Storage.Map;
end Reply_Queue;
protected body Reply_Queue is
procedure Put (Event : Event_Type) is
Id : Command_Id_Type := Event_Command_Id (Event);
begin
Storage.Insert (Id, Event);
end Put;
entry Take (for Id in Command_Id_Type) (Event : out Event_Type) -- entry family
when Storage.Contains(Id) is -- family designator (entry index) in barrier
begin
Event := Storage.Element (Id);
Storage.Delete (Id);
end Take;
end Reply_Queue;