Something like the following works.
Making the field "private [this]" turns it into the desired field reference ("getfield").
Access from a different instance is through an accessor "state()" which, if made @inline, will happily loosen the access restriction to the field.
That also means that the updater (which happens to reside in the companion module) can also access it.
(Because the normal accessor for the var is not emitted for an object-private member, you can define your own, using parens. But you don't need to use parens at the call site, other.state. Your uniform access principle dollars at work. Or Swiss francs.)
Also notice the totally hip usage of `new`
in backticks for a param name. I don't even know how to make the ticks show up in this markup. Because both params are the same type, one is likely to want to write cas(expect=prev, `new`=changed)
, so I might have used next
instead, but if this markup supported a hipster thumbs-up, I'd give it right now. :+1: Did it work? Can anyone see my thumb? [I guess I saw that on github. Hubster, not hipster.]
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 = "Ivar@%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
}
Showing that state() is really inlined:
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
Not only is it "OK to ask and answer your own questions",
https://blog.stackoverflow.com/2011/07/its-ok-to-ask-and-answer-your-own-questions/
it's infinitely more satisfying.
(More power to Daniel Sobral, Rex Kerr, Retronym and the rest of the Justice League.)