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 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 ****************************************************************************/
29
30 #include "cpl_port.h"
31 #include "gdal_priv.h"
32
33 #include <cstring>
34
35 #include "cpl_conv.h"
36 #include "cpl_error.h"
37 #include "cpl_string.h"
38 #include "gdal.h"
39
40 CPL_CVSID("$Id: gdaldefaultasync.cpp dca024c6230a7d7f29afd2818afdc23313a18542 2018-05-06 18:08:36 +0200 Even Rouault $")
41
42 CPL_C_START
43 GDALAsyncReader *
44 GDALGetDefaultAsyncReader( GDALDataset* poDS,
45 int nXOff, int nYOff, int nXSize, int nYSize,
46 void *pBuf, int nBufXSize, int nBufYSize,
47 GDALDataType eBufType,
48 int nBandCount, int* panBandMap,
49 int nPixelSpace, int nLineSpace,
50 int nBandSpace, char **papszOptions );
51 CPL_C_END
52
53 /************************************************************************/
54 /* ==================================================================== */
55 /* GDALAsyncReader */
56 /* ==================================================================== */
57 /************************************************************************/
58
59 /************************************************************************/
60 /* GDALAsyncReader() */
61 /************************************************************************/
62
GDALAsyncReader()63 GDALAsyncReader::GDALAsyncReader() :
64 poDS(nullptr),
65 nXOff(0),
66 nYOff(0),
67 nXSize(0),
68 nYSize(0),
69 pBuf(nullptr),
70 nBufXSize(0),
71 nBufYSize(0),
72 eBufType(GDT_Unknown),
73 nBandCount(0),
74 panBandMap(nullptr),
75 nPixelSpace(0),
76 nLineSpace(0),
77 nBandSpace(0)
78 {
79 }
80
81 /************************************************************************/
82 /* ~GDALAsyncReader() */
83 /************************************************************************/
84 GDALAsyncReader::~GDALAsyncReader() = default;
85
86 /************************************************************************/
87 /* GetNextUpdatedRegion() */
88 /************************************************************************/
89
90 /**
91 * \fn GDALAsyncStatusType GDALAsyncReader::GetNextUpdatedRegion( double dfTimeout, int* pnBufXOff, int* pnBufYOff, int* pnBufXSize, int* pnBufYSize) = 0;
92 *
93 * \brief Get async IO update
94 *
95 * Provide an opportunity for an asynchronous IO request to update the
96 * image buffer and return an indication of the area of the buffer that
97 * has been updated.
98 *
99 * The dfTimeout parameter can be used to wait for additional data to
100 * become available. The timeout does not limit the amount
101 * of time this method may spend actually processing available data.
102 *
103 * The following return status are possible.
104 * - GARIO_PENDING: No imagery was altered in the buffer, but there is still
105 * activity pending, and the application should continue to call
106 * GetNextUpdatedRegion() as time permits.
107 * - GARIO_UPDATE: Some of the imagery has been updated, but there is still
108 * activity pending.
109 * - GARIO_ERROR: Something has gone wrong. The asynchronous request should
110 * be ended.
111 * - GARIO_COMPLETE: An update has occurred and there is no more pending work
112 * on this request. The request should be ended and the buffer used.
113 *
114 * @param dfTimeout the number of seconds to wait for additional updates. Use
115 * -1 to wait indefinitely, or zero to not wait at all if there is no data
116 * available.
117 * @param pnBufXOff location to return the X offset of the area of the
118 * request buffer that has been updated.
119 * @param pnBufYOff location to return the Y offset of the area of the
120 * request buffer that has been updated.
121 * @param pnBufXSize location to return the X size of the area of the
122 * request buffer that has been updated.
123 * @param pnBufYSize location to return the Y size of the area of the
124 * request buffer that has been updated.
125 *
126 * @return GARIO_ status, details described above.
127 */
128
129 /************************************************************************/
130 /* GDALARGetNextUpdatedRegion() */
131 /************************************************************************/
132
133 /**
134 * \brief Get async IO update
135 *
136 * Provide an opportunity for an asynchronous IO request to update the
137 * image buffer and return an indication of the area of the buffer that
138 * has been updated.
139 *
140 * The dfTimeout parameter can be used to wait for additional data to
141 * become available. The timeout does not limit the amount
142 * of time this method may spend actually processing available data.
143 *
144 * The following return status are possible.
145 * - GARIO_PENDING: No imagery was altered in the buffer, but there is still
146 * activity pending, and the application should continue to call
147 * GetNextUpdatedRegion() as time permits.
148 * - GARIO_UPDATE: Some of the imagery has been updated, but there is still
149 * activity pending.
150 * - GARIO_ERROR: Something has gone wrong. The asynchronous request should
151 * be ended.
152 * - GARIO_COMPLETE: An update has occurred and there is no more pending work
153 * on this request. The request should be ended and the buffer used.
154 *
155 * This is the same as GDALAsyncReader::GetNextUpdatedRegion()
156 *
157 * @param hARIO handle to the async reader.
158 * @param dfTimeout the number of seconds to wait for additional updates. Use
159 * -1 to wait indefinitely, or zero to not wait at all if there is no data
160 * available.
161 * @param pnBufXOff location to return the X offset of the area of the
162 * request buffer that has been updated.
163 * @param pnBufYOff location to return the Y offset of the area of the
164 * request buffer that has been updated.
165 * @param pnBufXSize location to return the X size of the area of the
166 * request buffer that has been updated.
167 * @param pnBufYSize location to return the Y size of the area of the
168 * request buffer that has been updated.
169 *
170 * @return GARIO_ status, details described above.
171 */
172
173 GDALAsyncStatusType CPL_STDCALL
GDALARGetNextUpdatedRegion(GDALAsyncReaderH hARIO,double dfTimeout,int * pnBufXOff,int * pnBufYOff,int * pnBufXSize,int * pnBufYSize)174 GDALARGetNextUpdatedRegion(GDALAsyncReaderH hARIO, double dfTimeout,
175 int* pnBufXOff, int* pnBufYOff,
176 int* pnBufXSize, int* pnBufYSize)
177 {
178 VALIDATE_POINTER1(hARIO, "GDALARGetNextUpdatedRegion", GARIO_ERROR);
179 return static_cast<GDALAsyncReader *>(hARIO)->GetNextUpdatedRegion(
180 dfTimeout, pnBufXOff, pnBufYOff, pnBufXSize, pnBufYSize);
181 }
182
183 /************************************************************************/
184 /* LockBuffer() */
185 /************************************************************************/
186
187 /**
188 * \fn GDALAsyncReader::LockBuffer(double)
189 * \brief Lock image buffer.
190 *
191 * Locks the image buffer passed into GDALDataset::BeginAsyncReader().
192 * This is useful to ensure the image buffer is not being modified while
193 * it is being used by the application. UnlockBuffer() should be used
194 * to release this lock when it is no longer needed.
195 *
196 * @param dfTimeout the time in seconds to wait attempting to lock the buffer.
197 * -1.0 to wait indefinitely and 0 to not wait at all if it can't be
198 * acquired immediately. Default is -1.0 (infinite wait).
199 *
200 * @return TRUE if successful, or FALSE on an error.
201 */
202
203 /**/
204 /**/
205
LockBuffer(double)206 int GDALAsyncReader::LockBuffer( double /* dfTimeout */ )
207 {
208 return TRUE;
209 }
210
211 /************************************************************************/
212 /* GDALARLockBuffer() */
213 /************************************************************************/
214
215 /**
216 * \brief Lock image buffer.
217 *
218 * Locks the image buffer passed into GDALDataset::BeginAsyncReader().
219 * This is useful to ensure the image buffer is not being modified while
220 * it is being used by the application. UnlockBuffer() should be used
221 * to release this lock when it is no longer needed.
222 *
223 * This is the same as GDALAsyncReader::LockBuffer()
224 *
225 * @param hARIO handle to async reader.
226 * @param dfTimeout the time in seconds to wait attempting to lock the buffer.
227 * -1.0 to wait indefinitely and 0 to not wait at all if it can't be
228 * acquired immediately. Default is -1.0 (infinite wait).
229 *
230 * @return TRUE if successful, or FALSE on an error.
231 */
232
GDALARLockBuffer(GDALAsyncReaderH hARIO,double dfTimeout)233 int CPL_STDCALL GDALARLockBuffer(GDALAsyncReaderH hARIO, double dfTimeout )
234 {
235 VALIDATE_POINTER1(hARIO, "GDALARLockBuffer",FALSE);
236 return static_cast<GDALAsyncReader *>(hARIO)->LockBuffer( dfTimeout );
237 }
238
239 /************************************************************************/
240 /* UnlockBuffer() */
241 /************************************************************************/
242
243 /**
244 * \brief Unlock image buffer.
245 *
246 * Releases a lock on the image buffer previously taken with LockBuffer().
247 */
248
UnlockBuffer()249 void GDALAsyncReader::UnlockBuffer()
250
251 {
252 }
253
254 /************************************************************************/
255 /* GDALARUnlockBuffer() */
256 /************************************************************************/
257
258 /**
259 * \brief Unlock image buffer.
260 *
261 * Releases a lock on the image buffer previously taken with LockBuffer().
262 *
263 * This is the same as GDALAsyncReader::UnlockBuffer()
264 *
265 * @param hARIO handle to async reader.
266 */
267
GDALARUnlockBuffer(GDALAsyncReaderH hARIO)268 void CPL_STDCALL GDALARUnlockBuffer(GDALAsyncReaderH hARIO)
269 {
270 VALIDATE_POINTER0(hARIO, "GDALARUnlockBuffer");
271 static_cast<GDALAsyncReader *>(hARIO)->UnlockBuffer();
272 }
273
274 /************************************************************************/
275 /* ==================================================================== */
276 /* GDALDefaultAsyncReader */
277 /* ==================================================================== */
278 /************************************************************************/
279
280 class GDALDefaultAsyncReader : public GDALAsyncReader
281 {
282 private:
283 char **papszOptions = nullptr;
284
285 CPL_DISALLOW_COPY_ASSIGN(GDALDefaultAsyncReader)
286
287 public:
288 GDALDefaultAsyncReader(GDALDataset* poDS,
289 int nXOff, int nYOff,
290 int nXSize, int nYSize,
291 void *pBuf,
292 int nBufXSize, int nBufYSize,
293 GDALDataType eBufType,
294 int nBandCount, int* panBandMap,
295 int nPixelSpace, int nLineSpace,
296 int nBandSpace, char **papszOptions);
297 ~GDALDefaultAsyncReader() override;
298
299 GDALAsyncStatusType GetNextUpdatedRegion(double dfTimeout,
300 int* pnBufXOff,
301 int* pnBufYOff,
302 int* pnBufXSize,
303 int* pnBufYSize) override;
304 };
305
306 /************************************************************************/
307 /* GDALGetDefaultAsyncReader() */
308 /************************************************************************/
309
310 GDALAsyncReader *
GDALGetDefaultAsyncReader(GDALDataset * poDS,int nXOff,int nYOff,int nXSize,int nYSize,void * pBuf,int nBufXSize,int nBufYSize,GDALDataType eBufType,int nBandCount,int * panBandMap,int nPixelSpace,int nLineSpace,int nBandSpace,char ** papszOptions)311 GDALGetDefaultAsyncReader( GDALDataset* poDS,
312 int nXOff, int nYOff,
313 int nXSize, int nYSize,
314 void *pBuf,
315 int nBufXSize, int nBufYSize,
316 GDALDataType eBufType,
317 int nBandCount, int* panBandMap,
318 int nPixelSpace, int nLineSpace,
319 int nBandSpace, char **papszOptions)
320
321 {
322 return new GDALDefaultAsyncReader( poDS,
323 nXOff, nYOff, nXSize, nYSize,
324 pBuf, nBufXSize, nBufYSize, eBufType,
325 nBandCount, panBandMap,
326 nPixelSpace, nLineSpace, nBandSpace,
327 papszOptions );
328 }
329
330 /************************************************************************/
331 /* GDALDefaultAsyncReader() */
332 /************************************************************************/
333
334 GDALDefaultAsyncReader::
GDALDefaultAsyncReader(GDALDataset * poDSIn,int nXOffIn,int nYOffIn,int nXSizeIn,int nYSizeIn,void * pBufIn,int nBufXSizeIn,int nBufYSizeIn,GDALDataType eBufTypeIn,int nBandCountIn,int * panBandMapIn,int nPixelSpaceIn,int nLineSpaceIn,int nBandSpaceIn,char ** papszOptionsIn)335 GDALDefaultAsyncReader( GDALDataset* poDSIn,
336 int nXOffIn, int nYOffIn,
337 int nXSizeIn, int nYSizeIn,
338 void *pBufIn,
339 int nBufXSizeIn, int nBufYSizeIn,
340 GDALDataType eBufTypeIn,
341 int nBandCountIn, int* panBandMapIn,
342 int nPixelSpaceIn, int nLineSpaceIn,
343 int nBandSpaceIn, char **papszOptionsIn)
344
345 {
346 poDS = poDSIn;
347 nXOff = nXOffIn;
348 nYOff = nYOffIn;
349 nXSize = nXSizeIn;
350 nYSize = nYSizeIn;
351 pBuf = pBufIn;
352 nBufXSize = nBufXSizeIn;
353 nBufYSize = nBufYSizeIn;
354 eBufType = eBufTypeIn;
355 nBandCount = nBandCountIn;
356 panBandMap = static_cast<int*>(CPLMalloc(sizeof(int)*nBandCountIn));
357
358 if( panBandMapIn != nullptr )
359 memcpy( panBandMap, panBandMapIn, sizeof(int)*nBandCount );
360 else
361 {
362 for( int i = 0; i < nBandCount; i++ )
363 panBandMap[i] = i+1;
364 }
365
366 nPixelSpace = nPixelSpaceIn;
367 nLineSpace = nLineSpaceIn;
368 nBandSpace = nBandSpaceIn;
369
370 papszOptions = CSLDuplicate(papszOptionsIn);
371 }
372
373 /************************************************************************/
374 /* ~GDALDefaultAsyncReader() */
375 /************************************************************************/
376
~GDALDefaultAsyncReader()377 GDALDefaultAsyncReader::~GDALDefaultAsyncReader()
378
379 {
380 CPLFree( panBandMap );
381 CSLDestroy( papszOptions );
382 }
383
384 /************************************************************************/
385 /* GetNextUpdatedRegion() */
386 /************************************************************************/
387
388 GDALAsyncStatusType
GetNextUpdatedRegion(double,int * pnBufXOff,int * pnBufYOff,int * pnBufXSize,int * pnBufYSize)389 GDALDefaultAsyncReader::GetNextUpdatedRegion( double /*dfTimeout*/,
390 int* pnBufXOff,
391 int* pnBufYOff,
392 int* pnBufXSize,
393 int* pnBufYSize )
394 {
395 CPLErr eErr;
396
397 eErr = poDS->RasterIO( GF_Read, nXOff, nYOff, nXSize, nYSize,
398 pBuf, nBufXSize, nBufYSize, eBufType,
399 nBandCount, panBandMap,
400 nPixelSpace, nLineSpace, nBandSpace,
401 nullptr );
402
403 *pnBufXOff = 0;
404 *pnBufYOff = 0;
405 *pnBufXSize = nBufXSize;
406 *pnBufYSize = nBufYSize;
407
408 if( eErr == CE_None )
409 return GARIO_COMPLETE;
410 else
411 return GARIO_ERROR;
412 }
413