Author |
Topic: Cascaded ON CLOSE (Read 1403 times) |
|
Michael Hutton
Developer
member is offline


Gender: 
Posts: 248
|
 |
Re: Cascaded ON CLOSE
« Reply #6 on: Jun 22nd, 2010, 10:08am » |
|
I did think of that, as you say, using the RETURN statement with an ON CLOSE would invoke the cleanup of the Library objects potentially creating an error when they are encountered again.
The upshot is to warn the user of the Library not to use a RETURN with the ON CLOSE statement when using the library.
However, I don't see another explicit advantage of jumping straight to the ON CLOSE vectors code rather than sending a WM_CLOSE message to the window, except maybe the length of code. Isn't it six of one and half a dozen of the other?
Michael
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: Cascaded ON CLOSE
« Reply #7 on: Jun 22nd, 2010, 11:40am » |
|
on Jun 22nd, 2010, 10:08am, Michael Hutton wrote:| However, I don't see another explicit advantage of jumping straight to the ON CLOSE vectors code rather than sending a WM_CLOSE message to the window, except maybe the length of code. Isn't it six of one and half a dozen of the other? |
|
Well, I gave you one good reason why jumping to the vector is better: it will result in a 'Not in a subroutine' error if the user has an ON CLOSE RETURN. Issuing an error must be better than relying on the user noticing a warning in the library documentation!
Another thing is that your code has a potential weakness. After you send the WM_CLOSE message, you immediately exit from PROC_MYLIB_Cleanup, and then you execute an END statement:
Code: ON CLOSE PROC_MYLIB_Cleanup : END END disables ON CLOSE altogether, so it's possible the user's handler may never be called, if the END gets executed before the WM_CLOSE message has worked its way through the system.
Admittedly this is an unlikely scenario, because the chances are that the user's ON CLOSE will have been activated (as a result of your WM_CLOSE message) before the interpreter reaches the END statement - but this could easily change if I modified BB4W. For example, one thing I've considered more than once is testing for an 'interrupt' not every statement but (say) every five statements, to reduce the overhead. If I made that change your code would be guaranteed to fail.
Of course you could overcome this problem by following the SYS "SendMessage" with an 'infinite loop', rather than exiting via the ENDPROC to the END statement:
Code: SYS "SendMessage", @hwnd%, WM_CLOSE, 0,0
REPEAT : WAIT 0 : UNTIL FALSE But why use a complicated solution when a simpler, faster, more straightforward one is available?
Richard.
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: Cascaded ON CLOSE
« Reply #8 on: Sep 24th, 2010, 4:32pm » |
|
It's taken a while, but I've finally worked out how to do this elegantly. The technique is described in this Wiki article:
http://bb4w.wikispaces.com/Cascaded+ON+CLOSE+handling
Here's the code of a demo program:
Code: PRINT "Click Close to test cascaded ON CLOSE handling"
PRINT "Press Escape to test cascaded ON ERROR handling"
PRINT
ON ERROR PRINT "Error handled in Main: " REPORT$ : END
ON CLOSE PRINT "Close handled in Main" : END
PROC0
END
DEF PROC0
LOCAL dummy
ON CLOSE LOCAL ERROR 111, "Close"
ON ERROR LOCAL RESTORE LOCAL \
\ IF ERR = 111 PRINT "Close handled in PROC0" : PROCclose ELSE \
\ PRINT "Error handled in PROC0" : ERROR ERR,REPORT$
dummy = FN1
ENDPROC
DEF FN1
ON CLOSE LOCAL ERROR 111, "Close"
ON ERROR LOCAL RESTORE LOCAL \
\ IF ERR = 111 PRINT "Close handled in FN1" : PROCclose ELSE \
\ PRINT "Error handled in FN1" : ERROR ERR,REPORT$
PROC2
= 1
DEF PROC2
ON CLOSE LOCAL ERROR 111, "Close"
ON ERROR LOCAL RESTORE LOCAL \
\ IF ERR = 111 PRINT "Close handled in PROC2" : PROCclose ELSE \
\ PRINT "Error handled in PROC2" : ERROR ERR,REPORT$
REPEAT
WAIT 1
UNTIL FALSE
ENDPROC
DEF PROCclose
IF !392 PROC(^@%+392) ELSE QUIT
ENDPROC Richard.
|
| « Last Edit: Oct 8th, 2010, 3:20pm by admin » |
Logged
|
|
|
|
Michael Hutton
Developer
member is offline


Gender: 
Posts: 248
|
 |
Re: Cascaded ON CLOSE
« Reply #9 on: Oct 8th, 2010, 12:37pm » |
|
I think I understood the code but surely this is still a ON CLOSE LOCAL solution. I am not sure I can see how to incorporate this code into a library which would take care of it's own clean up of objects it creates unless you ask the programmer to put their main program in a PROC (in this case PROC2) which the library calls. Hence if an ON CLOSE is detected in PROC2 the cascading clean up is performed.
As soon as you exit the PROC2 all the ON CLOSE LOCALs are 'forgotten'. Or yet again have I missed the point.
Michael
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: Cascaded ON CLOSE
« Reply #10 on: Oct 8th, 2010, 3:17pm » |
|
on Oct 8th, 2010, 12:37pm, Michael Hutton wrote:| I am not sure I can see how to incorporate this code into a library which would take care of it's own clean up of objects it creates |
|
Sorry, I'm being a bit slow today (it doesn't help having a nasty cough for the last 7 weeks that won't go away). You'll have to explain what you mean in more detail.
As an experiment I've transferred PROC2 into a library, to simulate the situation you describe. There's nothing 'shared' between the library and the main prog as far as I can see (I've chosen a different error code and called PROCclose something different) and the main prog doesn't have to know that any 'local' CLOSE handling happens in the library. But it all seems to work as it did before.
Quote:| As soon as you exit the PROC2 all the ON CLOSE LOCALs are 'forgotten'. |
|
In what sense "forgotten"? If I move the WAIT code out of PROC2 and instead put it in FN1 after the PROC2 statement, a CLOSE still seems to be trapped at each 'level'.
Richard.
Don't put an apostrophe in ITS unless you mean IT IS: http://www.youtube.com/watch?v=Vc2aSz9Ficw
|
|
Logged
|
|
|
|
admin
Administrator
member is offline


Posts: 1145
|
 |
Re: Cascaded ON CLOSE
« Reply #11 on: Oct 8th, 2010, 4:58pm » |
|
on Oct 8th, 2010, 12:37pm, Michael Hutton wrote:| I think I understood the code but surely this is still a ON CLOSE LOCAL solution. |
|
The title of this thread is Cascaded ON CLOSE so of course it's an ON CLOSE LOCAL solution, because that's what you need in that case! In the same way, the solution to the Cascaded ON ERROR problem is an ON ERROR LOCAL solution.
If you're asking about a situation where a library creates a global object, which then needs to be cleared up when the program is eventually closed, that's got nothing to do with cascaded ON CLOSE or ON ERROR handling, and is off-topic for this thread.
The solution to that issue is for the library to provide its own cleanup procedure that the user must call from the main program in his global cleanup code, typically activated from both his ON ERROR and ON CLOSE handlers. Many libraries have just that:
COMLIB has PROC_comexit GDIPLIB has PROC_gdipexit MDILIB has PROC_exitmdi SOCKLIB has PROC_exitsockets
etc.
Richard.
|
|
Logged
|
|
|
|
|