Nov 4, 2018

[cppcon 2018] An allocator is a handle to a heap - Lessons learned from std::pmr - Arthur O'Dwyer

This talk given by Arthur is a recap from his talk on C++Now 2018.

Define object:
  • An object has an address.
    (Unlike pure value, which will be replaced with the value by compiler in the assembly)
  • Has state.
  • Address, pointer, name, unique identifier, handle --- all synonymous for the purpose, they are value type.

Sequence Container:
  • Act as object.
  • Act as value.


Define allocator:
For std::vector,
  • Where does the memory for v[i] come from?
    • From A::allocate(n)
  • What is the thing represented by points to the value?
    • From A::pointer type.
  • Container holds an instance of the allocator type A within itself.
  • What can we put inside the allocator instance?
    • :-)


  • Has a pointer to a std::pmr::memory_resource
  • All the shared state goes into the memory_resource

Usage:
// std
namespace pmr {
    template <class T>
    using vector = std::vector<T, std::pmr::polymorphic_allocator<T>>;
}
std::vector<int, std::pmr::polymorphic_allocator<int>> vec(allocator_instance);






Allocator is:
A value represents a handle to a source of memory with some other orthogonal pieces.
Thus:
  • Allocator types should be copyable, just like pointers.
  • Allocator types should be cheaply copyable, like pointers.
    They need not be trivially copyable
  • Memory-resource types should generally be immobile.


Recap, Allocators must be 'copy-only' types
i.e If std::move(allocator) should do a copy instead of move, exactly act like std::move(pointer) should remains the same pointer.


Reference:




An allocator should satisfy allocator completeness requirements.



Allocator completeness requirements
An allocator type X for type T additionally satisfies the allocator completeness requirements if both of the following are true regardless of whether T is a complete type:
  • X is a complete type
  • Except for value_type, all the member types of std::allocator_traits<X> are complete types.


Take aways:
  • Use std::allocator_traits::construct to create instance.
  • iterator_facade
    We implement a complete set of primitive functions (and data members); then inherit from iterator_facade to provide the standard zoo of operators.
  • iterator_adaptor
    We override some but not all the primitive functions; then inherit from iterator_adaptor<Base> to provide the missing parts.
  • Executor coming in C++23
    P0443: std::executor

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.