Asynchronous callbacks

For everything that's not in any way related to PureBasic. General chat etc...
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Asynchronous callbacks

Post by Oso »

I've noticed the widespread use of new programming terms since coming to PureBasic, but not necessarily new techniques. Many appear to be concepts that were in use since the very dawn of programming, but with new names for what was an established technique — often names that aren't even meaningful and don't properly describe the concept. Callbacks is one of those. Another new term, code smells, on the other hand, is reasonably descriptive. :D

Nevertheless, I'm curious about the concept of asynchronous callbacks. The below might suggest it would commence inside a thread, but thought I'd seek others' ideas on how you interpret this term.

"This execution may be immediate as in a synchronous callback, or it might happen at a later point in time as in an asynchronous callback. Programming languages support callbacks in different ways, often implementing them with subroutines, lambda expressions, blocks, or function pointers. " - https://en.wikipedia.org/wiki/Callback_ ... ogramming)
User avatar
NicTheQuick
Addict
Addict
Posts: 1527
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: Asynchronous callbacks

Post by NicTheQuick »

Oso wrote: Wed Feb 15, 2023 12:33 pmNevertheless, I'm curious about the concept of asynchronous callbacks. The below might suggest it would commence inside a thread, but thought I'd seek others' ideas on how you interpret this term.
You are right. Asynchronous callbacks were usually called from a thread. Otherwise they could not be asynchronous. On the other side there are also synchronous callbacks which can only be called if you have some kind of main loop and an event handler which consists of some mechanisms to call that given callback. That is the case for example with (Wait)WIndowEvent().
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
User avatar
mk-soft
Always Here
Always Here
Posts: 6315
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Asynchronous callbacks

Post by mk-soft »

An example synchon callback is EnumWindows API. This only returns when all queries are finished.

Link: viewtopic.php?p=577071#p577071 (See windows part)

An example asynchon callback under Linux is the libwebkit2gtk to get the HTML code. See WebKit_GetHtmlCode.
Here it gets complicated. When called, the callback function is passed and the function returns immediately. In the internal thread of the webkit the data is formed. If the data is complete, the passed callback is hooked into the main programme (where the WaitWindowEvent of PB also runs). This means that fetching the HTML code only works if the event loop is also running.

Link: viewtopic.php?t=78274

It took me a while to figure out that you can't also wait for the data to be called up without the EventLoop running.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Re: Asynchronous callbacks

Post by Oso »

Thanks for these replies NicTheQuick and mk-soft, I think what I can observe from asynchronous callbacks is that it's necessary to deal with the issue of timing — in as far as you're waiting for a process to do its work and you don't know exactly when that's going to complete.
mk-soft wrote: Wed Feb 15, 2023 3:31 pm An example asynchon callback under Linux is the libwebkit2gtk to get the HTML code. See WebKit_GetHtmlCode.
This is going to have to be something I come back to at some point. I'd love to run your GTK example but just wish that I had the time to set up Ubuntu and PB :( My Linux systems are all CentOS and Manjaro.
User avatar
mk-soft
Always Here
Always Here
Posts: 6315
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Asynchronous callbacks

Post by mk-soft »

Oso wrote: Thu Feb 16, 2023 11:15 pm This is going to have to be something I come back to at some point. I'd love to run your GTK example but just wish that I had the time to set up Ubuntu and PB :( My Linux systems are all CentOS and Manjaro.
Link Install PB on Manjaro (Testet with Raspberry Manjaro with packet manager pacman)

Simple Install of Purebasic ... (Part 2)

Must be the same for Manjaro (Intel)
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
idle
Always Here
Always Here
Posts: 6025
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Asynchronous callbacks

Post by idle »

call backs offer versatility they can be used synchronously or asynchronously. They provide a nice way to interleave events. For instance rather than processing and populating and returning a list or an array to a user you can use a callback function so the program only does one parse of the data. Say you're transforming data from a map into a list or array that's the time to consider a callback otherwise you would walk the map to populate the list of results and then the user would parse that list again. So it like N vs 2N plus the allow users to adapt the code.
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Re: Asynchronous callbacks

Post by Oso »

idle wrote: Fri Feb 17, 2023 8:20 pm call backs offer versatility they can be used synchronously or asynchronously. They provide a nice way to interleave events. For instance rather than processing and populating and returning a list or an array to a user you can use a callback function so the program only does one parse of the data. Say you're transforming data from a map into a list or array that's the time to consider a callback otherwise you would walk the map to populate the list of results and then the user would parse that list again. So it like N vs 2N plus the allow users to adapt the code.
Thanks for the reply Idle, but I'm a bit unclear about this. Although I've seen some variation in what people describe as a callback, the most consistent description I can find, seems to be this...
A callback is a function passed as an argument to another function.
That's a technique that I'm sure many of us have been using for a long time in various languages, without necessarily referring to it as a callback. What you describe though, seems to me like a thread that's going away to populate an array, rather than where the name of the function is passed as an argument. There's an example at https://www.w3schools.com/js/js_callback.asp (it's a Javascript page but otherwise an ideal example) which shows the simple case of a calculator routine, in which the name of the function to display the result is passed as an argument to the routine myCalculator, to call at the point just before it finishes. This seems to match the description "A callback is a function passed as an argument to another function".
JavaScript Callbacks

Using a callback, you could call the calculator function (myCalculator) with a callback (myCallback), and let the calculator function run the callback after the calculation is finished — Example :

Code: Select all

function myDisplayer(some) {
  document.getElementById("demo").innerHTML = some;
}

function myCalculator(num1, num2, myCallback) {
  let sum = num1 + num2;
  myCallback(sum);
}

myCalculator(5, 5, myDisplayer);
User avatar
mk-soft
Always Here
Always Here
Posts: 6315
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Asynchronous callbacks

Post by mk-soft »

Example with callback parameter ... (synchron callback)

Code: Select all

;-TOP

#ProgramTitle = "Main Window"
#ProgramVersion = "v1.01.2"

Enumeration Windows
  #Main
EndEnumeration

Enumeration MenuBar
  #MainMenu
EndEnumeration

Enumeration MenuItems
  #MainMenuAbout
  #MainMenuExit
EndEnumeration

Enumeration Gadgets
  #MainList
  #MainButton1
  #MainButton2
EndEnumeration

Enumeration StatusBar
  #MainStatusBar
EndEnumeration

; ----

Prototype protoDisplayCB(Value)

Procedure myDisplayListCB(Value)
  AddGadgetItem(#MainList, -1, "Result = " + Value)
EndProcedure

Procedure myDisplayStatusCB(Value)
  StatusBarText(#MainStatusBar, 0, "Result = " + Value)
EndProcedure

Procedure myCalculater(Value1, Value2, *Callback.protoDisplayCB)
  Protected result
  
  result = Value1 * Value2
  *Callback(result)
EndProcedure

; ----

Procedure UpdateWindow()
  Protected dx, dy
  dx = WindowWidth(#Main)
  dy = WindowHeight(#Main) - StatusBarHeight(#MainStatusBar) - MenuHeight()
  ; Resize gadgets
  ResizeGadget(#MainList, 5, 5, dx - 10, dy - 45)
  ResizeGadget(#MainButton1, 10, dy - 35, 120, 30)
  ResizeGadget(#MainButton2, dx - 130, dy - 35, 120, 30)
EndProcedure

Procedure Main()
  Protected dx, dy, value
  
  #MainStyle = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget
  
  If OpenWindow(#Main, #PB_Ignore, #PB_Ignore, 800, 600, #ProgramTitle , #MainStyle)
    ; Menu
    CreateMenu(#MainMenu, WindowID(#Main))
    MenuTitle("&File")
    CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
      MenuItem(#PB_Menu_About, "")
    CompilerElse
      MenuItem(#MainMenuAbout, "About")
    CompilerEndIf
    ; Menu File Items
    
    CompilerIf Not #PB_Compiler_OS = #PB_OS_MacOS
      MenuBar()
      MenuItem(#MainMenuExit, "E&xit")
    CompilerEndIf
    
    ; StatusBar
    CreateStatusBar(#MainStatusBar, WindowID(#Main))
    AddStatusBarField(#PB_Ignore)
    
    ; Gadgets
    dx = WindowWidth(#Main)
    dy = WindowHeight(#Main) - StatusBarHeight(#MainStatusBar) - MenuHeight()
    ListViewGadget(#MainList, 5, 5, dx -10, dy - 45)
    ButtonGadget(#MainButton1, 10, dy - 35, 120, 30, "Update List")
    ButtonGadget(#MainButton2, dx - 130, dy - 35, 120, 30, "Update Status")
    
    ; Bind Events
    BindEvent(#PB_Event_SizeWindow, @UpdateWindow(), #Main)
    
    ; Event Loop
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Select EventWindow()
            Case #Main
              Break
              
          EndSelect
          
        Case #PB_Event_Menu
          Select EventMenu()
            CompilerIf #PB_Compiler_OS = #PB_OS_MacOS   
              Case #PB_Menu_About
                PostEvent(#PB_Event_Menu, #Main, #MainMenuAbout)
                
              Case #PB_Menu_Preferences
                
              Case #PB_Menu_Quit
                PostEvent(#PB_Event_CloseWindow, #Main, #Null)
                
            CompilerEndIf
            
          Case #MainMenuAbout
            MessageRequester("About", #ProgramTitle + #LF$ + #ProgramVersion, #PB_MessageRequester_Info)
              
          Case #MainMenuExit
            PostEvent(#PB_Event_CloseWindow, #Main, #Null)
            
          EndSelect
          
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #MainButton1
              value + 1
              myCalculater(value, 10, @myDisplayListCB())
              
            Case #MainButton2
              myCalculater(value, 10, @myDisplayStatusCB())
              
          EndSelect
          
      EndSelect
    ForEver
    
  EndIf
  
EndProcedure : Main()
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
idle
Always Here
Always Here
Posts: 6025
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Asynchronous callbacks

Post by idle »

mk-soft wrote: Sat Feb 18, 2023 3:59 pm Example with callback parameter ... (synchron callback)

Code: Select all

;-TOP

#ProgramTitle = "Main Window"
#ProgramVersion = "v1.01.2"

Enumeration Windows
  #Main
EndEnumeration

Enumeration MenuBar
  #MainMenu
EndEnumeration

Enumeration MenuItems
  #MainMenuAbout
  #MainMenuExit
EndEnumeration

Enumeration Gadgets
  #MainList
  #MainButton1
  #MainButton2
EndEnumeration

Enumeration StatusBar
  #MainStatusBar
EndEnumeration

; ----

Prototype protoDisplayCB(Value)

Procedure myDisplayListCB(Value)
  AddGadgetItem(#MainList, -1, "Result = " + Value)
EndProcedure

Procedure myDisplayStatusCB(Value)
  StatusBarText(#MainStatusBar, 0, "Result = " + Value)
EndProcedure

Procedure myCalculater(Value1, Value2, *Callback.protoDisplayCB)
  Protected result
  
  result = Value1 * Value2
  *Callback(result)
EndProcedure

; ----

Procedure UpdateWindow()
  Protected dx, dy
  dx = WindowWidth(#Main)
  dy = WindowHeight(#Main) - StatusBarHeight(#MainStatusBar) - MenuHeight()
  ; Resize gadgets
  ResizeGadget(#MainList, 5, 5, dx - 10, dy - 45)
  ResizeGadget(#MainButton1, 10, dy - 35, 120, 30)
  ResizeGadget(#MainButton2, dx - 130, dy - 35, 120, 30)
EndProcedure

Procedure Main()
  Protected dx, dy, value
  
  #MainStyle = #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MaximizeGadget | #PB_Window_MinimizeGadget
  
  If OpenWindow(#Main, #PB_Ignore, #PB_Ignore, 800, 600, #ProgramTitle , #MainStyle)
    ; Menu
    CreateMenu(#MainMenu, WindowID(#Main))
    MenuTitle("&File")
    CompilerIf #PB_Compiler_OS = #PB_OS_MacOS
      MenuItem(#PB_Menu_About, "")
    CompilerElse
      MenuItem(#MainMenuAbout, "About")
    CompilerEndIf
    ; Menu File Items
    
    CompilerIf Not #PB_Compiler_OS = #PB_OS_MacOS
      MenuBar()
      MenuItem(#MainMenuExit, "E&xit")
    CompilerEndIf
    
    ; StatusBar
    CreateStatusBar(#MainStatusBar, WindowID(#Main))
    AddStatusBarField(#PB_Ignore)
    
    ; Gadgets
    dx = WindowWidth(#Main)
    dy = WindowHeight(#Main) - StatusBarHeight(#MainStatusBar) - MenuHeight()
    ListViewGadget(#MainList, 5, 5, dx -10, dy - 45)
    ButtonGadget(#MainButton1, 10, dy - 35, 120, 30, "Update List")
    ButtonGadget(#MainButton2, dx - 130, dy - 35, 120, 30, "Update Status")
    
    ; Bind Events
    BindEvent(#PB_Event_SizeWindow, @UpdateWindow(), #Main)
    
    ; Event Loop
    Repeat
      Select WaitWindowEvent()
        Case #PB_Event_CloseWindow
          Select EventWindow()
            Case #Main
              Break
              
          EndSelect
          
        Case #PB_Event_Menu
          Select EventMenu()
            CompilerIf #PB_Compiler_OS = #PB_OS_MacOS   
              Case #PB_Menu_About
                PostEvent(#PB_Event_Menu, #Main, #MainMenuAbout)
                
              Case #PB_Menu_Preferences
                
              Case #PB_Menu_Quit
                PostEvent(#PB_Event_CloseWindow, #Main, #Null)
                
            CompilerEndIf
            
          Case #MainMenuAbout
            MessageRequester("About", #ProgramTitle + #LF$ + #ProgramVersion, #PB_MessageRequester_Info)
              
          Case #MainMenuExit
            PostEvent(#PB_Event_CloseWindow, #Main, #Null)
            
          EndSelect
          
        Case #PB_Event_Gadget
          Select EventGadget()
            Case #MainButton1
              value + 1
              myCalculater(value, 10, @myDisplayListCB())
              
            Case #MainButton2
              myCalculater(value, 10, @myDisplayStatusCB())
              
          EndSelect
          
      EndSelect
    ForEver
    
  EndIf
  
EndProcedure : Main()
Good example
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Re: Asynchronous callbacks

Post by Oso »

idle wrote: Sun Feb 19, 2023 12:08 am
mk-soft wrote: Sat Feb 18, 2023 3:59 pm Example with callback parameter ... (synchron callback)
Good example
Thanks for the replies again mk-soft and idle, I'm just about to scrutinise this example to try to get a better understanding, so just sending a quick note mk-soft to let you know your efforts were not sent in vain :D
Oso
Enthusiast
Enthusiast
Posts: 595
Joined: Wed Jul 20, 2022 10:09 am

Re: Asynchronous callbacks

Post by Oso »

mk-soft wrote: Sat Feb 18, 2023 3:59 pm Example with callback parameter ... (synchron callback)
I looked at the code and tried it, thanks again for sending this. I see that this line...

Code: Select all

myCalculater(value, 10, @myDisplayListCB())
... is passing @myDisplayListCB as the procedure to call within myCalculater :

Code: Select all

Procedure myCalculater(Value1, Value2, *Callback.protoDisplayCB)
...which myCalculater then calls with this...

Code: Select all

*Callback(result)
The question I have is whether we need to use a Prototype? To be honest, I'd deliberately left out Prototypes from my PB learning up to now and focus on the essentials, noting the below...
Prototypes — Description

For advanced programmers. Prototype allows to declare a type which will map a function
Do we have no choice but to use this in the callback?

The other thing I just want to check also, is whether in PB, the definition of callback is the same as is referred to in general, in other words "A callback is a function passed as an argument to another function".

I assume the following would not be considered a callback, because OutputResult() — the procedure to call — is not passed as an argument...

Code: Select all

EnableExplicit

Procedure OutputResult(displayresult.i)
  Debug displayresult.i
EndProcedure

Procedure Calculate(param1.i, param2.i)
  Define result.i = param1.i * param2.i
  OutputResult(result.i)
EndProcedure

Calculate(2, 4)
User avatar
mk-soft
Always Here
Always Here
Posts: 6315
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: Asynchronous callbacks

Post by mk-soft »

I assume the following would not be considered a callback, because the procedure to call is not passed as an argument...
Of course, this is no longer a callback, but only a direct function call.
The question I have is whether we need to use a Prototype? To be honest, I'd deliberately left out Prototypes from my PB learning up to now and focus on the essentials, noting the below...
This is the best method to pass the parameters correctly to the callback.


May I ask how old you are and what you have programmed with before?

Maybe we can get you on the right path.
It looks like you still lack a few basics for programming.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
idle
Always Here
Always Here
Posts: 6025
Joined: Fri Sep 21, 2007 5:52 am
Location: New Zealand

Re: Asynchronous callbacks

Post by idle »

@oso

Yes you should be using prototypes. The prototypes template provide the runtime information for the parameters types.
Post Reply