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

欢迎!有关如何使用本网站更多信息,请参阅关于页面。

+2
记录和类型
重新分类

作为一个对原子和比较并设置作为并发原语非常感兴趣的人,能够在deftype的可变字段上进行比较并设置操作会很好,这样可以避免Java的AtomicReference或clojure atom之所带来的开销(更多对象占用更多内存,追踪更多指针)。

JVM有几种机制可以直接在字段上执行CAS(AtomicReferenceFieldUpdater,VarHandles等)。看起来deftype可以根据请求提供这样的功能。

目前可以使用AtomicReferenceFieldUpdater与deftype,但由于volatile字段是私有的,以及缺少静态初始化器,这有些复杂。

1 答案

0

这听起来像一项有趣的要求,但它更像是一个解决方案而非一个问题。您能从那个角度重新表述一下吗?

很抱歉,我实在不明白你在问什么。

我想这已经是你第二次或第三次就这个问题给出类似反馈了(之前在 #clojure-dev),我已经重写过一次(我以为)以包括那个反馈。感谢你抽出时间,但很明显,我就是不明白。
也就是说,“我正在尝试做X,但我做不到”。X是什么?在什么情况下你需要这样做?
真是出丑,我之前基本上误解了相反的意思,并删除了我具体问题中所有的引用。

我编写了一种自定义类型的引用类型,其实并不是Clojure的引用类型,而是一种类似的东西。一个带有内容控制的方盒引证类型。A最终变得略微像原子或引用。

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

在“纯Clojure”中编写,唯一的方法是通过在deftype字段中使用atom或AtomicReference包装器来持有值。这可以工作,但会增加1或2层指针追踪。我想去掉这些额外的指针。

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

典型的模式不适用于当前的deftype,因为尽管您可以使得deftype字段可变,但这也会使其成为私有,从而难以构造字段访问对象。由于字段是私有的,所以您不能从“外部”构造它,并且deftype没有提供进行静态初始化的方法。有办法绕过这个问题,基本上是在您的deftype中添加一个什么也不做的方法,创建并返回字段访问对象,然后在某些顶层静态上下文中构造一个您的deftype的空实例并调用该方法。因此,这样做是可行的,但很糟糕。

我开始尝试构造空的deftype实例,但最终只写了一个极度简化的deftype版本,用于生成具有字段和设置特定字段AtomicReferenceFieldUpdater的静态初始化器的类。这也可行,但这依赖于对asm库的一些经验,并且需要小心以良好地配合aot编译(我认为我已经处理对了,但不确定)。

比较和设置很棒,如果能提供一种方法在deftype字段上进行比较和设置,而不需要对想要比较和设置的值添加额外的对象包装,那就更好了。在Java/jvm中存在实现这种方法的机制,但在Clojure中利用这些机制很痛苦。
我认为Alex的要求尚未满足。即使使用原子引用和比较和设置,具有可变状态也是解决您试图解决的问题的解决方案。使用可变状态和CAS要解决什么问题?

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