/** Destroys a pool of worker threads. * * Any still pending job will be completed before the destructor returns. */ CPLWorkerThreadPool::~CPLWorkerThreadPool() { if( hCond ) { WaitCompletion(); CPLAcquireMutex(hMutex, 1000.0); eState = CPLWTS_STOP; CPLReleaseMutex(hMutex); for(size_t i=0;i<aWT.size();i++) { CPLAcquireMutex(aWT[i].hMutex, 1000.0); CPLCondSignal(aWT[i].hCond); CPLReleaseMutex(aWT[i].hMutex); CPLJoinThread(aWT[i].hThread); CPLDestroyCond(aWT[i].hCond); CPLDestroyMutex(aWT[i].hMutex); } CPLListDestroy(psWaitingWorkerThreadsList); CPLDestroyCond(hCond); } CPLDestroyMutex(hMutex); }
/** Queue a new job. * * @param pfnFunc Function to run for the job. * @param pData User data to pass to the job function. * @return true in case of success. */ bool CPLWorkerThreadPool::SubmitJob( CPLThreadFunc pfnFunc, void* pData ) { CPLAssert( !aWT.empty() ); CPLWorkerThreadJob* psJob = static_cast<CPLWorkerThreadJob *>( VSI_MALLOC_VERBOSE(sizeof(CPLWorkerThreadJob))); if( psJob == nullptr ) return false; psJob->pfnFunc = pfnFunc; psJob->pData = pData; CPLList* psItem = static_cast<CPLList *>(VSI_MALLOC_VERBOSE(sizeof(CPLList))); if( psItem == nullptr ) { VSIFree(psJob); return false; } psItem->pData = psJob; CPLAcquireMutex(hMutex, 1000.0); psItem->psNext = psJobQueue; psJobQueue = psItem; nPendingJobs++; if( psWaitingWorkerThreadsList ) { CPLWorkerThread* psWorkerThread = static_cast<CPLWorkerThread *>(psWaitingWorkerThreadsList->pData); CPLAssert( psWorkerThread->bMarkedAsWaiting ); psWorkerThread->bMarkedAsWaiting = FALSE; CPLList* psNext = psWaitingWorkerThreadsList->psNext; CPLList* psToFree = psWaitingWorkerThreadsList; psWaitingWorkerThreadsList = psNext; nWaitingWorkerThreads--; // CPLAssert( // CPLListCount(psWaitingWorkerThreadsList) == nWaitingWorkerThreads); #if DEBUG_VERBOSE CPLDebug("JOB", "Waking up %p", psWorkerThread); #endif CPLAcquireMutex(psWorkerThread->hMutex, 1000.0); CPLReleaseMutex(hMutex); CPLCondSignal(psWorkerThread->hCond); CPLReleaseMutex(psWorkerThread->hMutex); CPLFree(psToFree); } else { CPLReleaseMutex(hMutex); } return true; }
static void WorkerFunc( void *arg ) { GDALDatasetH hDSIn = static_cast<GDALDatasetH>(arg); GDALDatasetH hDS = nullptr; for( int iOpenIter = 0; iOpenIter < nOpenIterations; iOpenIter++ ) { if( hDSIn != nullptr ) { hDS = hDSIn; } else { if( bLockOnOpen ) CPLAcquireMutex(pGlobalMutex, 100.0); hDS = GDALOpen(pszFilename, GA_ReadOnly); if( bLockOnOpen ) CPLReleaseMutex(pGlobalMutex); } for( int iIter = 0; iIter < nIterations && hDS != nullptr; iIter++ ) { const int nMyChecksum = GDALChecksumImage(GDALGetRasterBand(hDS, 1), 0, 0, GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS)); if( nMyChecksum != nChecksum ) { printf("Checksum ERROR in worker thread!\n"); break; } } if( hDS && hDSIn == nullptr ) { if( bLockOnOpen ) CPLAcquireMutex(pGlobalMutex, 100.0); GDALClose( hDS ); if( bLockOnOpen ) CPLReleaseMutex(pGlobalMutex); } else if ( hDSIn != nullptr ) { GDALFlushCache(hDSIn); } } CPLAcquireMutex(pGlobalMutex, 100.0); nPendingThreads--; CPLReleaseMutex(pGlobalMutex); }
void *CPLCreateMutex() { pthread_mutex_t *hMutex; hMutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); #if defined(PTHREAD_MUTEX_RECURSIVE) || defined(HAVE_PTHREAD_MUTEX_RECURSIVE) { pthread_mutexattr_t attr; pthread_mutexattr_init( &attr ); pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE ); pthread_mutex_init( hMutex, &attr ); } /* BSDs have PTHREAD_MUTEX_RECURSIVE as an enum, not a define. */ /* But they have #define MUTEX_TYPE_COUNTING_FAST PTHREAD_MUTEX_RECURSIVE */ #elif defined(MUTEX_TYPE_COUNTING_FAST) { pthread_mutexattr_t attr; pthread_mutexattr_init( &attr ); pthread_mutexattr_settype( &attr, MUTEX_TYPE_COUNTING_FAST ); pthread_mutex_init( hMutex, &attr ); } #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) pthread_mutex_t tmp_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; *hMutex = tmp_mutex; #else #error "Recursive mutexes apparently unsupported, configure --without-threads" #endif // mutexes are implicitly acquired when created. CPLAcquireMutex( hMutex, 0.0 ); return (void *) hMutex; }
void CPLWorkerThreadPool::DeclareJobFinished() { CPLAcquireMutex(hMutex, 1000.0); nPendingJobs--; CPLCondSignal(hCond); CPLReleaseMutex(hMutex); }
static void WorkerFunc( void * ) { GDALDatasetH hDS; int iIter, iOpenIter; for( iOpenIter = 0; iOpenIter < nOpenIterations; iOpenIter++ ) { if( bLockOnOpen ) CPLAcquireMutex( pGlobalMutex, 100.0 ); hDS = GDALOpen( pszFilename, GA_ReadOnly ); if( bLockOnOpen ) CPLReleaseMutex( pGlobalMutex ); for( iIter = 0; iIter < nIterations && hDS != NULL; iIter++ ) { int nMyChecksum; nMyChecksum = GDALChecksumImage( GDALGetRasterBand( hDS, 1 ), 0, 0, GDALGetRasterXSize( hDS ), GDALGetRasterYSize( hDS ) ); if( nMyChecksum != nChecksum ) { printf( "Checksum ERROR in worker thread!\n" ); break; } } if( hDS ) { if( bLockOnOpen ) CPLAcquireMutex( pGlobalMutex, 100.0 ); GDALClose( hDS ); if( bLockOnOpen ) CPLReleaseMutex( pGlobalMutex ); } } CPLAcquireMutex( pGlobalMutex, 100.0 ); nPendingThreads--; CPLReleaseMutex( pGlobalMutex ); }
int CPLCreateOrAcquireMutex( void **phMutex, double dfWaitInSeconds ) { int bSuccess = FALSE; #ifndef MUTEX_NONE static void *hCOAMutex = NULL; /* ** ironically, creation of this initial mutex is not threadsafe ** even though we use it to ensure that creation of other mutexes ** is threadsafe. */ if( hCOAMutex == NULL ) { hCOAMutex = CPLCreateMutex(); if (hCOAMutex == NULL) { *phMutex = NULL; return FALSE; } } else { CPLAcquireMutex( hCOAMutex, dfWaitInSeconds ); } if( *phMutex == NULL ) { *phMutex = CPLCreateMutex(); bSuccess = *phMutex != NULL; CPLReleaseMutex( hCOAMutex ); } else { CPLReleaseMutex( hCOAMutex ); bSuccess = CPLAcquireMutex( *phMutex, dfWaitInSeconds ); } #endif /* ndef MUTEX_NONE */ return bSuccess; }
void CPLCondWait( void *hCond, void* hClientMutex ) { Win32Cond* psCond = (Win32Cond*) hCond; HANDLE hEvent = (HANDLE) CPLGetTLS(CTLS_WIN32_COND); if (hEvent == NULL) { hEvent = CreateEvent(NULL, /* security attributes */ 0, /* manual reset = no */ 0, /* initial state = unsignaled */ NULL /* no name */); CPLAssert(hEvent != NULL); CPLSetTLSWithFreeFunc(CTLS_WIN32_COND, hEvent, CPLTLSFreeEvent); } /* Insert the waiter into the waiter list of the condition */ CPLAcquireMutex(psCond->hInternalMutex, 1000.0); WaiterItem* psItem = (WaiterItem*)malloc(sizeof(WaiterItem)); CPLAssert(psItem != NULL); psItem->hEvent = hEvent; psItem->psNext = psCond->psWaiterList; psCond->psWaiterList = psItem; CPLReleaseMutex(psCond->hInternalMutex); /* Release the client mutex before waiting for the event being signaled */ CPLReleaseMutex(hClientMutex); // Ideally we would check that we do not get WAIT_FAILED but it is hard // to report a failure. WaitForSingleObject(hEvent, INFINITE); /* Reacquire the client mutex */ CPLAcquireMutex(hClientMutex, 1000.0); }
/** Wait for completion of part or whole jobs. * * @param nMaxRemainingJobs Maximum number of pendings jobs that are allowed * in the queue after this method has completed. Might be * 0 to wait for all jobs. */ void CPLWorkerThreadPool::WaitCompletion(int nMaxRemainingJobs) { if( nMaxRemainingJobs < 0 ) nMaxRemainingJobs = 0; while( true ) { CPLAcquireMutex(hMutex, 1000.0); int nPendingJobsLocal = nPendingJobs; if( nPendingJobsLocal > nMaxRemainingJobs ) CPLCondWait(hCond, hMutex); CPLReleaseMutex(hMutex); if( nPendingJobsLocal <= nMaxRemainingJobs ) break; } }
void GDALAbstractBandBlockCache::WaitKeepAliveCounter() { #ifdef DEBUG_VERBOSE CPLDebug("GDAL", "WaitKeepAliveCounter()"); #endif CPLAcquireMutex(hCondMutex, 1000); while( nKeepAliveCounter != 0 ) { CPLDebug( "GDAL", "Waiting for other thread to finish working with our " "blocks" ); CPLCondWait(hCond, hCondMutex); } CPLReleaseMutex(hCondMutex); }
void CPLCondSignal( void *hCond ) { Win32Cond* psCond = (Win32Cond*) hCond; /* Signal the first registered event, and remove it from the list */ CPLAcquireMutex(psCond->hInternalMutex, 1000.0); WaiterItem* psIter = psCond->psWaiterList; if (psIter != NULL) { SetEvent(psIter->hEvent); psCond->psWaiterList = psIter->psNext; free(psIter); } CPLReleaseMutex(psCond->hInternalMutex); }
CPLMutexHolder::CPLMutexHolder( void *hMutexIn, double dfWaitInSeconds, const char *pszFileIn, int nLineIn ) { #ifndef MUTEX_NONE pszFile = pszFileIn; nLine = nLineIn; hMutex = hMutexIn; if( hMutex != NULL && !CPLAcquireMutex( hMutex, dfWaitInSeconds ) ) { fprintf( stderr, "CPLMutexHolder: Failed to acquire mutex!\n" ); hMutex = NULL; } #endif /* ndef MUTEX_NONE */ }
void CPLCondBroadcast( void *hCond ) { Win32Cond* psCond = (Win32Cond*) hCond; /* Signal all the registered events, and remove them from the list */ CPLAcquireMutex(psCond->hInternalMutex, 1000.0); WaiterItem* psIter = psCond->psWaiterList; while (psIter != NULL) { WaiterItem* psNext = psIter->psNext; SetEvent(psIter->hEvent); free(psIter); psIter = psNext; } psCond->psWaiterList = NULL; CPLReleaseMutex(psCond->hInternalMutex); }
int CPLCreateOrAcquireMutex( void **phMutex, double dfWaitInSeconds ) { int bSuccess = FALSE; pthread_mutex_lock(&global_mutex); if( *phMutex == NULL ) { *phMutex = CPLCreateMutexInternal(TRUE); bSuccess = *phMutex != NULL; pthread_mutex_unlock(&global_mutex); } else { pthread_mutex_unlock(&global_mutex); bSuccess = CPLAcquireMutex( *phMutex, dfWaitInSeconds ); } return bSuccess; }
void GDALAbstractBandBlockCache::AddBlockToFreeList( GDALRasterBlock *poBlock ) { CPLAssert(poBlock->poPrevious == NULL); CPLAssert(poBlock->poNext == NULL); { #ifdef DEBUG_VERBOSE_ABBC CPLAtomicInc(&nAllBandsKeptAlivedBlocks); fprintf(stderr, "AddBlockToFreeList(): nAllBandsKeptAlivedBlocks=%d\n", nAllBandsKeptAlivedBlocks); #endif CPLLockHolderOptionalLockD(hSpinLock); poBlock->poNext = psListBlocksToFree; psListBlocksToFree = poBlock; } // If no more blocks in transient state, then warn WaitKeepAliveCounter() CPLAcquireMutex(hCondMutex, 1000); if( CPLAtomicDec(&nKeepAliveCounter) == 0 ) { CPLCondSignal(hCond); } CPLReleaseMutex(hCondMutex); }
int CPLCreateOrAcquireMutex( void **phMutex, double dfWaitInSeconds ) { int bSuccess = FALSE; static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&global_mutex); if( *phMutex == NULL ) { *phMutex = CPLCreateMutex(); bSuccess = *phMutex != NULL; pthread_mutex_unlock(&global_mutex); } else { pthread_mutex_unlock(&global_mutex); bSuccess = CPLAcquireMutex( *phMutex, dfWaitInSeconds ); } return bSuccess; }
static void *CPLCreateMutexInternal(int bAlreadyInGlobalLock) { MutexLinkedElt* psItem = (MutexLinkedElt *) malloc(sizeof(MutexLinkedElt)); if (psItem == NULL) return NULL; if( !bAlreadyInGlobalLock ) pthread_mutex_lock(&global_mutex); psItem->psPrev = NULL; psItem->psNext = psMutexList; if( psMutexList ) psMutexList->psPrev = psItem; psMutexList = psItem; if( !bAlreadyInGlobalLock ) pthread_mutex_unlock(&global_mutex); CPLInitMutex(psItem); // mutexes are implicitly acquired when created. CPLAcquireMutex( &(psItem->sMutex), 0.0 ); return psItem; }
GDALDataset *HDF4Dataset::Open( GDALOpenInfo * poOpenInfo ) { if( !Identify( poOpenInfo ) ) return NULL; CPLMutexHolderD(&hHDF4Mutex); /* -------------------------------------------------------------------- */ /* Try opening the dataset. */ /* -------------------------------------------------------------------- */ // Attempt to increase maximum number of opened HDF files #ifdef HDF4_HAS_MAXOPENFILES intn nCurrMax = 0; intn nSysLimit = 0; if ( SDget_maxopenfiles(&nCurrMax, &nSysLimit) >= 0 && nCurrMax < nSysLimit ) { /*intn res = */SDreset_maxopenfiles( nSysLimit ); } #endif /* HDF4_HAS_MAXOPENFILES */ int32 hHDF4 = Hopen(poOpenInfo->pszFilename, DFACC_READ, 0); if( hHDF4 <= 0 ) return( NULL ); Hclose( hHDF4 ); /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ // Release mutex otherwise we will deadlock with GDALDataset own mutex. CPLReleaseMutex(hHDF4Mutex); HDF4Dataset *poDS = new HDF4Dataset(); CPLAcquireMutex(hHDF4Mutex, 1000.0); if( poOpenInfo->fpL != NULL ) { VSIFCloseL(poOpenInfo->fpL); poOpenInfo->fpL = NULL; } /* -------------------------------------------------------------------- */ /* Open HDF SDS Interface. */ /* -------------------------------------------------------------------- */ poDS->hSD = SDstart( poOpenInfo->pszFilename, DFACC_READ ); if ( poDS->hSD == -1 ) { // Release mutex otherwise we will deadlock with GDALDataset own mutex. CPLReleaseMutex(hHDF4Mutex); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open HDF4 file \"%s\" for SDS reading.\n", poOpenInfo->pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Now read Global Attributes. */ /* -------------------------------------------------------------------- */ if ( poDS->ReadGlobalAttributes( poDS->hSD ) != CE_None ) { // Release mutex otherwise we will deadlock with GDALDataset own mutex. CPLReleaseMutex(hHDF4Mutex); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to read global attributes from HDF4 file \"%s\".\n", poOpenInfo->pszFilename ); return NULL; } poDS->SetMetadata( poDS->papszGlobalMetadata, "" ); /* -------------------------------------------------------------------- */ /* Determine type of file we read. */ /* -------------------------------------------------------------------- */ const char *pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Signature"); if ( pszValue != NULL && EQUAL( pszValue, pszGDALSignature ) ) { poDS->iSubdatasetType = H4ST_GDAL; poDS->pszSubdatasetType = "GDAL_HDF4"; } else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title")) != NULL && EQUAL( pszValue, "SeaWiFS Level-1A Data" ) ) { poDS->iSubdatasetType = H4ST_SEAWIFS_L1A; poDS->pszSubdatasetType = "SEAWIFS_L1A"; } else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title")) != NULL && EQUAL( pszValue, "SeaWiFS Level-2 Data" ) ) { poDS->iSubdatasetType = H4ST_SEAWIFS_L2; poDS->pszSubdatasetType = "SEAWIFS_L2"; } else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "Title")) != NULL && EQUAL( pszValue, "SeaWiFS Level-3 Standard Mapped Image" ) ) { poDS->iSubdatasetType = H4ST_SEAWIFS_L3; poDS->pszSubdatasetType = "SEAWIFS_L3"; } else if ( (pszValue = CSLFetchNameValue(poDS->papszGlobalMetadata, "L1 File Generated By")) != NULL && STARTS_WITH_CI(pszValue, "HYP version ") ) { poDS->iSubdatasetType = H4ST_HYPERION_L1; poDS->pszSubdatasetType = "HYPERION_L1"; } else { poDS->iSubdatasetType = H4ST_UNKNOWN; poDS->pszSubdatasetType = "UNKNOWN"; } /* -------------------------------------------------------------------- */ /* If we have HDF-EOS dataset, process it here. */ /* -------------------------------------------------------------------- */ int32 aiDimSizes[H4_MAX_VAR_DIMS]; // TODO: Get this off of the stack. int32 iRank = 0; int32 iNumType = 0; int32 nAttrs = 0; bool bIsHDF = true; // Sometimes "HDFEOSVersion" attribute is not defined and we will // determine HDF-EOS datasets using other records // (see ReadGlobalAttributes() method). if ( poDS->bIsHDFEOS || CSLFetchNameValue(poDS->papszGlobalMetadata, "HDFEOSVersion") ) { /* -------------------------------------------------------------------- */ /* Process swath layers. */ /* -------------------------------------------------------------------- */ hHDF4 = SWopen( poOpenInfo->pszFilename, DFACC_READ ); if( hHDF4 < 0) { // Release mutex otherwise we will deadlock with GDALDataset own // mutex. CPLReleaseMutex(hHDF4Mutex); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open HDF-EOS file \"%s\" for swath reading.\n", poOpenInfo->pszFilename ); return NULL; } int32 nStrBufSize; int32 nSubDatasets = SWinqswath(poOpenInfo->pszFilename, NULL, &nStrBufSize); #ifdef DEBUG CPLDebug( "HDF4", "Number of HDF-EOS swaths: %d", static_cast<int>( nSubDatasets ) ); #endif if ( nSubDatasets > 0 && nStrBufSize > 0 ) { char *pszSwathList = static_cast<char *>( CPLMalloc( nStrBufSize + 1 ) ); SWinqswath( poOpenInfo->pszFilename, pszSwathList, &nStrBufSize ); pszSwathList[nStrBufSize] = '\0'; #ifdef DEBUG CPLDebug( "HDF4", "List of HDF-EOS swaths: %s", pszSwathList ); #endif char **papszSwaths = CSLTokenizeString2( pszSwathList, ",", CSLT_HONOURSTRINGS ); CPLFree( pszSwathList ); if ( nSubDatasets != CSLCount(papszSwaths) ) { CSLDestroy( papszSwaths ); // Release mutex otherwise we will deadlock with GDALDataset own // mutex. CPLReleaseMutex(hHDF4Mutex); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); CPLDebug( "HDF4", "Cannot parse list of HDF-EOS grids." ); return NULL; } for( int32 i = 0; i < nSubDatasets; i++) { const int32 hSW = SWattach( hHDF4, papszSwaths[i] ); const int32 nFields = SWnentries( hSW, HDFE_NENTDFLD, &nStrBufSize ); char *pszFieldList = static_cast<char *>( CPLMalloc( nStrBufSize + 1 ) ); int32 *paiRank = static_cast<int32 *>( CPLMalloc( nFields * sizeof(int32) ) ); int32 *paiNumType = static_cast<int32 *>( CPLMalloc( nFields * sizeof(int32) ) ); SWinqdatafields( hSW, pszFieldList, paiRank, paiNumType ); #ifdef DEBUG { char * const pszTmp = SPrintArray( GDT_UInt32, paiRank, nFields, "," ); CPLDebug( "HDF4", "Number of data fields in swath %d: %d", static_cast<int>( i ), static_cast<int>( nFields ) ); CPLDebug( "HDF4", "List of data fields in swath %d: %s", static_cast<int>( i ), pszFieldList ); CPLDebug( "HDF4", "Data fields ranks: %s", pszTmp ); CPLFree( pszTmp ); } #endif char **papszFields = CSLTokenizeString2( pszFieldList, ",", CSLT_HONOURSTRINGS ); char szTemp[256] = {'\0'}; // TODO: Get this off the stack. for( int32 j = 0; j < nFields; j++ ) { SWfieldinfo( hSW, papszFields[j], &iRank, aiDimSizes, &iNumType, NULL ); if ( iRank < 2 ) continue; // Add field to the list of GDAL subdatasets const int nCount = CSLCount( poDS->papszSubDatasets ) / 2; snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 ); // We will use the field index as an identificator. poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets, szTemp, CPLSPrintf("HDF4_EOS:EOS_SWATH:\"%s\":%s:%s", poOpenInfo->pszFilename, papszSwaths[i], papszFields[j]) ); snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 ); char *pszString = SPrintArray( GDT_UInt32, aiDimSizes, iRank, "x" ); poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets, szTemp, CPLSPrintf( "[%s] %s %s (%s)", pszString, papszFields[j], papszSwaths[i], poDS->GetDataTypeName(iNumType) ) ); CPLFree( pszString ); szTemp[0] = '\0'; } CSLDestroy( papszFields ); CPLFree( paiNumType ); CPLFree( paiRank ); CPLFree( pszFieldList ); SWdetach( hSW ); } CSLDestroy( papszSwaths ); } SWclose( hHDF4 ); /* -------------------------------------------------------------------- */ /* Process grid layers. */ /* -------------------------------------------------------------------- */ hHDF4 = GDopen( poOpenInfo->pszFilename, DFACC_READ ); nSubDatasets = GDinqgrid( poOpenInfo->pszFilename, NULL, &nStrBufSize ); #ifdef DEBUG CPLDebug( "HDF4", "Number of HDF-EOS grids: %d", static_cast<int>( nSubDatasets ) ); #endif if ( nSubDatasets > 0 && nStrBufSize > 0 ) { char *pszGridList = static_cast<char *>( CPLMalloc( nStrBufSize + 1 ) ); GDinqgrid( poOpenInfo->pszFilename, pszGridList, &nStrBufSize ); #ifdef DEBUG CPLDebug( "HDF4", "List of HDF-EOS grids: %s", pszGridList ); #endif char **papszGrids = CSLTokenizeString2( pszGridList, ",", CSLT_HONOURSTRINGS ); CPLFree( pszGridList ); if ( nSubDatasets != CSLCount(papszGrids) ) { CSLDestroy( papszGrids ); GDclose( hHDF4 ); // Release mutex otherwise we will deadlock with GDALDataset own // mutex. CPLReleaseMutex(hHDF4Mutex); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); CPLDebug( "HDF4", "Cannot parse list of HDF-EOS grids." ); return NULL; } for( int32 i = 0; i < nSubDatasets; i++) { const int32 hGD = GDattach( hHDF4, papszGrids[i] ); const int32 nFields = GDnentries( hGD, HDFE_NENTDFLD, &nStrBufSize ); char *pszFieldList = static_cast<char *>( CPLMalloc( nStrBufSize + 1 ) ); int32 *paiRank = static_cast<int32 *>( CPLMalloc( nFields * sizeof(int32) ) ); int32 *paiNumType = static_cast<int32 *>( CPLMalloc( nFields * sizeof(int32) ) ); GDinqfields( hGD, pszFieldList, paiRank, paiNumType ); #ifdef DEBUG { char* pszTmp = SPrintArray( GDT_UInt32, paiRank, nFields, "," ); CPLDebug( "HDF4", "Number of fields in grid %d: %d", static_cast<int>( i ), static_cast<int>( nFields ) ); CPLDebug( "HDF4", "List of fields in grid %d: %s", static_cast<int>( i ), pszFieldList ); CPLDebug( "HDF4", "Fields ranks: %s", pszTmp ); CPLFree( pszTmp ); } #endif char **papszFields = CSLTokenizeString2( pszFieldList, ",", CSLT_HONOURSTRINGS ); char szTemp[256]; for( int32 j = 0; j < nFields; j++ ) { GDfieldinfo( hGD, papszFields[j], &iRank, aiDimSizes, &iNumType, NULL ); if ( iRank < 2 ) continue; // Add field to the list of GDAL subdatasets const int nCount = CSLCount( poDS->papszSubDatasets ) / 2; snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 ); // We will use the field index as an identificator. poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp, CPLSPrintf( "HDF4_EOS:EOS_GRID:\"%s\":%s:%s", poOpenInfo->pszFilename, papszGrids[i], papszFields[j])); snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 ); char *pszString = SPrintArray( GDT_UInt32, aiDimSizes, iRank, "x" ); poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets, szTemp, CPLSPrintf("[%s] %s %s (%s)", pszString, papszFields[j], papszGrids[i], poDS->GetDataTypeName(iNumType)) ); CPLFree( pszString ); } CSLDestroy( papszFields ); CPLFree( paiNumType ); CPLFree( paiRank ); CPLFree( pszFieldList ); GDdetach( hGD ); } CSLDestroy( papszGrids ); } GDclose( hHDF4 ); bIsHDF = ( nSubDatasets == 0 ); // Try to read as HDF } char szName[VSNAMELENMAX + 1]; if( bIsHDF ) { /* -------------------------------------------------------------------- */ /* Make a list of subdatasets from SDSs contained in input HDF file. */ /* -------------------------------------------------------------------- */ int32 nDatasets = 0; if ( SDfileinfo( poDS->hSD, &nDatasets, &nAttrs ) != 0 ) return NULL; char szTemp[256] = {'\0'}; // TODO: Get this off the stack. const char *pszName = NULL; for( int32 i = 0; i < nDatasets; i++ ) { const int32 iSDS = SDselect( poDS->hSD, i ); if ( SDgetinfo( iSDS, szName, &iRank, aiDimSizes, &iNumType, &nAttrs) != 0 ) return NULL; if ( iRank == 1 ) // Skip 1D datsets continue; // Do sort of known datasets. We will display only image bands if ( (poDS->iSubdatasetType == H4ST_SEAWIFS_L1A ) && !STARTS_WITH_CI(szName, "l1a_data") ) continue; else pszName = szName; // Add datasets with multiple dimensions to the list of GDAL subdatasets const int nCount = CSLCount( poDS->papszSubDatasets ) / 2; snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 ); // We will use SDS index as an identificator, because SDS names // are not unique. Filename also needed for further file opening poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets, szTemp, CPLSPrintf( "HDF4_SDS:%s:\"%s\":%ld", poDS->pszSubdatasetType, poOpenInfo->pszFilename, static_cast<long>( i ) ) ); snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 ); char *pszString = SPrintArray( GDT_UInt32, aiDimSizes, iRank, "x" ); poDS->papszSubDatasets = CSLSetNameValue( poDS->papszSubDatasets, szTemp, CPLSPrintf( "[%s] %s (%s)", pszString, pszName, poDS->GetDataTypeName(iNumType)) ); CPLFree( pszString ); SDendaccess( iSDS ); szTemp[0] = '\0'; } SDend( poDS->hSD ); poDS->hSD = 0; } /* -------------------------------------------------------------------- */ /* Build a list of raster images. Note, that HDF-EOS dataset may */ /* contain a raster image as well. */ /* -------------------------------------------------------------------- */ hHDF4 = Hopen(poOpenInfo->pszFilename, DFACC_READ, 0); poDS->hGR = GRstart( hHDF4 ); if ( poDS->hGR != -1 ) { if ( GRfileinfo( poDS->hGR, &poDS->nImages, &nAttrs ) == -1 ) { // Release mutex otherwise we will deadlock with GDALDataset own // mutex. CPLReleaseMutex(hHDF4Mutex); GRend( poDS->hGR ); poDS->hGR = 0; Hclose( hHDF4 ); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); return NULL; } char szTemp[256] = {'\0'}; // TODO: Get this off the stack. for( int32 i = 0; i < poDS->nImages; i++ ) { const int32 iGR = GRselect( poDS->hGR, i ); // iRank in GR interface has another meaning. It represents number // of samples per pixel. aiDimSizes has only two dimensions. int32 iInterlaceMode; if ( GRgetiminfo( iGR, szName, &iRank, &iNumType, &iInterlaceMode, aiDimSizes, &nAttrs ) != 0 ) { // Release mutex otherwise we will deadlock with GDALDataset // own mutex. CPLReleaseMutex(hHDF4Mutex); GRend( poDS->hGR ); poDS->hGR = 0; Hclose( hHDF4 ); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); return NULL; } const int nCount = CSLCount( poDS->papszSubDatasets ) / 2; snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_NAME", nCount + 1 ); poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp,CPLSPrintf( "HDF4_GR:UNKNOWN:\"%s\":%ld", poOpenInfo->pszFilename, static_cast<long>( i ) ) ); snprintf( szTemp, sizeof(szTemp), "SUBDATASET_%d_DESC", nCount + 1 ); char *pszString = SPrintArray( GDT_UInt32, aiDimSizes, 2, "x" ); poDS->papszSubDatasets = CSLSetNameValue(poDS->papszSubDatasets, szTemp, CPLSPrintf( "[%sx%ld] %s (%s)", pszString, static_cast<long>( iRank ), szName, poDS->GetDataTypeName(iNumType)) ); CPLFree( pszString ); GRendaccess( iGR ); szTemp[0] = '\0'; } GRend( poDS->hGR ); poDS->hGR = 0; } Hclose( hHDF4 ); poDS->nRasterXSize = poDS->nRasterYSize = 512; // XXX: bogus values // Make sure we don't try to do any pam stuff with this dataset. poDS->nPamFlags |= GPF_NOSAVE; /* -------------------------------------------------------------------- */ /* If we have single subdataset only, open it immediately */ /* -------------------------------------------------------------------- */ if ( CSLCount( poDS->papszSubDatasets ) / 2 == 1 ) { char *pszSDSName = CPLStrdup( CSLFetchNameValue( poDS->papszSubDatasets, "SUBDATASET_1_NAME" )); // Release mutex otherwise we will deadlock with GDALDataset own mutex. CPLReleaseMutex(hHDF4Mutex); delete poDS; poDS = NULL; GDALDataset* poRetDS = reinterpret_cast<GDALDataset*>( GDALOpen( pszSDSName, poOpenInfo->eAccess ) ); CPLFree( pszSDSName ); CPLAcquireMutex(hHDF4Mutex, 1000.0); if (poRetDS) { poRetDS->SetDescription(poOpenInfo->pszFilename); } return poRetDS; } else { /* -------------------------------------------------------------------- */ /* Confirm the requested access is supported. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) { // Release mutex otherwise we will deadlock with GDALDataset own // mutex. CPLReleaseMutex(hHDF4Mutex); delete poDS; CPLAcquireMutex(hHDF4Mutex, 1000.0); CPLError( CE_Failure, CPLE_NotSupported, "The HDF4 driver does not support update access to " "existing datasets.\n" ); return NULL; } } return( poDS ); }
int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z, int *pabSuccess ) { int err, i; /* -------------------------------------------------------------------- */ /* Potentially transform to radians. */ /* -------------------------------------------------------------------- */ if( bSourceLatLong ) { if( bSourceWrap ) { for( i = 0; i < nCount; i++ ) { if( x[i] != HUGE_VAL && y[i] != HUGE_VAL ) { if( x[i] < dfSourceWrapLong - 180.0 ) x[i] += 360.0; else if( x[i] > dfSourceWrapLong + 180 ) x[i] -= 360.0; } } } for( i = 0; i < nCount; i++ ) { if( x[i] != HUGE_VAL ) { x[i] *= dfSourceToRadians; y[i] *= dfSourceToRadians; } } } /* -------------------------------------------------------------------- */ /* Do the transformation using PROJ.4. */ /* -------------------------------------------------------------------- */ if( !bIdentityTransform && pjctx == NULL ) { /* The mutex has already been created */ CPLAssert(hPROJMutex != NULL); CPLAcquireMutex(hPROJMutex, 1000.0); } if( bIdentityTransform ) err = 0; else if (bCheckWithInvertProj) { /* For some projections, we cannot detect if we are trying to reproject */ /* coordinates outside the validity area of the projection. So let's do */ /* the reverse reprojection and compare with the source coordinates */ if (nCount > nMaxCount) { nMaxCount = nCount; padfOriX = (double*) CPLRealloc(padfOriX, sizeof(double)*nCount); padfOriY = (double*) CPLRealloc(padfOriY, sizeof(double)*nCount); padfOriZ = (double*) CPLRealloc(padfOriZ, sizeof(double)*nCount); padfTargetX = (double*) CPLRealloc(padfTargetX, sizeof(double)*nCount); padfTargetY = (double*) CPLRealloc(padfTargetY, sizeof(double)*nCount); padfTargetZ = (double*) CPLRealloc(padfTargetZ, sizeof(double)*nCount); } memcpy(padfOriX, x, sizeof(double)*nCount); memcpy(padfOriY, y, sizeof(double)*nCount); if (z) { memcpy(padfOriZ, z, sizeof(double)*nCount); } err = pfn_pj_transform( psPJSource, psPJTarget, nCount, 1, x, y, z ); if (err == 0) { memcpy(padfTargetX, x, sizeof(double)*nCount); memcpy(padfTargetY, y, sizeof(double)*nCount); if (z) { memcpy(padfTargetZ, z, sizeof(double)*nCount); } err = pfn_pj_transform( psPJTarget, psPJSource , nCount, 1, padfTargetX, padfTargetY, (z) ? padfTargetZ : NULL); if (err == 0) { for( i = 0; i < nCount; i++ ) { if ( x[i] != HUGE_VAL && y[i] != HUGE_VAL && (fabs(padfTargetX[i] - padfOriX[i]) > dfThreshold || fabs(padfTargetY[i] - padfOriY[i]) > dfThreshold) ) { x[i] = HUGE_VAL; y[i] = HUGE_VAL; } } } } } else { err = pfn_pj_transform( psPJSource, psPJTarget, nCount, 1, x, y, z ); } /* -------------------------------------------------------------------- */ /* Try to report an error through CPL. Get proj.4 error string */ /* if possible. Try to avoid reporting thousands of error */ /* ... supress further error reporting on this OGRProj4CT if we */ /* have already reported 20 errors. */ /* -------------------------------------------------------------------- */ if( err != 0 ) { if( pabSuccess ) memset( pabSuccess, 0, sizeof(int) * nCount ); if( ++nErrorCount < 20 ) { if (pjctx != NULL) /* pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0 */ CPLAcquireMutex(hPROJMutex, 1000.0); const char *pszError = NULL; if( pfn_pj_strerrno != NULL ) pszError = pfn_pj_strerrno( err ); if( pszError == NULL ) CPLError( CE_Failure, CPLE_AppDefined, "Reprojection failed, err = %d", err ); else CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError ); if (pjctx != NULL) /* pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0 */ CPLReleaseMutex(hPROJMutex); } else if( nErrorCount == 20 ) { CPLError( CE_Failure, CPLE_AppDefined, "Reprojection failed, err = %d, further errors will be supressed on the transform object.", err ); } if (pjctx == NULL) CPLReleaseMutex(hPROJMutex); return FALSE; } if( !bIdentityTransform && pjctx == NULL ) CPLReleaseMutex(hPROJMutex); /* -------------------------------------------------------------------- */ /* Potentially transform back to degrees. */ /* -------------------------------------------------------------------- */ if( bTargetLatLong ) { for( i = 0; i < nCount; i++ ) { if( x[i] != HUGE_VAL && y[i] != HUGE_VAL ) { x[i] *= dfTargetFromRadians; y[i] *= dfTargetFromRadians; } } if( bTargetWrap ) { for( i = 0; i < nCount; i++ ) { if( x[i] != HUGE_VAL && y[i] != HUGE_VAL ) { if( x[i] < dfTargetWrapLong - 180.0 ) x[i] += 360.0; else if( x[i] > dfTargetWrapLong + 180 ) x[i] -= 360.0; } } } } /* -------------------------------------------------------------------- */ /* Establish error information if pabSuccess provided. */ /* -------------------------------------------------------------------- */ if( pabSuccess ) { for( i = 0; i < nCount; i++ ) { if( x[i] == HUGE_VAL || y[i] == HUGE_VAL ) pabSuccess[i] = FALSE; else pabSuccess[i] = TRUE; } } return TRUE; }
CPLWorkerThreadJob * CPLWorkerThreadPool::GetNextJob( CPLWorkerThread* psWorkerThread ) { while(true) { CPLAcquireMutex(hMutex, 1000.0); if( eState == CPLWTS_STOP ) { CPLReleaseMutex(hMutex); return nullptr; } CPLList* psTopJobIter = psJobQueue; if( psTopJobIter ) { psJobQueue = psTopJobIter->psNext; #if DEBUG_VERBOSE CPLDebug("JOB", "%p got a job", psWorkerThread); #endif CPLWorkerThreadJob* psJob = static_cast<CPLWorkerThreadJob*>(psTopJobIter->pData); CPLReleaseMutex(hMutex); CPLFree(psTopJobIter); return psJob; } if( !psWorkerThread->bMarkedAsWaiting ) { psWorkerThread->bMarkedAsWaiting = TRUE; nWaitingWorkerThreads++; CPLAssert(nWaitingWorkerThreads <= static_cast<int>(aWT.size())); CPLList* psItem = static_cast<CPLList *>(VSI_MALLOC_VERBOSE(sizeof(CPLList))); if( psItem == nullptr ) { eState = CPLWTS_ERROR; CPLCondSignal(hCond); CPLReleaseMutex(hMutex); return nullptr; } psItem->pData = psWorkerThread; psItem->psNext = psWaitingWorkerThreadsList; psWaitingWorkerThreadsList = psItem; #if DEBUG_VERBOSE CPLAssert(CPLListCount(psWaitingWorkerThreadsList) == nWaitingWorkerThreads); #endif } CPLCondSignal(hCond); CPLAcquireMutex(psWorkerThread->hMutex, 1000.0); #if DEBUG_VERBOSE CPLDebug("JOB", "%p sleeping", psWorkerThread); #endif CPLReleaseMutex(hMutex); CPLCondWait( psWorkerThread->hCond, psWorkerThread->hMutex ); // TODO(rouault): Explain or delete. // CPLWorkerThreadJob* psJob = psWorkerThread->psNextJob; // psWorkerThread->psNextJob = nullptr; CPLReleaseMutex(psWorkerThread->hMutex); // TODO(rouault): Explain or delete. // if( psJob ) // return psJob; } }
void VSICurlStreamingFSHandler::AcquireMutex() { CPLAcquireMutex(hMutex, 1000.0); }
/** Setup the pool. * * @param nThreads Number of threads to launch * @param pfnInitFunc Initialization function to run in each thread. May be NULL * @param pasInitData Array of initialization data. Its length must be nThreads, * or it should be NULL. * @return true if initialization was successful. */ bool CPLWorkerThreadPool::Setup(int nThreads, CPLThreadFunc pfnInitFunc, void** pasInitData) { CPLAssert( nThreads > 0 ); hCond = CPLCreateCond(); if( hCond == nullptr ) return false; bool bRet = true; aWT.resize(nThreads); for(int i=0;i<nThreads;i++) { aWT[i].pfnInitFunc = pfnInitFunc; aWT[i].pInitData = pasInitData ? pasInitData[i] : nullptr; aWT[i].poTP = this; aWT[i].hMutex = CPLCreateMutexEx(CPL_MUTEX_REGULAR); if( aWT[i].hMutex == nullptr ) { nThreads = i; aWT.resize(nThreads); bRet = false; break; } CPLReleaseMutex(aWT[i].hMutex); aWT[i].hCond = CPLCreateCond(); if( aWT[i].hCond == nullptr ) { CPLDestroyMutex(aWT[i].hMutex); nThreads = i; aWT.resize(nThreads); bRet = false; break; } aWT[i].bMarkedAsWaiting = FALSE; // aWT[i].psNextJob = nullptr; aWT[i].hThread = CPLCreateJoinableThread(WorkerThreadFunction, &(aWT[i])); if( aWT[i].hThread == nullptr ) { nThreads = i; aWT.resize(nThreads); bRet = false; break; } } // Wait all threads to be started while( true ) { CPLAcquireMutex(hMutex, 1000.0); int nWaitingWorkerThreadsLocal = nWaitingWorkerThreads; if( nWaitingWorkerThreadsLocal < nThreads ) CPLCondWait(hCond, hMutex); CPLReleaseMutex(hMutex); if( nWaitingWorkerThreadsLocal == nThreads ) break; } if( eState == CPLWTS_ERROR ) bRet = false; return bRet; }
void VSICurlStreamingHandle::AcquireMutex() { CPLAcquireMutex(hRingBufferMutex, 1000.0); }
/** Transform an array of points * * @param nCount Number of points * @param x Array of nCount x values. * @param y Array of nCount y values. * @param z Array of nCount z values. * @param pabSuccess Output array of nCount value that will be set to TRUE/FALSE * @return TRUE or FALSE */ int OGRProj4CT::TransformEx( int nCount, double *x, double *y, double *z, int *pabSuccess ) { int err; /* -------------------------------------------------------------------- */ /* Potentially transform to radians. */ /* -------------------------------------------------------------------- */ if( bSourceLatLong ) { if( bSourceWrap ) { for( int i = 0; i < nCount; i++ ) { if( x[i] != HUGE_VAL && y[i] != HUGE_VAL ) { if( x[i] < dfSourceWrapLong - 180.0 ) x[i] += 360.0; else if( x[i] > dfSourceWrapLong + 180 ) x[i] -= 360.0; } } } for( int i = 0; i < nCount; i++ ) { if( x[i] != HUGE_VAL ) { x[i] *= dfSourceToRadians; y[i] *= dfSourceToRadians; } } } /* -------------------------------------------------------------------- */ /* Optimized transform from WebMercator to WGS84 */ /* -------------------------------------------------------------------- */ bool bTransformDone = false; if( bWebMercatorToWGS84 ) { #define REVERSE_SPHERE_RADIUS (1. / 6378137.) double y0 = y[0]; for( int i = 0; i < nCount; i++ ) { if( x[i] != HUGE_VAL ) { x[i] = x[i] * REVERSE_SPHERE_RADIUS; if( x[i] > M_PI ) { if( x[i] < M_PI+1e-14 ) x[i] = M_PI; else if( bCheckWithInvertProj ) { x[i] = y[i] = HUGE_VAL; y0 = HUGE_VAL; continue; } else { do { x[i] -= 2 * M_PI; } while ( x[i] > M_PI ); } } else if( x[i] < -M_PI ) { if( x[i] > -M_PI-1e-14 ) x[i] = -M_PI; else if( bCheckWithInvertProj ) { x[i] = y[i] = HUGE_VAL; y0 = HUGE_VAL; continue; } else { do { x[i] += 2 * M_PI; } while( x[i] < -M_PI ); } } // Optimization for the case where we are provided a whole line of same northing if( i > 0 && y[i] == y0 ) y[i] = y[0]; else y[i] = M_PI / 2 - 2. * atan(exp(-y[i] * REVERSE_SPHERE_RADIUS)); } } bTransformDone = true; } else if( bIdentityTransform ) { bTransformDone = true; } /* -------------------------------------------------------------------- */ /* Do the transformation (or not...) using PROJ.4. */ /* -------------------------------------------------------------------- */ if( !bTransformDone && pjctx == NULL ) { /* The mutex has already been created */ CPLAssert(hPROJMutex != NULL); CPLAcquireMutex(hPROJMutex, 1000.0); } if( bTransformDone ) err = 0; else if( bCheckWithInvertProj ) { // For some projections, we cannot detect if we are trying to reproject // coordinates outside the validity area of the projection. So let's do // the reverse reprojection and compare with the source coordinates. if (nCount > nMaxCount) { nMaxCount = nCount; padfOriX = (double*) CPLRealloc(padfOriX, sizeof(double)*nCount); padfOriY = (double*) CPLRealloc(padfOriY, sizeof(double)*nCount); padfOriZ = (double*) CPLRealloc(padfOriZ, sizeof(double)*nCount); padfTargetX = (double*) CPLRealloc(padfTargetX, sizeof(double)*nCount); padfTargetY = (double*) CPLRealloc(padfTargetY, sizeof(double)*nCount); padfTargetZ = (double*) CPLRealloc(padfTargetZ, sizeof(double)*nCount); } memcpy(padfOriX, x, sizeof(double)*nCount); memcpy(padfOriY, y, sizeof(double)*nCount); if (z) { memcpy(padfOriZ, z, sizeof(double)*nCount); } err = pfn_pj_transform( psPJSource, psPJTarget, nCount, 1, x, y, z ); if (err == 0) { memcpy(padfTargetX, x, sizeof(double)*nCount); memcpy(padfTargetY, y, sizeof(double)*nCount); if (z) { memcpy(padfTargetZ, z, sizeof(double)*nCount); } err = pfn_pj_transform( psPJTarget, psPJSource , nCount, 1, padfTargetX, padfTargetY, (z) ? padfTargetZ : NULL); if (err == 0) { for( int i = 0; i < nCount; i++ ) { if ( x[i] != HUGE_VAL && y[i] != HUGE_VAL && (fabs(padfTargetX[i] - padfOriX[i]) > dfThreshold || fabs(padfTargetY[i] - padfOriY[i]) > dfThreshold) ) { x[i] = HUGE_VAL; y[i] = HUGE_VAL; } } } } } else { err = pfn_pj_transform( psPJSource, psPJTarget, nCount, 1, x, y, z ); } /* -------------------------------------------------------------------- */ /* Try to report an error through CPL. Get proj.4 error string */ /* if possible. Try to avoid reporting thousands of error */ /* ... suppress further error reporting on this OGRProj4CT if we */ /* have already reported 20 errors. */ /* -------------------------------------------------------------------- */ if( err != 0 ) { if( pabSuccess ) memset( pabSuccess, 0, sizeof(int) * nCount ); if( ++nErrorCount < 20 ) { if (pjctx != NULL) /* pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0 */ CPLAcquireMutex(hPROJMutex, 1000.0); const char *pszError = NULL; if( pfn_pj_strerrno != NULL ) pszError = pfn_pj_strerrno( err ); if( pszError == NULL ) CPLError( CE_Failure, CPLE_AppDefined, "Reprojection failed, err = %d", err ); else CPLError( CE_Failure, CPLE_AppDefined, "%s", pszError ); if (pjctx != NULL) /* pfn_pj_strerrno not yet thread-safe in PROJ 4.8.0 */ CPLReleaseMutex(hPROJMutex); } else if( nErrorCount == 20 ) { CPLError( CE_Failure, CPLE_AppDefined, "Reprojection failed, err = %d, further errors will be suppressed on the transform object.", err ); } if (pjctx == NULL) CPLReleaseMutex(hPROJMutex); return FALSE; } if( !bTransformDone && pjctx == NULL ) CPLReleaseMutex(hPROJMutex); /* -------------------------------------------------------------------- */ /* Potentially transform back to degrees. */ /* -------------------------------------------------------------------- */ if( bTargetLatLong ) { for( int i = 0; i < nCount; i++ ) { if( x[i] != HUGE_VAL && y[i] != HUGE_VAL ) { x[i] *= dfTargetFromRadians; y[i] *= dfTargetFromRadians; } } if( bTargetWrap ) { for( int i = 0; i < nCount; i++ ) { if( x[i] != HUGE_VAL && y[i] != HUGE_VAL ) { if( x[i] < dfTargetWrapLong - 180.0 ) x[i] += 360.0; else if( x[i] > dfTargetWrapLong + 180 ) x[i] -= 360.0; } } } } /* -------------------------------------------------------------------- */ /* Establish error information if pabSuccess provided. */ /* -------------------------------------------------------------------- */ if( pabSuccess ) { for( int i = 0; i < nCount; i++ ) { if( x[i] == HUGE_VAL || y[i] == HUGE_VAL ) pabSuccess[i] = FALSE; else pabSuccess[i] = TRUE; } } return TRUE; }
GDALDataset *GMTDataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Does this file have the GMT magic number? */ /* -------------------------------------------------------------------- */ if( poOpenInfo->fpL == NULL || poOpenInfo->nHeaderBytes < 50 ) return NULL; if( poOpenInfo->pabyHeader[0] != 'C' || poOpenInfo->pabyHeader[1] != 'D' || poOpenInfo->pabyHeader[2] != 'F' || poOpenInfo->pabyHeader[3] != 1 ) return NULL; CPLMutexHolderD(&hNCMutex); /* -------------------------------------------------------------------- */ /* Try opening the dataset. */ /* -------------------------------------------------------------------- */ int cdfid, nm_id, dim_count, z_id; if( nc_open( poOpenInfo->pszFilename, NC_NOWRITE, &cdfid ) != NC_NOERR ) return NULL; if( nc_inq_varid( cdfid, "dimension", &nm_id ) != NC_NOERR || nc_inq_varid( cdfid, "z", &z_id ) != NC_NOERR ) { #ifdef notdef CPLError( CE_Warning, CPLE_AppDefined, "%s is a GMT file, but not in GMT configuration.", poOpenInfo->pszFilename ); #endif nc_close( cdfid ); return NULL; } if( nc_inq_ndims( cdfid, &dim_count ) != NC_NOERR || dim_count < 2 ) { nc_close( cdfid ); return NULL; } /* -------------------------------------------------------------------- */ /* Confirm the requested access is supported. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) { nc_close( cdfid ); CPLError( CE_Failure, CPLE_NotSupported, "The GMT driver does not support update access to existing" " datasets.\n" ); return NULL; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ GMTDataset *poDS; CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex poDS = new GMTDataset(); CPLAcquireMutex(hNCMutex, 1000.0); poDS->cdfid = cdfid; poDS->z_id = z_id; /* -------------------------------------------------------------------- */ /* Get dimensions. If we can't find this, then this is a */ /* GMT file, but not a normal grid product. */ /* -------------------------------------------------------------------- */ size_t start[2], edge[2]; int nm[2]; start[0] = 0; edge[0] = 2; nc_get_vara_int(cdfid, nm_id, start, edge, nm); poDS->nRasterXSize = nm[0]; poDS->nRasterYSize = nm[1]; /* -------------------------------------------------------------------- */ /* Fetch "z" attributes scale_factor, add_offset, and */ /* node_offset. */ /* -------------------------------------------------------------------- */ double scale_factor=1.0, add_offset=0.0; int node_offset = 1; nc_get_att_double( cdfid, z_id, "scale_factor", &scale_factor ); nc_get_att_double( cdfid, z_id, "add_offset", &add_offset ); nc_get_att_int( cdfid, z_id, "node_offset", &node_offset ); /* -------------------------------------------------------------------- */ /* Get x/y range information. */ /* -------------------------------------------------------------------- */ int x_range_id, y_range_id; if( nc_inq_varid (cdfid, "x_range", &x_range_id) == NC_NOERR && nc_inq_varid (cdfid, "y_range", &y_range_id) == NC_NOERR ) { double x_range[2], y_range[2]; nc_get_vara_double( cdfid, x_range_id, start, edge, x_range ); nc_get_vara_double( cdfid, y_range_id, start, edge, y_range ); // Pixel is area if( node_offset == 1 ) { poDS->adfGeoTransform[0] = x_range[0]; poDS->adfGeoTransform[1] = (x_range[1] - x_range[0]) / poDS->nRasterXSize; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = y_range[1]; poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = (y_range[0] - y_range[1]) / poDS->nRasterYSize; } // Pixel is point - offset by half pixel. else /* node_offset == 0 */ { poDS->adfGeoTransform[1] = (x_range[1] - x_range[0]) / (poDS->nRasterXSize-1); poDS->adfGeoTransform[0] = x_range[0] - poDS->adfGeoTransform[1]*0.5; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = (y_range[0] - y_range[1]) / (poDS->nRasterYSize-1); poDS->adfGeoTransform[3] = y_range[1] - poDS->adfGeoTransform[5]*0.5; } } else { poDS->adfGeoTransform[0] = 0.0; poDS->adfGeoTransform[1] = 1.0; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = 0.0; poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = 1.0; } /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ poDS->nBands = 1; poDS->SetBand( 1, new GMTRasterBand( poDS, z_id, 1 )); if( scale_factor != 1.0 || add_offset != 0.0 ) { poDS->GetRasterBand(1)->SetOffset( add_offset ); poDS->GetRasterBand(1)->SetScale( scale_factor ); } /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); CPLReleaseMutex(hNCMutex); // Release mutex otherwise we'll deadlock with GDALDataset own mutex poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for external overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() ); CPLAcquireMutex(hNCMutex, 1000.0); return( poDS ); }
GDALAsyncStatusType ECWAsyncReader::GetNextUpdatedRegion( double dfTimeout, int* pnXBufOff, int* pnYBufOff, int* pnXBufSize, int* pnYBufSize ) { CPLDebug( "ECW", "GetNextUpdatedRegion()" ); /* -------------------------------------------------------------------- */ /* We always mark the whole raster as updated since the ECW SDK */ /* does not have a concept of partial update notifications. */ /* -------------------------------------------------------------------- */ *pnXBufOff = 0; *pnYBufOff = 0; *pnXBufSize = nBufXSize; *pnYBufSize = nBufYSize; if( bComplete && !bUpdateReady ) { CPLDebug( "ECW", "return GARIO_COMPLETE" ); return GARIO_COMPLETE; } /* -------------------------------------------------------------------- */ /* Wait till our timeout, or until we are notified there is */ /* data ready. We are trusting the CPLSleep() to be pretty */ /* accurate instead of keeping track of time elapsed ourselves */ /* - this is not necessarily a good approach. */ /* -------------------------------------------------------------------- */ if( dfTimeout < 0.0 ) dfTimeout = 100000.0; while( !bUpdateReady && dfTimeout > 0.0 ) { CPLSleep( MIN(0.1, dfTimeout) ); dfTimeout -= 0.1; CPLDebug( "ECW", "wait..." ); } if( !bUpdateReady ) { CPLDebug( "ECW", "return GARIO_PENDING" ); return GARIO_PENDING; } bUpdateReady = FALSE; /* -------------------------------------------------------------------- */ /* Acquire Mutex */ /* -------------------------------------------------------------------- */ if( !CPLAcquireMutex( hMutex, dfTimeout ) ) { CPLDebug( "ECW", "return GARIO_PENDING" ); return GARIO_PENDING; } /* -------------------------------------------------------------------- */ /* Actually decode the imagery into our buffer. */ /* -------------------------------------------------------------------- */ NCSEcwReadStatus eRStatus = ReadToBuffer(); if( eRStatus != NCSECW_READ_OK ) { CPLReleaseMutex( hMutex ); return GARIO_ERROR; } /* -------------------------------------------------------------------- */ /* Return indication of complete or just buffer updateded. */ /* -------------------------------------------------------------------- */ if( bComplete && !bUpdateReady ) { CPLReleaseMutex( hMutex ); CPLDebug( "ECW", "return GARIO_COMPLETE" ); return GARIO_COMPLETE; } else { CPLReleaseMutex( hMutex ); CPLDebug( "ECW", "return GARIO_UPDATE" ); return GARIO_UPDATE; } }
/** Queue several jobs * * @param pfnFunc Function to run for the job. * @param apData User data instances to pass to the job function. * @return true in case of success. */ bool CPLWorkerThreadPool::SubmitJobs(CPLThreadFunc pfnFunc, const std::vector<void*>& apData) { CPLAssert( !aWT.empty() ); CPLAcquireMutex(hMutex, 1000.0); CPLList* psJobQueueInit = psJobQueue; bool bRet = true; for(size_t i=0;i<apData.size();i++) { CPLWorkerThreadJob* psJob = static_cast<CPLWorkerThreadJob*>( VSI_MALLOC_VERBOSE(sizeof(CPLWorkerThreadJob))); if( psJob == nullptr ) { bRet = false; break; } psJob->pfnFunc = pfnFunc; psJob->pData = apData[i]; CPLList* psItem = static_cast<CPLList *>(VSI_MALLOC_VERBOSE(sizeof(CPLList))); if( psItem == nullptr ) { VSIFree(psJob); bRet = false; break; } psItem->pData = psJob; psItem->psNext = psJobQueue; psJobQueue = psItem; nPendingJobs++; } if( !bRet ) { for( CPLList* psIter = psJobQueue; psIter != psJobQueueInit; ) { CPLList* psNext = psIter->psNext; VSIFree(psIter->pData); VSIFree(psIter); nPendingJobs--; psIter = psNext; } } CPLReleaseMutex(hMutex); if( !bRet ) return false; for(size_t i=0;i<apData.size();i++) { CPLAcquireMutex(hMutex, 1000.0); if( psWaitingWorkerThreadsList && psJobQueue ) { CPLWorkerThread* psWorkerThread; psWorkerThread = static_cast<CPLWorkerThread*>(psWaitingWorkerThreadsList->pData); CPLAssert( psWorkerThread->bMarkedAsWaiting ); psWorkerThread->bMarkedAsWaiting = FALSE; CPLList* psNext = psWaitingWorkerThreadsList->psNext; CPLList* psToFree = psWaitingWorkerThreadsList; psWaitingWorkerThreadsList = psNext; nWaitingWorkerThreads--; // CPLAssert( // CPLListCount(psWaitingWorkerThreadsList) == // nWaitingWorkerThreads); #if DEBUG_VERBOSE CPLDebug("JOB", "Waking up %p", psWorkerThread); #endif CPLAcquireMutex(psWorkerThread->hMutex, 1000.0); // CPLAssert(psWorkerThread->psNextJob == nullptr); // psWorkerThread->psNextJob = // (CPLWorkerThreadJob*)psJobQueue->pData; // psNext = psJobQueue->psNext; // CPLFree(psJobQueue); // psJobQueue = psNext; CPLReleaseMutex(hMutex); CPLCondSignal(psWorkerThread->hCond); CPLReleaseMutex(psWorkerThread->hMutex); CPLFree(psToFree); } else { CPLReleaseMutex(hMutex); break; } } return true; }