2012-09-19 7 views
8

La multa libreria di Twitter utilizza la seguente classe Java, che viene estesa da una classe Scala che legge il campo volatile e lo aggiorna utilizzando AtomicReferenceFieldUpdater. L'accesso deve essere almeno privato, vale a dire, deve consentire other.state.Twitter afferma che la Scala non può emettere un campo volatile grezzo non verniciato. Vero?

La richiesta motivazionale nel commento è vera? Quant'è vero? ("Come" significa in che modo e in che misura.)

public class IVarField<A> { 
    /** This is needed because we cannot create a field like this in Scala. */ 
    volatile State<A> state; 
} 

risposta

14

Qualcosa come i seguenti lavori.

Fare il campo "privato [questo]" lo trasforma nel riferimento di campo desiderato ("getfield").

L'accesso da un'istanza diversa avviene tramite un "stato()" di accesso che, se reso @inline, allenterà felicemente la restrizione di accesso al campo.

Ciò significa anche che l'aggiornamento (che si verifica risiedere nel modulo associato) può anche accedervi.

(Poiché il normale accesso per la variabile non viene emesso per un membro privato dell'oggetto, è possibile definire il proprio, utilizzando Parents. Tuttavia, non è necessario utilizzare Parens nel sito di chiamata, other.state. principio di accesso uniforme dollari sul lavoro o in franchi svizzeri)

Si noti inoltre l'uso totalmente hip di `new` nei backtick per un nome param. I non sanno anche come far apparire i tick in questo markup. Poiché entrambi i parametri sono dello stesso tipo, è probabile che uno voglia scrivere cas(expect=prev, `new`=changed), quindi avrei potuto usare next invece, ma se questo markup supportava un pollice in su, lo darei adesso. : +1: ha funzionato? Qualcuno può vedere il mio pollice? [Credo di averlo visto su Github. . Hubster, non lasciatevi intimidire]

object IVar { 
    // TODO: retrieve mangled name by reflection 
    private final val stateField = "com$twitter$concurrent$IVar$$state" 
    private val stateUpd = AtomicReferenceFieldUpdater.newUpdater(
     classOf[IVar[_]], classOf[State[_]], stateField) 
} 

final class IVar[A] { //}extends IVarField[A] { 
    import IVar._ 

    @volatile private[this] var state: State[A] = initState: State[A] 

    @inline private final def state(): State[A] = this.state 

    override def toString = "[email protected]%s(state=%s)".format(hashCode, state) 

    @inline private[this] 
    def cas(expect: State[A], `new`: State[A]) = stateUpd.compareAndSet(this, expect, `new`) 

    def depth: Int = { 
    @tailrec 
    def loop(iv: IVar[_], d: Int): Int = iv.state match { 
     case Linked(iv) => loop(iv, d + 1) 
     case _ => d 
    } 
    loop(this, 0) 
    } 
    // etc 
} 

Mostrando questo stato() è davvero inline:

private final int loop$1(com.twitter.concurrent.IVar, int); 
    flags: ACC_PRIVATE, ACC_FINAL 
    Code: 
    stack=3, locals=5, args_size=3 
     0: aload_1 
    // Field com$twitter$concurrent$IVar$$state:Lcom/twitter/concurrent/ivar/State; 
     1: getfield  #16     
     4: astore_3 

Non solo è "OK per chiedere e rispondere alle vostre proprie domande",

http://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/

è infinitamente più soddisfacente.

(Più potere per Daniel Sobral, Rex Kerr, Retronym e il resto della Justice League.)

Problemi correlati