LCOV - code coverage report
Current view: directory - port - cpl_multiproc.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 180 134 74.4 %
Date: 2012-12-26 Functions: 31 25 80.6 %

       1                 : /**********************************************************************
       2                 :  * $Id: cpl_multiproc.cpp 25226 2012-11-11 20:23:39Z 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                 :  *
      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 25226 2012-11-11 20:23:39Z rouault $");
      44                 : 
      45                 : #if defined(CPL_MULTIPROC_STUB) && !defined(DEBUG)
      46                 : #  define MUTEX_NONE
      47                 : #endif
      48                 : 
      49                 : /************************************************************************/
      50                 : /*                           CPLMutexHolder()                           */
      51                 : /************************************************************************/
      52                 : 
      53        15794988 : CPLMutexHolder::CPLMutexHolder( void **phMutex, double dfWaitInSeconds,
      54                 :                                 const char *pszFileIn, 
      55                 :                                 int nLineIn )
      56                 : 
      57                 : {
      58                 : #ifndef MUTEX_NONE
      59        15794988 :     pszFile = pszFileIn;
      60        15794988 :     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        15794988 :     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        15794988 :         hMutex = *phMutex;
      87                 :     }
      88                 : #endif /* ndef MUTEX_NONE */
      89        15794988 : }
      90                 : 
      91                 : /************************************************************************/
      92                 : /*                          ~CPLMutexHolder()                           */
      93                 : /************************************************************************/
      94                 : 
      95        15794988 : CPLMutexHolder::~CPLMutexHolder()
      96                 : 
      97                 : {
      98                 : #ifndef MUTEX_NONE
      99        15794988 :     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        15794988 :         CPLReleaseMutex( hMutex );
     107                 :     }
     108                 : #endif /* ndef MUTEX_NONE */
     109        15794988 : }
     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            1102 : static void CPLCleanupTLSList( void **papTLSList )
     170                 : 
     171                 : {
     172                 :     int i;
     173                 : 
     174                 : //    printf( "CPLCleanupTLSList(%p)\n", papTLSList );
     175                 :     
     176            1102 :     if( papTLSList == NULL )
     177               0 :         return;
     178                 : 
     179           36366 :     for( i = 0; i < CTLS_MAX; i++ )
     180                 :     {
     181           35264 :         if( papTLSList[i] != NULL && papTLSList[i+CTLS_MAX] != NULL )
     182                 :         {
     183            2572 :             CPLTLSFreeFunc pfnFree = (CPLTLSFreeFunc) papTLSList[i + CTLS_MAX];
     184            2572 :             pfnFree( papTLSList[i] );
     185            2572 :             papTLSList[i] = NULL;
     186                 :         }
     187                 :     }
     188                 : 
     189            1102 :     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                 : /*                             CPLGetNumCPUs()                          */
     205                 : /************************************************************************/
     206                 : 
     207                 : int CPLGetNumCPUs()
     208                 : {
     209                 :     return 1;
     210                 : }
     211                 : 
     212                 : /************************************************************************/
     213                 : /*                        CPLGetThreadingModel()                        */
     214                 : /************************************************************************/
     215                 : 
     216                 : const char *CPLGetThreadingModel()
     217                 : 
     218                 : {
     219                 :     return "stub";
     220                 : }
     221                 : 
     222                 : /************************************************************************/
     223                 : /*                           CPLCreateMutex()                           */
     224                 : /************************************************************************/
     225                 : 
     226                 : void *CPLCreateMutex()
     227                 : 
     228                 : {
     229                 : #ifndef MUTEX_NONE
     230                 :     unsigned char *pabyMutex = (unsigned char *) malloc( 4 );
     231                 : 
     232                 :     pabyMutex[0] = 1;
     233                 :     pabyMutex[1] = 'r';
     234                 :     pabyMutex[2] = 'e';
     235                 :     pabyMutex[3] = 'd';
     236                 : 
     237                 :     return (void *) pabyMutex;
     238                 : #else
     239                 :     return (void *) 0xdeadbeef;
     240                 : #endif 
     241                 : }
     242                 : 
     243                 : /************************************************************************/
     244                 : /*                          CPLAcquireMutex()                           */
     245                 : /************************************************************************/
     246                 : 
     247                 : int CPLAcquireMutex( void *hMutex, double dfWaitInSeconds )
     248                 : 
     249                 : {
     250                 : #ifndef MUTEX_NONE
     251                 :     unsigned char *pabyMutex = (unsigned char *) hMutex;
     252                 : 
     253                 :     CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e' 
     254                 :                && pabyMutex[3] == 'd' );
     255                 : 
     256                 :     pabyMutex[0] += 1;
     257                 : 
     258                 :     return TRUE;
     259                 : #else
     260                 :     return TRUE;
     261                 : #endif
     262                 : }
     263                 : 
     264                 : /************************************************************************/
     265                 : /*                          CPLReleaseMutex()                           */
     266                 : /************************************************************************/
     267                 : 
     268                 : void CPLReleaseMutex( void *hMutex )
     269                 : 
     270                 : {
     271                 : #ifndef MUTEX_NONE
     272                 :     unsigned char *pabyMutex = (unsigned char *) hMutex;
     273                 : 
     274                 :     CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e' 
     275                 :                && pabyMutex[3] == 'd' );
     276                 : 
     277                 :     if( pabyMutex[0] < 1 )
     278                 :         CPLDebug( "CPLMultiProc", 
     279                 :                   "CPLReleaseMutex() called on mutex with %d as ref count!",
     280                 :                   pabyMutex[0] );
     281                 : 
     282                 :     pabyMutex[0] -= 1;
     283                 : #endif
     284                 : }
     285                 : 
     286                 : /************************************************************************/
     287                 : /*                          CPLDestroyMutex()                           */
     288                 : /************************************************************************/
     289                 : 
     290                 : void CPLDestroyMutex( void *hMutex )
     291                 : 
     292                 : {
     293                 : #ifndef MUTEX_NONE
     294                 :     unsigned char *pabyMutex = (unsigned char *) hMutex;
     295                 : 
     296                 :     CPLAssert( pabyMutex[1] == 'r' && pabyMutex[2] == 'e' 
     297                 :                && pabyMutex[3] == 'd' );
     298                 : 
     299                 :     free( pabyMutex );
     300                 : #endif
     301                 : }
     302                 : 
     303                 : /************************************************************************/
     304                 : /*                            CPLCreateCond()                           */
     305                 : /************************************************************************/
     306                 : 
     307                 : void  *CPLCreateCond()
     308                 : {
     309                 :     return NULL;
     310                 : }
     311                 : 
     312                 : /************************************************************************/
     313                 : /*                            CPLCondWait()                             */
     314                 : /************************************************************************/
     315                 : 
     316                 : void  CPLCondWait( void *hCond, void* hMutex )
     317                 : {
     318                 : }
     319                 : 
     320                 : /************************************************************************/
     321                 : /*                            CPLCondSignal()                           */
     322                 : /************************************************************************/
     323                 : 
     324                 : void  CPLCondSignal( void *hCond )
     325                 : {
     326                 : }
     327                 : 
     328                 : /************************************************************************/
     329                 : /*                           CPLCondBroadcast()                         */
     330                 : /************************************************************************/
     331                 : 
     332                 : void  CPLCondBroadcast( void *hCond )
     333                 : {
     334                 : }
     335                 : 
     336                 : /************************************************************************/
     337                 : /*                            CPLDestroyCond()                          */
     338                 : /************************************************************************/
     339                 : 
     340                 : void  CPLDestroyCond( void *hCond )
     341                 : {
     342                 : }
     343                 : 
     344                 : /************************************************************************/
     345                 : /*                            CPLLockFile()                             */
     346                 : /*                                                                      */
     347                 : /*      Lock a file.  This implementation has a terrible race           */
     348                 : /*      condition.  If we don't succeed in opening the lock file, we    */
     349                 : /*      assume we can create one and own the target file, but other     */
     350                 : /*      processes might easily try creating the target file at the      */
     351                 : /*      same time, overlapping us.  Death!  Mayhem!  The traditional    */
     352                 : /*      solution is to use open() with _O_CREAT|_O_EXCL but this        */
     353                 : /*      function and these arguments aren't trivially portable.         */
     354                 : /*      Also, this still leaves a race condition on NFS drivers         */
     355                 : /*      (apparently).                                                   */
     356                 : /************************************************************************/
     357                 : 
     358                 : void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
     359                 : 
     360                 : {
     361                 :     FILE      *fpLock;
     362                 :     char      *pszLockFilename;
     363                 :     
     364                 : /* -------------------------------------------------------------------- */
     365                 : /*      We use a lock file with a name derived from the file we want    */
     366                 : /*      to lock to represent the file being locked.  Note that for      */
     367                 : /*      the stub implementation the target file does not even need      */
     368                 : /*      to exist to be locked.                                          */
     369                 : /* -------------------------------------------------------------------- */
     370                 :     pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
     371                 :     sprintf( pszLockFilename, "%s.lock", pszPath );
     372                 : 
     373                 :     fpLock = fopen( pszLockFilename, "r" );
     374                 :     while( fpLock != NULL && dfWaitInSeconds > 0.0 )
     375                 :     {
     376                 :         fclose( fpLock );
     377                 :         CPLSleep( MIN(dfWaitInSeconds,0.5) );
     378                 :         dfWaitInSeconds -= 0.5;
     379                 : 
     380                 :         fpLock = fopen( pszLockFilename, "r" );
     381                 :     }
     382                 :         
     383                 :     if( fpLock != NULL )
     384                 :     {
     385                 :         fclose( fpLock );
     386                 :         CPLFree( pszLockFilename );
     387                 :         return NULL;
     388                 :     }
     389                 : 
     390                 :     fpLock = fopen( pszLockFilename, "w" );
     391                 : 
     392                 :     if( fpLock == NULL )
     393                 :     {
     394                 :         CPLFree( pszLockFilename );
     395                 :         return NULL;
     396                 :     }
     397                 : 
     398                 :     fwrite( "held\n", 1, 5, fpLock );
     399                 :     fclose( fpLock );
     400                 : 
     401                 :     return pszLockFilename;
     402                 : }
     403                 : 
     404                 : /************************************************************************/
     405                 : /*                           CPLUnlockFile()                            */
     406                 : /************************************************************************/
     407                 : 
     408                 : void CPLUnlockFile( void *hLock )
     409                 : 
     410                 : {
     411                 :     char *pszLockFilename = (char *) hLock;
     412                 : 
     413                 :     if( hLock == NULL )
     414                 :         return;
     415                 :     
     416                 :     VSIUnlink( pszLockFilename );
     417                 :     
     418                 :     CPLFree( pszLockFilename );
     419                 : }
     420                 : 
     421                 : /************************************************************************/
     422                 : /*                             CPLGetPID()                              */
     423                 : /************************************************************************/
     424                 : 
     425                 : GIntBig CPLGetPID()
     426                 : 
     427                 : {
     428                 :     return 1;
     429                 : }
     430                 : 
     431                 : /************************************************************************/
     432                 : /*                          CPLCreateThread();                          */
     433                 : /************************************************************************/
     434                 : 
     435                 : int CPLCreateThread( CPLThreadFunc pfnMain, void *pArg )
     436                 : 
     437                 : {
     438                 :     CPLDebug( "CPLCreateThread", "Fails to dummy implementation" );
     439                 : 
     440                 :     return -1;
     441                 : }
     442                 : 
     443                 : /************************************************************************/
     444                 : /*                      CPLCreateJoinableThread()                       */
     445                 : /************************************************************************/
     446                 : 
     447                 : void* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pThreadArg )
     448                 : 
     449                 : {
     450                 :     CPLDebug( "CPLCreateJoinableThread", "Fails to dummy implementation" );
     451                 : 
     452                 :     return NULL;
     453                 : }
     454                 : 
     455                 : /************************************************************************/
     456                 : /*                          CPLJoinThread()                             */
     457                 : /************************************************************************/
     458                 : 
     459                 : void CPLJoinThread(void* hJoinableThread)
     460                 : {
     461                 : }
     462                 : 
     463                 : /************************************************************************/
     464                 : /*                              CPLSleep()                              */
     465                 : /************************************************************************/
     466                 : 
     467                 : void CPLSleep( double dfWaitInSeconds )
     468                 : 
     469                 : {
     470                 :     time_t  ltime;
     471                 :     time_t  ttime;
     472                 : 
     473                 :     time( &ltime );
     474                 :     ttime = ltime + (int) (dfWaitInSeconds+0.5);
     475                 : 
     476                 :     for( ; ltime < ttime; time(&ltime) )
     477                 :     {
     478                 :         /* currently we just busy wait.  Perhaps we could at least block on 
     479                 :            io? */
     480                 :     }
     481                 : }
     482                 : 
     483                 : /************************************************************************/
     484                 : /*                           CPLGetTLSList()                            */
     485                 : /************************************************************************/
     486                 : 
     487                 : static void **papTLSList = NULL;
     488                 : 
     489                 : static void **CPLGetTLSList()
     490                 : 
     491                 : {
     492                 :     if( papTLSList == NULL )
     493                 :         papTLSList = (void **) CPLCalloc(sizeof(void*),CTLS_MAX*2);
     494                 : 
     495                 :     return papTLSList;
     496                 : }
     497                 : 
     498                 : /************************************************************************/
     499                 : /*                           CPLCleanupTLS()                            */
     500                 : /************************************************************************/
     501                 : 
     502                 : void CPLCleanupTLS()
     503                 : 
     504                 : {
     505                 :     CPLCleanupTLSList( papTLSList );
     506                 :     papTLSList = NULL;
     507                 : }
     508                 : 
     509                 : /* endif CPL_MULTIPROC_STUB */
     510                 : 
     511                 : #elif defined(CPL_MULTIPROC_WIN32)
     512                 : 
     513                 : 
     514                 :   /************************************************************************/
     515                 :   /* ==================================================================== */
     516                 :   /*                        CPL_MULTIPROC_WIN32                           */
     517                 :   /*                                                                      */
     518                 :   /*    WIN32 Implementation of multiprocessing functions.                */
     519                 :   /* ==================================================================== */
     520                 :   /************************************************************************/
     521                 : 
     522                 : /* InitializeCriticalSectionAndSpinCount requires _WIN32_WINNT >= 0x403 */
     523                 : #define _WIN32_WINNT 0x0500
     524                 : 
     525                 : #include <windows.h>
     526                 : 
     527                 : /* windows.h header must be included above following lines. */
     528                 : #if defined(WIN32CE)
     529                 : #  include "cpl_win32ce_api.h"
     530                 : #  define TLS_OUT_OF_INDEXES ((DWORD)0xFFFFFFFF)
     531                 : #endif
     532                 : 
     533                 : /************************************************************************/
     534                 : /*                             CPLGetNumCPUs()                          */
     535                 : /************************************************************************/
     536                 : 
     537                 : int CPLGetNumCPUs()
     538                 : {
     539                 :     SYSTEM_INFO info;
     540                 :     GetSystemInfo(&info);
     541                 :     DWORD dwNum = info.dwNumberOfProcessors;
     542                 :     if( dwNum < 1 )
     543                 :         return 1;
     544                 :     return (int)dwNum;
     545                 : }
     546                 : 
     547                 : /************************************************************************/
     548                 : /*                        CPLGetThreadingModel()                        */
     549                 : /************************************************************************/
     550                 : 
     551                 : const char *CPLGetThreadingModel()
     552                 : 
     553                 : {
     554                 :     return "win32";
     555                 : }
     556                 : 
     557                 : /************************************************************************/
     558                 : /*                           CPLCreateMutex()                           */
     559                 : /************************************************************************/
     560                 : 
     561                 : void *CPLCreateMutex()
     562                 : 
     563                 : {
     564                 : #ifdef USE_WIN32_MUTEX
     565                 :     HANDLE hMutex;
     566                 : 
     567                 :     hMutex = CreateMutex( NULL, TRUE, NULL );
     568                 : 
     569                 :     return (void *) hMutex;
     570                 : #else
     571                 :     CRITICAL_SECTION *pcs;
     572                 : 
     573                 :   /* Do not use CPLMalloc() since its debugging infrastructure */
     574                 :   /* can call the CPL*Mutex functions... */
     575                 :     pcs = (CRITICAL_SECTION *)malloc(sizeof(*pcs));
     576                 :     if( pcs )
     577                 :     {
     578                 :       InitializeCriticalSectionAndSpinCount(pcs, 4000);
     579                 :       EnterCriticalSection(pcs);
     580                 :     }
     581                 : 
     582                 :     return (void *) pcs;
     583                 : #endif
     584                 : }
     585                 : 
     586                 : /************************************************************************/
     587                 : /*                          CPLAcquireMutex()                           */
     588                 : /************************************************************************/
     589                 : 
     590                 : int CPLAcquireMutex( void *hMutexIn, double dfWaitInSeconds )
     591                 : 
     592                 : {
     593                 : #ifdef USE_WIN32_MUTEX
     594                 :     HANDLE hMutex = (HANDLE) hMutexIn;
     595                 :     DWORD  hr;
     596                 : 
     597                 :     hr = WaitForSingleObject( hMutex, (int) (dfWaitInSeconds * 1000) );
     598                 :     
     599                 :     return hr != WAIT_TIMEOUT;
     600                 : #else
     601                 :     CRITICAL_SECTION *pcs = (CRITICAL_SECTION *)hMutexIn;
     602                 :     BOOL ret;
     603                 : 
     604                 :     while( (ret = TryEnterCriticalSection(pcs)) == 0 && dfWaitInSeconds > 0.0 )
     605                 :     {
     606                 :         CPLSleep( MIN(dfWaitInSeconds,0.125) );
     607                 :         dfWaitInSeconds -= 0.125;
     608                 :     }
     609                 :     
     610                 :     return ret;
     611                 : #endif
     612                 : }
     613                 : 
     614                 : /************************************************************************/
     615                 : /*                          CPLReleaseMutex()                           */
     616                 : /************************************************************************/
     617                 : 
     618                 : void CPLReleaseMutex( void *hMutexIn )
     619                 : 
     620                 : {
     621                 : #ifdef USE_WIN32_MUTEX
     622                 :     HANDLE hMutex = (HANDLE) hMutexIn;
     623                 : 
     624                 :     ReleaseMutex( hMutex );
     625                 : #else
     626                 :     CRITICAL_SECTION *pcs = (CRITICAL_SECTION *)hMutexIn;
     627                 : 
     628                 :     LeaveCriticalSection(pcs);
     629                 : #endif
     630                 : }
     631                 : 
     632                 : /************************************************************************/
     633                 : /*                          CPLDestroyMutex()                           */
     634                 : /************************************************************************/
     635                 : 
     636                 : void CPLDestroyMutex( void *hMutexIn )
     637                 : 
     638                 : {
     639                 : #ifdef USE_WIN32_MUTEX
     640                 :     HANDLE hMutex = (HANDLE) hMutexIn;
     641                 : 
     642                 :     CloseHandle( hMutex );
     643                 : #else
     644                 :     CRITICAL_SECTION *pcs = (CRITICAL_SECTION *)hMutexIn;
     645                 : 
     646                 :     DeleteCriticalSection( pcs );
     647                 :     free( pcs );
     648                 : #endif
     649                 : }
     650                 : 
     651                 : /************************************************************************/
     652                 : /*                            CPLCreateCond()                           */
     653                 : /************************************************************************/
     654                 : 
     655                 : struct _WaiterItem
     656                 : {
     657                 :     HANDLE hEvent;
     658                 :     struct _WaiterItem* psNext;
     659                 : };
     660                 : typedef struct _WaiterItem WaiterItem;
     661                 : 
     662                 : typedef struct
     663                 : {
     664                 :     void        *hInternalMutex;
     665                 :     WaiterItem  *psWaiterList;
     666                 : } Win32Cond;
     667                 : 
     668                 : void  *CPLCreateCond()
     669                 : {
     670                 :     Win32Cond* psCond = (Win32Cond*) malloc(sizeof(Win32Cond));
     671                 :     if (psCond == NULL)
     672                 :         return NULL;
     673                 :     psCond->hInternalMutex = CPLCreateMutex();
     674                 :     if (psCond->hInternalMutex == NULL)
     675                 :     {
     676                 :         free(psCond);
     677                 :         return NULL;
     678                 :     }
     679                 :     CPLReleaseMutex(psCond->hInternalMutex);
     680                 :     psCond->psWaiterList = NULL;
     681                 :     return psCond;
     682                 : }
     683                 : 
     684                 : /************************************************************************/
     685                 : /*                            CPLCondWait()                             */
     686                 : /************************************************************************/
     687                 : 
     688                 : static void CPLTLSFreeEvent(void* pData)
     689                 : {
     690                 :     CloseHandle((HANDLE)pData);
     691                 : }
     692                 : 
     693                 : void  CPLCondWait( void *hCond, void* hClientMutex )
     694                 : {
     695                 :     Win32Cond* psCond = (Win32Cond*) hCond;
     696                 : 
     697                 :     HANDLE hEvent = (HANDLE) CPLGetTLS(CTLS_WIN32_COND);
     698                 :     if (hEvent == NULL)
     699                 :     {
     700                 :         hEvent = CreateEvent(NULL, /* security attributes */
     701                 :                              0,    /* manual reset = no */
     702                 :                              0,    /* initial state = unsignaled */
     703                 :                              NULL  /* no name */);
     704                 :         CPLAssert(hEvent != NULL);
     705                 : 
     706                 :         CPLSetTLSWithFreeFunc(CTLS_WIN32_COND, hEvent, CPLTLSFreeEvent);
     707                 :     }
     708                 : 
     709                 :     /* Insert the waiter into the waiter list of the condition */
     710                 :     CPLAcquireMutex(psCond->hInternalMutex, 1000.0);
     711                 : 
     712                 :     WaiterItem* psItem = (WaiterItem*)malloc(sizeof(WaiterItem));
     713                 :     CPLAssert(psItem != NULL);
     714                 : 
     715                 :     psItem->hEvent = hEvent;
     716                 :     psItem->psNext = psCond->psWaiterList;
     717                 : 
     718                 :     psCond->psWaiterList = psItem;
     719                 : 
     720                 :     CPLReleaseMutex(psCond->hInternalMutex);
     721                 : 
     722                 :     /* Release the client mutex before waiting for the event being signaled */
     723                 :     CPLReleaseMutex(hClientMutex);
     724                 : 
     725                 :     DWORD nRet = WaitForSingleObject(hEvent, INFINITE);
     726                 :     CPLAssert (nRet != WAIT_FAILED);
     727                 : 
     728                 :     /* Reacquire the client mutex */
     729                 :     CPLAcquireMutex(hClientMutex, 1000.0);
     730                 : }
     731                 : 
     732                 : /************************************************************************/
     733                 : /*                            CPLCondSignal()                           */
     734                 : /************************************************************************/
     735                 : 
     736                 : void  CPLCondSignal( void *hCond )
     737                 : {
     738                 :     Win32Cond* psCond = (Win32Cond*) hCond;
     739                 : 
     740                 :     /* Signal the first registered event, and remove it from the list */
     741                 :     CPLAcquireMutex(psCond->hInternalMutex, 1000.0);
     742                 : 
     743                 :     WaiterItem* psIter = psCond->psWaiterList;
     744                 :     if (psIter != NULL)
     745                 :     {
     746                 :         SetEvent(psIter->hEvent);
     747                 :         psCond->psWaiterList = psIter->psNext;
     748                 :         free(psIter);
     749                 :     }
     750                 : 
     751                 :     CPLReleaseMutex(psCond->hInternalMutex);
     752                 : }
     753                 : 
     754                 : /************************************************************************/
     755                 : /*                           CPLCondBroadcast()                         */
     756                 : /************************************************************************/
     757                 : 
     758                 : void  CPLCondBroadcast( void *hCond )
     759                 : {
     760                 :     Win32Cond* psCond = (Win32Cond*) hCond;
     761                 : 
     762                 :     /* Signal all the registered events, and remove them from the list */
     763                 :     CPLAcquireMutex(psCond->hInternalMutex, 1000.0);
     764                 : 
     765                 :     WaiterItem* psIter = psCond->psWaiterList;
     766                 :     while (psIter != NULL)
     767                 :     {
     768                 :         WaiterItem* psNext = psIter->psNext;
     769                 :         SetEvent(psIter->hEvent);
     770                 :         free(psIter);
     771                 :         psIter = psNext;
     772                 :     }
     773                 :     psCond->psWaiterList = NULL;
     774                 : 
     775                 :     CPLReleaseMutex(psCond->hInternalMutex);
     776                 : }
     777                 : 
     778                 : /************************************************************************/
     779                 : /*                            CPLDestroyCond()                          */
     780                 : /************************************************************************/
     781                 : 
     782                 : void  CPLDestroyCond( void *hCond )
     783                 : {
     784                 :     Win32Cond* psCond = (Win32Cond*) hCond;
     785                 :     CPLDestroyMutex(psCond->hInternalMutex);
     786                 :     psCond->hInternalMutex = NULL;
     787                 :     CPLAssert(psCond->psWaiterList == NULL);
     788                 :     free(psCond);
     789                 : }
     790                 : 
     791                 : /************************************************************************/
     792                 : /*                            CPLLockFile()                             */
     793                 : /************************************************************************/
     794                 : 
     795                 : void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
     796                 : 
     797                 : {
     798                 :     char      *pszLockFilename;
     799                 :     HANDLE    hLockFile;
     800                 :     
     801                 :     pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
     802                 :     sprintf( pszLockFilename, "%s.lock", pszPath );
     803                 : 
     804                 :     hLockFile = 
     805                 :         CreateFile( pszLockFilename, GENERIC_WRITE, 0, NULL,CREATE_NEW, 
     806                 :                     FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, NULL );
     807                 : 
     808                 :     while( GetLastError() == ERROR_ALREADY_EXISTS
     809                 :            && dfWaitInSeconds > 0.0 )
     810                 :     {
     811                 :         CloseHandle( hLockFile );
     812                 :         CPLSleep( MIN(dfWaitInSeconds,0.125) );
     813                 :         dfWaitInSeconds -= 0.125;
     814                 : 
     815                 :         hLockFile = 
     816                 :             CreateFile( pszLockFilename, GENERIC_WRITE, 0, NULL, CREATE_NEW, 
     817                 :                         FILE_ATTRIBUTE_NORMAL|FILE_FLAG_DELETE_ON_CLOSE, 
     818                 :                         NULL );
     819                 :     }
     820                 : 
     821                 :     CPLFree( pszLockFilename );
     822                 : 
     823                 :     if( hLockFile == INVALID_HANDLE_VALUE )
     824                 :         return NULL;
     825                 : 
     826                 :     if( GetLastError() == ERROR_ALREADY_EXISTS )
     827                 :     {
     828                 :         CloseHandle( hLockFile );
     829                 :         return NULL;
     830                 :     }
     831                 : 
     832                 :     return (void *) hLockFile;
     833                 : }
     834                 : 
     835                 : /************************************************************************/
     836                 : /*                           CPLUnlockFile()                            */
     837                 : /************************************************************************/
     838                 : 
     839                 : void CPLUnlockFile( void *hLock )
     840                 : 
     841                 : {
     842                 :     HANDLE    hLockFile = (HANDLE) hLock;
     843                 : 
     844                 :     CloseHandle( hLockFile );
     845                 : }
     846                 : 
     847                 : /************************************************************************/
     848                 : /*                             CPLGetPID()                              */
     849                 : /************************************************************************/
     850                 : 
     851                 : GIntBig CPLGetPID()
     852                 : 
     853                 : {
     854                 :     return (GIntBig) GetCurrentThreadId();
     855                 : }
     856                 : 
     857                 : /************************************************************************/
     858                 : /*                       CPLStdCallThreadJacket()                       */
     859                 : /************************************************************************/
     860                 : 
     861                 : typedef struct {
     862                 :     void *pAppData;
     863                 :     CPLThreadFunc pfnMain;
     864                 :     HANDLE hThread;
     865                 : } CPLStdCallThreadInfo;
     866                 : 
     867                 : static DWORD WINAPI CPLStdCallThreadJacket( void *pData )
     868                 : 
     869                 : {
     870                 :     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) pData;
     871                 : 
     872                 :     psInfo->pfnMain( psInfo->pAppData );
     873                 : 
     874                 :     if (psInfo->hThread == NULL)
     875                 :         CPLFree( psInfo ); /* Only for detached threads */
     876                 : 
     877                 :     CPLCleanupTLS();
     878                 : 
     879                 :     return 0;
     880                 : }
     881                 : 
     882                 : /************************************************************************/
     883                 : /*                          CPLCreateThread()                           */
     884                 : /*                                                                      */
     885                 : /*      The WIN32 CreateThread() call requires an entry point that      */
     886                 : /*      has __stdcall conventions, so we provide a jacket function      */
     887                 : /*      to supply that.                                                 */
     888                 : /************************************************************************/
     889                 : 
     890                 : int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
     891                 : 
     892                 : {
     893                 :     HANDLE hThread;
     894                 :     DWORD  nThreadId;
     895                 :     CPLStdCallThreadInfo *psInfo;
     896                 : 
     897                 :     psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
     898                 :     psInfo->pAppData = pThreadArg;
     899                 :     psInfo->pfnMain = pfnMain;
     900                 :     psInfo->hThread = NULL;
     901                 : 
     902                 :     hThread = CreateThread( NULL, 0, CPLStdCallThreadJacket, psInfo, 
     903                 :                             0, &nThreadId );
     904                 : 
     905                 :     if( hThread == NULL )
     906                 :         return -1;
     907                 : 
     908                 :     CloseHandle( hThread );
     909                 : 
     910                 :     return nThreadId;
     911                 : }
     912                 : 
     913                 : /************************************************************************/
     914                 : /*                      CPLCreateJoinableThread()                       */
     915                 : /************************************************************************/
     916                 : 
     917                 : void* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pThreadArg )
     918                 : 
     919                 : {
     920                 :     HANDLE hThread;
     921                 :     DWORD  nThreadId;
     922                 :     CPLStdCallThreadInfo *psInfo;
     923                 : 
     924                 :     psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
     925                 :     psInfo->pAppData = pThreadArg;
     926                 :     psInfo->pfnMain = pfnMain;
     927                 : 
     928                 :     hThread = CreateThread( NULL, 0, CPLStdCallThreadJacket, psInfo, 
     929                 :                             0, &nThreadId );
     930                 : 
     931                 :     if( hThread == NULL )
     932                 :         return NULL;
     933                 :         
     934                 :     psInfo->hThread = hThread;
     935                 :     return psInfo;
     936                 : }
     937                 : 
     938                 : /************************************************************************/
     939                 : /*                          CPLJoinThread()                             */
     940                 : /************************************************************************/
     941                 : 
     942                 : void CPLJoinThread(void* hJoinableThread)
     943                 : {
     944                 :     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) hJoinableThread;
     945                 :     
     946                 :     WaitForSingleObject(psInfo->hThread, INFINITE);
     947                 :     CloseHandle( psInfo->hThread );
     948                 :     CPLFree( psInfo );
     949                 : }
     950                 : 
     951                 : /************************************************************************/
     952                 : /*                              CPLSleep()                              */
     953                 : /************************************************************************/
     954                 : 
     955                 : void CPLSleep( double dfWaitInSeconds )
     956                 : 
     957                 : {
     958                 :     Sleep( (DWORD) (dfWaitInSeconds * 1000.0) );
     959                 : }
     960                 : 
     961                 : static int           bTLSKeySetup = FALSE;
     962                 : static DWORD         nTLSKey;
     963                 : 
     964                 : /************************************************************************/
     965                 : /*                           CPLGetTLSList()                            */
     966                 : /************************************************************************/
     967                 : 
     968                 : static void **CPLGetTLSList()
     969                 : 
     970                 : {
     971                 :     void **papTLSList;
     972                 : 
     973                 :     if( !bTLSKeySetup )
     974                 :     {
     975                 :         nTLSKey = TlsAlloc();
     976                 :         if( nTLSKey == TLS_OUT_OF_INDEXES )
     977                 :         {
     978                 :             CPLError( CE_Fatal, CPLE_AppDefined, 
     979                 :                       "TlsAlloc() failed!" );
     980                 :         }
     981                 :         bTLSKeySetup = TRUE;
     982                 :     }
     983                 : 
     984                 :     papTLSList = (void **) TlsGetValue( nTLSKey );
     985                 :     if( papTLSList == NULL )
     986                 :     {
     987                 :         papTLSList = (void **) CPLCalloc(sizeof(void*),CTLS_MAX*2);
     988                 :         if( TlsSetValue( nTLSKey, papTLSList ) == 0 )
     989                 :         {
     990                 :             CPLError( CE_Fatal, CPLE_AppDefined, 
     991                 :                       "TlsSetValue() failed!" );
     992                 :         }
     993                 :     }
     994                 : 
     995                 :     return papTLSList;
     996                 : }
     997                 : 
     998                 : /************************************************************************/
     999                 : /*                           CPLCleanupTLS()                            */
    1000                 : /************************************************************************/
    1001                 : 
    1002                 : void CPLCleanupTLS()
    1003                 : 
    1004                 : {
    1005                 :     void **papTLSList;
    1006                 : 
    1007                 :     if( !bTLSKeySetup )
    1008                 :         return;
    1009                 : 
    1010                 :     papTLSList = (void **) TlsGetValue( nTLSKey );
    1011                 :     if( papTLSList == NULL )
    1012                 :         return;
    1013                 : 
    1014                 :     TlsSetValue( nTLSKey, NULL );
    1015                 : 
    1016                 :     CPLCleanupTLSList( papTLSList );
    1017                 : }
    1018                 : 
    1019                 : /* endif CPL_MULTIPROC_WIN32 */
    1020                 : 
    1021                 : #elif defined(CPL_MULTIPROC_PTHREAD)
    1022                 : 
    1023                 : #include <pthread.h>
    1024                 : #include <time.h>
    1025                 : #include <unistd.h>
    1026                 : 
    1027                 :   /************************************************************************/
    1028                 :   /* ==================================================================== */
    1029                 :   /*                        CPL_MULTIPROC_PTHREAD                         */
    1030                 :   /*                                                                      */
    1031                 :   /*    PTHREAD Implementation of multiprocessing functions.              */
    1032                 :   /* ==================================================================== */
    1033                 :   /************************************************************************/
    1034                 : 
    1035                 : /************************************************************************/
    1036                 : /*                             CPLGetNumCPUs()                          */
    1037                 : /************************************************************************/
    1038                 : 
    1039              47 : int CPLGetNumCPUs()
    1040                 : {
    1041                 : #ifdef _SC_NPROCESSORS_ONLN
    1042              47 :     return (int)sysconf(_SC_NPROCESSORS_ONLN);
    1043                 : #else
    1044                 :     return 1;
    1045                 : #endif
    1046                 : }
    1047                 : 
    1048                 : /************************************************************************/
    1049                 : /*                      CPLCreateOrAcquireMutex()                       */
    1050                 : /************************************************************************/
    1051                 : 
    1052        15794988 : int CPLCreateOrAcquireMutex( void **phMutex, double dfWaitInSeconds )
    1053                 : 
    1054                 : {
    1055        15794988 :     int bSuccess = FALSE;
    1056                 :     static pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
    1057                 : 
    1058        15794988 :     pthread_mutex_lock(&global_mutex);
    1059        15794988 :     if( *phMutex == NULL )
    1060                 :     {
    1061            8390 :         *phMutex = CPLCreateMutex();
    1062            8390 :         bSuccess = *phMutex != NULL;
    1063            8390 :         pthread_mutex_unlock(&global_mutex);
    1064                 :     }
    1065                 :     else
    1066                 :     {
    1067        15786598 :         pthread_mutex_unlock(&global_mutex);
    1068                 : 
    1069        15786598 :         bSuccess = CPLAcquireMutex( *phMutex, dfWaitInSeconds );
    1070                 :     }
    1071                 : 
    1072        15794988 :     return bSuccess;
    1073                 : }
    1074                 : 
    1075                 : /************************************************************************/
    1076                 : /*                        CPLGetThreadingModel()                        */
    1077                 : /************************************************************************/
    1078                 : 
    1079               0 : const char *CPLGetThreadingModel()
    1080                 : 
    1081                 : {
    1082               0 :     return "pthread";
    1083                 : }
    1084                 : 
    1085                 : /************************************************************************/
    1086                 : /*                           CPLCreateMutex()                           */
    1087                 : /************************************************************************/
    1088                 : 
    1089            9287 : void *CPLCreateMutex()
    1090                 : 
    1091                 : {
    1092                 :     pthread_mutex_t *hMutex;
    1093                 : 
    1094            9287 :     hMutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
    1095            9287 :     if (hMutex == NULL)
    1096               0 :         return NULL;
    1097                 : 
    1098                 : #if defined(PTHREAD_MUTEX_RECURSIVE) || defined(HAVE_PTHREAD_MUTEX_RECURSIVE)
    1099                 :     {
    1100                 :         pthread_mutexattr_t  attr;
    1101            9287 :         pthread_mutexattr_init( &attr );
    1102            9287 :         pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE );
    1103            9287 :         pthread_mutex_init( hMutex, &attr );
    1104                 :     }
    1105                 : /* BSDs have PTHREAD_MUTEX_RECURSIVE as an enum, not a define. */
    1106                 : /* But they have #define MUTEX_TYPE_COUNTING_FAST PTHREAD_MUTEX_RECURSIVE */
    1107                 : #elif defined(MUTEX_TYPE_COUNTING_FAST)
    1108                 :     {
    1109                 :         pthread_mutexattr_t  attr;
    1110                 :         pthread_mutexattr_init( &attr );
    1111                 :         pthread_mutexattr_settype( &attr, MUTEX_TYPE_COUNTING_FAST );
    1112                 :         pthread_mutex_init( hMutex, &attr );
    1113                 :     }
    1114                 : #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP)
    1115                 :     pthread_mutex_t tmp_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
    1116                 :     *hMutex = tmp_mutex;
    1117                 : #else
    1118                 : #error "Recursive mutexes apparently unsupported, configure --without-threads" 
    1119                 : #endif
    1120                 : 
    1121                 :     // mutexes are implicitly acquired when created.
    1122            9287 :     CPLAcquireMutex( hMutex, 0.0 );
    1123                 : 
    1124            9287 :     return (void *) hMutex;
    1125                 : }
    1126                 : 
    1127                 : /************************************************************************/
    1128                 : /*                          CPLAcquireMutex()                           */
    1129                 : /************************************************************************/
    1130                 : 
    1131        15841325 : int CPLAcquireMutex( void *hMutexIn, double dfWaitInSeconds )
    1132                 : 
    1133                 : {
    1134                 :     int err;
    1135                 : 
    1136                 :     /* we need to add timeout support */
    1137        15841325 :     err =  pthread_mutex_lock( (pthread_mutex_t *) hMutexIn );
    1138                 :     
    1139        15841326 :     if( err != 0 )
    1140                 :     {
    1141               0 :         if( err == EDEADLK )
    1142               0 :             fprintf(stderr, "CPLAcquireMutex: Error = %d/EDEADLK", err );
    1143                 :         else
    1144               0 :             fprintf(stderr, "CPLAcquireMutex: Error = %d", err );
    1145                 : 
    1146               0 :         return FALSE;
    1147                 :     }
    1148                 : 
    1149        15841326 :     return TRUE;
    1150                 : }
    1151                 : 
    1152                 : /************************************************************************/
    1153                 : /*                          CPLReleaseMutex()                           */
    1154                 : /************************************************************************/
    1155                 : 
    1156        15841326 : void CPLReleaseMutex( void *hMutexIn )
    1157                 : 
    1158                 : {
    1159        15841326 :     pthread_mutex_unlock( (pthread_mutex_t *) hMutexIn );
    1160        15841324 : }
    1161                 : 
    1162                 : /************************************************************************/
    1163                 : /*                          CPLDestroyMutex()                           */
    1164                 : /************************************************************************/
    1165                 : 
    1166            5592 : void CPLDestroyMutex( void *hMutexIn )
    1167                 : 
    1168                 : {
    1169            5592 :     pthread_mutex_destroy( (pthread_mutex_t *) hMutexIn );
    1170            5592 :     free( hMutexIn );
    1171            5592 : }
    1172                 : 
    1173                 : /************************************************************************/
    1174                 : /*                            CPLCreateCond()                           */
    1175                 : /************************************************************************/
    1176                 : 
    1177             112 : void  *CPLCreateCond()
    1178                 : {
    1179             112 :     pthread_cond_t* pCond = (pthread_cond_t* )malloc(sizeof(pthread_cond_t));
    1180             112 :     if (pCond)
    1181             112 :         pthread_cond_init(pCond, NULL);
    1182             112 :     return pCond;
    1183                 : }
    1184                 : 
    1185                 : /************************************************************************/
    1186                 : /*                            CPLCondWait()                             */
    1187                 : /************************************************************************/
    1188                 : 
    1189            4259 : void  CPLCondWait( void *hCond, void* hMutex )
    1190                 : {
    1191            4259 :     pthread_cond_t* pCond = (pthread_cond_t* )hCond;
    1192            4259 :     pthread_mutex_t * pMutex = (pthread_mutex_t *)hMutex;
    1193            4259 :     pthread_cond_wait(pCond,  pMutex);
    1194            4259 : }
    1195                 : 
    1196                 : /************************************************************************/
    1197                 : /*                            CPLCondSignal()                           */
    1198                 : /************************************************************************/
    1199                 : 
    1200           12826 : void  CPLCondSignal( void *hCond )
    1201                 : {
    1202           12826 :     pthread_cond_t* pCond = (pthread_cond_t* )hCond;
    1203           12826 :     pthread_cond_signal(pCond);
    1204           12826 : }
    1205                 : 
    1206                 : /************************************************************************/
    1207                 : /*                           CPLCondBroadcast()                         */
    1208                 : /************************************************************************/
    1209                 : 
    1210               0 : void  CPLCondBroadcast( void *hCond )
    1211                 : {
    1212               0 :     pthread_cond_t* pCond = (pthread_cond_t* )hCond;
    1213               0 :     pthread_cond_broadcast(pCond);
    1214               0 : }
    1215                 : 
    1216                 : /************************************************************************/
    1217                 : /*                            CPLDestroyCond()                          */
    1218                 : /************************************************************************/
    1219                 : 
    1220             112 : void  CPLDestroyCond( void *hCond )
    1221                 : {
    1222             112 :     pthread_cond_t* pCond = (pthread_cond_t* )hCond;
    1223             112 :     pthread_cond_destroy(pCond);
    1224             112 :     free(hCond);
    1225             112 : }
    1226                 : 
    1227                 : /************************************************************************/
    1228                 : /*                            CPLLockFile()                             */
    1229                 : /*                                                                      */
    1230                 : /*      This is really a stub implementation, see first                 */
    1231                 : /*      CPLLockFile() for caveats.                                      */
    1232                 : /************************************************************************/
    1233                 : 
    1234               2 : void *CPLLockFile( const char *pszPath, double dfWaitInSeconds )
    1235                 : 
    1236                 : {
    1237                 :     FILE      *fpLock;
    1238                 :     char      *pszLockFilename;
    1239                 :     
    1240                 : /* -------------------------------------------------------------------- */
    1241                 : /*      We use a lock file with a name derived from the file we want    */
    1242                 : /*      to lock to represent the file being locked.  Note that for      */
    1243                 : /*      the stub implementation the target file does not even need      */
    1244                 : /*      to exist to be locked.                                          */
    1245                 : /* -------------------------------------------------------------------- */
    1246               2 :     pszLockFilename = (char *) CPLMalloc(strlen(pszPath) + 30);
    1247               2 :     sprintf( pszLockFilename, "%s.lock", pszPath );
    1248                 : 
    1249               2 :     fpLock = fopen( pszLockFilename, "r" );
    1250               4 :     while( fpLock != NULL && dfWaitInSeconds > 0.0 )
    1251                 :     {
    1252               0 :         fclose( fpLock );
    1253               0 :         CPLSleep( MIN(dfWaitInSeconds,0.5) );
    1254               0 :         dfWaitInSeconds -= 0.5;
    1255                 : 
    1256               0 :         fpLock = fopen( pszLockFilename, "r" );
    1257                 :     }
    1258                 :         
    1259               2 :     if( fpLock != NULL )
    1260                 :     {
    1261               0 :         fclose( fpLock );
    1262               0 :         CPLFree( pszLockFilename );
    1263               0 :         return NULL;
    1264                 :     }
    1265                 : 
    1266               2 :     fpLock = fopen( pszLockFilename, "w" );
    1267                 : 
    1268               2 :     if( fpLock == NULL )
    1269                 :     {
    1270               0 :         CPLFree( pszLockFilename );
    1271               0 :         return NULL;
    1272                 :     }
    1273                 : 
    1274               2 :     fwrite( "held\n", 1, 5, fpLock );
    1275               2 :     fclose( fpLock );
    1276                 : 
    1277               2 :     return pszLockFilename;
    1278                 : }
    1279                 : 
    1280                 : /************************************************************************/
    1281                 : /*                           CPLUnlockFile()                            */
    1282                 : /************************************************************************/
    1283                 : 
    1284               2 : void CPLUnlockFile( void *hLock )
    1285                 : 
    1286                 : {
    1287               2 :     char *pszLockFilename = (char *) hLock;
    1288                 : 
    1289               2 :     if( hLock == NULL )
    1290               0 :         return;
    1291                 :     
    1292               2 :     VSIUnlink( pszLockFilename );
    1293                 :     
    1294               2 :     CPLFree( pszLockFilename );
    1295                 : }
    1296                 : 
    1297                 : /************************************************************************/
    1298                 : /*                             CPLGetPID()                              */
    1299                 : /************************************************************************/
    1300                 : 
    1301           44921 : GIntBig CPLGetPID()
    1302                 : 
    1303                 : {
    1304           44921 :     return (GIntBig) pthread_self();
    1305                 : }
    1306                 : 
    1307                 : /************************************************************************/
    1308                 : /*                       CPLStdCallThreadJacket()                       */
    1309                 : /************************************************************************/
    1310                 : 
    1311                 : typedef struct {
    1312                 :     void *pAppData;
    1313                 :     CPLThreadFunc pfnMain;
    1314                 :     pthread_t hThread;
    1315                 :     int bJoinable;
    1316                 : } CPLStdCallThreadInfo;
    1317                 : 
    1318             178 : static void *CPLStdCallThreadJacket( void *pData )
    1319                 : 
    1320                 : {
    1321             178 :     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo *) pData;
    1322                 : 
    1323             178 :     psInfo->pfnMain( psInfo->pAppData );
    1324                 : 
    1325             178 :     if (!psInfo->bJoinable)
    1326               0 :         CPLFree( psInfo );
    1327                 : 
    1328             178 :     return NULL;
    1329                 : }
    1330                 : 
    1331                 : /************************************************************************/
    1332                 : /*                          CPLCreateThread()                           */
    1333                 : /*                                                                      */
    1334                 : /*      The WIN32 CreateThread() call requires an entry point that      */
    1335                 : /*      has __stdcall conventions, so we provide a jacket function      */
    1336                 : /*      to supply that.                                                 */
    1337                 : /************************************************************************/
    1338                 : 
    1339               0 : int CPLCreateThread( CPLThreadFunc pfnMain, void *pThreadArg )
    1340                 : 
    1341                 : {
    1342                 : 
    1343                 :     CPLStdCallThreadInfo *psInfo;
    1344                 :     pthread_attr_t hThreadAttr;
    1345                 : 
    1346               0 :     psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
    1347               0 :     psInfo->pAppData = pThreadArg;
    1348               0 :     psInfo->pfnMain = pfnMain;
    1349               0 :     psInfo->bJoinable = FALSE;
    1350                 : 
    1351               0 :     pthread_attr_init( &hThreadAttr );
    1352               0 :     pthread_attr_setdetachstate( &hThreadAttr, PTHREAD_CREATE_DETACHED );
    1353               0 :     if( pthread_create( &(psInfo->hThread), &hThreadAttr, 
    1354                 :                         CPLStdCallThreadJacket, (void *) psInfo ) != 0 )
    1355                 :     {
    1356               0 :         CPLFree( psInfo );
    1357               0 :         return -1;
    1358                 :     }
    1359                 : 
    1360               0 :     return 1; /* can we return the actual thread pid? */
    1361                 : }
    1362                 : 
    1363                 : /************************************************************************/
    1364                 : /*                      CPLCreateJoinableThread()                       */
    1365                 : /************************************************************************/
    1366                 : 
    1367             178 : void* CPLCreateJoinableThread( CPLThreadFunc pfnMain, void *pThreadArg )
    1368                 : 
    1369                 : {
    1370                 :     CPLStdCallThreadInfo *psInfo;
    1371                 :     pthread_attr_t hThreadAttr;
    1372                 : 
    1373             178 :     psInfo = (CPLStdCallThreadInfo*) CPLCalloc(sizeof(CPLStdCallThreadInfo),1);
    1374             178 :     psInfo->pAppData = pThreadArg;
    1375             178 :     psInfo->pfnMain = pfnMain;
    1376             178 :     psInfo->bJoinable = TRUE;
    1377                 : 
    1378             178 :     pthread_attr_init( &hThreadAttr );
    1379             178 :     pthread_attr_setdetachstate( &hThreadAttr, PTHREAD_CREATE_JOINABLE );
    1380             178 :     if( pthread_create( &(psInfo->hThread), &hThreadAttr,
    1381                 :                         CPLStdCallThreadJacket, (void *) psInfo ) != 0 )
    1382                 :     {
    1383               0 :         CPLFree( psInfo );
    1384               0 :         return NULL;
    1385                 :     }
    1386                 : 
    1387             178 :     return psInfo;
    1388                 : }
    1389                 : 
    1390                 : /************************************************************************/
    1391                 : /*                          CPLJoinThread()                             */
    1392                 : /************************************************************************/
    1393                 : 
    1394             178 : void CPLJoinThread(void* hJoinableThread)
    1395                 : {
    1396             178 :     CPLStdCallThreadInfo *psInfo = (CPLStdCallThreadInfo*) hJoinableThread;
    1397                 : 
    1398                 :     void* status;
    1399             178 :     pthread_join( psInfo->hThread, &status);
    1400                 : 
    1401             178 :     CPLFree(psInfo);
    1402             178 : }
    1403                 : 
    1404                 : /************************************************************************/
    1405                 : /*                              CPLSleep()                              */
    1406                 : /************************************************************************/
    1407                 : 
    1408               0 : void CPLSleep( double dfWaitInSeconds )
    1409                 : 
    1410                 : {
    1411                 :     struct timespec sRequest, sRemain;
    1412                 : 
    1413               0 :     sRequest.tv_sec = (int) floor(dfWaitInSeconds);
    1414               0 :     sRequest.tv_nsec = (int) ((dfWaitInSeconds - sRequest.tv_sec)*1000000000);
    1415               0 :     nanosleep( &sRequest, &sRemain );
    1416               0 : }
    1417                 : 
    1418                 : static pthread_key_t  oTLSKey;
    1419                 : static pthread_once_t oTLSKeySetup = PTHREAD_ONCE_INIT;
    1420                 : 
    1421                 : /************************************************************************/
    1422                 : /*                             CPLMake_key()                            */
    1423                 : /************************************************************************/
    1424                 : 
    1425             713 : static void CPLMake_key()
    1426                 : 
    1427                 : {
    1428             713 :     if( pthread_key_create( &oTLSKey, (void (*)(void*)) CPLCleanupTLSList ) != 0 )
    1429                 :     {
    1430               0 :         CPLError( CE_Fatal, CPLE_AppDefined, "pthread_key_create() failed!" );
    1431                 :     }
    1432             713 : }
    1433                 : 
    1434                 : /************************************************************************/
    1435                 : /*                             CPLCleanupTLS()                          */
    1436                 : /************************************************************************/
    1437                 : 
    1438            1052 : void CPLCleanupTLS()
    1439                 : 
    1440                 : {
    1441                 :     void **papTLSList;
    1442                 : 
    1443            1052 :     papTLSList = (void **) pthread_getspecific( oTLSKey );
    1444            1052 :     if( papTLSList == NULL )
    1445              19 :         return;
    1446                 : 
    1447            1033 :     pthread_setspecific( oTLSKey, NULL );
    1448                 : 
    1449            1033 :     CPLCleanupTLSList( papTLSList );
    1450                 : }
    1451                 : 
    1452                 : /************************************************************************/
    1453                 : /*                           CPLGetTLSList()                            */
    1454                 : /************************************************************************/
    1455                 : 
    1456        38470958 : static void **CPLGetTLSList()
    1457                 : 
    1458                 : {
    1459                 :     void **papTLSList;
    1460                 : 
    1461        38470958 :     if ( pthread_once(&oTLSKeySetup, CPLMake_key) != 0 )
    1462                 :     {
    1463                 :         CPLError( CE_Fatal, CPLE_AppDefined,
    1464               0 :             "pthread_once() failed!" );
    1465                 :     }
    1466                 : 
    1467        38470957 :     papTLSList = (void **) pthread_getspecific( oTLSKey );
    1468        38470958 :     if( papTLSList == NULL )
    1469                 :     {
    1470            1128 :         papTLSList = (void **) CPLCalloc(sizeof(void*),CTLS_MAX*2);
    1471            1128 :         if( pthread_setspecific( oTLSKey, papTLSList ) != 0 )
    1472                 :         {
    1473                 :             CPLError( CE_Fatal, CPLE_AppDefined,
    1474               0 :                 "pthread_setspecific() failed!" );
    1475                 :         }
    1476                 :     }
    1477                 : 
    1478        38470958 :     return papTLSList;
    1479                 : }
    1480                 : 
    1481                 : #endif /* def CPL_MULTIPROC_PTHREAD */
    1482                 : 
    1483                 : /************************************************************************/
    1484                 : /*                             CPLGetTLS()                              */
    1485                 : /************************************************************************/
    1486                 : 
    1487        38461458 : void *CPLGetTLS( int nIndex )
    1488                 : 
    1489                 : {
    1490        38461458 :     void** papTLSList = CPLGetTLSList();
    1491                 : 
    1492        38461459 :     CPLAssert( nIndex >= 0 && nIndex < CTLS_MAX );
    1493                 : 
    1494        38461459 :     return papTLSList[nIndex];
    1495                 : }
    1496                 : 
    1497                 : /************************************************************************/
    1498                 : /*                             CPLSetTLS()                              */
    1499                 : /************************************************************************/
    1500                 : 
    1501            8170 : void CPLSetTLS( int nIndex, void *pData, int bFreeOnExit )
    1502                 : 
    1503                 : {
    1504            8170 :     CPLSetTLSWithFreeFunc(nIndex, pData, (bFreeOnExit) ? CPLFree : NULL);
    1505            8170 : }
    1506                 : 
    1507                 : /************************************************************************/
    1508                 : /*                      CPLSetTLSWithFreeFunc()                         */
    1509                 : /************************************************************************/
    1510                 : 
    1511                 : /* Warning : the CPLTLSFreeFunc must not in any case directly or indirectly */
    1512                 : /* use or fetch any TLS data, or a terminating thread will hang ! */
    1513            9499 : void CPLSetTLSWithFreeFunc( int nIndex, void *pData, CPLTLSFreeFunc pfnFree )
    1514                 : 
    1515                 : {
    1516            9499 :     void **papTLSList = CPLGetTLSList();
    1517                 : 
    1518            9499 :     CPLAssert( nIndex >= 0 && nIndex < CTLS_MAX );
    1519                 : 
    1520            9499 :     papTLSList[nIndex] = pData;
    1521            9499 :     papTLSList[CTLS_MAX + nIndex] = (void*) pfnFree;
    1522            9499 : }

Generated by: LCOV version 1.7