使用 Raku 并发的简单、可停止的计时器

p6s*_*eve 8 concurrency raku

我一直在努力解决 Promises、Supplies 和其他并发功能,但我找不到一种简单的方法来完成我想要的事情。

我的目标是做这样的事情:

class Timer {
    has $.promise;
    has $.counter is default(0);

    method start {
        $!promise = Promise.new;

        loop {
            $!counter++;
            self.show;
        }
    }   

    method stop {
        $!promise.break;
    }   

    method reset {
        $!counter = Nil;
        self.show;
    }

    method show {
        say "timer: $!counter";
    }   
}

my Timer $t .= new;
$t.start;
$t.stop;
$t.reset;
Run Code Online (Sandbox Code Playgroud)

当然,这是行不通的,因为循环将运行到无穷大,并且我们永远不会继续到 $t.stop。

那么,您能否建议我如何将 Raku 并发性纳入考虑范围,以实现我想要的效果?

Eli*_*sen 9

这将是我的基础Timer课。它需要一个:display参数,该参数必须是Callable进行显示。

请注意,start控制语句用于启动并发。在它内部,只有一个循环调用显示逻辑,直到循环条件变为假。您可以通过调用该.stop方法来完成此操作。

class Timer {
    has &.display is required;
    has Bool $!running;

    method start(Timer:D: --> Nil) {
        $!running = True;
        start {
            &!display() while $!running;
        }
    }

    method stop(Timer:D: --> Nil) {
        $!running = False;
    }
}

sub display() {
    state $count;
    print (++$count).fmt('%6d') ~ "\b" x 6;
}

my $timer = Timer.new(:&display);

$timer.start;

sleep 5;

$timer.stop;
Run Code Online (Sandbox Code Playgroud)

  • 啊 - 谢谢@lizmat - 这正是我所设想的......我想要一个 1 秒的刻度,这样我就可以在显示子中放入 ```sleep 1;``` 。不要问我为什么我不能从 raku 并发文档中组装它,因为这几乎就是他们所说的......! (2认同)