7 个版本
0.2.2 | 2021年3月18日 |
---|---|
0.2.1 | 2020年6月9日 |
0.2.0 |
|
0.1.5 |
|
#288 in 并发
8,796 每月下载次数
用于 8 个 crates (3 直接)
58KB
1K SLoC
global_counter
此 crate 实现了全局计数器,包括通用和原始的计数器,它们基于经过充分测试的同步原语,即默认的 parking_lot
Mutex 和 stdlibs 的原子类型。还有更快但精度较低的计数器,具体细节请参阅文档。
使用方法
将以下依赖项添加到您的 Cargo.toml 文件中
[dependencies]
global_counter = "0.2.2"
导入时使用 #[macro_use]
注解,如下所示
#[macro_use]
extern crate global_counter;
如果您想禁用 parking_lot
的使用,并改为使用 stdlibs Mutex,请禁用默认功能
[dependencies.global_counter]
version = "0.2.2"
default-features = false
快速入门
创建一个计数器
use global_counter::generic::Counter;
use global_counter::primitive::exact::CounterI16;
// Generic
global_counter!(COUTER_NAME, CountedType, CountedType::default());
// If you feel funny, you can also create a generic global counter without a macro.
// Take a look at the implemtation of the macro, it's simply wrapping in a once_cell::sync::Lazy<...>.
// Primitive
static COUNTER_NAME : CounterI16 = CounterI16::new(0);
增加计数器的值
COUNTER_NAME.inc();
获取计数器的值
// Generic
let val_borrowed = COUNTER_NAME.get_borrowed();
// Or
let val = COUNTER_NAME.get_cloned();
// Primitive
let val = COUNTER_NAME.get();
示例 - 用于从多个线程中索引 vec 的原始计数器
#[macro_use]
extern crate global_counter;
use global_counter::primitive::exact::CounterUsize;
use std::sync::{Arc, Mutex};
fn main() {
// This is a primitive counter. Implemented using atomics, more efficient than its generic equivalent.
// Available for primitive integer types.
static COUNTER: CounterUsize = CounterUsize::new(0);
// We want to copy the 'from' arr to the 'to' arr. From multiple threads.
// Please don't do this in actual code.
let from = Arc::new(Mutex::new(vec![1, 5, 22, 10000, 43, -4, 39, 1, 2]));
let to = Arc::new(Mutex::new(vec![0, 0, 0, 0, 0, 0, 0, 0, 0]));
// 3 elements each in two other threads + 3 elements in this thread.
// After joining those two threads, all elements will have been copied.
let to_arc = to.clone();
let from_arc = from.clone();
let t1 = std::thread::spawn(move || {
// '.inc()' increments the counter, returning the previous value.
let indices = [COUNTER.inc(), COUNTER.inc(), COUNTER.inc()];
for &i in indices.iter() {
to_arc.lock().unwrap()[i] = from_arc.lock().unwrap()[i];
}
});
let to_arc = to.clone();
let from_arc = from.clone();
let t2 = std::thread::spawn(move || {
let indices = [COUNTER.inc(), COUNTER.inc(), COUNTER.inc()];
for &i in indices.iter() {
to_arc.lock().unwrap()[i] = from_arc.lock().unwrap()[i];
}
});
let indices = [COUNTER.inc(), COUNTER.inc(), COUNTER.inc()];
for &i in indices.iter() {
to.lock().unwrap()[i] = from.lock().unwrap()[i];
}
t1.join().unwrap();
t2.join().unwrap();
assert_eq!(**to.lock().unwrap(), **from.lock().unwrap());
}
示例 - 不克隆被计数的结构体
#[macro_use]
extern crate global_counter;
use global_counter::generic::{Counter, Inc};
use std::collections::LinkedList;
use std::iter::FromIterator;
// Note how this (supposedly) doesn't implement `Clone`.
#[derive(Debug, PartialEq, Eq)]
struct CardinalityCountedList(LinkedList<()>);
// Incrementing to us means just inserting another element.
impl Inc for CardinalityCountedList {
fn inc(&mut self) {
self.0.push_back(());
}
}
// Some helper methods.
impl CardinalityCountedList {
pub fn with_cardinality(card: usize) -> Self {
CardinalityCountedList(LinkedList::from_iter(std::iter::repeat(()).take(card)))
}
pub fn card(&self) -> usize {
self.0.len()
}
}
// We create a new global, thread-safe Counter.
// Could also do this in the main fn or wherever.
global_counter!(
COUNTER, // Name
CardinalityCountedList, // Type
CardinalityCountedList::with_cardinality(0) // Initial value
);
fn main() {
// Note how we use a borrow, but never clone this LinkedList.
// Of course, a cloning, convenient API is also available.
assert_eq!((*COUNTER.get_borrowed()).card(), 0);
let t1 = std::thread::spawn(move || {
for _ in 0..(1 << 20) {
COUNTER.inc();
}
});
let t2 = std::thread::spawn(move || {
for _ in 0..(1 << 20) {
COUNTER.inc();
}
});
t1.join().unwrap();
let card = (*COUNTER.get_borrowed()).card();
// t1 finished, t2 maybe did something.
assert!((1 << 20) <= card && card <= (2 << 20));
t2.join().unwrap();
// Both threads finished, the counter guarantees `Inc` was executed 2 << 20 times.
assert_eq!((*COUNTER.get_borrowed()).card(), 2 << 20);
}
变更日志
此库仍在开发中。达到相对稳定状态后,将引入详细的变更日志。将每个版本升级视为破坏性更改。
最小 Rust 版本
从版本 0.2.2 开始,此 crate 需要 Rust 版本 1.46 或更高版本才能编译。
许可证
根据您的选择,许可协议为以下之一
- Apache 许可证 2.0 (LICENSE-APACHE 或 https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT 许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
。
贡献
除非您明确声明,否则根据Apache-2.0许可证定义,您有意提交以包含在工作中的任何贡献,将按上述方式双重授权,不附加任何额外条款或条件。
依赖项
~0.5–0.8MB
~13K SLoC