暨 Repository 简介

引子Rust 在处理数据时表现第一好情况的是处理树状数据,第二好的情况是数据能够看作有向无环图,但是其中执行数据变化的修改脉络路径仍然能看作是树形,同样好的也还有粗粒度执行的可以看作是多读单写锁的协议下的数据处理,诸如此类。在这个舒适带之外,Rust工作的就没有那么好。虽然还能用,但是处理变得棘手,很多为了安全性和友好性准备的语言特征都不再能够协助你,使用体验变得不方便起来。这本书(指《Learn Rust With Entirely Too Many Linked Lists》)的目标之一就是探索(在Rust开发中)如何与双向链表这样的东西打交道。 双向链表是一个 Rust 在当前的设计中,让你不能写,或者至少不能轻易的不小心的写出来的结构。双向链表不只是具有不明确的所有权,它实际上具有的是循环的所有权,显然离 Rust 的舒适区域相去甚远。显然,最直接、也是在智力上最诚实的对这本书的回应就是:它深入地论断反对了在Rust中使用循环依赖数据。原则就是开发中“不要让数据循环依赖”,看看你能做到什么地步。这也是 Rust 设计的思路。我不认为我写的 Rust 程序中有很多的循环依赖数据,少数用到的地方都是使用封装好的库,或者是不透明的引用句柄(而不是 Rust 所有权系统跟踪着的原生引用)。

我觉得这段话总结的蛮好的,除了“不要让数据循环依赖”略显武断。在实际的业务开发中,在某些特定的场景之下,“不要让数据循环依赖”总是要让路于“让数据循环依赖变得可管理”。当然这段话的末尾实际上已经提到了解决方案——使用封装好的库(让别人使用某种机制来替你管理并封装起来),而别人实际实现的方法就是使用不透明的引用句柄。

最最常见的不透明的引用句柄其实就是原生指针。原生指针尺寸小,速度快。缺点也是显而易见的,它对bug几乎完全没有容灾性。遇到数据的不一致,甚至有时候只是业务逻辑上的逻辑错误导致的,就很可能要与SIGSEGV相伴了。如果是部署到用户手上的系统,喏,一个崭新的CVE可能就诞生了。

另外一种很常见的不透明引用句柄就是索引。索引尺寸小,速度也很好,具有最基本的容灾性——至少很容易就能保证不会访问到不存在的值。它最大的缺点是会丢失类型信息。的确在很多情况下,会想要擦除类型信息,但是在逻辑上想要找回类型信息的时候,单纯的索引显然会捉襟见肘。另外就是需要小心处理值删除引起其他值的索引偏移。最简单的办法就是让索引无法偏移,当然这也并不是全无代价的。

Repository

repository的其他功能,希望对大家有借鉴意义。

repository目前的最大的限制是要求其中所有的数据都符合core::any::Any这个特质,所以无法使用带有非'static引用类型的数据。这并不是什么大问题,如果真的需要,你可以将非'static类型的值留在Repo之外,使用某种方法建立对应关系,然后封装一层即可使用。另外就是我目前没有实现多线程版本。我自己是有用这个库试验性的写了一些东西,感觉至少对于单线程环境下的一般使用还是很方便的。

用 Repo 定义双向链表和节点

先上代码:

userepository::{Repo,EntityPtr,ErrorasRepoError};usecore::any::Any;struct LinkedList{repo: Repo,ends: Option>,EntityPtr>)>,len: usize,}struct Node{value: T,prev: Option>>,next: Option>>,}

这里用到了 repository 里的 Repo 这个类型,它是一块存储空间,你可以把它想像成类似 Vec 一样的东西,但是它可以放多种类型的数据,所以没有泛型约束。

在这里我们会用它来存储双向链表的节点,因为节点的值的类型是用户指定的 T ,所以用泛型指定。我们打算把Node放进Repo,这要求它符合Any特质约束,所以T也需要符合Any特质约束,写成T: Any。

将类型为 Node 的数据放入 Repo 会得到一个EntityPtr> 这是一个满足Copy的大小为usize两倍的不透明的引用句柄。你可以随意存储、序列化、传输。它的类型上记录了实际内容值的类型。我们在Node内,就是用它套上Option用来存储前一个节点和后一个节点的。

那么我想要访问实际的Node怎么办呢?Rust 分为共享借用和独占借用。如果ptr是一个EntityPtr>,那么获取共享借用和独占借用分别是:

// 获取共享借用letnode_ref=ptr.get_ref(&repo)?;// 获取独占借用letnode_mut=ptr.get_mut(&mutrepo)?;

因为EntityPtr是完全独立于Repo存在的,所以这一步有报错的可能:比如对应的值可能已经删掉了,之类的。这里用了问号做错误处理。

接下来就是实现双向链表的各种方法了。其实都比较简单,在这里不做赘述。

Repo 里的类型擦除

有时候我们需要把一堆不同类型的指针存在一起。这个时候EntityPtr会因为上面带了类型而做不到这一点。EntityPtr 上提供了entity_id()方法,获取到一个EntityId。它是一个只有一个usize大小的,不带类型标识的索引编号。从 EntityId 重新获取EntityPtr则是通过cast_ptr方法。

// 获取 ptr 对应的idletnode_id=ptr.entity_id(&repo)?;// 获取 id 对应的ptrletnode_ptr=node_id.cast_ptr::>(&repo);assert_eq!(node_ptr,Some(ptr));

Repo 里的预分配机制

有时候我们在构建数据结构时,它们存在循环引用,然而因为构建是逐个进行的,那么就会存在前一个值需要引用后一个值,但是后一个值还没有创建的情况。 repository 提供了预分配机制,允许你先为一个值构建EntityPtr,然后在稍后再加入实际对应的值数据。

举个例子:假如有个数据结构叫“文档”,存储“根节点”,而在节点上又需要存储对应的文档的引用。代码如下:

struct Doc{root_node: EntityPtr}struct Node{doc: EntityPtr}repo.transaction_preallocate(|tx|-> EntityPtr{letdoc_ptr=tx.preallocate::();letnode=Node{doc: doc_ptr};letnode_ptr=tx.repo_mut().insert(node);letdoc=Doc{root_node: node_ptr};// 只是演示,所以省去了错误处理,直接unwrap()。tx.init_preallocation(doc_ptr,doc).unwrap();doc_ptr});

好啦,这次就简单介绍到这,欢迎讨论。

rust高级矿场_高级 Rust 所有权管理相关推荐

  1. rust 局域网联机_腐蚀rust搭建Rust服务器及联机教程

    今天 九游和大家讲解腐蚀rust搭建Rust服务器及 联机教程 腐蚀rust服务器搭建教程.这里为大家介绍如何搭建服务器,可以进行单机也可以和小伙伴联机,下面介绍详细的方法. Steam游戏后台服务器 ...

  2. rust键位失灵_用Rust写操作系统(四)——竞争条件与死锁

    一.概要说明 当多个任务访问同一个资源(数据)是就会引发竞争条件问题,这不仅在进程间会出现,在操作系统和进程间也会出现.由竞争条件引发的问题很难复现和调试,这也是其最困难的地方.本实验的目的在于了解竞 ...

  3. java高级教程_高级Java教程

    java高级教程 课程大纲 学习Java基础很容易. 但是,真正钻研该语言并研究其更高级的概念和细微差别将使您成为一名出色的Java开发人员. 网络上充斥着"软","便宜 ...

  4. rust队友开挂_腐蚀RUST判断开挂玩家方法说明 怎么识别玩家是否外挂

    <腐蚀RUST>无论是私服还是官服都有玩家开挂,这样影响其他玩家体验.有些还很难被识别出来.本次巴士小编就给大家带来<腐蚀RUST>开挂玩家识别方法,希望对给为玩家有所帮助. ...

  5. java高级计算器_高级计算器[Java版]

    import java.util.Scanner; /* * time:       2012年11月17日 11:34:10 * content:     高级计算器 * author:    覃唐 ...

  6. python实现高级计算器_高级计算器功能Tkinter GUI和variab

    编辑:我修正了这个帖子所涉及的错误,等等,现在我正在尝试一种不同的方式来实现我最初想要的高级功能.这次我有一个显示器,还有一个显示功能.按钮通过在所述显示中插入文本来调用更新功能.我想知道如何使用这个 ...

  7. 腐蚀rust服务器命令_腐蚀Rust游戏指令大全 全游戏指令一览

    今天小编要为大家带来得是腐蚀Rust游戏指令大全,腐蚀Rust是一款第一人称僵尸生存网络游戏,在游戏中玩家需要防范动物.僵尸.玩家的袭击,并依靠各类物品进行生存. 全游戏指令一览 基本指令 (以下在聊 ...

  8. rust 飞天指令_腐蚀RUST代码大全 腐蚀RUST指令代码一览

    腐蚀(RUST)是一款开放世界生存游戏,在游戏中玩家可以使用指令代码来简便自己的游戏,下面就来分享一下腐蚀RUST指令代码大全. 腐蚀RUST指令代码一览 基本指令 (以下在聊天框内输入) /msg ...

  9. rust申请解封_参考 - Rust的确切自动解除引用规则是什么?

    我正在学习/试验Rust,在我用这种语言找到的所有优雅中,有一个让我感到困惑并且看起来完全不合适的特点. 在进行方法调用时,Rust会自动取消引用指针. 我做了一些测试来确定确切的行为: struct ...

最新文章

  1. 有源晶振和无源晶振的区别
  2. 虚幻争霸服务器维护,《虚幻争霸》将于4月停止运营 玩家可全额退款
  3. 由浅入深CIL系列:6.For和Foreach的CIL结构组成以及运行效率
  4. Java线程详解(1)-概念与原理
  5. openfire过滤脏话插件,控制消息是否发送
  6. 关于如何学好前端开发,你需要知道的事!
  7. 现代ups电源及电路图集_2020山特UPS电源自动开机200KVA实力
  8. 【Flask】ORM关系以及一对多
  9. 能力提升综合题单Part 8.3.1 二叉树Part 8.3.2 树的直径
  10. 迷你屏+OLED好屏:个性专业两手抓 华硕灵耀X 14专业好屏体验
  11. BUUCTF crackMe 题解
  12. Java对象的GC内存分配和回收策略
  13. 前端200道面试题及答案(更新中)
  14. Android HAL层
  15. SQLServer安装程序无法打开注册表项 UNKNOWN\Components\…的问题
  16. 115、闪点、燃点、自然点的概念
  17. geodatabase怎么连接MySQL_实用帖-手把手教你如何上传GEO数据库
  18. Android9.0支持exFat格式u盘识别
  19. 七张图带你了解电子招标投标全流程!
  20. Visual Studio 2019调试HTK代码

热门文章

  1. linux awk命令详解,使用system来内嵌系统命令,批量github,批量批下载视频, awk合并两列...
  2. css学习入门篇(1)
  3. 初探 Unix 操作系统
  4. sdwan安全如何加固?六种安全SD-WAN方案分享
  5. CentOS 6下编译安装Nginx
  6. python 周末大作业之2
  7. 记一次FastJSON和Jackson解析json时遇到的中括号问题
  8. ue4 材质表达式分类
  9. db2-存储过程word版
  10. iis+nginx实现负载均衡