这是一个错误百出的喜剧,我之前基本上完全误解了事情的反面,并删除了我特定问题的所有引用。
我编写了一种自定义的引用类型,不是真正的 Clojure 引用类型,但是一种类似的东西。一个带有对内容进行控制变异的盒子。A 实际上类似于原子或 ref。
我的类型是一个引用类型,具有一个可变字段,该字段指向引用本身指向的内容,以及用于促进其他操作的其它字段。我希望使用 compare and set 更改这个可变字段。
在纯 Clojure 中编写,只能通过使用存储在 deftype 字段中的值的原子或 AtomicReference 包装来实现这一点。这没问题,但增加了 1 或 2 级指针跟踪。我希望去掉那些额外的指针。
Java 为在可变字段上直接执行比较和设置提供了至少两种不同的设施(可能需要该字段是 volative 的,我忘记了)。这两个机制都是通过创建一种类型的字段访问器对象来工作的。一个类的典型模式似乎是在静态初始化器中创建字段访问器对象,然后在执行基于 cas 的字段操作时引用它。
典型的模式不适用于当前的deftype,因为尽管你可以使deftype字段的属性可变,但这也会使其私有,这就使得构建字段访问器对象变得困难。由于字段是私有的,所以你不能从“外部”构建,因为deftype不提供进行静态初始化的方法。为此,你可以采取一些变通方法,基本上是在你的deftype中添加一个什么也不做的方法来创建和返回字段访问器对象,然后在某些顶级静态上下文中构建一个你的deftype的示例实例并调用该方法。因此,这是可行的,但相当糟糕。
我最初尝试了创建一个示例deftype实例,但最终只简写成一个非常简化的deftype以生成一个包含字段和用于为特定字段设置AtomicReferenceFieldUpdater的静态初始化器的类。这也奏效了,但需要有一定的asm库经验,并且需要小心才能使其与aot编译良好兼容(我认为这一部分是正确的,但不确定)。
比较和设置非常棒,我们希望能提供一种对deftype字段进行操作的方式,而不需要额外的 wrappers 对我们想要比较和设置的对象进行包装。在java/jvm中存在这样的机制,但在Clojure中充分利用这些机制是痛苦的。