1/*****************************************************************************/
2// Copyright 2006-2007 Adobe Systems Incorporated
3// All Rights Reserved.
4//
5// NOTICE: Adobe permits you to use, modify, and distribute this file in
6// accordance with the terms of the Adobe license agreement accompanying it.
7/*****************************************************************************/
8
9/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_memory.h#1 $ */
10/* $DateTime: 2012/05/30 13:28:51 $ */
11/* $Change: 832332 $ */
12/* $Author: tknoll $ */
13
14/** Support for memory allocation.
15 */
16
17/*****************************************************************************/
18
19#ifndef __dng_memory__
20#define __dng_memory__
21
22/*****************************************************************************/
23
24#include "dng_classes.h"
25#include "dng_exceptions.h"
26#include "dng_safe_arithmetic.h"
27#include "dng_types.h"
28
29#include <cstdlib>
30#include <vector>
31
32/*****************************************************************************/
33
34/// \brief Class to provide resource acquisition is instantiation discipline
35/// for small memory allocations.
36///
37/// This class does not use dng_memory_allocator for memory allocation.
38
39class dng_memory_data
40 {
41
42 private:
43
44 char *fBuffer;
45
46 public:
47
48 /// Construct an empty memory buffer using malloc.
49 /// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
50
51 dng_memory_data ();
52
53 /// Construct memory buffer of size bytes using malloc.
54 /// \param size Number of bytes of memory needed.
55 /// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
56
57 dng_memory_data (uint32 size);
58
59 /// Note: This constructor is for internal use only and should not be
60 /// considered part of the DNG SDK API.
61 ///
62 /// Construct memory buffer of count elements of elementSize bytes each.
63 /// \param count Number of elements.
64 /// \param elementSize Size of each element.
65 /// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
66 dng_memory_data (uint32 count, std::size_t elementSize);
67
68 /// Release memory buffer using free.
69
70 ~dng_memory_data ();
71
72 /// Clear existing memory buffer and allocate new memory of size bytes.
73 /// \param size Number of bytes of memory needed.
74 /// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
75
76 void Allocate (uint32 size);
77
78 /// Note: This method is for internal use only and should not be
79 /// considered part of the DNG SDK API.
80 ///
81 /// Clear existing memory buffer and allocate new memory of count
82 /// elements of elementSize bytes each.
83 /// \param count Number of elements.
84 /// \param elementSize Size of each element.
85 /// \exception dng_memory_full with fErrorCode equal to dng_error_memory.
86 void Allocate (uint32 count, std::size_t elementSize);
87
88 /// Release any allocated memory using free. Object is still valid and
89 /// Allocate can be called again.
90
91 void Clear ();
92
93 /// Return pointer to allocated memory as a void *..
94 /// \retval void * valid for as many bytes as were allocated.
95
96 void * Buffer ()
97 {
98 return fBuffer;
99 }
100
101 /// Return pointer to allocated memory as a const void *.
102 /// \retval const void * valid for as many bytes as were allocated.
103
104 const void * Buffer () const
105 {
106 return fBuffer;
107 }
108
109 /// Return pointer to allocated memory as a char *.
110 /// \retval char * valid for as many bytes as were allocated.
111
112 char * Buffer_char ()
113 {
114 return (char *) Buffer ();
115 }
116
117 /// Return pointer to allocated memory as a const char *.
118 /// \retval const char * valid for as many bytes as were allocated.
119
120 const char * Buffer_char () const
121 {
122 return (const char *) Buffer ();
123 }
124
125 /// Return pointer to allocated memory as a uint8 *.
126 /// \retval uint8 * valid for as many bytes as were allocated.
127
128 uint8 * Buffer_uint8 ()
129 {
130 return (uint8 *) Buffer ();
131 }
132
133 /// Return pointer to allocated memory as a const uint8 *.
134 /// \retval const uint8 * valid for as many bytes as were allocated.
135
136 const uint8 * Buffer_uint8 () const
137 {
138 return (const uint8 *) Buffer ();
139 }
140
141 /// Return pointer to allocated memory as a uint16 *.
142 /// \retval uint16 * valid for as many bytes as were allocated.
143
144 uint16 * Buffer_uint16 ()
145 {
146 return (uint16 *) Buffer ();
147 }
148
149 /// Return pointer to allocated memory as a const uint16 *.
150 /// \retval const uint16 * valid for as many bytes as were allocated.
151
152 const uint16 * Buffer_uint16 () const
153 {
154 return (const uint16 *) Buffer ();
155 }
156
157 /// Return pointer to allocated memory as a int16 *.
158 /// \retval int16 * valid for as many bytes as were allocated.
159
160 int16 * Buffer_int16 ()
161 {
162 return (int16 *) Buffer ();
163 }
164
165 /// Return pointer to allocated memory as a const int16 *.
166 /// \retval const int16 * valid for as many bytes as were allocated.
167
168 const int16 * Buffer_int16 () const
169 {
170 return (const int16 *) Buffer ();
171 }
172
173 /// Return pointer to allocated memory as a uint32 *.
174 /// \retval uint32 * valid for as many bytes as were allocated.
175
176 uint32 * Buffer_uint32 ()
177 {
178 return (uint32 *) Buffer ();
179 }
180
181 /// Return pointer to allocated memory as a uint32 *.
182 /// \retval uint32 * valid for as many bytes as were allocated.
183
184 const uint32 * Buffer_uint32 () const
185 {
186 return (const uint32 *) Buffer ();
187 }
188
189 /// Return pointer to allocated memory as a const int32 *.
190 /// \retval const int32 * valid for as many bytes as were allocated.
191
192 int32 * Buffer_int32 ()
193 {
194 return (int32 *) Buffer ();
195 }
196
197 /// Return pointer to allocated memory as a const int32 *.
198 /// \retval const int32 * valid for as many bytes as were allocated.
199
200 const int32 * Buffer_int32 () const
201 {
202 return (const int32 *) Buffer ();
203 }
204
205 /// Return pointer to allocated memory as a uint64 *.
206 /// \retval uint64 * valid for as many bytes as were allocated.
207
208 uint64 * Buffer_uint64 ()
209 {
210 return (uint64 *) Buffer ();
211 }
212
213 /// Return pointer to allocated memory as a uint64 *.
214 /// \retval uint64 * valid for as many bytes as were allocated.
215
216 const uint64 * Buffer_uint64 () const
217 {
218 return (const uint64 *) Buffer ();
219 }
220
221 /// Return pointer to allocated memory as a const int64 *.
222 /// \retval const int64 * valid for as many bytes as were allocated.
223
224 int64 * Buffer_int64 ()
225 {
226 return (int64 *) Buffer ();
227 }
228
229 /// Return pointer to allocated memory as a const int64 *.
230 /// \retval const int64 * valid for as many bytes as were allocated.
231
232 const int64 * Buffer_int64 () const
233 {
234 return (const int64 *) Buffer ();
235 }
236
237 /// Return pointer to allocated memory as a real32 *.
238 /// \retval real32 * valid for as many bytes as were allocated.
239
240 real32 * Buffer_real32 ()
241 {
242 return (real32 *) Buffer ();
243 }
244
245 /// Return pointer to allocated memory as a const real32 *.
246 /// \retval const real32 * valid for as many bytes as were allocated.
247
248 const real32 * Buffer_real32 () const
249 {
250 return (const real32 *) Buffer ();
251 }
252
253 /// Return pointer to allocated memory as a real64 *.
254 /// \retval real64 * valid for as many bytes as were allocated.
255
256 real64 * Buffer_real64 ()
257 {
258 return (real64 *) Buffer ();
259 }
260
261 /// Return pointer to allocated memory as a const real64 *.
262 /// \retval const real64 * valid for as many bytes as were allocated.
263
264 const real64 * Buffer_real64 () const
265 {
266 return (const real64 *) Buffer ();
267 }
268
269 private:
270
271 // Hidden copy constructor and assignment operator.
272
273 dng_memory_data (const dng_memory_data &data);
274
275 dng_memory_data & operator= (const dng_memory_data &data);
276
277 };
278
279/*****************************************************************************/
280
281/// \brief Class to provide resource acquisition is instantiation discipline for
282/// image buffers and other larger memory allocations.
283///
284/// This class requires a dng_memory_allocator for allocation.
285
286class dng_memory_block
287 {
288
289 private:
290
291 uint32 fLogicalSize;
292
293 char *fBuffer;
294
295 protected:
296
297 dng_memory_block (uint32 logicalSize)
298 : fLogicalSize (logicalSize)
299 , fBuffer (NULL)
300 {
301 }
302
303 uint32 PhysicalSize ()
304 {
305
306 // This size is padded for TWO reasons! The first is allow alignment
307 // to 16-byte boundaries if the allocator does not do that already. The
308 // second, which is very important, so to provide safe overread areas for
309 // SSE2-type bottlenecks, which can often be written faster by allowing them
310 // to reading slightly block. Someone on the image core them did not
311 // understand this and removed this padding. I'm undoing this removal
312 // and restoring this padding, since removing it might lead to memory
313 // access crashes in some cases.
314
315 // This padding is throwing off all of our allocations (f.e. dng_string, pixel buffers, etc)
316 // that uses dng_memory_block on iOS/Android that is memory limited. Imagecore carefully
317 // allocates pow2 tile buffers, but this bumps us to the next ssd block (+4K).
318 // This also makes it difficult to identify memory reports in Instruments since all
319 // numbers are off by 64. Imagecore never crashed from the removal of the padding.
320 // The allocator on Win64/Mac64 is 16-byte aligned already. iOS is too.
321 // Linux is 8 byte, but it's using mem_align.
322 // We should fix the SIMD routines and revisit removing this padding - Alec.
323
324 uint32 result;
325 if (!SafeUint32Add(fLogicalSize, 64u, &result))
326 {
327 ThrowMemoryFull("Arithmetic overflow in PhysicalSize()");
328 }
329
330 return result;
331
332 }
333
334 void SetBuffer (void *p)
335 {
336 fBuffer = (char *) ((((uintptr) p) + 15) & ~((uintptr) 15));
337 }
338
339 public:
340
341 virtual ~dng_memory_block ()
342 {
343 }
344
345 dng_memory_block * Clone (dng_memory_allocator &allocator) const;
346
347 /// Getter for available size, in bytes, of memory block.
348 /// \retval size in bytes of available memory in memory block.
349
350 uint32 LogicalSize () const
351 {
352 return fLogicalSize;
353 }
354
355 /// Return pointer to allocated memory as a void *..
356 /// \retval void * valid for as many bytes as were allocated.
357
358 void * Buffer ()
359 {
360 return fBuffer;
361 }
362
363 /// Return pointer to allocated memory as a const void *.
364 /// \retval const void * valid for as many bytes as were allocated.
365
366 const void * Buffer () const
367 {
368 return fBuffer;
369 }
370
371 /// Return pointer to allocated memory as a char *.
372 /// \retval char * valid for as many bytes as were allocated.
373
374 char * Buffer_char ()
375 {
376 return (char *) Buffer ();
377 }
378
379 /// Return pointer to allocated memory as a const char *.
380 /// \retval const char * valid for as many bytes as were allocated.
381
382 const char * Buffer_char () const
383 {
384 return (const char *) Buffer ();
385 }
386
387 /// Return pointer to allocated memory as a uint8 *.
388 /// \retval uint8 * valid for as many bytes as were allocated.
389
390 uint8 * Buffer_uint8 ()
391 {
392 return (uint8 *) Buffer ();
393 }
394
395 /// Return pointer to allocated memory as a const uint8 *.
396 /// \retval const uint8 * valid for as many bytes as were allocated.
397
398 const uint8 * Buffer_uint8 () const
399 {
400 return (const uint8 *) Buffer ();
401 }
402
403 /// Return pointer to allocated memory as a uint16 *.
404 /// \retval uint16 * valid for as many bytes as were allocated.
405
406 uint16 * Buffer_uint16 ()
407 {
408 return (uint16 *) Buffer ();
409 }
410
411 /// Return pointer to allocated memory as a const uint16 *.
412 /// \retval const uint16 * valid for as many bytes as were allocated.
413
414 const uint16 * Buffer_uint16 () const
415 {
416 return (const uint16 *) Buffer ();
417 }
418
419 /// Return pointer to allocated memory as a int16 *.
420 /// \retval int16 * valid for as many bytes as were allocated.
421
422 int16 * Buffer_int16 ()
423 {
424 return (int16 *) Buffer ();
425 }
426
427 /// Return pointer to allocated memory as a const int16 *.
428 /// \retval const int16 * valid for as many bytes as were allocated.
429
430 const int16 * Buffer_int16 () const
431 {
432 return (const int16 *) Buffer ();
433 }
434
435 /// Return pointer to allocated memory as a uint32 *.
436 /// \retval uint32 * valid for as many bytes as were allocated.
437
438 uint32 * Buffer_uint32 ()
439 {
440 return (uint32 *) Buffer ();
441 }
442
443 /// Return pointer to allocated memory as a const uint32 *.
444 /// \retval const uint32 * valid for as many bytes as were allocated.
445
446 const uint32 * Buffer_uint32 () const
447 {
448 return (const uint32 *) Buffer ();
449 }
450
451 /// Return pointer to allocated memory as a int32 *.
452 /// \retval int32 * valid for as many bytes as were allocated.
453
454 int32 * Buffer_int32 ()
455 {
456 return (int32 *) Buffer ();
457 }
458
459 /// Return pointer to allocated memory as a const int32 *.
460 /// \retval const int32 * valid for as many bytes as were allocated.
461
462 const int32 * Buffer_int32 () const
463 {
464 return (const int32 *) Buffer ();
465 }
466
467 /// Return pointer to allocated memory as a real32 *.
468 /// \retval real32 * valid for as many bytes as were allocated.
469
470 real32 * Buffer_real32 ()
471 {
472 return (real32 *) Buffer ();
473 }
474
475 /// Return pointer to allocated memory as a const real32 *.
476 /// \retval const real32 * valid for as many bytes as were allocated.
477
478 const real32 * Buffer_real32 () const
479 {
480 return (const real32 *) Buffer ();
481 }
482
483 /// Return pointer to allocated memory as a real64 *.
484 /// \retval real64 * valid for as many bytes as were allocated.
485
486 real64 * Buffer_real64 ()
487 {
488 return (real64 *) Buffer ();
489 }
490
491 /// Return pointer to allocated memory as a const real64 *.
492 /// \retval const real64 * valid for as many bytes as were allocated.
493
494 const real64 * Buffer_real64 () const
495 {
496 return (const real64 *) Buffer ();
497 }
498
499 private:
500
501 // Hidden copy constructor and assignment operator.
502
503 dng_memory_block (const dng_memory_block &data);
504
505 dng_memory_block & operator= (const dng_memory_block &data);
506
507 };
508
509/*****************************************************************************/
510
511/// \brief Interface for dng_memory_block allocator.
512
513class dng_memory_allocator
514 {
515
516 public:
517
518 virtual ~dng_memory_allocator ()
519 {
520 }
521
522 /// Allocate a dng_memory block.
523 /// \param size Number of bytes in memory block.
524 /// \retval A dng_memory_block with at least size bytes of valid storage.
525 /// \exception dng_exception with fErrorCode equal to dng_error_memory.
526
527 virtual dng_memory_block * Allocate (uint32 size);
528
529 };
530
531/*****************************************************************************/
532
533/// \brief Default memory allocator used if NULL is passed in for allocator
534/// when constructing a dng_host.
535///
536/// Uses new and delete for memory block object and malloc/free for underlying
537/// buffer.
538
539extern dng_memory_allocator gDefaultDNGMemoryAllocator;
540
541/*****************************************************************************/
542
543// C++ allocator (i.e. an implementation of the Allocator concept) that throws a
544// dng_exception with error code dng_error_memory if it cannot allocate memory.
545template <typename T>
546class dng_std_allocator
547 {
548
549 public:
550 typedef T value_type;
551
552 // Default implementations of default constructor and copy constructor.
553 dng_std_allocator () = default;
554 dng_std_allocator (const dng_std_allocator&) = default;
555 template<typename U> dng_std_allocator (const dng_std_allocator<U>&) {}
556
557 T* allocate (size_t n)
558 {
559 const size_t size = SafeSizetMult(n, sizeof (T));
560 T *retval = static_cast<T *> (malloc (size));
561 if (!retval) {
562 ThrowMemoryFull ();
563 }
564 return retval;
565 }
566
567 void deallocate (T *ptr, size_t n)
568 {
569 free (ptr);
570 }
571};
572
573template <class T>
574bool operator== (const dng_std_allocator<T> &a1,
575 const dng_std_allocator<T> &a2)
576 {
577 return true;
578 }
579
580template <class T>
581bool operator!= (const dng_std_allocator<T> &a1,
582 const dng_std_allocator<T> &a2)
583 {
584 return false;
585 }
586
587// std::vector specialized to use dng_std_allocator for allocation.
588template <class T> using dng_std_vector = std::vector<T, dng_std_allocator<T> >;
589
590/*****************************************************************************/
591
592#endif
593
594/*****************************************************************************/
595