C++ 使用std::atomic<;T*>;作为篱笆

C++ 使用std::atomic<;T*>;作为篱笆,c++,concurrency,atomic,C++,Concurrency,Atomic,我在下面为异步资源管理器编写了一个资源类。在加载期间,将使用默认资源(例如黑色纹理)创建资源对象,以便使用该资源的主线程不必等待,即使它是一个空白资源。加载完成后,加载程序线程将调用setResource(),并将基础资源设置为新加载的资源。但也涉及所有权问题。因此,当加载完成时,新分配的资源将归resource类所有,以便在资源被销毁或调用另一个setResource时释放它,因为磁盘上的文件已更改,需要重新加载 template <typename T> class Resour

我在下面为异步资源管理器编写了一个资源类。在加载期间,将使用默认资源(例如黑色纹理)创建资源对象,以便使用该资源的主线程不必等待,即使它是一个空白资源。加载完成后,加载程序线程将调用setResource(),并将基础资源设置为新加载的资源。但也涉及所有权问题。因此,当加载完成时,新分配的资源将归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; }
};
模板
类资源{
受保护的:
//底层对象
原子资源;
//我有自己的资源吗
布尔等业主;
//用于更快映射的资源Id
uint64_t id;
//名字
std::字符串名;
公众:
资源(T*res):资源(res)、isOwner(false)、id(0)、名称(“非”){
资源(std::unique_ptr&&res)
:resource(res.release()),isOwner(true),id(0),name(“non”){
~Resource(){
if(isOwner)delete resource.load(std::memory\u order\u acquire);
}
资源(资源&&)=默认值;
资源(const Resource&)=删除;
资源和运算符=(常量资源-)=删除;
T*getResource(){
返回resource.load(std::memory\u order\u acquire);
}
void setResource(T*res,bool own=false){
如果(isOwner){
删除resource.load(std::memory\u order\u acquire);
}
isOwner=自己的;
resource.store(res,std::memory\u order\u release);
}
void setResource(std::unique_ptr&&res){
如果(isOwner){
删除resource.load(std::memory\u order\u acquire);
}
isOwner=true;
resource.store(res.release(),std::memory\u order\u release);
}
void setId(uint64_t idd){id=idd;}
};

isOwner上是否存在数据竞争,或者atomic.store()在这种情况下起到了围栏的作用?或者我应该改变整个所有权方法,只使用我不知道是否可行的
std::atomic

当代码确实
删除resource.load(std::memory\u order\u acquire)时另一个线程可能仍在使用该资源,因此这是一个争用条件

一个简单的解决方法是永远不要删除现有资源。您可以将该黑色纹理作为全局对象,在应用程序的整个执行过程中保持静态存储持续时间

另一种方法是让
getResource
返回一个
std::shared_ptr
(按值),以便在最后一个用户处理旧资源时自动销毁它。例如:

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);
    }
};
struct NullDeleter{
样板
void运算符()(T常量&){}
};
样板
类资源{
受保护的:
std::共享的ptr资源;
公众:
资源(T&res):资源(&res,NullDeleter{}){}
资源(std::shared_ptr const&res):资源(res){
std::shared_ptr getResource(){
返回原子加载(&U)资源;
}
void setResource(std::shared_ptr const&res){
原子存储(和资源,res);
}
};

当你不能重新执行<代码> STD::UnQuyPPTR <代码>这里,用一个简单的<代码>交换< /代码>作为你的代码> StaseReals?