io: getline (Prompt) в порожденном процессе: Prompt не отображается - PullRequest
0 голосов
/ 02 февраля 2019

Вот код:

-module(my).
-compile(export_all).

test() ->
    register(go, spawn(my, init, []) ).

init() ->
    Reply = io:get_line("enter:"),
    io:format("Reply= ~s~n", [Reply]).

В оболочке:

~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3  (abort with ^G)

1> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}

2> my:test().
true 

3>    

Если я добавлю timer:sleep() здесь:

test() ->
    register(go, spawn(my, init, []) ).

init() ->
    timer:sleep(1000),  %%<<<==========HERE
    Reply = io:get_line("enter:"),
    io:format("Reply= ~s~n", [Reply]).

и запуститеновый код в оболочке, затем через 1 секунду приглашение оболочки 3> в выводе первого примера внезапно исчезает и заменяется на enter::

~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3  (abort with ^G)

1> c(my).    
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}

2> my:test().
true
enter:

И если я что-то ввожу, то, как и ожидалось, ясм. Reply= xx.

Если переместить timer:sleep() сюда:

test() ->
    register(go, spawn(my, init, []) ),
    timer:sleep(1000).  %%<<======HERE

init() ->
    Reply = io:get_line("enter:"),
    io:format("Reply= ~s~n", [Reply]).

и запустить код в оболочке, я вижу:

~/erlang_programs$ erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3  (abort with ^G)

1> c(my).    
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}

2> my:test().
enter:

затем enter: внезапно исчезает и заменяется на ok:

1> c(my).    
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}

2> my:test().
ok    

3>    

Этот работает , как и ожидалось:

1> Reply = io:get_line("enter: ").
enter: hello
"hello\n"

2> Reply.
"hello\n"

3> 

Может кто-нибудь объяснить, какая расаусловие происходит в первом примере?

1 Ответ

0 голосов
/ 05 февраля 2019

На самом деле это не совсем гонка.Проблема возникает из-за того, что у нас есть только один поток std_in, и его может использовать только один процесс в данный момент времени.

1) В первом фрагменте кода процесс 'go' получает управление над std_in с помощью функции get_line / 1.,Но после этого функция test / 0 возвращается в оболочку Erlang, и оболочка получает управление под std_in (оболочка Erlang ожидает ввода данных пользователем с приглашением типа «>»).Так что процесс 'go' теперь не связан с std_in и не получает никаких символов от std_in.Все входные данные отправляются в оболочку Erlang.

2) Второй фрагмент имеет функцию sleep / 1 в init / 1.Так что ситуация обратная.Мы позволяем оболочке Erlang достичь ожидания ввода и ПОСЛЕ того, как выполняется get_line / 1 в процессе 'go'.Так что теперь процесс 'go' получает контроль над std_in и получает символы с клавиатуры.Но после того, как процесс 'go' завершается, оболочка Erlang восстанавливает свое состояние.

3) Третий фрагмент - только 1-й, но усугубляет ситуацию с функцией сна / 1.

4) Ничего не объясняет четвертый фрагмент.Он работает как ожидалось.

5) Чтобы проиллюстрировать эту точку зрения, вы можете запустить следующий код:

-module(my).
-compile(export_all).

test() ->
    spawn_link(my, init1, []),
    spawn_link(my, init2, []).

init1() ->
    timer:sleep(100),
    init(0, "0").

init2() ->
    timer:sleep(100),
    init(0, "1").

init(N, Title) ->
%    io:format(">>init(~p)~n", [N]),
    Reply = io:get_line(Title ++ "> enter:"),
    io:format("[~s] (e - exit) Reply= ~s", [Title, Reply]),
    case Reply of
      "e\n" -> ok;
      _ -> init(N+1, Title)
    end.

Модуль запускает два процесса с get_line / 1.Но только один процесс может кроме ввода от std_in в последнее время:

50> my:test().
<0.192.0>
1> enter:w
[1] (e - exit) Reply= w
1> enter:d
[1] (e - exit) Reply= d
1> enter:e
[1] (e - exit) Reply= e
0> enter:dd
[0] (e - exit) Reply= dd
0> enter:e
[0] (e - exit) Reply= e
51> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...