diff --git a/CUDADataFormats/Common/interface/CUDAProductBase.h b/CUDADataFormats/Common/interface/CUDAProductBase.h
index 4d0bc120eb3d3..b530c1a98b585 100644
--- a/CUDADataFormats/Common/interface/CUDAProductBase.h
+++ b/CUDADataFormats/Common/interface/CUDAProductBase.h
@@ -17,7 +17,10 @@ namespace impl {
class CUDAProductBase {
public:
CUDAProductBase() = default; // Needed only for ROOT dictionary generation
+ ~CUDAProductBase();
+ CUDAProductBase(const CUDAProductBase&) = delete;
+ CUDAProductBase& operator=(const CUDAProductBase&) = delete;
CUDAProductBase(CUDAProductBase&& other)
: stream_{std::move(other.stream_)},
event_{std::move(other.event_)},
diff --git a/CUDADataFormats/Common/src/CUDAProductBase.cc b/CUDADataFormats/Common/src/CUDAProductBase.cc
index b09fd98f91359..84ef1d561e665 100644
--- a/CUDADataFormats/Common/src/CUDAProductBase.cc
+++ b/CUDADataFormats/Common/src/CUDAProductBase.cc
@@ -8,3 +8,15 @@ bool CUDAProductBase::isAvailable() const {
}
return event_->has_occurred();
}
+
+CUDAProductBase::~CUDAProductBase() {
+ // Make sure that the production of the product in the GPU is
+ // complete before destructing the product. This is to make sure
+ // that the EDM stream does not move to the next event before all
+ // asynchronous processing of the current is complete.
+ if (event_) {
+ // TODO: a callback notifying a WaitingTaskHolder (or similar)
+ // would avoid blocking the CPU, but would also require more work.
+ event_->synchronize();
+ }
+}
diff --git a/CUDADataFormats/Track/BuildFile.xml b/CUDADataFormats/Track/BuildFile.xml
index 2aa4baedb0bb2..1184c1c7c55f2 100644
--- a/CUDADataFormats/Track/BuildFile.xml
+++ b/CUDADataFormats/Track/BuildFile.xml
@@ -1,5 +1,6 @@
+
diff --git a/CUDADataFormats/Vertex/BuildFile.xml b/CUDADataFormats/Vertex/BuildFile.xml
index 2aa4baedb0bb2..1184c1c7c55f2 100644
--- a/CUDADataFormats/Vertex/BuildFile.xml
+++ b/CUDADataFormats/Vertex/BuildFile.xml
@@ -1,5 +1,6 @@
+