The following test code (F#) is not returning the result I'd expect:
let safeCount() =
let n = 1000000
let counter = ref 0
let spinlock = ref <| SpinLock(false)
let run i0 i1 () =
for i=i0 to i1-1 do
let locked = ref false
try
(!spinlock).Enter locked
if !locked then
counter := !counter + 1
finally
if !locked then
(!spinlock).Exit()
let thread = System.Threading.Thread(run 0 (n/2))
thread.Start()
run (n/2) n ()
thread.Join()
!counter
I'd expect the SpinLock
to mutually exclude the counter and, therefore, for it to return counts of 1,000,000 but, instead, it returns smaller values as if no mutual exclusion is occurring.
Any ideas what's wrong?
The reason why the SpinLock struct is being copied is because ! is a function: structs are copied when passed as arguments to a function or returned from a function (or any other kind of assignment for that matter). However, if you access the contents of the ref cell directly, no copying takes place.
let safeCount() =
let n = 1000000
let counter = ref 0
let spinlock = ref <| SpinLock(false)
let run i0 i1 () =
for i=i0 to i1-1 do
let locked = ref false
try
spinlock.contents.Enter locked
if !locked then
counter := !counter + 1
finally
if !locked then
spinlock.contents.Exit()
let thread = System.Threading.Thread(run 0 (n/2))
thread.Start()
run (n/2) n ()
thread.Join()
!counter
SpinLock is a value type. When you dereference your spinLock variable (!spinLock), the struct got copied, and the lock you enter/exit is now different.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With