How to Modify AssetsManagerEx compare diff to Multithread?

How to Modify AssetsManagerEx compare diff to Multithread?
Hi, first sorry my pool english,
i’m chinese, currently using Cocos Creator 1.0.1,
in my project, i using HotUpdate in first scene,
when update start, and found remote has new version,
in AssetsManager.cpp -> startUpdate() method
here will call _localManifest->genDiff( _remoteManifest );
but that will temporary freeze front UI few seconds,
i wanna find solution for reslove this problem, How can i fix this?

any suggest for me?
thanks you :smiley:

Hi, guys…

i modify code void AssetsManagerEx::startUpdate()
using std::thread with lambda,
and std::mutex, std::condition_variable, std::unique_lock<std::mutex> to control…

but UI freeze problem still not resolve…

any one can help?

FullCode:

void AssetsManagerEx::startUpdate()
{
    CCLOG( "[Raz][AMEx] Into startUpdate()..." );
    if (_updateState != State::NEED_UPDATE) { CCLOG( "[Raz][AMEx] update status don't need Update, return." ); return; }

    _updateState = State::UPDATING;
    // Clean up before update
    _failedUnits.clear();
    _downloadUnits.clear();
    _compressedFiles.clear();
    _totalWaitToDownload = _totalToDownload = 0;
    _percent = _percentByFile = _sizeCollected = _totalSize = 0;
    _downloadedSize.clear();
    _totalEnabled = false;


    // Temporary manifest exists, resuming previous download
    if (_tempManifest->isLoaded() && _tempManifest->versionEquals(_remoteManifest))
    {
        CCLOG("[Raz][AMEx] Manifest Version Equal.");
        _tempManifest->genResumeAssetsList(&_downloadUnits);
        _totalWaitToDownload = _totalToDownload = (int)_downloadUnits.size();
        this->batchDownload();
        
        std::string msg = StringUtils::format("Resuming from previous unfinished update, %d files remains to be finished.", _totalToDownload);
        dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", msg);
    }
    // Check difference
    else
    {
        // Temporary manifest not exists or out of date,
        // it will be used to register the download states of each asset,
        // in this case, it equals remote manifest.
        _tempManifest->release();
        _tempManifest = _remoteManifest;

        CCLOG("[Raz][AMEx] Manifest Version Not Equal, GenDiff...");
        dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", "GenerateDiff.Start" );
        CCLOG("[Raz][AMEx] Start Generate Diff files.");


        std::mutex mutex;
        std::condition_variable watcher;
        std::unique_lock<std::mutex> uniqueLock( mutex );

        std::unordered_map<std::string, Manifest::AssetDiff> diff_map;

        //========================================================================================================================
        std::thread _t_genDiff( [&]( std::unordered_map<std::string, Manifest::AssetDiff>& _map )
        {
            CCLOG( "[Raz][AMEx][Thread] genDiff Start..." );
            //--------------------------------------------------------------------------------------------------------------------

            _map = _localManifest->genDiff( _remoteManifest );

            //--------------------------------------------------------------------------------------------------------------------
            CCLOG( "[Raz][AMEx][Thread] genDiff Done." );
            watcher.notify_one();

        }, std::ref( diff_map ) );


        //========================================================================================================================
        watcher.wait( uniqueLock );

        CCLOG("[Raz][AMEx] Done Generate Diff files, size[%d]", diff_map.size() );
        dispatchUpdateEvent( EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", "GenerateDiff.Done" );

        _t_genDiff.detach();

        if (diff_map.size() == 0)
        {
            updateSucceed();
        }
        else
        {
            // Generate download units for all assets that need to be updated or added
            std::string packageUrl = _remoteManifest->getPackageUrl();

            CCLOG("[Raz][AMEx] Start compare version between local and remote..");

            dispatchUpdateEvent( EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", "CompareDiff.Start" );
            //========================================================================================================================
            std::thread _t_compare( [&]()
            {
                CCLOG( "[Raz][AMEx][Thread] genDiff Start..." );
                //--------------------------------------------------------------------------------------------------------------------

                for (auto it = diff_map.begin(); it != diff_map.end(); ++it)
                {
                    Manifest::AssetDiff diff = it->second;

                    if ( diff.type == Manifest::DiffType::DELETED )
                    {
                        _fileUtils->removeFile(_storagePath + diff.asset.path);
                    }
                    else
                    {
                        std::string path = diff.asset.path;
                        _fileUtils->createDirectory( basename(_storagePath + path) ); // Create path

                        DownloadUnit unit;
                        unit.customId = it->first;
                        unit.srcUrl = packageUrl + path;
                        unit.storagePath = _storagePath + path;
                        _downloadUnits.emplace( unit.customId, unit );
                    }
                }

                //--------------------------------------------------------------------------------------------------------------------
                CCLOG( "[Raz][AMEx][Thread] genDiff Done." );
                watcher.notify_one();

            } );
            //========================================================================================================================
            watcher.wait( uniqueLock );
            dispatchUpdateEvent( EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", "CompareDiff.Done" );

            _t_compare.detach();

            CCLOG("[Raz][AMEx] Done of compare version between local and remote");

            dispatchUpdateEvent( EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", "CreateDownload.Start" );
            //========================================================================================================================
            std::thread _t_createDownload( [&,this]( std::condition_variable& watcher )
            {
                CCLOG( "[Raz][AMEx][Thread] Create Catch Download Start..." );
                //--------------------------------------------------------------------------------------------------------------------

                //CCLOG("[Raz][AMEx] Set Remote Manifest Assets download success.");
                // Set other assets' downloadState to SUCCESSED
                auto &assets = _remoteManifest->getAssets();
                for (auto it = assets.cbegin(); it != assets.cend(); ++it)
                {
                    const std::string &key = it->first;
                    auto diffIt = diff_map.find(key);
                    if (diffIt == diff_map.end())
                    {
                        _tempManifest->setAssetDownloadState( key, Manifest::DownloadState::SUCCESSED );
                    }
                }
                _totalWaitToDownload = _totalToDownload = (int)_downloadUnits.size();

                this->batchDownload();

                //--------------------------------------------------------------------------------------------------------------------
                CCLOG( "[Raz][AMEx][Thread] Create Catch Download Done." );
                watcher.notify_one();

            }, std::ref( watcher ) );
            //========================================================================================================================
            watcher.wait( uniqueLock );
            dispatchUpdateEvent( EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", "CreateDownload.Done" );

            _t_createDownload.detach();

            std::string msg = StringUtils::format("Start to update %d files from remote package.", _totalToDownload);
            CCLOG("[Raz][AMEx] Dispatch Update Progression FileCount[%d]  Message[%s]", _totalToDownload, msg.c_str() );
            dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", msg);
        }
    }

    _waitToUpdate = false;
}