在lock下取用資料的可行方案

今天在網路上看到一篇討論C++語法的文章,討論一般在取用需使用lock物件鎖定保護的資料的相關可能作法。以下先將文章中提到的基本方式,以及其中一種方式整理成完成的程式碼列示如下,至於這裏所說的完整程式碼是指可以正常編譯的。因為原始文章中只提供程式碼片段而已。

#include <mutex>

class Widget{    
    
};

class TestCase{
    // Assume we have these member variables
    std::mutex m_mutex;
    Widget m_widget;

    public:

    void Test01(){
        // Get a copy of the widget
        Widget widget;
        {
            auto guard = std::lock_guard(m_mutex);
            widget = m_widget;
        }
    }

    void Test02(){
        // Get a copy of the widget
        Widget widget = [&] {
            auto guard = std::lock_guard(m_mutex);
            return m_widget;
        }();
    }
};

int main(){
    TestCase t1;
    t1.Test01();
    t1.Test02();
    return 0;
}

程式碼範例中的TestCase::Test01()就是一般最常用的方式。首先會先宣告一個Widget物件,再進行Lock,並於Lock區段中將資料複製一份出來。在這段基本的用法中,因為一開始先宣告了一個Widget物件,所以default constructor就會被呼叫,如果這個物件的default constructor裏要做的事不少的話,那這段就會被浪費掉了。因為最後這個物件還是會被另一個物件內容所取代。

所以文章作者的想法就是想看看是否有其它方式可以省掉這個執行default consturctor的部份。作者提供的第一種方式就是用lambda函式在Lock下取出及回傳物件的內容,而呼叫函式的部份就用一個物件來接收(參考TestCase::Test02這個函式)。在這裏則是使用了編譯器最佳化的RVO(Return Value Optimization)方式,在TestCase::Test01函式中的傳回值直接就是套用到函式外等待接收的物件上,這樣可以省去一次的default constructor的呼叫。

至於其它還有幾種可替代的方式,就請大家再自行參考原始文章了。

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *