Repository: google/filament
File: filament/backend/src/Platform.cpp (C++)

Code before:
bool Platform::setPresentFrameId(SwapChain const*, uint64_t) noexcept {
    return false;
}

bool Platform::queryFrameTimestamps(SwapChain const*, uint64_t, FrameTimestamps*) const noexcept {
    return false;
}

void Platform::setBlobFunc(InsertBlobFunc&& insertBlob, RetrieveBlobFunc&& retrieveBlob) noexcept {
    std::lock_guard<std::mutex> lock(mBlobFuncsMutex);
    mInsertBlob = std::move(insertBlob);
    mRetrieveBlob = std::move(retrieveBlob);
}

bool Platform::hasInsertBlobFunc() const noexcept {
    std::lock_guard<decltype(mBlobFuncsMutex)> lock(mBlobFuncsMutex);
    return bool(mInsertBlob);
}

bool Platform::hasRetrieveBlobFunc() const noexcept {
    std::lock_guard<decltype(mBlobFuncsMutex)> lock(mBlobFuncsMutex);
    return bool(mRetrieveBlob);
}

void Platform::insertBlob(void const* key, size_t keySize, void const* value, size_t valueSize) {
    std::lock_guard<decltype(mBlobFuncsMutex)> lock(mBlobFuncsMutex);
    if (mInsertBlob) {
        mInsertBlob(key, keySize, value, valueSize);
    }
}

size_t Platform::retrieveBlob(void const* key, size_t keySize, void* value, size_t valueSize) {
    std::lock_guard<decltype(mBlobFuncsMutex)> lock(mBlobFuncsMutex);
    if (mRetrieveBlob) {
        return mRetrieveBlob(key, keySize, value, valueSize);
    }
    return 0;
}

void Platform::setDebugUpdateStatFunc(DebugUpdateStatFunc&& debugUpdateStat) noexcept {
    std::lock_guard<decltype(mDebugUpdateStatFuncMutex)> lock(mDebugUpdateStatFuncMutex);
    mDebugUpdateStat = std::move(debugUpdateStat);
}

bool Platform::hasDebugUpdateStatFunc() const noexcept {
    std::lock_guard<decltype(mDebugUpdateStatFuncMutex)> lock(mDebugUpdateStatFuncMutex);
    return bool(mDebugUpdateStat);
}

void Platform::debugUpdateStat(const char* key, uint64_t intValue) {
    std::lock_guard<decltype(mDebugUpdateStatFuncMutex)> lock(mDebugUpdateStatFuncMutex);

Review comment (suggestion):
we can't call `mInsertBlob` with the lock held. We need to get the callback to a local with the lock held, release the lock and then call the callback.

Code after:
bool Platform::setPresentFrameId(SwapChain const*, uint64_t) noexcept {
    return false;
}

bool Platform::queryFrameTimestamps(SwapChain const*, uint64_t, FrameTimestamps*) const noexcept {
    return false;
}

void Platform::setBlobFunc(InsertBlobFunc&& insertBlob, RetrieveBlobFunc&& retrieveBlob) noexcept {
    std::lock_guard<decltype(mMutex)> lock(mMutex);
    mInsertBlob = std::make_shared<InsertBlobFunc>(std::move(insertBlob));
    mRetrieveBlob = std::make_shared<RetrieveBlobFunc>(std::move(retrieveBlob));
}

bool Platform::hasInsertBlobFunc() const noexcept {
    std::lock_guard<decltype(mMutex)> lock(mMutex);
    return bool(mInsertBlob);
}

bool Platform::hasRetrieveBlobFunc() const noexcept {
    std::lock_guard<decltype(mMutex)> lock(mMutex);
    return bool(mRetrieveBlob);
}

void Platform::insertBlob(void const* key, size_t keySize, void const* value, size_t valueSize) {
    std::shared_ptr<InsertBlobFunc> callback;
    {
        std::unique_lock<decltype(mMutex)> lock(mMutex);
        callback = mInsertBlob;
    }
    if (callback) {
        (*callback)(key, keySize, value, valueSize);
    }
}

size_t Platform::retrieveBlob(void const* key, size_t keySize, void* value, size_t valueSize) {
    std::shared_ptr<RetrieveBlobFunc> callback;
    {
        std::unique_lock<decltype(mMutex)> lock(mMutex);
        callback = mRetrieveBlob;
    }
    if (callback) {
        return (*callback)(key, keySize, value, valueSize);
    }
    return 0;
}

void Platform::setDebugUpdateStatFunc(DebugUpdateStatFunc&& debugUpdateStat) noexcept {
    std::lock_guard<decltype(mMutex)> lock(mMutex);
    mDebugUpdateStat = std::make_shared<DebugUpdateStatFunc>(std::move(debugUpdateStat));
}