Re: Threads and Progress Monitors

2003-05-31 Thread Dulcimer

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

2003-05-31 Thread Dave Whipp
"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)

2003-05-31 Thread Dulcimer
> >   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)

2003-05-31 Thread Dave Whipp
"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)

2003-05-31 Thread Dulcimer

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

2003-05-31 Thread Dave Whipp

"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.