Wiki improvements

Forum for discussion about the documentation project.
Post Reply
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Wiki improvements

Post by dodicat »

I think this is asynchronous, do a task until requested to do another specific task via callbacks.

Code: Select all

Screen 19

Declare Sub main(As Any Ptr)

Function Linear( Byval x As Double ) As Double
    Return x
End Function

Function Quadratic( Byval x As Double ) As Double
    Return x * x
End Function

Function Sinusoidal( Byval x As Double ) As Double
    Return Sin(x)
End Function

Sub readkey(x As Long,y As Long,st As String,message As String,clr As Ulong)
    Dim As String i=""
    Static As String j,blink
    Var c=Color
    i=Inkey
    If Left(i,1)=Chr(08) Then j=Mid(j,1,Len(j)-1)
    Select Case Left(i,1)
    Case Chr(0) To Chr(254)
        If Left(i,1)<>Chr(08) Then
            j=j+Left(i,1)
        End If
    End Select
    If Frac(Timer)>.5 Then blink=" " Else blink="_"
    If Left(i,1)=Chr(27) Then j=""
    If i<>Chr(13) Then
        Locate x,y,0
        Color clr
        Print  st & j & blink 
        Color c
    Else
        j=Rtrim(j,Chr(13))
        message=j
        j=""
    End If
End Sub

Sub server(Listen As Any Ptr)
    Dim As String message
    dim As Single x
    dim As zstring * 20 s="Async callback demo "
    If listen=@readkey  Then
        Do
            Window
            x+=.2
            If x>800 Then x=0
            Screenlock
            Cls
            Draw String(x,300),s
            Draw String(x-800,300),s
            Cast(Sub(As Long,As Long,As String,As String,As Ulong),Listen) _
            (3,3,"Enter (L)inear, (Q)uadratic (S)inusoidal (or exit to end) ",message,3)
            
            Select Case message
            Case "L","l"
                main(@linear)
                print "linear"
            Case "Q","q"
                main(@quadratic)
                print "quadratic"
            Case "S","s"
                main(@sinusoidal)
                print "sinusiodal"
            Case "exit"
                Exit sub
            Case Else
                If Len(message) Then  Print "  " +message+" <-- wot's this?"
            End Select
            Screenunlock
            Sleep 1
        Loop
    Else
        'complete a callback
        Window (-15,-10)-(15,10)
        Dim As  Function(As Double) As Double d=listen
        Pset( -15, d(-15) )
        For x As Double = -15 To 15 Step 0.1
            Line -( x, d(x) )
        Next x
    End If
End Sub

Sub main(p As Any Ptr)
    server(p)
End Sub

main(@readkey) 
But I could be wrong.
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Wiki improvements

Post by fxm »

dodicat wrote:I think this is asynchronous, do a task until requested to do another specific task via callbacks...
...then continue the first task and so and so.
For me, these are nested synchronous callbacks.

For me, without multi-threading, we cannot do any asynchronous processing in FreeBASIC.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Wiki improvements

Post by dodicat »

Your threading code books a slot 1500 milliseconds into the loop (9 white dots)
I checked, it runs linear, sinusiodal and quadratic in that order

Code: Select all

#include "fbthread.bi"

Type MathFunction As Function( ByVal x As Double ) As Double

Function Linear( ByVal x As Double ) As Double
    Return x
End Function

Function Quadratic( ByVal x As Double ) As Double
    Return x * x
End Function

Function Sinusoidal( ByVal x As Double ) As Double
    Return Sin(x)
End Function

Sub ThreadPlotF( ByVal p As Any Ptr )
    Dim f As MathFunction = p
    Window (-15,-10)-(15,10)
    '' sleep added only to check the asynchronous way of the callback
    Sleep 1500, 0
    PSet( -15, f(-15) )
    For x As Double = -15 To 15 Step 0.1
        Line -( x, f(x) )
    Next
End Sub

Screen 19

ThreadDetach( ThreadCreate( @ThreadPlotF, @Linear ) )
ThreadDetach( ThreadCreate( @ThreadPlotF, @Sinusoidal ) )
ThreadDetach( ThreadCreate( @ThreadPlotF, @Quadratic ) )

'' following code added only to check the asynchronous way of callbacks
Print "Asynchronous callbacks requested"
Print "Main program continues ";
dim as double t=timer
For I As Integer = 1 to 15
    Print ".";
    if timer-t>=1500/1000 then color 3
    Sleep 200, 0
Next I
Print
Print "Main program finished"

Sleep  
However the user can manually book a slot 1500 milliiseconds into the loop (9 dots).

Code: Select all

 

#include "fbthread.bi"

Type MathFunction As Function( ByVal x As Double ) As Double

Function Linear( ByVal x As Double ) As Double
    Return x
End Function

Function Quadratic( ByVal x As Double ) As Double
    Return x * x
End Function

Function Sinusoidal( ByVal x As Double ) As Double
    Return Sin(x)
End Function

Sub ThreadPlotF( ByVal p As Any Ptr,byref flag as double)
    if flag=0 then flag=timer+1500/1000:return
    Dim f As MathFunction = p
    Window (-15,-10)-(15,10)
    PSet( -15, f(-15) )
    For x As Double = -15 To 15 Step 0.1
        Line -( x, f(x) )
    Next
End Sub

Screen 19

function main(f as double) as double
    static as long c
     if c>=2 then  return 0
     if f=0 then 
         ThreadPlotF(0,f)
     else
ThreadPlotF(@linear,1)
ThreadPlotF(@sinusoidal,1)
ThreadPlotF(@quadratic,1)
end if
c+=1
return f
end function

var slot=main(0)



Print "Asynchronous callbacks booked"
Print "Main program continues ";
For I As Integer = 1 to 15
    print ".";
    if timer>=slot then main(1):color 3
    Sleep 200, 0
Next I
Print
Print "Main program finished"

Sleep
So why is one async and the other sync?
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Wiki improvements

Post by fxm »

Between the two main program loops, there is a big difference:

1)
For I As Integer = 1 to 15
Print ".";
if timer-t>=1500/1000 then color 3
Sleep 200, 0
Next I

=> No synchronization for plotting in the main loop

2)
For I As Integer = 1 to 15
print ".";
if timer>=slot then main(1):color 3
Sleep 200, 0
Next I

=> Synchronization for plotting in the main loop
because main(1) calls ThreadPlotF(@linear,1), then ThreadPlotF(@sinusoidal,1), and then ThreadPlotF(@quadratic,1).


Just because the result on the screen looks similar does not mean that the programing used is of the same type.
badidea
Posts: 2586
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Wiki improvements

Post by badidea »

dodicat wrote:I think this is asynchronous, do a task until requested to do another specific task via callbacks.
...
Your code does not exit properly here. It freezes after trying 'exit'+enter.
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Wiki improvements

Post by dodicat »

Sorry badidea, Linux of course, you should screenunlock before Exit sub on "exit".
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Wiki improvements

Post by dodicat »

Fxm's threading is just about as predictable as calling the callbacks manually.

Code: Select all

#include "fbthread.bi"

Type MathFunction As Function( ByVal x As Double ) As Double

Function Linear( ByVal x As Double ) As Double
    Return x
End Function

Function Quadratic( ByVal x As Double ) As Double
    Return x * x
End Function

Function Sinusoidal( ByVal x As Double ) As Double
    Return Sin(x)
End Function

Sub ThreadPlotF( ByVal p As Any Ptr )
    Dim f As MathFunction = p
    Window (-15,-10)-(15,10)
    '' sleep added only to check the asynchronous way of the callback
    Sleep 4000+ 2000, 0
    PSet( -15, f(-15) )
    For x As Double = -15 To 15 Step 0.1
        Line -( x, f(x) )
    Next
End Sub

Screen 19
print "starting in 4 seconds. . ."

dim as string s
dim as long flagL,flagS,flagQ
dim as double t=timer
sleep 200
var delta=timer-t 'get time for sleep 200

t=timer

ThreadDetach( ThreadCreate( @ThreadPlotF, @Linear ) )
sleep 2000
ThreadDetach( ThreadCreate( @ThreadPlotF, @Sinusoidal ) )
sleep 2000
ThreadDetach( ThreadCreate( @ThreadPlotF, @Quadratic ) )

'' following code added only to check the asynchronous way of callbacks
Print "Asynchronous callbacks requested"
Print "Main program continues "
For I As Integer = 1 to 30
    locate 12
    s+="."
    print s
    locate 7
    if flagL=0 and timer-t>=4000/1000    then  s+="L":           print "Linear in a two seconds":flagL=1
    locate 8
    if flagS=0 and timer-t>=4000/1000 +2  -delta  then s+="S":   print "sinusoidal in two seconds":flagS=1
    locate 9
    if flagQ=0 and timer-t>=4000/1000 +2 +2 - delta  then s+="Q": print "quadratic in two seconds":flagQ=1
    Sleep 200, 0
Next I
Print
Print "Main program finished"

Sleep  
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Wiki improvements

Post by fxm »

Obviously, when there is enough free time and well-chosen tempos, multi-threading is quite predictable, but not at all otherwise:

Code: Select all

#include "fbthread.bi"

Sub thread (Byval p As Any Ptr)
    For I As Integer = 1 To 20
        Print Cast(Uinteger, p);
        Sleep 20, 1
    Next I
End Sub

For I As Integer = 0 To 9
    ThreadDetach(ThreadCreate(@thread, Cast(Any Ptr, I)))
    Sleep 1000, 1
Next I
Print
Print
For I As Integer = 0 To 9
    ThreadDetach(ThreadCreate(@thread, Cast(Any Ptr, I)))
Next I

Sleep

Code: Select all

00000000000000000000111111111111111111112222222222222222222233333333333333333333444444444444444444445555555555555555555566666666666666666666777777777777777777778888888888888888888899999999999999999999

01245369870783426159264091753885194276032194806375350892614747690523182519780463640912387587314620950261789345438120567918243596700215893674473850921626083417591593064287824031756965904812373724968501
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Wiki improvements

Post by dodicat »

Thanks fxm.
I suppose if sleep 1000 and sleep 20 were exactly 1000 and 20 milliseconds consecutively respectively, then the last string would run out perfectly.
Your first threading example for async callbacks belongs in the help file certainly, but before you say that threading is the only way to achieve async callbacks in FreeBASIC more rigorous proof is required IMHO, and a good definition of sync and async callbacks.

consecutively
Last edited by dodicat on Sep 24, 2020 13:17, edited 1 time in total.
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Wiki improvements

Post by fxm »

dodicat wrote:I suppose if sleep 1000 and sleep 20 were exactly 1000 and 20 milliseconds consecutively, then the last string would run out perfectly.
Provided also that the processor has at least 10+1 cores (if a thread has to be multiplexed on several cores, this will obviously break the supposed perfect synchronism).
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Wiki improvements

Post by fxm »

The concept of callback functions can be implemented by using OOP.
Specialized objects instead of specialized functions can be passed to the procedure (these specialized objects containing the specialized functions as override members).

OOP example for plotting the 3 math functions in a synchronous mode:

Code: Select all

Type MathFunction Extends Object
    Declare Abstract Function f( ByVal x As Double ) As Double
End Type

Type Linear Extends MathFunction
    Declare Function f( ByVal x As Double ) As Double Override
End Type
Function Linear.f( ByVal x As Double ) As Double
    Return x
End Function

Type Quadratic Extends MathFunction
    Declare Function f( ByVal x As Double ) As Double Override
End Type
Function Quadratic.f( ByVal x As Double ) As Double
    Return x * x
End Function

Type Sinusoidal Extends MathFunction
    Declare Function f( ByVal x As Double ) As Double Override
End Type
Function Sinusoidal.f( ByVal x As Double ) As Double
    Return Sin(x)
End Function

Sub PlotF( ByRef mt As MathFunction )
    PSet( -15, mt.f(-15) )
    For x As Double = -15 To 15 Step 0.1
        Line -( x, mt.f(x) )
    Next
End Sub

Screen 19
Window (-15,-10)-(15,10)

PlotF( Linear() )
PlotF( Quadratic() )
PlotF( Sinusoidal() )

Sleep
coderJeff
Site Admin
Posts: 4313
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Wiki improvements

Post by coderJeff »

dodicat wrote:but before you say that threading is the only way to achieve async callbacks in FreeBASIC more rigorous proof is required IMHO, and a good definition of sync and async callbacks.
I'm no expert for sure; this is how it's stored in my brain:
synchronous - caller is blocked while callee executes
asynchronous - callee returns immediately and caller's execution and callee's execution happen "concurrently"
"concurrently" - either real or simulated. Real as in more than one CPU (hardware/chip) does work at the same time, or simulated as in more than 1 thread of execution time share a single CPU

asynchronous DOS example: DMA transfer, from what I remember: using DMA for sound buffer updates on soundblaster. caller initiates a memory transfer from main memory to sound card memory and callback mechanism is a hardware interrupt / interrupt handler

asynchronous Windows example: either the WSAAsync*() API for winsock which uses a message to HWND as callback mechanism, or OVERLAPPED I/O which uses a windows event as callback mechanism.

For freebasic, unless using some specific platform specific asynchronous method, I think that multiple threads would be the only way to have asynchronous execution (concurrency either real or simulated).

Regardless of method, asynchronous methods or callbacks need to be thread-safe, or re-entrant safe, etc. Shared resources between the main thread and any worker / callback threads should probably use a mutex to access shared resources. For example, a shared area of memory or printing to the screen.
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Wiki improvements

Post by fxm »

fxm wrote:The concept of callback functions can be implemented by using OOP.
Specialized objects instead of specialized functions can be passed to the procedure (these specialized objects containing the specialized functions as override members).

OOP example for plotting the 3 math functions in a synchronous mode:

Code: Select all

Type MathFunction Extends Object
    Declare Abstract Function f( ByVal x As Double ) As Double
End Type

Type Linear Extends MathFunction
    Declare Function f( ByVal x As Double ) As Double Override
End Type
Function Linear.f( ByVal x As Double ) As Double
    Return x
End Function

Type Quadratic Extends MathFunction
    Declare Function f( ByVal x As Double ) As Double Override
End Type
Function Quadratic.f( ByVal x As Double ) As Double
    Return x * x
End Function

Type Sinusoidal Extends MathFunction
    Declare Function f( ByVal x As Double ) As Double Override
End Type
Function Sinusoidal.f( ByVal x As Double ) As Double
    Return Sin(x)
End Function

Sub PlotF( ByRef mt As MathFunction )
    PSet( -15, mt.f(-15) )
    For x As Double = -15 To 15 Step 0.1
        Line -( x, mt.f(x) )
    Next
End Sub

Screen 19
Window (-15,-10)-(15,10)

PlotF( Linear() )
PlotF( Quadratic() )
PlotF( Sinusoidal() )

Sleep
Similar example, but in an asynchronous mode by using another thread:

Code: Select all

#include "fbthread.bi"

Type MathFunction Extends Object
    Declare Abstract Function f( ByVal x As Double ) As Double
End Type

Type Linear Extends MathFunction
    Declare Function f( ByVal x As Double ) As Double Override
End Type
Function Linear.f( ByVal x As Double ) As Double
    Return x
End Function

Type Quadratic Extends MathFunction
    Declare Function f( ByVal x As Double ) As Double Override
End Type
Function Quadratic.f( ByVal x As Double ) As Double
    Return x * x
End Function

Type Sinusoidal Extends MathFunction
    Declare Function f( ByVal x As Double ) As Double Override
End Type
Function Sinusoidal.f( ByVal x As Double ) As Double
    Return Sin(x)
End Function

Sub ThreadPlotF( ByVal p As Any Ptr )
    Dim pmt As MathFunction Ptr = p
    Window (-15,-10)-(15,10)
    PSet( -15, pmt->f(-15) )
    For x As Double = -15 To 15 Step 0.1
        Line -( x, pmt->f(x) )
    Next
End Sub

Screen 19

ThreadDetach( ThreadCreate( @ThreadPlotF, @Linear() ) )
ThreadDetach( ThreadCreate( @ThreadPlotF, @Sinusoidal() ) )
ThreadDetach( ThreadCreate( @ThreadPlotF, @Quadratic() ) )

Sleep
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Wiki improvements

Post by MrSwiss »

IMO, in the threaded examples there is the MUTEX missing, when using ThreadDetach() at least.
If ThreadWait() would be used instead, probably not mandatory.
fxm
Moderator
Posts: 12083
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Wiki improvements

Post by fxm »

Where do you see the need for a MUTEX?
I don't see this necessity triggered by detaching the thread.
Post Reply