Rust中的胖指针怎么使用

发布时间:2021-12-27 09:37:48 作者:iii
来源:亿速云 阅读:409

这篇文章主要讲解了“Rust中的胖指针怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Rust中的胖指针怎么使用”吧!

唤醒器

Waker  类型允许在运行时的reactor 部分和执行器部分之间进行松散耦合。
通过使用不与  Future  执行绑定的唤醒机制,运行时实现者可以提出有趣的新唤醒机制。例如,可以生成一个线程来执行一些工作,这些工作结束时通知  Future  ,这完全独立于当前的运行时。
如果没有唤醒程序,执行程序将是通知正在运行的任务的唯一方式,而使用唤醒程序,我们将得到一个松散耦合,其中很容易使用新的  leaf-future  来扩展生态系统。
如果你想了解更多关于 Waker 类型背后的原因,我可以推荐   Withoutboats articles series about them   。  

理解唤醒器

在实现我们自己的  Future  时,我们遇到的最令人困惑的事情之一就是我们如何实现一个唤醒器。创建一个 Waker 需要创建一个 vtable,这个vtable允许我们使用动态方式调用我们真实的Waker实现.
如果你想知道更多关于Rust中的动态分发,我可以推荐 Adam Schwalm 写的一篇文章     Exploring Dynamic Dispatch in Rust   .  
让我们更详细地解释一下。

Rust中的胖指针

为了更好地理解我们如何在 Rust 中实现 Waker,我们需要退后一步并讨论一些基本原理。让我们首先看看 Rust 中一些不同指针类型的大小。
运行以下代码:

trait SomeTrait { }
fn main() {    println!("======== The size of different pointers in Rust: ========");    println!("&dyn Trait:-----{}", size_of::<&dyn SomeTrait>());    println!("&[&dyn Trait]:--{}", size_of::<&[&dyn SomeTrait]>());    println!("Box<Trait>:-----{}", size_of::<Box<SomeTrait>>());    println!("&i32:-----------{}", size_of::<&i32>());    println!("&[i32]:---------{}", size_of::<&[i32]>());    println!("Box<i32>:-------{}", size_of::<Box<i32>>());    println!("&Box<i32>:------{}", size_of::<&Box<i32>>());    println!("[&dyn Trait;4]:-{}", size_of::<[&dyn SomeTrait; 4]>());    println!("[i32;4]:--------{}", size_of::<[i32; 4]>());}
从运行后的输出中可以看到,引用的大小是不同的。许多是8字节(在64位系统中是指针大小) ,但有些是16字节。
16字节大小的指针被称为“胖指针” ,因为它们携带额外的信息。
例如    &[i32]  :
例如    &dyn SomeTrait  :
这就是我们将要关注的胖指针的类型。  &dyn SomeTrait   是一个trait的引用,或者 Rust称之为一个trait对象。
指向 trait 对象的指针布局如下:
这样做的好处是,我们可以引用一个对象,除了它实现了 trait 定义的方法之外,我们对这个对象一无所知。为了达到这个目的,我们使用动态分发。
让我们用代码而不是文字来解释这一点,通过这些部分来实现我们自己的 trait 对象:

// A reference to a trait object is a fat pointer: (data_ptr, vtable_ptr)trait Test {    fn add(&self) -> i32;    fn sub(&self) -> i32;    fn mul(&self) -> i32;}
// This will represent our home brewn fat pointer to a trait object   #[repr(C)]struct FatPointer<'a> {    /// A reference is a pointer to an instantiated `Data` instance    data: &'a mut Data,    /// Since we need to pass in literal values like length and alignment it's    /// easiest for us to convert pointers to usize-integers instead of the other way around.    vtable: *const usize,}
// This is the data in our trait object. It's just two numbers we want to operate on.struct Data {    a: i32,    b: i32,}
// ====== function definitions ======fn add(s: &Data) -> i32 {    s.a + s.b}fn sub(s: &Data) -> i32 {    s.a - s.b}fn mul(s: &Data) -> i32 {    s.a * s.b}
fn main() {    let mut data = Data {a: 3, b: 2};    // vtable is like special purpose array of pointer-length types with a fixed    // format where the three first values has a special meaning like the    // length of the array is encoded in the array itself as the second value.    let vtable = vec![        0,            // pointer to `Drop` (which we're not implementing here)        6,            // lenght of vtable        8,            // alignment
       // we need to make sure we add these in the same order as defined in the Trait.        add as usize, // function pointer - try changing the order of `add`        sub as usize, // function pointer - and `sub` to see what happens        mul as usize, // function pointer    ];
   let fat_pointer = FatPointer { data: &mut data, vtable: vtable.as_ptr()};    let test = unsafe { std::mem::transmute::<FatPointer, &dyn Test>(fat_pointer) };
   // And voalá, it's now a trait object we can call methods on    println!("Add: 3 + 2 = {}", test.add());    println!("Sub: 3 - 2 = {}", test.sub());    println!("Mul: 3 * 2 = {}", test.mul());}

感谢各位的阅读,以上就是“Rust中的胖指针怎么使用”的内容了,经过本文的学习后,相信大家对Rust中的胖指针怎么使用这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

推荐阅读:
  1. 如何配置胖AP
  2. Cisco胖AP配置上网

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

rust

上一篇:php手册怎么理解

下一篇:Vue+Axios请求接口方法与传参方式是什么

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》