これは、テキストブックであっても、どこにでも提示されているように、Adaの非常に基本的な保護境界バッファです。 (これはもっと大きなものの一部ですが、コードを最小限に単純化して、動作を再現しました)。 私は1つのタスクにそれを供給し、 "メイン"のボディがそれから読んでいるとうまくいくようです。しかし、パターとゲッターという2つのタスクを以下のように使用すると、1st Getでブロックされます。ものではない再評価されているバリアにあなたが見ることができるように、取得(Ada)奇妙な閉塞について2つのタスクで基本保護された有界バッファを取得
$ ./test_buffer
Putter started
Put X= 0; First= 0, Last= 0, Count= 0
Put X= 1; First= 0, Last= 1, Count= 1
Put X= 2; First= 0, Last= 2, Count= 2
Put X= 3; First= 0, Last= 3, Count= 3
Getter started
Put X= 4; First= 0, Last= 4, Count= 4
Put X= 5; First= 0, Last= 5, Count= 5
Put X= 6; First= 0, Last= 6, Count= 6
Put X= 7; First= 0, Last= 7, Count= 7
Put X= 8; First= 0, Last= 8, Count= 8
^C
が実行されません取得ん、そう:
with Ada.Text_IO;use Ada.Text_IO;
procedure test_buffer is
maxItems : constant Positive := 10;
type Index is mod maxItems;
maxCount : constant Index := 9;
type ItemArray is array(Index) of Integer;
protected Buffer is
entry Put(X : in Integer);
entry Get(X : out Integer);
private
First, Last, Count : Index := 0;
buf : ItemArray;
end;
protected body Buffer is
entry Put(X : in Integer) when Last - First < maxCount is
begin
Put_Line("Put X="&X'Img & "; First="&First'Img&", Last="&Last'Img&", Count="&Count'Img);
buf(Last) := X;
Last := Last + 1;
Count := Count + 1;
end;
--
entry Get(X : out Integer) when Last - First > 0 is
begin
Put_Line("Get X="&X'Img & "; First="&First'Img&", Last="&Last'Img&", Count="&Count'Img);
X := buf(First);
First := First + 1;
Count := Count - 1;
end;
end;
task Putter;
task body Putter is
begin
Put_Line("Putter started");
for i in 0 ..25 loop
Buffer.Put(i);
end loop;
end;
task Getter;
task body Getter is
X : Integer;
begin
Put_Line("Getter started");
loop
Put_Line("requesting X..");
Buffer.Get(X);
Put_Line("got X="&X'Img);
end loop;
end;
-- X : Integer;
begin
-- loop
-- Buffer.Get(X);
-- Put_Line("got X="&X'Img);
-- end loop;
Null;
end test_buffer;
これは、次のような出力を出してくれる。しかし、本体のコメントを外してタスクをコメントアウトする(またはメインコードのコメントを外してから同時読み込みを行う)と、すべての読み取りと書き込みで正常に処理されます。
ルールを見つけることができません。 (2番目のタスクは外部的なので、いいえ、保護されたオブジェクトの内部呼び出しに対する再評価ではありません)。
私はここで何かが分からないか、これはバグですか?
Debian Stretchのgcc-6(FSF)は私のために働きます(間違いなくバグがないことは証明されません)。お使いのOSとコンパイラのバージョンは何ですか?ここでは、両方のタスクが最初のPutの前に開始され、違いが生じる可能性があります。 –
私のためにも動作します(Debian/Jessieの64ビット版GNAT 4.9.2)。しかし、I/Oコールは「潜在的にブロックされている」ため、保護された操作の中では違法であることに注意してください。 –
いいえ、ここではまだ別のコンピュータでも動作しません。そしてそれはさらに奇妙になる。これがどのように標準的であるかを見ると、GNAT.Bounded_Buffers(その本体にはまったく同じコードがあります)がインスタンス化され、挿入と削除(コードに入れて取得)がすぐに停止します。これは –