'===========================================================================
' Subject: CODE POINTER DEMONSTRATION         Date: 10-05-95 (10:04)       
'  Author: Jamshid Khoshrangi                 Code: PB32                   
'  Origin: FidoNet POWER_BAS Echo           Packet: PB.ABC
'===========================================================================
$IF 0


    CODEPTR.BAS                                             CODEPTR.BAS

                        Code Pointer Demonstration

                       Written by Jamshid Khoshrangi


    PURPOSE:

        This program demonstrates the power of PowerBASIC v3.2's new
        code pointers.  In this case "power" is defined as "speed"
        and for the purposes of this demonstration, code pointers are
        compared to a SELECT CASE statement, and both are timed within
        a loop.

    BACKGROUND NOTES:

        This demonstration illustrates the use of a code pointer table
        as a replacement for the traditionally utilized SELECT CASE
        statement under special conditions.  Those conditions?  Well,
        if all the SELECT CASE structure does is route the program to
        one of a selection of SUBs, and each of those SUBs accepts the
        same parameters, or no parameters at all, such as:

            SELECT CASE x
                CASE 1
                    DoTaskOne

                CASE 2
                    DoTaskTwo

                CASE 3
                    DoTaskThree

            END SELECT

        This type of SELECT CASE is common in finite state systems.  I
        can personally see great use for this in two of my own programs.

        Even if you don't program this way now, after you see the speed
        gains presented by code pointers under these conditions, you
        may start asking yourself just how you can take advantage of the
        code pointer table method!

        If you'd like more information on how this can be used in real
        programs, feel free to contact me on the POWERBASIC echo in
        Fidonet.

        Jamshid Khoshrangi

$ENDIF

'   This statement REALLY SPEEDS THINGS UP!
$ERROR ALL OFF

$DIM ALL

DEFINT A-Z

DIM CodePtrTable (1:8) AS SHARED DWORD

'   This type is just used for this demo... no real meaning

TYPE OurType
    Alpha   AS INTEGER
    Beta    AS STRING * 32
    Gamma   AS BYTE
    Delta   AS LONG
END TYPE

'   It is important to note that each of the following SUB's that
'   will be in the CodePtrTable accepts the same number and types
'   of parameters!

DECLARE SUB A (One AS INTEGER, Two AS STRING, Three AS OurType)
DECLARE SUB B (One AS INTEGER, Two AS STRING, Three AS OurType)
DECLARE SUB C (One AS INTEGER, Two AS STRING, Three AS OurType)
DECLARE SUB D (One AS INTEGER, Two AS STRING, Three AS OurType)
DECLARE SUB E (One AS INTEGER, Two AS STRING, Three AS OurType)
DECLARE SUB F (One AS INTEGER, Two AS STRING, Three AS OurType)
DECLARE SUB G (One AS INTEGER, Two AS STRING, Three AS OurType)
DECLARE SUB H (One AS INTEGER, Two AS STRING, Three AS OurType)

DECLARE SUB DoTheDemo ()
DECLARE SUB InitializeTheCodePtrTable ()
DECLARE SUB RunTheSelectCaseDemo ()
DECLARE SUB RunTheCodePtrDemo ()


'   Demo begins here!

DoTheDemo

END

SUB DoTheDemo ()

    DIM SelectCaseEndTimer AS LONG
    DIM CodePtrEndTimer AS LONG

    CLS

    VIEW TEXT (25,5)-(70,20)

    PRINT "Code Pointer Demonstration"
    PRINT

    InitializeTheCodePtrTable

    MTIMER
    RunTheSelectCaseDemo
    SelectCaseEndTimer = MTIMER
    PRINT "SELECT  CASE: ", SelectCaseEndTimer

    MTIMER
    RunTheCodePtrDemo
    CodePtrEndTimer = MTIMER
    PRINT "CODE POINTER: ", CodePtrEndTimer

    PRINT
    PRINT "Approximately";
    PRINT  INT(1/(CodePtrEndTimer / SelectCaseEndTimer)*10)/10;
    PRINT "times faster!"
    PRINT
    PRINT "Need I say more?"
    PRINT "Kudos to PowerBASIC version 3.2!"


END SUB

SUB InitializeTheCodePtrTable ()
    '   The table must be initialized!
    CodePtrTable(1) = CODEPTR32(A) : CodePtrTable(2) = CODEPTR32(B)
    CodePtrTable(3) = CODEPTR32(C) : CodePtrTable(4) = CODEPTR32(D)
    CodePtrTable(5) = CODEPTR32(E) : CodePtrTable(6) = CODEPTR32(F)
    CodePtrTable(7) = CODEPTR32(G) : CodePtrTable(8) = CODEPTR32(H)

END SUB
'
SUB RunTheSelectCaseDemo ()
    DIM One     AS INTEGER
    DIM Two     AS STRING
    DIM Three   AS OurType

    DIM i AS INTEGER, x AS INTEGER

    FOR i = 1 TO 1000
        FOR x = 1 TO 8

            ' The appropriate SUB is called by means of a SELECT CASE
            ' statement....

            ' NB: I don't normally format my code like the following....
            '     I just did it here to conserve space....

            SELECT CASE x
                CASE 1 : A one, two, three
                CASE 2 : B one, two, three
                CASE 3 : C one, two, three
                CASE 4 : D one, two, three
                CASE 5 : E one, two, three
                CASE 6 : F one, two, three
                CASE 7 : G one, two, three
                CASE 8 : H one, two, three
            END SELECT
        NEXT x
    NEXT i

END SUB


SUB RunTheCodePtrDemo ()

    DIM one     AS INTEGER
    DIM two     AS STRING
    DIM three   AS OurType

    DIM i AS INTEGER, x AS INTEGER

    FOR i = 1 TO 1000
        FOR x = 1 TO 8

            '   The appropriate SUB is called by means of a code pointer,
            '   and the parameters are passed accordingly, using the newly
            '   introduced BDECL format....

            CALL DWORD CodePtrTable(x) BDECL (one, two, three)

        NEXT x
    NEXT i

END SUB

'   The SUB's follow....
'   For this demo, they are just empty wrappers, but you get
'   the idea.

SUB A (One AS INTEGER, Two AS STRING, Three AS OurType)
END SUB

SUB B (One AS INTEGER, Two AS STRING, Three AS OurType)
END SUB

SUB C (One AS INTEGER, Two AS STRING, Three AS OurType)
END SUB

SUB D (One AS INTEGER, Two AS STRING, Three AS OurType)
END SUB

SUB E (One AS INTEGER, Two AS STRING, Three AS OurType)
END SUB

SUB F (One AS INTEGER, Two AS STRING, Three AS OurType)
END SUB

SUB G (One AS INTEGER, Two AS STRING, Three AS OurType)
END SUB

SUB H (One AS INTEGER, Two AS STRING, Three AS OurType)
END SUB
