Re: [MacPerl-Toolbox] A difficulty with Mac-Events.pm

[email protected] (Alan Fry) Fri, 6 Apr 2001 12:42:02 +0100
Newsgroups perl.macperl.toolbox
Message-ID <p05010401b6f34ab38d93@[158.152.146.73]>
At 9:52 am +0200 05/04/01, Matthias Neeracher wrote:

>In article <p05010400b6ef3fcf9e7a@[158.152.146.73]>, Alan Fry 
><[email protected]> writes:
>
>>  However in the case of the script involving the browser the problem
>>  does not seem to arise during the BEGIN sequence but later on as the
>  > script runs. For instance the script 'hangs' at the lines:
>
>Ah! Now that rings a bell (I haven't actually done much toolbox Perl
>programming in a long time, so your first post didn't trigger much). Now,
>though, I seem to remember that the issue is that the inclusion of
>Mac::Events is the trigger for switching MacPerl from implicit event handling
>(MacPerl does it for you) to explicit event handling (MacPerl avoids handling
>events unless you call WaitNextEvent explicitly).

Many thanks for the explanation. I suspected something of the kind might be up.

In the application proposed a MacWindow would be used running 
alongside a browser window keeping a log of what was happening as the 
Perl scrip unfolded.

The first problem is to find a way of keeping both the browser window 
and the MacPerl window alive to 'mouseDown' (and possibly other) 
events in their regions. A way of doing this is to interleave the 
window's 'WaitNextEvent' with the browser's 'listen'.

In the particular application the browser's package is of the general 
form while(1) {[do stuff]} so we write in the 'while(1)' loop:

     while ( 1 ) {
         my $connection;
         while (!$connection) {
             $connection = $socket->accept;  # has a 'x' second timeout
             $gui->pause;                    # has a 10 ticks timer
             $gui->{win}->redraw             # to be sure the window updates
         }                                   # $gui == reference to 
window object

         if ($connection) {
             ..... [program runs logging happenings] .....
         }
     }

and in the MacWindow package:

     sub pause {
         my ($ref) = @_;
         my $ticks = TickCount() + 10;
         while(TickCount() < $ticks){ WaitNextEvent }
     }

This has the effect that the program cycles endlessly round listening 
for browser requests (for 'x' seconds) and looking for mouse clicks 
for (say) 10 ticks. If the socket timer is based on the four-element 
select() (which it is in IO::Socket) values of x shorter than 1 
second are possible. Even with 1 second the arrangement feels 
reasonably 'comfortable'.

Mouse events and browser requests are not lost if the program is away 
at the time so to speak, since it seems both will queue up.

The second problem is more obscure, but it seems that opportunistic 
events (I suspect 'idle' events) occurring while the browser is 
composing a long (say 30K+) page will cut the connection. If that 
happens an incomplete page is the usual result. Netscape and MS 
InternetExplorer behave differently; sad to say IE gives a more 
graceful performance.

That can be avoided by a timer loop giving adequate time for the page 
to be composed along the lines:

     my $del = int length($html)/250;             # determine delay time
     print $connection $html;                     # download the page $html
     my $tim = TickCount() + $del;
     while (TickCount() < $tim) {WaitNextEvent};  # give browser time

In this example the allowance is set to 250 bytes per 'tick' which 
seems (so far as one can tell visually) to give about a 25% safety 
margin on this machine at least.

I suppose to be portable between Macs of various ages and speeds some 
enquiries ought to made from 'gestalt' to determine the appropriate 
allowance. It would be much nicer if one could get from the browser a 
'finished writing' signal but I don't know how to do this if indeed 
it is possible.

Quite how this timer loop functions is shrouded in mystery, but it 
does seem to be reliable.

>I'm sorry if this is inconveniencing you, but I seem to remember that this
>seemed like the only reasonable way to reconcile the needs of plain perl
>scripts with the needs of fancy tooplbox clients.

I'm sure you're right and it is pretty much a 'force majeure'. It 
poses some interesting questions however for MacWindows used in these 
kind of circumstances. Similar difficulties arise using MacWindows 
for 'progress bar' applications for instance.

The 'interleaving' trick might be useful more widely than just the 
special case of a browser logging window so I hope this rather 
overlong message might be of some general interest.

Alan Fry