4
4296

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

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

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

x
 
1
#!/usr/bin/perl
2
3
use strict;
4
use warnings;
5
6
use Coro;
7
use Coro::Handle;
8
9
my $coro_1 = async {
10
11
    open my $fh, '<', "/etc/passwd" or die "$!";
12
13
    $fh = unblock $fh;
14
15
    for ( 1 .. 2 ) {
16
        print "coro_1 start\n";
17
18
        my $result = $fh->readline();
19
20
        print "coro_1 finish: " . length($result) . "\n";
21
    }
22
};
23
24
my $coro_2 = async {
25
26
    open my $fh, '<', "/etc/passwd" or die "$!";
27
28
    $fh = unblock $fh;
29
30
    for ( 1 .. 2 ) {
31
        print "                     coro_2 start\n";
32
33
        my $result = $fh->readline();
34
35
        print "                     coro_2 finish: " . length($result) . "\n";
36
    }
37
};
38
39
$coro_1->join;
40
$coro_2->join;
41
42
print "END\n";

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

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

Вот вывод:

9
 
1
coro_1 start
2
coro_1 finish: 32
3
coro_1 start
4
coro_1 finish: 48
5
                     coro_2 start
6
                     coro_2 finish: 32
7
                     coro_2 start
8
                     coro_2 finish: 48
9
END

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

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

9
 
1
coro_1 start
2
                     coro_2 start
3
coro_1 finish: 32
4
coro_1 start
5
                     coro_2 finish: 32
6
                     coro_2 start
7
coro_1 finish: 48
8
                     coro_2 finish: 48
9
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;
    ```