23 July 2019, 22:01 | #1 |
Registered User
Join Date: May 2018
Location: The Netherlands
Posts: 30
|
Ending a message-loop properly
Hoping that this is posted in the right place, as I do have a question about the handling the OS's message-pump, but my code is in assembly.
Anyway, here goes... I'm simply opening a window and then, when the close gadget is clicked, closing it again. My code is working, but there's something weird going on that I don't understand, and I hope someone can explain it to me... or point me to a bug Here's the Code:
;-------------------------------------- ; Includes ;-------------------------------------- incdir "inclAsmMrt:" include "exec/exec.i" include "exec/exec_lib.i" include "intuition/intuition.i" include "intuition/intuition_lib.i" ;-------------------------------------- ; Code ;-------------------------------------- start: ;open intiution library lea IntuitLibName,a1 moveq #36,d0 ;version 36 CALLEXEC OpenLibrary tst.l d0 beq end move.l d0,_IntuitionBase ;open window lea NewWindow_Main,a0 ;NewWindow struct CALLINT OpenWindow tst.l d0 beq end_intuit move.l d0,Window_Main ;- - - - - - - - - - - ; start message-loop ;- - - - - - - - - - - ;get the window's userport movea.l Window_Main,a0 movea.l wd_UserPort(a0),a0 move.l a0,UserPort_Main wait_for_msg: ;wait for message movea.l UserPort_Main,a0 CALLEXEC WaitPort tst.l d0 beq wait_for_msg check_msg_type: ;get the message's class exg d0,a1 move.l im_Class(a1),d5 ;discard the message CALLEXEC ReplyMsg ;check for close-window message cmpi.l #IDCMP_CLOSEWINDOW,d5 beq close_window get_msg: ;get next message movea.l UserPort_Main,a0 CALLEXEC GetMsg tst.l d0 beq wait_for_msg bra check_msg_type ;- - - - - - - - - - - ; end message-loop ;- - - - - - - - - - - close_window: ;discard all remaining messages movea.l UserPort_Main,a0 CALLEXEC GetMsg tst.l d0 beq do_close exg d0,a1 CALLEXEC ReplyMsg ;<<<<<<<<<<< bra close_window do_close: ;close the window movea.l Window_Main,a0 CALLINT CloseWindow end_intuit: ;close intuition library movea.l _IntuitionBase,a1 CALLEXEC CloseLibrary end: ;exit with success clr.l d0 rts ;-------------------------------------- ; Data ;-------------------------------------- ;libraries even _IntuitionBase: dc.l 0 IntuitLibName: INTNAME ;main window even Window_Main: dc.l 0 UserPort_Main: dc.l 0 NewWindow_Main: dc.w 10 ;left dc.w 10 ;top dc.w 250 ;width dc.w 100 ;height dc.b 1 ;detail pen dc.b 2 ;block pen dc.l IDCMP_CLOSEWINDOW ;idcmp flags dc.l WFLG_SIZEGADGET+WFLG_CLOSEGADGET+WFLG_DRAGBAR+WFLG_DEPTHGADGET+WFLG_ACTIVATE ;flags dc.l 0 ;ptr to first gadget (in node list) dc.l 0 ;ptr to checkmark images dc.l WinTitle_Main ;ptr to title dc.l 0 ;ptr to screen dc.l 0 ;ptr to bitmap struct dc.w 20 ;min width dc.w 20 ;min height dc.w 600 ;max width dc.w 300 ;max height dc.w 1 ;type (screen) 1=WB,2=Publ,F=Custm even WinTitle_Main: dc.b "Hi World!",0 ;-------------------------------------- The issue arises when discarding left-over messages in close_window. I have three scenarios: 1. Don't discard any message -> prog hangs at: CALLINT CloseWindow 2. Discard all messages using CALLEXEC ReplyMsg -> Every reply seems to trigger a new message, resulting in an infinite loop 3. Discard all messages without calling CALLEXEC ReplyMsg -> success! One additional thing... in scenario 2, when I click the close gadget exactly three times, the prog exits the infinite loop and closes the window nicely. I just don't get it. Am I doing something wrong? Shouldn't I call ReplyMsg? But if I don't then how does the OS know when to free the messages? And why do I get stuck in an infinite loop when I do reply to the messages? And what's up with clicking the close gadget three times? I could use some on this. |
23 July 2019, 22:24 | #2 |
Semi-Retired
Join Date: Mar 2012
Location: Leiden / The Netherlands
Posts: 1,993
|
Not sure if it is the problem, but WaitPort does not remove the first message from the queue. So you are handling it twice. (d0 from WaitPort then ReplyMsg-ing it, followed by GetMsg and ReplyMsg-ing it again).
So you do a first GetMsg() after the WaitPort() and then handle that message. From the RKM: FUNCTION This function waits for the given port to become non-empty. If necessary, the Wait() function will be called to wait for the port signal. If a message is already present at the port, this function will return immediately. The return value is always a pointer to the first message queued (but it is not removed from the queue). |
24 July 2019, 18:59 | #3 | |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,214
|
Quote:
First, as already stated, WaitForPort() only checks whether the port has any messages pending, but it does not remove them from the port. GetMsg() does. So the typical event loop looks like this: Code:
do { WaitPort(port); msg = GetMsg(port); ... handle message ... ReplyMsg(msg); } while(!quit); There is no need to be afraid that messages are still pending in the IDCMP port of the window will "leak". Intuition is aware of the race condition, and removes them before deleting the window. Actually, they are not "released", but recycled for another program or another event. |
|
24 July 2019, 21:51 | #4 | |
Registered User
Join Date: May 2018
Location: The Netherlands
Posts: 30
|
Quote:
It doesn't seem to fix all issues though, but it does fix the click 3 times issue. Will test it further when I'm back at my Amiga. |
|
24 July 2019, 21:54 | #5 | |
Registered User
Join Date: May 2018
Location: The Netherlands
Posts: 30
|
Quote:
This is very useful info. Where do you get this? Any good readings? I would really like to read up on Intuition. There doesn't seem to be much info. |
|
25 July 2019, 12:30 | #6 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,214
|
Well, there are certainly a couple of problems with the Os, but that's none. It is kind of obvious that intuition has to do something about the problem as you can call "CloseWindow()" any time, and this shouldn't cause races either. So, it is kind of obvious that something has to happen about this in intuition. Other than that, well,... in my case it is matter of "Use the source, Luke!". Well... The Rom Kernel Reference Manuals are certainly the best information you can get, and you find them online these days. They contain example programs that demonstrate how things work. I would suggest looking there.
|
28 July 2019, 17:08 | #7 |
Registered User
Join Date: May 2018
Location: The Netherlands
Posts: 30
|
Hmm, still having issues. After removal of the code that discards all existing messages, it now hangs when closing the window.
If I don't need to free any messages after IDCMP_CloseWindow, why does it freeze up now? Here's my current Code:
;-------------------------------------- ;PRINTV start ;ADDWATCH start ;ADDWATCH close_window ;ADDWATCH end_intuit ;-------------------------------------- ; Includes ;-------------------------------------- incdir "inclAsmMrt:" include "exec/exec.i" include "exec/exec_lib.i" include "intuition/intuition.i" include "intuition/intuition_lib.i" ;-------------------------------------- ; Code ;-------------------------------------- start: ;open intiution library lea IntuitLibName,a1 moveq.l #36,d0 ;version 36 CALLEXEC OpenLibrary tst.l d0 beq end move.l d0,_IntuitionBase ;open window lea NewWindow_Main,a0 CALLINT OpenWindow tst.l d0 beq end_intuit move.l d0,Window_Main ;- - - - - - - - - - - ; start message loop ;- - - - - - - - - - - ;get the window's userport movea.l Window_Main,a0 movea.l wd_UserPort(a0),a0 move.l a0,UserPort_Main wait_for_msg: ;wait form message on userport movea.l UserPort_Main,a0 CALLEXEC WaitPort tst.l d0 beq wait_for_msg get_msg: ;get (next) message from queue CALLEXEC GetMsg tst.l d0 beq wait_for_msg check_msg_type: ;get message's properties exg d0,a1 move.l im_Class(a1),d5 ;close the message CALLEXEC ReplyMsg ;check for actions on message cmpi.l #IDCMP_CLOSEWINDOW,d5 beq close_window ;check for more messages bra get_msg ;- - - - - - - - - - ; end message loop ;- - - - - - - - - - close_window: movea.l Window_Main,a0 CALLINT CloseWindow end_intuit: ;close intuit library movea.l _IntuitionBase,a1 CALLEXEC CloseLibrary end: ;exit with success clr.l d0 rts ;-------------------------------------- ; Data ;-------------------------------------- ;libraries even _IntuitionBase: dc.l 0 IntuitLibName: INTNAME ;main window even Window_Main: dc.l 0 UserPort_Main: dc.l 0 NewWindow_Main: dc.w 10 ;left dc.w 10 ;top dc.w 250 ;width dc.w 100 ;height dc.b 1 ;detail pen dc.b 2 ;block pen dc.l IDCMP_CLOSEWINDOW ;idcmp flags dc.l WFLG_SIZEGADGET+WFLG_CLOSEGADGET+WFLG_DRAGBAR+WFLG_DEPTHGADGET+WFLG_ACTIVATE ;flags dc.l 0 ;ptr to first gadget (in node list) dc.l 0 ;ptr to checkmark images dc.l WinTitle_Main ;ptr to title dc.l 0 ;ptr to screen dc.l 0 ;ptr to bitmap struct dc.w 20 ;min width dc.w 20 ;min height dc.w 600 ;max width dc.w 300 ;max height dc.w 1 ;type (screen) 1=WB,2=Publ,F=Custm even WinTitle_Main: dc.b "Hi World!",0 ;-------------------------------------- Perhaps I'm doing something wrong there too. Anyone's got some experience with AsmPro debugger? It doesn't seem to understand the ADDWATCH command neither. (still developing on the Amiga itself is really nice) |
28 July 2019, 17:10 | #8 |
Registered User
Join Date: May 2018
Location: The Netherlands
Posts: 30
|
Another quick question...
When calling library functions of exec and intuition, are the registers always preserved (except for the return values)? |
28 July 2019, 18:02 | #9 |
Registered User
Join Date: Aug 2004
Location:
Posts: 3,333
|
Typically, OS functions preserve all registers except D0, D1, A0 and A1. However that can vary; read the autodoc for each function to be sure.
In your code example you assume that WaitPort() preserves register A0, but I don't think it does. A0 could contain anything when you call GetMsg(). |
28 July 2019, 18:16 | #10 |
Registered User
Join Date: Dec 2010
Location: Athens/Greece
Age: 53
Posts: 719
|
Doesn't freeze on me. I assembled with vasm and run it from cli. Works as designed, I think
So, try making an executable and run it from cli. When you call OS functions, a0-a1/d0-d1 are trash registers, all other registers saved. There are a few functions that preserve all registers but that's clearly stated on the autodocs. (e.g. WaitBlit) |
28 July 2019, 20:27 | #11 |
Registered User
Join Date: Jun 2016
Location: europe
Posts: 1,039
|
Works for me in asm-one.
How do you run it, from cli or wb? You don't have proper startup code for wb, so maybe that's the reason. Try this, it works for me in asm-one, cli, and wb. Code:
; additional incude for process struct INCLUDE dos/dosextens.i start: **** INSERT THIS AFTER LABEL start: AbsExecBase EQU 4 move.l (AbsExecBase).w,a6 sub.l a1,a1 jsr (_LVOFindTask,a6) move.l d0,a2 moveq #0,d5 tst.l (pr_CLI,a2) bne.b .FromCLI .FromWB lea (pr_MsgPort,a2),a0 jsr (_LVOWaitPort,a6) lea (pr_MsgPort,a2),a0 jsr (_LVOGetMsg,a6) move.l d0,d5 .FromCLI **** ;open intiution library ... end: **** INSERT THIS AFTER LABEL end: tst.l d5 beq.b .NoMsg jsr (_LVOForbid,a6) move.l d5,a1 jsr (_LVOReplyMsg,a6) .NoMsg **** ;exit with success ... |
28 July 2019, 20:28 | #12 |
Registered User
Join Date: May 2018
Location: The Netherlands
Posts: 30
|
|
28 July 2019, 20:35 | #13 | |
Registered User
Join Date: May 2018
Location: The Netherlands
Posts: 30
|
Quote:
Is it to make the program runnable from CLI as well as WB? From what I've learned so far, there's no need to "free" messages at application's end. So the Forbid and ReplyMsg should not be needed. |
|
28 July 2019, 20:50 | #14 |
Registered User
Join Date: Jun 2016
Location: europe
Posts: 1,039
|
Yeah, it's to make it work from WB, in which case the first thing you receive is a love letter from WB and if you don't reply at the end, it will dump your program and bad things will happen.
|
02 August 2019, 19:58 | #15 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,214
|
If you don't reply in the end, the workbench will never unload your program and you have a memory leak.
|
06 February 2022, 15:13 | #16 |
Zone Friend
Join Date: May 2006
Location: France
Posts: 1,801
|
I’ve seen some code examples where there’s no tst.l do after opening a library, it is present in CBM code so is it mandatory and if not why?
|
06 February 2022, 15:25 | #17 |
Registered User
Join Date: Jan 2019
Location: Germany
Posts: 3,214
|
There is no such guarantee that the Os is setting any condition codes. If you get away with not testing d0 for 0 but instead use the condition code directly, you have been lucky.
|
06 February 2022, 17:30 | #18 |
Zone Friend
Join Date: May 2006
Location: France
Posts: 1,801
|
Thanks for the answer.
|
17 February 2022, 21:18 | #19 |
Zone Friend
Join Date: May 2006
Location: France
Posts: 1,801
|
Answer was there put it here for reference
http://amigadev.elowar.com/read/ADCD.../node001C.html |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
WinUAE stuck in a loop | Leandro Jardim | support.WinUAE | 2 | 07 April 2018 21:38 |
It Came from the Desert crashing in a Loop | gb_pdx | support.FS-UAE | 5 | 04 January 2017 20:43 |
Copper loop confusions | Fell | Coders. Asm / Hardware | 15 | 21 September 2015 21:02 |
fastest possible rom copy loop | Yulquen74 | Coders. Asm / Hardware | 17 | 10 May 2014 19:10 |
Sampled loop in cracktro | absence | request.Music | 2 | 30 June 2012 11:33 |
|
|