簡體   English   中英

scoped_lock 訪問資源的優雅模式?

[英]Elegant pattern for scoped_lock to access resource?

我在使用互斥鎖進行訪問控制的容器中有對象。 我經常做這樣的事情:

rsrc *r;
{
    scoped_lock l(mtx);
    r = container.pop( );
}
// ... use r

(我使用 scoped_lock 來確保在異常之后進行清理等。)但是,我不喜歡 { ... } 塊,它不是顯式控制結構的一部分(它只是為了為 scoped_lock 創建一個范圍)並且我不喜歡r的空初始化,然后在 { ... } 塊中(可能但不確定)賦值。

我可以做這樣的事情:

inline rsrc *locked_pop( mutex &mtx, container &c ) { scoped_lock l(mtx); return c.pop( ); }

進而

rsrc *r = locked_pop( mtx, container );

沒關系,但我有一些情況,我需要在同一個鎖下從相同(或不同)容器中獲取多個項目。

你知道一種優雅的、通用的方法嗎? (這不是一個專門的 Boost 問題,但我正在使用這些庫,所以 Boost-ism 就可以了。)

std::tuple<resource_a, resource_b> lock_and_pop(std::mutex& m, container& c)
{
    std::lock_guard<std::mutex> lock(m);
    auto& top = container.front();
    auto result = std::make_tuple(std::move(top.res_a), std::move(top.res_b));
    container.pop_front();
    return result;    
}

您可以使用 lambda。

template<class F>
decltype(auto) while_locked(mutex& m,F&&f){
  auto lock = scoped_lock(m);
  return std::forward<F>(f);
}

像這樣使用:

auto* r = while_locked(mtx, [&]{return container.pop( );});

現在,我喜歡將我的鎖綁定到我鎖定的數據上。 所以我寫了thread_safe<T>它公開read(F&&)constwrite(F&&)const-> const

它們的簽名是[T]->(T->U)->U ,其中[T]是包裝的T(T->U)是傳入的F ,而UF返回的。

Read 獲得一個讀鎖,寫一個寫鎖,然后->返回一個讀鎖持有對象,重載->運算符返回T const*

我們還可以通過互斥鎖上的 orsering 來處理多路訪問。

然后我們得到:

auto* r = container.write([](auto&&container){return container.pop_back();});

這有點光滑。

->技巧依賴於a->b被定義為(a.operator->())->b對於非指針類型的事實。 所以我們可以返回一個持有鎖的臨時對象,然后有一個operator->返回指針。

這讓我們可以做bool b = container->empty() ,它無縫地做一個讀鎖,讀取empty的值,存儲它,然后解鎖讀鎖。

空無一人。 如果您想鎖定資源並避免在每條指令中鎖定它。 最好的是本地訪問資源,如您的問題所示。

我沒有意識到 scoped_lock 有一個 unlock() 函數,它允許在破壞 scoped_lock 之前解鎖(我認為 ~scoped_lock() 是解鎖的唯一方法,任何其他 unlock() 都會導致雙重解鎖,當scoped_locker 超出了范圍)。 由於您可以在范圍結束之前 unlock() ,這對我來說已經足夠優雅了:

void consume_resource( locked_container &c ) {
    scoped_lock l(c.mtx);
    rsrc *r1 = c.pop( );
    rsrc *r2 = c.pop( );
    l.unlock( );
    // CONTAINER NOT LOCKED ANY MORE, DON'T FIDDLE WITH IT (even to check empty(), etc.)
    // use resources pulled from container
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM