LCOV - code coverage report
Current view: directory - port - cpl_multiproc.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 129 89 69.0 %
Date: 2010-01-09 Functions: 19 16 84.2 %

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

Generated by: LCOV version 1.7