;redcode
;name AsynchronousFlagsV1
;author Skybuck
;version 1
;history version 1 created on 7 december 2007
;
; Let's write an asynchronous flagging mechanisme.
;
; Since different copies, instances could be busy with different code paths
and lengths and therefore keeping them insync
; could be a difficult and unwanted requirement.
;
; So instead the idea is the following:
;
; Each instance can specify via a variable how long it thinks it can not
respond to flag changes because it's executing code.
;
; The length depends on the number of instructions it has to execute before
it can return to set a flag.
;
; The other instances could copy this time length into their own local
copies... and start decrementing it.
;
; Since all threads share the same ammount of cycles this will work if
thread specified the correct waiting ammount of time
; which should equal it's number of instructions it has to execute as
describe above.
;
; To proof that this concept could work I will write two warriors, which
execute totally different code and it should still work.
;
; The idea is as follows:
;
; When a warrior wants to know if another warrior is alive it will
"challenge" the other warrior.
; "Challenge" means setting the other warriors flag to zero.
;
; The warrior will then use the other warriors timeout value so to speak to
start waiting for the flag to come back online.
;
; If the other warrior's flag does not come back online on time it's an
indication the other warrior is dead or could not reach
; it's set flag instruction on time. which can only happen if for some
reason it executed more instruction then it should it's a
; clear indication something is wrong with the other warrior.
;
; Furthermore the challenging only works for two warriors... if it would
need to support multiple then the warriors would
; need to use multiple flags...
;
; One idea for multiple warriors could be to use the p-space... this safes
space on the core... reducing the risk of getting bombed
; and causing malfunction
;
; Each warrior would need it's own flag location or something... but let's
not go into that because things will get too complex
; and messy for now.
;
; The following code idea/algorithm will be used:
;
; "Challenge" the other warrior by setting it's flag to zero.
; set your own flag to alive.
; Copy the waiting time to a local variable
; Start a spinning loop and decrement the local variable.
; jump out of the loop if the flag came back online, indicating other
warrior is alive.
; or if loop exit is reached indicates other warrior malfunction.
;
; Warriors must first challenge each other, and then set their flag to
alive... otherwise they would dead lock
;
; Ok seems to be working just nice =D
;
spl Warrior2Begin
Warrior1Begin
Warrior1Length equ Warrior1End - Warrior1Begin
Warrior1MainLoopBegin
Warrior1ChallengeOtherWarrior
mov.ab #0, Warrior2IsAlive
Warrior1IamAlive
mov.ab #1, Warrior1IsAlive
Warrior1SetWaitingTime
mov.ab #Warrior1Length, Warrior1Timeout ; rough estimate for now
Warrior1CopyWaitingTimeFromOtherWarrior
mov.b Warrior2Timeout, Warrior1WaitForOtherWarrior
; could dead lock just hope both set flags before entering here
Warrior1TimeoutLoopBegin
jmn Warrior1DetectsWarrior2IsAlive, Warrior2IsAlive
djn Warrior1TimeoutLoopBegin, Warrior1WaitForOtherWarrior
Warrior1TimeoutLoopEnd
Warrior1DetectsWarrior2IsDead
mov #444, >Warrior1Debug ; debug code let know we detect warrior 2 is
dead.
jmp Warrior1CheckOtherWarriorDone
Warrior1DetectsWarrior2IsAlive
mov #555, >Warrior1Debug ; debug code let know we detect warrior 2 is
alive.
Warrior1CheckOtherWarriorDone
Warrior1DoSomeArbitraryStuff
nop $0, $0
nop $0, $0
nop $0, $0
djn warrior1skipdeath, #5
dat $0, $0 ; simulate death after 5 runs.
warrior1skipdeath
nop $0, $0
jmp Warrior1MainLoopBegin
Warrior1Data
Warrior1IsAlive dat $0, $0
Warrior1Timeout dat $0, $0
Warrior1WaitForOtherWarrior dat $0, $0
Warrior1Debug dat $0, $1000
Warrior1End
dat $0, $0
dat $0, $0
dat $0, $0
dat $0, $0
dat $0, $0
Warrior2Begin
Warrior2Length equ Warrior2End - Warrior2Begin
Warrior2MainLoopBegin
Warrior2IamAlive
mov.ab #1, Warrior2IsAlive
Warrior2SetWaitingTime
mov.ab #Warrior2Length, Warrior2Timeout
Warrior2ChallengeOtherWarrior
mov.ab #0, Warrior1IsAlive
Warrior2CopyWaitingTimeFromOtherWarrior
mov.b Warrior1Timeout, Warrior2WaitForOtherWarrior
Warrior2TimeoutLoopBegin
jmn Warrior2DetectsWarrior1IsAlive, Warrior1IsAlive
djn Warrior2TimeoutLoopBegin, Warrior2WaitForOtherWarrior
Warrior2TimeoutLoopEnd
Warrior2DetectsWarrior1IsDead
mov #666, >Warrior2Debug ; debug code let know we detect warrior 2 is
dead.
jmp Warrior2CheckOtherWarriorDone
Warrior2DetectsWarrior1IsAlive
mov #777, >Warrior2Debug ; debug code let know we detect warrior 2 is
alive.
Warrior2CheckOtherWarriorDone
Warrior2DoSomeArbitraryStuff
nop $0, $0
nop $0, $0
nop $0, $0
nop $0, $0
nop $0, $0
nop $0, $0
nop $0, $0
nop $0, $0
nop $0, $0
nop $0, $0
nop $0, $0
nop $0, $0
nop $0, $0
nop $0, $0
nop $0, $0
nop $0, $0
nop $0, $0
djn warrior2skipdeath, #10
dat $0, $0 ; simulate death after 3 runs.
warrior2skipdeath
nop $0, $0
nop $0, $0
jmp Warrior2MainLoopBegin
Warrior2Data
Warrior2IsAlive dat $0, $0
Warrior2Timeout dat $0, $0
Warrior2WaitForOtherWarrior dat $0, $0
Warrior2Debug dat $0, $5000
Warrior2End