Author Topic: SBT  (Read 35397 times)

0 Members and 2 Guests are viewing this topic.

Charles Pegge

  • Guest
Re: SBT
« Reply #90 on: May 16, 2015, 01:17:47 PM »
In general, the OS expects to see only one GUI per process, ie: one message loop and one main window.

JRS

  • Guest
Re: SBT
« Reply #91 on: May 16, 2015, 01:24:34 PM »
Seems to be the case. I took a look at the DLLC code to see how you solved the mystery and the ASM magic ended the show for me.

Quote from: IUP Mailing List
Note that in GTK this is really easy to achieve:  GLib is thread-safe,
and so you can simply call g_idle_add from your worker thread to
register an idle callback.  The idle callback will then be called from
the GTK main loop in the IUP thread (since IUP simply uses the GTK main
loop, all this should work seamlessly without any modification to IUP).



.
« Last Edit: May 16, 2015, 01:44:32 PM by John »

JRS

  • Guest
Re: SBT
« Reply #92 on: May 17, 2015, 05:55:50 PM »
Hi Charles,

I was able to get the thread execution object handle and pass it back to the host. I can now access thread variables and call functions just like the embedded interface I started off with.

Check out All BASIC for more.

John

JRS

  • Guest
Re: SBT
« Reply #93 on: May 18, 2015, 08:32:42 AM »
Charles,

Now that I'm able to call SB thread script functions from the host (boot) SB script, can I follow your path and wrap the IUP GUI generation and event code into a SB main::main function? How would you suggest I precede from here to test if your DLLC method and see if I can get it working under Linux?

Update

I got both IUP test window to show. I needed to give the thread scripts time to load before calling their main functions. The problem is the event buffers fill up quickly and puts the windows in distress. All I need to figure out now is to how to drain and process the events.

Here is what gets returned from the thread main function.

Code: Script BASIC
  1. Iup::Show(Form)
  2. main=Iup::MainLoop()
  3. END FUNCTION
  4.  

Code: Script BASIC
  1. IMPORT sbt.inc
  2.  
  3. sb1 = SB_ThreadStart("test.sbq",undef,"/etc/scriba/basic.conf")
  4. sb2 = SB_ThreadStart("test2.sbq",undef,"/etc/scriba/basic.conf")
  5. sb1_rtn = SB_CallSubArgs(sb1, "main::main", sb1, 0)
  6. sb2_rtn = SB_CallSubArgs(sb2, "main::main", sb2, 0)
  7.  
  8. PRINT "Thread 1 = ", sb1_rtn,"\n"
  9. PRINT "Thread 2 = ", sb2_rtn,"\n"
  10.  
  11. LINE INPUT wait
  12.  


jrs@laptop:~/sb/sb22/sbt$ scriba iupmain.sb
Thread 1 = undef
Thread 2 = undef
Killed
jrs@laptop:~/sb/sb22/sbt$


I think I'm close to getting this working. I'm just confused how to process events. Can you offer any advice?
« Last Edit: May 18, 2015, 10:41:48 PM by John »

JRS

  • Guest
Re: SBT
« Reply #94 on: May 19, 2015, 04:49:48 PM »
Hi Charles,

Code: OxygenBasic
  1.   sbcb[v]={pProg,fa,np, @t.scriba_CallArgEx,RetVal,idat} 'PROGRAM,FUNCTION
  2.  r=CallBackTable[v] 'callback handle to pass on to the DLL
  3.  *pReturnValue=ReturnLong pst,r
  4.  

If I can work my way through this O2 functionality, I think I can finish up from there. I'm trying to imagine this in C:o

Charles Pegge

  • Guest
Re: SBT
« Reply #95 on: May 19, 2015, 05:34:41 PM »
Hi John,

I would suggest processing IUP low level callback messages, like mouse-move, without attempting to pass the callback to SB. Mouse coordinates and key states can be stored in SB global variables, or a shared table,  leaving more occasional events, like button-clicks to be relayed onto SB callbacks.

As you can see, threading and callbacks is really messy stuff, and way beyond the scope of a casual SB user. So the more the extension module can do internally, the better.

DLLC was too generic to be useable for this task.


JRS

  • Guest
Re: SBT
« Reply #96 on: May 19, 2015, 05:56:21 PM »
Quote from: Charles
I would suggest processing IUP low level callback messages, like mouse-move, without attempting to pass the callback to SB.

I do that now with the SB IUP extension module. It's a bit of a hack as I'm returning to SB with every filtered callback and SB does the ICALL. This goes back to my inability to get MyICall (trial ext. mod.) to work. I'm by that now.

I still need to get square in my head how thread functions really don't return but remain as a life of their own in the same parent process. It's like playing who's on first. It still boggles my mind that a complete working scriba is created as a threaded function. I've decided to use MT as the thread cop. Trying to use sleep while things get loaded is too variable. (program size, ext. mod, ...) MT will smooth that out.

I have to move the event routines out of the IUP extension module and into the SBT ext. mod. My hope is this direction of fooling the threads as to who is in control is a slick trick or the method I posted from the IUP mailing list is the proper method to chose. I want something cross platform and you have already paved the way.  8)

One of the next SB tasks on my list is to be able from one called SB extension module function call another without returning to SB.
« Last Edit: May 19, 2015, 07:55:22 PM by John »

JRS

  • Guest
Re: SBT
« Reply #97 on: May 19, 2015, 11:08:00 PM »
Charles,

Before I start on a considerable effort to reproduce what you have done in DLLC, I'm going to try the call g_idle_add from the worker thread to
register an idle callback method first before trying to implant into SBT the IUP event responsibilities.

This single thread example works using my existing IUP custom Iup::MainLoop (single step callback return to SB) It looks like the only issue is treating the Gtk MainLoop() with a does of g_idle_add to play nicely with threads.

Notice MT's first day on the job as a thread cop.  Works great and responsive.

Code: Script BASIC
  1. IMPORT mt.bas
  2. IMPORT sbt.inc
  3.  
  4. sb1 = SB_ThreadStart("test.sbq",undef,"/etc/scriba/basic.conf")
  5.  
  6. WHILE mt::GetVariable("STATUS") <> "OK"
  7. WEND
  8.  
  9. sb1_rtn = SB_CallSubArgs(sb1, "main::main", sb1, 0)
  10.  
  11. SB_Destroy(sb1)
  12.  

test.sbq
Code: Script BASIC
  1. ' Script BASIC Rapid-Q form conversion
  2.  
  3. IMPORT mt.bas
  4. IMPORT sbt.inc
  5. IMPORT iup.bas
  6.  
  7. ' CALLBACKS FUNCTIONS
  8.  
  9. SUB Button_Quit
  10.   Iup::ExitLoop = TRUE
  11. END SUB  
  12.  
  13. SUB Win_exit
  14.   Iup::ExitLoop = TRUE
  15. END SUB
  16.  
  17. FUNCTION main(pProg,idat)
  18.  
  19.   ' SBIUP-Q INIT
  20.  
  21.   Iup::Open()
  22.   Iup::SetGlobal("DEFAULTFONT", "Sans, 7.5")
  23.  
  24.   ' CREATE FORM
  25.  
  26.   Form = Iup::Create("dialog")
  27.          Iup::SetAttributes(Form, "RASTERSIZE=320x240, TITLE=\"Form1\"")
  28.  
  29.        Label1  = Iup::Create("label")
  30.                  Iup::SetAttributes(Label1, "TITLE=\"Customer\", RASTERSIZE=55x13, FLOATING=YES, POSITION=\"19,19\"")
  31.  
  32.        Edit1   = Iup::Create("text")
  33.                  Iup::SetAttributes(Edit1, "RASTERSIZE=121x21, FLOATING=YES, POSITION=\"72,16\"")
  34.  
  35.        Button1 = Iup::Create("button")
  36.                  Iup::SetAttributes(Button1, "TITLE=\"&Quit\", RASTERSIZE=75x25, FLOATING=YES, POSITION=\"107,164\"")
  37.  
  38.   vbx = Iup::Vbox(Label1, Edit1, Button1)
  39.   Iup::Append(Form, vbx)
  40.                  
  41.   ' SET CALLBACKS
  42.  
  43.   Iup::SetCallback(Form, "CLOSE_CB", ADDRESS(Win_exit()))
  44.   Iup::SetCallback(Button1, "ACTION", ADDRESS(Button_Quit()))
  45.  
  46.   ' MAIN
  47.  
  48.   ' Iup::Show(Iup::LayoutDialog(Form))
  49.  Iup::Show(Form)
  50.   Iup::MainLoop
  51.   Iup::Close
  52.   main = "STARTED"
  53. END FUNCTION
  54. mt::SetVariable("STATUS","OK")
  55.  

.
« Last Edit: May 19, 2015, 11:23:24 PM by John »

JRS

  • Guest
Re: SBT
« Reply #98 on: May 20, 2015, 09:30:34 AM »
Charles,

I think I'm on my way to to actually getting this working. I added a new SB_msSleep() function to give me better control of my waiting for thread status MT messages.

Code: Script BASIC
  1. WHILE mt::GetVariable("STATUS") <> "OK"
  2.   SB_msSleep(20)
  3. WEND
  4.  

This does a 20 microseconds Linux usleep call.

The plan going forward is to create a common IUP callback that handles all of the various callback function argument lists as a variadic call. I will do a g_idle_add call as part of the callback definition function. I think with MT making sure everything plays by the defined rules, threading shouldn't be that scary.

« Last Edit: May 20, 2015, 10:09:15 AM by John »

JRS

  • Guest
Re: SBT
« Reply #99 on: May 20, 2015, 06:30:16 PM »
Charles,

I have been spending a lot of time lately learning from your DLLC code. You spent an amazing amount of time with Script BASIC and making it O2 accessible. If anyone needed an embeddable scripting engine for O2, you have it covered with SB.  :)

Thanks for all the time, help and wealth of knowledge you have shared with me over the years.

John

JRS

  • Guest
Re: SBT
« Reply #100 on: May 20, 2015, 09:17:14 PM »
Charles,

I noticed the HexToBin.sb program in the O2 zip and it dawned on me, was this the beginnings of an assembler?  :-X

Code: Script BASIC
  1.  
  2.  ' TEST HEXADECIMAL TO BINARY CONVERSION
  3. ' =====================================
  4.  
  5.  
  6.   s="B8 04 03 02  01    c3"
  7.  
  8.   'CONVERT TO BINARY
  9.  '-----------------
  10.  
  11.   le=len(s)
  12.   i=1
  13.   j=1
  14.   a=0
  15.   n=0
  16.   while i<=le
  17.     w=asc(mid(s,i,1))
  18.     if w>96 then
  19.       w-=39
  20.     elseif w>64 then
  21.       w-=7
  22.     end if
  23.     w-=48
  24.     if w>=0 then
  25.       a=a*16+w
  26.       n=1
  27.     else
  28.       if n=1 then
  29.         v[j]=chr(a)
  30.         a=0
  31.         j+=1
  32.         n=0
  33.       end if
  34.     end if
  35.     i+=1
  36.   wend
  37.   if n=1 then
  38.     v[j]=chr(a)
  39.   end if
  40.  
  41.  
  42.   'SAVE BINARY
  43.  '-----------
  44.  
  45.   op=join("",v)
  46.  
  47.   open "t.bin" for output as 1
  48.   print #1,op
  49.   close 1
  50.  
  51.   'LOAD BINARY
  52.  '-----------
  53.  
  54.   n=filelen("t.bin")
  55.   open "t.bin" for binary as 1
  56.   op=input(n,1)
  57.   close 1
  58.   '
  59.  'DISPLAY
  60.  '-------
  61.  
  62.   print "lENGTH=" & len(op) & "  BYTE CONTENT="
  63.  
  64.   for i=1 to len(op)
  65.     s="0" & hex(asc(mid(op,i,1)))
  66.     print right(s,2) & " "
  67.   next
  68.  
  69.  
  70.   line input z
  71.  

JRS

  • Guest
Re: SBT
« Reply #101 on: May 20, 2015, 10:58:46 PM »
Charles,

I think this is going to be easier than I thought. I'm able to run my IupLoopStepWait based callback from the host SB script and capture events in the thread. Once I get the TID (Thread ID) attached to the callback definition I'll give more than one thread a try. I'm thinking this is going to work for the first pass. It will make a good tutorial on threaded GUI.  ;D

JRS

  • Guest
Re: SBT
« Reply #102 on: May 21, 2015, 08:01:06 PM »
For the most part I have this working. Before I move on to dealing with multiple threads I still need a sane callback map created by the threads but used by the host doing the calling. Most of this will be transparent in the second round when callbacks and calling SB scripts are handled internally in the extension module interface. Since my existing pre-thread IUP interface is close to working, it's worth extending the original hack to deal with threading. 

So far it's been more fun than frustrating. Unlike the local variable type display issues I was having with the debugger.

Charles Pegge

  • Guest
Re: SBT
« Reply #103 on: May 21, 2015, 11:31:48 PM »
Quote
I noticed the HexToBin.sb program in the O2 zip and it dawned on me, was this the beginnings of an assembler?  :-X

It is a seed program for something, but to become an X86 assembler, it needs another 150K!

Such is the dilemma of building demo programs - turning them into useful products is many times more complex.

JRS

  • Guest
Re: SBT
« Reply #104 on: May 22, 2015, 07:54:24 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.

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, pprog )
  15.   event{ih}[0] = ih
  16.   event{ih}[1] = fname
  17.   event{ih}[2] = pprog
  18.   SetCallback = __SetCallback(ih, aname)
  19. END FUNCTION
  20.  

iupmain.sb
Code: Script BASIC
  1. IMPORT mt.bas
  2. IMPORT sbt.inc
  3. IMPORT iup.bas
  4.  
  5. SUB SB_Wait(mtvar)
  6.   WHILE mt::GetVariable(mtvar) <> "OK"
  7.     SB_msSleep(20)
  8.   WEND
  9. END SUB
  10.  
  11. sb1 = SB_ThreadStart("rqdemo1.sb",undef,"/etc/scriba/basic.conf")
  12. SB_Wait("sb1_loaded")
  13.  
  14. sb1_rtn = SB_CallSubArgs(sb1, "main::main", sb1)
  15. SB_Wait("sb1_main")
  16.  
  17. sb2 = SB_ThreadStart("rqdemo2.sb",undef,"/etc/scriba/basic.conf")
  18. SB_Wait("sb2_loaded")
  19.  
  20. sb2_rtn = SB_CallSubArgs(sb2, "main::main", sb2)
  21. SB_Wait("sb2_main")
  22.  
  23. threads = 2
  24. sb1_active = TRUE
  25. sb2_active = TRUE
  26.  
  27. WHILE threads
  28.   IF sb1_active THEN
  29.     sb1_event_class = SB_CallSubArgs(sb1, "iup::mainloop")
  30.     IF sb1_event_class = "CLOSE_CB" THEN
  31.       sb1_active = FALSE
  32.       threads -= 1
  33.     END IF
  34.   END IF
  35.   IF sb2_active THEN
  36.     sb2_event_class = SB_CallSubArgs(sb2, "iup::mainloop")
  37.     IF sb2_event_class = "CLOSE_CB" THEN
  38.       sb2_active = FALSE
  39.       threads -= 1
  40.     END IF
  41.   END IF
  42. WEND
  43.  
  44. Iup::Close()
  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 sbt.inc
  5. IMPORT iup.bas
  6.  
  7. ' CALLBACKS FUNCTIONS
  8.  
  9. SUB button_quit
  10.   PRINT "Thread 1 Quit Button Pressed\n"
  11. END SUB  
  12.  
  13. SUB win_exit
  14.   ' Good-Bye  
  15. END SUB
  16.  
  17. FUNCTION main(pProg)
  18.  
  19.   ' SBIUP-Q INIT
  20.  
  21.   Iup::Open()
  22.   Iup::SetGlobal("DEFAULTFONT", "Sans, 7.5")
  23.  
  24.   ' CREATE FORM
  25.  
  26.   Form = Iup::Create("dialog")
  27.          Iup::SetAttributes(Form, "RASTERSIZE=320x240, TITLE=\"Thread 1\"")
  28.  
  29.        Label1  = Iup::Create("label")
  30.                  Iup::SetAttributes(Label1, "TITLE=\"Customer\", RASTERSIZE=55x13, FLOATING=YES, POSITION=\"19,19\"")
  31.  
  32.        Edit1   = Iup::Create("text")
  33.                  Iup::SetAttributes(Edit1, "RASTERSIZE=121x21, FLOATING=YES, POSITION=\"72,16\"")
  34.  
  35.        Button1 = Iup::Create("button")
  36.                  Iup::SetAttributes(Button1, "TITLE=\"&Quit\", RASTERSIZE=75x25, FLOATING=YES, POSITION=\"107,164\"")
  37.  
  38.   vbx = Iup::Vbox(Label1, Edit1, Button1)
  39.   Iup::Append(Form, vbx)
  40.                  
  41.   ' SET CALLBACKS
  42.  
  43.   Iup::SetCallback(Form, "CLOSE_CB", ADDRESS(win_exit()))
  44.   Iup::SetCallback(Button1, "ACTION", ADDRESS(button_quit()))
  45.   Iup::Show(Form)
  46.   mt::SetVariable("sb1_main","OK")
  47. END FUNCTION
  48. mt::SetVariable("sb1_loaded","OK")
  49.  


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