IF NOT empty(S) THEN decrement(S) ELSE suspend_current_task_on(S)
IF any_task_is_suspended_on(S) THEN
unsuspend_one_task_suspended_on(S)
ELSE
increment(S)
b: buffer(1..N); t: integer:=0; -- the number of items in buffer b
process producer i:element; repeat produce (i); p(free_space_in_buffer); p(mutual_exclusion); append i to buffer b; -- modifies t, b v(mutual_exclusion); v(item_in_buffer); forever
process consumer j:element; repeat p(item_in_buffer); p(mutual_exclusion); remove item from buffer into j; -- modifies t, b v(mutual_exclusion) v(free_space_in_buffer); consume(j); forever
TASK buffer_handler IS ENTRY append(item:element); ENTRY remove(item:OUT element); END;
TASK BODY buffer_handler IS
n: CONSTANT integer := 20;
contents: ARRAY (1..n) OF element;
cur_in, cur_out: integer RANGE 1..n:=1;
tot: integer RANGE 0..n:=0;
BEGIN
LOOP
SELECT
WHEN tot<n =>
ACCEPT append(item: IN element) DO
contents(cur_in) := item;
cur_in := (cur_in MOD n) + 1;
tot := tot + 1;
END;
OR
WHEN tot > 0 =>
ACCEPT remove(item: OUT integer) DO
item := contents(cur_out);
cur_out := (cur_out MOD N) + 1;
tot := tot - 1;
END;
END SELECT;
END LOOP;
END buffer_handler;