簡體   English   中英

在僅移動類型上強制復制(然后銷毀)

[英]Force copy (then destroy) on move-only type

考慮以下無鎖工作竊取(de)que函數:

template<class T>
inline T WorkStealQ<T>::Steal(void)
{
    auto tail{_tail.load(std::memory_order_acquire)};
    if (_head.load(std::memory_order_acquire) <= tail) return T();
    auto task{_tasks[tail & _mask]};
    if (_tail.compare_exchange_weak(tail, tail + 1, std::memory_order_release, std::memory_order_relaxed)) return task;
    return T();
}

但是,如果T僅可移動但不可復制該怎么辦? 問題是從緩沖區讀取項目是一項復制操作,無法更改為auto task{std::move(_tasks[tail & _mask])}; 因為另一個並發操作也可以移動它,在這種情況下,任何非只讀但又修改原始操作的move構造函數(例如,使指向資源的指針為空)都會破壞算法。

請注意, Steal()的整體語義僅從外部角度執行一次移動,因為只有一個並發操作將返回存儲在該位置的T並返回。 輸掉比賽的其他任何人都將使compare_exchange_weak()失敗。 因此,就用戶而言,該操作不會破壞僅可移動T的語義。 不幸的是,在內部,它需要制作一個臨時的T淺拷貝,直到確定是將其完成還是放棄后再將其保留在緩沖區中(這基本上是兩階段移動,中間進行檢查)。

一種實現方法是使T副本構造函數和副本分配私有成員,並擁有一個friend WorkStealQ 問題是在我可能想用作T的第三方庫類的情況下該怎么做。 在那種情況下,除了使用指向此類對象的指針而不是侵入性地存儲它們(從而導致性能下降)之外,還有其他選擇嗎? 我假設對於帶有虛函數的類,即使對於淺表副本, memcpy也無法使用。

我認為最好的選擇可能是為每個T顯式定義一個單獨的shallow_copy類,並在工作竊取函數中使用該類。 這也將使您能夠處理任何導致您的類型變為僅移動的問題(因為您無法先驗地知道臨時副本可以避免這些問題)。

暫無
暫無

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

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