Unordered
Raku doesn't have an ordered message queue. It has an unordered list of things that needs doing.
# schedule them to run at the same second
# just to make it more likely that they will be out of order
my $wait = now + 1;
my @run;
for 1..20 -> $n {
push @run, Promise.at($wait).then: {say $n}
}
await @run;
That could print the numbers in any order.
1
2
3
4
5
6
7
8
11
12
13
14
15
16
17
18
9
10
19
20
Raku is actually multi-threaded. If you give it enough work, it will use all of your cpu cores.
That means that there can never be a way to say run this after everything currently in the queue finishes.
Even if I just used start
, it could sometimes run things out of order.
my @run;
for 1..20 -> $n {
push @run, start {say $n}
};
await @run;
You could run that hundreds of times before it starts printing things out of order, but it will do so eventually.
Even if you went low-level and used $*SCHEDULER.cue
, there is no guarantee that it will run after everything else.
my @nums;
for 1..100 -> $n {
$*SCHEDULER.cue: {push @nums, $n; say $n}
}
say @nums;
Not only may it run out of order, the @nums
array probably won't have all of the values because each thread may clobber what another thread is doing.
Under the hood, the Promise methods that schedule something to run eventually calls $*SCHEDULER.cue
in some fashion.
Schedule off something else
You can tell Raku to run your code after something else.
my $p = Promise.in(1);
my $p2 = $p.then: {say 'first'}
my $p3 = $p.then: {say 'second'}
react {
whenever start say('first') {
whenever start say('second') {
}
}
}
You need to have a reference to that thing though.
Slow
If Raku did have a way to run things after the currently scheduled events, then it would have to keep track of what is running and make sure that your code doesn't run until after they have finished.
my $a = start {
# pointless busy-work that takes two seconds
my $wait = now + 2;
my $n = 0;
while now ≤ $wait {
$n++
}
say $n; # make sure the loop doesn't get optimized away
say 'first';
}
my $b = start say 'second';
await $a, $b;
second
1427387
first
If that made sure that $b
ran after $a
, then no work would be done on $b
for two whole seconds.
Instead it just causes $b
to run on another thread because the one that is dealing with $a
is currently busy.
That is a good thing, because what if $b
was also slow. We would be scheduling two slow things to run in sequence instead of in parallel.
Javascript
I think that the only reason it currently works in Javascript is because it doesn't appear to take advantage of multiple cpu cores. Or it has something like a GIL.
I've written Raku code that has had my 4 core CPU at 500% utilization. (Intel hyperthreaded cpu, where one core appears to be 2 cores)
I'm not sure you can do same with a single Javascript program.