Perl6制作一个可观察的计时器

Mik*_*kel 5 concurrency perl6 observer-pattern

我试图使用计时器类编写一个观察者模式,该计时器类以给定的间隔调用其订户.一直试图理解Perl6中的承诺概念.

class Timer does Observable
{
    has Promise $!p;
    has Int $!interval;
    has Bool $!active = False;

    submethod BUILD(Int :$!interval) {}

    method start {
        $!p = Promise.start( {
            $!active = True;
            loop {
                sleep($!interval);
                @!action_listeners>>.actionPerformed(ActionEvent.new);
                if !$!active {$!p.keep}
            }
        });
    }

    method stop {
        $!active = False;
    }
}
Run Code Online (Sandbox Code Playgroud)

Observer角色只是一个包含订阅者的数组.当然,我应该制作一个方法来更新角色中的所有订阅者.

role Observable {
    has ActionListener @!action_listeners;

    method addActionListener(ActionListener $al){
        @!action_listeners.push($al);
    }

    method removeActionListener{
        @!action_listeners.pop;
    }
}
Run Code Online (Sandbox Code Playgroud)

ActionListener角色只有一个actionPerformed方法.ActionEvent类可能不是nessesary,它现在只是一个空类.

role ActionListener
{
    method actionPerformed(ActionEvent $e) { ... }
}
Run Code Online (Sandbox Code Playgroud)

从脚本运行:

my Subscriber $s = Subscriber.new;
my Timer $t = Timer.new(interval => 1);

$t.start;
$t.addActionListener($s);
$t.addActionListener(Subscriber.new);

.... #doing stuff that lasts for a while
$t.stop;
Run Code Online (Sandbox Code Playgroud)

订阅者类实现ActionListener角色(具有名为actionPerformed的方法).

虽然这很好用:调用订阅者的actionPerformed方法,直到我调用计时器的stop方法.虽然没有正确的方法来删除给定的订户.此外,我想知道是否有更好的方法来保持/违反承诺,从外部给出代码循环无限.

我基本上想知道我是否可能错过了Perl6的内置功能?我重新发明轮子了吗?

tim*_*imo 8

要回答更进一步发明轮子的问题:你应该看一下Supply.Supply是Perl 6术语Observable,Tap是Perl 6术语Subscription.

为了获得在常规间隔中调用订阅者的可观察对象,可以使用Supply类型的interval类方法.你会打电话.tap对结果.interval调用注册一个代码块中运行每当Supply emitSA值和结果.tap调用是Tap,你可以关闭与认购对象.

如果您想了解更多有关耗材的信息,Jonathan Worthington的这些谈话幻灯片可能会很有趣.

  • OOC,怎么停止间隔?通过关闭最后一个“水龙头”? (2认同)

Eli*_*sen 6

回答你的问题"我是否重新发明轮子?".有可能.

你实际上可以要求当前ThreadPoolScheduler(又名$*SCHEDULER)提示一段代码以一定间隔运行:

my $canceller = $*SCHEDULER.cue( { say $++ }, every => 0.2 );
sleep 2;
# 0 1 2 3 4 5 6 7 8 9
$canceller.cancel;
say "stopped";  # no numbers should be seen afterward
# stopped    
sleep 1;        # keep from exiting immediately
Run Code Online (Sandbox Code Playgroud)

这不涉及任何问题Promise,所以如果你的目标是了解更多Promises,那么这不是一条路.如果要创建观察者模式,这可能是创建它的最简洁方法.