4
4158

Асинхронный ввод/вывод в Coro::Handle

ivanych
2016-01-27 14:38 обн. 2016-01-27 17:04

Пытаюсь разобраться с Coro::Handle.

Нужно параллельно/асинхронно читать два файла.

Вот минимальный проблемный код:

#!/usr/bin/perl

use strict;
use warnings;

use Coro;
use Coro::Handle;

my $coro_1 = async {

    open my $fh, '<', "/etc/passwd" or die "$!";

    $fh = unblock $fh;

    for ( 1 .. 2 ) {
        print "coro_1 start\n";

        my $result = $fh->readline();

        print "coro_1 finish: " . length($result) . "\n";
    }
};

my $coro_2 = async {

    open my $fh, '<', "/etc/passwd" or die "$!";

    $fh = unblock $fh;

    for ( 1 .. 2 ) {
        print "                     coro_2 start\n";

        my $result = $fh->readline();

        print "                     coro_2 finish: " . length($result) . "\n";
    }
};

$coro_1->join;
$coro_2->join;

print "END\n";

Здесь создаются два треда, в каждом построчно читается файл. Я понимаю так - при каждом вызове readline управление должно передаваться в другой тред. Соответственно, работать треды должны поочередно.

Но у меня сначала отрабатывает один тред, потом другой. Т.е. такое ощущение, что readline блокируется и не передает управление в другой тред.

Вот вывод:

coro_1 start
coro_1 finish: 32
coro_1 start
coro_1 finish: 48
                     coro_2 start
                     coro_2 finish: 32
                     coro_2 start
                     coro_2 finish: 48
END

Хорошо видно, что сначала отработал первый тред (левая колонка), потом второй тред (правая колонка).

А вот как должно бы быть (если я ничего не напутал):

coro_1 start
                     coro_2 start
coro_1 finish: 32
coro_1 start
                     coro_2 finish: 32
                     coro_2 start
coro_1 finish: 48
                     coro_2 finish: 48
END

Почему у меня работает не параллельно/асинхронно? Что я упустил?

  • dart
    2016-01-28 10:15 #

    Coro реализует "волокна" - волокна, в отличие от процессов выполняются последовательно, а не параллельно. Переключение между ними происходит только если нужно подождать ввод или вывод. В данном примере ждать ничего не нужно - /etc/passwd будет читаться всегда и без задержек.

    или CTRL+Enter формат
  • qsimpleq
    2016-03-04 09:17 обн. 2016-03-04 09:41 #

    dart всё правильно написал, сам при знакомстве наелся с этим. Проклятые корутины :).

    Правда очень здорово оказалось использовать при мониторинге сети, где в полную мощь вся эта дурня себя показала. Правда теперь не понятно, будет ли Марк адаптировать Coro под новые версии perl, что меня напрягает адово, т.к. грядёт ubuntu 16.04 на сервера, а с ней и perl 5.22.

    #########

    Для такой задачи можно посмотреть на MCE, и сразу же пример

    Сам об этой штуке узнал с неделю назад, и, таки, интересно выглядит, но сам ещё не копался.

    или CTRL+Enter формат
  • py2h
    2016-12-12 20:33 #

    Чтобы было так, как вы ожидали, нужно было вставить cede в блок for.

    или CTRL+Enter формат
Чтобы ответить, залогиньтесь или зарегистрируйтесь.
  • @user
  • _italic_

    italic

  • **bold**

    bold

  • [PP](http://pragmaticperl.com)

    PP

  • <http://pragmaticperl.com>

    http://pragmaticperl.com

  • module:Plack

    Plack

  • release:URI

    URI

  • author:VTI

    VTI

  • `my $foo = 'bar'`
  • ```
    my $multi;
    $line;
    ```