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

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

+2

作为一名真正对原子和compare-and-set作为并发原语很感兴趣的人,能够在没有额外开销(更多对象占用更多内存,更多指针要追踪)的情况下,在对deftype中的可变字段进行compare-and-set操作将会很棒,不管是使用java AtomicReference还是clojure atom。

Java虚拟机有几种机制可以让您直接在字段上实现cas(如AtomicReferenceFieldUpdater、VarHandles等)。看起来deftype可以按请求提供此类功能。

目前可以使用AtomicReferenceFieldUpdater与deftype搭配使用,但因为私有volatile字段和缺少静态初始化器,操作相对复杂。

1 个答案

0

这似乎是一个有趣的要求,但它更是一个解决方案而不是问题。你能从那个角度重述一下吗?

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

我觉得这是第二次或第三次你在这(之前在 #clojure-dev)给出类似的反馈,我已经重写了一篇(我认为)包含这些反馈的文章。感谢你花时间,但很明显,我并没有明白。
例如,"我正在尝试构建 X,但做不到"。X 是什么?在什么情况下你需要这样做?
这是一个荒谬的错误喜剧,我以前基本相反地理解了这些事情,并删除了我特定问题的所有引用。

我编写了一种定制的引用类型,不是真正的 Clojure 引用类型,但是一种类似的东西。一个带有内容受控变异的箱子。A 最终会变得稍像是原子或 ref。

我的类型是一种引用类型,有一个指向引用自身指向内容的可变字段,以及其他方便执行其他操作的 fields。我希望使用 compare and set 来修改这个可变字段。

在 "vanilla" Clojure 中编写,唯一能够实现这种方法的方法是使用原子或 AtomicReference 包装在 deftype 字段中的值。这工作,但增加了 1 或 2 个指针追逐级别。我想去掉这些额外的指针。

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

典型的模式不适合与原生的deftype一起使用,尽管你可以使一个deftype字段可变,但这也会使其成为私有,从而使得构建字段访问器对象变得困难。你不能从“外部”构建一个,因为字段是私有的,而且deftype也不提供进行静态初始化的方式。大致有几种解决办法,基本思路是在你的deftype中添加一个方法,这个方法除了创建和返回字段访问器对象外什么都不做,然后在某个顶层静态环境中构建一个deftype的伪实例并调用该方法。因此,这实际上是可行的,只是有点糟糕。

起初我尝试构建一个伪deftype实例,但最终我只编写了一个极简化版本的deftype,用来生成一个具有字段和一个静态初始化器的类,该初始化器为特定字段设置AtomicReferenceFieldUpdater。这也可行,但依赖于对asm库的一些经验,以及与aot编译兼容的细心处理(我认为这一点做到了,但不是很确定)。

Compare-and-set非常棒,如果能有一种方法在deftype字段上实现它而不需要在比较和设置的想要比较和设置的内容周围添加额外的对象封装,那就更好了。机制存在于Java/JVM中,但在Clojure中利用它非常痛苦。
by
我认为Alex的要求仍未实现。即使使用atom-like reference和compare-and-set,使某些东西可变也是解决你试图解决的问题的方案。什么是使用可变状态和CAS解决的问题呢?

如果我们能一直追溯到原始问题,那么可能会有两种情况发生……一是1)我们发现有一些好方法可以解决Clojure中现有构造的问题,二是有可能是一个具有挑战性的未解决的问题,它可能导致语言、库或新库的增加。
by
我来到这里是因为我觉得具有可变状态的deftype可能是解决我所遇到问题的好方法。我有一个基于Clojure代码的用户界面,我需要实现/扩展TableModel的一个实现,并将其提供给我的JTable实例。我需要某种方法来更新TableModel的内容……我想我可以重新创建它并每次给JTable一个新的TableModel,但这对于Swing来说似乎效率不高。我也可以使用gen-class,如果这是最好的方法,那么将没问题。我想要显示的数据在我应用程序的状态中,它位于一个atom中。数据变更时,我想将这些更改发送到app state atom上的swap!,并将这些更改传播回TableModel,并随后通过JTable显示它们。所以问题/疑问是如何将TableModel连接到app状态。
将这些内容写出来,我的解决方案看起来很明确...即直接从表格模型引用应用程序状态,并在应用程序状态更改时触发表格结构/行等更改。然而,我漏提到了一个层次。我实际上在使用FRP(函数式反应式编程)进行UI开发。因此,视图是应用程序状态的函数。视图函数是纯函数,但鉴于JTable在Swing中的编码方式,它必须包含实际数据的引用。因此,我可以选择在每次视图渲染时创建一个新的表格模型,使用某些自定义或现有类在表格模型中存储状态,违反该案例的FRP模型,或者考虑其他我尚未想到的解决方案。
...