이것은 Ada에서 텍스트 기반의 책들과 마찬가지로 매우 제한적인 보호 된 경계 버퍼입니다. (이것은 더 큰 일의 일부이지만 최소한의 코드로 코드를 단순화하여 동작을 재현했습니다.) 1 개의 작업에 먹이를주고 "기본"본문에서 읽는 것이 좋습니다. 하지만 아래의 두 작업 (Putter 및 Getter)을 사용하면 첫 번째 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;
이 다음과 같은 출력을 뱉는 다. 그러나 주체의 주석을 제거하고 작업을 주석으로 처리 (또는 주 코드의 주석 처리를 제거하여 동시 읽기를 얻는 경우)하면 모든 읽기 및 쓰기 작업으로 정상적으로 진행됩니다.
규칙을 찾을 수없는 것 같습니다. Get (2 번째 작업은 외부 객체이므로 보호 객체의 내부 호출에 대한 재평가가 아닌)에서 장벽을 막을 수 있습니다.
여기에 명백한 내용이 누락되었거나 버그입니까?
데비안 스트레치의 gcc-6 (FSF)에 대한 저의 작품 (틀림없이, 버그가 없다는 것을 증명하지는 않습니다). OS 및 컴파일러 버전은 무엇입니까? 여기서 두 작업은 첫 번째 Put 전에 시작되어 차이가 발생할 수 있습니다. –
나를 위해 일합니다 (64 비트 데비안/제시에 대한 GNAT 4.9.2). 그러나 I/O 호출은 "잠재적으로 차단"되어 보호 된 작업 내에서 불법임을 알고 있어야합니다. –
아니요, 다른 컴퓨터에서도 계속 작동합니다. 그리고 그것은 더 이상해진다. 이것이 표준적인 방법을 살펴보면, GNAT.Bounded_Buffers (본문에 거의 동일한 코드가 있음)를 인스턴스화하고 삽입 및 제거 (코드에 넣고 가져옴)가 매달려 더 빨리 중단됩니다. 이 : –