int GDALRasterBlock::TakeLock() { const int nLockVal = AddLock(); CPLAssert(nLockVal >= 0); if( bSleepsForBockCacheDebug ) CPLSleep(CPLAtof( CPLGetConfigOption("GDAL_RB_TRYGET_SLEEP_AFTER_TAKE_LOCK", "0"))); if( nLockVal == 0 ) { #ifdef DEBUG CPLDebug( "GDAL", "TakeLock(%p): Block(%d,%d,%p) is being evicted while trying to " "reacquire it.", reinterpret_cast<void *>(CPLGetPID()), nXOff, nYOff, poBand ); #endif // The block is being evicted by GDALRasterBlock::Internalize() // or FlushCacheBlock(), so wait for this to be done before trying // again. DropLock(); // wait for the block having been unreferenced TAKE_LOCK; return FALSE; } Touch(); return TRUE; }
CPLErr GDALRasterBlock::Internalize() { CPLMutexHolderD(&hRBMutex); void *pNewData; int nSizeInBytes; GIntBig nCurCacheMax = GDALGetCacheMax64(); /* No risk of overflow as it is checked in GDALRasterBand::InitBlockInfo() */ nSizeInBytes = nXSize * nYSize * (GDALGetDataTypeSize(eType) / 8); pNewData = VSIMalloc(nSizeInBytes); if (pNewData == NULL) { CPLError(CE_Failure, CPLE_OutOfMemory, "GDALRasterBlock::Internalize : Out of memory allocating %d bytes.", nSizeInBytes); return(CE_Failure); } if (pData != NULL) memcpy(pNewData, pData, nSizeInBytes); pData = pNewData; /* -------------------------------------------------------------------- */ /* Flush old blocks if we are nearing our memory limit. */ /* -------------------------------------------------------------------- */ AddLock(); /* don't flush this block! */ nCacheUsed += nSizeInBytes; while (nCacheUsed > nCurCacheMax) { GIntBig nOldCacheUsed = nCacheUsed; GDALFlushCacheBlock(); if (nCacheUsed == nOldCacheUsed) break; } /* -------------------------------------------------------------------- */ /* Add this block to the list. */ /* -------------------------------------------------------------------- */ Touch(); DropLock(); return(CE_None); }