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 行
尾随单元格
目的
这个小型项目受到像magnetic
和evmap
这样的作品的启发,这些作品专注于无锁。在这里,我介绍了一些表示“尾随状态”语义的某种Cell
的包装器。这种结构在你有一个性能关键的数据结构,其中读取必须快速,但写入可以缓慢(可能非常罕见)的情况下很有用。关键在于状态由用户提供,并且由用户控制。
例如,我打算用它来存储游戏中的bidir-map
,该映射将客户端ID(数量固定)映射到玩家ID(与玩家(如用户名)相关联)。
实用性
一组连接的TcWriter<M>
可以具有任何数量(最初为0)的读取TcReader<T,M>
对象,这些对象可以用于任何类型T
(通常是同一类型的T)。这在以下情况下特别有用:
- 包装的
T
数据具有集合W和R,其中W != R。 - 读取速度比写入速度更重要。例如:写入非常罕见。
- 如果读取状态稍微过时是可以接受的。
它还具备以下良好的特性:
- 细粒度控制读取同步事件。
- 写入者可以随时加入和离开(使用
TcWriter::clone
)。 - 读取者可以随时加入和离开(使用
TcWriter::add_reader
)。 - 提供阻塞和非阻塞写入选项。
- 读取者可以解包以返回他们的
T
状态。
实现允许读取者不仅可以用不同的本地状态初始化,甚至可以用不同类型的初始状态初始化(只要它们都实现了与写入者相同的M
的TakesMessage<M>
)。我不太清楚这个选项可能有什么用,但支持它并不需要任何成本,所以为什么不呢。
自己使用它
为了使编写者和读者能够通信,它们依赖于某种“消息”的概念。因此,在可以进行任何操作之前,需要为将要表示“状态”的对象实现trait TakesMessage
。这涉及到只实现一个函数,该函数定义了当面对特定的消息时,如何更新你的状态对象。
接下来需要创建一个第一个写对象。所有连接到它的读取器都直接或间接从这个写对象继承而来。然后可以根据需要将这些读取器在多个线程上分配,每个线程调用所需的函数,最终都会归结为
- 与写者同步。
- 访问内部数据。
底层实现
TcWriter
和 TcReader
实现为在 bus::Bus
上的包装器,其中写者作为 M
生产者,读取器作为 M
消费者。然而,任何写者的消息都会到达所有读取器。读取器在调用它们的 TcReader::update
函数时消费缓冲的消息,并将这些消息依次应用到它们局部状态上(由特定义义)。
示例
有关更多带注释的示例,请参阅 tests.rs
。
依赖关系
~0.6–0.9MB
~13K SLoC