| /*****************************************************************************/ |
| // Copyright 2006-2007 Adobe Systems Incorporated |
| // All Rights Reserved. |
| // |
| // NOTICE: Adobe permits you to use, modify, and distribute this file in |
| // accordance with the terms of the Adobe license agreement accompanying it. |
| /*****************************************************************************/ |
| |
| /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_memory.h#1 $ */ |
| /* $DateTime: 2012/05/30 13:28:51 $ */ |
| /* $Change: 832332 $ */ |
| /* $Author: tknoll $ */ |
| |
| /** Support for memory allocation. |
| */ |
| |
| /*****************************************************************************/ |
| |
| #ifndef __dng_memory__ |
| #define __dng_memory__ |
| |
| /*****************************************************************************/ |
| |
| #include "dng_classes.h" |
| #include "dng_exceptions.h" |
| #include "dng_safe_arithmetic.h" |
| #include "dng_types.h" |
| |
| #include <cstdlib> |
| #include <vector> |
| |
| /*****************************************************************************/ |
| |
| /// \brief Class to provide resource acquisition is instantiation discipline |
| /// for small memory allocations. |
| /// |
| /// This class does not use dng_memory_allocator for memory allocation. |
| |
| class dng_memory_data |
| { |
| |
| private: |
| |
| char *fBuffer; |
| |
| public: |
| |
| /// Construct an empty memory buffer using malloc. |
| /// \exception dng_memory_full with fErrorCode equal to dng_error_memory. |
| |
| dng_memory_data (); |
| |
| /// Construct memory buffer of size bytes using malloc. |
| /// \param size Number of bytes of memory needed. |
| /// \exception dng_memory_full with fErrorCode equal to dng_error_memory. |
| |
| dng_memory_data (uint32 size); |
| |
| /// Note: This constructor is for internal use only and should not be |
| /// considered part of the DNG SDK API. |
| /// |
| /// Construct memory buffer of count elements of elementSize bytes each. |
| /// \param count Number of elements. |
| /// \param elementSize Size of each element. |
| /// \exception dng_memory_full with fErrorCode equal to dng_error_memory. |
| dng_memory_data (uint32 count, std::size_t elementSize); |
| |
| /// Release memory buffer using free. |
| |
| ~dng_memory_data (); |
| |
| /// Clear existing memory buffer and allocate new memory of size bytes. |
| /// \param size Number of bytes of memory needed. |
| /// \exception dng_memory_full with fErrorCode equal to dng_error_memory. |
| |
| void Allocate (uint32 size); |
| |
| /// Note: This method is for internal use only and should not be |
| /// considered part of the DNG SDK API. |
| /// |
| /// Clear existing memory buffer and allocate new memory of count |
| /// elements of elementSize bytes each. |
| /// \param count Number of elements. |
| /// \param elementSize Size of each element. |
| /// \exception dng_memory_full with fErrorCode equal to dng_error_memory. |
| void Allocate (uint32 count, std::size_t elementSize); |
| |
| /// Release any allocated memory using free. Object is still valid and |
| /// Allocate can be called again. |
| |
| void Clear (); |
| |
| /// Return pointer to allocated memory as a void *.. |
| /// \retval void * valid for as many bytes as were allocated. |
| |
| void * Buffer () |
| { |
| return fBuffer; |
| } |
| |
| /// Return pointer to allocated memory as a const void *. |
| /// \retval const void * valid for as many bytes as were allocated. |
| |
| const void * Buffer () const |
| { |
| return fBuffer; |
| } |
| |
| /// Return pointer to allocated memory as a char *. |
| /// \retval char * valid for as many bytes as were allocated. |
| |
| char * Buffer_char () |
| { |
| return (char *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const char *. |
| /// \retval const char * valid for as many bytes as were allocated. |
| |
| const char * Buffer_char () const |
| { |
| return (const char *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a uint8 *. |
| /// \retval uint8 * valid for as many bytes as were allocated. |
| |
| uint8 * Buffer_uint8 () |
| { |
| return (uint8 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const uint8 *. |
| /// \retval const uint8 * valid for as many bytes as were allocated. |
| |
| const uint8 * Buffer_uint8 () const |
| { |
| return (const uint8 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a uint16 *. |
| /// \retval uint16 * valid for as many bytes as were allocated. |
| |
| uint16 * Buffer_uint16 () |
| { |
| return (uint16 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const uint16 *. |
| /// \retval const uint16 * valid for as many bytes as were allocated. |
| |
| const uint16 * Buffer_uint16 () const |
| { |
| return (const uint16 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a int16 *. |
| /// \retval int16 * valid for as many bytes as were allocated. |
| |
| int16 * Buffer_int16 () |
| { |
| return (int16 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const int16 *. |
| /// \retval const int16 * valid for as many bytes as were allocated. |
| |
| const int16 * Buffer_int16 () const |
| { |
| return (const int16 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a uint32 *. |
| /// \retval uint32 * valid for as many bytes as were allocated. |
| |
| uint32 * Buffer_uint32 () |
| { |
| return (uint32 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a uint32 *. |
| /// \retval uint32 * valid for as many bytes as were allocated. |
| |
| const uint32 * Buffer_uint32 () const |
| { |
| return (const uint32 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const int32 *. |
| /// \retval const int32 * valid for as many bytes as were allocated. |
| |
| int32 * Buffer_int32 () |
| { |
| return (int32 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const int32 *. |
| /// \retval const int32 * valid for as many bytes as were allocated. |
| |
| const int32 * Buffer_int32 () const |
| { |
| return (const int32 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a uint64 *. |
| /// \retval uint64 * valid for as many bytes as were allocated. |
| |
| uint64 * Buffer_uint64 () |
| { |
| return (uint64 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a uint64 *. |
| /// \retval uint64 * valid for as many bytes as were allocated. |
| |
| const uint64 * Buffer_uint64 () const |
| { |
| return (const uint64 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const int64 *. |
| /// \retval const int64 * valid for as many bytes as were allocated. |
| |
| int64 * Buffer_int64 () |
| { |
| return (int64 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const int64 *. |
| /// \retval const int64 * valid for as many bytes as were allocated. |
| |
| const int64 * Buffer_int64 () const |
| { |
| return (const int64 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a real32 *. |
| /// \retval real32 * valid for as many bytes as were allocated. |
| |
| real32 * Buffer_real32 () |
| { |
| return (real32 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const real32 *. |
| /// \retval const real32 * valid for as many bytes as were allocated. |
| |
| const real32 * Buffer_real32 () const |
| { |
| return (const real32 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a real64 *. |
| /// \retval real64 * valid for as many bytes as were allocated. |
| |
| real64 * Buffer_real64 () |
| { |
| return (real64 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const real64 *. |
| /// \retval const real64 * valid for as many bytes as were allocated. |
| |
| const real64 * Buffer_real64 () const |
| { |
| return (const real64 *) Buffer (); |
| } |
| |
| private: |
| |
| // Hidden copy constructor and assignment operator. |
| |
| dng_memory_data (const dng_memory_data &data); |
| |
| dng_memory_data & operator= (const dng_memory_data &data); |
| |
| }; |
| |
| /*****************************************************************************/ |
| |
| /// \brief Class to provide resource acquisition is instantiation discipline for |
| /// image buffers and other larger memory allocations. |
| /// |
| /// This class requires a dng_memory_allocator for allocation. |
| |
| class dng_memory_block |
| { |
| |
| private: |
| |
| uint32 fLogicalSize; |
| |
| char *fBuffer; |
| |
| protected: |
| |
| dng_memory_block (uint32 logicalSize) |
| : fLogicalSize (logicalSize) |
| , fBuffer (NULL) |
| { |
| } |
| |
| uint32 PhysicalSize () |
| { |
| |
| // This size is padded for TWO reasons! The first is allow alignment |
| // to 16-byte boundaries if the allocator does not do that already. The |
| // second, which is very important, so to provide safe overread areas for |
| // SSE2-type bottlenecks, which can often be written faster by allowing them |
| // to reading slightly block. Someone on the image core them did not |
| // understand this and removed this padding. I'm undoing this removal |
| // and restoring this padding, since removing it might lead to memory |
| // access crashes in some cases. |
| |
| // This padding is throwing off all of our allocations (f.e. dng_string, pixel buffers, etc) |
| // that uses dng_memory_block on iOS/Android that is memory limited. Imagecore carefully |
| // allocates pow2 tile buffers, but this bumps us to the next ssd block (+4K). |
| // This also makes it difficult to identify memory reports in Instruments since all |
| // numbers are off by 64. Imagecore never crashed from the removal of the padding. |
| // The allocator on Win64/Mac64 is 16-byte aligned already. iOS is too. |
| // Linux is 8 byte, but it's using mem_align. |
| // We should fix the SIMD routines and revisit removing this padding - Alec. |
| |
| uint32 result; |
| if (!SafeUint32Add(fLogicalSize, 64u, &result)) |
| { |
| ThrowMemoryFull("Arithmetic overflow in PhysicalSize()"); |
| } |
| |
| return result; |
| |
| } |
| |
| void SetBuffer (void *p) |
| { |
| fBuffer = (char *) ((((uintptr) p) + 15) & ~((uintptr) 15)); |
| } |
| |
| public: |
| |
| virtual ~dng_memory_block () |
| { |
| } |
| |
| dng_memory_block * Clone (dng_memory_allocator &allocator) const; |
| |
| /// Getter for available size, in bytes, of memory block. |
| /// \retval size in bytes of available memory in memory block. |
| |
| uint32 LogicalSize () const |
| { |
| return fLogicalSize; |
| } |
| |
| /// Return pointer to allocated memory as a void *.. |
| /// \retval void * valid for as many bytes as were allocated. |
| |
| void * Buffer () |
| { |
| return fBuffer; |
| } |
| |
| /// Return pointer to allocated memory as a const void *. |
| /// \retval const void * valid for as many bytes as were allocated. |
| |
| const void * Buffer () const |
| { |
| return fBuffer; |
| } |
| |
| /// Return pointer to allocated memory as a char *. |
| /// \retval char * valid for as many bytes as were allocated. |
| |
| char * Buffer_char () |
| { |
| return (char *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const char *. |
| /// \retval const char * valid for as many bytes as were allocated. |
| |
| const char * Buffer_char () const |
| { |
| return (const char *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a uint8 *. |
| /// \retval uint8 * valid for as many bytes as were allocated. |
| |
| uint8 * Buffer_uint8 () |
| { |
| return (uint8 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const uint8 *. |
| /// \retval const uint8 * valid for as many bytes as were allocated. |
| |
| const uint8 * Buffer_uint8 () const |
| { |
| return (const uint8 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a uint16 *. |
| /// \retval uint16 * valid for as many bytes as were allocated. |
| |
| uint16 * Buffer_uint16 () |
| { |
| return (uint16 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const uint16 *. |
| /// \retval const uint16 * valid for as many bytes as were allocated. |
| |
| const uint16 * Buffer_uint16 () const |
| { |
| return (const uint16 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a int16 *. |
| /// \retval int16 * valid for as many bytes as were allocated. |
| |
| int16 * Buffer_int16 () |
| { |
| return (int16 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const int16 *. |
| /// \retval const int16 * valid for as many bytes as were allocated. |
| |
| const int16 * Buffer_int16 () const |
| { |
| return (const int16 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a uint32 *. |
| /// \retval uint32 * valid for as many bytes as were allocated. |
| |
| uint32 * Buffer_uint32 () |
| { |
| return (uint32 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const uint32 *. |
| /// \retval const uint32 * valid for as many bytes as were allocated. |
| |
| const uint32 * Buffer_uint32 () const |
| { |
| return (const uint32 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a int32 *. |
| /// \retval int32 * valid for as many bytes as were allocated. |
| |
| int32 * Buffer_int32 () |
| { |
| return (int32 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const int32 *. |
| /// \retval const int32 * valid for as many bytes as were allocated. |
| |
| const int32 * Buffer_int32 () const |
| { |
| return (const int32 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a real32 *. |
| /// \retval real32 * valid for as many bytes as were allocated. |
| |
| real32 * Buffer_real32 () |
| { |
| return (real32 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const real32 *. |
| /// \retval const real32 * valid for as many bytes as were allocated. |
| |
| const real32 * Buffer_real32 () const |
| { |
| return (const real32 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a real64 *. |
| /// \retval real64 * valid for as many bytes as were allocated. |
| |
| real64 * Buffer_real64 () |
| { |
| return (real64 *) Buffer (); |
| } |
| |
| /// Return pointer to allocated memory as a const real64 *. |
| /// \retval const real64 * valid for as many bytes as were allocated. |
| |
| const real64 * Buffer_real64 () const |
| { |
| return (const real64 *) Buffer (); |
| } |
| |
| private: |
| |
| // Hidden copy constructor and assignment operator. |
| |
| dng_memory_block (const dng_memory_block &data); |
| |
| dng_memory_block & operator= (const dng_memory_block &data); |
| |
| }; |
| |
| /*****************************************************************************/ |
| |
| /// \brief Interface for dng_memory_block allocator. |
| |
| class dng_memory_allocator |
| { |
| |
| public: |
| |
| virtual ~dng_memory_allocator () |
| { |
| } |
| |
| /// Allocate a dng_memory block. |
| /// \param size Number of bytes in memory block. |
| /// \retval A dng_memory_block with at least size bytes of valid storage. |
| /// \exception dng_exception with fErrorCode equal to dng_error_memory. |
| |
| virtual dng_memory_block * Allocate (uint32 size); |
| |
| }; |
| |
| /*****************************************************************************/ |
| |
| /// \brief Default memory allocator used if NULL is passed in for allocator |
| /// when constructing a dng_host. |
| /// |
| /// Uses new and delete for memory block object and malloc/free for underlying |
| /// buffer. |
| |
| extern dng_memory_allocator gDefaultDNGMemoryAllocator; |
| |
| /*****************************************************************************/ |
| |
| // C++ allocator (i.e. an implementation of the Allocator concept) that throws a |
| // dng_exception with error code dng_error_memory if it cannot allocate memory. |
| template <typename T> |
| class dng_std_allocator |
| { |
| |
| public: |
| typedef T value_type; |
| |
| // Default implementations of default constructor and copy constructor. |
| dng_std_allocator () = default; |
| dng_std_allocator (const dng_std_allocator&) = default; |
| template<typename U> dng_std_allocator (const dng_std_allocator<U>&) {} |
| |
| T* allocate (size_t n) |
| { |
| const size_t size = SafeSizetMult(n, sizeof (T)); |
| T *retval = static_cast<T *> (malloc (size)); |
| if (!retval) { |
| ThrowMemoryFull (); |
| } |
| return retval; |
| } |
| |
| void deallocate (T *ptr, size_t n) |
| { |
| free (ptr); |
| } |
| }; |
| |
| template <class T> |
| bool operator== (const dng_std_allocator<T> &a1, |
| const dng_std_allocator<T> &a2) |
| { |
| return true; |
| } |
| |
| template <class T> |
| bool operator!= (const dng_std_allocator<T> &a1, |
| const dng_std_allocator<T> &a2) |
| { |
| return false; |
| } |
| |
| // std::vector specialized to use dng_std_allocator for allocation. |
| template <class T> using dng_std_vector = std::vector<T, dng_std_allocator<T> >; |
| |
| /*****************************************************************************/ |
| |
| #endif |
| |
| /*****************************************************************************/ |