3个不稳定版本
0.2.0 | 2021年1月1日 |
---|---|
0.1.1 | 2021年1月1日 |
0.1.0 | 2021年1月1日 |
#624 在 过程宏
5KB
79 行
indirect-once
类似于glibc的ifunc
的一次可解析运行时间接。
用法
indirect-once
包提供了一些宏,用于帮助实现类似于glibc的ifunc
的运行时间接(但不依赖特殊的编译器支持)。暴露的API旨在与ifunc
API在精神上相似,但带有Rust风格。
示例
indirect-once
支持两种宏风格。
过程宏
默认风格是一个属性过程宏。它看起来更干净,更接近原始的ifunc
(该宏也作为属性暴露)。这种风格的缺点是它可能会引入对一些过程宏工具包的依赖,这可能会增加编译时间(如syn
、proc_macro2
、quote
等)。如果您认为保持依赖图小或尽可能降低编译时间很重要,可以通过禁用proc-macro
功能来选择退出。
use indirect_once::*;
// Two implementations of foo. One should be picked at runtime based on hardware features.
fn foo_with_avx(x: i32, y: u8, p: bool) -> u16 { unimplemented!() };
fn foo_with_sse(x: i32, y: u8, p: bool) -> u16 { unimplemented!() };
// A resolver function to decide which to pick. Gets called at most once, the first time foo is called.
fn resolve_foo() -> &'static fn(i32, u8, bool) -> u16 {
if(cpu_has_avx!()) {
&(foo_with_avx as _)
} else {
&(foo_with_sse as _)
}
}
// Now define the real foo.
#[indirect(resolver = "resolve_foo")]
pub fn foo(x: i32, y: u8, p: bool) -> u16 {}
macro_rules!
宏
另一种宏风格是简单的macro_rules!
宏。生成的代码非常相似,但它不引入任何过程宏包。
use indirect_once::*;
// Two implementations of foo. One should be picked at runtime based on hardware features.
fn foo_with_avx(x: i32, y: u8, p: bool) -> u16 { unimplemented!() };
fn foo_with_sse(x: i32, y: u8, p: bool) -> u16 { unimplemented!() };
// A resolver function to decide which to pick. Gets called at most once, the first time foo is called.
fn resolve_foo() -> &'static fn(i32, u8, bool) -> u16 {
if(cpu_has_avx!()) {
&(foo_with_avx as _)
} else {
&(foo_with_sse as _)
}
}
// Now define the real foo.
pub indirect_fn! {
resolver = resolve_foo; fn foo(x: i32, y: u8, p: bool) -> u16 {}
}
行为
在任一风格中,指定在宏或属性的resolver
参数中的函数将在第一次调用新声明的函数时最多调用一次。
默认情况下,实现使用std::sync::Once
,但parking-lot
功能将其替换为基于parking_lot::Once
的后端。在任何情况下,一旦解析器运行过一次,这应该是一个简单的原子加载。
许可
indirect-once
采用MIT许可和Apache 2.0许可的双重许可。您可以选择您喜欢的任意一个。
依赖关系
~0–6MB