Author Topic: SBT  (Read 35391 times)

0 Members and 1 Guest are viewing this topic.

JRS

  • Guest
Re: SBT
« Reply #105 on: May 23, 2015, 12:52:58 AM »
I can't seem to exit the main::main function when the IupMainLoop ends. I may have hit the wall with this method I'm using.

Charles Pegge

  • Guest
Re: SBT
« Reply #106 on: May 23, 2015, 01:17:05 AM »
Hi John,

Do you have something like this in your extension code:

Code: [Select]
WaitForMultipleObjects ThreadsRunning, hThread, 1, INFINITE

for i=1 to ThreadsRunning
  CloseHandle hThread[ i ]
next

JRS

  • Guest
Re: SBT
« Reply #107 on: May 23, 2015, 02:02:45 AM »
I have a single thread working. I had to remove the main = Iup::MainLoop return and called it from the parent (host/boot) script. I'll let you know how enabling the second thread goes.


JRS

  • Guest
Re: SBT
« Reply #108 on: May 23, 2015, 02:49:19 AM »
I can get both thread windows to show and close but I'm not able to run two event loops at the same time. Next task to solve.

My approach is going to be calling the IUP event routines from the host script and use IupLoopStep and not have IUP Wait and create my own JRSMainLoop polling both thread event ques.

Good Night!
« Last Edit: May 23, 2015, 02:58:50 AM by John »

JRS

  • Guest
Re: SBT
« Reply #109 on: May 23, 2015, 11:02:54 AM »
Charles,

Adding thread support to SBT has been a rewarding stroll down multi-threading ally. The best way to describe what is going on is pretend you you're putting on a puppet show.  ;D

JRS

  • Guest
Re: SBT
« Reply #110 on: May 23, 2015, 02:47:28 PM »
Quote from: IupLoopStep
This function is useful for allowing a second message loop to be managed by the application itself. This means that messages can be intercepted and callbacks can be processed inside an application loop.

IupLoopStep returns immediately after processing any messages or if there are no messages to process. IupLoopStepWait put the system in idle until a message is processed (since 3.0).

If IUP_CLOSE is returned the IupMainLoop will not end because the return code was already processed. If you want to end IupMainLoop when IUP_CLOSE is returned by IupLoopStep then call IupExitLoop after IupLoopStep returns.

An example of how to use this function is a counter that can be stopped by the user. For such, the user has to interact with the system, which is possible by calling the function periodically.

This way, this function replaces old mechanisms implemented using the Idle callback.

Note that this function does not replace IupMainLoop.

It looks like this is going to be a minor change to my IupMainLoop for threads. I'm trying to make this so it works generically for both threaded and single script application models.

Quote
IupMainLoopLevel

Returns the current cascade level of IupMainLoop. When no calls were done, return value is 0. You can use this function to check if IupMainLoop was already called and avoid calling it again. A call to IupPopup will increase one level.

Reminds me of checking the keyboard buffer for key presses but not grabbing the key code.

JRS

  • Guest
Re: SBT
« Reply #111 on: May 23, 2015, 06:28:48 PM »
I have made some progress with IUP running in a threaded mode. I still need to add the g_idle_add() to add thread support at the Gtk level. If not obvious in the code example, the SB_CallSubArgs() function is calling both SB script FUNCTIONs/SUBs and extension module shared object (.so) functions in threads transparently for the user.  8)

iup.bas (callback functions)
Code: Script BASIC
  1. FUNCTION MainLoop
  2. LOCAL this_event, aname
  3.   LoopStep()
  4.   this_event = GetEvent()
  5.   IF this_event <> undef THEN
  6.     aname = GetActionName()
  7.     IF this_event = event{this_event}[0] THEN
  8.       ICALL(event{this_event}[1])
  9.     END IF
  10.   END IF
  11.   MainLoop = aname
  12. END FUNCTION
  13.  
  14. FUNCTION SetCallback(ih, aname, fname)
  15.   event{ih}[0] = ih
  16.   event{ih}[1] = fname
  17.   SetCallback = __SetCallback(ih, aname)
  18. END FUNCTION
  19.  

iupmain.sb
Code: Script BASIC
  1. IMPORT mt.bas
  2. IMPORT sbt.inc
  3.  
  4. SUB SB_Wait(mtvar)
  5.   WHILE mt::GetVariable(mtvar) <> "OK"
  6.     SB_msSleep(20)
  7.   WEND
  8. END SUB
  9.  
  10. sb1 = SB_ThreadStart("rqdemo1.sb",undef,"/etc/scriba/basic.conf")
  11. SB_Wait("sb1_loaded")
  12.  
  13. sb1_rtn = SB_CallSub(sb1, "main::main")
  14. SB_Wait("sb1_main")
  15.  
  16. sb2 = SB_ThreadStart("rqdemo2.sb",undef,"/etc/scriba/basic.conf")
  17. SB_Wait("sb2_loaded")
  18.  
  19. sb2_rtn = SB_CallSub(sb2, "main::main")
  20. SB_Wait("sb2_main")
  21.  
  22. threads = 2
  23. sb1_active = TRUE
  24. sb2_active = TRUE
  25.  
  26. WHILE threads
  27.   IF sb1_active THEN
  28.     sb1_event_class = SB_CallSubArgs(sb1, "iup::mainloop")
  29.     IF sb1_event_class = "CLOSE_CB" THEN
  30.       sb1_active = FALSE
  31.       threads -= 1
  32.     END IF
  33.   END IF
  34.   IF sb2_active THEN
  35.     sb2_event_class = SB_CallSubArgs(sb2, "iup::mainloop")
  36.     IF sb2_event_class = "CLOSE_CB" THEN
  37.       sb2_active = FALSE
  38.       threads -= 1
  39.     END IF
  40.   END IF
  41. WEND
  42.  
  43. SB_CallSub(sb2, "iup::exitloop")
  44. SB_CallSub(sb1, "iup::exitloop")
  45.  

rqdemo1.sb (rqdemo2.sb is identical other than references as being the second thread)
Code: Script BASIC
  1. ' Script BASIC Rapid-Q form conversion
  2.  
  3. IMPORT mt.bas
  4. IMPORT iup.bas
  5.  
  6. ' CALLBACKS FUNCTIONS
  7.  
  8. SUB button_quit
  9.   PRINT "Thread 1 Quit Button Pressed\n"
  10. END SUB  
  11.  
  12. SUB win_exit
  13.   ' Good-Bye  
  14. END SUB
  15.  
  16. SUB main
  17.  
  18.   ' SBIUP-Q INIT
  19.  
  20.   Iup::Open()
  21.   Iup::SetGlobal("DEFAULTFONT", "Sans, 7.5")
  22.  
  23.   ' CREATE FORM
  24.  
  25.   Form = Iup::Create("dialog")
  26.          Iup::SetAttributes(Form, "RASTERSIZE=320x240, TITLE=\"Thread 1\"")
  27.  
  28.        Label1  = Iup::Create("label")
  29.                  Iup::SetAttributes(Label1, "TITLE=\"Customer\", RASTERSIZE=55x13, FLOATING=YES, POSITION=\"19,19\"")
  30.  
  31.        Edit1   = Iup::Create("text")
  32.                  Iup::SetAttributes(Edit1, "RASTERSIZE=121x21, FLOATING=YES, POSITION=\"72,16\"")
  33.  
  34.        Button1 = Iup::Create("button")
  35.                  Iup::SetAttributes(Button1, "TITLE=\"&Quit\", RASTERSIZE=75x25, FLOATING=YES, POSITION=\"107,164\"")
  36.  
  37.   vbx = Iup::Vbox(Label1, Edit1, Button1)
  38.   Iup::Append(Form, vbx)
  39.                  
  40.   ' SET CALLBACKS
  41.  
  42.   Iup::SetCallback(Form, "CLOSE_CB", ADDRESS(win_exit()))
  43.   Iup::SetCallback(Button1, "ACTION", ADDRESS(button_quit()))
  44.   Iup::Show(Form)
  45.   mt::SetVariable("sb1_main","OK")
  46. END SUB
  47. mt::SetVariable("sb1_loaded","OK")
  48.  


.
« Last Edit: May 23, 2015, 11:09:06 PM by John »

JRS

  • Guest
Re: SBT
« Reply #112 on: May 23, 2015, 11:46:44 PM »
Charles,

I forgot that I didn't have the filter code in the Iup::LoopStep() and only the Iup::LoopStepWait() function. I'm no longer getting segment faults for no reason and clicks are much more responsive. I guess filtering out mouse movement events does help.

Code: C
  1. /*
  2. int IupLoopStep(void);  <iup.h>
  3.  
  4. Runs one iteration of the message loop.
  5. */
  6. besFUNCTION(PuiLoopStep)
  7.  
  8. retry_event:
  9.   IupLoopStep();
  10.   if (evtHandle == NULL) goto retry_event;
  11.   besRETURN_LONG(IUP_DEFAULT);
  12. besEND
  13.  
« Last Edit: May 23, 2015, 11:54:25 PM by John »

JRS

  • Guest
Re: SBT
« Reply #113 on: May 24, 2015, 01:11:39 PM »
Charles,

Even though my IupLoopStep() wrapper function was filtering out everything except defined callback events, one to the core CPU was running at 100%. I added a usleep and that brought it down to about 7-12%. At this point even without the Gtk tweaks for threading, it's responsive and seems stable. The second thread window sometimes starts max size and/or without a min/max system menu button. Other than that, I think I can try more complex IUP examples (On-line Dictionary) and see how it goes.

Code: C
  1. /*
  2. int IupLoopStep(void);  <iup.h>
  3.  
  4. Runs one iteration of the message loop.
  5. */
  6. besFUNCTION(PuiLoopStep)
  7.  
  8. retry_event:
  9.   IupLoopStep();
  10.   if (evtHandle == NULL){
  11.     usleep(50);
  12.     goto retry_event;
  13.   }      
  14.   besRETURN_LONG(IUP_DEFAULT);
  15. besEND
  16.  

BTW: I ran into a case where SB AUTO VARS (arrays) is expanding the array with referencing undef elements.  :-\ I'm going to see if the forced variable initializing SB option will resolve the issue.

Here is my latest callback wrappers.

Code: Script BASIC
  1. FUNCTION MainLoop
  2. LOCAL this_event, aname
  3.   LoopStep()
  4.   this_event = GetEvent()
  5.   ICALL(event{BB_HTA(this_event)}[1])
  6.   MainLoop = GetActionName()
  7. END FUNCTION
  8.  
  9. FUNCTION SetCallback(ih, aname, fname)
  10.   event{BB_HTA(ih)}[0] = BB_HTA(ih)
  11.   event{BB_HTA(ih)}[1] = fname
  12.   SetCallback = __SetCallback(ih, aname)
  13. END FUNCTION
  14.  
« Last Edit: May 24, 2015, 01:26:45 PM by John »

JRS

  • Guest
Re: SBT
« Reply #114 on: May 24, 2015, 04:16:02 PM »
Charles,

As it turns out the Iup::MainLoop wrapper function has to be run in the host script. It seems to run flawlessly in this mode and responsive to every click even if I rapidly click on the button. Everything closes as it should without the OS bitching on exit. I'll post a fresh set of code on All BASIC / Script BASIC forums when I can get a better method of passing the callback map back to the host.

I'm getting happier with this with each post. I hope it continues that way.  ;)

Done!

I finally got this worked out and didn't have to inform Gtk or IUP that they're being threaded8)

I can click on either thread window's button as fast as I can and it responds with the being pressed message. The only minor issue I still have is the second thread window will open in max size and sometimes without a max/restore window button. At this point I'm happy.

iup.bas - callback handling functions
Code: Script BASIC
  1. FUNCTION MainLoop
  2. LOCAL hex_event
  3.   LoopStep()
  4.   this_event = GetEvent()
  5.   hex_event = BB_HTA(this_event)
  6.   IF hex_event = event{hex_event}[0] THEN
  7.     IF event{hex_event}[2] = 1 THEN
  8.       SB_CallSub(main::sb1, event{hex_event}[1])
  9.     ELSEIF event{hex_event}[2] = 2 THEN
  10.       SB_CallSub(main::sb2, event{hex_event}[1])
  11.     END IF
  12.     MainLoop = GetActionName()
  13.   END IF  
  14. END FUNCTION
  15.  
  16. FUNCTION SetThreadCallback(ih, aname, fname, tnum)
  17.   t_event = mt::GetVariable("Callback_Map")
  18.   IF t_event = undef THEN t_event = ""
  19.   t_event = t_event & BB_HTA(ih) & "|" & fname & "|" & tnum & "\n"
  20.   mt::SetVariable("Callback_Map", t_event)
  21.   SetThreadCallback = __SetCallback(ih, aname)
  22. END FUNCTION
  23.  
  24. SUB GetThreadCallback
  25.   LOCAL t_event, e_list, e_array, x
  26.   t_event = mt::GetVariable("Callback_Map")
  27.   SPLITA t_event BY "\n" TO e_list
  28.   FOR x = 0 TO UBOUND(e_list)
  29.     SPLITA e_list[x] BY "|" TO e_array
  30.     event{e_array[0]}[0] = e_array[0]
  31.     event{e_array[0]}[1] = e_array[1]
  32.     event{e_array[0]}[2] = e_array[2]
  33.   NEXT
  34. END SUB
  35.  
  36. FUNCTION BB_HTA(AsciiStr)
  37.   LOCAL AsciiLen,ScanPos,HexStr
  38.   AsciiLen = LEN(AsciiStr)
  39.   HexStr = ""
  40.   IF AsciiLen THEN
  41.     FOR ScanPos = 1 TO AsciiLen
  42.       HexStr &= RIGHT("0" & HEX(ASC(MID(AsciiStr, ScanPos, 1))),2)
  43.     NEXT ScanPos
  44.   ELSE
  45.     HexStr = ""
  46.   END IF
  47.   BB_HTA = HexStr
  48. END FUNCTION
  49.  

iupmain.sb - host SB script (puppet master)
Code: Script BASIC
  1. IMPORT mt.bas
  2. IMPORT sbt.inc
  3. IMPORT iup.bas
  4.  
  5. Iup::Open()
  6.  
  7. SUB SB_Wait(mtvar)
  8.   WHILE mt::GetVariable(mtvar) <> "OK"
  9.     SB_msSleep(5000)
  10.   WEND
  11. END SUB
  12.  
  13. sb1 = SB_ThreadStart("rqdemo1.sb",undef,"/etc/scriba/basic.conf")
  14. SB_Wait("sb1_loaded")
  15. sb1_rtn = SB_CallSubArgs(sb1, "main::main", sb1)
  16.  
  17. sb2 = SB_ThreadStart("rqdemo2.sb",undef,"/etc/scriba/basic.conf")
  18. SB_Wait("sb2_loaded")
  19. sb2_rtn = SB_CallSubArgs(sb2, "main::main", sb2)
  20.  
  21. threads = 2
  22.  
  23. Iup::GetThreadCallback()
  24.  
  25. WHILE threads
  26.   event_class = Iup::MainLoop()
  27.   IF event_class = "CLOSE_CB" THEN
  28.     threads -= 1
  29.     IF Iup::event{Iup::BB_HTA(Iup::this_event)}[2] = 1 THEN
  30.       SB_CallSub(sb1, "iup::exitloop")
  31.     ELSEIF Iup::event{Iup::BB_HTA(Iup::this_event)}[2] = 2 THEN
  32.       SB_CallSub(sb2, "iup::exitloop")
  33.     END IF
  34.   END IF  
  35.   SB_msSleep(250)
  36. WEND
  37.  
  38. Iup::Close()
  39. SB_Destroy(sb2)
  40. SB_Destroy(sb1)
  41.  

rqdemo1.sb - rqdemo2.sb is identical other than the references to it been the second thread.
Code: Script BASIC
  1. ' Script BASIC Rapid-Q form conversion
  2.  
  3. IMPORT mt.bas
  4. IMPORT iup.bas
  5.  
  6. ' CALLBACKS FUNCTIONS
  7.  
  8. SUB button_quit
  9.   PRINT "Thread 1 Quit Button Pressed\n"
  10. END SUB  
  11.  
  12. SUB win_exit
  13.   ' Good-Bye  
  14. END SUB
  15.  
  16. SUB main
  17.  
  18.   ' SBIUP-Q INIT
  19.  
  20.   Iup::Open()
  21.   Iup::SetGlobal("DEFAULTFONT", "Sans, 7.5")
  22.  
  23.   ' CREATE FORM
  24.  
  25.   Form = Iup::Create("dialog")
  26.          Iup::SetAttributes(Form, "RASTERSIZE=320x240, TITLE=\"Thread 1\"")
  27.  
  28.        Label1  = Iup::Create("label")
  29.                  Iup::SetAttributes(Label1, "TITLE=\"Customer\", RASTERSIZE=55x13, FLOATING=YES, POSITION=\"19,19\"")
  30.  
  31.        Edit1   = Iup::Create("text")
  32.                  Iup::SetAttributes(Edit1, "RASTERSIZE=121x21, FLOATING=YES, POSITION=\"72,16\"")
  33.  
  34.        Button1 = Iup::Create("button")
  35.                  Iup::SetAttributes(Button1, "TITLE=\"&Quit\", RASTERSIZE=75x25, FLOATING=YES, POSITION=\"107,164\"")
  36.  
  37.   vbx = Iup::Vbox(Label1, Edit1, Button1)
  38.   Iup::Append(Form, vbx)
  39.                  
  40.   ' SET CALLBACKS
  41.  
  42.   Iup::SetThreadCallback(Form, "CLOSE_CB", "main::win_exit", 1)
  43.   Iup::SetThreadCallback(Button1, "ACTION", "main::button_quit", 1)
  44.   Iup::Show(Form)
  45. END SUB
  46. mt::SetVariable("sb1_loaded","OK")
  47.  


.
« Last Edit: May 25, 2015, 12:18:35 AM by John »

JRS

  • Guest
SBT IUP Threaded Linux 64 bit Working
« Reply #115 on: May 25, 2015, 06:16:20 PM »
The solution to my unstable IUP start-up issues were resolved with creating an IUP dialog in the parent script before creating threaded children dialogs.  I moved the Iup::MainLoop and Iup::GetThreadCallback routines into the main script from the IUP extension module. At this point everything is working as expected and I couldn't be happier.

Moral: How can you have well behaved children if you don't have a mature parent in charge?  ::)

SBx_Main
Code: Script BASIC
  1. ' SBT IUP Theaded Example
  2.  
  3. IMPORT mt.bas
  4. IMPORT sbt.inc
  5. IMPORT iup.bas
  6. IMPORT "SBx"
  7.  
  8. Iup::Open()
  9.  
  10. SUB SB_Wait(mtvar)
  11.   WHILE mt::GetVariable(mtvar) <> "OK"
  12.     SB_msSleep(5000)
  13.   WEND
  14. END SUB
  15.  
  16. SUB btn1_clicked
  17.   PRINT "Main 0 Button 1 Pressed\n"
  18.   PRINT "Which Mouse Button: ",CHR(Iup::GetBtnPressed()),"\n"
  19.   PRINT "Button Up/Dn State: ",Iup::GetBtnState(),"\n"
  20. END SUB
  21.  
  22. SUB btn2_clicked
  23.   PRINT "Main 0 Button 2 Pressed\n"
  24. END SUB
  25.  
  26. SUB btn3_clicked
  27.   PRINT "Main 0 Button 3 Pressed\n"
  28. END SUB
  29.  
  30. SUB win_exit
  31.   ' Good-Bye
  32. END SUB
  33.  
  34. win = DIALOG()
  35. SETPROPERTIES win, "TITLE=\"SBx Main 0\", SIZE=300x"
  36. horzbox = HBOX()
  37. SETPROPERTIES horzbox, "GAP=5"
  38. btn1 = BUTTON()
  39. SETPROPERTIES btn1, "TITLE=\"Button 1\", EXPAND=HORIZONTAL"
  40. btn2 = BUTTON()
  41. SETPROPERTIES btn2, "TITLE=\"Button 2\", EXPAND=HORIZONTAL"
  42. btn3 = BUTTON()
  43. SETPROPERTIES btn3, "TITLE=\"Button 3\", EXPAND=HORIZONTAL"
  44. APPEND horzbox, btn1
  45. APPEND horzbox, btn2
  46. APPEND horzbox, btn3
  47. APPEND win, horzbox
  48. Iup::SetThreadCallback(win, "CLOSE_CB", ADDRESS(win_exit()), 0)
  49. Iup::SetThreadCallback(btn1, "BUTTON_CB", ADDRESS(btn1_clicked()), 0)
  50. Iup::SetThreadCallback(btn2, "ACTION", ADDRESS(btn2_clicked()), 0)
  51. Iup::SetThreadCallback(btn3, "ACTION", ADDRESS(btn3_clicked()), 0)
  52. SHOW win
  53.  
  54. ' Puppet Show
  55.  
  56. sb1 = SB_ThreadStart("SBx_T1",undef,"/etc/scriba/basic.conf")
  57. SB_Wait("sb1_loaded")
  58. sb1_rtn = SB_CallSubArgs(sb1, "main::main", sb1)
  59.  
  60. sb2 = SB_ThreadStart("SBx_T2",undef,"/etc/scriba/basic.conf")
  61. SB_Wait("sb2_loaded")
  62. sb2_rtn = SB_CallSubArgs(sb2, "main::main", sb2)
  63.  
  64. threads = 3
  65.  
  66. t_event = mt::GetVariable("Callback_Map")
  67. SPLITA t_event BY "\n" TO e_list
  68. FOR x = 0 TO UBOUND(e_list)
  69.   SPLITA e_list[x] BY "|" TO e_array
  70.   event{e_array[0]}[0] = e_array[0]
  71.   event{e_array[0]}[1] = e_array[1]
  72.   event{e_array[0]}[2] = e_array[2]
  73. NEXT
  74.  
  75. WHILE threads
  76.   Iup::LoopStep()
  77.   this_event = Iup::GetEvent()
  78.   hex_event = Iup::BB_HTA(this_event)
  79.   IF hex_event = event{hex_event}[0] THEN
  80.     IF event{hex_event}[2] = 0 THEN
  81.       ICALL event{hex_event}[1]
  82.     ELSE IF event{hex_event}[2] = 1 THEN
  83.       SB_CallSub(sb1, event{hex_event}[1])
  84.     ELSE IF event{hex_event}[2] = 2 THEN
  85.       SB_CallSub(sb2, event{hex_event}[1])
  86.     END IF
  87.     IF Iup::GetActionName() = "CLOSE_CB" THEN threads -= 1
  88.   END IF  
  89.   SB_msSleep(250)
  90. WEND
  91.  
  92. Iup::Close()
  93. SB_Destroy(sb2)
  94. SB_Destroy(sb1)
  95.  

SBx_T1 - T2 is the same
Code: Script BASIC
  1. ' SBx_buttons Example (Thread 1)
  2.  
  3. IMPORT mt.bas
  4. IMPORT iup.bas
  5. IMPORT "SBx"
  6.  
  7. SUB btn1_clicked
  8.   PRINT "Thread 1 Button 1 Pressed\n"
  9.   PRINT "Which Mouse Button: ",CHR(Iup::GetBtnPressed()),"\n"
  10.   PRINT "Button Up/Dn State: ",Iup::GetBtnState(),"\n"
  11. END SUB
  12.  
  13. SUB btn2_clicked
  14.   PRINT "Thread 1 Button 2 Pressed\n"
  15. END SUB
  16.  
  17. SUB btn3_clicked
  18.   PRINT "Thread 1 Button 3 Pressed\n"
  19. END SUB
  20.  
  21. SUB win_exit
  22.   ' Good-Bye
  23. END SUB
  24.  
  25. SUB main
  26.   win = DIALOG()
  27.   SETPROPERTIES win, "TITLE=\"SBx Thread 1\", SIZE=300x"
  28.   horzbox = HBOX()
  29.   SETPROPERTIES horzbox, "GAP=5"
  30.   btn1 = BUTTON()
  31.   SETPROPERTIES btn1, "TITLE=\"Button 1\", EXPAND=HORIZONTAL"
  32.   btn2 = BUTTON()
  33.   SETPROPERTIES btn2, "TITLE=\"Button 2\", EXPAND=HORIZONTAL"
  34.   btn3 = BUTTON()
  35.   SETPROPERTIES btn3, "TITLE=\"Button 3\", EXPAND=HORIZONTAL"
  36.   APPEND horzbox, btn1
  37.   APPEND horzbox, btn2
  38.   APPEND horzbox, btn3
  39.   APPEND win, horzbox
  40.   Iup::SetThreadCallback(win, "CLOSE_CB", "main::win_exit", 1)
  41.   Iup::SetThreadCallback(btn1, "BUTTON_CB", "main::btn1_clicked", 1)
  42.   Iup::SetThreadCallback(btn2, "ACTION", "main::btn2_clicked", 1)
  43.   Iup::SetThreadCallback(btn3, "ACTION", "main::btn3_clicked", 1)
  44.   SHOW win
  45. END SUB
  46. mt::SetVariable("sb1_loaded","OK")
  47.  

.
« Last Edit: May 26, 2015, 10:31:54 AM by John »

Mike Lobanovsky

  • Guest
Re: SBT
« Reply #116 on: May 26, 2015, 06:52:58 AM »
Congrats, John, going successfully multithreaded with an interpretative GUI is no easy task at all! :D

JRS

  • Guest
Re: SBT
« Reply #117 on: May 26, 2015, 08:48:33 AM »
Thanks Mike but the credit really needs to go to Peter Verhas (SB & sbhttpd) and Charles Pegge (DLLC) for showing me the way.

I've been after a SBT like extension module for years. It was a now or never kind of thing.  :)

JRS

  • Guest
SBx 3 Forms
« Reply #118 on: May 27, 2015, 10:20:28 PM »
As it turns out, you really don't need threading to achieve multiple window support. As I see it threading of a IUP dialog would be a special use case. It's good to know it can be done.

Code: Script BASIC
  1. ' SBx_buttons Example (3 Form Version)
  2.  
  3. IMPORT iup.bas
  4. IMPORT sbt.inc
  5. IMPORT "SBx"
  6.  
  7. ' Form 1 Callback Routines
  8. SUB frm1_btn1_clicked
  9.   PRINT "Form 1 Button 1 Pressed\n"
  10.   PRINT "Which Mouse Button: ",CHR(Iup::GetBtnPressed()),"\n"
  11.   PRINT "Button Up/Dn State: ",Iup::GetBtnState(),"\n"
  12. END SUB
  13.  
  14. SUB frm1_btn2_clicked
  15.   PRINT "Form 1 Button 2 Pressed\n"
  16. END SUB
  17.  
  18. SUB frm1_btn3_clicked
  19.   PRINT "Form 1 Button 3 Pressed\n"
  20. END SUB
  21.  
  22. ' Form 2  Callback Routines
  23. SUB frm2_btn1_clicked
  24.   PRINT "Form 2 Button 1 Pressed\n"
  25.   PRINT "Which Mouse Button: ",CHR(Iup::GetBtnPressed()),"\n"
  26.   PRINT "Button Up/Dn State: ",Iup::GetBtnState(),"\n"
  27. END SUB
  28.  
  29. SUB frm2_btn2_clicked
  30.   PRINT "Form 2 Button 2 Pressed\n"
  31. END SUB
  32.  
  33. SUB frm2_btn3_clicked
  34.   PRINT "Form 2 Button 3 Pressed\n"
  35. END SUB
  36.  
  37. ' Form 3 Callback Routines
  38. SUB frm3_btn1_clicked
  39.   PRINT "Form 3 Button 1 Pressed\n"
  40.   PRINT "Which Mouse Button: ",CHR(Iup::GetBtnPressed()),"\n"
  41.   PRINT "Button Up/Dn State: ",Iup::GetBtnState(),"\n"
  42. END SUB
  43.  
  44. SUB frm3_btn2_clicked
  45.   PRINT "Form 3 Button 2 Pressed\n"
  46. END SUB
  47.  
  48. SUB frm3_btn3_clicked
  49.   PRINT "Form 3 Button 3 Pressed\n"
  50. END SUB
  51.  
  52. SUB win_exit
  53.   ' Good-Bye
  54. END SUB
  55.  
  56. Iup::Open()
  57.  
  58. ' Form 1 Dialog
  59. win1 = DIALOG()
  60. SETPROPERTIES(win1, "TITLE=\"SBx Form 1\", SIZE=300x")
  61. horzbox1 = HBOX()
  62. SETPROPERTIES horzbox1, "GAP=5"
  63. btn1_1 = BUTTON()
  64. SETPROPERTIES btn1_1, "TITLE=\"Button 1\", EXPAND=HORIZONTAL"
  65. btn1_2 = BUTTON()
  66. SETPROPERTIES btn1_2, "TITLE=\"Button 2\", EXPAND=HORIZONTAL"
  67. btn1_3 = BUTTON()
  68. SETPROPERTIES btn1_3, "TITLE=\"Button 3\", EXPAND=HORIZONTAL"
  69. APPEND horzbox1, btn1_1
  70. APPEND horzbox1, btn1_2
  71. APPEND horzbox1, btn1_3
  72. APPEND win1, horzbox1
  73. Iup::SetCallback win1, "CLOSE_CB", ADDRESS(win_exit())
  74. Iup::SetCallback btn1_1, "BUTTON_CB", ADDRESS(frm1_btn1_clicked())
  75. Iup::SetCallback btn1_2, "ACTION", ADDRESS(frm1_btn2_clicked())
  76. Iup::SetCallback btn1_3, "ACTION", ADDRESS(frm1_btn3_clicked())
  77. Iup::ShowXY(win1,500,200)
  78.  
  79.  
  80.  
  81. ' Form 2 Dialog
  82. win2 = DIALOG()
  83. SETPROPERTIES win2, "TITLE=\"SBx Form 2\", SIZE=300x"
  84. horzbox2 = HBOX()
  85. SETPROPERTIES horzbox2, "GAP=5"
  86. btn2_1 = BUTTON()
  87. SETPROPERTIES btn2_1, "TITLE=\"Button 1\", EXPAND=HORIZONTAL"
  88. btn2_2 = BUTTON()
  89. SETPROPERTIES btn2_2, "TITLE=\"Button 2\", EXPAND=HORIZONTAL"
  90. btn2_3 = BUTTON()
  91. SETPROPERTIES btn2_3, "TITLE=\"Button 3\", EXPAND=HORIZONTAL"
  92. APPEND horzbox2, btn2_1
  93. APPEND horzbox2, btn2_2
  94. APPEND horzbox2, btn2_3
  95. APPEND win2, horzbox2
  96. Iup::SetCallback win2, "CLOSE_CB", ADDRESS(win_exit())
  97. Iup::SetCallback btn2_1, "BUTTON_CB", ADDRESS(frm2_btn1_clicked())
  98. Iup::SetCallback btn2_2, "ACTION", ADDRESS(frm2_btn2_clicked())
  99. Iup::SetCallback btn2_3, "ACTION", ADDRESS(frm2_btn3_clicked())
  100. Iup::ShowXY(win2,500,400)
  101.  
  102. ' Form 3 Dialog
  103. win3 = DIALOG()
  104. SETPROPERTIES win3, "TITLE=\"SBx Form 3\", SIZE=300x"
  105. horzbox3 = HBOX()
  106. SETPROPERTIES horzbox3, "GAP=5"
  107. btn3_1 = BUTTON()
  108. SETPROPERTIES btn3_1, "TITLE=\"Button 1\", EXPAND=HORIZONTAL"
  109. btn3_2 = BUTTON()
  110. SETPROPERTIES btn3_2, "TITLE=\"Button 2\", EXPAND=HORIZONTAL"
  111. btn3_3 = BUTTON()
  112. SETPROPERTIES btn3_3, "TITLE=\"Button 3\", EXPAND=HORIZONTAL"
  113. APPEND horzbox3, btn3_1
  114. APPEND horzbox3, btn3_2
  115. APPEND horzbox3, btn3_3
  116. APPEND win3, horzbox3
  117. Iup::SetCallback win3, "CLOSE_CB", ADDRESS(win_exit())
  118. Iup::SetCallback btn3_1, "BUTTON_CB", ADDRESS(frm3_btn1_clicked())
  119. Iup::SetCallback btn3_2, "ACTION", ADDRESS(frm3_btn2_clicked())
  120. Iup::SetCallback btn3_3, "ACTION", ADDRESS(frm3_btn3_clicked())
  121. Iup::ShowXY(win3,500,600)
  122.  
  123.  
  124.  
  125. ' Event Loop
  126. windows = 3
  127.  
  128. WHILE windows
  129.   Iup::LoopStep()
  130.   this_event = Iup::GetEvent()
  131.   this_event = Iup::BB_HTA(this_event)
  132.   IF this_event = event{this_event}[0] THEN
  133.     ICALL event{this_event}[1]
  134.     IF Iup::GetActionName() = "CLOSE_CB" THEN windows -= 1
  135.   END IF  
  136.   SB_msSleep(250)
  137. WEND
  138.  
  139. Iup::Close
  140.  

iup.bas - I changed the Iup::SetCallback() to create the event array in the main namespace.
Code: Script BASIC
  1. FUNCTION SetCallback(ih, aname, fname)
  2.   main::event{BB_HTA(ih)}[0] = BB_HTA(ih)
  3.   main::event{BB_HTA(ih)}[1] = fname
  4.   SetCallback = __SetCallback(ih, aname)
  5. END FUNCTION
  6.  


.

JRS

  • Guest
Re: SBT - thread testing
« Reply #119 on: June 09, 2015, 11:49:17 PM »
I'm now 100% convinced that Script BASIC is truly running in a threaded mode.

ttmain.sb
Code: Script BASIC
  1. IMPORT sbt.inc
  2.  
  3. SB_ThreadStart("tt1.sb",undef,"/etc/scriba/basic.conf")
  4. SB_ThreadStart("tt2.sb",undef,"/etc/scriba/basic.conf")
  5. SB_ThreadStart("tt3.sb",undef,"/etc/scriba/basic.conf")
  6.  
  7. PRINT "SB Host\n"
  8. SB_msSleep(50000)
  9.  

tt1.sb
Code: Script BASIC
  1. ' Test Thread
  2.  
  3. IMPORT sbt.inc
  4.  
  5. FOR x = 1 TO 10
  6.   PRINT "Thread 1: ",x,"\n"
  7.   SB_msSleep(1000)
  8. NEXT
  9.  
  10. SB_ThreadEnd
  11.  

tt2.sb
Code: Script BASIC
  1. ' Test Thread
  2.  
  3. IMPORT sbt.inc
  4.  
  5. FOR x = 1 TO 10
  6.   PRINT "Thread 2: ",x,"\n"
  7.   SB_msSleep(2000)
  8. NEXT
  9.  
  10. SB_ThreadEnd
  11.  

tt3.sb
Code: Script BASIC
  1. ' Test Thread
  2.  
  3. IMPORT sbt.inc
  4.  
  5. FOR x = 1 TO 10
  6.   PRINT "Thread 3: ",x,"\n"
  7.   SB_msSleep(3000)
  8. NEXT
  9.  
  10. SB_ThreadEnd
  11.  

Output

scriptbasic: ~/sb22/test $ time scriba ttmain.sb
Thread 1: 1
SB Host
Thread 1: 2
Thread 2: 1
Thread 1: 3
Thread 3: 1
Thread 1: 4
Thread 2: 2
Thread 1: 5
Thread 3: 2
Thread 1: 6
Thread 2: 3
Thread 1: 7
Thread 1: 8
Thread 2: 4
Thread 3: 3
Thread 1: 9
Thread 1: 10
Thread 2: 5
Thread 3: 4
Thread 2: 6
Thread 2: 7
Thread 3: 5
Thread 2: 8
Thread 3: 6
Thread 2: 9
Thread 3: 7
Thread 2: 10
Thread 3: 8
Thread 3: 9
Thread 3: 10
 
real    0m0.054s
user    0m0.005s
sys     0m0.002s
scriptbasic: ~/sb22/test $
« Last Edit: June 11, 2015, 12:09:44 AM by John »