< 返回版块

ChaosBot 发表于 2018-09-25 11:46

Tags:rustnews

Web框架Thruster发布0.5

原文

thruster


Niko办公时间:循环服务

讨论了一个经典的问题:Rust如何处理循环数据? 答案是,不需要循环。

当使用带有GC的语言,比如js,可以这么写:

function setup() {
  var directory = {};
  var service1 = new Service1(directory);
  var service2 = new Service2(directory);
  return directory;
}

function Service1(directory) {
  self.directory = directory;
  directory.service1 = self;
  ...
}

function Service2(directory) {
  self.directory = directory;
  directory.service2 = self;
  ...
}

希望有多个服务,并且可以彼此通信,通过创建directory来存储这些服务对象。directory里存储的对象都可以互相访问。

但是将此代码修改为Rust时,就会陷入困惑:

struct Directory {
    service1: Option<Service1>,
    service2: Option<Service2>,
}

创建Directory时,Service还不存在,所以使用Option。但是初始化directory之后,Service就永远不可能为None。最大的问题是,该如何管理内存?因为Service1有可能会引用到Service2。

使用Arc或原子类型和锁,可以改善,但还不是最好的办法。


#[derive(Clone)]
struct Directory {
  service1: Sender<Message1>,
  service2: Sender<Message2>,
}

/// Whatever kind of message service1 expects.
struct Message1 { .. }

/// Whatever kind of message service2 expects.
struct Message2 { .. }

可以使用Sender<Message>类型来解耦,不要通过共享内存来通信,要通过通信来共享内存。

Sender是指Channel中的Sender,利用Channel来实现一个Actor模型,每个service就是一个Actor,Actor之间通过发送消息来相互调用。

Niko使用std::sync::channel来演示这种思想,然后使用Arc、Mutex和ConVar实现了一个简单的自定义Channel。

完整代码

原文


ABA问题和并发回收

编写无锁数据结构就会出现ABA问题。比如在编写无锁栈的时候:

  1. 栈里包含A和B
  2. 线程M开始pop操作
  3. 线程M 加载 A = top.load()
  4. 线程M 检查 A ==Null
  5. 线程M 测试为false,解引用 B = (* A).next
  6. 线程M被暂停
  7. 线程M弹出堆栈
  8. 线程M释放A
  9. 线程M分配指针C
  10. 线程N push C
  11. 线程N分配指针,并且分配器重用A指针
  12. 线程N push A
  13. 堆栈现在是A/ C/ B
  14. 线程N被挂起并且线程M恢复
  15. 使top.compare_and_swap(A, B)成功
  16. 现在堆栈B和C被泄漏

前 1 - 13步,实际上在栈顶的A值已经发生过了变化。但是到第15步进行CAS操作的时候,将A值换为B,CAS操作没有分辨出A值实际上已经不是之前的A。所以就发生了ABA问题。

ABA问题的本质是内存回收。对于上面的问题,A被弹出以后,就不应该被释放,因为还有B在用着它,也不能被线程N 重用。

所以一般使用 险象指针(hazard pointers,HP)来阻止释放还被其他线程使用的指针。 将来crossbeam-epoch也打算支持险象指针。

所以作者基于这种思想实现了一个crate: lockfree

该库提供了一些无锁数据结构,以及提供API为每个线程都增加一个删除队列,解决ABA问题

原文


「系列文章」为Eurobot创建机器人:第1部分

作者是为了参加某个机器人比赛,基于Raspberry PI 3,用Rust编写机器人固件

原文


Smithy进度更新:我如何将WebAssembly 打包尺寸减少90%

Smithy,一个用Rust编写的Web开发框架,可以编译为WebAssembly,它的目标是让你使用惯用的Rust来编写前端代码。

开始准备alpha版本了。新版本使用了wasm-bindgen提供的js-sys和web-sys

原文


使用Runner来运行小的Rust代码片段

$ cat print.rs println!("Hello, World!");

$ runner print.rs Hello, World!

runner对代码片段默认会有main函数包装:

// file.rs let mut f = File::open("file.rs")?; let mut buf = String::new(); f.read_to_string(&mut buf)?; println!("{}",buf);

还可以直接运行代码:

$ runner -i "(0..4).map(|n| 2*n)" 0 2 4 6

总之,就像是一个方便的终端版的playground

runner

原文


[WIP]Rust编写的模块化系统监视器

先关注下

hegemon


评论区

写评论

还没有评论

1 共 0 条评论, 1 页