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
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: 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
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)
--- 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 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.