ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

0040-Bytes-bytes源码阅读

2022-08-30 08:32:17  阅读:190  来源: 互联网

标签:mut 0040 clone bytes 源码 AtomicPtr Shared shared ptr


环境

  • Time 2022-05-29
  • Rust 1.61.0
  • Bytes 1.1.0

前言

说明

参考:

  1. https://github.com/tokio-rs/bytes
  2. https://zhuanlan.zhihu.com/p/109977513

目标

之前阅读的部分,都是关于静态的字节,后面开始涉及到动态。其中有很多关于原子类型的操作,来实现无锁并发。
这里不深入,先简单理解,之后有机会单独学原子操作和无锁数据结构和并发。
实现 bytes.rs 中的动态字节部分的方法。

loom.rs

AtomicPtr 增加了一个 with_mut 方法,该方法是一个闭包。

pub(crate) mod sync {
    pub(crate) mod atomic {
        pub(crate) use core::sync::atomic::{fence, AtomicPtr, AtomicUsize, Ordering};

        pub(crate) trait AtomicMut<T> {
            fn with_mut<F, R>(&mut self, f: F) -> R
            where
                F: FnOnce(&mut *mut T) -> R;
        }

        impl<T> AtomicMut<T> for AtomicPtr<T> {
            fn with_mut<F, R>(&mut self, f: F) -> R
            where
                F: FnOnce(&mut *mut T) -> R,
            {
                f(self.get_mut())
            }
        }
    }
}

Shared

当字节分配到栈上的时候,为了避免多次分配,需要对字节进行共享。定义了一个共享的结构,_vec 是指向真正的数据,ref_cnt 是共享时的计数。

struct Shared {
    _vec: Vec<u8>,
    ref_cnt: AtomicUsize,
}

Vtable

忽略其中的内存序相关内容,这两个方法相当于将 AtomicPtr<()> 转换成了 *mut Shared

static SHARED_VTABLE: Vtable = Vtable {
    clone: shared_clone,
    drop: shared_drop,
};

unsafe fn shared_clone(data: &AtomicPtr<()>, ptr: *const u8, len: usize) -> Bytes {
    let shared = data.load(Ordering::Relaxed);
    shallow_clone_arc(shared as _, ptr, len)
}

unsafe fn shared_drop(data: &mut AtomicPtr<()>, _ptr: *const u8, _len: usize) {
    data.with_mut(|shared| {
        release_shared(*shared as *mut Shared);
    });
}

shallow_clone_arc

对于引用类型的 clone,指需要将引用加一就可以了。

unsafe fn shallow_clone_arc(shared: *mut Shared, ptr: *const u8, len: usize) -> Bytes {
    let old_size = (*shared).ref_cnt.fetch_add(1, Ordering::Relaxed);

    Bytes {
        ptr,
        len,
        data: AtomicPtr::new(shared as _),
        vtable: &SHARED_VTABLE,
    }
}

release_shared

对于引用类型,如果引用不为 1,直接将引用减一。如果引用为 1,表示是最后一个引用,需要释放数据。
将原始指针转换成了 Box,会受到所有权管理,Box 超出范围自动释放 Shared,里面的字节数据也被释放。

unsafe fn release_shared(ptr: *mut Shared) {
    if (*ptr).ref_cnt.fetch_sub(1, Ordering::Release) != 1 {
        return;
    }
    atomic::fence(Ordering::Acquire);
    Box::from_raw(ptr);
}

总结

了解了 Bytes 中对于共享的字节的处理方法,和 Rc 有点类似。

附录

标签:mut,0040,clone,bytes,源码,AtomicPtr,Shared,shared,ptr
来源: https://www.cnblogs.com/jiangbo4444/p/16638037.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有