01:02
kjp left
01:03
kjp joined
01:04
kjp left
01:05
kjp joined
|
|||
simon_sibl | how can I get self to be rw in a method ? | 05:53 | |
method prepend($self is rw: $item --> LList) { * } | 06:05 | ||
I dont understand this syntax | |||
why I cant add a , after the is rw and why I need to add : instead ? | |||
librasteve | stuff before the ‘:’ in the Signature applies to the method invocant | 06:22 | |
08:12
dakkar joined
|
|||
lizmat | in core, this is usually written as: method foo(\SELF:) .... | 08:15 | |
so that "self" is the ro copy of the invocant, and SELF is the actual invocant (whether that can be written to or not) | |||
librasteve | .oO - that's interesting - I guess not copying is a perf improvement - not sure I understand why the default is to make a copy (but there are many things I do not understand!) | 08:17 | |
[my guess is that ro copy of all args is the default for all Routines and that Methods retain this pattern for the invocant also by default ... and that ro copy is kind of the traditional stackframe thing] | 08:20 | ||
simon_sibl | I was wondering, with async using react and supply, how can I be sure it wont spawn a thread ? so that I dont need to worry about race condition | 08:41 | |
could use a channel to be sure if not sure | 08:43 | ||
because here without any start it shows multiple $*THREAD ID... | 09:08 | ||
cdn.discordapp.com/attachments/768...1c14f& | |||
(also not sure why doing pick(**) here doesnt work making an unlimited supply) | |||
added a whenever in the supply block and it works now 🙏 | 09:55 | ||
I would guess that the code happening in the whenever is locked and cannot happen at the same time as another one (without adding a start or a thread spawn function) | 09:59 | ||
lizmat | from the doc: Please note that one should keep the code inside the whenever as small as possible, as only one whenever block will be executed at any time. One can use a start block inside the whenever block to run longer running code. | 10:02 | |
docs.raku.org/syntax/whenever | |||
simon_sibl | ah thank you, as much as I find this confusing, is it whenever within the same react, because for example, I have a whenever in my supply block that I use in my react block, the rule still apply I guess ? | 10:05 | |
my $sup = supply { ... whenever ... }; react { ... whenever $sup { ... } ...}; | 10:06 | ||
lizmat | the thing you need to know is that "whenever" is really executed only once: it adds the block to the outer react / supply logic | 10:07 | |
and that react / supply logic is then responsible for handling the events coming in and executing the correct associated block | 10:08 | ||
so it *looks* like the whenever is being executed each time, but in fact it is only the block that is getting called at the right time | 10:09 | ||
hope that makes sense :) | |||
simon_sibl | ah makes a lot of sense, I am just curious because sometimes the $*THREAD.id is different, which seems like multiple thread are taking care of what only 1 thread should take care of | 10:10 | |
lizmat | it gets handed to whatever thread is available at the time | 10:11 | |
simon_sibl | actually I even tried changing RAKUDO_MAX_THREADS to 1 (and 2) and it didnt work, the minimum required seemed to be 3 | ||
but isnt async supposed to be handled only within 1 thread ? | |||
lizmat | you cannot expect code to be running on the same thread all of the time | ||
simon_sibl | I mean, in C with poll, its always the same thread right ? | ||
lizmat | the only thing you can rely on, is that only *one* whenever block inside of a react / supply is run at the same time | 10:12 | |
simon_sibl | so even if different thread take care of the whenever, I can count on that to be sure there wont be any race condition | ||
lizmat | so e.g. you *can* update a hash that is visible inside 2 whenevers, because only one of them will be able to make changes at a time | ||
right | |||
that's the whole USP of "whenever" :-) | 10:13 | ||
simon_sibl | okay perfect, a bit obscure why the multiple thread even in a single thread program but okay xD | ||
lizmat | well, there's always a thread that runs spesh and the optimizer | ||
simon_sibl | right sometimes I forget raku isnt a ahead of time compiler | 10:15 | |
and that there is a GC and all that | |||
lizmat | if you want to get an idea of e.g. the inlines that were tried / succeeded, run your code with -MSIL | ||
simon_sibl | ah indeed interesting | 10:18 | |
I dont understand all the output but that looks useful | |||
lizmat | the best speed optimizations you get when the bytecode is small enough to get inlined | 10:19 | |
simon_sibl | I am still in the honey moon of how "simple" async/parallelism is easy to make in Raku (still not sure about concurrency) | 10:20 | |
10:24
lizmat left,
guifa_ joined,
lizmat joined,
guifa left
|
|||
lizmat | :-) | 10:24 | |
simon_sibl | start is parallelism in Raku ? not sure which keywords does concurrency, starts seems to be involved in many examples | 10:26 | |
lizmat | m: say "before"; my $a = start { sleep 1; say "done in start" }; say "after"; await $a | 10:27 | |
camelia | before after done in start |
||
lizmat | so, yes :-) | ||
simon_sibl | I mean, if I have multiple start block, will they be executed in parallel or concurrently ? (sorry if I missed your example) | 10:30 | |
lizmat | they will be executed concurrently as long as there are free threads available to execute them | 10:32 | |
basically, "start" schedules the block to be executed by threads in the thread pool | |||
and returns a Promise that will be kept if successfully completed, or will be broken on an execution error inside the block | 10:33 | ||
simon_sibl | if its a thread pool, isnt it parallel then ? 🥹 just wanna understand if they will execute at the same same time or if they will share execution (one at a time but each a little by little) | 10:38 | |
(for example goroutines in Go are concurrent, not parallel) | 10:50 | ||
lizmat | each block will in principle run on the same thread (in parallel with other blocks in other threads) until it executes code that may relinquish the thread to the thread pool | 10:51 | |
one of such is executing an "await" | |||
so, if you run let's say 5 start blocks, and none of them does an "await", then they will all have their own thread until completion | 10:52 | ||
(in parallel) | |||
m: my int $a; await (^10).map( { start { ++$a for ^1000000 } } ); say $a | 10:54 | ||
camelia | 5801158 | ||
lizmat | note that that number should ideally be 10000000 if the increments wouldn't have trampled on each other | 10:55 | |
note that if you make than an atomic int and use atomic increment, it works: | 10:57 | ||
m: my atomicint $a; await (^10).map( { start { ++⚛$a for ^1000000 } } ); say $a | |||
camelia | 10000000 | ||
lizmat | alternate approach using inside thread logic, and summing in the end: | 11:00 | |
m: my @p = (^10).map( { start { my int $a; ++$a for ^1000000; $a } } ); await @p; say sum @p>>.result | |||
camelia | 10000000 | ||
simon_sibl | in your first message you mean threadpool or thread ? I thought start would start a new thread each time ? | 11:10 | |
sorry I am just confused xD | 11:11 | ||
I think I am confused also because it seems Raku is doing locking before printing to stdout | 11:14 | ||
because otherwise the output should be messed up at some point if threads write at the same time |