diff --git a/CUDADataFormats/Common/interface/CUDAProductBase.h b/CUDADataFormats/Common/interface/CUDAProductBase.h
index 381d6a06f4a52..2ddd2157b1178 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 068b33b2f659b..3c23f037955e3 100644
--- a/CUDADataFormats/Common/src/CUDAProductBase.cc
+++ b/CUDADataFormats/Common/src/CUDAProductBase.cc
@@ -9,3 +9,15 @@ bool CUDAProductBase::isAvailable() const {
}
return cudautils::eventIsOccurred(event_->id());
}
+
+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 bf606ba2330e1..e3f9a0910bbd8 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 bf606ba2330e1..e3f9a0910bbd8 100644
--- a/CUDADataFormats/Vertex/BuildFile.xml
+++ b/CUDADataFormats/Vertex/BuildFile.xml
@@ -1,5 +1,6 @@
+