#style #run-time #glibc #one-time #ifunc #indirection #resolvable

indirect-once

类似于glibc的ifunc的一次可解析运行时间接

3个不稳定版本

0.2.0 2021年1月1日
0.1.1 2021年1月1日
0.1.0 2021年1月1日

#624过程宏

MIT/Apache

5KB
79

indirect-once

类似于glibc的ifunc的一次可解析运行时间接。

Crates.io Docs.rs GitHub top language

用法

indirect-once包提供了一些宏,用于帮助实现类似于glibc的ifunc的运行时间接(但不依赖特殊的编译器支持)。暴露的API旨在与ifunc API在精神上相似,但带有Rust风格。

示例

indirect-once支持两种宏风格。

过程宏

默认风格是一个属性过程宏。它看起来更干净,更接近原始的ifunc(该宏也作为属性暴露)。这种风格的缺点是它可能会引入对一些过程宏工具包的依赖,这可能会增加编译时间(如synproc_macro2quote等)。如果您认为保持依赖图小或尽可能降低编译时间很重要,可以通过禁用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