Skip to content

Commit

Permalink
gdalproxypool.cpp: reduce mutex contention, particularly useful for V…
Browse files Browse the repository at this point in the history
…RT multithreading of remove sources
  • Loading branch information
rouault committed Aug 1, 2024
1 parent 044bc69 commit f20a59c
Showing 1 changed file with 33 additions and 24 deletions.
57 changes: 33 additions & 24 deletions gcore/gdalproxypool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,17 @@ struct _GDALProxyPoolCacheEntry
GDALProxyPoolCacheEntry *next;
};

// This variable prevents a dataset that is going to be opened in
// GDALDatasetPool::_RefDataset from increasing refCount if, during its
// opening, it creates a GDALProxyPoolDataset.
// We increment it before opening or closing a cached dataset and decrement
// it afterwards
// The typical use case is a VRT made of simple sources that are VRT
// We don't want the "inner" VRT to take a reference on the pool, otherwise
// there is a high chance that this reference will not be dropped and the pool
// remain ghost.
static thread_local int refCountOfDisableRefCount = 0;

class GDALDatasetPool
{
private:
Expand All @@ -100,19 +111,6 @@ class GDALDatasetPool
GDALProxyPoolCacheEntry *firstEntry = nullptr;
GDALProxyPoolCacheEntry *lastEntry = nullptr;

/* This variable prevents a dataset that is going to be opened in
* GDALDatasetPool::_RefDataset */
/* from increasing refCount if, during its opening, it creates a
* GDALProxyPoolDataset */
/* We increment it before opening or closing a cached dataset and decrement
* it afterwards */
/* The typical use case is a VRT made of simple sources that are VRT */
/* We don't want the "inner" VRT to take a reference on the pool, otherwise
* there is */
/* a high chance that this reference will not be dropped and the pool remain
* ghost */
int refCountOfDisableRefCount = 0;

/* Caution : to be sure that we don't run out of entries, size must be at */
/* least greater or equal than the maximum number of threads */
explicit GDALDatasetPool(int maxSize, int64_t nMaxRAMUsage);
Expand Down Expand Up @@ -256,6 +254,9 @@ GDALDatasetPool::_RefDataset(const char *pszFileName, GDALAccess eAccess,
CSLConstList papszOpenOptions, int bShared,
bool bForceOpen, const char *pszOwner)
{
CPLMutex **pMutex = GDALGetphDLMutex();
CPLMutexHolderD(pMutex);

if (bInDestruction)
return nullptr;

Expand Down Expand Up @@ -340,7 +341,7 @@ GDALDatasetPool::_RefDataset(const char *pszFileName, GDALAccess eAccess,
{
GDALProxyPoolCacheEntry *next = cur->next;

if (cur->pszFileNameAndOpenOptions &&
if (cur->refCount >= 0 && cur->pszFileNameAndOpenOptions &&
osFilenameAndOO == cur->pszFileNameAndOpenOptions &&
((bShared && cur->responsiblePID == responsiblePID &&
((cur->pszOwner == nullptr && pszOwner == nullptr) ||
Expand Down Expand Up @@ -414,15 +415,24 @@ GDALDatasetPool::_RefDataset(const char *pszFileName, GDALAccess eAccess,
cur->pszFileNameAndOpenOptions = CPLStrdup(osFilenameAndOO.c_str());
cur->pszOwner = (pszOwner) ? CPLStrdup(pszOwner) : nullptr;
cur->responsiblePID = responsiblePID;
cur->refCount = 1;
cur->refCount = -1; // to mark loading of dataset in progress
cur->nRAMUsage = 0;

refCountOfDisableRefCount++;
int nFlag = ((eAccess == GA_Update) ? GDAL_OF_UPDATE : GDAL_OF_READONLY) |
GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR;
const int nFlag =
((eAccess == GA_Update) ? GDAL_OF_UPDATE : GDAL_OF_READONLY) |
GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR;
CPLConfigOptionSetter oSetter("CPL_ALLOW_VSISTDIN", "NO", true);
cur->poDS = GDALDataset::Open(pszFileName, nFlag, nullptr, papszOpenOptions,

// Release mutex while opening dataset to avoid lock contention.
CPLReleaseMutex(*pMutex);
auto poDS = GDALDataset::Open(pszFileName, nFlag, nullptr, papszOpenOptions,
nullptr);
CPLAcquireMutex(*pMutex, 1000.0);

cur->poDS = poDS;
cur->refCount = 1;

refCountOfDisableRefCount--;

if (cur->poDS)
Expand Down Expand Up @@ -545,7 +555,7 @@ void GDALDatasetPool::Ref()
singleton =
new GDALDatasetPool(GDALGetMaxDatasetPoolSize(), l_nMaxRAMUsage);
}
if (singleton->refCountOfDisableRefCount == 0)
if (refCountOfDisableRefCount == 0)
singleton->refCount++;
}

Expand All @@ -555,7 +565,7 @@ void GDALDatasetPool::PreventDestroy()
CPLMutexHolderD(GDALGetphDLMutex());
if (!singleton)
return;
singleton->refCountOfDisableRefCount++;
refCountOfDisableRefCount++;
}

/* keep that in sync with gdaldrivermanager.cpp */
Expand All @@ -578,7 +588,7 @@ void GDALDatasetPool::Unref()
CPLAssert(false);
return;
}
if (singleton->refCountOfDisableRefCount == 0)
if (refCountOfDisableRefCount == 0)
{
singleton->refCount--;
if (singleton->refCount == 0)
Expand All @@ -595,8 +605,8 @@ void GDALDatasetPool::ForceDestroy()
CPLMutexHolderD(GDALGetphDLMutex());
if (!singleton)
return;
singleton->refCountOfDisableRefCount--;
CPLAssert(singleton->refCountOfDisableRefCount == 0);
refCountOfDisableRefCount--;
CPLAssert(refCountOfDisableRefCount == 0);
singleton->refCount = 0;
delete singleton;
singleton = nullptr;
Expand All @@ -619,7 +629,6 @@ GDALDatasetPool::RefDataset(const char *pszFileName, GDALAccess eAccess,
char **papszOpenOptions, int bShared,
bool bForceOpen, const char *pszOwner)
{
CPLMutexHolderD(GDALGetphDLMutex());
return singleton->_RefDataset(pszFileName, eAccess, papszOpenOptions,
bShared, bForceOpen, pszOwner);
}
Expand Down

0 comments on commit f20a59c

Please sign in to comment.