私は自分のマルチスレッドの大部分をAdaを使って行います。次のAdaの例は、コンディション変数の待機にタイムアウトを適用することによって、コンシューマが非応答プロデューサを処理し、プロデューサが非応答コンシューマを処理する方法を示しています。
------------------------------------------------------------------
-- Producer-Consumer Package --
------------------------------------------------------------------
with Ada.Text_IO; use Ada.Text_IO;
procedure Protected_Producer_Consumer is
protected Buffer is
entry Put(Item : in Integer);
entry Get(Item : out Integer);
private
Value : Integer := Integer'First;
Is_New : Boolean := False;
end Buffer;
protected body Buffer is
entry Put(Item : in Integer) when not Is_New is
begin
Value := Item;
Is_New := True;
end Put;
entry Get(Item : out Integer) when Is_New is
begin
Item := Value;
Is_New := False;
end Get;
end Buffer;
task producer;
task body producer is
Wait_Limit : constant Natural := 5;
Written : Boolean := False;
begin
for value in 1..15 loop
Written := False;
for try in 1..Wait_Limit loop
Select
Buffer.Put(Value);
Written := True;
or
delay 0.5;
end select;
exit when Written;
end loop;
if not Written then
Put_Line("Producer terminating. Consumer not responding.");
exit;
end if;
end loop;
end producer;
task consumer;
task body consumer is
Wait_Limit : Natural := 5;
Value_Read : Boolean;
The_Value : Integer;
begin
Loop
Value_Read := False;
for try in 1..Wait_Limit loop
select
Buffer.Get(The_Value);
Value_Read := True;
Put_Line("Consumer read value: " & Integer'Image(The_Value));
or
delay 0.5;
end select;
exit when Value_Read;
end loop;
if not Value_Read then
Put_Line("Consumer terminating. Producer not responding.");
exit;
end if;
end loop;
end Consumer;
begin
null;
end Protected_Producer_Consumer;
上記の例のバッファなどのAdaで保護されたオブジェクトは、自動的に相互排除を提供します。上の例では、BufferオブジェクトにPutとGetの2つのエントリがあります。 Putエントリは、バッファ内部変数Is_NewがFalseの場合にのみ実行できます。 Getエントリは、バッファの内部変数Is_NewがTrueの場合にのみ実行できます。
Producerタスク(C++のスレッドに似ています)には、変数「値」を最初の1に、次に2までを15まで設定する外部ループが含まれています。バッファはWait_Limit回までバッファリングされます。毎回プロデューサが0.5秒間タイマーを設定し、成功しなかった場合は再び試行します。プロデューサがWait_Limitに失敗すると、エラーメッセージが書き込まれ、終了します。
消費者の行動はプロデューサに似ています。 Getエントリを呼び出してBufferから値を読み取ります。また、試行ごとに0.5秒待ってから、Wait_Limitの連続した失敗からバッファから値を読み取った後に終了します。
このプログラムの出力は次のとおりです。
Consumer read value: 1
Consumer read value: 2
Consumer read value: 3
Consumer read value: 4
Consumer read value: 5
Consumer read value: 6
Consumer read value: 7
Consumer read value: 8
Consumer read value: 9
Consumer read value: 10
Consumer read value: 11
Consumer read value: 12
Consumer read value: 13
Consumer read value: 14
Consumer read value: 15
Consumer terminating. Producer not responding.
あなたが予想される例外の本質とは何ですか?プロデューサが共有バッファへの書き込みに失敗した場合、プロデューサは例外を処理する必要があり、消費者は例外を認識すべきではありません。コンシューマが共有バッファからの読み込みに失敗した場合、コンシューマは例外を処理する必要があり、プロデューサは例外を認識すべきではありません。 –
@JimRogers consumeItem(item)および/またはproduceItem()は例外 –
に直面する可能性がありますが、2つのスレッド間の唯一のインターフェイスはバッファです。プロデューサが例外に遭遇した場合、コンシューマはそれが例外から回復するのを待つ。同様に、消費者が例外に遭遇した場合、プロデューサは消費者が例外から回復するのを待つ。プロデューサまたはコンシューマのいずれかが例外から回復しないことを心配する場合は、各スレッドのバッファへのアクセス待ちにタイムアウトを適用する必要があります。 –