#share #lock #data #debugging

resman

运行时管理资源借用

16 次重大发布

0.17.0 2023年9月23日
0.16.1 2023年4月6日
0.16.0 2022年12月26日
0.15.0 2022年7月5日
0.3.0 2021年6月28日

#141 in 并发

Download history 129/week @ 2024-04-05 132/week @ 2024-04-12 133/week @ 2024-04-19 190/week @ 2024-04-26 137/week @ 2024-05-03 137/week @ 2024-05-10 96/week @ 2024-05-17 127/week @ 2024-05-24 127/week @ 2024-05-31 60/week @ 2024-06-07 91/week @ 2024-06-14 84/week @ 2024-06-21 42/week @ 2024-06-28 15/week @ 2024-07-05 84/week @ 2024-07-12 90/week @ 2024-07-19

每月 233 次下载
用于 28 Crates (直接使用 3 个)

MIT/Apache 许可

120KB
3K SLoC

🗂️ resman

Crates.io docs.rs CI Coverage Status

运行时管理资源借用。

此库提供了一个可以存储任何类型之一以及同时为每种类型提供可变借用的映射。

注意: 此实现是从 shred 中提取的,以下有一些不同:

  • Debug 实现打印出键的类型名称而不是类型 ID。
  • 使用 downcast-rs 而不是 mopa 来进行类型降级。
  • 当资源类型实现了这些特质时,为借用类型添加了 DebugPartialEq 实现。
  • 当资源已被借用时,对于 try_borrow* 函数,返回 Err 而不是引发恐慌。

用法

将以下内容添加到 Cargo.toml

resman = "0.16.0"

# or
resman = { version = "0.17.0", features = ["debug"] }
resman = { version = "0.17.0", features = ["fn_res"] }
resman = { version = "0.17.0", features = ["fn_res", "fn_res_mut"] }
resman = { version = "0.17.0", features = ["fn_res", "fn_meta"] }
resman = { version = "0.17.0", features = ["fn_res", "fn_res_mut", "fn_meta"] }

# requires nightly
resman = { version = "0.17.0", features = ["fn_res", "fn_res_mut", "fn_res_once"] }

代码中

use resman::Resources;

#[derive(Debug)]
struct A(u32);
#[derive(Debug)]
struct B(u32);

let mut resources = Resources::default();

resources.insert(A(1));
resources.insert(B(2));

// We can validly have two mutable borrows from the `Resources` map!
let mut a = resources.borrow_mut::<A>();
let mut b = resources.borrow_mut::<B>();
a.0 = 2;
b.0 = 3;

// We need to explicitly drop the A and B borrows, because they are runtime
// managed borrows, and rustc doesn't know to drop them before the immutable
// borrows after this.
drop(a);
drop(b);

// Multiple immutable borrows to the same resource are valid.
let a_0 = resources.borrow::<A>();
let _a_1 = resources.borrow::<A>();
let b = resources.borrow::<B>();

println!("A: {}", a_0.0);
println!("B: {}", b.0);

// Trying to mutably borrow a resource that is already borrowed (immutably
// or mutably) returns `Err`.
let a_try_borrow_mut = resources.try_borrow_mut::<A>();
let exists = if a_try_borrow_mut.is_ok() {
    "Ok(..)"
} else {
    "Err"
};
println!("a_try_borrow_mut: {}", exists); // prints "Err"

功能

"debug":

Debug 实现 Resources 将在打印时使用值的 Debug 实现。这要求所有 Resources 也实现 Debug

示例

use resman::Resources;

let mut resources = Resources::default();
resources.insert(1u32);
println!("{:?}", resources);

// Without `"debug"` feature:
// {u32: ".."}

// With `"debug"` feature:
// {u32: 1}

"fn_res":

启用 FnRes 特质,允许在泛型函数类型下动态调用函数。

此 API 的使用方法如下:

  1. 定义要运行的常规函数或闭包。

    • 函数应将 &T&mut T 作为参数。
    • 所有函数的返回类型应相同。

    目前参数限制为 7 个。

  2. 调用 my_function.into_fn_res() 以获得 Box<dyn FnRes>

  3. 调用 fn_res.call(&resources) 以自动从 resources 借用 T 并调用函数。

示例

use resman::{FnRes, IntoFnRes, Resources};

/// Borrows `u32` mutably, and `u64` immutably.
fn f1(a: &mut u32, b: &u64) -> u64 {
    *a += 1;
    *a as u64 + *b
}

/// Borrows `u32` immutably, and `u64` mutably.
fn f2(a: &u32, b: &mut u64) -> u64 {
    *b += 1;
    *a as u64 + *b
}

let functions = [
    f1.into_fn_res(),
    f2.into_fn_res(),
    (|a: &u32, b: &u64| *a as u64 + *b).into_fn_res(),
];

let mut resources = Resources::default();
resources.insert(0u32);
resources.insert(0u64);

let sum = functions
    .iter()
    .fold(0, |sum, fn_res| sum + fn_res.call(&resources));

assert_eq!(5, sum); // 1 + 2 + 2

let debug_str = format!("{:?}", resources);
assert!(debug_str.contains("u32: 1"));
assert!(debug_str.contains("u64: 1"));

由于 Resources 具有内部可变性,在使用 FnRes::call 时,必须注意不要同时运行多个从 Resources 可变借用相同值的函数,否则会导致恐慌。

使用 FnRes::try_call 的非恐慌版本,如果在运行时出现重叠借用冲突,它将返回一个 BorrowFail 错误。

"fn_res_mut":

"fn_res" 类似,启用 IntoFnResMutFnResMut 特性。

FnResMut 为实现了 impl FnMut 的函数和闭包实现,但不为 Fn 实现。

"fn_res_once":

需要使用 nightly

"fn_res_mut" 类似,启用 IntoFnResOnceFnResOnce 特性。

FnResOnce 为实现了 impl FnOnce 的函数和闭包实现,但不为 FnMut 实现。

"fn_meta":

FnMeta 作为隐式特性添加到 FnRes。这意味着可以查询任何 FnRes 的函数元数据。

"high_arg_count":

FnResIntoFnResIntoFnResource 实现的参数数量从 6 增加到 8。

这是因为随着参数数量的增加,编译时间显著增加——当仅启用 "fn_res" 时,从 6 个参数的 4 秒增加到 8 个参数的 26 秒,当启用 "fn_mut""fn_once" 时,可高达一分钟。

另请参阅

  • anymap:任何类型的映射,没有多个可变借用。
  • rt_map:从映射中进行运行时管理的可变借用。
  • shred:包含 Resources 类型,以及一个任务调度器。

许可证

根据您选择,许可为以下之一

自由选择。

贡献

除非您明确说明,否则根据 Apache-2.0 许可证定义,任何有意提交以包含在您的工作中的贡献,都将按上述方式双许可,没有任何额外的条款或条件。

依赖关系

~1MB
~22K SLoC