/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 | } |