DeviceProduct

DeviceProductBase

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
#ifndef DataFormats_Common_interface_DeviceProduct_h
#define DataFormats_Common_interface_DeviceProduct_h

#include <cassert>
#include <memory>

#include "DataFormats/Common/interface/Uninitialized.h"

namespace edm {
  class DeviceProductBase {
  public:
    DeviceProductBase() = default;
    ~DeviceProductBase() = default;

    // TODO: in principle this function is an implementation detail
    template <typename M>
    M const& metadata() const {
      // TODO: I believe the assertion could be removed safely after
      // the data dependence and scheduling systems would guarantee
      // that the an EDModule in a given execution space can access
      // only to the EDProducts in a memory space compatible with the
      // execution space.
      //
      // On the other hand, with Alpaka (likely with others) the
      // getSynchronized() does additional checks so the added cost is
      // probably not that much?
      assert(typeid(M) == *metadataType_);
      return *static_cast<M const*>(metadata_.get());
    }

  protected:
    template <typename M>
    explicit DeviceProductBase(std::shared_ptr<M> metadata)
        : metadata_(std::move(metadata)), metadataType_(&typeid(M)) {}

  private:
    std::shared_ptr<void const> metadata_;
    std::type_info const* metadataType_;
  };

  /**
   * A wrapper for Event Data product in device memory accompanied
   * with some device-specific metadata. Not intended to be used directly by
   * developers (except in ROOT dictionary declarations in
   * classes_def.xml similar to edm::Wrapper).
   */
  template <typename T>
  class DeviceProduct : public DeviceProductBase {
  public:
    DeviceProduct()
      requires(requires { T(); })
    = default;

    explicit DeviceProduct(edm::Uninitialized)
      requires(requires { T(edm::kUninitialized); })
        : data_{edm::kUninitialized} {}

    template <typename M, typename... Args>
    explicit DeviceProduct(std::shared_ptr<M> metadata, Args&&... args)
        : DeviceProductBase(std::move(metadata)), data_(std::forward<Args>(args)...) {}

    DeviceProduct(const DeviceProduct&) = delete;
    DeviceProduct& operator=(const DeviceProduct&) = delete;
    DeviceProduct(DeviceProduct&&) = default;
    DeviceProduct& operator=(DeviceProduct&&) = default;

    /**
     * Get the actual data product after the metadata object has
     * synchronized the access. The synchronization details depend on
     * the metadata type, which the caller must know. All the
     * arguments are passed to M::synchronize() function.
     */
    template <typename M, typename... Args>
    T const& getSynchronized(Args&&... args) const {
      auto const& md = metadata<M>();
      md.synchronize(std::forward<Args>(args)...);
      return data_;
    }

  private:
    T data_;  //!
  };
}  // namespace edm
#endif