4 个稳定版本

1.1.1 2023年9月21日
1.1.0 2022年12月12日
1.0.1 2023年9月21日
1.0.0 2022年7月19日

#290并发

每月 22 次下载
second-music-system 中使用

MIT/Apache

19KB
168 代码行

arcow

此 crate 提供了一个线程安全的、引用计数的指针,它使用写时复制语义来实现可变性。

我创建它是因为我不知道从 2015 年开始在标准 Rust 中就有的 Arc::make_mut 方法。我考虑过废弃它以支持标准解决方案,但有一些微小的优势可以勉强证明它是合理的

  • Arcow 比标准库中的 Arc::make_mut 更易于使用。(从缺点来说,更容易意外通过 Arcow 进行突变。)
  • Arcow 不支持弱引用,这使得它在运行时效率更高。

如何

创建一个 Arcow<T>。这就像一个可以廉价克隆的 T,可以像普通对象一样进行修改,即使 T 实际上克隆成本很高。你可以自由地将 Arcow<T> 的克隆发送到多个线程。

请注意,原子操作不是免费的;这就是为什么 Arcow 没有实现 Copy。只有当以下条件满足时,克隆 Arcow<T> 并将其发送到另一个线程才会比克隆 T 更便宜:

  1. T 很大(克隆成本高),并且
  2. Arcow<T> 的克隆中有相当一部分将在不进行突变的情况下被使用和消费。

为什么不

如果可能的话,您应该考虑使用 Cow<T>。如果您想要将突变传播到对同一底层 T 的其他引用,那么您根本不需要写时复制,您实际上想要做的是在 Mutex<T> 的包装中。

原因呢?

假设您正在实现一个游戏服务器。您跟踪多个游戏状态迭代,可能有很多,以允许保存、客户端预测和其他问题。您的大部分游戏状态都很简单,因此每个迭代只有一个单独的副本。但是,您的游戏发生在 Map 上,而这个 Map 通常大约有 64KiB。在总体规模上,这并不多,但它会迅速增加,将地图复制到每个新迭代的开销浪费了大量的 CPU 时间。您的自动测试尤其受到影响,因为它们几乎所有的空闲时间都在复制,而不是真正测试您的逻辑。

因此,您将 Map 包装在一个 Arc 中。现在,您已经用一个单一的原子操作替换了 64KiB 的副本。您拍拍自己的背,然后继续前进。

但问题是 Map 可以改变。

在绝大多数迭代中,Map 不会改变。但有时,有人会砍倒一棵树,或者建造一堵墙,或者铺路,当这样做时,这些更改将反映在 Map 中。如果您移除 Arc,这没有问题,因为每个迭代都有自己的地图副本来突变。但现在,您在每个迭代中都要复制整个 64KiB,尽管不到 1% 的迭代会随后突变地图。

Cow 对于这种情况不起作用,因为没有长期存在的“主副本”的地图,所有其他游戏状态都可以从中借用。没有特定的迭代可以信任这一点。旧迭代将随着它们不再相关而被修剪,新的迭代也不一定保留(例如,废弃的预测时间线)。

每当有变化时都克隆 Arc<Map> 是一个可行的解决方案,但如果有两个玩家在同一个时间单位砍倒一棵树怎么办?这是一个浪费的副本。然后还有这种情况,您是单玩家模式中客户端的内部服务器,只有一个相关的迭代...现在,每次更改都会复制 Map,尽管根本不超过一个引用!

因此,Arcow。它非常像一个简化的 Arc,但有一个额外的特性:它可以被突变。一个有生命的引用计数指针要么是唯一的,要么是共享的。如果您有一个唯一的 Arcow,突变很简单。 DerefMut 将返回对内部类型的可变引用。只要这个可变引用存在,您就不能再克隆 Arcow,因此唯一性得到保持。如果您有一个共享的 ArcowDerefMut 将首先将您的 Arcow “分割”成原始共享值的唯一克隆,然后您就设置好了。

(*并不完全准确。你可以克隆当前可变借用的一个 Arcow,但你之后不能再通过这个借用进行修改。查看:)

# use arcow::Arcow;
// error[E0502]: cannot borrow `a` as immutable because it is also borrowed as mutable
   let mut a = Arcow::new(456);
   let borrowed = &mut *a;
//                      - mutable borrow occurs here
   *borrowed = 42;
   let b = a.clone();
//         ^^^^^^^^^ immutable borrow occurs here
   *borrowed = 47;
// --------- mutable borrow later used here

法律条款

Arcow 版权所有 2022, 2023 Solra Bizna,并许可以下任一:

任选其一。

除非你明确声明,否则任何你有意提交以包含在 Arcow 库中的贡献,如 Apache-2.0 许可协议中定义的,应按上述方式双重许可,不附加任何额外条款或条件。

无运行时依赖