Re: Can't quit from Dock or cmd-Q
Re: Can't quit from Dock or cmd-Q
- Subject: Re: Can't quit from Dock or cmd-Q
- From: has <email@hidden>
- Date: Fri, 25 Oct 2002 14:10:53 +0100
Paul Berkowitz <wrote:
>
> 'Quit' is polite and civilised [...]
>
> You want it to finish that work first, and only _then_ shut down in an
>
> organised fashion.
>
>
But all that can be taken care of in a 'quit' handler.
Perhaps sometimes it can. More likely is that it "sort of can" ... if you
don't mind a bit of chaos and mess. Almost certain, though, is that "it can
all be taken care of in quit" is not the Right Thing to do. Such sweeping
statements are potentially dangerous and misleading.
Welcome to the grand game of "You are NOT the Boss of Me."
-------
A PARABLE
Say hello to the routine juggleBalls(). [1]
At any time he is keeping a dozen balls up in the air, and he is an expert
at this. In his entire career, he has never, ever dropped a single one. You
can _absolutely_ trust him to look after your balls. [2]
Anyway... one day juggleBalls() is doing his thing [3] when quit() walks
into the room. Seeing juggleBalls() working away ignoring him, quit() is
enraged:
"How dare you keep on working in MY presence! Don't you know I am the
BOSS of you all?!? Stop everything THIS INSTANT!!!"
So saying, quit() grabs juggleBalls() by the neck and throws him out the
door. An instant later, all the balls which were, till that point, up in
the air, crash to floor. Fortunately for quit(), some of them were made of
harmless rubber, so land without any real damage. Others, however, were
made of extremely valuable, delicate glass, and smash themselves to
smithereens.
At this point, quit() grabs dustpan and brush and hurriedly sweeps the
shattered glass under the edge of the rug in the hope that nobody will find
out what's happened here.
...
Yet all this chaos and disaster could have been avoided if quit() had
simply _asked_ juggleBalls() [who is the expert in ball-juggling, after
all] to catch all the balls and put them down safely before leaving the
room at his earliest convenience.
Moral: This game is ALL about cooperation between friends, and there is NO
room for martinets.
The End
-------
>
In fact the quit handler does intercept the termination signal [...]
>
and allows me to do all the cleaning up necessary. but
>
then it just continues on, as you say.
It should _not_ be the quit handler's responsibility to do the cleaning up
for _others_; i.e. it's not quit's place to grab somebody else's balls [3]
out of the air and stash them. It's quit's job to go up to anyone currently
working and _politely ask_ them to finish up what they're doing and return
control to the system.
I realise this explanation is all in pretty abstract terms, but you're
getting into "Real Design" territory here. You've got to understand WHY
things are done a certain way before you'll know WHAT to implement and HOW.
--
>
My clunky workaround, which you will hate but i am grateful for
Don't be so quick to make such assumptions...
>
was to set a global variable in the quit
>
handler, let the current loop iteration finish (what choice is there?) and
>
then save the database and error number -128 at the top of the next loop
>
iteration if the global variable has been reset. Works pretty well - just a
>
few seconds delay and no mess.
You've _almost_ got it.
In an event-driven OO system (e.g. a GUI app), you'd probably do it all via
messaging: dispatching a finishUpNow() message that's passed from active
component [object] to active component so that they all shut down in an
ordered fashion.
In a batch-processing procedural system (as yours presumably is), you've
got the right idea: have a global finishUpNow flag that active components
[subroutines] periodically poll during their normal operation. If that flag
changes to true, each component should finish up at its earliest
convenience and return control to its caller. (Not every subroutine needs
to poll finishUpNow, of course, just the main ones which drive the system.)
======================================================================
-------
--FLAGS
global _stop
-------
--MAIN ROUTINES
on doSubProcess()
beep
end doProcess
on doProcess()
repeat 10 times -- cannot be interrupted; must be allowed to complete
doSubProcess()
end repeat
end doProcess
on main()
repeat until _stop -- safe to stop at any time
doProcess()
end repeat
end main
-------
--EVENTS
on run
set _stop to false
main()
end run
on quit
set _stop to true
continue quit
end quit
======================================================================
The one criticism I'd make with your particular implementation is the same
one I mentioned in my previous footnote: you're using errors to do normal
flow control, which is a bit of a dodgy practice. Use errors to signify
"Things That Have Gone Wrong". Since 'quit' is a _normal_ operation it
doesn't really fall into this category, so using errors (through expediency
or oversight) isn't really appropriate. [4]
But the main thing is shifting your mindset to something more open and
flexible. Think about your system more as a collection of cooperating
components, each with its own set of tasks and responsibilities to perform,
than in one-dimensional, Literal "Do Step 1, Step 2, Step 3, Step 4..."
terms.
This is why I tasked you for the "you'll hate this clunky workaround"
comment, as what you're trying to do is neither clunky nor a workaround,
nor do I somehow "hate it on principle". It's [primarily(?)] your
_assumptions_ that were flawed. [5][6][7]
-----
BTW, I _do_ recommend finding out if non stay-open apps are supposed to
show a Quit menu option in OS X or not. It might be a deliberate design
change, or it might be an accidental slip-up. As has been noted with other
"features", it's unwise to depend on something that might in fact be a bug,
so if it's not documented then assume it's non-friendly until confirmed one
way or the other by an AS engineer. (<sigh> Do miss seeing Chris N around
these parts...)
HTH
has
--
[1][2][3] NO!!! And don't you even THINK of it, you damn dirty Freudians. ;p
[4] If I were the designer of AppleScript, I'd make it generate a
screeching-crashing-smashing sound effect each time an error was raised.
That would rapidly motivate scripters not to throw errors without
justifiable cause. :)
[5] Or, as I keep saying: "Assumptions Baaaad." :)
[6] I think if you look outside the narrow confines of the AS world, you'll
find that much of what you think is new and of your own invention was long
ago discovered and documented by others, and its merits/awfulness copiously
analysed and recorded. (e.g. I'm talking largely out of my own learning on
OOD and event-driven systems which I've got from reading books, websites,
etc; I've not come across an exact discussion of your particular problem,
but based on what I do know I'm pretty confident I'm talking sense. People
who know more are welcome to put me right if I've errored anywhere.)
[7] I _would_ criticise your handiwork if I thought you were using Quit for
the _wrong purpose_ (i.e. as an emergency stop, which is User-Cancelled's
[aka Cmd-period] job, not Quit's). But without any information on what your
system actually does or why you want to use Quit this way, I'm not in a
position to comment. [7a]
[7a] It does seem a little unusual for a batch-processing system to want to
use Quit, but that doesn't rule out the possibility of a valid use for the
thing.
--
http://www.barple.pwp.blueyonder.co.uk -- The Little Page of AppleScripts
_______________________________________________
applescript-users mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/applescript-users
Do not post admin requests to the list. They will be ignored.