comp.lang.ada
 help / color / mirror / Atom feed
* weird block on Get from basic protected bounded buffer with 2 tasks
@ 2017-12-12 19:08 George Shapovalov
  2017-12-12 20:18 ` Jeffrey R. Carter
  2017-12-12 21:16 ` Dmitry A. Kazakov
  0 siblings, 2 replies; 6+ messages in thread
From: George Shapovalov @ 2017-12-12 19:08 UTC (permalink / raw)


Hi guys,

Sorry if this is a trivial issue, but I can't seem to find any (RM) rules regulating this or mentions of similar issues on Google..

This is a very basic protected bounded buffer in Ada, pretty much the text-book example. (This is a part of a bigger thing, but I simplified code down to bare minimum, where it reproduced the behavior). Don't mind the modular type for counters please, I tried using a range (just as in GNAT.Bounded_buffer) or going without Counter. The indices are not a culprit here, all ways to count them behave identically..

It seems to work just fine if I have 1 task feeding it and the "main" body is reading from it. But it blocks on the 1st Get if I use 2 tasks - Putter and Getter, just as below.

with Ada.Text_IO;use Ada.Text_IO;
procedure test_buffer is

    maxItems : constant := 10;
    type Index is mod maxItems;
    maxCount : constant Index := Index(maxItems - 1);
    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 Count < maxCount and Buffer.Get'Count = 0 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 Count > 0 is
        begin
            X := buf(First);
            First := First + 1;
            Count := Count - 1;
            Put_Line("Get X="&X'Img & "; First="&First'Img&", Last="&Last'Img&", Count="&Count'Img);
        end;
    end;

    task Putter;
    task body Putter is
    begin
        Put_Line("Putter started");
        for i in 0 ..25 loop
            Put_Line("putting i="&i'Img);
            Buffer.Put(i);
        end loop;
    end;

    task Getter;
    task body Getter is
        X : Integer;
    begin
        Put_Line("Getter started");
        loop
            Put_Line("getting 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;
    abort Getter;
end test_buffer;


The output it gives me looks like this:
$ ./test_buffer 
Getter started
getting X..
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
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

Sometimes it manages to read one or two items before blocking (thenn more are pushed in correspondingly):
$ ./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
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
Getter started
getting X..
Put X= 7; First= 0, Last= 7, Count= 7
Put X= 8; First= 0, Last= 8, Count= 8
Get X= 0; First= 1, Last= 9, Count= 8
,  got X= 0
getting X..
Get X= 1; First= 2, Last= 9, Count= 7
,  got X= 1
getting X..
Put X= 9; First= 2, Last= 9, Count= 7
Put X= 10; First= 2, Last= 0, Count= 8
Get X= 2; First= 3, Last= 1, Count= 8
Put X= 11; First= 3, Last= 1, Count= 8
^C

I was suspecting issues with the barrier (thus that 'Count check in there just for the heck of it - I thought might be prioritizing Gets would make it behave, but its exactly the same without using 'Count in when). However I cannot seem to find any rule that would stall the barrier on Get (2nd task is external to the protected object, so no, its not the no reevaluation on internal calls of protected object). Oh, and if I move comments around, to execute Gets in the loop in the main part (whether I comment out or leave Getter running in parallel), then it seems to work Ok..

So, what gives? Am I missing something here or is this a bug?

The used platform: Gentoo Linux, gnat-gpl-2017, gcc-6.3.0

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-12-13  9:25 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-12 19:08 weird block on Get from basic protected bounded buffer with 2 tasks George Shapovalov
2017-12-12 20:18 ` Jeffrey R. Carter
2017-12-12 20:55   ` George Shapovalov
2017-12-12 21:01     ` George Shapovalov
2017-12-12 21:16 ` Dmitry A. Kazakov
2017-12-13  9:25   ` George Shapovalov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox