Repository: google/filament
File: filament/src/details/Engine.cpp (C++)

Code before:
        // Terminate the backend resource immediately as they're unnecessary from this point.
        const_cast<T*>(p)->terminate(*this);

        // We defer the destruction of the frontend object until the creation process completes.
        // This ensures the object remains valid while the creation process still holds references
        // to it.
        mDeferredAsyncObjectDestruction.push_back([this, p=const_cast<T*>(p)]() {
            if (!p->isCreationComplete()) {
                return false;
            }
            mHeapAllocator.destroy(p);
            return true;
        });
    }
}

// -----------------------------------------------------------------------------------------------

UTILS_NOINLINE
bool FEngine::destroy(const FBufferObject* p) {
    return terminateAndDestroy(p, mBufferObjects);
}

UTILS_NOINLINE
bool FEngine::destroy(const FVertexBuffer* p) {
    if (p && !p->isCreationComplete()) {
        terminateAndDeferAsyncObjectDestruction(p, mVertexBuffers);
        return true;
    }
    return terminateAndDestroy(p, mVertexBuffers);
}

UTILS_NOINLINE
bool FEngine::destroy(const FIndexBuffer* p) {
    if (p && !p->isCreationComplete()) {
        terminateAndDeferAsyncObjectDestruction(p, mIndexBuffers);
        return true;
    }
    return terminateAndDestroy(p, mIndexBuffers);
}

UTILS_NOINLINE
bool FEngine::destroy(const FSkinningBuffer* p) {
    return terminateAndDestroy(p, mSkinningBuffers);
}

UTILS_NOINLINE
bool FEngine::destroy(const FMorphTargetBuffer* p) {
    return terminateAndDestroy(p, mMorphTargetBuffers);
}


Review comment (refactor):
shouldn't this be `isAsyncMode()`?  Also I think the `p && !p->isCreationComplete` should be inside terminateAndDeferAsync... so that it's not duplicated 3 times.

Code after:
}

template<typename T, typename Lock>
UTILS_ALWAYS_INLINE
bool FEngine::terminateAndDestroyLocked(Lock& lock, const T* p, ResourceList<T>& list) {
    if (p == nullptr) return true;
    lock.lock();
    bool const success = list.remove(p);
    lock.unlock();

#if UTILS_HAS_RTTI
    auto typeName = CallStack::typeName<T>();
    const char * const typeNameCStr = typeName.c_str();
#else
    const char * const typeNameCStr = "<no-rtti>";
#endif

    if (ASSERT_PRECONDITION_NON_FATAL(success,
            "Object %s at %p doesn't exist (double free?)", typeNameCStr, p)) {
        const_cast<T*>(p)->terminate(*this);
        mHeapAllocator.destroy(const_cast<T*>(p));
    }
    return success;
}

// -----------------------------------------------------------------------------------------------

UTILS_NOINLINE
bool FEngine::destroy(const FBufferObject* p) {
    return terminateAndDestroy(p, mBufferObjects);
}

UTILS_NOINLINE
bool FEngine::destroy(const FVertexBuffer* p) {
    return terminateAndDestroy(p, mVertexBuffers);
}

UTILS_NOINLINE
bool FEngine::destroy(const FIndexBuffer* p) {
    return terminateAndDestroy(p, mIndexBuffers);
}

UTILS_NOINLINE
bool FEngine::destroy(const FSkinningBuffer* p) {
    return terminateAndDestroy(p, mSkinningBuffers);
}

UTILS_NOINLINE
bool FEngine::destroy(const FMorphTargetBuffer* p) {
    return terminateAndDestroy(p, mMorphTargetBuffers);
}