2024 Clojure调查!中分享您的想法。

欢迎!请查看关于页面以了解更多关于如何操作的信息。

+2 投票

作为一名对原子和比较/设置作为并发原语的实现非常感兴趣的人,能够在不承担开销(更多对象将占用更多内存,并且需要更多的指针进行追踪)的情况下,在deftype的可变字段上执行比较和设置将是非常好的。

JVM有几个机制允许您直接在字段上执行CAS(AtomicReferenceFieldUpdater,VarHandles等)。似乎deftype可以在请求时提供此类功能。

目前可以使用AtomicReferenceFieldUpdater与deftype一起使用,但因其私有volatile字段和缺乏静态初始化而相当复杂。

1 个答案

0 投票

这看起来像是一个有趣的需求,但更多是解决方案而不是问题。能否从一个更全面的视角来重新提出它?

对不起,我实在不明白你在问什么。

我认为这是你第二次或第三次对此给出类似的反馈(之前在 #clojure-dev),我已经修改了一次以(我认为)包含该反馈。感谢您抽出时间,但看来很清楚,我就是不懂。
也就是,“我在尝试做X,但做不到”。X是什么?为什么需要这样做的情况?
多么糟糕的误会啊,我之前基本上是完全相反地误解了这件事,然后把所有关于我特定问题的地方都删除了。

我编写了一种自定义的引用类型,其实并不是真正的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中利用起来很痛苦。
by
我认为Alex的要求仍然没有满足。有一个可变的对象,即使是一个类似于引用和比较和设置的原子对象,也是解决你正在尝试解决的问题的方法。使用可变状态和CAS要解决的问题是什么?

如果我们能回到原始问题,那么可能发生以下两种情况之一......要么1)我们将发现其他解决此问题的好方法,这些方法使用Clojure中的现有结构,要么2)我们面临一个具有挑战性的未解决的问题,这可能导致语言的扩展、库的扩展或新库的出现。
by
我来这里是因为我认为使用具有可变状态的deftype可能是我面临问题的良好解决方案。我有一个基于Clojure代码的UI,我需要实现/扩展TableModel的一个实现,并将其提供给JTable实例。某种程度上,我需要更新TableModel的内容...我想我可以完全重新创建它,并每次都给JTable一个新的TableModel,但这似乎对Swing来说并不高效。我还可以使用gen-class - 如果这是最好的方式,那么就没问题。我希望显示的数据在我应用状态中,而应用状态在atom中。当数据发生变化时,我想将更改发送到应用状态atom上的swap!,并将这些更改传播回TableModel,然后使用JTable显示。所以问题/问题是如何将TableModel连接到应用状态。
by
将这些内容写出来后,我的解决方案似乎很明确...直接从TableModel引用应用状态,并在应用状态更改时触发表格结构/行等更改。然而,还有一层我没有提到。我实际上正在使用UI的FRP(函数响应式编程)。所以视图是应用状态的一个函数。视图函数是一个纯函数,但由于Swing中JTable的编码方式,它必须包含对实际数据的引用。因此,我必须为每次视图渲染创建一个新的TableModel,使用某些自定义或现有类在TableModel中存储状态,违反此案例的FRP模型,或者我没有想到的其他方法。
...