diff --git a/source/include/marlin/EmptyEventCreator.h b/source/include/marlin/EmptyEventCreator.h
new file mode 100644
index 0000000..fd9f3ad
--- /dev/null
+++ b/source/include/marlin/EmptyEventCreator.h
@@ -0,0 +1,38 @@
+#ifndef EmptyEventCreator_h
+#define EmptyEventCreator_h 1
+
+#include "marlin/DataSourceProcessor.h"
+
+namespace marlin {
+
+/** Creates empty LCIO Events that can then be populated by other processors.
+ *  Useful for testing purposes and examples, where having a dedicated input
+ *  just for "getting the event loop going" is not always practical. This needs
+ *  to be the first active processor and additionally requires that there are no
+ *  LCIO input collections present (i.e. make sure to not set the
+ *  LCIOInputFiles parameter).
+ *
+ *  <h4>Input</h4>
+ *  None
+ *
+ *  <h4>Output</4>
+ *  an empty LCEvent
+ *
+ *  @author: T. Madlener, DESY
+ */
+class EmptyEventCreator : public DataSourceProcessor {
+public:
+  EmptyEventCreator();
+
+  marlin::Processor* newProcessor() override { return new EmptyEventCreator; }
+
+  void readDataSource(int numEvents) override;
+  void init() override;
+
+private:
+  int m_eventNumber{0};
+};
+
+}
+
+#endif
diff --git a/source/src/EmptyEventCreator.cc b/source/src/EmptyEventCreator.cc
new file mode 100644
index 0000000..f4405a2
--- /dev/null
+++ b/source/src/EmptyEventCreator.cc
@@ -0,0 +1,40 @@
+#include "marlin/EmptyEventCreator.h"
+
+#include "marlin/ProcessorMgr.h"
+
+#include "IMPL/LCEventImpl.h"
+#include "IMPL/LCRunHeaderImpl.h"
+
+#include <memory>
+
+namespace marlin {
+EmptyEventCreator anEmptyEventCreator;
+
+EmptyEventCreator::EmptyEventCreator() : DataSourceProcessor("EmptyEventCreator") {
+  _description = "Creates empty events that can be filled by other processors";
+}
+
+void EmptyEventCreator::init() {
+  printParameters();  // Do we need to do anything at all?
+}
+
+void EmptyEventCreator::readDataSource(int numEvents) {
+  while (m_eventNumber < numEvents) {
+    if (isFirstEvent()) {
+      auto* runHeader = new LCRunHeaderImpl; // who cleans this up?
+      runHeader->setDescription("Empty events produced to be filled later");
+      runHeader->setRunNumber(0);
+
+      ProcessorMgr::instance()->processRunHeader(runHeader);
+      _isFirstEvent = false;
+    }
+
+    auto evt = std::make_unique<LCEventImpl>();
+    evt->setRunNumber(0);
+    evt->setEventNumber(m_eventNumber++);
+
+    ProcessorMgr::instance()->processEvent(evt.get());
+  }
+}
+
+} // namespace marlin