#一致性 #同步 #广播 #无锁 #最终一致性 #数据结构

trailing_cell

为在读取速度重要且严格一致性不是必需的情况下(数据可能过时)共享数据结构提供包装器

5个不稳定版本

使用旧的Rust 2015

0.3.0 2018年1月17日
0.2.1 2018年1月11日
0.2.0 2018年1月11日
0.1.1 2018年1月10日
0.1.0 2018年1月10日

#一致性中排名第10

自定义许可证

16KB
221

尾随单元格

目的

这个小型项目受到像magneticevmap这样的作品的启发,这些作品专注于无锁。在这里,我介绍了一些表示“尾随状态”语义的某种Cell的包装器。这种结构在你有一个性能关键的数据结构,其中读取必须快速,但写入可以缓慢(可能非常罕见)的情况下很有用。关键在于状态由用户提供,并且由用户控制。

例如,我打算用它来存储游戏中的bidir-map,该映射将客户端ID(数量固定)映射到玩家ID(与玩家(如用户名)相关联)。

实用性

一组连接的TcWriter<M>可以具有任何数量(最初为0)的读取TcReader<T,M>对象,这些对象可以用于任何类型T(通常是同一类型的T)。这在以下情况下特别有用:

  • 包装的T数据具有集合W和R,其中W != R。
  • 读取速度比写入速度更重要。例如:写入非常罕见。
  • 如果读取状态稍微过时是可以接受的。

它还具备以下良好的特性:

  • 细粒度控制读取同步事件。
  • 写入者可以随时加入和离开(使用TcWriter::clone)。
  • 读取者可以随时加入和离开(使用TcWriter::add_reader)。
  • 提供阻塞和非阻塞写入选项。
  • 读取者可以解包以返回他们的T状态。

实现允许读取者不仅可以用不同的本地状态初始化,甚至可以用不同类型的初始状态初始化(只要它们都实现了与写入者相同的MTakesMessage<M>)。我不太清楚这个选项可能有什么用,但支持它并不需要任何成本,所以为什么不呢。

自己使用它

为了使编写者和读者能够通信,它们依赖于某种“消息”的概念。因此,在可以进行任何操作之前,需要为将要表示“状态”的对象实现trait TakesMessage。这涉及到只实现一个函数,该函数定义了当面对特定的消息时,如何更新你的状态对象。

接下来需要创建一个第一个写对象。所有连接到它的读取器都直接或间接从这个写对象继承而来。然后可以根据需要将这些读取器在多个线程上分配,每个线程调用所需的函数,最终都会归结为

  • 与写者同步。
  • 访问内部数据。

底层实现

TcWriterTcReader 实现为在 bus::Bus 上的包装器,其中写者作为 M 生产者,读取器作为 M 消费者。然而,任何写者的消息都会到达所有读取器。读取器在调用它们的 TcReader::update 函数时消费缓冲的消息,并将这些消息依次应用到它们局部状态上(由特定义义)。

示例

有关更多带注释的示例,请参阅 tests.rs

依赖关系

~0.6–0.9MB
~13K SLoC