加锁与解锁,多步事务回滚


class Mutex
{
}


void lock(Mutex m)
{
}


void unlock(Mutex m)
{
}


void process()
{
}


void mutexDemo()
{
    Mutex m = new Mutex();
    lock(m); // 锁定该互斥量
    scope(exit) unlock(m); // 在离开该域时解锁
    process(); // 过程处理
}


// 多步事务时的回滚
class Transaction
{
    this(Foo f, Bar b, Def d)
    {
    }
}


class Foo
{
}


class Bar
{
}


struct Def
{
}


Foo fooDo()
{
    Foo f;
    return f;
}


Bar barDo()
{
    Bar b;
    return b;
}


void undoFoo(Foo f)
{
}


void undoBar(Bar b)
{
}


Def doDef()
{
    Def d;
    return d;
}


Transaction transactionDemo()
{
    Foo f;
    Bar b;
    Def d;


    f = fooDo();
    scope(failure) undoFoo(f);
    b = barDo();
    scope(failure) undoBar(b);
    d = doDef();
    return new Transaction(f, b, d);
}


// 状态管理
class State
{
    bool _verbose; // =true表示输出信息;=false表示不输出


    void foo()
    {
        auto verboseSaved = _verbose;
        _verbose = false;
        scope(exit) _verbose = verboseSaved; // 不管以何种方式(正常or异常)退出,都恢复之前保存的状态


        // ...
    }
}


/*
这里又另一个关于多步事务的例子,这次是一个电子邮件程序。发送一封电子邮件需要两个操作:
(1)完成 SMTP 发送操作。
(2)复制该电子邮件到“已发送(Sent)”文件夹,它对于 POP 是位于本地磁盘里面的,而对于 IMAP,则处于远端位置。
那些实际上没有被发送的信息不应该出现在“已发送(Sent)”里,而已经发送的信息必须出现在“已发送(Sent)”里。
操作(1)不是可恢复的,因为它是众所周知的分布计算问题。操作(2)是可恢复的,并且带有一定程度的可靠性(some degree of reliability)。因此我们将该工作分成三步:
(1)把信息复制到“已发送(Sent)”,同时把标题更改为 "[Sending] <Subject>"。这个操作要求确保在用户的 IMAP 账号里(或者本地磁盘)有一定的空间,以及连接存在并且有效等等。
(2)通过 SMTP 发送信息。
(3)如果发送失败,就从“已发送(Sent)”里删除该信息。 如果信息发送成功,就把标题由 "[Sending] <Subject>" 更改为 "<Subject>"。
这两个操作都有很高的成功性。如果该文件夹是本地的,成功的可能性非常高。如果文件夹是远程的,成功的可能性仍然比(2)要高很多,因为它并没有导致任意大数据的传送。
*/
class Msg
{
    string _title; // char[]与string有什么区别?
    int _ID;


    string title()
    {
        return _title;
    }


    void setTitle(string title)
    {
        _title = title;
    }


    int ID()
    {
        return _ID;
    }
}


class Mailer
{
    void send(Msg msg)
    {
        {
            string origTitle = msg.title();
            scope(exit) msg.setTitle(origTitle);
            msg.setTitle("[Sending] " ~ origTitle);
            copy(msg, "Sent");
        }


        scope(success) setTitle(msg.ID(), "Sent", msg.title);
        scope(failure) remove(msg.ID(), "Sent");
        smtpSend(msg); // 最后做可靠性最低的部分
    }


private:
    void copy(Msg msg, string to)
    {
    }


    void setTitle(int msgID, string from, string title)
    {
    }


    void remove(int msgID, string from)
    {
    }


    void smtpSend(Msg msg)
    {
    }

}


int main(string[] argv)
{
    writeln("Hello D-World!");


    mutexDemo();
    transactionDemo();


    auto s = new State();
    s.foo();


    auto msg = new Msg();
    Mailer mailer = new Mailer();
    mailer.send(msg);


    getchar();
    return 0;
}

转载于:https://my.oschina.net/u/3485339/blog/900275

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值