多么糟糕的误会啊,我之前基本上是完全相反地误解了这件事,然后把所有关于我特定问题的地方都删除了。
我编写了一种自定义的引用类型,其实并不是真正的Clojure引用类型,但类似的东西。一个带有内容受控改变的盒子。结果是有点像atom或ref。
我的类型作为引用类型,有一个可变字段,指向引用本身指向的内容,还包括其他字段以方便其他操作。我想要使用compare and set来改变这个可变字段。
在“纯”Clojure中编写,唯一的方式是通过原子或AtomicReference包装在deftype字段中持有的值来做这件事。这可行,但会增加1或2级指针追踪。我想摆脱那些额外的指针。
Java提供了至少两种直接在可变字段上执行compare and set的设施(可能要求字段是volatile的,我忘记了)。这两个机制都通过创建一种字段访问器对象来实现。一个类的典型模式似乎是在静态初始化器中创建字段访问器对象,然后在实例的字段上执行cas类型操作时使用它。
典型的模式无法与原样使用的deftype配合工作,因为虽然你可以使deftype的字段可变,但这也会使其私有,从而使得构建字段访问器对象变得困难。由于字段是私有的,因此不能从"外部"构建,而且deftype不提供执行静态初始化的方法。 有解决这个问题的方法,基本上是向你的deftype添加一个什么也不做的函数,仅创建并返回字段访问器对象,然后在某些顶级静态上下文中构造一个你的deftype的虚拟实例并调用此方法。所以这是可行的,但有点糟糕。
我最初做了虚拟deftype实例的事情,但最终只是编写了一个极简化的deftype版本,用于生成具有字段和设置特定字段AtomicReferenceFieldUpdater的静态初始化器的类。这也行得通,但这依赖于对asm库的一些经验,并且需要注意使其与aot编译良好配合(我认为这一部分是对的,但不完全确定)。
比较和设置非常好,我们希望能提供一个在deftype字段上执行操作的方式,而无需将我们想要比较和设置的内容包装在额外的对象中。在java/jvm中存在实现此类操作的机制,但在Clojure中利用起来很痛苦。