RFE: Provide registration-based serialization of polymorphic allocators

Issue #339 new
Amir Kamil created an issue

The UPC++ specification is silent on the treatment of std::pmr::polymorphic_allocator<T> in serialization. Rather than prescribe a specific solution in the spec, we can provide a registration-based implementation of serialization in upcxx-extras. User code would collectively register memory resources, and the implementation would translate between the registered resources when serializing and deserializing a polymorphic_allocator. If an allocator using an unregistered resource is serialized, it would be deserialized using the default resource.

The following is a proposed (untested) implementation:

#include <map>
#include <vector>
#include <memory_resource>

namespace upcxx {
  namespace extras {
    class resource_map {
    public:
      static void add(std::pmr::memory_resource* ptr) {
        assert(registration_map.find(ptr) == registration_map.end());
        registration_map[ptr] = registration_list.size();
        registration_list.push_back(ptr);
      }

      static std::pmr::memory_resource* get_resource(int index) {
        assert(index >= -1 && index < registration_list.size());
        if (index == -1) {
          return std::pmr::get_default_resource();
        }
        return registration_list[index];
      }

      static int get_index(std::pmr::memory_resource* ptr) {
        auto it = registration_map.find(ptr);
        if (it == registration_map.end()) {
          return -1;
        }
        return it->second;
      }

    private:
      static std::vector<std::pmr::memory_resource*> registration_list;
      static std::map<std::pmr::memory_resource*, int> registration_map;
    };

    std::vector<std::pmr::memory_resource*> resource_map::registration_list;
    std::map<std::pmr::memory_resource*, int> resource_map::registration_map;
  } // namespace extras

  template<typename T>
  struct serialization<std::pmr::polymorphic_allocator<T>> {
    template <typename Writer>
    static void serialize(Writer& writer,
                          std::pmr::polymorphic_allocator<T> const& pma) {
      writer.write(extras::resource_map::get_index(pma.resource()));
    }
    template <typename Reader>
    static std::pmr::polymorphic_allocator<T>* deserialize(Reader& reader,
                                                           void* storage) {
      auto resource = extras::resource_map.get_resource(reader.read<int>());
      return new(storage) std::pmr::polymorphic_allocator<T>(resource);
    }
  };
} // namespace upcxx

We would also need to document this in a README and perhaps show an example.

Comments (3)

  1. Dan Bonachea
    • removed milestone
    • removed version

    The proposed work lives in upcxx-extras and is not coupled to UPC++ release milestones

  2. Log in to comment