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 | |
39 | class 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 | |
286 | class 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 | |
513 | class 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 | |
539 | extern 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. |
545 | template <typename T> |
546 | class 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 | |
573 | template <class T> |
574 | bool operator== (const dng_std_allocator<T> &a1, |
575 | const dng_std_allocator<T> &a2) |
576 | { |
577 | return true; |
578 | } |
579 | |
580 | template <class T> |
581 | bool 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. |
588 | template <class T> using dng_std_vector = std::vector<T, dng_std_allocator<T> >; |
589 | |
590 | /*****************************************************************************/ |
591 | |
592 | #endif |
593 | |
594 | /*****************************************************************************/ |
595 | |