2010-06-11 14 views
5

Il seguente codice di prova (F #) non restituisce il risultato che ci si aspetta:.NET 4 SpinLock

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 

mi aspetto il SpinLock di escludere reciprocamente il bancone e, di conseguenza, per poter tornare conta 1.000.000 ma, invece, restituisce valori più piccoli come se non si verificasse alcuna esclusione reciproca.

Qualche idea cosa c'è che non va?

risposta

3

MODIFICA: Stephen Swensen ha un modo per accedere direttamente a uno stile di riferimento SpinLock di seguito. ! restituisce una copia delle strutture quindi non dovrebbe essere utilizzato in questo caso.

Puoi avvolgere SpinLock in una classe che funziona (ho provato ad utilizzare uno SpinLock statica e immutabile inutilmente)

type SpinLockClass() = 
    let s = System.Threading.SpinLock(false) 
    member x.Enter locked = s.Enter(locked) 
    member x.Exit() = s.Exit() 

let safeCount() = 
    let n = 1000000 
    let counter = ref 0 
    let spinlock = SpinLockClass() 
    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 
+0

Grazie. Sembra che i campi nelle classi non vengano copiati ma tutto il resto. Se questo è giusto, ha anche implicazioni per altre applicazioni come l'aritmetica complessa, in cui si desidera evitare di copiare le strutture (e C# è attualmente molto più veloce di F #). –

8

SpinLock è un tipo di valore. Quando si disattiva la variabile spinLock (! SpinLock), la struttura viene copiata e il blocco inserito/chiuso è ora diverso.

+0

Può essere risolto? –

10

Il motivo per cui è stato copiato lo struct SpinLock è perché! è una funzione: le strutture vengono copiate quando vengono passate come argomenti a una funzione o restituite da una funzione (o qualsiasi altro tipo di assegnazione per quella materia). Tuttavia, se si accede direttamente al contenuto della cella di riferimento, non viene eseguita alcuna copia.

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