Line data Source code
1 : /****************************************************************************** 2 : * Project: GDAL Core 3 : * Purpose: Test block cache & writing behaviour under multi-threading 4 : * Author: Even Rouault, <even dot rouault at spatialys dot com> 5 : * 6 : ****************************************************************************** 7 : * Copyright (c) 2016, Even Rouault <even dot rouault at spatialys dot com> 8 : * 9 : * SPDX-License-Identifier: MIT 10 : ****************************************************************************/ 11 : 12 : #include "cpl_multiproc.h" 13 : #include "gdal_alg.h" 14 : #include "gdal_priv.h" 15 : 16 : #include "gtest_include.h" 17 : 18 : namespace 19 : { 20 : 21 : // --------------------------------------------------------------------------- 22 : 23 2 : static void thread_func(void *ptr) 24 : { 25 2 : int num = *(int *)ptr; 26 2 : GDALDriver *poDriver = (GDALDriver *)GDALGetDriverByName("ENVI"); 27 : GDALDataset *poDSRef = 28 2 : (GDALDataset *)GDALOpen("/vsimem/test_ref", GA_ReadOnly); 29 2 : GDALDataset *poDS = poDriver->Create(CPLSPrintf("/vsimem/test%d", num), 100, 30 : 2000, 1, GDT_Byte, nullptr); 31 2 : GDALRasterBand *poBand = poDS->GetRasterBand(1); 32 2 : GDALRasterBand *poBandRef = poDSRef->GetRasterBand(1); 33 4002 : for (int i = 0; i < 2000; i++) 34 : { 35 4000 : GDALRasterBlock *poBlockRef = poBandRef->GetLockedBlockRef(0, i); 36 4000 : GDALRasterBlock *poBlockRW = poBand->GetLockedBlockRef(0, i); 37 4000 : poBlockRW->MarkDirty(); 38 4000 : memset(poBlockRW->GetDataRef(), 0xFF, 100); 39 4000 : poBlockRef->DropLock(); 40 4000 : poBlockRW->DropLock(); 41 : } 42 2 : GDALClose(poDS); 43 2 : GDALClose(poDSRef); 44 2 : } 45 : 46 4 : TEST(testmultithreadedwriting, test) 47 : { 48 1 : bool bEndlessLoop = CPLTestBool(CPLGetConfigOption("ENDLESS_LOOPS", "NO")); 49 : 50 : CPLJoinableThread *hThread1; 51 : CPLJoinableThread *hThread2; 52 : 53 1 : GDALAllRegister(); 54 1 : GDALSetCacheMax(10000); 55 : 56 1 : int one = 1; 57 1 : int two = 2; 58 1 : GDALDriver *poDriver = (GDALDriver *)GDALGetDriverByName("ENVI"); 59 1 : if (poDriver == nullptr) 60 : { 61 0 : GTEST_SKIP() << "ENVI driver missing"; 62 : return; 63 : } 64 : GDALDataset *poDS = 65 1 : poDriver->Create("/vsimem/test_ref", 100, 2000, 1, GDT_Byte, nullptr); 66 1 : GDALClose(poDS); 67 : 68 1 : int counter = 0; 69 1 : const int nloops = bEndlessLoop ? 2 * 1000 * 1000 * 1000 : 1; 70 2 : for (int i = 0; i < nloops; ++i) 71 : { 72 1 : ++i; 73 1 : if ((i % 20) == 0) 74 0 : printf("%d\n", counter); 75 : 76 1 : hThread1 = CPLCreateJoinableThread(thread_func, &one); 77 1 : hThread2 = CPLCreateJoinableThread(thread_func, &two); 78 : 79 1 : CPLJoinThread(hThread1); 80 1 : CPLJoinThread(hThread2); 81 : 82 : GDALDataset *poDSRef = 83 1 : (GDALDataset *)GDALOpen("/vsimem/test1", GA_ReadOnly); 84 : const int cs = 85 1 : GDALChecksumImage(poDSRef->GetRasterBand(1), 0, 0, 100, 2000); 86 1 : EXPECT_EQ(cs, 29689); 87 1 : GDALClose(poDSRef); 88 : 89 1 : poDriver->Delete("/vsimem/test1"); 90 1 : poDriver->Delete("/vsimem/test2"); 91 : } 92 : 93 1 : poDriver->Delete("/vsimem/test_ref"); 94 : 95 1 : GDALDestroyDriverManager(); 96 : } 97 : 98 : } // namespace