LCOV - code coverage report
Current view: directory - port - cpl_multiproc.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 137 112 81.8 %
Date: 2011-12-18 Functions: 23 20 87.0 %

       1                 : /**********************************************************************
       2                 :  * $Id: cpl_multiproc.cpp 22648 2011-07-05 23:14:50Z warmerdam $
       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                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  * 
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  * 
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      22                 :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #ifndef _GNU_SOURCE
      31                 : #define _GNU_SOURCE
      32                 : #endif
      33                 : 
      34                 : #include "cpl_multiproc.h"
      35                 : #include "cpl_conv.h"
      36                 : 
      37                 : #if !defined(WIN32CE)
      38                 : #  include <time.h>
      39                 : #else
      40                 : #  include <wce_time.h>
      41                 : #endif
      42                 : 
      43                 : CPL_CVSID("$Id: cpl_multiproc.cpp 22648 2011-07-05 23:14:50Z warmerdam $");
      44                 : 
      45                 : #if defined(CPL_MULTIPROC_STUB) && !defined(DEBUG)
      46                 : #  define MUTEX_NONE
      47                 : #endif
      48                 : 
      49                 : /************************************************************************/
      50                 : /*                           CPLMutexHolder()                           */
      51                 : /************************************************************************/
      52                 : 
      53        14314782 : CPLMutexHolder::CPLMutexHolder( void **phMutex, double dfWaitInSeconds,
      54                 :                                 const char *pszFileIn, 
      55                 :                                 int nLineIn )
      56                 : 
      57                 : {
      58                 : #ifndef MUTEX_NONE
      59        14314782 :     pszFile = pszFileIn;
      60        14314782 :     nLine = nLineIn;
      61                 : 
      62                 : #ifdef DEBUG_MUTEX
      63                 :     /*
      64                 :      * XXX: There is no way to use CPLDebug() here because it works with
      65                 :      * mutexes itself so we will fall in infinite recursion. Good old
      66                 :      * fprintf() will do the job right.
      67                 :      */
      68                 :     fprintf( stderr,
      69                 :              "CPLMutexHolder: Request %p for pid %ld at %d/%s.\n", 
      70                 :              *phMutex, (long) CPLGetPID(), nLine, pszFile );
      71                 : #endif
      72                 : 
      73        14314782 :     if( !CPLCreateOrAcquireMutex( phMutex, dfWaitInSeconds ) )
      74                 :     {
      75               0 :         fprintf( stderr, "CPLMutexHolder: Failed to acquire mutex!\n" );
      76               0 :         hMutex = NULL;
      77                 :     }
      78                 :     else
      79                 :     {
      80                 : #ifdef DEBUG_MUTEX
      81                 :         fprintf( stderr,
      82                 :                  "CPLMutexHolder: Acquired %p for pid %ld at %d/%s.\n", 
      83                 :                  *phMutex, (long) CPLGetPID(), nLine, pszFile );
      84                 : #endif
      85                 : 
      86        14314782 :         hMutex = *phMutex;
      87                 :     }
      88                 : #endif /* ndef MUTEX_NONE */
      89        14314782 : }
      90                 : 
      91                 : /************************************************************************/
      92                 : /*                          ~CPLMutexHolder()                           */
      93                 : /************************************************************************/
      94                 : 
      95        14314782 : CPLMutexHolder::~CPLMutexHolder()
      96                 : 
      97                 : {
      98                 : #ifndef MUTEX_NONE
      99        14314782 :     if( hMutex != NULL )
     100                 :     {
     101                 : #ifdef DEBUG_MUTEX
     102                 :         fprintf( stderr,
     103                 :                  "~CPLMutexHolder: Release %p for pid %ld at %d/%s.\n", 
     104                 :                  hMutex, (long) CPLGetPID(), nLine, pszFile );
     105                 : #endif
     106        14314782 :         CPLReleaseMutex( hMutex );
     107                 :     }
     108                 : #endif /* ndef MUTEX_NONE */
     109        14314782 : }
     110                 : 
     111                 : 
     112                 : /************************************************************************/
     113                 : /*                      CPLCreateOrAcquireMutex()                       */
     114                 : /************************************************************************/
     115                 : 
     116                 : #ifndef CPL_MULTIPROC_PTHREAD
     117                 : int CPLCreateOrAcquireMutex( void **phMutex, double dfWaitInSeconds )
     118                 : 
     119                 : {
     120                 :     int bSuccess = FALSE;
     121                 : 
     122                 : #ifndef MUTEX_NONE
     123                 :     static void *hCOAMutex = NULL;
     124                 : 
     125                 :     /*
     126                 :     ** ironically, creation of this initial mutex is not threadsafe
     127                 :     ** even though we use it to ensure that creation of other mutexes
     128                 :     ** is threadsafe. 
     129                 :     */
     130                 :     if( hCOAMutex == NULL )
     131                 :     {
     132                 :         hCOAMutex = CPLCreateMutex();
     133                 :         if (hCOAMutex == NULL)
     134                 :         {
     135                 :             *phMutex = NULL;
     136                 :             return FALSE;
     137                 :         }
     138                 :     }
     139                 :     else
     140                 :     {
     141                 :         CPLAcquireMutex( hCOAMutex, dfWaitInSeconds );
     142                 :     }
     143                 : 
     144                 :     if( *phMutex == NULL )
     145                 :     {
     146                 :         *phMutex = CPLCreateMutex();
     147                 :         bSuccess = *phMutex != NULL;
     148                 :         CPLReleaseMutex( hCOAMutex );
     149                 :     }
     150                 :     else
     151                 :     {
     152                 :         CPLReleaseMutex( hCOAMutex );
     153                 : 
     154                 :         bSuccess = CPLAcquireMutex( *phMutex, dfWaitInSeconds );
     155                 :     }
     156                 : #endif /* ndef MUTEX_NONE */
     157                 : 
     158                 :     return bSuccess;
     159                 : }
     160                 : #endif
     161                 : 
     162                 : /************************************************************************/
     163                 : /*                        CPLCleanupTLSList()                           */
     164                 : /*                                                                      */
     165                 : /*      Free resources associated with a TLS vector (implementation     */
     166                 : /*      independent).                                                   */
     167                 : /************************************************************************/
     168                 : 
     169             966 : static void CPLCleanupTLSList( void **papTLSList )
     170                 : 
     171                 : {
     172                 :     int i;
     173                 : 
     174                 : //    printf( "CPLCleanupTLSList(%p)\n", papTLSList );
     175                 :     
     176             966 :     if( papTLSList == NULL )
     177               0 :         return;
     178                 : 
     179           31878 :     for( i = 0; i < CTLS_MAX; i++ )
     180                 :     {
     181           30912 :         if( papTLSList[i] != NULL && papTLSList[i+CTLS_MAX] != NULL )
     182                 :         {
     183            2026 :             CPLTLSFreeFunc pfnFree = (CPLTLSFreeFunc) papTLSList[i + CTLS_MAX];
     184            2026 :             pfnFree( papTLSList[i] );
     185            2026 :             papTLSList[i] = NULL;
     186                 :         }
     187                 :     }
     188                 : 
     189             966 :     CPLFree( papTLSList );
     190                 : }
     191                 : 
     192                 : #if defined(CPL_MULTIPROC_STUB)
     193                 : /************************************************************************/
     194                 : /* ==================================================================== */
     195                 : /*                        CPL_MULTIPROC_STUB                            */
     196                 : /*                                                                      */
     197                 : /*      Stub implementation.  Mutexes don't provide exclusion, file     */
     198                 : /*      locking is achieved with extra "lock files", and thread         */
     199                 : /*      creation doesn't work.  The PID is always just one.             */
     200                 : /* ==================================================================== */
     201                 : /************************************************************************/
     202                 : 
     203                 : /************************************************************************/
     204                 : /*                        CPLGetThreadingModel()                        */
     205                 : /************************************************************************/
     206                 : 
     207                 : const char *CPLGetThreadingModel()
     208                 : 
     209                 : {
     210                 :     return "stub";
     211                 : }
     212                 : 
     213                 : /************************************************************************/
     214                 : /*                           CPLCreateMutex()                           */
     215                 : /************************************************************************/
     216                 : 
     217                 : void *CPLCreateMutex()
     218                 : 
     219                 : {
     220                 : #ifndef MUTEX_NONE
     221                 :     unsigned char *pabyMutex = (unsigned char *) CPLMalloc( 4 );
     222                 : 
     223                 :     pabyMutex[0] = 1;
     224                 :     pabyMutex[1] = 'r';
     225                 :     pabyMutex[2] = 'e';
     226                 :     pabyMutex[3] = 'd';
     227                 : 
     228                 :     return (void *) pabyMutex;
     229                 : #else
     230                 :     return (void *) 0xdeadbeef;
     231                 : #endif 
     232                 : }
     233                 : 
     234                 : /************************************************************************/
     235                 : /*                          CPLAcquireMutex()                           */
     236                 : /************************************************************************/
     237                 : 
     238                 : int CPLAcquireMutex( void *hMutex, double dfWaitInSeconds )
     239                 : 
     240                 : {
     241                 : #ifndef MUTEX_NONE
     242                 :     unsigned char *pabyMutex = (unsigned char *) hMutex;
     243                 : 
     244                 :     CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e' 
     245                 :                && pabyMutex[3] == 'd' );
     246                 : 
     247                 :     pabyMutex[0] += 1;
     248                 : 
     249                 :     return TRUE;
     250                 : #else
     251                 :     return TRUE;
     252                 : #endif
     253                 : }
     254                 : 
     255                 : /************************************************************************/
     256                 : /*                          CPLReleaseMutex()                           */
     257                 : /************************************************************************/
     258                 : 
     259                 : void CPLReleaseMutex( void *hMutex )
     260                 : 
     261                 : {
     262                 : #ifndef MUTEX_NONE
     263                 :     unsigned char *pabyMutex = (unsigned char *) hMutex;
     264                 : 
     265                 :     CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e' 
     266                 :                && pabyMutex[3] == 'd' );
     267                 : 
     268                 :     if( pabyMutex[0] < 1 )
     269                 :         CPLDebug( "CPLMultiProc", 
     270                 :                   "CPLReleaseMutex() called on mutex with %d as ref count!",
     271                 :                   pabyMutex[0] );
     272                 : 
     273                 :     pabyMutex[0] -= 1;
     274                 : #endif
     275                 : }
     276                 : 
     277                 : /************************************************************************/
     278                 : /*                          CPLDestroyMutex()                           */
     279                 : /************************************************************************/
     280                 : 
     281                 : void CPLDestroyMutex( void *hMutex )
     282                 : 
     283                 : {
     284                 : #ifndef MUTEX_NONE
     285                 :     unsigned char *pabyMutex = (unsigned char *) hMutex;
     286                 : 
     287                 :     CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e' 
     288                 :                && pabyMutex[3] == 'd' );
     289                 : 
     290                 :     CPLFree( pabyMutex );
     291                 : #endif
     292                 : }
     293                 : 
     294                 : /************************************************************************/
     295                 : /*                            CPLLockFile()                             */
     296                 : /*                                                                      */
     297                 : /*      Lock a file.  This implementation has a terrible race           */
     298                 : /*      condition.  If we don't succeed in opening the lock file, we    */
     299                 : /*      assume we can create one and own the target file, but other     */
     300                 : /*      processes might easily try creating the target file at the      */
     301                 : /*      same time, overlapping us.  Death!  Mayhem!  The traditional    */
     302                 : /*      solution is to use open() with _O_CREAT|_O_EXCL but this        */
     303                 : /*      function and these arguments aren't trivially portable.         */
     304                 : /*      Also, this still leaves a race condition on NFS drivers         */
     305                 : /*      (apparently).                                                   */
     306                 : /************************************************************************/
     307                 : 
     308                 : void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
     309                 : 
     310                 : {
     311                 :     FILE      *fpLock;
     312                 :     char      *pszLockFilename;
     313                 :     
     314                 : /* -------------------------------------------------------------------- */
     315                 : /*      We use a lock file with a name derived from the file we want    */
     316                 : /*      to lock to represent the file being locked.  Note that for      */
     317                 : /*      the stub implementation the target file does not even need      */
     318                 : /*      to exist to be locked.                                          */
     319                 : /* -------------------------------------------------------------------- */
     320                 :     pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
     321                 :     sprintf( pszLockFilename, "%s.lock", pszPath );
     322                 : 
     323                 :     fpLock = fopen( pszLockFilename, "r" );
     324                 :     while( fpLock != NULL && dfWaitInSeconds > 0.0 )
     325                 :     {
     326                 :         fclose( fpLock );
     327                 :         CPLSleep( MIN(dfWaitInSeconds,0.5) );
     328                 :         dfWaitInSeconds -= 0.5;
     329                 : 
     330                 :         fpLock = fopen( pszLockFilename, "r" );
     331                 :     }
     332                 :         
     333                 :     if( fpLock != NULL )
     334                 :     {
     335                 :         fclose( fpLock );
     336                 :         CPLFree( pszLockFilename );
     337                 :         return NULL;
     338                 :     }
     339                 : 
     340                 :     fpLock = fopen( pszLockFilename, "w" );
     341                 : 
     342                 :     if( fpLock == NULL )
     343                 :     {
     344                 :         CPLFree( pszLockFilename );
     345                 :         return NULL;
     346                 :     }
     347                 : 
     348                 :     fwrite( "held\n", 1, 5, fpLock );
     349                 :     fclose( fpLock );
     350                 : 
     351                 :     return pszLockFilename;
     352                 : }
     353                 : 
     354                 : /************************************************************************/
     355                 : /*                           CPLUnlockFile()                            */
     356                 : /************************************************************************/
     357                 : 
     358                 : void CPLUnlockFile( void *hLock )
     359                 : 
     360                 : {
     361                 :     char *pszLockFilename = (char *) hLock;
     362                 : 
     363                 :     if( hLock == NULL )
     364                 :         return;
     365                 :     
     366                 :     VSIUnlink( pszLockFilename );
     367                 :     
     368                 :     CPLFree( pszLockFilename );
     369                 : }
     370                 : 
     371                 : /************************************************************************/
     372                 : /*                             CPLGetPID()                              */
     373                 : /************************************************************************/
     374                 : 
     375                 : GIntBig CPLGetPID()
     376                 : 
     377                 : {
     378                 :     return 1;
     379                 : }
     380                 : 
     381                 : /************************************************************************/
     382                 : /*                          CPLCreateThread();                          */
     383                 : /************************************************************************/
     384                 : 
     385                 : int CPLCreateThread( CPLThreadFunc pfnMain, void *pArg )
     386                 : 
     387                 : {
     388                 :     CPLDebug( "CPLCreateThread", "Fails to dummy implementation" );
     389                 : 
     390                 :     return -1;
     391                 : }
     392                 : 
     393                 : /************************************************************************/
     394                 : /*                              CPLSleep()                              */
     395                 : /************************************************************************/
     396                 : 
     397                 : void CPLSleep( double dfWaitInSeconds )
     398                 : 
     399                 : {
     400                 :     time_t  ltime;
     401                 :     time_t  ttime;
     402                 : 
     403                 :     time( &ltime );
     404                 :     ttime = ltime + (int) (dfWaitInSeconds+0.5);
     405                 : 
     406                 :     for( ; ltime < ttime; time(&ltime) )
     407                 :     {
     408                 :         /* currently we just busy wait.  Perhaps we could at least block on 
     409                 :            io? */
     410                 :     }
     411                 : }
     412                 : 
     413                 : /************************************************************************/
     414                 : /*                           CPLGetTLSList()                            */
     415                 : /************************************************************************/
     416                 : 
     417                 : static void **papTLSList = NULL;
     418                 : 
     419                 : static void **CPLGetTLSList()
     420                 : 
     421                 : {
     422                 :     if( papTLSList == NULL )
     423                 :         papTLSList = (void **) CPLCalloc(sizeof(void*),CTLS_MAX*2);
     424                 : 
     425                 :     return papTLSList;
     426                 : }
     427                 : 
     428                 : /************************************************************************/
     429                 : /*                           CPLCleanupTLS()                            */
     430                 : /************************************************************************/
     431                 : 
     432                 : void CPLCleanupTLS()
     433                 : 
     434                 : {
     435                 :     CPLCleanupTLSList( papTLSList );
     436                 :     papTLSList = NULL;
     437                 : }
     438                 : 
     439                 : /* endif CPL_MULTIPROC_STUB */
     440                 : 
     441                 : #elif defined(CPL_MULTIPROC_WIN32)
     442                 : 
     443                 : 
     444                 :   /************************************************************************/
     445                 :   /* ==================================================================== */
     446                 :   /*                        CPL_MULTIPROC_WIN32                           */
     447                 :   /*                                                                      */
     448                 :   /*    WIN32 Implementation of multiprocessing functions.                */
     449                 :   /* ==================================================================== */
     450                 :   /************************************************************************/
     451                 : 
     452                 : /* InitializeCriticalSectionAndSpinCount requires _WIN32_WINNT >= 0x403 */
     453                 : #define _WIN32_WINNT 0x0500
     454                 : 
     455                 : #include <windows.h>
     456                 : 
     457                 : /* windows.h header must be included above following lines. */
     458                 : #if defined(WIN32CE)
     459                 : #  include "cpl_win32ce_api.h"
     460                 : #  define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
     461                 : #endif
     462                 : 
     463                 : /************************************************************************/
     464                 : /*                        CPLGetThreadingModel()                        */
     465                 : /************************************************************************/
     466                 : 
     467                 : const char *CPLGetThreadingModel()
     468                 : 
     469                 : {
     470                 :     return "win32";
     471                 : }
     472                 : 
     473                 : /************************************************************************/
     474                 : /*                           CPLCreateMutex()                           */
     475                 : /************************************************************************/
     476                 : 
     477                 : void *CPLCreateMutex()
     478                 : 
     479                 : {
     480                 : #ifdef USE_WIN32_MUTEX
     481                 :     HANDLE hMutex;
     482                 : 
     483                 :     hMutex = CreateMutex( NULL, TRUE, NULL );
     484                 : 
     485                 :     return (void *) hMutex;
     486                 : #else
     487                 :     CRITICAL_SECTION *pcs;
     488                 : 
     489                 :   /* Do not use CPLMalloc() since its debugging infrastructure */
     490                 :   /* can call the CPL*Mutex functions... */
     491                 :     pcs = (CRITICAL_SECTION *)malloc(sizeof(*pcs));
     492                 :     if( pcs )
     493                 :     {
     494                 :       InitializeCriticalSectionAndSpinCount(pcs, 4000);
     495                 :       EnterCriticalSection(pcs);
     496                 :     }
     497                 : 
     498                 :     return (void *) pcs;
     499                 : #endif
     500                 : }
     501                 : 
     502                 : /************************************************************************/
     503                 : /*                          CPLAcquireMutex()                           */
     504                 : /************************************************************************/
     505                 : 
     506                 : int CPLAcquireMutex( void *hMutexIn, double dfWaitInSeconds )
     507                 : 
     508                 : {
     509                 : #ifdef USE_WIN32_MUTEX
     510                 :     HANDLE hMutex = (HANDLE) hMutexIn;
     511                 :     DWORD  hr;
     512                 : 
     513                 :     hr = WaitForSingleObject( hMutex, (int) (dfWaitInSeconds * 1000) );
     514                 :     
     515                 :     return hr != WAIT_TIMEOUT;
     516                 : #else
     517                 :     CRITICAL_SECTION *pcs = (CRITICAL_SECTION *)hMutexIn;
     518                 :     BOOL ret;
     519                 : 
     520                 :     while( (ret = TryEnterCriticalSection(pcs)) == 0 && dfWaitInSeconds > 0.0 )
     521                 :     {
     522                 :         CPLSleep( MIN(dfWaitInSeconds,0.125) );
     523                 :         dfWaitInSeconds -= 0.125;
     524                 :     }
     525                 :     
     526                 :     return ret;
     527                 : #endif
     528                 : }
     529                 : 
     530                 : /************************************************************************/
     531                 : /*                          CPLReleaseMutex()                           */
     532                 : /************************************************************************/
     533                 : 
     534                 : void CPLReleaseMutex( void *hMutexIn )
     535                 : 
     536                 : {
     537                 : #ifdef USE_WIN32_MUTEX
     538                 :     HANDLE hMutex = (HANDLE) hMutexIn;
     539                 : 
     540                 :     ReleaseMutex( hMutex );
     541                 : #else
     542                 :     CRITICAL_SECTION *pcs = (CRITICAL_SECTION *)hMutexIn;
     543                 : 
     544                 :     LeaveCriticalSection(pcs);
     545                 : #endif
     546                 : }
     547                 : 
     548                 : /************************************************************************/
     549                 : /*                          CPLDestroyMutex()                           */
     550                 : /************************************************************************/
     551                 : 
     552                 : void CPLDestroyMutex( void *hMutexIn )
     553                 : 
     554                 : {
     555                 : #ifdef USE_WIN32_MUTEX
     556                 :     HANDLE hMutex = (HANDLE) hMutexIn;
     557                 : 
     558                 :     CloseHandle( hMutex );
     559                 : #else
     560                 :     CRITICAL_SECTION *pcs = (CRITICAL_SECTION *)hMutexIn;
     561                 : 
     562                 :     DeleteCriticalSection( pcs );
     563                 :     free( pcs );
     564                 : #endif
     565                 : }
     566                 : 
     567                 : /************************************************************************/
     568                 : /*                            CPLLockFile()                             */
     569                 : /************************************************************************/
     570                 : 
     571                 : void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
     572                 : 
     573                 : {
     574                 :     char      *pszLockFilename;
     575                 :     HANDLE    hLockFile;
     576                 :     
     577                 :     pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
     578                 :     sprintf( pszLockFilename, "%s.lock", pszPath );
     579                 : 
     580                 :     hLockFile = 
     581                 :         CreateFile( pszLockFilename, GENERIC_WRITE, 0, NULL,CREATE_NEW, 
     582                 :                     FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL );
     583                 : 
     584                 :     while( GetLastError() == ERROR_ALREADY_EXISTS
     585                 :            && dfWaitInSeconds > 0.0 )
     586                 :     {
     587                 :         CloseHandle( hLockFile );
     588                 :         CPLSleep( MIN(dfWaitInSeconds,0.125) );
     589                 :         dfWaitInSeconds -= 0.125;
     590                 : 
     591                 :         hLockFile = 
     592                 :             CreateFile( pszLockFilename, GENERIC_WRITE, 0, NULL, CREATE_NEW, 
     593                 :                         FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, 
     594                 :                         NULL );
     595                 :     }
     596                 : 
     597                 :     CPLFree( pszLockFilename );
     598                 : 
     599                 :     if( hLockFile == INVALID_HANDLE_VALUE )
     600                 :         return NULL;
     601                 : 
     602                 :     if( GetLastError() == ERROR_ALREADY_EXISTS )
     603                 :     {
     604                 :         CloseHandle( hLockFile );
     605                 :         return NULL;
     606                 :     }
     607                 : 
     608                 :     return (void *) hLockFile;
     609                 : }
     610                 : 
     611                 : /************************************************************************/
     612                 : /*                           CPLUnlockFile()                            */
     613                 : /************************************************************************/
     614                 : 
     615                 : void CPLUnlockFile( void *hLock )
     616                 : 
     617                 : {
     618                 :     HANDLE    hLockFile = (HANDLE) hLock;
     619                 : 
     620                 :     CloseHandle( hLockFile );
     621                 : }
     622                 : 
     623                 : /************************************************************************/
     624                 : /*                             CPLGetPID()                              */
     625                 : /************************************************************************/
     626                 : 
     627                 : GIntBig CPLGetPID()
     628                 : 
     629                 : {
     630                 :     return (GIntBig) GetCurrentThreadId();
     631                 : }
     632                 : 
     633                 : /************************************************************************/
     634                 : /*                       CPLStdCallThreadJacket()                       */
     635                 : /************************************************************************/
     636                 : 
     637                 : typedef struct {
     638                 :     void *pAppData;
     639                 :     CPLThreadFunc pfnMain;
     640                 : } CPLStdCallThreadInfo;
     641                 : 
     642                 : static DWORD WINAPI CPLStdCallThreadJacket( void *pData )
     643                 : 
     644                 : {
     645                 :     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) pData;
     646                 : 
     647                 :     psInfo->pfnMain( psInfo->pAppData );
     648                 : 
     649                 :     CPLFree( psInfo );
     650                 : 
     651                 :     CPLCleanupTLS();
     652                 : 
     653                 :     return 0;
     654                 : }
     655                 : 
     656                 : /************************************************************************/
     657                 : /*                          CPLCreateThread()                           */
     658                 : /*                                                                      */
     659                 : /*      The WIN32 CreateThread() call requires an entry point that      */
     660                 : /*      has __stdcall conventions, so we provide a jacket function      */
     661                 : /*      to supply that.                                                 */
     662                 : /************************************************************************/
     663                 : 
     664                 : int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
     665                 : 
     666                 : {
     667                 :     HANDLE hThread;
     668                 :     DWORD  nThreadId;
     669                 :     CPLStdCallThreadInfo *psInfo;
     670                 : 
     671                 :     psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
     672                 :     psInfo->pAppData = pThreadArg;
     673                 :     psInfo->pfnMain = pfnMain;
     674                 : 
     675                 :     hThread = CreateThread( NULL, 0, CPLStdCallThreadJacket, psInfo, 
     676                 :                             0, &nThreadId );
     677                 : 
     678                 :     if( hThread == NULL )
     679                 :         return -1;
     680                 : 
     681                 :     CloseHandle( hThread );
     682                 : 
     683                 :     return nThreadId;
     684                 : }
     685                 : 
     686                 : /************************************************************************/
     687                 : /*                              CPLSleep()                              */
     688                 : /************************************************************************/
     689                 : 
     690                 : void CPLSleep( double dfWaitInSeconds )
     691                 : 
     692                 : {
     693                 :     Sleep( (DWORD) (dfWaitInSeconds * 1000.0) );
     694                 : }
     695                 : 
     696                 : static int           bTLSKeySetup = FALSE;
     697                 : static DWORD         nTLSKey;
     698                 : 
     699                 : /************************************************************************/
     700                 : /*                           CPLGetTLSList()                            */
     701                 : /************************************************************************/
     702                 : 
     703                 : static void **CPLGetTLSList()
     704                 : 
     705                 : {
     706                 :     void **papTLSList;
     707                 : 
     708                 :     if( !bTLSKeySetup )
     709                 :     {
     710                 :         nTLSKey = TlsAlloc();
     711                 :         if( nTLSKey == TLS_OUT_OF_INDEXES )
     712                 :         {
     713                 :             CPLError( CE_Fatal, CPLE_AppDefined, 
     714                 :                       "TlsAlloc() failed!" );
     715                 :         }
     716                 :         bTLSKeySetup = TRUE;
     717                 :     }
     718                 : 
     719                 :     papTLSList = (void **) TlsGetValue( nTLSKey );
     720                 :     if( papTLSList == NULL )
     721                 :     {
     722                 :         papTLSList = (void **) CPLCalloc(sizeof(void*),CTLS_MAX*2);
     723                 :         if( TlsSetValue( nTLSKey, papTLSList ) == 0 )
     724                 :         {
     725                 :             CPLError( CE_Fatal, CPLE_AppDefined, 
     726                 :                       "TlsSetValue() failed!" );
     727                 :         }
     728                 :     }
     729                 : 
     730                 :     return papTLSList;
     731                 : }
     732                 : 
     733                 : /************************************************************************/
     734                 : /*                           CPLCleanupTLS()                            */
     735                 : /************************************************************************/
     736                 : 
     737                 : void CPLCleanupTLS()
     738                 : 
     739                 : {
     740                 :     void **papTLSList;
     741                 : 
     742                 :     if( !bTLSKeySetup )
     743                 :         return;
     744                 : 
     745                 :     papTLSList = (void **) TlsGetValue( nTLSKey );
     746                 :     if( papTLSList == NULL )
     747                 :         return;
     748                 : 
     749                 :     TlsSetValue( nTLSKey, NULL );
     750                 : 
     751                 :     CPLCleanupTLSList( papTLSList );
     752                 : }
     753                 : 
     754                 : /* endif CPL_MULTIPROC_WIN32 */
     755                 : 
     756                 : #elif defined(CPL_MULTIPROC_PTHREAD)
     757                 : 
     758                 : #include <pthread.h>
     759                 : #include <time.h>
     760                 : 
     761                 :   /************************************************************************/
     762                 :   /* ==================================================================== */
     763                 :   /*                        CPL_MULTIPROC_PTHREAD                         */
     764                 :   /*                                                                      */
     765                 :   /*    PTHREAD Implementation of multiprocessing functions.              */
     766                 :   /* ==================================================================== */
     767                 :   /************************************************************************/
     768                 : 
     769                 : /************************************************************************/
     770                 : /*                      CPLCreateOrAcquireMutex()                       */
     771                 : /************************************************************************/
     772                 : 
     773        14314782 : int CPLCreateOrAcquireMutex( void **phMutex, double dfWaitInSeconds )
     774                 : 
     775                 : {
     776        14314782 :     int bSuccess = FALSE;
     777                 :     static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
     778                 : 
     779        14314782 :     pthread_mutex_lock(&global_mutex);
     780        14314782 :     if( *phMutex == NULL )
     781                 :     {
     782            6127 :         *phMutex = CPLCreateMutex();
     783            6127 :         bSuccess = *phMutex != NULL;
     784            6127 :         pthread_mutex_unlock(&global_mutex);
     785                 :     }
     786                 :     else
     787                 :     {
     788        14308655 :         pthread_mutex_unlock(&global_mutex);
     789                 : 
     790        14308655 :         bSuccess = CPLAcquireMutex( *phMutex, dfWaitInSeconds );
     791                 :     }
     792                 : 
     793        14314782 :     return bSuccess;
     794                 : }
     795                 : 
     796                 : /************************************************************************/
     797                 : /*                        CPLGetThreadingModel()                        */
     798                 : /************************************************************************/
     799                 : 
     800               0 : const char *CPLGetThreadingModel()
     801                 : 
     802                 : {
     803               0 :     return "pthread";
     804                 : }
     805                 : 
     806                 : /************************************************************************/
     807                 : /*                           CPLCreateMutex()                           */
     808                 : /************************************************************************/
     809                 : 
     810            6243 : void *CPLCreateMutex()
     811                 : 
     812                 : {
     813                 :     pthread_mutex_t *hMutex;
     814                 : 
     815            6243 :     hMutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
     816            6243 :     if (hMutex == NULL)
     817               0 :         return NULL;
     818                 : 
     819                 : #if defined(PTHREAD_MUTEX_RECURSIVE) || defined(HAVE_PTHREAD_MUTEX_RECURSIVE)
     820                 :     {
     821                 :         pthread_mutexattr_t  attr;
     822            6243 :         pthread_mutexattr_init( &attr );
     823            6243 :         pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
     824            6243 :         pthread_mutex_init( hMutex, &attr );
     825                 :     }
     826                 : /* BSDs have PTHREAD_MUTEX_RECURSIVE as an enum, not a define. */
     827                 : /* But they have #define MUTEX_TYPE_COUNTING_FAST PTHREAD_MUTEX_RECURSIVE */
     828                 : #elif defined(MUTEX_TYPE_COUNTING_FAST)
     829                 :     {
     830                 :         pthread_mutexattr_t  attr;
     831                 :         pthread_mutexattr_init( &attr );
     832                 :         pthread_mutexattr_settype( &attr, MUTEX_TYPE_COUNTING_FAST );
     833                 :         pthread_mutex_init( hMutex, &attr );
     834                 :     }
     835                 : #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
     836                 :     pthread_mutex_t tmp_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
     837                 :     *hMutex = tmp_mutex;
     838                 : #else
     839                 : #error "Recursive mutexes apparently unsupported, configure --without-threads" 
     840                 : #endif
     841                 : 
     842                 :     // mutexes are implicitly acquired when created.
     843            6243 :     CPLAcquireMutex( hMutex, 0.0 );
     844                 : 
     845            6243 :     return (void *) hMutex;
     846                 : }
     847                 : 
     848                 : /************************************************************************/
     849                 : /*                          CPLAcquireMutex()                           */
     850                 : /************************************************************************/
     851                 : 
     852        14333163 : int CPLAcquireMutex( void *hMutexIn, double dfWaitInSeconds )
     853                 : 
     854                 : {
     855                 :     int err;
     856                 : 
     857                 :     /* we need to add timeout support */
     858        14333163 :     err =  pthread_mutex_lock( (pthread_mutex_t *) hMutexIn );
     859                 :     
     860        14333163 :     if( err != 0 )
     861                 :     {
     862               0 :         if( err == EDEADLK )
     863               0 :             fprintf(stderr, "CPLAcquireMutex: Error = %d/EDEADLK", err );
     864                 :         else
     865               0 :             fprintf(stderr, "CPLAcquireMutex: Error = %d", err );
     866                 : 
     867               0 :         return FALSE;
     868                 :     }
     869                 : 
     870        14333163 :     return TRUE;
     871                 : }
     872                 : 
     873                 : /************************************************************************/
     874                 : /*                          CPLReleaseMutex()                           */
     875                 : /************************************************************************/
     876                 : 
     877        14333163 : void CPLReleaseMutex( void *hMutexIn )
     878                 : 
     879                 : {
     880        14333163 :     pthread_mutex_unlock( (pthread_mutex_t *) hMutexIn );
     881        14333163 : }
     882                 : 
     883                 : /************************************************************************/
     884                 : /*                          CPLDestroyMutex()                           */
     885                 : /************************************************************************/
     886                 : 
     887            3637 : void CPLDestroyMutex( void *hMutexIn )
     888                 : 
     889                 : {
     890            3637 :     pthread_mutex_destroy( (pthread_mutex_t *) hMutexIn );
     891            3637 :     free( hMutexIn );
     892            3637 : }
     893                 : 
     894                 : /************************************************************************/
     895                 : /*                            CPLLockFile()                             */
     896                 : /*                                                                      */
     897                 : /*      This is really a stub implementation, see first                 */
     898                 : /*      CPLLockFile() for caveats.                                      */
     899                 : /************************************************************************/
     900                 : 
     901               2 : void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
     902                 : 
     903                 : {
     904                 :     FILE      *fpLock;
     905                 :     char      *pszLockFilename;
     906                 :     
     907                 : /* -------------------------------------------------------------------- */
     908                 : /*      We use a lock file with a name derived from the file we want    */
     909                 : /*      to lock to represent the file being locked.  Note that for      */
     910                 : /*      the stub implementation the target file does not even need      */
     911                 : /*      to exist to be locked.                                          */
     912                 : /* -------------------------------------------------------------------- */
     913               2 :     pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
     914               2 :     sprintf( pszLockFilename, "%s.lock", pszPath );
     915                 : 
     916               2 :     fpLock = fopen( pszLockFilename, "r" );
     917               4 :     while( fpLock != NULL && dfWaitInSeconds > 0.0 )
     918                 :     {
     919               0 :         fclose( fpLock );
     920               0 :         CPLSleep( MIN(dfWaitInSeconds,0.5) );
     921               0 :         dfWaitInSeconds -= 0.5;
     922                 : 
     923               0 :         fpLock = fopen( pszLockFilename, "r" );
     924                 :     }
     925                 :         
     926               2 :     if( fpLock != NULL )
     927                 :     {
     928               0 :         fclose( fpLock );
     929               0 :         CPLFree( pszLockFilename );
     930               0 :         return NULL;
     931                 :     }
     932                 : 
     933               2 :     fpLock = fopen( pszLockFilename, "w" );
     934                 : 
     935               2 :     if( fpLock == NULL )
     936                 :     {
     937               0 :         CPLFree( pszLockFilename );
     938               0 :         return NULL;
     939                 :     }
     940                 : 
     941               2 :     fwrite( "held\n", 1, 5, fpLock );
     942               2 :     fclose( fpLock );
     943                 : 
     944               2 :     return pszLockFilename;
     945                 : }
     946                 : 
     947                 : /************************************************************************/
     948                 : /*                           CPLUnlockFile()                            */
     949                 : /************************************************************************/
     950                 : 
     951               2 : void CPLUnlockFile( void *hLock )
     952                 : 
     953                 : {
     954               2 :     char *pszLockFilename = (char *) hLock;
     955                 : 
     956               2 :     if( hLock == NULL )
     957               0 :         return;
     958                 :     
     959               2 :     VSIUnlink( pszLockFilename );
     960                 :     
     961               2 :     CPLFree( pszLockFilename );
     962                 : }
     963                 : 
     964                 : /************************************************************************/
     965                 : /*                             CPLGetPID()                              */
     966                 : /************************************************************************/
     967                 : 
     968           24347 : GIntBig CPLGetPID()
     969                 : 
     970                 : {
     971           24347 :     return (GIntBig) pthread_self();
     972                 : }
     973                 : 
     974                 : /************************************************************************/
     975                 : /*                       CPLStdCallThreadJacket()                       */
     976                 : /************************************************************************/
     977                 : 
     978                 : typedef struct {
     979                 :     void *pAppData;
     980                 :     CPLThreadFunc pfnMain;
     981                 :     pthread_t hThread;
     982                 : } CPLStdCallThreadInfo;
     983                 : 
     984               1 : static void *CPLStdCallThreadJacket( void *pData )
     985                 : 
     986                 : {
     987               1 :     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) pData;
     988                 : 
     989               1 :     psInfo->pfnMain( psInfo->pAppData );
     990                 : 
     991               1 :     CPLFree( psInfo );
     992                 : 
     993               1 :     return NULL;
     994                 : }
     995                 : 
     996                 : /************************************************************************/
     997                 : /*                          CPLCreateThread()                           */
     998                 : /*                                                                      */
     999                 : /*      The WIN32 CreateThread() call requires an entry point that      */
    1000                 : /*      has __stdcall conventions, so we provide a jacket function      */
    1001                 : /*      to supply that.                                                 */
    1002                 : /************************************************************************/
    1003                 : 
    1004               1 : int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
    1005                 : 
    1006                 : {
    1007                 : 
    1008                 :     CPLStdCallThreadInfo *psInfo;
    1009                 :     pthread_attr_t hThreadAttr;
    1010                 : 
    1011               1 :     psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
    1012               1 :     psInfo->pAppData = pThreadArg;
    1013               1 :     psInfo->pfnMain = pfnMain;
    1014                 : 
    1015               1 :     pthread_attr_init( &hThreadAttr );
    1016               1 :     pthread_attr_setdetachstate( &hThreadAttr, PTHREAD_CREATE_DETACHED );
    1017               1 :     if( pthread_create( &(psInfo->hThread), &hThreadAttr, 
    1018                 :                         CPLStdCallThreadJacket, (void *) psInfo ) != 0 )
    1019                 :     {
    1020               0 :         CPLFree( psInfo );
    1021               0 :         return -1;
    1022                 :     }
    1023                 : 
    1024               1 :     return 1; /* can we return the actual thread pid? */
    1025                 : }
    1026                 : 
    1027                 : /************************************************************************/
    1028                 : /*                              CPLSleep()                              */
    1029                 : /************************************************************************/
    1030                 : 
    1031               1 : void CPLSleep( double dfWaitInSeconds )
    1032                 : 
    1033                 : {
    1034                 :     struct timespec sRequest, sRemain;
    1035                 : 
    1036               1 :     sRequest.tv_sec = (int) floor(dfWaitInSeconds);
    1037               1 :     sRequest.tv_nsec = (int) ((dfWaitInSeconds - sRequest.tv_sec)*1000000000);
    1038               1 :     nanosleep( &sRequest, &sRemain );
    1039               1 : }
    1040                 : 
    1041                 : static pthread_key_t  oTLSKey;
    1042                 : static pthread_once_t oTLSKeySetup = PTHREAD_ONCE_INIT;
    1043                 : 
    1044                 : /************************************************************************/
    1045                 : /*                             CPLMake_key()                            */
    1046                 : /************************************************************************/
    1047                 : 
    1048             649 : static void CPLMake_key()
    1049                 : 
    1050                 : {
    1051             649 :     if( pthread_key_create( &oTLSKey, (void (*)(void*)) CPLCleanupTLSList ) != 0 )
    1052                 :     {
    1053               0 :         CPLError( CE_Fatal, CPLE_AppDefined, "pthread_key_create() failed!" );
    1054                 :     }
    1055             649 : }
    1056                 : 
    1057                 : /************************************************************************/
    1058                 : /*                             CPLCleanupTLS()                          */
    1059                 : /************************************************************************/
    1060                 : 
    1061             982 : void CPLCleanupTLS()
    1062                 : 
    1063                 : {
    1064                 :     void **papTLSList;
    1065                 : 
    1066             982 :     papTLSList = (void **) pthread_getspecific( oTLSKey );
    1067             982 :     if( papTLSList == NULL )
    1068              18 :         return;
    1069                 : 
    1070             964 :     pthread_setspecific( oTLSKey, NULL );
    1071                 : 
    1072             964 :     CPLCleanupTLSList( papTLSList );
    1073                 : }
    1074                 : 
    1075                 : /************************************************************************/
    1076                 : /*                           CPLGetTLSList()                            */
    1077                 : /************************************************************************/
    1078                 : 
    1079        31293257 : static void **CPLGetTLSList()
    1080                 : 
    1081                 : {
    1082                 :     void **papTLSList;
    1083                 : 
    1084        31293257 :     if ( pthread_once(&oTLSKeySetup, CPLMake_key) != 0 )
    1085                 :     {
    1086                 :         CPLError( CE_Fatal, CPLE_AppDefined,
    1087               0 :             "pthread_once() failed!" );
    1088                 :     }
    1089                 : 
    1090        31293257 :     papTLSList = (void **) pthread_getspecific( oTLSKey );
    1091        31293257 :     if( papTLSList == NULL )
    1092                 :     {
    1093             987 :         papTLSList = (void **) CPLCalloc(sizeof(void*),CTLS_MAX*2);
    1094             987 :         if( pthread_setspecific( oTLSKey, papTLSList ) != 0 )
    1095                 :         {
    1096                 :             CPLError( CE_Fatal, CPLE_AppDefined,
    1097               0 :                 "pthread_setspecific() failed!" );
    1098                 :         }
    1099                 :     }
    1100                 : 
    1101        31293257 :     return papTLSList;
    1102                 : }
    1103                 : 
    1104                 : #endif /* def CPL_MULTIPROC_PTHREAD */
    1105                 : 
    1106                 : /************************************************************************/
    1107                 : /*                             CPLGetTLS()                              */
    1108                 : /************************************************************************/
    1109                 : 
    1110        31287282 : void *CPLGetTLS( int nIndex )
    1111                 : 
    1112                 : {
    1113        31287282 :     void** papTLSList = CPLGetTLSList();
    1114                 : 
    1115        31287282 :     CPLAssert( nIndex >= 0 && nIndex < CTLS_MAX );
    1116                 : 
    1117        31287282 :     return papTLSList[nIndex];
    1118                 : }
    1119                 : 
    1120                 : /************************************************************************/
    1121                 : /*                             CPLSetTLS()                              */
    1122                 : /************************************************************************/
    1123                 : 
    1124            4824 : void CPLSetTLS( int nIndex, void *pData, int bFreeOnExit )
    1125                 : 
    1126                 : {
    1127            4824 :     CPLSetTLSWithFreeFunc(nIndex, pData, (bFreeOnExit) ? CPLFree : NULL);
    1128            4824 : }
    1129                 : 
    1130                 : /************************************************************************/
    1131                 : /*                      CPLSetTLSWithFreeFunc()                         */
    1132                 : /************************************************************************/
    1133                 : 
    1134                 : /* Warning : the CPLTLSFreeFunc must not in any case directly or indirectly */
    1135                 : /* use or fetch any TLS data, or a terminating thread will hang ! */
    1136            5975 : void CPLSetTLSWithFreeFunc( int nIndex, void *pData, CPLTLSFreeFunc pfnFree )
    1137                 : 
    1138                 : {
    1139            5975 :     void **papTLSList = CPLGetTLSList();
    1140                 : 
    1141            5975 :     CPLAssert( nIndex >= 0 && nIndex < CTLS_MAX );
    1142                 : 
    1143            5975 :     papTLSList[nIndex] = pData;
    1144            5975 :     papTLSList[CTLS_MAX + nIndex] = (void*) pfnFree;
    1145            5975 : }

Generated by: LCOV version 1.7