; Listing11-2.asm
;
; A program that demonstrates thread-safe
; data sharing between fibers.

            option     casemap:none
            .nolist
            include    aoalib.inc
            include    aoaProcs.inc
            includelib aoalib.lib
            include    c:\masm32\include64\win64.inc
            include    c:\masm32\include64\kernel32.inc
            includelib c:\masm32\lib64\kernel32.lib  
            
            .list
            
; Program title:

            .const
             align  word
ttlStr       byte   "Listing 11-2", 0


; Fiber data shared among all the fibers:

fiberData_t struct
fiberMain   qword   ?       ;Pointer to asmMain object
fiber1      qword   ?       ;Pointer to fiber1 object
fiber2      qword   ?       ;Pointer to fiber2 object
fiber1Data  dword   ?       ;Data for fiber1
fiber2Data  dword   ?
asmMainData dword   ?
fiberData_t ends
            
            
            .data
mainFiber   qword   ?       ;Pointer to Windows' asmMain stuff
fiber       qword   ?       ;Pointer to Windows' myFiber stuff
fiberData   dword   456
            .code


            locals  fiber1, fiberData:qword
fiber1      proc
            push    rbp
            mov     rbp, rsp
            sub     rsp, 80
            
            mov     fiber1$fiberData, rcx
            mov     (fiberData_t ptr [rcx]).fiber1Data, 123
            
; Switch over to fiber2:

            call    print
            byte    "switching to fiber2", nl, 0
            
            mov     rcx, (fiberData_t ptr [rcx]).fiber2
            call    SwitchToFiber

            leave   ;Never executes, just because...
            ret
fiber1      endp

            locals  fiber2, fiberData:qword
fiber2      proc
            push    rbp
            mov     rbp, rsp
            sub     rsp, 80
            
            mov     fiber2$fiberData, rcx
            mov     (fiberData_t ptr [rcx]).fiber2Data, 456
            
; Switch over to asmMain:

            call    print
            byte    "switching to asmMain", nl, 0
            
            mov     rcx, (fiberData_t ptr [rcx]).fiberMain
            call    SwitchToFiber

            leave   ;Never executes, just because...
            ret
fiber2      endp

;--------------------------------------------------
;
; Here is the main assembly language function.
            
            locals  asmMain, fiberData:fiberData_t
            
            public  asmMain
asmMain     proc
            push    rbp
            mov     rbp, rsp
            sub     rsp, 128

; Initialize the fiberData fields:

            mov     asmMain$fiberData.asmMainData, 0
            mov     asmMain$fiberData.fiber1Data, 1
            mov     asmMain$fiberData.fiber2Data, 2

; Conver asmMain to fiberMain:
            
            lea     rcx, asmMain$fiberData
            call    ConvertThreadToFiber
            mov     asmMain$fiberData.fiberMain, rax

; Create fiber1:
            
            xor     rcx, rcx
            lea     rdx, fiber1
            lea     r8, asmMain$fiberData
            call    CreateFiber
            mov     asmMain$fiberData.fiber1, rax

; Create fiber2:
            
            xor     rcx, rcx
            lea     rdx, fiber2
            lea     r8, asmMain$fiberData
            call    CreateFiber
            mov     asmMain$fiberData.fiber2, rax
            
; Switch between the fibers:

            call    print
            byte    "Switching to fiber1", nl, 0
            
            mov     rcx, asmMain$fiberData.fiber1
            call    SwitchToFiber
                        
            mov     edx, asmMain$fiberData.asmMainData
            mov     r8d, asmMain$fiberData.fiber1Data
            mov     r9d, asmMain$fiberData.fiber2Data
            call    print
            byte    "Before quitting, aM=%d, f1=%d, f2=%d"
            byte    nl, 0
            
; Clean up the fiber2 we created:

            mov     rcx, asmMain$fiberData.fiber1
            call    DeleteFiber
            
            mov     rcx, asmMain$fiberData.fiber2
            call    DeleteFiber
            
            call    ConvertFiberToThread
            test    al, al
            jnz      allDone
            
            call    GetLastError
            mov     edx, eax
            call    print
            byte    "Windows error %d converting fiber "
            byte    "to thread", nl, 0
            
allDone:    leave
            ret
        
asmMain     endp
            end