LCOV - code coverage report
Current view: top level - autotest/cpp - testthreadcond.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 59 61 96.7 %
Date: 2024-05-14 13:00:50 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  * $Id$
       3             :  *
       4             :  * Project:  GDAL Core
       5             :  * Purpose:  Test thread API
       6             :  * Author:   Even Rouault, <even dot rouault at spatialys.com>
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2012, Even Rouault <even dot rouault at spatialys.com>
      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
      22             :  * OR 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 DEBUG
      31             : #define DEBUG
      32             : #endif
      33             : 
      34             : #include "cpl_multiproc.h"
      35             : #include "cpl_string.h"
      36             : 
      37             : #include "gtest_include.h"
      38             : 
      39             : namespace
      40             : {
      41             : 
      42             : // ---------------------------------------------------------------------------
      43             : 
      44             : CPLCond *hCond = nullptr;
      45             : CPLCond *hCondJobFinished = nullptr;
      46             : CPLMutex *hClientMutex = nullptr;
      47             : 
      48             : struct _JobItem
      49             : {
      50             :     int nJobNumber;
      51             :     struct _JobItem *psNext;
      52             : };
      53             : typedef struct _JobItem JobItem;
      54             : 
      55             : JobItem *psJobList = nullptr;
      56             : int nJobListSize = 0;
      57             : int nThreadTotal = 0;
      58             : int bProducedFinished = 0;
      59             : int bVerbose = FALSE;
      60             : 
      61           1 : static void ProducerThread(void * /* unused */)
      62             : {
      63             :     int i;
      64           1 :     int jobNumber = 0;
      65             :     JobItem *psItem;
      66             : 
      67         109 :     while (jobNumber < 1000)
      68             :     {
      69         108 :         CPLAcquireMutex(hClientMutex, 1000.0);
      70             : 
      71        1110 :         for (i = 0; i < nThreadTotal; i++)
      72             :         {
      73        1002 :             jobNumber++;
      74        1002 :             nJobListSize++;
      75        1002 :             psItem = (JobItem *)malloc(sizeof(JobItem));
      76        1002 :             psItem->nJobNumber = jobNumber;
      77        1002 :             psItem->psNext = psJobList;
      78        1002 :             psJobList = psItem;
      79             :         }
      80             : 
      81         108 :         CPLCondBroadcast(hCond);
      82             : 
      83         197 :         while (nJobListSize > nThreadTotal)
      84             :         {
      85          89 :             CPLCondWait(hCondJobFinished, hClientMutex);
      86             :         }
      87         108 :         CPLReleaseMutex(hClientMutex);
      88             :     }
      89             : 
      90           1 :     CPLAcquireMutex(hClientMutex, 1000.0);
      91           1 :     bProducedFinished = 1;
      92           1 :     CPLCondBroadcast(hCond);
      93           1 :     CPLReleaseMutex(hClientMutex);
      94           1 : }
      95             : 
      96          10 : static void ConsumerThread(void *pIndex)
      97             : {
      98             :     int nJobNumber;
      99             :     int nThreadIndex;
     100             :     JobItem *psNext;
     101             : 
     102          10 :     nThreadIndex = *(int *)pIndex;
     103          10 :     free(pIndex);
     104             : 
     105          10 :     if (bVerbose)
     106           0 :         printf("Thread %d created\n", nThreadIndex);
     107             : 
     108          10 :     nThreadTotal++;
     109             : 
     110             :     while (TRUE)
     111             :     {
     112        1000 :         CPLAcquireMutex(hClientMutex, 1000.0);
     113        1432 :         while (psJobList == nullptr && !bProducedFinished)
     114         428 :             CPLCondWait(hCond, hClientMutex);
     115        1004 :         if (bProducedFinished)
     116             :         {
     117          10 :             CPLReleaseMutex(hClientMutex);
     118          10 :             break;
     119             :         }
     120             : 
     121         994 :         nJobNumber = psJobList->nJobNumber;
     122         994 :         psNext = psJobList->psNext;
     123         994 :         free(psJobList);
     124         994 :         psJobList = psNext;
     125         994 :         CPLReleaseMutex(hClientMutex);
     126             : 
     127         989 :         if (bVerbose)
     128           0 :             printf("Thread %d consumed job %d\n", nThreadIndex, nJobNumber);
     129             : 
     130         989 :         CPLAcquireMutex(hClientMutex, 1000.0);
     131         994 :         nJobListSize--;
     132         994 :         CPLCondSignal(hCondJobFinished);
     133         994 :         CPLReleaseMutex(hClientMutex);
     134             :     }
     135          10 : }
     136             : 
     137           4 : TEST(testthreadcond, test)
     138             : {
     139             :     int i;
     140             :     CPLJoinableThread *apThreads[10];
     141             : 
     142           1 :     bVerbose = CPLTestBool(CPLGetConfigOption("VERBOSE", "NO"));
     143             : 
     144           1 :     hCond = CPLCreateCond();
     145           1 :     hCondJobFinished = CPLCreateCond();
     146             : 
     147           1 :     hClientMutex = CPLCreateMutex();
     148           1 :     CPLReleaseMutex(hClientMutex);
     149             : 
     150           1 :     CPLCreateThread(ProducerThread, nullptr);
     151             : 
     152          11 :     for (i = 0; i < 10; i++)
     153             :     {
     154          10 :         int *pi = (int *)malloc(sizeof(int));
     155          10 :         *pi = i;
     156          10 :         apThreads[i] = CPLCreateJoinableThread(ConsumerThread, pi);
     157             :     }
     158             : 
     159          11 :     for (i = 0; i < 10; i++)
     160             :     {
     161          10 :         CPLJoinThread(apThreads[i]);
     162             :     }
     163             : 
     164           1 :     CPLDestroyCond(hCond);
     165           1 :     CPLDestroyCond(hCondJobFinished);
     166           1 :     CPLDestroyMutex(hClientMutex);
     167           1 : }
     168             : 
     169             : }  // namespace

Generated by: LCOV version 1.14