CPLErr GDALHashSetBandBlockCache::FlushCache()
{
    FreeDanglingBlocks();

    CPLErr eGlobalErr = poBand->eFlushBlockErr;

    std::set<GDALRasterBlock*, BlockComparator> oOldSet;
    {
        CPLLockHolderOptionalLockD( hLock );
        oOldSet = std::move(m_oSet);
    }

    for( auto& poBlock: oOldSet )
    {
        if( poBlock->DropLockForRemovalFromStorage() )
        {
            CPLErr eErr = CE_None;

            if( eGlobalErr == CE_None && poBlock->GetDirty() )
                eErr = poBlock->Write();

            delete poBlock;

            if( eErr != CE_None )
                eGlobalErr = eErr;
        }
    }

    WaitKeepAliveCounter();

    return( eGlobalErr );
}
CPLErr GDALArrayBandBlockCache::FlushCache()
{
    FreeDanglingBlocks();

    CPLErr eGlobalErr = poBand->eFlushBlockErr;

/* -------------------------------------------------------------------- */
/*      Flush all blocks in memory ... this case is without subblocking.*/
/* -------------------------------------------------------------------- */
    if( !bSubBlockingActive )
    {
        for( int iY = 0; iY < poBand->nBlocksPerColumn; iY++ )
        {
            for( int iX = 0; iX < poBand->nBlocksPerRow; iX++ )
            {
                if( u.papoBlocks[iX + iY*poBand->nBlocksPerRow] != NULL )
                {
                    CPLErr    eErr;

                    eErr = FlushBlock( iX, iY, eGlobalErr == CE_None );

                    if( eErr != CE_None )
                        eGlobalErr = eErr;
                }
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      With subblocking.  We can short circuit missing subblocks.      */
/* -------------------------------------------------------------------- */
    else
    {
        int iSBX, iSBY;

        for( iSBY = 0; iSBY < nSubBlocksPerColumn; iSBY++ )
        {
            for( iSBX = 0; iSBX < nSubBlocksPerRow; iSBX++ )
            {
                int nSubBlock = iSBX + iSBY * nSubBlocksPerRow;
            
                GDALRasterBlock **papoSubBlockGrid =  u.papapoBlocks[nSubBlock];

                if( papoSubBlockGrid == NULL )
                    continue;

                for( int iY = 0; iY < SUBBLOCK_SIZE; iY++ )
                {
                    for( int iX = 0; iX < SUBBLOCK_SIZE; iX++ )
                    {
                        if( papoSubBlockGrid[iX + iY * SUBBLOCK_SIZE] != NULL )
                        {
                            CPLErr eErr;

                            eErr = FlushBlock( iX + iSBX * SUBBLOCK_SIZE, 
                                            iY + iSBY * SUBBLOCK_SIZE,
                                            eGlobalErr == CE_None );
                            if( eErr != CE_None )
                                eGlobalErr = eErr;
                        }
                    }
                }

                // We might as well get rid of this grid chunk since we know 
                // it is now empty.
                u.papapoBlocks[nSubBlock] = NULL;
                CPLFree( papoSubBlockGrid );
            }
        }
    }

    WaitKeepAliveCounter();

    return( eGlobalErr );
}