10.2 Memory

The Memory class is the basic templated data container of the LYRIC library. It is merely a C++ wrapper for standard C memory handling functions such as memcpy, memmove, etc. But since it is a C++ class, it provides functionalities like automatic resource deallocation and an exception based error handling.

The Memory class is to be used only with either language built-in types (such as int, float, etc), or fastmemops classes. The later can be defined by programmers as described in section 6.2. The Memory class can also be used to store pointers, but all the data cloning has to be implemented manually. Better classes such as Array1D, List, or from these base classes derived classes exist in LYRIC, which provide easier to use containers.

The Memory class is intended to be used only by LYRIC library developers, and only in very rare cases. Memory is used by both Array1D (resp. Memory1D), and List, to handle memory block allocation, deallocation, copying, and moving.


Synopsis


  #include <lyric/Memory.hpp>
  
  template <class MIT>
  class Memory
  {
  public:
    ~Memory ();
    Memory ();
    Memory (Size size)
      throw (Exception::Memory::Alloc);
    Memory (const Memory& block)
      throw (Exception::Memory::Alloc);
    Memory (Size size, const MIT* items)
      throw (Exception::Memory::Alloc);
    MIT& operator [] (Size index)
      throw (Exception::Memory::Range);
    const MIT& operator [] (Size index) const
      throw (Exception::Memory::Range);
    Size size () const;
    void create (Size size)
      throw (Exception::Memory::Alloc);
    void create (Size size, const MIT* items)
      throw (Exception::Memory::Alloc);
    void resize (Size newsize)
      throw (Exception::Memory::Alloc);
    void destroy ();
    void fill (Size index, Size size, const MIT& item);
    void clone (const Memory& block)
      throw (Exception::Memory::Alloc);
    void copy (Size index, const Memory& block)
      throw (Exception::Memory::Range);
    void copy (Size index, const Memory& block, Size size)
      throw (Exception::Memory::Range);
    void move (Size size, Size src, Size dest)
      throw (Exception::Memory::Move);
  protected:
    void ndcreate (Size size)
      throw (::Exception::Memory::Alloc);
    void recover (Size size, MIT* data);
    void chkmove (Size size, Size src, Size dest)
      throw (Exception::Memory::Move);
  private:
    Size size_;
    MIT* data_;
    Memory& operator = (const Memory& block)
      throw (Exception::Memory::Alloc);
    void create_ (Size size)
      throw (Exception::Memory::Alloc);
    void destroy_ ();
  };


Description


˜Memory ()
Destroys this memory block, releasing eventually reserved memory. All stored items are destroyed.

Memory ()
Constructs this as an empty memory block. No memory is reserved, pointers are set to NULL and sizes to zero.
The only guaranteed setting for the future is the size to zero. Code should never rely on NULL pointers, except for internal use.

Memory (Size size)
Constructs this memory block with a given size. A contiguous memory chunk of item-size.size bytes is allocated, and on success the size indicator updated.
|\ Exception::Memory::Alloc
is thrown if not enough memory is found to store size items.

Memory (const Memory& block)
Constructs this memory block from the given memory block. All properties and data of block are cloned into this.
|\ Exception::Memory::Alloc
is thrown if not enough memory was found to store block.size() items.

Memory (Size size, const MIT* items)
Constructs this memory block from the given size and the C-like memory block pointed by items. This constructor tried to reserve space to store size items, then copies size items stored at location pointed by items into this.
Warning  The argument size controls the copy process. Thus the memory location pointed by items and the size * sizeof(MIT) following bytes must be readable by the current process. If not you’ll get memory access errors.
|\ Exception::Memory::Alloc
is thrown if not enough memory was found to store size items.

MIT& operator [...] (Size index)
Returns the reference of item at position index in this memory block. This subscript operator gives read and write access to a given item.
|\ Exception::Memory::Range
is thrown if the given index is out of this container’s size, and only if the -DO_RANGE_CHECK is given to the compiler, resp. if O_RANGE_CHECK is defined.

const MIT& operator [...] (Size index) const
Returns a const reference to item at position index in this memory block. This subscript operator gives read only access to a given item.
|\ Exception::Memory::Range
is thrown if the given index is out of this container’s size, and only if the -DO_RANGE_CHECK is given to the compiler, resp. if O_RANGE_CHECK is defined.

Size size () const
Returns the size of this memory block. The returned value is given in number of items, not bytes.

void create (Size size)
Creates this memory block with the given size. This function tries to reserve size items in memory.
Warning  This function is destructive. Indeed, all data previously stored in this are destroyed before a new memory allocation is done.
|\ Exception::Memory::Alloc
is thrown if not enough memory was found to store size items.

void resize (Size newsize)
Resizes this memory block to the given newsize. If the current size and newsize are identical, no action is taken, else this function tries to reserve newsize items in memory, and then copies the old data previously stored in this to the new memory block. It then releases the old memory block. In case of failure the old size and data are restored in this.
|\ Exception::Memory::Alloc
is thrown if not enough memory was found to store newsize items.

void destroy ()
Destroys this memory block. This function releases the reserved memory block to the system, and sets the size to zero.

void fill (Size index, Size size, const MIT& item)
Fills this memory block with the given item. The filling operation starts at position index, and is performed over size items. No range checking is done in this function. It is assumed that the caller has checked index and size thoroughly.
Graphic browser needed to see picture
Figure 10.1: Illustration of the memory filling algorithm by means of memcpys. The light gray shaded items are the source, and the dark gray shaded ones the destination for the memcpy instructions.

The filling algorithm is written by means of memcpy. It copies the item at first position, then copies it to the next position. It has now 2 contiguous items it can copy to positions 3 and 4 with one memcpy call. With now 4 contiguous items, it can fill positions 5 to 8 in one memcpy. And so on, until size items are filled into this memory block, starting at position index. Figure 10.2 illustrates the memory filling process by means of memcpys.

void clone (const Memory& block)
Clones the given memory block into this memory block. All properties and data of block are cloned into this. This function destroys the data previously stored in this memory block.
|\ Exception::Memory::Alloc
is thrown if not enough memory was found to store block.size() items.

void copy (Size index, const Memory& block)
Copies the data stored in the given memory block into the data part of this memory block, at position index in this. Figure 10.2 illustrates the copy process.
|\ Exception::Memory::Range
is thrown if this is not big enough to store index + block.size() items.


Graphic browser needed to see picture
Figure 10.2: Illusration of the Memory::copy (Size index, const Memory& block) function.


void copy (Size index, const Memory& block, Size size)
Copies a sub-part of the given size of the data stored in the given memory block into the data part of this memory block, at position index in this. Figure 10.2 illustrates the copy process.
|\ Exception::Memory::Range
is thrown if this is not big enough to store index + size items, or if the given size is bigger than block.size().


Graphic browser needed to see picture
Figure 10.3: Illusration of the Memory::copy (Size index, const Memory& block, Size size) function.


void ndcreate (Size size)
Protected
Creates this memory block with the given size. This function tries to reserve size items in memory.
This is the non destructive version of the public create function. It is used in derived classes resize functions, where the old data must remain safe until data copy is done.
Warning  The use of this function assumes that the old memory block is released later by some other function. It is recommended that the old data pointer is saved before this call. The data pointer can be goten with &memory[0], with memory being an object of class Memory.

void recover (Size size, MIT* data)
Protected
Recovers from an old size and data. Assign the size and data to this memory block.
This function is used in derived classes when some data recovery - to set back to old values after a creation exception for example - is needed.
Warning  Use this function with care, since it can have the effect of loosing actually correct size and data pointer values in this memory block.

void chkmove (Size size, Size src, Size dest)
Protected
Checks if the move of size items from position src to dest is possible in this memory block. This function checks if the move would throw some items outside this memory block. If the move would fail it throws an exception, else it does nothing.
|\ Exception::Memory::Move
is thrown if the move is not possible.