1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
{---------------------------------------------------------------
Thoughts on closing of windows.
Goals:
o All windows should be closed on program termination (including
IOErrors, heap overflow, etc) - otherwise there's no way to clean
things up before the next run.
o It should always be possible to quit (by hitting ctrl-C or whatever).
There are three aspects to window closing - the program explicitly
closing windows by calling closeWindow; the user explicitly closing
windows by clicking on the closeWindow button; and implicitly closing
them when the window closes.
Whatever solution is adopted ought to carry over to similar sitations
involving open files, etc.
(We also need to do somthing about registering the window class!)
Explicit window closing:
o Cannot be avoided (eg we can't use the GC system to do this) because
it has a user-visible effect. (The same goes for file closing, etc.)
o We have to keep track of whether the window has been closed or not
because the underlying window system will object to trying to perform
any window operations on a closed window. This raises a number of issues:
o Window closing has to be an atomic action - we can't let two threads
close windows at once.
newtype WindowHandle = Window (MVar WindowState)
o Performing operations on closed windows ought to raise an IOError.
(Blocking the thread or just skipping the operation would also
work - but seem wrong.)
o After the last window is closed, we will never need any more events
so the eventloop should terminate.
This is essential on Windows because ctrl-C doesn't abort calls to
GetNextEvent- so we tend to get stuck in unbreakable loops :-(
o Requires a global count of all currently open windows.
(Or run an eventloop for every open window - but window systems
encourage the "one event loop per process" approach so it may not
be possible.)
User level window closing:
o It might be possible to eliminate this possibility by trapping closeWindow
requests? (But can we trap all such requests?)
o If window ops on closed windows raises an IOError (or whatever), we need a
way to test whether a window has been closed or not.
(We might well want to add this test anyway even if we can eliminate
this form of closing - but it wouldn't be essential - just convenient.)
o We might want to be able to wait for a window to be closed.
(Several threads might want to wait on the same window - so a raw MVar
would be the wrong thing...)
Implicit window closing:
o Implementations:
o Foreign object pointers can be used to deallocate objects when
windows become unreachable.
o Space leaks might prevent some windows from being closed.
o We cannot control order in which windows are deallocated.
o Deallocation executes C code - but doesn't call Haskell code.
o No need to maintain explicit list of open windows since the GC
system does this anyway.
o Add a general purpose "onExit" mechanism to let us specify code to
be executed when exection terminates:
o Does "termination" include hitting ctrl-C, stack/heap overflow,
hitting bottom (error/pattern match failure), IOError, etc?
o If so, what do we do if error occurs inside onExit code?
o If we implement "onExit" mechanism in Haskell, we need to
add some error catching primitives.
o Need a global mutable variable to maintain list of open windows.
(We can test this in the event loop too...)
o Order of evaluation of onExit code must be specified carefully
(not hard) or left deliberately unspecified.
o Close windows at end of call to runGraphics:
o Same issues as with onExit (should we catch errors, how do we
catch errors, need to maintain list of open windows).
o What happens if program runs "runGraphics" multiple times in
one program:
o do
runGraphics (openWindow ...)
runGraphics ...
o do
w <- runGraphics (openWindow ..)
runGraphics (closeWindow w)
Can be caught be using the runST polymorphism trick.
o do
wr <- newRef ...
runGraphics (do
w <- openWindow ...
putRef wr w
)
runGraphics (do
w <- getRef wr
closeWindow ...
)
Cannot be caught by runST polymorphism trick.
o runGraphics (runGraphics ...)
---------------------------------------------------------------}
|