Я плохо знаком с Erlang и пытаюсь программировать программу проблемы с ограниченным буфером. Это почти работает, за исключением проверки, что производители не добираются слишком далеко впереди и перезаписывают неиспользованные данные. Для обработки этого я решил попытаться поместить защиту на свой буфер () функция так, чтобы у меня могла быть версия w/o, получают используемый, когда буфер полон, версия w/o отправляют используемый, когда буфер пуст, и нормальная версия для остальной части времени.
Моя проблема состоит в том, что защита для версии получателя меньше требует, чтобы я знал размер массива, представляющего буфер, который требует вызова к array:size/1
. По-видимому, Erlang не позволяет вызовы функции в защите, который препятствует тому, чтобы это работало. Там некоторый путь состоит в том, чтобы работать вокруг этого, не изменяя объявление функции для моего буферного агента?
%% buffer: array num num
%% A process that holds the shared buffer for the producers and consumers
buffer(Buf, NextWrite, NextRead) when NextWrite == NextRead ->
io:format(" * ~w, ~w, ~w~n", [array:to_list(Buf), NextRead, NextWrite]),
receive
{enqueue, Reply_Pid, Num} ->
io:format("~w: > ~w~n", [Reply_Pid, Num]),
buffer(array:set(NextWrite rem array:size(Buf), Num, Buf), NextWrite + 1, NextRead);
finish ->
io:format("finished printing~n")
end;
buffer(Buf, NextWrite, NextRead) when (NextWrite - NextRead) == array:size(Buf) ->
io:format(" * ~w, ~w, ~w~n", [array:to_list(Buf), NextRead, NextWrite]),
receive
{dequeue, Reply_Pid} ->
io:format("~w: < ~w~n", [Reply_Pid, array:get(NextRead rem array:size(Buf), Buf)]),
Reply_Pid ! {reply, array:get(NextRead rem array:size(Buf), Buf)},
buffer(Buf, NextWrite, NextRead + 1);
finish ->
io:format("finished printing~n")
end;
buffer(Buf, NextWrite, NextRead) ->
io:format(" * ~w, ~w, ~w~n", [array:to_list(Buf), NextRead, NextWrite]),
receive
{dequeue, Reply_Pid} ->
io:format("~w: < ~w~n", [Reply_Pid, array:get(NextRead rem array:size(Buf), Buf)]),
Reply_Pid ! {reply, array:get(NextRead rem array:size(Buf), Buf)},
buffer(Buf, NextWrite, NextRead + 1);
{enqueue, Reply_Pid, Num} ->
io:format("~w: > ~w~n", [Reply_Pid, Num]),
buffer(array:set(NextWrite rem array:size(Buf), Num, Buf), NextWrite + 1, NextRead);
finish ->
io:format("finished printing~n")
end.
Есть только определенные функции, которые можно использовать в guard, см. Guard Sequences в руководстве по Erlang. Вы можете легко сделать то, что вам нужно, следующим образом:
buffer(Buf, NextWrite, NextRead) -> buffer(Buf, NextWrite, NextRead, array:size(Buf)).
buffer(Buf, NextWrite, NextRead, _) when NextWrite == NextRead ->
;
buffer(Buf, NextWrite, NextRead, BufSize) when (NextWrite - NextRead) == BufSize ->
;
buffer(Buf, NextWrite, NextRead, _) ->
.