Code: Select all
'iLock and iUnLock are single level locks using integers as workbuffers
'they are threadsafe and highly efficient.
' if iLock(fThisLock) then try
' finally
' iUnlock(fThisLock);
' end;
' InterlockedDecrement == __sync_sub_and_fetch()
' InterlockedIncrement == __sync_add_and_fetch()
' sleep == sleep?
type bBool as integer
sub iUnlock pascal(ByRef Flag as Integer)
'in-eax- [flag], ecx,edx free
asm
'reset the signal
push eax
call InterlockedDecrement
end asm
end sub
function iLock pascal(ByRef Flag as Integer) as bBool
'in-eax- [flag], ecx,edx free
asm
' <signal> is a signal to this block of code being in use
cmp eax,0 'nil pointer?
jz @nowork 'trapped; returns false
'
push ebx 'save original
mov ebx, eax 'sleep will reuse eax,ecx,edx
@AquireLock:
cmp [ebx],0 'ok.. is the Flag=0?
jz @GotLock 'it is, oh joy
'give up the time-slice and wait for the number to become 0.
push $00000000
call sleep
jmp @AquireLock
@GotLock: 'we got the lock
push ebx 'pass the var pointer
call InterlockedIncrement ' increment the value
'
@InsanityCheck: 'trap is the var is now <> 1 for some reason
cmp [ebx],1 'ok.. is the Flag set to 1?
je @done 'good. that's as it should be.
@InsanityFixup: 'decrement, wait randomly, try again
push ebx 'pass the var pointer
call InterlockedDecrement ' reset the signal to make up for the attempt
'
push ebx 'save the var pointer
mov eax, esi 'pick up the value of the stack as most random
and eax,$1F 'limit the range to 5 bits
push eax 'push the parameter 0..31 ms delay
call sleep 'sleep for some random period so we dont deadlock
pop ebx 'restore the var pointer
'
push ebx 'and push it again before reentering the loop
jmp @AquireLock 'start over
@done: 'really done.
pop ebx 'restore the original
mov eax,1 'return true
@nowork:
end asm
end function