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