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-11-21 22:18:42 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             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #ifndef DEBUG
      15             : #define DEBUG
      16             : #endif
      17             : 
      18             : #include "cpl_multiproc.h"
      19             : #include "cpl_string.h"
      20             : 
      21             : #include "gtest_include.h"
      22             : 
      23             : namespace
      24             : {
      25             : 
      26             : // ---------------------------------------------------------------------------
      27             : 
      28             : CPLCond *hCond = nullptr;
      29             : CPLCond *hCondJobFinished = nullptr;
      30             : CPLMutex *hClientMutex = nullptr;
      31             : 
      32             : struct _JobItem
      33             : {
      34             :     int nJobNumber;
      35             :     struct _JobItem *psNext;
      36             : };
      37             : typedef struct _JobItem JobItem;
      38             : 
      39             : JobItem *psJobList = nullptr;
      40             : int nJobListSize = 0;
      41             : int nThreadTotal = 0;
      42             : int bProducedFinished = 0;
      43             : int bVerbose = FALSE;
      44             : 
      45           1 : static void ProducerThread(void * /* unused */)
      46             : {
      47             :     int i;
      48           1 :     int jobNumber = 0;
      49             :     JobItem *psItem;
      50             : 
      51       69906 :     while (jobNumber < 1000)
      52             :     {
      53       69905 :         CPLAcquireMutex(hClientMutex, 1000.0);
      54             : 
      55       70905 :         for (i = 0; i < nThreadTotal; i++)
      56             :         {
      57        1000 :             jobNumber++;
      58        1000 :             nJobListSize++;
      59        1000 :             psItem = (JobItem *)malloc(sizeof(JobItem));
      60        1000 :             psItem->nJobNumber = jobNumber;
      61        1000 :             psItem->psNext = psJobList;
      62        1000 :             psJobList = psItem;
      63             :         }
      64             : 
      65       69905 :         CPLCondBroadcast(hCond);
      66             : 
      67       70087 :         while (nJobListSize > nThreadTotal)
      68             :         {
      69         182 :             CPLCondWait(hCondJobFinished, hClientMutex);
      70             :         }
      71       69905 :         CPLReleaseMutex(hClientMutex);
      72             :     }
      73             : 
      74           1 :     CPLAcquireMutex(hClientMutex, 1000.0);
      75           1 :     bProducedFinished = 1;
      76           1 :     CPLCondBroadcast(hCond);
      77           1 :     CPLReleaseMutex(hClientMutex);
      78           1 : }
      79             : 
      80          10 : static void ConsumerThread(void *pIndex)
      81             : {
      82             :     int nJobNumber;
      83             :     int nThreadIndex;
      84             :     JobItem *psNext;
      85             : 
      86          10 :     nThreadIndex = *(int *)pIndex;
      87          10 :     free(pIndex);
      88             : 
      89          10 :     if (bVerbose)
      90           0 :         printf("Thread %d created\n", nThreadIndex);
      91             : 
      92          10 :     nThreadTotal++;
      93             : 
      94             :     while (TRUE)
      95             :     {
      96        1009 :         CPLAcquireMutex(hClientMutex, 1000.0);
      97        1147 :         while (psJobList == nullptr && !bProducedFinished)
      98         137 :             CPLCondWait(hCond, hClientMutex);
      99        1010 :         if (bProducedFinished)
     100             :         {
     101          10 :             CPLReleaseMutex(hClientMutex);
     102          10 :             break;
     103             :         }
     104             : 
     105        1000 :         nJobNumber = psJobList->nJobNumber;
     106        1000 :         psNext = psJobList->psNext;
     107        1000 :         free(psJobList);
     108        1000 :         psJobList = psNext;
     109        1000 :         CPLReleaseMutex(hClientMutex);
     110             : 
     111         999 :         if (bVerbose)
     112           0 :             printf("Thread %d consumed job %d\n", nThreadIndex, nJobNumber);
     113             : 
     114         999 :         CPLAcquireMutex(hClientMutex, 1000.0);
     115        1000 :         nJobListSize--;
     116        1000 :         CPLCondSignal(hCondJobFinished);
     117        1000 :         CPLReleaseMutex(hClientMutex);
     118             :     }
     119          10 : }
     120             : 
     121           4 : TEST(testthreadcond, test)
     122             : {
     123             :     int i;
     124             :     CPLJoinableThread *apThreads[10];
     125             : 
     126           1 :     bVerbose = CPLTestBool(CPLGetConfigOption("VERBOSE", "NO"));
     127             : 
     128           1 :     hCond = CPLCreateCond();
     129           1 :     hCondJobFinished = CPLCreateCond();
     130             : 
     131           1 :     hClientMutex = CPLCreateMutex();
     132           1 :     CPLReleaseMutex(hClientMutex);
     133             : 
     134           1 :     CPLCreateThread(ProducerThread, nullptr);
     135             : 
     136          11 :     for (i = 0; i < 10; i++)
     137             :     {
     138          10 :         int *pi = (int *)malloc(sizeof(int));
     139          10 :         *pi = i;
     140          10 :         apThreads[i] = CPLCreateJoinableThread(ConsumerThread, pi);
     141             :     }
     142             : 
     143          11 :     for (i = 0; i < 10; i++)
     144             :     {
     145          10 :         CPLJoinThread(apThreads[i]);
     146             :     }
     147             : 
     148           1 :     CPLDestroyCond(hCond);
     149           1 :     CPLDestroyCond(hCondJobFinished);
     150           1 :     CPLDestroyMutex(hClientMutex);
     151           1 : }
     152             : 
     153             : }  // namespace

Generated by: LCOV version 1.14