1 /********************************************************************** 2 * $Id: cpl_multiproc.h 5bf28e3bebd1032c4c8f50564d077f95cdf897d3 2020-09-30 14:07:46 +0200 Even Rouault $ 3 * 4 * Project: CPL - Common Portability Library 5 * Purpose: CPL Multi-Threading, and process handling portability functions. 6 * Author: Frank Warmerdam, warmerdam@pobox.com 7 * 8 ********************************************************************** 9 * Copyright (c) 2002, Frank Warmerdam 10 * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com> 11 * 12 * Permission is hereby granted, free of charge, to any person obtaining a 13 * copy of this software and associated documentation files (the "Software"), 14 * to deal in the Software without restriction, including without limitation 15 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 16 * and/or sell copies of the Software, and to permit persons to whom the 17 * Software is furnished to do so, subject to the following conditions: 18 * 19 * The above copyright notice and this permission notice shall be included 20 * in all copies or substantial portions of the Software. 21 * 22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 25 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 * DEALINGS IN THE SOFTWARE. 29 ****************************************************************************/ 30 31 #ifndef CPL_MULTIPROC_H_INCLUDED_ 32 #define CPL_MULTIPROC_H_INCLUDED_ 33 34 #include "cpl_port.h" 35 36 /* 37 ** There are three primary implementations of the multi-process support 38 ** controlled by one of CPL_MULTIPROC_WIN32, CPL_MULTIPROC_PTHREAD or 39 ** CPL_MULTIPROC_STUB being defined. If none are defined, the stub 40 ** implementation will be used. 41 */ 42 43 #if defined(WIN32) && !defined(CPL_MULTIPROC_STUB) 44 # define CPL_MULTIPROC_WIN32 45 /* MinGW can have pthread support, so disable it to avoid issues */ 46 /* in cpl_multiproc.cpp */ 47 # undef CPL_MULTIPROC_PTHREAD 48 #endif 49 50 #if !defined(CPL_MULTIPROC_WIN32) && !defined(CPL_MULTIPROC_PTHREAD) \ 51 && !defined(CPL_MULTIPROC_STUB) && !defined(CPL_MULTIPROC_NONE) 52 # define CPL_MULTIPROC_STUB 53 #endif 54 55 CPL_C_START 56 57 typedef void (*CPLThreadFunc)(void *); 58 59 void CPL_DLL *CPLLockFile( const char *pszPath, double dfWaitInSeconds ); 60 void CPL_DLL CPLUnlockFile( void *hLock ); 61 62 #ifdef DEBUG 63 typedef struct _CPLMutex CPLMutex; 64 typedef struct _CPLCond CPLCond; 65 typedef struct _CPLJoinableThread CPLJoinableThread; 66 #else 67 #define CPLMutex void 68 #define CPLCond void 69 #define CPLJoinableThread void 70 #endif 71 72 /* Options for CPLCreateMutexEx() and CPLCreateOrAcquireMutexEx() */ 73 #define CPL_MUTEX_RECURSIVE 0 74 #define CPL_MUTEX_ADAPTIVE 1 75 #define CPL_MUTEX_REGULAR 2 76 77 CPLMutex CPL_DLL *CPLCreateMutex( void ); /* returned acquired */ 78 CPLMutex CPL_DLL *CPLCreateMutexEx( int nOptions ); /* returned acquired */ 79 int CPL_DLL CPLCreateOrAcquireMutex( CPLMutex **, double dfWaitInSeconds ); 80 int CPL_DLL CPLCreateOrAcquireMutexEx( CPLMutex **, double dfWaitInSeconds, int nOptions ); 81 int CPL_DLL CPLAcquireMutex( CPLMutex *hMutex, double dfWaitInSeconds ); 82 void CPL_DLL CPLReleaseMutex( CPLMutex *hMutex ); 83 void CPL_DLL CPLDestroyMutex( CPLMutex *hMutex ); 84 void CPL_DLL CPLCleanupMasterMutex( void ); 85 86 CPLCond CPL_DLL *CPLCreateCond( void ); 87 void CPL_DLL CPLCondWait( CPLCond *hCond, CPLMutex* hMutex ); 88 typedef enum 89 { 90 COND_TIMED_WAIT_COND, 91 COND_TIMED_WAIT_TIME_OUT, 92 COND_TIMED_WAIT_OTHER 93 } CPLCondTimedWaitReason; 94 CPLCondTimedWaitReason CPL_DLL CPLCondTimedWait( CPLCond *hCond, CPLMutex* hMutex, double dfWaitInSeconds ); 95 void CPL_DLL CPLCondSignal( CPLCond *hCond ); 96 void CPL_DLL CPLCondBroadcast( CPLCond *hCond ); 97 void CPL_DLL CPLDestroyCond( CPLCond *hCond ); 98 99 /** Contrary to what its name suggests, CPLGetPID() actually returns the thread id */ 100 GIntBig CPL_DLL CPLGetPID( void ); 101 int CPL_DLL CPLGetCurrentProcessID( void ); 102 int CPL_DLL CPLCreateThread( CPLThreadFunc pfnMain, void *pArg ); 103 CPLJoinableThread CPL_DLL* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pArg ); 104 void CPL_DLL CPLJoinThread(CPLJoinableThread* hJoinableThread); 105 void CPL_DLL CPLSleep( double dfWaitInSeconds ); 106 107 const char CPL_DLL *CPLGetThreadingModel( void ); 108 109 int CPL_DLL CPLGetNumCPUs( void ); 110 111 typedef struct _CPLLock CPLLock; 112 113 /* Currently LOCK_ADAPTIVE_MUTEX is Linux-only and LOCK_SPIN only available */ 114 /* on systems with pthread_spinlock API (so not MacOsX). If a requested type */ 115 /* isn't available, it fallbacks to LOCK_RECURSIVE_MUTEX */ 116 typedef enum 117 { 118 LOCK_RECURSIVE_MUTEX, 119 LOCK_ADAPTIVE_MUTEX, 120 LOCK_SPIN 121 } CPLLockType; 122 123 CPLLock CPL_DLL *CPLCreateLock( CPLLockType eType ); /* returned NON acquired */ 124 int CPL_DLL CPLCreateOrAcquireLock( CPLLock**, CPLLockType eType ); 125 int CPL_DLL CPLAcquireLock( CPLLock* ); 126 void CPL_DLL CPLReleaseLock( CPLLock* ); 127 void CPL_DLL CPLDestroyLock( CPLLock* ); 128 void CPL_DLL CPLLockSetDebugPerf( CPLLock*, int bEnableIn ); /* only available on x86/x86_64 with GCC for now */ 129 130 CPL_C_END 131 132 #if defined(__cplusplus) && !defined(CPL_SUPRESS_CPLUSPLUS) 133 134 /* Instantiates the mutex if not already done. The parameter x should be a (void**). */ 135 #define CPLMutexHolderD(x) CPLMutexHolder oHolder(x,1000.0,__FILE__,__LINE__); 136 137 /* Instantiates the mutex with options if not already done. */ 138 /* The parameter x should be a (void**). */ 139 #define CPLMutexHolderExD(x, nOptions) CPLMutexHolder oHolder(x,1000.0,__FILE__,__LINE__,nOptions); 140 141 /* This variant assumes the mutex has already been created. If not, it will */ 142 /* be a no-op. The parameter x should be a (void*) */ 143 #define CPLMutexHolderOptionalLockD(x) CPLMutexHolder oHolder(x,1000.0,__FILE__,__LINE__); 144 145 /** Object to hold a mutex */ 146 class CPL_DLL CPLMutexHolder 147 { 148 private: 149 CPLMutex *hMutex = nullptr; 150 // Only used for debugging. 151 const char *pszFile = nullptr; 152 int nLine = 0; 153 154 CPL_DISALLOW_COPY_ASSIGN(CPLMutexHolder) 155 156 public: 157 158 /** Instantiates the mutex if not already done. */ 159 explicit CPLMutexHolder( CPLMutex **phMutex, double dfWaitInSeconds = 1000.0, 160 const char *pszFile = __FILE__, 161 int nLine = __LINE__, 162 int nOptions = CPL_MUTEX_RECURSIVE); 163 164 /** This variant assumes the mutex has already been created. If not, it will 165 * be a no-op */ 166 explicit CPLMutexHolder( CPLMutex* hMutex, double dfWaitInSeconds = 1000.0, 167 const char *pszFile = __FILE__, 168 int nLine = __LINE__ ); 169 170 ~CPLMutexHolder(); 171 }; 172 173 /* Instantiates the lock if not already done. The parameter x should be a (CPLLock**). */ 174 #define CPLLockHolderD(x, eType) CPLLockHolder oHolder(x,eType,__FILE__,__LINE__); 175 176 /* This variant assumes the lock has already been created. If not, it will */ 177 /* be a no-op. The parameter should be (CPLLock*) */ 178 #define CPLLockHolderOptionalLockD(x) CPLLockHolder oHolder(x,__FILE__,__LINE__); 179 180 /** Object to hold a lock */ 181 class CPL_DLL CPLLockHolder 182 { 183 private: 184 CPLLock *hLock = nullptr; 185 const char *pszFile = nullptr; 186 int nLine = 0; 187 188 CPL_DISALLOW_COPY_ASSIGN(CPLLockHolder) 189 190 public: 191 192 /** Instantiates the lock if not already done. */ 193 CPLLockHolder( CPLLock **phSpin, CPLLockType eType, 194 const char *pszFile = __FILE__, 195 int nLine = __LINE__); 196 197 /** This variant assumes the lock has already been created. If not, it will 198 * be a no-op */ 199 explicit CPLLockHolder( CPLLock* hSpin, 200 const char *pszFile = __FILE__, 201 int nLine = __LINE__ ); 202 203 ~CPLLockHolder(); 204 }; 205 206 #endif /* def __cplusplus */ 207 208 /* -------------------------------------------------------------------- */ 209 /* Thread local storage. */ 210 /* -------------------------------------------------------------------- */ 211 212 #define CTLS_RLBUFFERINFO 1 /* cpl_conv.cpp */ 213 #define CTLS_WIN32_COND 2 /* cpl_multiproc.cpp */ 214 #define CTLS_CSVTABLEPTR 3 /* cpl_csv.cpp */ 215 #define CTLS_CSVDEFAULTFILENAME 4 /* cpl_csv.cpp */ 216 #define CTLS_ERRORCONTEXT 5 /* cpl_error.cpp */ 217 #define CTLS_VSICURL_CACHEDCONNECTION 6 /* cpl_vsil_curl.cpp */ 218 #define CTLS_PATHBUF 7 /* cpl_path.cpp */ 219 #define CTLS_ABSTRACTARCHIVE_SPLIT 8 /* cpl_vsil_abstract_archive.cpp */ 220 #define CTLS_GDALOPEN_ANTIRECURSION 9 /* gdaldataset.cpp */ 221 #define CTLS_CPLSPRINTF 10 /* cpl_string.h */ 222 #define CTLS_RESPONSIBLEPID 11 /* gdaldataset.cpp */ 223 #define CTLS_VERSIONINFO 12 /* gdal_misc.cpp */ 224 #define CTLS_VERSIONINFO_LICENCE 13 /* gdal_misc.cpp */ 225 #define CTLS_CONFIGOPTIONS 14 /* cpl_conv.cpp */ 226 #define CTLS_FINDFILE 15 /* cpl_findfile.cpp */ 227 #define CTLS_VSIERRORCONTEXT 16 /* cpl_vsi_error.cpp */ 228 #define CTLS_ERRORHANDLERACTIVEDATA 17 /* cpl_error.cpp */ 229 #define CTLS_PROJCONTEXTHOLDER 18 /* ogr_proj_p.cpp */ 230 #define CTLS_GDALDEFAULTOVR_ANTIREC 19 /* gdaldefaultoverviews.cpp */ 231 #define CTLS_HTTPFETCHCALLBACK 20 /* cpl_http.cpp */ 232 233 #define CTLS_MAX 32 234 235 CPL_C_START 236 void CPL_DLL * CPLGetTLS( int nIndex ); 237 void CPL_DLL * CPLGetTLSEx( int nIndex, int* pbMemoryErrorOccurred ); 238 void CPL_DLL CPLSetTLS( int nIndex, void *pData, int bFreeOnExit ); 239 240 /* Warning : the CPLTLSFreeFunc must not in any case directly or indirectly */ 241 /* use or fetch any TLS data, or a terminating thread will hang ! */ 242 typedef void (*CPLTLSFreeFunc)( void* pData ); 243 void CPL_DLL CPLSetTLSWithFreeFunc( int nIndex, void *pData, CPLTLSFreeFunc pfnFree ); 244 void CPL_DLL CPLSetTLSWithFreeFuncEx( int nIndex, void *pData, CPLTLSFreeFunc pfnFree, int* pbMemoryErrorOccurred ); 245 246 void CPL_DLL CPLCleanupTLS( void ); 247 CPL_C_END 248 249 #endif /* CPL_MULTIPROC_H_INCLUDED_ */ 250