1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
//! C 回调上下文的统一访问入口
//!
//! 官方 SDK 的多处接口要求调用方以 `void*` 形式移交回调上下文。本模块把
//! 「解引用该指针并调用 Rust 闭包」这一公共骨架收敛到一处,供各处 C 跳板复用。
//!
//! # 为何要有这一层
//!
//! 镜像拉取进度、镜像推送进度与组件安装进度三处跳板,骨架完全相同:
//! 判空 → 捕获 panic → 取 `Mutex` 锁 → 调用闭包。三份拷贝意味着「跨 FFI
//! 边界必须 `catch_unwind`」「并发回调必须串行化」这两条硬约束要在三个
//! 地方各自被想起一次——漏掉任何一处都是未定义行为或数据竞争。
//!
//! # 上下文的内存布局约定
//!
//! 上下文一律为 `Box<Mutex<F>>` 经 `Box::into_raw` 拆出的裸指针。以
//! `Mutex` 包裹是为了在官方从多线程并发派发时,把对闭包的调用串行化:
//! 各处跳板只要求 `F: Send`(而非 `Sync`),闭包内部状态不能被假定为
//! 单线程访问,这一点与 [`crate::session::WslcSessionHandle::register_crash_dump_callback`]
//! 采用的防护等级一致。
use c_void;
/// 在回调上下文中串行化地执行闭包,返回结果;上下文为空或调用失败时返回 `None`
///
/// # Safety
///
/// `context` 必须是由 `Box::into_raw(Box::new(Mutex::new(f)))` 拆出的、
/// 指向 `Mutex<F>` 的有效指针,且 `F` 必须与拆出时的类型严格一致。
/// 在官方停止回调之前,该内存必须保持有效——按错误类型回收会造成内存损坏。
pub unsafe