File: Loader.pm

package info (click to toggle)
libanyevent-xspromises-perl 0.005-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 320 kB
  • sloc: perl: 96; makefile: 3
file content (70 lines) | stat: -rw-r--r-- 2,066 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package AnyEvent::XSPromises::Loader;
use 5.010;
use strict;
use warnings;

our $VERSION = '0.005';

use AnyEvent;

require XSLoader;
XSLoader::load('AnyEvent::XSPromises', $VERSION);

AnyEvent::XSPromises::___set_conversion_helper(sub {
    my $promise= shift;
    my $deferred= AnyEvent::XSPromises::deferred();
    my $called;
    eval {
        $promise->then(sub {
            return if $called++;
            $deferred->resolve(@_);
        }, sub {
            return if $called++;
            $deferred->reject(@_);
        });
        1;
    } or do {
        my $error= $@;
        if (!$called++) {
            $deferred->reject($error);
        }
    };
    return $deferred->promise;
});

# We do not use AE::postpone, because it sets a timer of 0 seconds. While that sounds great in
# theory, the underlying libraries (eg. epoll, used by EV) don't support 0 second timers, and
# so they get passed 1ms instead. To avoid actually waiting a millisecond every time, we write
# data onto a socket read by the event loop. Of course, these sockets need to be carefully managed
# in case the code does a fork, so we need to frequently check $$.
my ($AE_PID, $AE_WATCH, $PIPE_IN, $PIPE_OUT);
BEGIN { $AE_PID= -1; }

sub ___notify_callback {
    if ($$ != $AE_PID) {
        ___reset_pipe();
    } else {
        sysread $PIPE_IN, my $read_buf, 16;
    }

    # sort makes perl push a pseudo-block on the stack that prevents callback code from using
    # next/last/redo. Without it, an accidental invocation of one of those could cause serious
    # problems. We have to assign it to @useless_variable or Perl thinks our code is a no-op
    # and optimizes it away.
    my @useless_variable= sort { AnyEvent::XSPromises::___flush(); 0 } 1, 2;
}

sub ___reset_pipe {
    close $PIPE_IN if $PIPE_IN;
    close $PIPE_OUT if $PIPE_OUT;
    pipe($PIPE_IN, $PIPE_OUT);
    $AE_WATCH= AE::io($PIPE_IN, 0, \&___notify_callback);
    $AE_PID= $$;
}

AnyEvent::XSPromises::___set_backend(sub {
    ___reset_pipe() if $$ != $AE_PID;
    syswrite $PIPE_OUT, "\0";
});

1;