📄 cpl_multiproc.cpp
字号:
/************************************************************************/
/* CPLDestroyMutex() */
/************************************************************************/
void CPLDestroyMutex( void *hMutexIn )
{
HANDLE hMutex = (HANDLE) hMutexIn;
CloseHandle( hMutex );
}
/************************************************************************/
/* CPLLockFile() */
/************************************************************************/
void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
{
char *pszLockFilename;
HANDLE hLockFile;
pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
sprintf( pszLockFilename, "%s.lock", pszPath );
hLockFile =
CreateFile( pszLockFilename, GENERIC_WRITE, 0, NULL,CREATE_NEW,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL );
while( GetLastError() == ERROR_ALREADY_EXISTS
&& dfWaitInSeconds > 0.0 )
{
CloseHandle( hLockFile );
CPLSleep( MIN(dfWaitInSeconds,0.125) );
dfWaitInSeconds -= 0.125;
hLockFile =
CreateFile( pszLockFilename, GENERIC_WRITE, 0, NULL, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE,
NULL );
}
CPLFree( pszLockFilename );
if( hLockFile == INVALID_HANDLE_VALUE )
return NULL;
if( GetLastError() == ERROR_ALREADY_EXISTS )
{
CloseHandle( hLockFile );
return NULL;
}
return (void *) hLockFile;
}
/************************************************************************/
/* CPLUnlockFile() */
/************************************************************************/
void CPLUnlockFile( void *hLock )
{
HANDLE hLockFile = (HANDLE) hLock;
CloseHandle( hLockFile );
}
/************************************************************************/
/* CPLGetPID() */
/************************************************************************/
int CPLGetPID()
{
return GetCurrentThreadId();
}
/************************************************************************/
/* CPLStdCallThreadJacket() */
/************************************************************************/
typedef struct {
void *pAppData;
CPLThreadFunc pfnMain;
} CPLStdCallThreadInfo;
static DWORD WINAPI CPLStdCallThreadJacket( void *pData )
{
CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) pData;
psInfo->pfnMain( psInfo->pAppData );
CPLFree( psInfo );
return 0;
}
/************************************************************************/
/* CPLCreateThread() */
/* */
/* The WIN32 CreateThread() call requires an entry point that */
/* has __stdcall conventions, so we provide a jacket function */
/* to supply that. */
/************************************************************************/
int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
{
HANDLE hThread;
DWORD nThreadId;
CPLStdCallThreadInfo *psInfo;
psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
psInfo->pAppData = pThreadArg;
psInfo->pfnMain = pfnMain;
hThread = CreateThread( NULL, 0, CPLStdCallThreadJacket, psInfo,
0, &nThreadId );
if( hThread == NULL )
return -1;
CloseHandle( hThread );
return nThreadId;
}
/************************************************************************/
/* CPLSleep() */
/************************************************************************/
void CPLSleep( double dfWaitInSeconds )
{
Sleep( (DWORD) (dfWaitInSeconds * 1000.0) );
}
static int bTLSKeySetup = FALSE;
static DWORD nTLSKey;
/************************************************************************/
/* CPLGetTLSList() */
/************************************************************************/
static void **CPLGetTLSList()
{
void **papTLSList;
if( !bTLSKeySetup )
{
nTLSKey = TlsAlloc();
if( nTLSKey == TLS_OUT_OF_INDEXES )
{
CPLError( CE_Fatal, CPLE_AppDefined,
"TlsAlloc() failed!" );
}
bTLSKeySetup = TRUE;
}
papTLSList = (void **) TlsGetValue( nTLSKey );
if( papTLSList == NULL )
{
papTLSList = (void **) CPLCalloc(sizeof(void*),CTLS_MAX*2);
if( TlsSetValue( nTLSKey, papTLSList ) == 0 )
{
CPLError( CE_Fatal, CPLE_AppDefined,
"TlsSetValue() failed!" );
}
}
return papTLSList;
}
/************************************************************************/
/* CPLCleanupTLS() */
/************************************************************************/
void CPLCleanupTLS()
{
void **papTLSList;
if( !bTLSKeySetup )
return;
papTLSList = (void **) TlsGetValue( nTLSKey );
if( papTLSList == NULL )
return;
TlsSetValue( nTLSKey, NULL );
CPLCleanupTLSList( papTLSList );
}
#endif /* def CPL_MULTIPROC_WIN32 */
#ifdef CPL_MULTIPROC_PTHREAD
#include <pthread.h>
#include <time.h>
/************************************************************************/
/* ==================================================================== */
/* CPL_MULTIPROC_PTHREAD */
/* */
/* PTHREAD Implementation of multiprocessing functions. */
/* ==================================================================== */
/************************************************************************/
/************************************************************************/
/* CPLGetThreadingModel() */
/************************************************************************/
const char *CPLGetThreadingModel()
{
return "pthread";
}
/************************************************************************/
/* CPLCreateMutex() */
/************************************************************************/
void *CPLCreateMutex()
{
pthread_mutex_t *hMutex;
hMutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
#if defined(PTHREAD_MUTEX_RECURSIVE)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init( &attr );
pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
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;
}
/************************************************************************/
/* CPLAcquireMutex() */
/************************************************************************/
int CPLAcquireMutex( void *hMutexIn, double dfWaitInSeconds )
{
int err;
/* we need to add timeout support */
err = pthread_mutex_lock( (pthread_mutex_t *) hMutexIn );
if( err != 0 )
{
if( err == EDEADLK )
CPLDebug( "CPLAcquireMutex", "Error = %d/EDEADLK", err );
else
CPLDebug( "CPLAcquireMutex", "Error = %d", err );
return FALSE;
}
return TRUE;
}
/************************************************************************/
/* CPLReleaseMutex() */
/************************************************************************/
void CPLReleaseMutex( void *hMutexIn )
{
pthread_mutex_unlock( (pthread_mutex_t *) hMutexIn );
}
/************************************************************************/
/* CPLDestroyMutex() */
/************************************************************************/
void CPLDestroyMutex( void *hMutexIn )
{
pthread_mutex_destroy( (pthread_mutex_t *) hMutexIn );
CPLFree( hMutexIn );
}
/************************************************************************/
/* CPLLockFile() */
/************************************************************************/
void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
{
CPLError( CE_Failure, CPLE_NotSupported,
"PThreads CPLLockFile() not implemented yet." );
return NULL;
}
/************************************************************************/
/* CPLUnlockFile() */
/************************************************************************/
void CPLUnlockFile( void *hLock )
{
}
/************************************************************************/
/* CPLGetPID() */
/************************************************************************/
int CPLGetPID()
{
return (int) pthread_self();
}
/************************************************************************/
/* CPLStdCallThreadJacket() */
/************************************************************************/
typedef struct {
void *pAppData;
CPLThreadFunc pfnMain;
pthread_t hThread;
} CPLStdCallThreadInfo;
static void *CPLStdCallThreadJacket( void *pData )
{
CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) pData;
psInfo->pfnMain( psInfo->pAppData );
CPLFree( psInfo );
return NULL;
}
/************************************************************************/
/* CPLCreateThread() */
/* */
/* The WIN32 CreateThread() call requires an entry point that */
/* has __stdcall conventions, so we provide a jacket function */
/* to supply that. */
/************************************************************************/
int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
{
CPLStdCallThreadInfo *psInfo;
pthread_attr_t hThreadAttr;
psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
psInfo->pAppData = pThreadArg;
psInfo->pfnMain = pfnMain;
pthread_attr_init( &hThreadAttr );
pthread_attr_setdetachstate( &hThreadAttr, PTHREAD_CREATE_DETACHED );
if( pthread_create( &(psInfo->hThread), &hThreadAttr,
CPLStdCallThreadJacket, (void *) psInfo ) != 0 )
{
CPLFree( psInfo );
return -1;
}
return 1; /* can we return the actual thread pid? */
}
/************************************************************************/
/* CPLSleep() */
/************************************************************************/
void CPLSleep( double dfWaitInSeconds )
{
struct timespec sRequest, sRemain;
sRequest.tv_sec = (int) floor(dfWaitInSeconds);
sRequest.tv_nsec = (int) ((dfWaitInSeconds - sRequest.tv_sec)*1000000000);
nanosleep( &sRequest, &sRemain );
}
static int bTLSKeySetup = FALSE;
static pthread_key_t oTLSKey;
/************************************************************************/
/* CPLCleanupTLS() */
/************************************************************************/
void CPLCleanupTLS()
{
void **papTLSList;
if( !bTLSKeySetup )
return;
papTLSList = (void **) pthread_getspecific( oTLSKey );
if( papTLSList == NULL )
return;
pthread_setspecific( oTLSKey, NULL );
CPLCleanupTLSList( papTLSList );
}
/************************************************************************/
/* CPLGetTLSList() */
/************************************************************************/
static void **CPLGetTLSList()
{
void **papTLSList;
if( !bTLSKeySetup )
{
if( pthread_key_create( &oTLSKey,
(void (*)(void*)) CPLCleanupTLSList ) != 0 )
{
CPLError( CE_Fatal, CPLE_AppDefined,
"pthread_key_create() failed!" );
}
bTLSKeySetup = TRUE;
}
papTLSList = (void **) pthread_getspecific( oTLSKey );
if( papTLSList == NULL )
{
papTLSList = (void **) CPLCalloc(sizeof(void*),CTLS_MAX*2);
if( pthread_setspecific( oTLSKey, papTLSList ) != 0 )
{
CPLError( CE_Fatal, CPLE_AppDefined,
"pthread_setspecific() failed!" );
}
}
return papTLSList;
}
#endif /* def CPL_MULTIPROC_PTHREAD */
/************************************************************************/
/* CPLGetTLS() */
/************************************************************************/
void *CPLGetTLS( int nIndex )
{
void** papTLSList = CPLGetTLSList();
CPLAssert( nIndex >= 0 && nIndex < CTLS_MAX );
return papTLSList[nIndex];
}
/************************************************************************/
/* CPLSetTLS() */
/************************************************************************/
void CPLSetTLS( int nIndex, void *pData, int bFreeOnExit )
{
void **papTLSList = CPLGetTLSList();
CPLAssert( nIndex >= 0 && nIndex < CTLS_MAX );
papTLSList[nIndex] = pData;
papTLSList[CTLS_MAX + nIndex] = (void *) bFreeOnExit;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -