代码之家  ›  专栏  ›  技术社区  ›  chenyf

在Perl 6中,每秒钟打印一次,并且每5秒使用react…睡眠10秒?

  •  12
  • chenyf  · 技术社区  · 6 年前

    我想每秒打印一次当前时间,还想每5秒睡眠10秒:

    react {
        whenever Supply.interval(1) {
            say DateTime.now.posix;
        }
    
        whenever Supply.interval(5) {
            sleep 10;
            say 'Sleep Done';
        }
    
        whenever signal(SIGINT) {
            say "Done.";
            done;
        }
    }
    

    1542371045
    Sleep Done
    1542371055
    Sleep Done
    1542371065
    Sleep Done
    1542371075
    Done.
    ...
    

    我想要的是:

    1542371045
    1542371046
    1542371047
    1542371048
    1542371049 
    Sleep Done
    1542371059
    1542371060
    1542371061  
    1542371062 
    1542371063         
    Sleep Done
    Done.
    

    不太了解 Promise , Supply

    5 回复  |  直到 5 年前
        1
  •  11
  •   Jonathan Worthington    6 年前

    根据具体需要,我可能会这样写:

    react {
        sub sequence() {
            whenever Supply.interval(1).head(5) {
                say DateTime.now.posix;
                LAST whenever Promise.in(10) {
                    say "Sleep done";
                    sequence();
                }
            }
        }
        sequence();
    }   
    

    输出如下:

    1542395158
    1542395159
    1542395160
    1542395161
    1542395162
    Sleep done
    1542395172
    1542395173
    1542395174
    1542395175
    1542395176
    Sleep done
    1542395186
    1542395187
    1542395188
    ...
    

    rotor

    而这 好像它可能是递归的,因为 whenever

    它还完全构建了异步构造,因此在Perl 6.d中不会-如果 react 在线程池上触发-永远阻止一个真正的OS线程。因此,你可以有数千个这样的活动。相比之下 sleep 将阻止一个真正的线程,这是什么 睡觉 传统上,我们希望这样做,但如果处理异步构造,这不是一个很好的选择。

        2
  •  8
  •   Brad Gilbert    6 年前

    react 被封锁了。 他们不会的。

    您还应该尝试将代码放在 whenever 尽可能短的跑步时间。
    (假设它是一个CPU中断处理程序。)
    这条规则可能有一些例外,特别是对于 supply 阻碍。

    使用您提供的结构,这是实现所需的一种方法:

     react {
        # Are we ignoring the interval(1) values?
        my Bool:D $ignore = False;
    
        # The sleeping status of interval(5).
        my Promise:D $sleep .= kept;
    
        whenever Supply.interval(1) {
            # Skip if it is supposed to be blocked.
            next if $ignore;
    
            say DateTime.now.posix;
        }
    
        # First one runs immediately, so skip it.
        whenever Supply.interval(5).skip {
            # Don't run while the “sleep” is pending.
            next unless $sleep.status; # Planned
    
            if $ignore {
                $ignore = False;
                say 'Sleep Done';
            } else {
                $ignore = True;
                # Must be less than the multiple of 5 we want
                # otherwise there may be a race condition.
                $sleep = Promise.in(9);
            }
        }
    
        whenever signal(SIGINT) {
            say "Done.";
            done;
        }
    }
    

    这还不是很清楚。
    .rotor 而是每三次跳过5次间隔?

    react {
        my Bool:D $ignore = True;
    
        # Note that first one runs immediately. (no .skip)
        # We also want it to always be a few milliseconds before
        # the other Supply, so we put it first.
        # (Should have done that with the previous example as well.)
        whenever Supply.interval(5).rotor(1, 1 => 1) {
            $ignore = !$ignore;
        }
    
        whenever Supply.interval(1) {
            next if $ignore;
    
            say DateTime.now.posix;
        }
    
        whenever signal(SIGINT) {
            say "Done.";
            done;
        }
    }
    

    既然这样,为什么不直接使用 .interval(1)

    react {
        whenever Supply.interval(1).rotor(1 xx 4, 1 => 10) {
            say DateTime.now.posix;
        }
    
        whenever signal(SIGINT) {
            say "Done.";
            done;
        }
    }
    

    请注意,我们不能只使用 5 => 10


    注意 .grep 也适用于Supply,所以我们可以用它来检查 $ignored 价值

    react {
        my Bool:D $ignore = True;
    
        whenever Supply.interval(5).rotor(1, 1 => 1) {
            $ignore = !$ignore;
        }
    
        whenever Supply.interval(1).grep({ !$ignore }) {
            say DateTime.now.posix;
        }
    
        whenever signal(SIGINT) {
            say "Done.";
            done;
        }
    }
    
        3
  •  5
  •   jjmerelo    5 年前

    也许这可以奏效:

    loop {
        react {
            whenever Supply.interval(1) {
                say DateTime.now.posix;
            }
    
            whenever Promise.in(5) {
                done;
            }
    
            whenever signal(SIGINT) {
                say "Done.";
                done;
            }
        }
        sleep 10;
    }
    

    输出为:

    1542347961
    1542347962
    1542347963
    1542347964
    1542347965
    1542347976 # <- 10s
    1542347977
    1542347978
    1542347979
    1542347980
    1542347991 # <- 10s
    
        4
  •  4
  •   Scimon Proctor    6 年前

    另一个 睡觉吧)。

    为了达到你想要的效果,我使用了这个方法,它使用了一个1秒的间隔和几个标志。

    react { 
        whenever Supply.interval(1) { 
            state $slept = False;  
            state $count = 0;
            if $count >= 0 { 
                if $slept { 
                    say "Sleep Done"; 
                    $slept = False 
                } 
                say DateTime.now.posix; 
            } 
            $count++; 
            if ( $count == 5 ) { 
                $count = -9; 
                $slept = True
            }
        }
        whenever signal(SIGINT) {
            say "Done.";
            done;
        }
    }
    

    state 变量,因为where块每秒都在它自己的线程中有效执行。状态变量允许我们跟踪当前情况。

        5
  •  2
  •   Elizabeth Mattijsen    6 年前

    只因为 whenever 将在任何时候执行 sleep 睡觉 作为异步作业,通过包装该作业的代码 变成 start

    react {
        whenever Supply.interval(1) {
            say DateTime.now.posix;
        }
    
        whenever Supply.interval(5) {
            start {
                sleep 10;
                say 'Sleep Done';
            }
        }
    
        whenever signal(SIGINT) {
            say "Done.";
            done;
        }
    }
    

    据我所知,这将提供所需的输出。

    推荐文章