Draw: Atomically release objects.

There may be scenarios where we release objects from separate threads,
just make them safe.
This commit is contained in:
Unknown W. Brackets 2021-10-07 18:22:23 -07:00
parent 309dcb2952
commit abc9ce671a
3 changed files with 15 additions and 21 deletions

View file

@ -69,30 +69,20 @@ bool DataFormatIsDepthStencil(DataFormat fmt) {
bool RefCountedObject::Release() {
if (refcount_ > 0 && refcount_ < 10000) {
refcount_--;
if (refcount_ == 0) {
if (--refcount_ == 0) {
delete this;
return true;
}
}
else {
_dbg_assert_msg_(false, "Refcount (%d) invalid for object %p - corrupt?", refcount_, this);
} else {
_dbg_assert_msg_(false, "Refcount (%d) invalid for object %p - corrupt?", refcount_.load(), this);
}
return false;
}
bool RefCountedObject::ReleaseAssertLast() {
_dbg_assert_msg_(refcount_ == 1, "RefCountedObject: Expected to be the last reference, but isn't!");
if (refcount_ > 0 && refcount_ < 10000) {
refcount_--;
if (refcount_ == 0) {
delete this;
return true;
}
} else {
ERROR_LOG(G3D, "Refcount (%d) invalid for object %p - corrupt?", refcount_, this);
}
return false;
bool released = Release();
_dbg_assert_msg_(released, "RefCountedObject: Expected to be the last reference, but isn't!");
return released;
}

View file

@ -6,6 +6,7 @@
#pragma once
#include <atomic>
#include <cstdint>
#include <cstddef>
#include <functional>
@ -324,7 +325,9 @@ protected:
class RefCountedObject {
public:
RefCountedObject() : refcount_(1) {}
RefCountedObject() {
refcount_ = 1;
}
virtual ~RefCountedObject() {}
void AddRef() { refcount_++; }
@ -332,7 +335,7 @@ public:
bool ReleaseAssertLast();
private:
int refcount_;
std::atomic<int> refcount_;
};
template <typename T>

View file

@ -597,9 +597,10 @@ std::shared_ptr<Download> Downloader::StartDownloadWithCallback(
void Downloader::Update() {
restart:
for (size_t i = 0; i < downloads_.size(); i++) {
if (downloads_[i]->Progress() == 1.0f || downloads_[i]->Failed()) {
downloads_[i]->RunCallback();
downloads_[i]->Join();
auto &dl = downloads_[i];
if (dl->Done()) {
dl->RunCallback();
dl->Join();
downloads_.erase(downloads_.begin() + i);
goto restart;
}