You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
595 lines
16 KiB
595 lines
16 KiB
/*****************************************************************************/
|
|
// 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
|
|
|
|
/*****************************************************************************/
|