Coverage Report

Created: 2026-02-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/gcore/gdaldefaultasync.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  GDAL Core
4
 * Purpose:  Implementation of GDALDefaultAsyncReader and the
5
 *           GDALAsyncReader base class.
6
 * Author:   Frank Warmerdam, warmerdam@pobox.com
7
 *
8
 ******************************************************************************
9
 * Copyright (c) 2010, Frank Warmerdam
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13
14
#include "cpl_port.h"
15
#include "gdal_priv.h"
16
17
#include <cstring>
18
19
#include "cpl_conv.h"
20
#include "cpl_error.h"
21
#include "cpl_string.h"
22
#include "gdal.h"
23
24
/************************************************************************/
25
/* ==================================================================== */
26
/*                         GDALAsyncReader                              */
27
/* ==================================================================== */
28
/************************************************************************/
29
30
/************************************************************************/
31
/*                          GDALAsyncReader()                           */
32
/************************************************************************/
33
34
GDALAsyncReader::GDALAsyncReader()
35
0
    : poDS(nullptr), nXOff(0), nYOff(0), nXSize(0), nYSize(0), pBuf(nullptr),
36
0
      nBufXSize(0), nBufYSize(0), eBufType(GDT_Unknown), nBandCount(0),
37
0
      panBandMap(nullptr), nPixelSpace(0), nLineSpace(0), nBandSpace(0)
38
0
{
39
0
}
40
41
/************************************************************************/
42
/*                          ~GDALAsyncReader()                          */
43
/************************************************************************/
44
0
GDALAsyncReader::~GDALAsyncReader() = default;
45
46
/************************************************************************/
47
/*                        GetNextUpdatedRegion()                        */
48
/************************************************************************/
49
50
/**
51
 * \fn GDALAsyncStatusType GDALAsyncReader::GetNextUpdatedRegion( double
52
 * dfTimeout, int* pnBufXOff, int* pnBufYOff, int* pnBufXSize, int* pnBufYSize)
53
 * = 0;
54
 *
55
 * \brief Get async IO update
56
 *
57
 * Provide an opportunity for an asynchronous IO request to update the
58
 * image buffer and return an indication of the area of the buffer that
59
 * has been updated.
60
 *
61
 * The dfTimeout parameter can be used to wait for additional data to
62
 * become available.  The timeout does not limit the amount
63
 * of time this method may spend actually processing available data.
64
 *
65
 * The following return status are possible.
66
 * - GARIO_PENDING: No imagery was altered in the buffer, but there is still
67
 * activity pending, and the application should continue to call
68
 * GetNextUpdatedRegion() as time permits.
69
 * - GARIO_UPDATE: Some of the imagery has been updated, but there is still
70
 * activity pending.
71
 * - GARIO_ERROR: Something has gone wrong. The asynchronous request should
72
 * be ended.
73
 * - GARIO_COMPLETE: An update has occurred and there is no more pending work
74
 * on this request. The request should be ended and the buffer used.
75
 *
76
 * @param dfTimeout the number of seconds to wait for additional updates.  Use
77
 * -1 to wait indefinitely, or zero to not wait at all if there is no data
78
 * available.
79
 * @param pnBufXOff location to return the X offset of the area of the
80
 * request buffer that has been updated.
81
 * @param pnBufYOff location to return the Y offset of the area of the
82
 * request buffer that has been updated.
83
 * @param pnBufXSize location to return the X size of the area of the
84
 * request buffer that has been updated.
85
 * @param pnBufYSize location to return the Y size of the area of the
86
 * request buffer that has been updated.
87
 *
88
 * @return GARIO_ status, details described above.
89
 */
90
91
/************************************************************************/
92
/*                     GDALARGetNextUpdatedRegion()                     */
93
/************************************************************************/
94
95
/**
96
 * \brief Get async IO update
97
 *
98
 * Provide an opportunity for an asynchronous IO request to update the
99
 * image buffer and return an indication of the area of the buffer that
100
 * has been updated.
101
 *
102
 * The dfTimeout parameter can be used to wait for additional data to
103
 * become available.  The timeout does not limit the amount
104
 * of time this method may spend actually processing available data.
105
 *
106
 * The following return status are possible.
107
 * - GARIO_PENDING: No imagery was altered in the buffer, but there is still
108
 * activity pending, and the application should continue to call
109
 * GetNextUpdatedRegion() as time permits.
110
 * - GARIO_UPDATE: Some of the imagery has been updated, but there is still
111
 * activity pending.
112
 * - GARIO_ERROR: Something has gone wrong. The asynchronous request should
113
 * be ended.
114
 * - GARIO_COMPLETE: An update has occurred and there is no more pending work
115
 * on this request. The request should be ended and the buffer used.
116
 *
117
 * This is the same as GDALAsyncReader::GetNextUpdatedRegion()
118
 *
119
 * @param hARIO handle to the async reader.
120
 * @param dfTimeout the number of seconds to wait for additional updates.  Use
121
 * -1 to wait indefinitely, or zero to not wait at all if there is no data
122
 * available.
123
 * @param pnBufXOff location to return the X offset of the area of the
124
 * request buffer that has been updated.
125
 * @param pnBufYOff location to return the Y offset of the area of the
126
 * request buffer that has been updated.
127
 * @param pnBufXSize location to return the X size of the area of the
128
 * request buffer that has been updated.
129
 * @param pnBufYSize location to return the Y size of the area of the
130
 * request buffer that has been updated.
131
 *
132
 * @return GARIO_ status, details described above.
133
 */
134
135
GDALAsyncStatusType CPL_STDCALL GDALARGetNextUpdatedRegion(
136
    GDALAsyncReaderH hARIO, double dfTimeout, int *pnBufXOff, int *pnBufYOff,
137
    int *pnBufXSize, int *pnBufYSize)
138
0
{
139
0
    VALIDATE_POINTER1(hARIO, "GDALARGetNextUpdatedRegion", GARIO_ERROR);
140
0
    return static_cast<GDALAsyncReader *>(hARIO)->GetNextUpdatedRegion(
141
0
        dfTimeout, pnBufXOff, pnBufYOff, pnBufXSize, pnBufYSize);
142
0
}
143
144
/************************************************************************/
145
/*                             LockBuffer()                             */
146
/************************************************************************/
147
148
/**
149
 * \fn GDALAsyncReader::LockBuffer(double)
150
 * \brief Lock image buffer.
151
 *
152
 * Locks the image buffer passed into GDALDataset::BeginAsyncReader().
153
 * This is useful to ensure the image buffer is not being modified while
154
 * it is being used by the application.  UnlockBuffer() should be used
155
 * to release this lock when it is no longer needed.
156
 *
157
 * @param dfTimeout the time in seconds to wait attempting to lock the buffer.
158
 * -1.0 to wait indefinitely and 0 to not wait at all if it can't be
159
 * acquired immediately.  Default is -1.0 (infinite wait).
160
 *
161
 * @return TRUE if successful, or FALSE on an error.
162
 */
163
164
/**/
165
/**/
166
167
int GDALAsyncReader::LockBuffer(double /* dfTimeout */)
168
0
{
169
0
    return TRUE;
170
0
}
171
172
/************************************************************************/
173
/*                          GDALARLockBuffer()                          */
174
/************************************************************************/
175
176
/**
177
 * \brief Lock image buffer.
178
 *
179
 * Locks the image buffer passed into GDALDataset::BeginAsyncReader().
180
 * This is useful to ensure the image buffer is not being modified while
181
 * it is being used by the application.  UnlockBuffer() should be used
182
 * to release this lock when it is no longer needed.
183
 *
184
 * This is the same as GDALAsyncReader::LockBuffer()
185
 *
186
 * @param hARIO handle to async reader.
187
 * @param dfTimeout the time in seconds to wait attempting to lock the buffer.
188
 * -1.0 to wait indefinitely and 0 to not wait at all if it can't be
189
 * acquired immediately.  Default is -1.0 (infinite wait).
190
 *
191
 * @return TRUE if successful, or FALSE on an error.
192
 */
193
194
int CPL_STDCALL GDALARLockBuffer(GDALAsyncReaderH hARIO, double dfTimeout)
195
0
{
196
0
    VALIDATE_POINTER1(hARIO, "GDALARLockBuffer", FALSE);
197
0
    return static_cast<GDALAsyncReader *>(hARIO)->LockBuffer(dfTimeout);
198
0
}
199
200
/************************************************************************/
201
/*                            UnlockBuffer()                            */
202
/************************************************************************/
203
204
/**
205
 * \brief Unlock image buffer.
206
 *
207
 * Releases a lock on the image buffer previously taken with LockBuffer().
208
 */
209
210
void GDALAsyncReader::UnlockBuffer()
211
212
0
{
213
0
}
214
215
/************************************************************************/
216
/*                         GDALARUnlockBuffer()                         */
217
/************************************************************************/
218
219
/**
220
 * \brief Unlock image buffer.
221
 *
222
 * Releases a lock on the image buffer previously taken with LockBuffer().
223
 *
224
 * This is the same as GDALAsyncReader::UnlockBuffer()
225
 *
226
 * @param hARIO handle to async reader.
227
 */
228
229
void CPL_STDCALL GDALARUnlockBuffer(GDALAsyncReaderH hARIO)
230
0
{
231
0
    VALIDATE_POINTER0(hARIO, "GDALARUnlockBuffer");
232
0
    static_cast<GDALAsyncReader *>(hARIO)->UnlockBuffer();
233
0
}
234
235
/************************************************************************/
236
/* ==================================================================== */
237
/*                     GDALDefaultAsyncReader                           */
238
/* ==================================================================== */
239
/************************************************************************/
240
241
class GDALDefaultAsyncReader : public GDALAsyncReader
242
{
243
  private:
244
    char **papszOptions = nullptr;
245
246
    CPL_DISALLOW_COPY_ASSIGN(GDALDefaultAsyncReader)
247
248
  public:
249
    GDALDefaultAsyncReader(GDALDataset *poDS, int nXOff, int nYOff, int nXSize,
250
                           int nYSize, void *pBuf, int nBufXSize, int nBufYSize,
251
                           GDALDataType eBufType, int nBandCount,
252
                           int *panBandMap, int nPixelSpace, int nLineSpace,
253
                           int nBandSpace, CSLConstList papszOptions);
254
    ~GDALDefaultAsyncReader() override;
255
256
    GDALAsyncStatusType GetNextUpdatedRegion(double dfTimeout, int *pnBufXOff,
257
                                             int *pnBufYOff, int *pnBufXSize,
258
                                             int *pnBufYSize) override;
259
};
260
261
/************************************************************************/
262
/*                     GDALGetDefaultAsyncReader()                      */
263
/************************************************************************/
264
265
GDALAsyncReader *
266
GDALGetDefaultAsyncReader(GDALDataset *poDS, int nXOff, int nYOff, int nXSize,
267
                          int nYSize, void *pBuf, int nBufXSize, int nBufYSize,
268
                          GDALDataType eBufType, int nBandCount,
269
                          int *panBandMap, int nPixelSpace, int nLineSpace,
270
                          int nBandSpace, CSLConstList papszOptions)
271
272
0
{
273
0
    return new GDALDefaultAsyncReader(poDS, nXOff, nYOff, nXSize, nYSize, pBuf,
274
0
                                      nBufXSize, nBufYSize, eBufType,
275
0
                                      nBandCount, panBandMap, nPixelSpace,
276
0
                                      nLineSpace, nBandSpace, papszOptions);
277
0
}
278
279
/************************************************************************/
280
/*                       GDALDefaultAsyncReader()                       */
281
/************************************************************************/
282
283
GDALDefaultAsyncReader::GDALDefaultAsyncReader(
284
    GDALDataset *poDSIn, int nXOffIn, int nYOffIn, int nXSizeIn, int nYSizeIn,
285
    void *pBufIn, int nBufXSizeIn, int nBufYSizeIn, GDALDataType eBufTypeIn,
286
    int nBandCountIn, int *panBandMapIn, int nPixelSpaceIn, int nLineSpaceIn,
287
    int nBandSpaceIn, CSLConstList papszOptionsIn)
288
289
0
{
290
0
    poDS = poDSIn;
291
0
    nXOff = nXOffIn;
292
0
    nYOff = nYOffIn;
293
0
    nXSize = nXSizeIn;
294
0
    nYSize = nYSizeIn;
295
0
    pBuf = pBufIn;
296
0
    nBufXSize = nBufXSizeIn;
297
0
    nBufYSize = nBufYSizeIn;
298
0
    eBufType = eBufTypeIn;
299
0
    nBandCount = nBandCountIn;
300
0
    panBandMap = static_cast<int *>(CPLMalloc(sizeof(int) * nBandCountIn));
301
302
0
    if (panBandMapIn != nullptr)
303
0
        memcpy(panBandMap, panBandMapIn, sizeof(int) * nBandCount);
304
0
    else
305
0
    {
306
0
        for (int i = 0; i < nBandCount; i++)
307
0
            panBandMap[i] = i + 1;
308
0
    }
309
310
0
    nPixelSpace = nPixelSpaceIn;
311
0
    nLineSpace = nLineSpaceIn;
312
0
    nBandSpace = nBandSpaceIn;
313
314
0
    papszOptions = CSLDuplicate(papszOptionsIn);
315
0
}
316
317
/************************************************************************/
318
/*                      ~GDALDefaultAsyncReader()                       */
319
/************************************************************************/
320
321
GDALDefaultAsyncReader::~GDALDefaultAsyncReader()
322
323
0
{
324
0
    CPLFree(panBandMap);
325
0
    CSLDestroy(papszOptions);
326
0
}
327
328
/************************************************************************/
329
/*                        GetNextUpdatedRegion()                        */
330
/************************************************************************/
331
332
GDALAsyncStatusType
333
GDALDefaultAsyncReader::GetNextUpdatedRegion(double /*dfTimeout*/,
334
                                             int *pnBufXOff, int *pnBufYOff,
335
                                             int *pnBufXSize, int *pnBufYSize)
336
0
{
337
0
    CPLErr eErr;
338
339
0
    eErr =
340
0
        poDS->RasterIO(GF_Read, nXOff, nYOff, nXSize, nYSize, pBuf, nBufXSize,
341
0
                       nBufYSize, eBufType, nBandCount, panBandMap, nPixelSpace,
342
0
                       nLineSpace, nBandSpace, nullptr);
343
344
0
    *pnBufXOff = 0;
345
0
    *pnBufYOff = 0;
346
0
    *pnBufXSize = nBufXSize;
347
0
    *pnBufYSize = nBufYSize;
348
349
0
    if (eErr == CE_None)
350
0
        return GARIO_COMPLETE;
351
0
    else
352
0
        return GARIO_ERROR;
353
0
}