添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
public func atomic() : async () { s := 1; //被回滚 ignore ping(); //被回滚,因为没有await,还没有真正调用ping() ignore 0/0; // trap! // a non-atomic method public func nonAtomic() : async () { s := 1; let f = ping(); s := 2; await f; s := 3; // this will not be rolled back! await f; //会重新调用ping(),f的实质不是ping()的返回值,而是类似于函数的调用接口 ignore 0/0;// trap!

在test_1.mo的程序中,当我们调用atomic()函数后,我们会发现,s的值并没有改变为1,pinged的值也未被改为true。这是因为在遇到 ignore 0/0; 这个trap时,会直接往回回滚,直到遇见“提交点”。而atomic()函数中并无这样的“提交点”,所以atomic()函数会被完全回滚。

而当我们调用nonAtomic()函数后,我们会发现,s变为3,pinged变为true。这是因为程序只能回滚到最后一个 await f; “提交点”。之前的状态更改均已提交,无法撤回。

再看一下代码,我们把atomic函数中的 ignore ping(); 改为 await ping(); 之后再来测试一下。

actor{
    var s = 0; 
    var pinged = false; 
    public func show() : async (Nat, Bool) {
        (s, pinged)
    public func ping() : async () { 
        pinged := true; 
    // an atomic method 
    public func atomic() : async () { 
        s := 1; //不会被回滚
        await ping(); //不会被回滚
        ignore 0/0; // trap! 
    // a non-atomic method 
    public func nonAtomic() : async () { 
        s := 1; 
        let f = ping(); 
        s := 2; 
        await f; 
        s := 3; // this will not be rolled back! 
        await f; //会重新调用ping(),f的实质不是ping()的返回值,而是类似于函数的调用接口
        ignore 0/0;// trap! 
2021-11-04-下午7.09.28-1024x725.png
- 测试结果 -

我们发现,await ping();之前的代码并没有被回滚,s和pinged的状态更改均已提交。这符合前面所说的规则。

深入理解:

我举这两个例子来对比是想再表达另外一点:

这里的ping()函数的返回值future可以认为还是这个函数,并不是函数调用的结果,如nonAtomic函数中的let f = ping();,这里的f并不是ping函数中的运算结果,而是a future,还是代表这个函数,函数体并未运行,f的type为async (),而不是(),需要ignore来“忽略这个返回值”(如test_1.mo的atomic函数中所示那样),函数返回值并未真正参与到运算结果中。而这里的future(如f),可以放在await后面来组成一个await表达式,这个表达式的结果就是ping函数真正的运算结果,type为(),不需要ignore(如test_2.mo的atomic函数中所示那样)。

Motoko NFT
- Motoko -