Re: Timers (was Threads and Progress Monitors)
"Dulcimer" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] > I find C too terse, and would > rather see a more verbose version I'm obviously more lazy than you ;-). > Ah. Ok, but if that's the case, you could as easily write it > >timeout(5) { coro { ... } }; > > and have the compiler build it accordingly. The same logic works either > way from that end. Given that its a macro, its probably true that I could do some up-front manipulation like that. But its a lot more work than launching a thread. However, given that it is a macro, we could eliminate the outer-curlies. Lets see if I know how to write a macro... macro timeout is parsed( rx:w/ $secs:= $code_type := ( thread | coro )? $code := /) { $code_type eq "thread" and $code = "{ thread $code }"; "my \$$(Perl.tmpvarname) = Timer.new(secs=>$secs, code=>$code);" } timeout(60) coro { ... } timeout(60) thread { ... } timeout(60) { ... } # default is coro Even if it works, I have a feeling that the macro has plenty of scope for improvement. > > Now here's another semantics question: would we want the following to > > be valid? > > > > sub slow > > { > >timeout(60) { return undef but "Error: timed out" }; > >return slow_imp; > > } > > Dunnoreturns from a single routing that are in different threads > could produce some real headaches. > > > How about: > > > > sub slow { > >timeout(60) { > > throw TimeoutException.new("Error: slow_fn timed out") > >}; > >return slow_imp; > > } > > I like thata lot better, but I'm still not sure how it would fly. Actually, I think that both have pretty-much the same problems. I assume @Dan could work out a way to get the mechanics to work (basically a mugging: we kill a thread/coro and steal its continuation point). But the semantics of the cleanup could cause a world of pain. But realistically, a common use of a timeout is to kill something that's been going on too long. I suppose we could require some level of cooperation the the "dead" code. Dave.
Re: Timers (was Threads and Progress Monitors)
--- Dave Whipp <[EMAIL PROTECTED]> wrote: > "Dulcimer" <[EMAIL PROTECTED]> wrote > > > But exposing the object like that still bothers be: I shouldn't > > > need the $tmp, nor the .new. > > > > I'm not so sure I agree with losing the new(). I kinda like that > > just for readability. Less isn't always more. :) > > > > Ok, how about this: > > > > sub slow_fn { > > temp &_.timer is last { .stop } = new Timer ( > >secs => 1, code => { .reset += print "." } > > ); > > return slow_fn_imp @_; > > } > > Wrong semantics: First, you're assuming that .reset is an attribute, > rather than a command (Yes, I believe the command/query separation, > where possible). Ok. And that leads to the next thing -- > Second, My intention was that if C ever fails (e.g. broken > pipe), then I'd stop resetting the timer. Your program meerly stops > incrementing the timeout. Agreed. > Even if we assume that the "temp &_.prop" thing works, I'm not sure > I'd want it littering my code. I could see it being used in a macro > defn though. Maybe. It isn't pretty, but I've seen worse. Hell, I've posted worse. :) > > Dunno -- I see what you're doing, but it's a little *too* helpful. > > I'd rather see a few more of the engine parts on this one. > > We can expose a few more parts by having the macro return the timer > object, so you could write: > > my $timer = timeout(60) { ... }; Ok, poorly phrased on my part. I just meant I'd like to visually see more of what's going on in the code. In other words, I'm not fond of the syntax proposal. I find C too terse, and would rather see a more verbose version. Merely a style issue, though. Still, your response to what it *looked* like I meant is a good idea, too. > > > A semantic question: what output would you expect for this: > > > > > > sub silly { > > >timeout(5) { print ".HERE."; sleep 4; print ".THERE." }; > > >for 1..5 -> $count { sleep 2; print "$count" }; > > > } > > > possible answers are > > >12.HERE.34.THERE.5 > > > or > > >12.HERE..THERE.345 > > > I'm thinking probably the latter, because its easier to launch a > > > thread in the codeblock than to un-launch it. > > > > un-launch? If they're threaded, aren't they running asynchronously? > > I see 12.HERE.34.THERE.5 as the interleaved output. I have no idea > > what you mean by "un-launch", sorry. > > Sorry, it was my feeble attempt at humor. lol -- and I was too dense to get it. :) > What I was getting at is that, if we assume the codeblock executes > asa coroutine, then you'd get the latter output. If you wanted a > thread, you could write: > > timeout(5) { thread { ... } }; > > but if we assume that the codeblock is launched as an asynchronous > thread, then there is no possible way the coerce it back into the > coroutine (i.e. to "un-launch" it). Ah. Ok, but if that's the case, you could as easily write it timeout(5) { coro { ... } }; and have the compiler build it accordingly. The same logic works either way from that end. Thread seem more sensible for a timeout, but as a general rule I'd probably prefer to see implicit coro's rather than implicit threads as the default. > Now here's another semantics question: would we want the following to > be valid? > > sub slow > { >timeout(60) { return undef but "Error: timed out" }; >return @slow_imp; > } Dunnoreturns from a single routing that are in different threads could produce some real headaches. > How about: > > sub slow { >timeout(60) { > throw TimeoutException.new("Error: slow_fn timed out") >}; >return @slow_imp; > } I like thata lot better, but I'm still not sure how it would fly. (Sorry for the reformat, btw -- got pretty cramped on my screen.) __ Do you Yahoo!? Yahoo! Calendar - Free online calendar with sync to Outlook(TM). http://calendar.yahoo.com
Re: Timers (was Threads and Progress Monitors)
"Dulcimer" <[EMAIL PROTECTED]> wrote > > But exposing the object like that still bothers be: I shouldn't need > > the $tmp, nor the .new. > > I'm not so sure I agree with losing the new(). I kinda like that just > for readability. Less isn't always more. :) > > Ok, how about this: > > sub slow_fn { > temp &_.timer is last { .stop } = new Timer ( >secs => 1, code => { .reset += print "." } > ); > return slow_fn_imp @_; > } Wrong semantics: First, you're assuming that .reset is an attribute, rather than a command (Yes, I believe the command/query separation, where possible). Second, My intention was that if C ever fails (e.g. broken pipe), then I'd stop resetting the timer. Your program meerly stops incrementing the timeout. Even if we assume that the "temp &_.prop" thing works, I'm not sure I'd want it littering my code. I could see it being used in a macro defn though. > Dunno -- I see what you're doing, but it's a little *too* helpful. > I'd rather see a few more of the engine parts on this one. We can expose a few more parts by having the macro return the timer object, so you could write: my $timer = timeout(60) { ... }; > > A semantic question: what output would you expect for this: > > > > sub silly { > >timeout(5) { print ".HERE."; sleep 4; print ".THERE." }; > >for 1..5 -> $count { sleep 2; print "$count" }; > > } > > possible answers are > >12.HERE.34.THERE.5 > > or > >12.HERE..THERE.345 > > I'm thinking probably the latter, because its easier to launch a > > thread in the codeblock than to un-launch it. > > un-launch? If they're threaded, aren't they running asynchronously? > I see 12.HERE.34.THERE.5 as the interleaved output. I have no idea what > you mean by "un-launch", sorry. Sorry, it was my feeble attempt at humor. What I was getting at is that, if we assume the codeblock executes asa coroutine, then you'd get the latter output. If you wanted a thread, you could write: timeout(5) { thread { ... } }; but if we assume that the codeblock is launched as an asynchronous thread, then there is no possible way the coerce it back into the coroutine (i.e. to "un-launch" it). Now here's another semantics question: would we want the following to be valid? sub slow { timeout(60) { return undef but "Error: timed out" }; return @slow_imp; } How about: sub slow { timeout(60) { throw TimeoutException.new("Error: slow_fn timed out") }; return @slow_imp; } Dave.
Re: Timers (was Threads and Progress Monitors)
> > sub slow_fn { > > my $pause = 1; > > my $timer is last { .stop } = new Timer secs => $pause++, > >reset => {$pause++}, > > code => {print "."}; > > return slow_fn_imp @_; > > } > > I'm thinking there's a way to avoid the $pause variable: > > sub slow_fn > { > my $tmp = new Timer( > secs=>1, code => { print "." and .reset(.count+1) }); > return slow_fn_imp @_; > } > > But exposing the object like that still bothers be: I shouldn't need > the $tmp, nor the .new. I'm not so sure I agree with losing the new(). I kinda like that just for readability. Less isn't always more. :) Ok, how about this: sub slow_fn { temp &_.timer is last { .stop } = new Timer ( secs => 1, code => { .reset += print "." } ); return slow_fn_imp @_; } That's only superficially different, but is a little more aesthetically satisfying, somehow. Then again, I'm a perverse bastard, lol... :) On the other hand, if this threads, does each call to slow_fn() get a unique &_, or did I just completely hose the whole process? Could I say my temp &_.timer is last { .stop } = new Timer ( ... ); # ? or is it even necessary with temp? > When someone writes the Std::Timer module, we can > add a macro to it such that: > > sub slow_fn > { > timeout(1) { print "." and .reset(.count+1) }; > return slow_fn_imp @_; > } Dunno -- I see what you're doing, but it's a little *too* helpful. I'd rather see a few more of the engine parts on this one. > I think the implementation is obvious, given the previous example of > the inline code. Though s/timeout/???/. alarm? trigger(), maybe? > A semantic question: what output would you expect for this: > > sub silly { >timeout(5) { print ".HERE."; sleep 4; print ".THERE." }; >for 1..5 -> $count { sleep 2; print "$count" }; > } > possible answers are >12.HERE.34.THERE.5 > or >12.HERE..THERE.345 > I'm thinking probably the latter, because its easier to launch a > thread in the codeblock than to un-launch it. un-launch? If they're threaded, aren't they running asynchronously? I see 12.HERE.34.THERE.5 as the interleaved output. I have no idea what you mean by "un-launch", sorry. > > As a sidenote, although it would actually reduce readability > > here, I'm still trying to wrap my brain thoroughly around the > > new dynamics of $_. Would this work correctly maybe? > > > > sub slow_fn { > > my $timer is last { .stop } = new Timer secs => $_=1, > >reset => {$_++}, > > code => {print "."}; > > return slow_fn_imp @_; > > } > > > > Isn't that $_ proprietary to slow_fn such that it *would* work? > > I had to stare at it for a few moments, but yes: I think it should > work (if we define a .reset attribute that accepts a codeblock). lol -- I was assuming we'd have to make reset accept codeblocks, and yes, I'd expect you to have to stare a bit. It's ugly, and I'd rather create a new variable that do this, tho we've seen that you don't need to. __ Do you Yahoo!? Yahoo! Calendar - Free online calendar with sync to Outlook(TM). http://calendar.yahoo.com
Timers (was Threads and Progress Monitors)
"Dulcimer" <[EMAIL PROTECTED]> wrote > so that the timer goes off after a second, prints a dot, and resets > itself to go off again after another second? And I still like the idea > of an expanding temporal window between dots: > > sub slow_fn { > my $pause = 1; > my $timer is last { .stop } = new Timer secs => $pause++, >reset => {$pause++}, > code => {print "."}; > return slow_fn_imp @_; > } I'm thinking there's a way to avoid the $pause variable: sub slow_fn { my $tmp = new Timer( secs=>1, code => { print "." and .reset(.count+1) }); return slow_fn_imp @_; } But exposing the object like that still bothers be: I shouldn't need the $tmp, nor the .new. When someone writes the Std::Timer module, we can add a macro to it such that: sub slow_fn { timeout(1) { print "." and .reset(.count+1) }; return slow_fn_imp @_; } I think the implementation is obvious, given the previous example of the inline code. Though s/timeout/???/. A semantic question: what output would you expect for this: sub silly { timeout(5) { print ".HERE."; sleep 4; print ".THERE." }; for 1..5 -> $count { sleep 2; print "$count" }; } possible answers are 12.HERE.34.THERE.5 or 12.HERE..THERE.345 I'm thinking probably the latter, because its easier to launch a thread in the codeblock than to un-launch it. > As a sidenote, although it would actually reduce readability here, I'm > still trying to wrap my brain thoroughly around the new dynamics of $_. > Would this work correctly maybe? > > sub slow_fn { > my $timer is last { .stop } = new Timer secs => $_=1, >reset => {$_++}, > code => {print "."}; > return slow_fn_imp @_; > } > > Isn't that $_ proprietary to slow_fn such that it *would* work? I had to stare at it for a few moments, but yes: I think it should work (if we define a .reset attribute that accepts a codeblock). Dave.
Re: Threads and Progress Monitors
--- Dave Whipp <[EMAIL PROTECTED]> wrote: > Dulcimer wrote: > >>sub slow_fn { > >> my $tick = Timer.new(60, { print "..." }); > >> return slow_fn_imp @_; > >>} > >> > >>Now if I could just get the compiler to not complain about that > >>unused variable... > > > > > > Maybe I'm being dense > > Why not just > > sub slow_fn { > >Timer.new(1, { print "." }); > >return slow_fn_imp @_; > > } Geez. I read my response this morning, which I wrote just before going to bed, and realized that I must've been dead on my feet. > The problem is that I want the timer to last for the duration of the > slow_fn_imp. If I don't assign it to a variable, then it may be GCed > at any time. I was making several assumptions which don't hold, apparently, such as that the underlying Timer would iterate until stopped. Not an ideal default, lol I thopught the point was to have the function print dots repeatedly, tho? > I've just realised, however, that I'm relying on it being destroyed > on leaving the scope. I'm not sure that the GC guarentees that. > I might need > >sub slow_fn { > my $timer is last { .stop } = Timer.new(60, { print "." }); > return slow_fn_imp @_; >} > > but that's starting to get cluttered again. I don't really consider that "clutter". It's clear and to the point, and Does What You Want. How about sub slow_fn { my $timer is last { .stop } = new Timer secs => 1, reset => 1, code => {print "."}; return slow_fn_imp @_; } so that the timer goes off after a second, prints a dot, and resets itself to go off again after another second? And I still like the idea of an expanding temporal window between dots: sub slow_fn { my $pause = 1; my $timer is last { .stop } = new Timer secs => $pause++, reset => {$pause++}, code => {print "."}; return slow_fn_imp @_; } As a sidenote, although it would actually reduce readability here, I'm still trying to wrap my brain thoroughly around the new dynamics of $_. Would this work correctly maybe? sub slow_fn { my $timer is last { .stop } = new Timer secs => $_=1, reset => {$_++}, code => {print "."}; return slow_fn_imp @_; } Isn't that $_ proprietary to slow_fn such that it *would* work? __ Do you Yahoo!? Yahoo! Calendar - Free online calendar with sync to Outlook(TM). http://calendar.yahoo.com
Re: Threads and Progress Monitors
Dave Whipp said: > I've just realised, however, that I'm relying on it being destroyed on > leaving the scope. I'm not sure that the GC guarentees that. GC doesn't, but I would be surprised if Perl 6 doesn't and in that case Parrot will be accommodating. Take a look at the recent p6i archives for the gory details. -- Paul Johnson - [EMAIL PROTECTED] http://www.pjcj.net
Re: Threads and Progress Monitors
Dulcimer wrote: sub slow_fn { my $tick = Timer.new(60, { print "..." }); return slow_fn_imp @_; } Now if I could just get the compiler to not complain about that unused variable... Maybe I'm being dense Why not just sub slow_fn { Timer.new(1, { print "." }); return slow_fn_imp @_; } The problem is that I want the timer to last for the duration of the slow_fn_imp. If I don't assign it to a variable, then it may be GCed at any time. I've just realised, however, that I'm relying on it being destroyed on leaving the scope. I'm not sure that the GC guarentees that. I might need sub slow_fn { my $timer is last { .stop } = Timer.new(60, { print "." }); return slow_fn_imp @_; } but that's starting to get cluttered again. Dave.
Re: Threads and Progress Monitors
> sub slow_fn { >my $tick = Timer.new(60, { print "..." }); >return slow_fn_imp @_; > } > > Now if I could just get the compiler to not complain about that > unused variable... Maybe I'm being dense Why not just sub slow_fn { Timer.new(1, { print "." }); return slow_fn_imp @_; } or maybe even sub slow_fn { my $tick = 1; Timer.new({$tick++}, { print "." }); return slow_fn_imp @_; } For a slowly slowing timer ? Or to my taste, sub slow_fn { Timer.new(60, { print "..." }); return slow_fn_imp @_; } __ Do you Yahoo!? Yahoo! Calendar - Free online calendar with sync to Outlook(TM). http://calendar.yahoo.com
Re: Threads and Progress Monitors
"Luke Palmer" <[EMAIL PROTECTED]> wrote in message news:[EMAIL PROTECTED] > my $result is lazy::threaded := { slow_fn_imp @_ }; > loop { > timeout(60); > return $result; > CATCH { > when Timeout { print "...$(time)\n" > } > } > > Now write the C function :-P. Well, the obvious is { temp %SIG{ALRM} = { print "..."; alarm(60) } alarm(60); LAST {alarm(0) }; return $result; } Needless to say, I don't like that. But the good thing now is that I don't need the loop. Now, if we had some form of Parrot-level signaling (instead of OS-level); and if we had resumable exceptions; then perhaps I'd be able to write sub slow_fn { my $tick = Timer.new(60); CATCH { when $tick => { print "..."; continue } } return slow_fn_imp @_ ; } I think this hides the threads pretty effectively. Is a parrot-level timer to much to ask for? How about resumable exceptions? But perhaps I'm still being too clever, when a simpler solution exists: sub slow_fn { my $tick = Timer.new(60, { print "..." }); return slow_fn_imp @_; } Now if I could just get the compiler to not complain about that unused variable... Dave.
Re: Threads and Progress Monitors
On Thursday, May 29, 2003, at 04:48 PM, Luke Palmer wrote: To nitpick: my $result is lazy::threaded := { slow_fn_imp @_ }; Pursuing this lazy-threaded variables notion, a question. Given: sub slow_func is threaded {# me likey this auto-parallelizing syntax! ... } Would we want to say that _both_ of these have the lazy-blocking behavior? my $result := slow_func(); print $result; my $result = slow_func(); print $result; Or would the first one block at C, but the second block immediately at the C<=>? The obvious answer is that the := binding "passes through" the lazyness, but the = assignment doesn't. But I wonder if that isn't a bit too obscure, to put it mildly. MikeL
Re: Threads and Progress Monitors
On Thursday, May 29, 2003, at 12:45 PM, Dave Whipp wrote: "Michael Lazzaro" <[EMAIL PROTECTED]> wrote in> # But if you want to get the thread object, so you can monitor it's { ... my $tid = thread &slow_func_impl(...); while $tid.active { status_monitor($tid.progress); sleep 60; } return $tid.result; } To my eye, that looks pretty darn slick. You might be a bit frustrated if the &slow_func_impl took 61 seconds :-(. How do we interrupt the C? Possibly in the same way as we'd timeout a blocking IO operations. Personally, I'd be happy with just making the C a smaller number, like one second, or a fifth of a second, or whatever. You want the status_monitor to be updated no more often than it needs to be, but often enough that it's not lagging. But if you really wanted wake-immediately-upon-end, I'd add that as a variant of C. For example, you might want a variant that blocked until a given variable "changed", just like in debuggers; that would allow: { my $tid = thread &slow_func_impl(...); while $tid.active { status_monitor($tid.progress); sleep( 60, watch => \($tid.progress) ); # do you even need the '\'? } return $tid.result; } ... which would sleep 60 seconds, or until the .progress attribute changed, whichever came first. You could make more builtins for that, but I think I'd like them to just be C or C variants. Obvious possibilities: sleep 60; # sleep 60 seconds sleep( block => $tid ); # sleep until given thread is complete sleep( watch => \$var ); # sleep until given var changes value sleep( 60, block => $tid, watch => [\$var1, \$var2, \$var3] ); five tests $tid.sleep(...);# sleep the given thread, instead of this one MikeL
Re: Threads and Progress Monitors
Dave wrote: > Still a bit too complex for my taste: perhaps we can use C to > generate exceptions: > > my lazy::threaded $result := { slow_fn_imp @_ }; > loop { > timeout(60); > return $result; > CATCH Timeout { print "...$(time)\n" } > } > > At last, no C! (Reminder: the suggested semantics of the threaded > variable were that a FETCH to it blocks until the result of the thread is > available). To nitpick: my $result is lazy::threaded := { slow_fn_imp @_ }; Because lazy::threaded isn't the I type, it's the I type. loop { timeout(60); return $result; CATCH { when Timeout { print "...$(time)\n" } } Because C is like C. I like that elegant use of threaded variables, by the way. Now write the C function :-P. Luke
Re: Threads and Progress Monitors
"John Macdonald" <[EMAIL PROTECTED]> wrote > At first glance, this doesn't need a thread - a > Instead of > sleep, though, I'd use a pipeline and read it with > a non-blocking read until there is no data. ... ++ For the lateral thinking. Definitely a valid solution to the problem, as given. So I'll change the problem prevent it: the slow fn is a 3rd-party blob with no access to source code and no progress indication. sub slow_fn { print "starting slow operation: this sometimes takes half an hour!\n"; my $tid = thread { slow_fn_imp @_ }; $start = time; loop { wait $tid | timeout(60); return $tid.result if $tid.done; print "... $(time-$start) seconds\n"; } } Still a bit too complex for my taste: perhaps we can use C to generate exceptions: my lazy::threaded $result := { slow_fn_imp @_ }; loop { timeout(60); return $result; CATCH Timeout { print "...$(time)\n" } } At last, no C! (Reminder: the suggested semantics of the threaded variable were that a FETCH to it blocks until the result of the thread is available). Dave.
Re: Threads and Progress Monitors
On Thu, May 29, 2003 at 10:47:35AM -0700, Dave Whipp wrote: > OK, we've beaten the producer/consumer thread/coro model to death. Here's a > different use of threads: how simple can we make this in P6: > > sub slow_func > { > my $percent_done = 0; > my $tid = thread { slow_func_imp( \$percent_done ) }; > thread { status_monitor($percent_done) and sleep 60 until > $tid.done }; > return wait $tid; > } At first glance, this doesn't need a thread - a coroutine is sufficient. Resume the status update coroutine whenever there has been some progress. It doesn't wait and poll a status variable, it just let the slow function work at its own speed without interruption until there is a reason to change the display. In fact, it probably doesn't need to be a coroutine either. A subroutine - display_status( $percent ) - should't require any code state to maintain, just a bit if data so all it needs is a closure or an object. At second glance, there is a reason for a higher powered solution. If updating the display to a new status takes a significant amount of time, especially I/O time, it would both block the slow function unnecessarily and would update for every percent point change. Using a separate process or thread allows the function to proceed without blocking, and allows the next update to jmp ahead to the current actual level, skipping all of the levels that occurred while the previous display was happening. Instead of sleep, though, I'd use a pipeline and read it with a non-blocking read until there is no data. Then, if the status has changed since the last update, do a display update and repeat the non-blocking read. If the status has not changed, do a blocking read to wait for the next status change.
Re: Threads and Progress Monitors
"Michael Lazzaro" <[EMAIL PROTECTED]> wrote in> # But if you want to get the thread object, so you can monitor it's > { > ... > my $tid = thread &slow_func_impl(...); > while $tid.active { > status_monitor($tid.progress); > sleep 60; > } > return $tid.result; > } > > To my eye, that looks pretty darn slick. You might be a bit frustrated if the &slow_func_impl took 61 seconds :-(. How do we interrupt the C? Possibly in the same way as we'd timeout a blocking IO operations. But I wonder if this could work: my $tid = thread &slow_func_impl(...); until wait $tid, timeout=>60 { status_monitor($tid.progress); } return $tid.result; Here I assume that C returns a true value if its waited condition occurs, but false if it times out. Hmm, A few days ago I tried indroducing a syntax for thread with a sensitivity list in place of an explict loop-forever thread. Perhaps I can reuse that syntax: my $tid = thread &slow_func_impl(...); thread $tid | timeout(60) { when $tid => { return $tid.result } default => { status_monitor $tid.progress } } Perhaps a different keyword would be better: C as the looping counterpart to C -- then extend C to accept a code block. Dave.
Re: Threads and Progress Monitors
On Thursday, May 29, 2003, at 10:47 AM, Dave Whipp wrote: OK, we've beaten the producer/consumer thread/coro model to death. Here's a different use of threads: how simple can we make this in P6: Hey, good example. Hmm... Well, for starters I think it wouldn't be a big deal to associate a "progress" attribute with each thread object. It should be that thread's responsibility to fill it out, if it wants to -- so you shouldn't ever have to pass \$percent_done as an argument, it should be a basic attribute of every thread instance. That might encourage people to add progress calculations to their threads after-the-fact, without changing the basic interface of what they wrote. I'll also claim that I would still prefer the auto-parallel, auto-lazy-blocking behavior on the thread results we've mused about previously. So coming from the semantics end, I'd love to see it written like this: # Declaring a threaded calculation sub slow_func_impl is threaded { while (...stuff...) { ... do stuff ... &_.thread.progress += 10.0; # or however you want to guesstimate[*] this } return $result; } # If you don't care about getting the actual thread object, just the result, # call it this way: { ... my $result = slow_func_impl(...); ... return $result; } # But if you want to get the thread object, so you can monitor it's progress, # call it this way: { ... my $tid = thread &slow_func_impl(...); while $tid.active { status_monitor($tid.progress); sleep 60; } return $tid.result; } To my eye, that looks pretty darn slick. MikeL [*] Huh. Imagine my surprise to find out that my spellcheck considers "guesstimate" to be a real word. And I always thought that was just a spasmostical pseudolexomangloid.
Re: Threads and Progress Monitors
--- Dave Whipp <[EMAIL PROTECTED]> wrote: > OK, we've beaten the producer/consumer thread/coro model to death. > Here's a > different use of threads: how simple can we make this in P6: > > sub slow_func > { > my $percent_done = 0; > my $tid = thread { slow_func_imp( \$percent_done ) }; > thread { status_monitor($percent_done) and sleep 60 until > $tid.done }; > return wait $tid; > } > > I think this would work under Austin's A17; but it feels a bit > clunky. The > fact that the "sleep 60" isn't broken as soon as the function is done > is > untidy, though I wouldn't want to start killing thread. > > perhaps: > > { > ... > $tid = thread { slow... } > status_monitor(\$percent_done) and wait(60 | $tid) until > $tid.done; > return $tid.result; > } > > The thing is, that "wait 60" probably can't work -- replace C<60> > with > C<$period>, and the semantics change. There are some obvious hacks > that > could work here: but is there a really nice solution. Ideally, we > won't need > the low level details such as C<$tid> sub slow_func_imp { my $pct_done = 0; ... yield $pct_done++; # Per my recent message ... } sub slow_func { my $tid := thread &slow_func_imp; status_monitor($tid.resume) while $tid.active; }
Threads and Progress Monitors
OK, we've beaten the producer/consumer thread/coro model to death. Here's a different use of threads: how simple can we make this in P6: sub slow_func { my $percent_done = 0; my $tid = thread { slow_func_imp( \$percent_done ) }; thread { status_monitor($percent_done) and sleep 60 until $tid.done }; return wait $tid; } I think this would work under Austin's A17; but it feels a bit clunky. The fact that the "sleep 60" isn't broken as soon as the function is done is untidy, though I wouldn't want to start killing thread. perhaps: { ... $tid = thread { slow... } status_monitor(\$percent_done) and wait(60 | $tid) until $tid.done; return $tid.result; } The thing is, that "wait 60" probably can't work -- replace C<60> with C<$period>, and the semantics change. There are some obvious hacks that could work here: but is there a really nice solution. Ideally, we won't need the low level details such as C<$tid> Dave.