Arhn - архитектура программирования

Как заставить gen_server ответить сообщением?

У меня есть gen_server, показанный ниже. Это работает по большей части. Однако, когда я запускаю его из оболочки, ответы возвращаются прямо в приглашение оболочки. Я бы ожидал, что они будут отправлены в виде сообщений обратно в pid оболочки, а затем я бы использовал flush(), чтобы увидеть их.

Что мне нужно изменить, чтобы foo_worker отправлял свои ответы в виде сообщений?

-module(foo_worker).
-behaviour(gen_server).

%% API
-export([start_link/1, start/1, init/1, send/3, die/1]).
-export([handle_call/3, handle_cast/2, handle_info/2, terminate/2]).

%%%-------------------------------------------------------------------

send(Worker, Ref, Counter) ->
  gen_server:call(Worker, {inc, Ref, Counter}).

die(Worker) ->
  gen_server:cast(Worker, die).

%%%-------------------------------------------------------------------

start_link(Limit) ->
  gen_server:start_link(?MODULE, [Limit], []).

start(Limit) ->
  gen_server:start(?MODULE, [Limit], []).

init([Limit]) ->
  {ok, Limit}.

handle_call(_, _, Limit) when Limit =< 0 ->
  exit({worker, eol});
handle_call({inc, Ref, Data}, From, Limit) ->
  io:format("From ~p~n", [From]),
  {reply, {Ref, updated, Data+1}, Limit - 1}.

handle_cast(die, _) ->
  io:format("~p Dying ~n",[self()]),
  exit(normal).

handle_info(Info, State) ->
  io:format("Unkown message ~p for state ~p~n", [Info, State]).

terminate(Reason, State) ->
  io:format("~p Died because ~p with state ~p~n", [self(), Reason, State]).
23.05.2015

Ответы:


1

Весь смысл gen_server:call/2,3 заключается в том, чтобы обернуть в вызов функции передачу сообщения в процесс gen_server и получение его ответа. Если вы хотите иметь дело только с сообщениями, не используйте gen_server:call/2,3, а пусть вызывающая сторона вызывает gen_server:cast/2 и включает pid вызывающей стороны в сообщение:

send(Worker, Ref, Counter) ->
    gen_server:cast(Worker, {inc, Ref, Counter, self()}).

Затем попросите gen_server:handle_cast/2 понять это сообщение и использовать pid, чтобы отправить ответ вызывающему абоненту:

handle_cast({inc, Ref, Data, From}, Limit) ->
    From ! {Ref, updated, Data+1},
    {noreply, Limit-1}.

Кстати, обратите внимание, что когда вы выбираете такой подход, вам нужно иметь дело с возможным сбоем. Если вы передаете сообщение процессу gen_server, но оно умирает до того, как отправит вам ответ, вам нужно убедиться, что вызывающая сторона не сидит и ждет вечно ответа, который никогда не придет. Лучше всего это сделать с помощью монитора, который вы можете вызывающая сторона контролирует процесс gen_server перед отправкой ему сообщения и демонитор как только он получит ответ. Если процесс gen_server умирает, вызывающая сторона вместо этого получит сообщение DOWN (см. monitor документацию для получения подробной информации). Также обратите внимание, что, делая это, вы повторно реализуете то, что gen_server:call/2,3 уже делает за вас.

23.05.2015
  • Спасибо, это было очень полезно. Меня смущает тот факт, что я пытаюсь заставить два gen_servers общаться друг с другом. Я не могу понять, как заставить работать обмен сообщениями туда и обратно, если они оба ждут в цикле gen_server. 24.05.2015
  • Функция gen_server:handle_info/2 обрабатывает прием обычных сообщений. Вы можете отправлять сообщения из него или из одной из других gen_server функций обратного вызова. 24.05.2015
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..