Coverage Report

Created: 2025-06-13 06:29

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