本书github链接:inside-rust-std-library
前面章节参见:
深入RUST标准库内核(序言) - 简书 (jianshu.com)
深入RUST标准库内核(一 概述) - 简书 (jianshu.com)
深入RUST标准库内核(二 内存)—Layout/原生指针 - 简书 (jianshu.com)
深入RUST标准库内核(二 内存)—NonNull<T>/申请及释放 - 简书 (jianshu.com)
深入RUST标准库内核(二 内存)—mem模块/MaybeUninit<T> - 简书 (jianshu.com)
RUST的固有(intrinsic)函数库
intrinsic库函数是指由编译器内置实现的函数,一般如下特点的函数用固有函数:
- 与CPU架构相关性很大,必须利用汇编实现或者利用汇编才能具备最高性能的函数,
- 和编译器密切相关的函数,由编译器来实现最为合适。
上面内存库章节中已经介绍了内存部分的intrinsic库函数,本节对其他部分做简略介绍
intrinsic 原子操作函数
原子操作函数主要用于多核CPU,多线程CPU时对数据的原子操作。intrinsic库中atomic_xxx及atomic_xxx_xxx类型的函数即为原子操作函数。原子操作函数主要用于并发编程中做临界保护,并且是其他临界保护机制的基础,如Mutex,RWlock等。
数学函数及位操作函数
各种整数及浮点的数学函数实现。这一部分放在intrinsic主要是因为现代CPU对浮点计算由很多支持,这些数学函数由汇编语言来实现更具备效率,那就有必要由编译器来内置实现。
intrinsic 指令优化及调试函数
断言类: assert_xxxx 类型的函数
函数栈:caller_location
小结
intrinsic函数库是从编译器层面完成跨CPU架构的一个手段,intrinsic通常被上层的库所封装。但在操作系统编程和框架编程时,仍然会不可避免的需要接触。
RUST标准库的基础Trait
RUST中直接针对泛型实现方法定义和Trait
实现方法或Trait时,可以针对泛型来实现特定的方法和Trait,并可以给泛型添加限制以描述。可以添加的泛型限制有:无限制,泛型的原生指针(可变/不可变)类型,泛型的引用(可变/不可变)类型,泛型的数组类型,泛型的切片类型,泛型的切片引用(可变/不可变)类型,泛型的元组(可变/不可变)类型,函数类型, 需实现特定的Trait限制等。
对某个具有针对泛型的类型结构体实现方法和Trait时,也可以对类型结构体的泛型做出如上所述的限制。
举例说明:
//为所有的类型实现了Borrow<T> Trait
impl<T: ?Sized> Borrow<T> for T {
fn borrow(&self) -> &T {
self
}
}
//为所有的引用类型实现Receiver Trait
impl<T: ?Sized> Receiver for &T {}
//为所有可变引用类型实现Receiver Trait
impl<T: ?Sized> Receiver for &mut T {}
//为所有原生不可变指针类型实现Clone Trait
impl<T: ?Sized> Clone for *const T {
fn clone(&self) -> Self {
*self
}
}
//为原生可变指针类型实现Clone Trait
impl<T: ?Sized> Clone for *mut T {
fn clone(&self) -> Self {
*self
}
}
//为切片类型[T]实现AsRef<[T]> Trait
impl<T> AsRef<[T]> for [T] {
fn as_ref(&self) -> &[T] {
self
}
}
// 切片的方法 具体实现的摘要
// [T;N]代表数组类型,[T]代表切片类型,
// 下面是针对所有切片类型的统一方法。
impl<T> [T] {
pub const fn len(&self) -> usize {
unsafe { crate::ptr::PtrRepr { const_ptr: self }.components.metadata }
}
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
//以下代码展示了RUST代码的极简洁及易理解
pub const fn first(&self) -> Option<&T> {
if let [first, ..] = self { Some(first) } else { None }
}
pub const fn split_first(&self) -> Option<(&T, &[T])> {
if let [first, tail @ ..] = self { Some((first, tail)) } else { None }
}
pub unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) {
unsafe { (self.get_unchecked(..mid), self.get_unchecked(mid..)) }
}
...
...
}
//原生指针 具体方法的实现摘要
impl<T: ?Sized> *const T {
pub const fn is_null(self) -> bool {
(self as *const u8).guaranteed_eq(null())
}
/// Casts to a pointer of another type.
pub const fn cast<U>(self) -> *const U {
self as _
}
pub unsafe fn as_ref<'a>(self) -> Option<&'a T> {
if self.is_null() { None } else { unsafe { Some(&*self) } }
}
...
...
}
//原生数组指针 具体方法实现摘要。需要注意,原生数组指针也是原生指针,
//此处不应该再实现 *const T的同名函数。
impl<T> *const [T] {
pub const fn len(self) -> usize {
metadata(self)
}
pub const fn as_ptr(self) -> *const T {
self as *const T
}
...
...
}
// 对&A实现PartialEq<&B> Trait, 如果A实现了 PartialEQ<B>
impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &A
where
A: PartialEq<B>,
{
fn eq(&self, other: &&B) -> bool {
PartialEq::eq(*self, *other)
}
fn ne(&self, other: &&B) -> bool {
PartialEq::ne(*self, *other)
}
}
针对限制的泛型实现方法和Trait大幅的减少了代码,受限制的泛型是RUST提供的强大的泛型语法。
编译器内置Trait代码分析
分析编译器内置Trait源代码发现源代码文件中的大部分内容实际上是参考文档。
本节主要给出对参考文档理解后的一些总结
//Send Trait
pub unsafe auto trait Send {
// empty.
}
//原生指针不支持Send Trait实现,利用"!"表示明确的对Trait的不支持
impl<T: ?Sized> !Send for *const T {}
impl<T: ?Sized> !Send for *mut T {}
mod impls {
// 实现Sync的类型的类型不可变引用支持Send
unsafe impl<T: Sync + ?Sized> Send for &T {}
// 实现Send的类型的类型可变引用支持 Send
unsafe impl<T: Send + ?Sized> Send for &mut T {}
}
// Sync Trait
pub unsafe auto trait Sync {
// Empty
}
//原生指针不支持Sync Trait
impl<T: ?Sized> !Sync for *const T {}
impl<T: ?Sized> !Sync for *mut T {}
pub trait Sized {
// Empty.
}
//如果一个Sized的类型要强制转换为动态大小类型,那必须实现Unsize Trait
//例如 [T;N] 实现了 Unsize<[T]>
pub trait Unsize<T: ?Sized> {
// Empty.
}
//模式匹配表达式匹配时编译器需要使用的Trait,如果一个结构实现了PartialEq,该Trait会自动被实现。
//推测这个结构应该是内存按位比较
pub trait StructuralPartialEq {
// Empty.
}
//主要用于模式匹配,如果一个结构实现了Eq, 该Trait会自动被实现。
pub trait StructuralEq {
// Empty.
}
//Copy,略
pub trait Copy: Clone {
// Empty.
}
//统一实现原生类型对Copy Trait的支持
mod copy_impls {
use super::Copy;
macro_rules! impl_copy {
($($t:ty)*) => {
$(
impl Copy for $t {}
)*
}
}
impl_copy! {
usize u8 u16 u32 u64 u128
isize i8 i16 i32 i64 i128
f32 f64
bool char
}
impl Copy for ! {}
impl<T: ?Sized> Copy for *const T {}
impl<T: ?Sized> Copy for *mut T {}
impl<T: ?Sized> Copy for &T {}
//& mut T不支持Copy,以保证RUST的借用规则
}
//PhantomData被用来在类型结构体中做一个标记,标记结构体逻辑上存在但不必有实体的成员,成员类型表现在PhantomData的泛型里
//PhantomData具体阐述请参考标准库文档。
//PhantomData是个单元结构体,单元结构体的变量名就是单元结构体的类型名。
//所以使用的时候直接使用PhantomData即可,编译器会将泛型的类型实例化信息自动带入PhantomData中
pub struct PhantomData<T: ?Sized>;