请分享您的想法,参加2024年Clojure调查!

欢迎!请参阅关于页面,了解有关此如何工作的更多信息。

+2
记录和类型
重新分类

作为一个非常注重原子和比较/设置作为并发原语的人来说,能够在不承担开销(更多的对象占用更多内存,更多的指针需要跟踪)的情况下对deftype中可变的字段进行比较/设置将非常不错。

JVM有几个机制能让您直接在字段上执行cas操作(AtomicReferenceFieldUpdater,VarHandles等)。deftype似乎可以提供这样的功能。

目前可以使用AtomicReferenceFieldUpdater与deftype配合使用,但由于volatile字段是私有的,并且缺少静态初始化器,导致操作较为复杂。

1 答案

0

这似乎是一个有趣的请求,但更像是一个解决方案而不是问题。您能否从那个角度重新陈述一下?

by
很抱歉,我实在不理解你在问什么。

我想这是你第二次或第三次对此提供类似的反馈(之前在 #clojure-dev),我已经重写了一篇,自认为已经包含了那些建议。感谢您花时间,但似乎很清楚,我就是不明白。
by
也就是说,“我正在尝试做X,但做不到”。X是什么?你在什么情况下需要这样做?
by
真是一场闹剧,我之前基本完全相反地误解了事情,甚至删除了所有与我特定问题相关的引用。

我编写了一种自定义的引用类型,并不是真的Clojure引用类型,但是一种类似的东西。一个拥有控制内容变异的盒子。A 最终变得有点像原子或ref。

我的类型是一个引用类型,它有一个可变字段,指向引用本身所指的任何内容,以及其他字段以辅助其他操作。我想使用比较和设置来变异这个可变字段。

在“纯”Clojure中编写,唯一的方法是通过在deftype字段周围的原子或AtomicReference包装器中使用值来实现。这行得通,但增加了1-2层的指针追踪级。我想去掉那些额外的指针。

Java 提供了至少两种直接在可变字段上执行比较和设置的设施(它们可能要求字段是volatile的,我忘记了)。这两种机制都通过创建某种字段访问器对象来实现。一个类的典型模式似乎是在静态初始化器中创建这个字段访问器对象,然后在需要在对实例字段的 cas 操作中使用它。

典型的模式不适用于当前的deftype,因为尽管可以通过设置deftype字段可变,但这也会将其变为私有,这使得构建字段访问器对象变得困难。由于字段是私有的,因此不能从“外部”构建,并且deftype不提供静态初始化的方法。 有解决这个问题的方法,基本思路是在你的deftype中添加一个方法,这个方法只负责创建并返回字段访问器对象,然后在某个顶层静态环境中构建一个deftype的示例实例并调用该方法。因此,可以使它工作,但这并不是一个好方法。

我最初尝试了بدائل به فرمRT.querySelectorAllcaffeine الت老家,但最终只是简单地给出了deftype的一个极其简化版的版本,以生成一个具有字段和设置特定字段AtomicReferenceFieldUpdater的静态初始化器的类。这也行得通,但依赖于asm库的一些经验,并且需要特别小心才能与aot编译良好配合(我认为这部分应该是对的,但不一定)。

比较并设置是非常好的,我们希望能够提供一种在deftype字段上执行该方法的方式,而无需在要比较和设置的内容周围添加额外的对象包装器。Java/jvm中存在实现这些功能的方法,但在Clojure中利用这些方法非常痛苦。
by
我认为Alex的要求仍然没有得到满足。即使使用原子引用和比较和设置,有可变状态也是解决你所尝试解决问题的方法。使用可变状态和CAS解决的问题是什么问题?

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