1 / 27

CIS 4930 Application Development Using C++ Dr. Kun Suk Kim CISE Department, University of Florida

CIS 4930 Application Development Using C++ Dr. Kun Suk Kim CISE Department, University of Florida. Allocators. Objectives. Using allocators as an application programmer Using allocators as an library programmer The default allocator A user-defined allocator

mili
Download Presentation

CIS 4930 Application Development Using C++ Dr. Kun Suk Kim CISE Department, University of Florida

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CIS 4930Application Development Using C++Dr. Kun Suk KimCISE Department, University of Florida Allocators

  2. Objectives • Using allocators as an application programmer • Using allocators as an library programmer • The default allocator • A user-defined allocator • Utilities for uninitialized memory • Ch 15

  3. Allocators • Low-level mechanisms for allocating and deallocating memory • A special memory model • Abstraction to translate the need to use memory into a raw call for memory • Different allocator types represent different schemes for memory management • Very specialized purposes

  4. Allocators • The STL includes several low-level algorithms for manipulating uninitialized memory • Default allocator • Default value everywhere an allocator can be used as an argument • Calls the new and delete operators namespace std { template <class T> class allocator; }

  5. Using Allocators as an Application Programmer • Pass the allocator as a template argument • Examples: • A vector with special allocator MyAlloc<> std::vector<int,MyAlloc<int> > v; • An int/float map with special allocator std::map<int,float,less<int>, MyAlloc<std::pair<const int,float> > > m; • A string with special allocator std::basic_string<char,std::char_char_traits<char>, MyAlloc<char> > s;

  6. Using Allocators as an Application Programmer • Special type definitions that use special allocators • Examples: • Special string type that uses special allocator typedef std::basic_string<char,std::char_char_traits<char>, MyAlloc<char> > xstring; • Special string/string map type that uses special allocator typedef std::map<xstring,xstring,less<xstring>, MyAlloc<std::pair<const xstring, xstring> > > xmap; • Create object of this type xmap mymap;

  7. Using Allocators as an Application Programmer • No difference to use objects with other than the default allocator • Don’t mix elements with different allocators • Otherwise, the behavior is undefined • Can check whether two allocators use the same memory model if (mymap.get_allocator() == s.get_allocator()) { // OK, mymap and s use the same or interchangeable allocators … }

  8. Using Allocators as a Library Programmer • Use allocators to implement containers and other components that are able to handle different allocators • With allocators, containers and algorithms can be parameterized by the way the elements are stored • Fundamental allocator operations

  9. Using Allocators as a Library Programmer • An implementation of a vector • A vector gets its allocator as a template or a constructor argument and • stores it somewhere internally namespace std { template <class T, class Allocator = allocator<T> > class vector { private: Allocator alloc; // allocator T* elems; // array of elements size_type numElems; // number of elements size_type sizeElems; // size of memory for the elements …

  10. Using Allocators as a Library Programmer public: explicit vector (const Allocator& Allocator()); explicit vector (size_type num, const T& val=T(), const Allocator& Allocator()); template <class InputIterator> vector(InputIterator beg, InputIterator end, const Allocator& Allocator()); vector(const vector<T, Allocator>& v); }; }

  11. Using Allocators as a Library Programmer • Implementation of the second constructor • Initializes the vector by num elements of value val namespace std { template <class T, class Allocator> vector<T,Allocator>::vector(size_type num, const T& val, const Allocator& a) : alloc(a) { sizeElems = numElems = num; elems = alloc.allocate(num); for (size_type i = 0; i < num; ++i) alloc.construct(&elems[i], val); } }

  12. Using Allocators as a Library Programmer • Convenience functions for uninitialized memory • These functions either succeed or have no effect

  13. Utilities for Uninitialized Memory namespace std { template <class ForwIter, class T> void uninitialized_fill(ForwIter beg, ForwIter end, const T& value) { typedef typename iterator_traits<ForwIter>::value_type VT; ForwIter save(beg); try { for (; beg!=end; ++beg) new (static_cast<void*>(&*beg))VT(value); } catch (…) { for (; save!=beg; ++save) save->~VT(); throw; } } }

  14. Utilities for Uninitialized Memory namespace std { template <class ForwIter, class Size, class T> void uninitialized_fill_n(ForwIter beg, Size num, const T& value) { typedef typename iterator_traits<ForwIter>::value_type VT; ForwIter save(beg); try { for (; num--; ++beg) new (static_cast<void*>(&*beg))VT(value); } catch (…) { for (; save!=beg; ++save) save->~VT(); throw; } } }

  15. Utilities for Uninitialized Memory namespace std { template <class InputIter, class ForwIter> ForwIter uninitialized_copy(InputIter beg, InputIter end, ForwIter dest) { typedef typename iterator_traits<ForwIter>::value_type VT; ForwIter save(dest); try { for (; beg!=end; ++beg,++dest) new (static_cast<void*>(&*dest))VT(*beg); return dest; } catch (…) { for (; save!=beg; ++save) save->~VT(); throw; } } }

  16. Using Allocators as a Library Programmer • Implementation of the second constructor • Using unitialized_fill_n() namespace std { template <class T, class Allocator> vector<T,Allocator>::vector(size_type num, const T& val, const Allocator& a) : alloc(a) { sizeElems = numElems = num; elems = alloc.allocate(num); unitialized_fill_n(elems, num, val); } }

  17. Using Allocators as a Library Programmer • Implementation of reserve() namespace std { template <class T, class Allocator> void vector<T,Allocator>::reserve(size_type size) { if (size <= sizeElems) return; T* newmem = alloc.allocate(size); unitialized_copy(elems, elems+numElems, newmem); for (size_type i = 0; i < numElems; ++i) alloc.destroy(&elems[i]); alloc.deallocate(elems, sizeElems); sizeElems = size; elems = newmem; } }

  18. Using Allocators as a Library Programmer • Raw storage iterators • Iterate over uninitialized memory to initialize it • First template argument (T*): output iterator for the type of the elements • Second template argument (T): the type of the elements • Initialize the storage to which elems refers by the value in range [x.begin(),x.end()) copy (x.begin(), x.end(), // source raw_storage_iterator<T*,T>(elems)); // destination

  19. Default Allocator • Uses global operators new and delete to allocate and deallocate memory • allocate() may throw a bad_alloc exception • May be optimized • By reusing deallocated memory • By allocating more memory than needed to save time in additional allocations

  20. Default Allocator • Constructors and destructor • Nothing to do because the allocator has no state • max_size() • Returns the largest value the can be passed meaningfully to allocate() to allocate storage • allocate() • Allocate memory with global new • deallocate() • Deallocate memory with global delete

  21. Default Allocator namespace std { template <class T> class allocator { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef T value_type; template <class U> struct rebind { typedef allocator<U> other; };

  22. Default Allocator pointer address (reference value) const { return &value; } const_pointer address (const_reference value) const { return &value; } allocator() throw() { } allocator(const allocator&) throw() { } template <class U> allocator (const allocator<U>&) throw() { } ~allocator() throw() { } size_type max_size () const throw() { return numeric_limits<size_t>::max() / sizeof(T); } pointer allocate (size_type num, allocator<void>::const_pointer hint = 0) { return (pointer)(::operator new(num*sizeof(T))); } void construct (pointer p, const T& value) { new((void*)p)T(value); }

  23. Default Allocator void destroy (pointer p) { p->~T(); } void deallocate (pointer p, size_type num) { ::operator delete((void*)p); } }; // return that all specializations of this allocator are interchangeable template <class T1, class T2> bool operator== (const allocator<T1>&, const allocator<T2>&) throw() { return true; } template <class T1, class T2> bool operator!= (const allocator<T1>&, const allocator<T2>&) throw() { return false; } }

  24. Default Allocator • Template structure rebind<> • Any allocator may allocate storage of another type indirectly • Allocator::rebind<T2>::other • The type of the same allocator specialized for elements of type T2 • rebind<> is useful for • implementing a container and • allocating memory for a type that differs from the element’s type

  25. Default Allocator • Implementation of a deque namespace std { template <class T, class Allocator = allocator<T> > class deque { private: typedef typename Allocator::rebind<T*>::other PtrAllocator; Allocator alloc; // allocator for values of type T PtrAllocator block_alloc; // allocator for values of type T* T** elems; // array of blocks of elements … }; }

  26. Default Allocator • Default has the specialization for type void namespace std { template <> class allocator<void> { public: typedef void* pointer; typedef const void* const_pointer; typedef void value_type; template <class U> struct rebind { typedef allocator<U> other; }; }; }

  27. A User-Defined Allocator • The only things that differ from the implementation of the default allocator • max_size() • allocate() • deallocate() • In these three functions, you program your own policy of memory allocation, such as • Reusing memory instead of freeing it immediately • Using share memory • Mapping the memory to a segment of an object-oriented database

More Related