簡體   English   中英

使用std :: atomic <T*> 作為圍欄

[英]Using std::atomic<T*> as a fence

我在下面為異步資源管理器編寫了Resource類。 在加載期間,將使用默認資源(例如,黑色紋理)創建一個Resource對象,以便將使用該Resource的主線程不必等待,即使它是一個空白資源。 加載完成后,加載器線程將調用setResource()並將基礎資源設置為新加載的資源。 但是也涉及所有權。 因此,當加載完成時,新分配的資源將歸Resource類所有,以便可以在銷毀Resource或調用另一個setResource時將其釋放,因為磁盤上的文件已更改並且需要重新加載。

template <typename T>
class Resource {
 protected:
  // Underlying object
  std::atomic<T*> resource;

  // Do I own resource
  bool isOwner;

  // Id of resource for faster mapping
  uint64_t id;

  // Name
  std::string name;

 public:
  Resource(T* res) : resource(res), isOwner(false), id(0), name("non") {}

  Resource(std::unique_ptr<T>&& res)
      : resource(res.release()), isOwner(true), id(0), name("non") {}

  ~Resource() {
    if (isOwner) delete resource.load(std::memory_order_acquire);
  }

  Resource(Resource&&) = default;

  Resource(const Resource&) = delete;
  Resource& operator=(const Resource&) = delete;

  T* getResource() { 
    return resource.load(std::memory_order_acquire);
  }

  void setResource(T* res, bool own = false) {
    if (isOwner) { 
      delete resource.load(std::memory_order_acquire);
    }

    isOwner = own;
    resource.store(res, std::memory_order_release);
  }

  void setResource(std::unique_ptr<T>&& res) {
    if (isOwner) { 
      delete resource.load(std::memory_order_acquire);
    }

    isOwner = true;
    resource.store(res.release(), std::memory_order_release);
  }

  void setId(uint64_t idd) { id = idd; }
};

在isOwner上是否存在數據爭用或在這種情況下atomic.store()是否充當籬笆? 還是我應該更改整個所有權方法,而只使用std::atomic<std::shared_ptr<T>>我不知道是否可行?

當代碼確實delete resource.load(std::memory_order_acquire); 另一個線程可能仍在使用資源,因此這是競爭條件。

一種簡單的解決方法是永遠不要刪除現有資源。 您可以將黑色紋理用作具有靜態存儲持續時間的全局對象,該靜態存儲持續時間在應用程序的整個執行過程中仍然有效。

另一個方法是讓getResource返回std::shared_ptr<T> (按值),以便在最后一個用戶處置舊資源時自動銷毀舊資源。 例如:

struct NullDeleter {
    template<class T>
    void operator()(T const&) {}
};

template<typename T>
class Resource {
protected:
    std::shared_ptr<T> resource;
public:
    Resource(T& res) : resource(&res, NullDeleter{}) {}

    Resource(std::shared_ptr<T> const& res) : resource(res) {}

    std::shared_ptr<T> getResource() {
        return atomic_load(&resource);
    }

    void setResource(std::shared_ptr<T> const& res) {
        atomic_store(&resource, res);
    }
};

暫無
暫無

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

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