diff --git a/HLT/Event/TrigByteStreamCnvSvc/CMakeLists.txt b/HLT/Event/TrigByteStreamCnvSvc/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f675677a7478f6e3edab7b09129f065f616cceab
--- /dev/null
+++ b/HLT/Event/TrigByteStreamCnvSvc/CMakeLists.txt
@@ -0,0 +1,52 @@
+################################################################################
+# Package: TrigByteStreamCnvSvc
+################################################################################
+
+# Declare the package name
+atlas_subdir( TrigByteStreamCnvSvc )
+
+# Declare the package's dependencies
+atlas_depends_on_subdirs(
+  PUBLIC
+    Control/AthenaBaseComps
+    Event/ByteStreamData
+  PRIVATE
+    Event/ByteStreamCnvSvcBase
+    Event/ByteStreamCnvSvc
+    Event/EventInfo
+    HLT/Trigger/TrigControl/TrigKernel
+)
+
+# External dependencies
+find_package( tdaq-common COMPONENTS eformat_write hltinterface )
+
+# Libraries in the package
+atlas_add_library(
+  TrigByteStreamCnvSvcLib
+    TrigByteStreamCnvSvc/*.h
+    src/*.cxx
+  PUBLIC_HEADERS
+    TrigByteStreamCnvSvc
+  LINK_LIBRARIES
+    AthenaBaseComps
+    ByteStreamData
+  PRIVATE_INCLUDE_DIRS
+    ${TDAQ-COMMON_INCLUDE_DIRS}
+  PRIVATE_LINK_LIBRARIES
+    ${TDAQ-COMMON_LIBRARIES}
+    ByteStreamCnvSvcBaseLib
+    ByteStreamCnvSvcLib
+    EventInfo
+    TrigKernel
+)
+
+# Components in the package
+atlas_add_component(
+  TrigByteStreamCnvSvc
+    src/components/*.cxx
+    LINK_LIBRARIES TrigByteStreamCnvSvcLib
+)
+
+# Install files from the package
+atlas_install_python_modules( python/*.py )
+atlas_install_joboptions( share/*.py )
diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.cxx b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..b469920796cd9c5d57b91ed6e23824cca3f09608
--- /dev/null
+++ b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.cxx
@@ -0,0 +1,61 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+// Trigger includes
+#include "TrigByteStreamCnvSvc.h"
+
+
+// =============================================================================
+// Standard constructor
+// =============================================================================
+TrigByteStreamCnvSvc::TrigByteStreamCnvSvc(const std::string& name, ISvcLocator* svcLoc)
+: ByteStreamCnvSvcBase(name, svcLoc) {}
+
+// =============================================================================
+// Standard destructor
+// =============================================================================
+TrigByteStreamCnvSvc::~TrigByteStreamCnvSvc() {}
+
+// =============================================================================
+// Implementation of Service::initialize
+// =============================================================================
+StatusCode TrigByteStreamCnvSvc::initialize() {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  // ...
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of Service::finalize
+// =============================================================================
+StatusCode TrigByteStreamCnvSvc::finalize() {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  // ...
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of IConversionSvc::connectOutput
+// The argument outputFile is not used
+// =============================================================================
+StatusCode TrigByteStreamCnvSvc::connectOutput(const std::string& /*outputFile*/) {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  // ...
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of IConversionSvc::commitOutput
+// The arguments outputFile and do_commit are not used
+// =============================================================================
+StatusCode TrigByteStreamCnvSvc::commitOutput(const std::string& /*outputFile*/, bool /*do_commit*/) {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  // ...
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
\ No newline at end of file
diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.h b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.h
new file mode 100644
index 0000000000000000000000000000000000000000..fceb2d9df3a848ee67199cadd6994e545cf29798
--- /dev/null
+++ b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamCnvSvc.h
@@ -0,0 +1,31 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGBYTESTREAMCNVSVC_H
+#define TRIGBYTESTREAMCNVSVC_H
+
+#include "ByteStreamCnvSvcBase/ByteStreamCnvSvcBase.h"
+
+/** @class TrigByteStreamCnvSvc
+ *  @brief A ByteStreamCnvSvc implementation for online use
+ **/
+class TrigByteStreamCnvSvc : public ByteStreamCnvSvcBase {
+public:
+  /// Standard constructor
+  TrigByteStreamCnvSvc(const std::string& name, ISvcLocator* svcLoc);
+  /// Standard destructor
+  virtual ~TrigByteStreamCnvSvc();
+
+  // ------------------------- IService methods --------------------------------
+  virtual StatusCode initialize() override;
+  virtual StatusCode finalize() override;
+
+  // ------------------------- IConversionSvc methods --------------------------
+  /// In the case of online BS data, this method creates the output FullEventFragment and fills its header
+  virtual StatusCode connectOutput(const std::string& outputFile) override;
+  /// In the case of online BS data, this method binds and sends out the output FullEventFragment
+  virtual StatusCode commitOutput(const std::string& outputFile, bool do_commit) override;
+};
+
+#endif // TRIGBYTESTREAMCNVSVC_H
diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamInputSvc.cxx b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamInputSvc.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..c57b26341e050ccf25c7af0cfbc267e936bbbd67
--- /dev/null
+++ b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamInputSvc.cxx
@@ -0,0 +1,169 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+// Trigger includes
+#include "TrigByteStreamInputSvc.h"
+#include "TrigKernel/HltExceptions.h"
+
+// Athena includes
+#include "AthenaKernel/EventContextClid.h"
+#include "EventInfo/EventInfo.h"
+#include "StoreGate/StoreGateSvc.h"
+
+// TDAQ includes
+#include "hltinterface/DataCollector.h"
+#include "eformat/write/FullEventFragment.h"
+
+// =============================================================================
+// Standard constructor
+// =============================================================================
+TrigByteStreamInputSvc::TrigByteStreamInputSvc(const std::string& name, ISvcLocator* svcLoc)
+: ByteStreamInputSvc(name, svcLoc),
+  m_robDataProviderSvc("ROBDataProviderSvc", name),
+  m_evtStore("StoreGateSvc", name) {}
+
+// =============================================================================
+// Standard destructor
+// =============================================================================
+TrigByteStreamInputSvc::~TrigByteStreamInputSvc() {}
+
+// =============================================================================
+// Implementation of IInterface::queryInterface
+// =============================================================================
+StatusCode TrigByteStreamInputSvc::queryInterface(const InterfaceID& riid, void** ppvInterface) {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+
+  if(ByteStreamInputSvc::interfaceID().versionMatch(riid))
+    *ppvInterface = static_cast<ByteStreamInputSvc*>(this);
+  else
+    return AthService::queryInterface(riid, ppvInterface);
+
+  addRef();
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of Service::initialize
+// =============================================================================
+StatusCode TrigByteStreamInputSvc::initialize() {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+
+  CHECK(m_robDataProviderSvc.retrieve());
+  CHECK(m_evtStore.retrieve());
+
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of Service::finalize
+// =============================================================================
+StatusCode TrigByteStreamInputSvc::finalize() {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  if (m_robDataProviderSvc.release().isFailure()) {
+    ATH_MSG_WARNING("Cannot release rob data provider");
+  }
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of ByteStreamInputSvc::nextEvent
+// =============================================================================
+const RawEvent* TrigByteStreamInputSvc::nextEvent() {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+
+  // get event context from event store
+  EventContext* eventContext = nullptr;
+  if (m_evtStore->retrieve(eventContext).isFailure()) {
+    ATH_MSG_ERROR("Failed to retrieve EventContext from the event store, new event cannot be read");
+    return nullptr;
+  }
+
+  ATH_MSG_DEBUG("Reading new event for event context " << *eventContext);
+
+  eformat::write::FullEventFragment l1r;
+  using DCStatus = hltinterface::DataCollector::Status;
+  auto status = DCStatus::NO_EVENT;
+  do {
+    status = hltinterface::DataCollector::instance()->getNext(l1r);
+    if (status == DCStatus::NO_EVENT)
+      ATH_MSG_ERROR("Failed to read new event, DataCollector::getNext returned Status::NO_EVENT. Trying again.");
+  } while (status == DCStatus::NO_EVENT);
+
+  if (status == DCStatus::STOP) {
+    ATH_MSG_DEBUG("No more events available");
+    throw hltonl::Exception::NoMoreEvents();
+  }
+  else if (status != DCStatus::OK) {
+    ATH_MSG_ERROR("Unhandled return Status " << static_cast<int>(status) << " from DataCollector::getNext");
+    return nullptr;
+  }
+  ATH_MSG_VERBOSE("DataCollector::getNext returned Status::OK");
+
+  // convert write::FullEventFragment to read::FullEventFragment (RawEvent)
+  const eformat::write::node_t* top = l1r.bind();
+  const size_t l1rFragmentSize = l1r.size_word();
+  uint32_t* buf = new uint32_t[l1rFragmentSize];
+  auto copiedSize = eformat::write::copy(*top,buf,l1rFragmentSize);
+  if(copiedSize!=l1rFragmentSize){
+    ATH_MSG_ERROR("Event serialization failed");
+    return nullptr;
+  }
+
+  // newRawEvent points to memory allocated by buf
+  RawEvent* newRawEvent = new RawEvent(buf);
+
+  // find the cache corresponding to the current slot
+  EventCache* cache = m_eventsCache.get(*eventContext);
+
+  // free the memory allocated to the previous event processed in the current slot
+  // -- if we make sure ROBDataProviderSvc does this, then TrigByteStreamInputSvc won't need a cache
+  releaseEvent(cache);
+
+  // put the new raw event into the cache
+  cache->rawEvent = newRawEvent;
+
+  m_robDataProviderSvc->setNextEvent(*eventContext,newRawEvent);
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return newRawEvent;
+}
+
+// =============================================================================
+// Implementation of ByteStreamInputSvc::previousEvent
+// =============================================================================
+const RawEvent* TrigByteStreamInputSvc::previousEvent() {
+  ATH_MSG_FATAL("The method " << __FUNCTION__ << " is not implemented for online running");
+  return nullptr;
+}
+
+// =============================================================================
+// Implementation of ByteStreamInputSvc::currentEvent
+// =============================================================================
+const RawEvent* TrigByteStreamInputSvc::currentEvent() const {
+  ATH_MSG_FATAL("The method " << __FUNCTION__ << " is not implemented for online running");
+  return nullptr;
+}
+
+// =============================================================================
+void TrigByteStreamInputSvc::releaseEvent(EventCache* cache)
+{
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  if (cache->rawEvent) {
+    OFFLINE_FRAGMENTS_NAMESPACE::PointerType fragment = cache->rawEvent->start();
+    delete[] fragment;
+    fragment = nullptr;
+    delete cache->rawEvent;
+    cache->rawEvent = nullptr;
+    // cache->eventStatus = 0;
+  }
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+}
+
+// =============================================================================
+TrigByteStreamInputSvc::EventCache::~EventCache() {
+  delete rawEvent;
+  rawEvent = 0;
+}
diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamInputSvc.h b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamInputSvc.h
new file mode 100644
index 0000000000000000000000000000000000000000..66fc6e623287cb49044ce9012d07c2d5b334ad19
--- /dev/null
+++ b/HLT/Event/TrigByteStreamCnvSvc/src/TrigByteStreamInputSvc.h
@@ -0,0 +1,59 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGBYTESTREAMINPUTSVC_H
+#define TRIGBYTESTREAMINPUTSVC_H
+
+#include "ByteStreamCnvSvc/ByteStreamInputSvc.h"
+#include "ByteStreamCnvSvcBase/IROBDataProviderSvc.h"
+#include "ByteStreamData/RawEvent.h"
+#include "AthenaKernel/SlotSpecificObj.h"
+
+// Forward declarations
+class StoreGateSvc;
+
+/** @class TrigByteStreamInputSvc
+ *  @brief A ByteStreamInputSvc implementation for online use, reading events from hltinterface::DataCollector
+ *
+ *  The layout and implementation are based on ByteStreamEventStorageInputSvc
+ **/
+class TrigByteStreamInputSvc : public ByteStreamInputSvc {
+public:
+  /// Standard constructor
+  TrigByteStreamInputSvc(const std::string& name, ISvcLocator* svcLoc);
+  /// Standard destructor
+  virtual ~TrigByteStreamInputSvc();
+
+  // -------------------------- IInterface methods -----------------------------
+  virtual StatusCode queryInterface(const InterfaceID& riid, void** ppvInterface) override;
+
+  // ------------------------- Service methods --------------------------------
+  virtual StatusCode initialize() override;
+  virtual StatusCode finalize() override;
+
+  // ------------------------- ByteStreamInputSvc methods ----------------------
+  virtual const RawEvent* nextEvent() override;
+  virtual const RawEvent* previousEvent() override;
+  virtual const RawEvent* currentEvent() const override;
+
+private:
+  // ------------------------- service handles ---- ----------------------------
+  ServiceHandle<IROBDataProviderSvc> m_robDataProviderSvc;
+  ServiceHandle<StoreGateSvc> m_evtStore;
+
+  // ------------------------- private data members ----------------------------
+  struct EventCache {
+    ~EventCache();
+    RawEvent* rawEvent = 0; //!< current event
+    // unsigned int eventStatus = 0; //!< status of the current event
+  };
+
+  SG::SlotSpecificObj<EventCache> m_eventsCache;
+
+  // ------------------------- private helper methods --------------------------
+  /// Clean up parts of previous event and re-init them
+  void releaseEvent(EventCache* cache);
+};
+
+#endif // TRIGBYTESTREAMINPUTSVC_H
diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/TrigEventSelectorByteStream.cxx b/HLT/Event/TrigByteStreamCnvSvc/src/TrigEventSelectorByteStream.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..07d0c129775b3217d24aefec232ec5b520341203
--- /dev/null
+++ b/HLT/Event/TrigByteStreamCnvSvc/src/TrigEventSelectorByteStream.cxx
@@ -0,0 +1,192 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+// Trigger includes
+#include "TrigEventSelectorByteStream.h"
+#include "TrigKernel/HltExceptions.h"
+
+// Athena includes
+#include "AthenaKernel/EventContextClid.h"
+#include "ByteStreamCnvSvc/ByteStreamInputSvc.h"
+#include "ByteStreamCnvSvcBase/ByteStreamAddress.h"
+#include "ByteStreamData/RawEvent.h"
+#include "EventInfo/EventInfo.h"
+#include "StoreGate/StoreGateSvc.h"
+
+// TDAQ includes
+#include "hltinterface/DataCollector.h"
+
+// =============================================================================
+// Standard constructor
+// =============================================================================
+TrigEventSelectorByteStream::TrigEventSelectorByteStream(const std::string& name, ISvcLocator* svcLoc)
+: base_class(name, svcLoc),
+  m_eventSource("ByteStreamInputSvc", name),
+  m_evtStore("StoreGateSvc", name) {
+  declareProperty("ByteStreamInputSvc", m_eventSource);
+}
+
+// =============================================================================
+// Standard destructor
+// =============================================================================
+TrigEventSelectorByteStream::~TrigEventSelectorByteStream() {}
+
+// =============================================================================
+// Implementation of Service::initialize
+// =============================================================================
+StatusCode TrigEventSelectorByteStream::initialize()
+{
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+
+  ATH_CHECK(m_eventSource.retrieve());
+  ATH_CHECK(m_evtStore.retrieve());
+
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of Service::finalize
+// =============================================================================
+StatusCode TrigEventSelectorByteStream::finalize()
+{
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  if (m_eventSource.release().isFailure()) {
+    ATH_MSG_WARNING("Cannot release the event source service");
+  }
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of IEvtSelector::next(Context&)
+// There is actually no event selection here, we process all events online
+// =============================================================================
+StatusCode TrigEventSelectorByteStream::next(IEvtSelector::Context& /*c*/) const
+{
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+
+  // RawEvent is a typedef for FullEventFragment
+  const RawEvent* ptrRawEvent = nullptr;
+
+  // Try to get the next event from the event source
+  try {
+    ptrRawEvent = m_eventSource->nextEvent();
+  }
+  catch (const hltonl::Exception::NoMoreEvents& e) {
+    ATH_MSG_INFO(e.what());
+    throw; // rethrow NoMoreEvents
+  }
+  catch (const std::exception& e) {
+    ATH_MSG_ERROR("Failed to get next event from the event source, std::exception caught: " << e.what());
+    return StatusCode::FAILURE;
+  }
+  catch (...) {
+    ATH_MSG_ERROR("Failed to get next event from the event source, unhandled exception caught");
+    return StatusCode::FAILURE;
+  }
+
+  // Check if something was returned
+  if (ptrRawEvent == nullptr) {
+    ATH_MSG_ERROR("Failed to get next event from the event source, nullptr returned");
+    return StatusCode::FAILURE;
+  }
+
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of IEvtSelector::createContext(Context*&)
+// =============================================================================
+StatusCode TrigEventSelectorByteStream::createContext(IEvtSelector::Context*& c) const
+{
+  c = new TrigEventSelectorByteStream::Context(this);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of IEvtSelector::releaseContext(Context*&)
+// =============================================================================
+StatusCode TrigEventSelectorByteStream::releaseContext(IEvtSelector::Context*& /*c*/) const
+{
+  // this does nothing
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of IEvtSelector::createAddress(Context&,IOpaqueAddress*&)
+// =============================================================================
+StatusCode TrigEventSelectorByteStream::createAddress(const IEvtSelector::Context& /*c*/, IOpaqueAddress*& iop) const
+{
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+
+  // Get event context from event store
+  EventContext* eventContext = nullptr;
+  ATH_CHECK(m_evtStore->retrieve(eventContext));
+
+  // Perhaps the name shouldn't be hard-coded
+  ByteStreamAddress* addr = new ByteStreamAddress(ClassID_traits<EventInfo>::ID(), "ByteStreamEventInfo", "");
+  addr->setEventContext(*eventContext);
+  iop = static_cast<IOpaqueAddress*>(addr);
+  ATH_CHECK(m_evtStore->recordAddress("ByteStreamEventInfo",iop));
+
+  ATH_MSG_DEBUG("Recorded new ByteStreamAddress for EventInfo with event context " << *eventContext);
+
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Unimplemented methods of IEvtSelector
+// =============================================================================
+#define TRIGEVENTSELECTORBYTESTREAM_UNIMPL \
+  ATH_MSG_FATAL("Misconfiguration - the method " << __FUNCTION__ << " cannot be used online"); \
+  return StatusCode::FAILURE;
+
+StatusCode TrigEventSelectorByteStream::next(IEvtSelector::Context& /*c*/, int /*jump*/) const
+{
+  TRIGEVENTSELECTORBYTESTREAM_UNIMPL
+}
+
+StatusCode TrigEventSelectorByteStream::previous(IEvtSelector::Context& /*c*/) const
+{
+  TRIGEVENTSELECTORBYTESTREAM_UNIMPL
+}
+
+StatusCode TrigEventSelectorByteStream::previous(IEvtSelector::Context& /*c*/, int /*jump*/) const
+{
+  TRIGEVENTSELECTORBYTESTREAM_UNIMPL
+}
+
+StatusCode TrigEventSelectorByteStream::last(IEvtSelector::Context& /*refContext*/) const
+{
+  TRIGEVENTSELECTORBYTESTREAM_UNIMPL
+}
+
+StatusCode TrigEventSelectorByteStream::rewind(IEvtSelector::Context& /*c*/) const
+{
+  TRIGEVENTSELECTORBYTESTREAM_UNIMPL
+}
+
+StatusCode TrigEventSelectorByteStream::resetCriteria(const std::string& /*cr*/, IEvtSelector::Context& /*c*/) const
+{
+  TRIGEVENTSELECTORBYTESTREAM_UNIMPL
+}
+
+// =============================================================================
+// Context implementation
+// =============================================================================
+TrigEventSelectorByteStream::Context::Context(const IEvtSelector* selector)
+: m_evtSelector(selector) {}
+
+TrigEventSelectorByteStream::Context::Context(const TrigEventSelectorByteStream::Context& other)
+: m_evtSelector(other.m_evtSelector) {}
+
+TrigEventSelectorByteStream::Context::~Context() {}
+
+void* TrigEventSelectorByteStream::Context::identifier() const
+{
+  return (void*)(m_evtSelector);
+}
diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/TrigEventSelectorByteStream.h b/HLT/Event/TrigByteStreamCnvSvc/src/TrigEventSelectorByteStream.h
new file mode 100644
index 0000000000000000000000000000000000000000..215116729ec3ebce90ac35d6e10318a657a8a765
--- /dev/null
+++ b/HLT/Event/TrigByteStreamCnvSvc/src/TrigEventSelectorByteStream.h
@@ -0,0 +1,69 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGEVENTSELECTORBYTESTREAM_H
+#define TRIGEVENTSELECTORBYTESTREAM_H
+
+#include "GaudiKernel/IEvtSelector.h"
+#include "AthenaBaseComps/AthService.h"
+
+// Forward declarations
+class ByteStreamInputSvc;
+class StoreGateSvc;
+
+/**
+ * @class  TrigEventSelectorByteStream
+ * @brief  online implementation of IEvtSelector for ByteStream
+ */
+
+class TrigEventSelectorByteStream : public extends<AthService, IEvtSelector> {
+public:
+  /**
+   * @class TrigEventSelectorByteStream::Context
+   * @brief Event Selector context for TrigEventSelectorByteStream
+   */
+  class Context : public IEvtSelector::Context {
+  public:
+    /// Constructor from a selector
+    Context(const IEvtSelector* selector);
+    /// Copy constructor
+    Context(const TrigEventSelectorByteStream::Context& other);
+    /// Default destructor
+    virtual ~Context();
+    /// Implementation of IEvtSelector::Context::identifier
+    virtual void* identifier() const override;
+  private:
+    /// pointer to the event selector
+    const IEvtSelector* m_evtSelector;
+  };
+
+  /// Standard constructor
+  TrigEventSelectorByteStream(const std::string& name, ISvcLocator* svcLoc);
+  /// Standard destructor
+  virtual ~TrigEventSelectorByteStream();
+
+  // ------------------------- Service methods --------------------------------
+  virtual StatusCode initialize() override;
+  virtual StatusCode finalize() override;
+
+  // ------------------------- IEvtSelector methods ---------------------------
+  virtual StatusCode createContext(IEvtSelector::Context*& c) const override;
+  virtual StatusCode next(IEvtSelector::Context& c) const override;
+  virtual StatusCode next(IEvtSelector::Context& c, int jump) const override;
+  virtual StatusCode previous(IEvtSelector::Context& c) const override;
+  virtual StatusCode previous(IEvtSelector::Context& c, int jump) const override;
+  virtual StatusCode last(IEvtSelector::Context& refContext) const override;
+  virtual StatusCode rewind(IEvtSelector::Context& c) const override;
+  virtual StatusCode createAddress(const IEvtSelector::Context& c, IOpaqueAddress*& iop) const override;
+  virtual StatusCode releaseContext(IEvtSelector::Context*& c) const override;
+  virtual StatusCode resetCriteria(const std::string& cr, IEvtSelector::Context& c) const override;
+
+private:
+  // @property Reference to the event source (ByteStreamInputSvc)
+  ServiceHandle<ByteStreamInputSvc> m_eventSource;
+  // Reference to the StoreGateScv
+  ServiceHandle<StoreGateSvc> m_evtStore;
+};
+
+#endif // TRIGEVENTSELECTORBYTESTREAM_H
diff --git a/HLT/Event/TrigByteStreamCnvSvc/src/components/TrigByteStreamCnvSvc_entries.cxx b/HLT/Event/TrigByteStreamCnvSvc/src/components/TrigByteStreamCnvSvc_entries.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4b702b644a60af65ff87dae2f18caa4cbf0f0fb8
--- /dev/null
+++ b/HLT/Event/TrigByteStreamCnvSvc/src/components/TrigByteStreamCnvSvc_entries.cxx
@@ -0,0 +1,7 @@
+#include "../TrigEventSelectorByteStream.h"
+#include "../TrigByteStreamInputSvc.h"
+#include "../TrigByteStreamCnvSvc.h"
+
+DECLARE_COMPONENT( TrigEventSelectorByteStream )
+DECLARE_COMPONENT( TrigByteStreamInputSvc )
+DECLARE_COMPONENT( TrigByteStreamCnvSvc )
diff --git a/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/HltExceptions.h b/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/HltExceptions.h
new file mode 100644
index 0000000000000000000000000000000000000000..7d7ec7cbf0da711280c0db910d83c98351a4b939
--- /dev/null
+++ b/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/HltExceptions.h
@@ -0,0 +1,25 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef HltExceptions_H
+#define HltExceptions_H
+
+#include <exception>
+
+namespace hltonl {
+  namespace Exception {
+    /**
+     * @class NoMoreEvents
+     * @brief Can be thrown if all events are already read from the input and another one is requested
+     */
+    class NoMoreEvents : public std::exception {
+      public:
+        NoMoreEvents() {}
+        virtual ~NoMoreEvents() {}
+        const char* what() const noexcept override {return "No more events to be processed";}
+    };
+  }
+}
+
+#endif // HltExceptions_H
diff --git a/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/HltOstreams.h b/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/HltOstreams.h
index 97bc24c94b8ae66d8655fc9c63d07dc00485f49a..5a591929bb2f149489bd355442efe21f3e368a93 100644
--- a/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/HltOstreams.h
+++ b/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/HltOstreams.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef HltOstreams_H
@@ -10,13 +10,11 @@
 #include <vector>
 #include <stdint.h>
 #include "eformat/eformat.h"
-#include "hltinterface/HLTResult.h"
 
 std::ostream& operator<<(std::ostream& os, const std::vector<eformat::helper::StreamTag>& rhs);
 std::ostream& operator<<(std::ostream& os, const std::vector<uint32_t>& rhs);
 std::ostream& operator<<(std::ostream& os, const std::vector<eformat::SubDetector>& rhs);
 std::ostream& operator<<(std::ostream& os, const std::set<uint32_t>& rhs);
 std::ostream& operator<<(std::ostream& os, const std::set<eformat::SubDetector>& rhs);
-std::ostream& operator<<(std::ostream& os, const hltinterface::HLTResult& rhs);
 
 #endif // HltOstreams_H
diff --git a/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/ITrigEventLoopMgr.h b/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/ITrigEventLoopMgr.h
index 0fe1a6891f9321841ae5d0aa4d8f721e99daad03..58caf01982f52808042bcea3e112e45062dfa914 100644
--- a/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/ITrigEventLoopMgr.h
+++ b/HLT/Trigger/TrigControl/TrigKernel/TrigKernel/ITrigEventLoopMgr.h
@@ -1,26 +1,12 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
 */
 
-/**@class ITrigEventLoopMgr
- * @brief EventLoopMgr interface implemented by the HLT event loop manager
- *
- * Provides additional interfaces for TDAQ state transitions used by the PSC.
- * It follows the usual Gaudi philosophy of separation framework and client
- * implemenation into sysXYZ and XYZ methods.
- *
- * @author  Frank Winklmeier
- * @version $Id: ITrigEventLoopMgr.h 39 2013-06-10 17:21:44Z ricab $
- */
-
 #ifndef TRIGKERNEL_ITRIGEVENTLOOPMGR_H
 #define TRIGKERNEL_ITRIGEVENTLOOPMGR_H
 
-#include "eformat/ROBFragment.h"
 #include "GaudiKernel/IInterface.h"
 #include <boost/property_tree/ptree.hpp>
-#include <vector>
-#include <stdint.h>
 
 namespace hltinterface
 {
@@ -28,12 +14,17 @@ namespace hltinterface
   struct HLTResult;
 }
 
+/**@class ITrigEventLoopMgr
+ * @brief EventLoopMgr interface implemented by the HLT event loop manager
+ *
+ * Provides additional interfaces for TDAQ state transitions used by the PSC.
+ *
+ * @author  Frank Winklmeier
+ */
 class ITrigEventLoopMgr: virtual public IInterface {
 public:
-  /*
-   * Retrieve interface ID
-   */
-  static const InterfaceID& interfaceID();
+  /// Interface ID
+  DeclareInterfaceID(ITrigEventLoopMgr, 21, 0);
 
   /**
    * prepareForRun method invoked by framework
@@ -44,24 +35,6 @@ public:
    * update parameters if necessary after forking workers and issue incident
    */
   virtual StatusCode hltUpdateAfterFork(const boost::property_tree::ptree &) = 0;
-
-  /**
-   * propagate a processing time out via the HLT framework to the steering/algorithms
-   */
-  virtual StatusCode timeOutReached(const boost::property_tree::ptree&) = 0;
-
-  /// process one event/RoI
-  virtual StatusCode
-  processRoIs(const std::vector<eformat::ROBFragment<const uint32_t*> >&,
-              hltinterface::HLTResult&,
-              const hltinterface::EventId& evId) = 0;
-
 };
 
-inline const InterfaceID& ITrigEventLoopMgr::interfaceID()
-{
-  static const InterfaceID IID_ITrigEventLoopMgr("ITrigEventLoopMgr", 20, 1);
-  return IID_ITrigEventLoopMgr;
-}
-
 #endif
diff --git a/HLT/Trigger/TrigControl/TrigKernel/src/HltOstreams.cxx b/HLT/Trigger/TrigControl/TrigKernel/src/HltOstreams.cxx
index a39824a8bbf4ef290b33b7453e308809d52ba5da..e1e99248c11cb511bdda300e631077ecb8e45097 100644
--- a/HLT/Trigger/TrigControl/TrigKernel/src/HltOstreams.cxx
+++ b/HLT/Trigger/TrigControl/TrigKernel/src/HltOstreams.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
 */
 
 //=========================================================================
@@ -16,8 +16,8 @@ std::ostream& operator<<(std::ostream& os, const std::vector<eformat::helper::St
   std::string prefix("\n(");
   for (std::vector<eformat::helper::StreamTag>::const_iterator it = rhs.begin(); it != rhs.end(); it++) {
     os << prefix << (*it).name << "," << (*it).type << "," << (*it).obeys_lumiblock
-       << ",[Rob="  << (*it).robs.size() << ":" << (*it).robs 
-       << "],[Det=" << (*it).dets.size() << ":" << (*it).dets  
+       << ",[Rob="  << (*it).robs.size() << ":" << (*it).robs
+       << "],[Det=" << (*it).dets.size() << ":" << (*it).dets
        << "])";
     prefix=",\n(";
   }
@@ -69,39 +69,3 @@ std::ostream& operator<<(std::ostream& os, const std::set<eformat::SubDetector>&
   }
   return os;
 }
-
-std::ostream& operator<<(std::ostream& os, const hltinterface::HLTResult& rhs) {
-  os << "[HLT Result]" ;
-  os << "\n HLT Result: fragment_pointer = " << std::hex << rhs.fragment_pointer << std::dec
-     << ", max_result_size [words] = " << rhs.max_result_size ;
-  os << "\n HLT Result: Number of HLT result ROBs = " << rhs.hltResult_robs.size() ;
-  os << "\n [";
-  if (rhs.fragment_pointer != 0) {
-    for (const auto& hltrob : rhs.hltResult_robs) {
-      os << "\n HLT ROB: Source Identifier = 0x" << std::hex << (hltrob.source_id()) << std::dec
-	 << ", ROB fragment size [words] = " << std::setw(6) << hltrob.fragment_size_word()
-	 << ", # status words = " << hltrob.nstatus() << ", status words =" ;
-      const uint32_t* it;
-      hltrob.status(it);
-      for (uint32_t i(0); i < hltrob.nstatus(); ++i) {
-	os << std::hex <<  std::setfill( '0' ) << " 0x" << std::setw(8) << *(it+i);
-	os << std::dec << std::setfill(' ');
-	if (i == 1)
-	  os << "(" << hltonl::PrintHltResultStatusCode((hltonl::ResultStatusCode) *(it+1)) << ")";
-	if (i == 2)
-	  os << "(" << hltonl::PrintPscErrorCode((hltonl::PSCErrorCode) *(it+2)) << ")";
-      }
-    }
-  } else {
-    os << "\n No HLT ROB Fragment: fragment_pointer pointer=0x" << std::hex << rhs.fragment_pointer << std::dec;
-  } 
-  os << "\n ]";
-
-  os << "\n Stream tags (Name, Type, LumiBlock, PEB Robs, PEB SubDets) : # of tags = " << rhs.stream_tag.size()     
-     << "\n [" << rhs.stream_tag << "\n ]";
-  os << "\n HLT trigger info words: # of words = " << rhs.trigger_info.size()
-     << "\n [" << rhs.trigger_info << "]";
-  os << "\n HLT PSC error words:    # of words = " << rhs.psc_errors.size()
-     << "\n [" << rhs.psc_errors << "]";
-  return os;
-}
diff --git a/HLT/Trigger/TrigControl/TrigPSC/TrigPSC/Psc.h b/HLT/Trigger/TrigControl/TrigPSC/TrigPSC/Psc.h
index a08fcfcc2756bfeae0cff02e93a5470266ea9327..cce46e17c9ca8ba4817fc692dd40f6bb38386022 100644
--- a/HLT/Trigger/TrigControl/TrigPSC/TrigPSC/Psc.h
+++ b/HLT/Trigger/TrigControl/TrigPSC/TrigPSC/Psc.h
@@ -17,6 +17,9 @@
 #include "hltinterface/HLTInterface.h"
 #include "hltinterface/EventId.h"
 
+// to be removed together with the Psc::process method
+#include "hltinterface/HLTResult.h"
+
 // Gaudi Includes
 #include "GaudiKernel/StatusCode.h"
 
@@ -36,13 +39,13 @@ namespace psc {
 
   // Fwd decl
   class Config;
-  
+
   /**
    * Common base class for HLT Pesa Steering Controller.
    */
   class Psc: public hltinterface::HLTInterface
   {
-  public:    
+  public:
     /**
      * C'tor. (Nothing happens here...)
      */
@@ -89,29 +92,15 @@ namespace psc {
      */
     virtual bool publishStatistics (const boost::property_tree::ptree& args);
 
-    /**
-     * Calls the HLT framework to notify it that a time out is imminent
-     */
-    virtual void timeOutReached (const boost::property_tree::ptree& args);
-
     /**
      * Calls the HLT framework to notify it that a user command has arrived
      */
     virtual bool hltUserCommand (const boost::property_tree::ptree& args);
 
     /**
-     * Process one event, taking as input, the LVL1 Result and producing as
-     * output, the HLT Result.
-     *
-     * @param l1r.  LVL1 result ROBs (input)
-     * @param hltr. HLT result (output)
-     * @param evId. EventId structure containing global event number l1id and lb
-     *  number (input)
+     * Starts the HLT event loop. The HLT framework will start requesting and processing events.
      */
-    virtual bool
-    process(const std::vector<eformat::ROBFragment<const uint32_t*>>& l1r,
-            hltinterface::HLTResult& hltr,
-            const hltinterface::EventId& evId);
+    virtual void doEventLoop ();
 
     /**
      * Method which can be called for a worker to perform the necessary steps to set
@@ -125,9 +114,9 @@ namespace psc {
      */
     virtual bool finalizeWorker (const boost::property_tree::ptree& args);
 
-
   private:
     bool setDFProperties(std::map<std::string, std::string> name_tr_table);
+    bool setAthenaProperties();
 
     /**
      * Initialize the application manager
@@ -149,12 +138,12 @@ namespace psc {
     IAppMgrUI*          m_pesaAppMgr;         ///< Application Manager
     std::string         m_nameEventLoopMgr;   ///< name of the event loop manager
     bool                m_interactive;        ///< Running in interactive mode (athenaMT/PT)
-    
+
     // User command handling
     bool           m_failNextUsrCmd;
     unsigned int   m_sleepNextUsrCmd;
     psc::Config * m_config;
   };
 }
-  
+
 #endif /* TRIGPSC_PSC_H */
diff --git a/HLT/Trigger/TrigControl/TrigPSC/share/TrigPSCPythonSetup.py b/HLT/Trigger/TrigControl/TrigPSC/share/TrigPSCPythonSetup.py
index 5217970f2acbfd870d916500f035d2b9e745bd63..3a1a962df3e82192686a418d72b3f13293f2c0bc 100755
--- a/HLT/Trigger/TrigControl/TrigPSC/share/TrigPSCPythonSetup.py
+++ b/HLT/Trigger/TrigControl/TrigPSC/share/TrigPSCPythonSetup.py
@@ -3,251 +3,266 @@
 ## @author Werner Wiedenmann <Werner.Wiedenmann@cern.ch>
 ###############################################################
  
-### basic setup files and definitions ----------------------------------------
-pscBootstrapFile     = "TrigServices/TrigServicesBootstrap.py"   # PSC bootstrap
-pscServiceSetupBegin = "TrigServices/TrigServicesCommonBegin.py" # Service definitions
-pscServiceSetupEnd   = "TrigServices/TrigServicesCommonEnd.py"   # Service definitions
-
-import sys, os, string
-
-### Set up some common flags --------------------------------------------------
-
-### athenaCommonFlags
-from AthenaCommon.AthenaCommonFlags import athenaCommonFlags
-athenaCommonFlags.isOnline.set_Value_and_Lock(True)
-del athenaCommonFlags
+### setup from a .pkl file
+from TrigPSC import PscConfig
+joPath = PscConfig.optmap['JOBOPTIONSPATH']
+if joPath[-4:] == '.pkl':
+   print "Configuring the job from a pickle file"
+   import AthenaCommon.ConfigurationShelve
+   AthenaCommon.ConfigurationShelve.loadJobOptionsCatalogue( joPath )
+   del AthenaCommon.ConfigurationShelve
+   print "Job configuration loaded successfully from a pickle file"
+
+else:
+
+   ### basic setup files and definitions ----------------------------------------
+   pscBootstrapFile     = "TrigServices/TrigServicesBootstrap.py"   # PSC bootstrap
+   pscServiceSetupBegin = "TrigServices/TrigServicesCommonBegin.py" # Service definitions
+   pscServiceSetupEnd   = "TrigServices/TrigServicesCommonEnd.py"   # Service definitions
+
+   import sys, os, string
+
+   ### Set up some common flags --------------------------------------------------
+
+   ### athenaCommonFlags
+   from AthenaCommon.AthenaCommonFlags import athenaCommonFlags
+   athenaCommonFlags.isOnline.set_Value_and_Lock(True)
+   del athenaCommonFlags
+
+   ### TriggerFlags
+   from TriggerJobOpts.TriggerFlags import TriggerFlags
+   TriggerFlags.doHLT.set_Value_and_Lock(True)
+
+   ### By default do not run in validation mode (do not lock this one!)
+   from TriggerJobOpts.TriggerFlags import TriggerFlags
+   TriggerFlags.Online.doValidation = False
+      
+   del TriggerFlags
+
+   ### logging and messages -----------------------------------------------------
+   from AthenaCommon.Logging import *
+   from AthenaCommon.Constants import *
+   import AthenaCommon.ExitCodes as ExitCodes
 
-### TriggerFlags
-from TriggerJobOpts.TriggerFlags import TriggerFlags
-TriggerFlags.doHLT.set_Value_and_Lock(True)
+   from TrigPSC import PscConfig
+   logLevel=string.upper(PscConfig.optmap['LOGLEVEL'])
+   logLevel=string.split(logLevel,",")
+   if len(logLevel)==0:
+      logLevel=["INFO","ERROR"]
 
-### By default do not run in validation mode (do not lock this one!)
-from TriggerJobOpts.TriggerFlags import TriggerFlags
-TriggerFlags.Online.doValidation = False
-    
-del TriggerFlags
+   if len(logLevel)==1:
+      logLevel.append("ERROR")
 
-### logging and messages -----------------------------------------------------
-from AthenaCommon.Logging import *
-from AthenaCommon.Constants import *
-import AthenaCommon.ExitCodes as ExitCodes
+   ### FOR DEVELOPMENT: force verbose log level
+   logLevel=["VERBOSE","DEBUG","INFO","ERROR"]
 
-from TrigPSC import PscConfig
-logLevel=string.upper(PscConfig.optmap['LOGLEVEL'])
-logLevel=string.split(logLevel,",")
-if len(logLevel)==0:
-   logLevel=["INFO","ERROR"]
-
-if len(logLevel)==1:
-   logLevel.append("ERROR")
-
-## test and set log level
-try:
-   exec( 'log.setLevel( logging.%s )' % logLevel[0] )
-except:
-   sys.exit( ExitCodes.OPTIONS_UNKNOWN )
-
-### file inclusion and tracing -----------------------------------------------
-from AthenaCommon.Include import Include, IncludeError, include
-showincludes = eval(PscConfig.optmap['SHOWINCLUDE'])
-include.setShowIncludes( showincludes )
-if showincludes:
-   import AthenaCommon.Include as AthCIncMod
-   AthCIncMod.marker = ' -#-'      # distinguish bootstrap from other jo-code
-
-if PscConfig.optmap['TRACEPATTERN']:
-   import AthenaCommon.Include
-   AthenaCommon.Include.tracePattern = PscConfig.optmap['TRACEPATTERN']
-
-#
-### gaudi --------------------------------------------------------------------
-try:
-   from GaudiPython import *
-except ImportError:
-   from gaudimodule import *
-
-from AthenaCommon.Configurable import *
-from AthenaCommon.OldStyleConfig import *
-
-### set output level  --------------------------------------------------------
-exec 'OUTPUTLEVEL = %s' % logLevel[0]
-if not os.environ.has_key( "POOL_OUTMSG_LEVEL" ):
-   exec 'os.environ[ "POOL_OUTMSG_LEVEL" ] = str(%s)' % logLevel[1]
-del logLevel
-
-OutputLevel=OUTPUTLEVEL
-HLTOutputLevel=OUTPUTLEVEL
-         
-### Athena configuration -----------------------------------------------------
-from AthenaCommon import CfgMgr
-
-## create the application manager and start in a non-initialised state
-from AthenaCommon.AppMgr import theApp
-from AthenaCommon.AppMgr import ToolSvc, ServiceMgr, theAuditorSvc
-
-## These properties have alread been set on the C++ ApplicationMgr in the Psc
-## but the configurable needs to have them set as well
-theApp.MessageSvcType    = PscConfig.optmap["MESSAGESVCTYPE"]
-theApp.JobOptionsSvcType = PscConfig.optmap["JOBOPTIONSSVCTYPE"]
-         
-## add the MessageSvc and the JobOptionsSvc to the ServiceMgr
-from AthenaCommon.ConfigurableDb import getConfigurable
-ServiceMgr += getConfigurable(theApp.JobOptionsSvcType)("JobOptionsSvc")
-ServiceMgr += getConfigurable(theApp.MessageSvcType   )("MessageSvc"   )
-
-## set the default values
-try:
-   include( pscBootstrapFile )
-except Exception, e:
-   if isinstance( e, IncludeError ):
-      print sys.exc_type, e
-      theApp._exitstate = ExitCodes.INCLUDE_ERROR
-      sys.exit( ExitCodes.INCLUDE_ERROR )
-   raise
-
-## properties of the application manager
-theApp.StatusCodeCheck = False     # enabled via TriggerFlags.Online.doValidation (see below)
-theApp.setOutputLevel(OUTPUTLEVEL)
-
-# Configure the CoreDumpSvc
-if not hasattr(ServiceMgr,"CoreDumpSvc"):
-   from AthenaServices.Configurables import CoreDumpSvc
-   ServiceMgr += CoreDumpSvc()
-
-# check if the CoreDumpSvc can provide the FatalHandler
-# in case this is not available try for backward compatibility
-# to load the old libAthenaServicesDict and try to install it from there
-#
-if ServiceMgr.CoreDumpSvc.properties().has_key('FatalHandler'): 
-   ServiceMgr.CoreDumpSvc.FatalHandler = -1         # make SIG_INT fatal
-
-## set resource limits
-from AthenaCommon.ResourceLimits import SetMaxLimits
-SetMaxLimits()
-del SetMaxLimits
-
-## reset include markers
-if showincludes:
-   AthCIncMod.marker = AthCIncMod.__marker__      # reset
-   del AthCIncMod
-del showincludes
-
-### run optional command before user job options script ----------------------
-if PscConfig.optmap['PRECOMMAND']:
-   print "\n"
-   print " +------------------------------------------------+ "
-   print " | Execute command before jobOptions script START.| "
-   print " +------------------------------------------------+ "
-   print " ---> Command = ", PscConfig.optmap['PRECOMMAND']
+   ## test and set log level
+   try:
+      exec( 'log.setLevel( logging.%s )' % logLevel[0] )
+   except:
+      sys.exit( ExitCodes.OPTIONS_UNKNOWN )
+
+   ### file inclusion and tracing -----------------------------------------------
+   from AthenaCommon.Include import Include, IncludeError, include
+   showincludes = eval(PscConfig.optmap['SHOWINCLUDE'])
+   include.setShowIncludes( showincludes )
+   if showincludes:
+      import AthenaCommon.Include as AthCIncMod
+      AthCIncMod.marker = ' -#-'      # distinguish bootstrap from other jo-code
+
+   if PscConfig.optmap['TRACEPATTERN']:
+      import AthenaCommon.Include
+      AthenaCommon.Include.tracePattern = PscConfig.optmap['TRACEPATTERN']
+
+   #
+   ### gaudi --------------------------------------------------------------------
    try:
-      exec PscConfig.optmap['PRECOMMAND']
+      from GaudiPython import *
+   except ImportError:
+      from gaudimodule import *
+
+   from AthenaCommon.Configurable import *
+   from AthenaCommon.OldStyleConfig import *
+
+   ### set output level  --------------------------------------------------------
+   exec 'OUTPUTLEVEL = %s' % logLevel[0]
+   if not os.environ.has_key( "POOL_OUTMSG_LEVEL" ):
+      exec 'os.environ[ "POOL_OUTMSG_LEVEL" ] = str(%s)' % logLevel[1]
+   del logLevel
+
+   OutputLevel=OUTPUTLEVEL
+   HLTOutputLevel=OUTPUTLEVEL
+            
+   ### Athena configuration -----------------------------------------------------
+   from AthenaCommon import CfgMgr
+
+   ## create the application manager and start in a non-initialised state
+   from AthenaCommon.AppMgr import theApp
+   from AthenaCommon.AppMgr import ToolSvc, ServiceMgr, theAuditorSvc
+
+   ## These properties have alread been set on the C++ ApplicationMgr in the Psc
+   ## but the configurable needs to have them set as well
+   theApp.MessageSvcType    = PscConfig.optmap["MESSAGESVCTYPE"]
+   theApp.JobOptionsSvcType = PscConfig.optmap["JOBOPTIONSSVCTYPE"]
+            
+   ## add the MessageSvc and the JobOptionsSvc to the ServiceMgr
+   from AthenaCommon.ConfigurableDb import getConfigurable
+   ServiceMgr += getConfigurable(theApp.JobOptionsSvcType)("JobOptionsSvc")
+   ServiceMgr += getConfigurable(theApp.MessageSvcType   )("MessageSvc"   )
+
+   ## set the default values
+   try:
+      include( pscBootstrapFile )
    except Exception, e:
       if isinstance( e, IncludeError ):
          print sys.exc_type, e
          theApp._exitstate = ExitCodes.INCLUDE_ERROR
-         sys.exit( theApp._exitstate )         
-      elif isinstance( e, ImportError ):
-         print sys.exc_type, e
-         theApp._exitstate = ExitCodes.IMPORT_ERROR
-         sys.exit( theApp._exitstate )
+         sys.exit( ExitCodes.INCLUDE_ERROR )
       raise
-   print " +------------------------------------------------+ "
-   print " | Execute command before jobOptions script END.  | "
-   print " +------------------------------------------------+ "
-   print "\n"
-
-### basic job configuration before user configuration ------------------------
-try:
-   include( pscServiceSetupBegin )
-   include.block( pscServiceSetupBegin )
-except Exception, e:
-   print sys.exc_type, e
-   if isinstance( e, IncludeError ):
-      theApp._exitstate = ExitCodes.INCLUDE_ERROR
-      sys.exit( theApp._exitstate )      
-   raise
-
-if 'interactive' in dir():   
-   import TrigPSC.PscConfig 
-   TrigPSC.PscConfig.interactive = bool(interactive)
-   del interactive
-   
-### run user jobOptions file -------------------------------------------------
-try:
-   include( "%s" % PscConfig.optmap['JOBOPTIONSPATH'] )
-except Exception, e:
-   if isinstance(e,SystemExit):
+
+   ## properties of the application manager
+   theApp.StatusCodeCheck = False     # enabled via TriggerFlags.Online.doValidation (see below)
+   theApp.setOutputLevel(OUTPUTLEVEL)
+
+   # Configure the CoreDumpSvc
+   if not hasattr(ServiceMgr,"CoreDumpSvc"):
+      from AthenaServices.Configurables import CoreDumpSvc
+      ServiceMgr += CoreDumpSvc()
+
+   # check if the CoreDumpSvc can provide the FatalHandler
+   # in case this is not available try for backward compatibility
+   # to load the old libAthenaServicesDict and try to install it from there
+   #
+   if ServiceMgr.CoreDumpSvc.properties().has_key('FatalHandler'): 
+      ServiceMgr.CoreDumpSvc.FatalHandler = -1         # make SIG_INT fatal
+
+   ## set resource limits
+   from AthenaCommon.ResourceLimits import SetMaxLimits
+   SetMaxLimits()
+   del SetMaxLimits
+
+   ## reset include markers
+   if showincludes:
+      AthCIncMod.marker = AthCIncMod.__marker__      # reset
+      del AthCIncMod
+   del showincludes
+
+   ### run optional command before user job options script ----------------------
+   if PscConfig.optmap['PRECOMMAND']:
+      print "\n"
+      print " +------------------------------------------------+ "
+      print " | Execute command before jobOptions script START.| "
+      print " +------------------------------------------------+ "
+      print " ---> Command = ", PscConfig.optmap['PRECOMMAND']
+      try:
+         exec PscConfig.optmap['PRECOMMAND']
+      except Exception, e:
+         if isinstance( e, IncludeError ):
+            print sys.exc_type, e
+            theApp._exitstate = ExitCodes.INCLUDE_ERROR
+            sys.exit( theApp._exitstate )         
+         elif isinstance( e, ImportError ):
+            print sys.exc_type, e
+            theApp._exitstate = ExitCodes.IMPORT_ERROR
+            sys.exit( theApp._exitstate )
+         raise
+      print " +------------------------------------------------+ "
+      print " | Execute command before jobOptions script END.  | "
+      print " +------------------------------------------------+ "
+      print "\n"
+
+   ### basic job configuration before user configuration ------------------------
+   try:
+      include( pscServiceSetupBegin )
+      include.block( pscServiceSetupBegin )
+   except Exception, e:
+      print sys.exc_type, e
+      if isinstance( e, IncludeError ):
+         theApp._exitstate = ExitCodes.INCLUDE_ERROR
+         sys.exit( theApp._exitstate )      
       raise
 
-   # "sanitize" the traceback under the assumption that it is the user's fault
-   import traceback
-   exc_info = sys.exc_info()
-   tb = traceback.extract_tb( exc_info[2] )
+   if 'interactive' in dir():   
+      import TrigPSC.PscConfig 
+      TrigPSC.PscConfig.interactive = bool(interactive)
+      del interactive
+      
+   ### run user jobOptions file -------------------------------------------------
+   try:
+      include( "%s" % PscConfig.optmap['JOBOPTIONSPATH'] )
+   except Exception, e:
+      if isinstance(e,SystemExit):
+         raise
 
-   short_tb = []
-   for frame_info in tb:
-      if not 'AthenaCommon' in frame_info[0]:
-         short_tb.append( frame_info )
+      # "sanitize" the traceback under the assumption that it is the user's fault
+      import traceback
+      exc_info = sys.exc_info()
+      tb = traceback.extract_tb( exc_info[2] )
 
-   print 'Shortened traceback (most recent user call last):'
-   print ''.join( traceback.format_list( short_tb ) ),
-   print ''.join( traceback.format_exception_only( exc_info[0], exc_info[1] ) ),
+      short_tb = []
+      for frame_info in tb:
+         if not 'AthenaCommon' in frame_info[0]:
+            short_tb.append( frame_info )
 
-   # additional processing to get right error codes
-   import AthenaCommon.ExitCodes as ExitCodes
-   if isinstance( e, IncludeError ):
-      theApp._exitstate = ExitCodes.INCLUDE_ERROR
-      sys.exit( theApp._exitstate )
-   elif isinstance( e, ImportError ):
-      theApp._exitstate = ExitCodes.IMPORT_ERROR
-      sys.exit( theApp._exitstate )
-
-   # Throw exception to stop application
-   theApp._exitstate = ExitCodes.UNKNOWN_EXCEPTION
-   raise
-
-### basic job configuration after user configuration -------------------------
-try:
-   include( pscServiceSetupEnd )
-   include.block( pscServiceSetupEnd )
-except Exception, e:
-   if isinstance( e, IncludeError ):
-      print sys.exc_type, e
-      theApp._exitstate = ExitCodes.INCLUDE_ERROR
-      sys.exit( ExitCodes.INCLUDE_ERROR )
-   raise
-
-### run optional command after user job options script -----------------------   
-if PscConfig.optmap['POSTCOMMAND']:
-   print "\n"
-   print " +------------------------------------------------+ "
-   print " | Execute command after jobOptions script START. | "
-   print " +------------------------------------------------+ "
-   print " ---> Command = ", PscConfig.optmap['POSTCOMMAND']
+      print 'Shortened traceback (most recent user call last):'
+      print ''.join( traceback.format_list( short_tb ) ),
+      print ''.join( traceback.format_exception_only( exc_info[0], exc_info[1] ) ),
+
+      # additional processing to get right error codes
+      import AthenaCommon.ExitCodes as ExitCodes
+      if isinstance( e, IncludeError ):
+         theApp._exitstate = ExitCodes.INCLUDE_ERROR
+         sys.exit( theApp._exitstate )
+      elif isinstance( e, ImportError ):
+         theApp._exitstate = ExitCodes.IMPORT_ERROR
+         sys.exit( theApp._exitstate )
+
+      # Throw exception to stop application
+      theApp._exitstate = ExitCodes.UNKNOWN_EXCEPTION
+      raise
+
+   ### basic job configuration after user configuration -------------------------
    try:
-      exec PscConfig.optmap['POSTCOMMAND']
+      include( pscServiceSetupEnd )
+      include.block( pscServiceSetupEnd )
    except Exception, e:
       if isinstance( e, IncludeError ):
          print sys.exc_type, e
          theApp._exitstate = ExitCodes.INCLUDE_ERROR
          sys.exit( ExitCodes.INCLUDE_ERROR )
-      elif isinstance( e, ImportError ):
-         print sys.exc_type, e
-         theApp._exitstate = ExitCodes.IMPORT_ERROR
-         sys.exit( ExitCodes.IMPORT_ERROR )
       raise
-   print " +------------------------------------------------+ "
-   print " | Execute command after jobOptions script END.   | "
-   print " +------------------------------------------------+ "
-   print "\n"
-
-### final tweaks -------------------------------------------------------------
-
-from TriggerJobOpts.TriggerFlags import TriggerFlags
-if TriggerFlags.Online.doValidation():
-   theApp.StatusCodeCheck = True
-
-del TriggerFlags
 
-### setup everything ---------------------------------------------------------
-theApp.setup()
+   ### run optional command after user job options script -----------------------   
+   if PscConfig.optmap['POSTCOMMAND']:
+      print "\n"
+      print " +------------------------------------------------+ "
+      print " | Execute command after jobOptions script START. | "
+      print " +------------------------------------------------+ "
+      print " ---> Command = ", PscConfig.optmap['POSTCOMMAND']
+      try:
+         exec PscConfig.optmap['POSTCOMMAND']
+      except Exception, e:
+         if isinstance( e, IncludeError ):
+            print sys.exc_type, e
+            theApp._exitstate = ExitCodes.INCLUDE_ERROR
+            sys.exit( ExitCodes.INCLUDE_ERROR )
+         elif isinstance( e, ImportError ):
+            print sys.exc_type, e
+            theApp._exitstate = ExitCodes.IMPORT_ERROR
+            sys.exit( ExitCodes.IMPORT_ERROR )
+         raise
+      print " +------------------------------------------------+ "
+      print " | Execute command after jobOptions script END.   | "
+      print " +------------------------------------------------+ "
+      print "\n"
+
+   ### final tweaks -------------------------------------------------------------
+
+   from TriggerJobOpts.TriggerFlags import TriggerFlags
+   if TriggerFlags.Online.doValidation():
+      theApp.StatusCodeCheck = True
+
+   del TriggerFlags
+
+   ### setup everything ---------------------------------------------------------
+   theApp.setup()
diff --git a/HLT/Trigger/TrigControl/TrigPSC/src/Config.cxx b/HLT/Trigger/TrigControl/TrigPSC/src/Config.cxx
index b9941967b58ed29b67c2a7afef380aa7e44303e0..88729ef3683d153dabdcdd5ca352993e2ec73ef9 100644
--- a/HLT/Trigger/TrigControl/TrigPSC/src/Config.cxx
+++ b/HLT/Trigger/TrigControl/TrigPSC/src/Config.cxx
@@ -312,14 +312,19 @@ void psc::Config::fillopt_common(const ptree& hlt)
   }
 
   const ptree& com = hlt.get_child("HLTCommonParameters.HLTCommonParameters");
-  optmap["MESSAGESVCTYPE"] = com.get_child("messageSvcType").data();
+  optmap["MESSAGESVCTYPE"]    = com.get_child("messageSvcType").data();
   optmap["JOBOPTIONSSVCTYPE"] = com.get_child("jobOptionsSvcType").data();
-  optmap["DLLNAME"] = com.get_child("dllName").data();
-  optmap["FACTORYNAME"] = com.get_child("factoryName").data();
-  optmap["DF_PARTITION_NAME"] = m_config.get_child("Configuration.Partition."
-                                                   "UID").data();
-  optmap["DF_APPLICATIONNAME"] =
-      m_config.get_child("Configuration.HLTMPPUApplication.UID").data();
+  optmap["DLLNAME"]           = com.get_child("dllName").data();
+  optmap["FACTORYNAME"]       = com.get_child("factoryName").data();
+
+  optmap["DF_PARTITION_NAME"] = m_config.get_child("Configuration.Partition.UID").data();
+
+  const ptree& hltmppu = m_config.get_child("Configuration.HLTMPPUApplication");
+  optmap["DF_APPLICATIONNAME"]  = hltmppu.get_child("UID").data();
+  optmap["HARDTIMEOUT"]         = hltmppu.get_child("HardTimeout").data();
+  optmap["SOFTTIMEOUTFRACTION"] = hltmppu.get_child("softTimeoutFraction").data();
+  optmap["NEVENTSLOTS"]         = hltmppu.get_child("numberOfEventSlots").data();
+  optmap["NTHREADS"]            = hltmppu.get_child("numberOfAthenaMTThreads").data();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/HLT/Trigger/TrigControl/TrigPSC/src/Psc.cxx b/HLT/Trigger/TrigControl/TrigPSC/src/Psc.cxx
index 7c1ad2e34e2ed2c8dd06f7cab6af697718cd8c46..0469d616712174bd69fd7e3b7c7472f843ff7777 100644
--- a/HLT/Trigger/TrigControl/TrigPSC/src/Psc.cxx
+++ b/HLT/Trigger/TrigControl/TrigPSC/src/Psc.cxx
@@ -27,6 +27,7 @@
 #include "GaudiKernel/SmartIF.h"
 #include "GaudiKernel/Bootstrap.h"
 #include "GaudiKernel/IAppMgrUI.h"
+#include "GaudiKernel/IEventProcessor.h"
 #include "GaudiKernel/ISvcLocator.h"
 #include "GaudiKernel/IProperty.h"
 #include "GaudiKernel/IService.h"
@@ -130,11 +131,12 @@ bool psc::Psc::configure(const ptree& config)
        * of libGaudiSvc.
        */
       void* libHandle = 0;
-      if (System::loadDynamicLib(dllname, &libHandle)) {
+      auto retval = System::loadDynamicLib(dllname, &libHandle);
+      if (retval == 1) {
         ERS_DEBUG(1,"Successfully pre-loaded " << dllname << "library");
       }
       else {
-        ERS_DEBUG(1,"Failed pre-loading " << dllname << "library");
+        ERS_DEBUG(1,"Failed pre-loading " << dllname << "library, returned code " << retval);
       }
     }
 
@@ -419,6 +421,9 @@ bool psc::Psc::configure(const ptree& config)
         <<" MuonCalBufferSize = " << m_config->getOption("MUONCALBUFFERSIZE") );
   }
 
+  // Write configuration specific to athena (HltEventLoopMgr)
+  if(!setAthenaProperties()) return false;
+
   if ( !jobOptConfig ) {
     // Run post-command
     std::string cmd = m_config->getOption("POSTCOMMAND");
@@ -647,20 +652,6 @@ bool psc::Psc::publishStatistics (const ptree& /*args*/)
   return true;
 }
 
-//--------------------------------------------------------------------------------
-// Time out is reached
-//--------------------------------------------------------------------------------
-void psc::Psc::timeOutReached (const ptree& args)
-{
-  ERS_DEBUG(1, "Time out reached for HLT processing");
-
-  // bind args to timeOutReached
-  auto tor = [&args](ITrigEventLoopMgr * mgr)
-             {return mgr->timeOutReached(args);};
-  callOnEventLoopMgr<ITrigEventLoopMgr>(tor, "timeOutReached").ignore();
-}
-
-
 
 //--------------------------------------------------------------------------------
 // User command. Can be sent via:
@@ -807,30 +798,16 @@ bool psc::Psc::hltUserCommand(const ptree& args)
   return true;
 }
 
-bool psc::Psc::process(const vector<ROBFragment<const uint32_t*> >& l1r,
-                       hltinterface::HLTResult& hltr,
-                       const hltinterface::EventId& evId)
+void psc::Psc::doEventLoop()
 {
-  // protect against empty L1 result vector
-  if ( l1r.empty() ) {
-    ERS_PSC_ERROR("psc::Psc::process: Received no L1 Result ROBs.");
-    return false;
-  }
-
-  uint32_t lvl1_id = l1r[0].rod_lvl1_id();
-  ERS_DEBUG(2,"psc::Psc::process: Start process() of event " << lvl1_id);
-
-  //
-  //--- Process Event/RoIs with the event loop manager and fill HLT Decision
-  //
-
+  ERS_LOG("psc::Psc::doEventLoop: start of doEventLoop()");
   StatusCode sc;
   try
   {
-    // bind l1r, hltr, and evId to processRoIs
-    auto proc = [&](ITrigEventLoopMgr * mgr)
-                {return mgr->processRoIs(l1r, hltr, evId);};
-    sc = callOnEventLoopMgr<ITrigEventLoopMgr>(proc, "processRoIs");
+    // bind maxevt=-1 (meaning all events) to executeRun
+    auto exec = [](IEventProcessor * mgr)
+                {return mgr->executeRun(-1);};
+    sc = callOnEventLoopMgr<IEventProcessor>(exec, "executeRun");
   }
   catch(const ers::Issue& e)
   {
@@ -847,22 +824,10 @@ bool psc::Psc::process(const vector<ROBFragment<const uint32_t*> >& l1r,
     ERS_PSC_ERROR("Caught an unknown exception");
     sc = StatusCode::FAILURE;
   }
-
-  ERS_DEBUG(2,"psc::Psc::process: Event " << lvl1_id  << " has /n" <<
-      "       # of stream tags        = " << hltr.stream_tag.size()         << " /n"  <<
-      "       # of HLT info words      = " << hltr.trigger_info.size()          << " /n"  <<
-      "       # of PSC error words = " << hltr.psc_errors.size()         << " /n"  <<
-      "       pointer to HLT result    = 0x" << std::hex << hltr.fragment_pointer << std::dec << " /n"
-  );
-
-  if( sc.isSuccess() || sc.isRecoverable() ) {
-    return true;
-  } else {
-    ERS_PSC_ERROR("psc::Psc::process: Error in processing RoIs for Level 1 ID ="
-                  << lvl1_id << " in the EventLoopMgr '"
-                  << m_nameEventLoopMgr << "'.");
-    return false;
+  if (sc.isFailure()) {
+    ERS_PSC_ERROR("psc::Psc::doEventLoop failed");
   }
+  ERS_LOG("psc::Psc::doEventLoop: end of doEventLoop()");
 }
 
 bool psc::Psc::prepareWorker (const boost::property_tree::ptree& args)
@@ -957,10 +922,108 @@ bool psc::Psc::setDFProperties(std::map<std::string, std::string> name_tr_table)
   return true;
 }
 
+bool psc::Psc::setAthenaProperties() {
+  // Use the IProperty interface of the ApplicationManager to find the EventLoopMgr name
+  SmartIF<IProperty> propMgr(m_pesaAppMgr);
+  if (!propMgr.isValid()) {
+    ERS_PSC_ERROR("Error retrieving IProperty interface of ApplicationMgr");
+    return false;
+  }
+  std::string eventLoopMgrName;
+  if (propMgr->getProperty("EventLoop", eventLoopMgrName).isFailure()) {
+    ERS_PSC_ERROR("Error while retrieving the property ApplicationMgr.EventLoop");
+    return false;
+  }
+
+  // Use the JobOptionsSvc to write athena-specific options in JobOptions Catalogue of EventLoopMgr
+  ServiceHandle<IJobOptionsSvc> p_jobOptionSvc("JobOptionsSvc","psc::Psc");
+
+  std::string opt = m_config->getOption("HARDTIMEOUT");
+  if (!opt.empty()) {
+    StatusCode sc = p_jobOptionSvc->addPropertyToCatalogue(
+      eventLoopMgrName,
+      FloatProperty("HardTimeout",std::stof(opt))
+    );
+    if (sc.isFailure()) {
+      ERS_PSC_ERROR("Error could not write the " << eventLoopMgrName
+                    << ".HardTimeout property in JobOptions Catalogue");
+      p_jobOptionSvc->release();
+      return false;
+    }
+  }
+  else {
+    ERS_PSC_ERROR("Failed to get the HARDTIMEOUT property from the configuration tree");
+    p_jobOptionSvc->release();
+    return false;
+  }
+
+  opt = m_config->getOption("SOFTTIMEOUTFRACTION");
+  if (!opt.empty()) {
+    StatusCode sc = p_jobOptionSvc->addPropertyToCatalogue(
+      eventLoopMgrName,
+      FloatProperty("SoftTimeoutFraction",std::stof(opt))
+    );
+    if (sc.isFailure()) {
+      ERS_PSC_ERROR("Error could not write the " << eventLoopMgrName
+                    << ".SoftTimeoutFraction property in JobOptions Catalogue");
+      p_jobOptionSvc->release();
+      return false;
+    }
+  }
+  else {
+    ERS_PSC_ERROR("Failed to get the SOFTTIMEOUTFRACTION property from the configuration tree");
+    p_jobOptionSvc->release();
+    return false;
+  }
+
+  /* The names "EventDataSvc" and "AvalancheSchedulerSvc" are hard-coded below, because it is not possible
+  to retrieve them from HltEventLoopMgr properties before it is initialised. Here we need to set the properties
+  before the services are initialised." */
+
+  opt = m_config->getOption("NEVENTSLOTS");
+  if (!opt.empty()) {
+    StatusCode sc = p_jobOptionSvc->addPropertyToCatalogue(
+      "EventDataSvc",
+      IntegerProperty("NSlots",std::stoi(opt))
+    );
+    if (sc.isFailure()) {
+      ERS_PSC_ERROR("Error could not write the EventDataSvc.NSlots property in JobOptions Catalogue");
+      p_jobOptionSvc->release();
+      return false;
+    }
+  }
+  else {
+    ERS_PSC_ERROR("Failed to get the NEVENTSLOTS property from the configuration tree");
+    p_jobOptionSvc->release();
+    return false;
+  }
+
+  opt = m_config->getOption("NTHREADS");
+  if (!opt.empty()) {
+    StatusCode sc = p_jobOptionSvc->addPropertyToCatalogue(
+      "AvalancheSchedulerSvc",
+      IntegerProperty("ThreadPoolSize",std::stoi(opt))
+    );
+    if (sc.isFailure()) {
+      ERS_PSC_ERROR("Error could not write the AvalancheSchedulerSvc.ThreadPoolSize property in JobOptions Catalogue");
+      p_jobOptionSvc->release();
+      return false;
+    }
+  }
+  else {
+    ERS_PSC_ERROR("Failed to get the NTHREADS property from the configuration tree");
+    p_jobOptionSvc->release();
+    return false;
+  }
+
+  return true;
+}
+
 template <typename T>
 StatusCode psc::Psc::callOnEventLoopMgr(std::function<StatusCode (T*)> func,
                                         const std::string& name) const
 {
+  // FIXME static variables are dangerous when forking
   static T* processingMgr = 0;
   StatusCode sc;
   if(!processingMgr) // if we already got it, no need to find it again
diff --git a/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt b/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt
index 007f3f211fc07d32d8d63b40172e64b321a1b53c..9cb8349e77b3c4fc403dda5543637469a43bae5b 100644
--- a/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt
+++ b/HLT/Trigger/TrigControl/TrigServices/CMakeLists.txt
@@ -11,9 +11,11 @@ atlas_depends_on_subdirs( PUBLIC
                           Control/AthenaKernel
                           Control/StoreGate
                           Event/ByteStreamCnvSvcBase
+                          Event/ByteStreamCnvSvc
                           Event/ByteStreamData
                           Event/EventInfo
                           Event/xAOD/xAODEventInfo
+                          Event/xAOD/xAODCnvInterfaces
                           GaudiKernel
                           HLT/Trigger/TrigControl/TrigKernel
                           Trigger/TrigDataAccess/TrigDataAccessMonitoring
@@ -26,7 +28,8 @@ atlas_depends_on_subdirs( PUBLIC
                           Trigger/TrigConfiguration/TrigConfInterfaces
                           Trigger/TrigEvent/TrigNavigation
                           Trigger/TrigMonitoring/TrigMonitorBase
-                          Trigger/TrigSteer/TrigInterfaces )
+                          Trigger/TrigSteer/TrigInterfaces
+                          Trigger/TrigSteer/TrigSteering )
 
 # External dependencies:
 find_package( Boost COMPONENTS filesystem thread system )
@@ -41,15 +44,14 @@ atlas_add_library( TrigServicesLib
                    PUBLIC_HEADERS TrigServices
                    INCLUDE_DIRS ${TDAQ-COMMON_INCLUDE_DIRS} ${TDAQ_INCLUDE_DIRS}
                    PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${CORAL_INCLUDE_DIRS}
-                   LINK_LIBRARIES ${TDAQ-COMMON_LIBRARIES} ${TDAQ_LIBRARIES} AthenaBaseComps AthenaKernel ByteStreamData EventInfo xAODEventInfo GaudiKernel TrigKernel TrigSteeringEvent StoreGateLib SGtests ByteStreamCnvSvcBaseLib ByteStreamData_test TrigDataAccessMonitoringLib TrigROBDataProviderSvcLib TrigNavigationLib TrigMonitorBaseLib TrigInterfacesLib
-                   PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} ${CORAL_LIBRARIES} SGTools AthenaPoolUtilities )
+                   LINK_LIBRARIES ${TDAQ-COMMON_LIBRARIES} ${TDAQ_LIBRARIES} AthenaBaseComps AthenaKernel ByteStreamCnvSvcLib ByteStreamData EventInfo xAODEventInfo GaudiKernel TrigKernel TrigSteeringEvent StoreGateLib SGtests ByteStreamCnvSvcBaseLib ByteStreamData_test TrigDataAccessMonitoringLib TrigROBDataProviderSvcLib TrigNavigationLib TrigMonitorBaseLib TrigInterfacesLib
+                   PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} ${CORAL_LIBRARIES} SGTools AthenaPoolUtilities TrigSteering )
 
 atlas_add_component( TrigServices
                      src/components/*.cxx
                      INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${CORAL_INCLUDE_DIRS} ${TDAQ-COMMON_INCLUDE_DIRS} ${TDAQ_INCLUDE_DIRS}
-                     LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} ${CORAL_LIBRARIES} ${TDAQ-COMMON_LIBRARIES} ${TDAQ_LIBRARIES} AthenaBaseComps AthenaKernel StoreGateLib SGtests ByteStreamCnvSvcBaseLib ByteStreamData ByteStreamData_test EventInfo xAODEventInfo GaudiKernel TrigKernel TrigDataAccessMonitoringLib TrigROBDataProviderSvcLib TrigSteeringEvent SGTools AthenaPoolUtilities TrigNavigationLib TrigMonitorBaseLib TrigInterfacesLib TrigServicesLib )
+                     LINK_LIBRARIES ${ROOT_LIBRARIES} ${Boost_LIBRARIES} ${CORAL_LIBRARIES} ${TDAQ-COMMON_LIBRARIES} ${TDAQ_LIBRARIES} AthenaBaseComps AthenaKernel StoreGateLib SGtests ByteStreamCnvSvcBaseLib ByteStreamData ByteStreamData_test EventInfo xAODEventInfo GaudiKernel TrigKernel TrigDataAccessMonitoringLib TrigROBDataProviderSvcLib TrigSteeringEvent SGTools AthenaPoolUtilities TrigNavigationLib TrigMonitorBaseLib TrigInterfacesLib TrigServicesLib  TrigSteering )
 
 # Install files from the package:
 atlas_install_python_modules( python/*.py )
 atlas_install_joboptions( share/*.py )
-
diff --git a/HLT/Trigger/TrigControl/TrigServices/TrigServices/HltEventLoopMgr.h b/HLT/Trigger/TrigControl/TrigServices/TrigServices/HltEventLoopMgr.h
index 2a35beeb4ac4e6e5eabb56ee77d709c52ea301f6..eeaa3fec46eda1fdd9ccfac0b1c32017ea12e844 100644
--- a/HLT/Trigger/TrigControl/TrigServices/TrigServices/HltEventLoopMgr.h
+++ b/HLT/Trigger/TrigControl/TrigServices/TrigServices/HltEventLoopMgr.h
@@ -5,467 +5,263 @@
 #ifndef TRIGSERVICES_HLTEVENTLOOPMGR_H
 #define TRIGSERVICES_HLTEVENTLOOPMGR_H
 
+// Trigger includes
+#include "TrigKernel/IHltTHistSvc.h"
 #include "TrigKernel/ITrigEventLoopMgr.h"
-#include "EventInfo/EventID.h"  /* number_type */
-#include "EventInfo/TriggerInfo.h"
-#include "xAODEventInfo/EventInfo.h"
-#include "eformat/eformat.h"
+#include "TrigROBDataProviderSvc/ITrigROBDataProviderSvc.h"
+#include "TrigSteering/ResultBuilderMT.h"
 
-// Framework include files
-#include "GaudiKernel/ServiceHandle.h"
-#include "GaudiKernel/SmartIF.h"
-#include "GaudiKernel/ToolHandle.h"
-#include "GaudiKernel/MinimalEventLoopMgr.h"
-#include "GaudiKernel/HistoProperty.h"
+// Athena includes
+#include "AthenaBaseComps/AthService.h"
 #include "AthenaKernel/Timeout.h"
-#include "TrigKernel/HltOstreams.h"
-#include "TrigKernel/HltAcceptFlag.h"
-#include "TrigKernel/HltResultStatusCode.h"
-#include "TrigKernel/HltPscErrorCode.h"
-#include "TrigKernel/IHltTHistSvc.h"
-#include "TrigROBDataProviderSvc/ITrigROBDataProviderSvc.h"
+#include "EventInfo/EventID.h" // number_type
+#include "StoreGate/WriteHandle.h"
+#include "xAODCnvInterfaces/IEventInfoCnvTool.h"
 
-#include <tuple>
-#include <utility>
-#include <functional>
+// Gaudi includes
+#include "GaudiKernel/IEventProcessor.h"
+#include "GaudiKernel/IEvtSelector.h"
+#include "GaudiKernel/SmartIF.h"
+
+// TDAQ includes
+#include "eformat/write/FullEventFragment.h"
+
+// System includes
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
 #include <memory>
-#include <vector>
-#include <set>
-#include <stdint.h>
+#include <thread>
 
 // Forward declarations
-class IIncidentSvc;
-class IAlgContextSvc;
+class CondAttrListCollection;
+class EventContext;
 class IAlgExecStateSvc;
-class StoreGateSvc;
+class IAlgorithm;
+class IAlgResourcePool;
+class IConversionSvc;
+class IHiveWhiteBoard;
+class IIncidentSvc;
 class IROBDataProviderSvc;
+class IScheduler;
 class ITHistSvc;
-class TrigISHelper;
-class TH1F;
-class TH2I;
-class TProfile;
-class EventInfo;
+class StoreGateSvc;
 class TrigCOOLUpdateHelper;
-class CondAttrListCollection;
-class EventContext;
-
 namespace coral {
   class AttributeList;
 }
-namespace TrigConf {
-  class IHLTConfigSvc;
-}
 namespace HLT {
   class HLTResult;
 }
-namespace eformat {
-  namespace write {
-    class ROBFragment;
-  }
-}
 
-class HltEventLoopMgr : public MinimalEventLoopMgr,
-                        virtual public ITrigEventLoopMgr,
-                        virtual public Athena::TimeoutMaster
+
+class HltEventLoopMgr : public extends2<AthService, ITrigEventLoopMgr, IEventProcessor>,
+                        public Athena::TimeoutMaster
 {
 
 public:
-  /// Standard Constructor
-  HltEventLoopMgr(const std::string& nam, ISvcLocator* svcLoc);
-  /// Standard Destructor
-  virtual ~HltEventLoopMgr();
-
-  /// implementation of IInterface: queryInterface
-  virtual StatusCode queryInterface(const InterfaceID& riid, void** ppvInterface);
-
-  /// \name State transitions
-  //@{
-  virtual StatusCode sysInitialize();
-  virtual StatusCode initialize();
-  
-  virtual StatusCode prepareForRun(const boost::property_tree::ptree & pt);
 
-  virtual StatusCode hltUpdateAfterFork(const boost::property_tree::ptree & pt);
-
-  virtual StatusCode stop();
-
-  virtual StatusCode sysFinalize();
-  virtual StatusCode finalize();
-
-  virtual StatusCode sysReinitialize();
-  virtual StatusCode reinitialize();  
-  //@}
-  
-  /// Event processing
-  virtual StatusCode executeEvent(void* par);
-  
-  virtual StatusCode
-  processRoIs(const std::vector<eformat::ROBFragment<const uint32_t*> >& l1_result,
-              hltinterface::HLTResult& hlt_result,
-              const hltinterface::EventId& evId);
-
-  /// Event timoeut reached
-  virtual StatusCode timeOutReached(const boost::property_tree::ptree& pt);
-
-  /// return the application Name
-  std::string applicationName() const { return m_applicationName.value(); }
-
-    /// \name Obsolete methods for online running
-  //@{
-  virtual StatusCode nextEvent(int maxevt);          ///< Obsolete
-  virtual StatusCode executeRun(int runNumber);      ///< Obsolete
-  virtual StatusCode stopRun();                      ///< Obsolete
-  virtual StatusCode start();                        ///< Obsolete
-  //@}
-  
-private:
+  /// Standard constructor
+  HltEventLoopMgr(const std::string& name, ISvcLocator* svcLoc);
+  /// Standard destructor
+  virtual ~HltEventLoopMgr();
 
-   /**
-   * @brief Call execute method of algorithms
-   * @return FAILURE in case one algorithm failed
-   */
-  StatusCode executeAlgorithms();
+  /// @name Gaudi state transitions (overriden from AthService)
+  ///@{
+  virtual StatusCode initialize() override;
+  virtual StatusCode start() override;
+  virtual StatusCode stop() override;
+  virtual StatusCode finalize() override;
+  virtual StatusCode reinitialize() override;
+  virtual StatusCode restart() override;
+  ///@}
+
+  /// @name State transitions of ITrigEventLoopMgr interface
+  ///@{
+  virtual StatusCode prepareForRun(const boost::property_tree::ptree& pt);
+  virtual StatusCode hltUpdateAfterFork(const boost::property_tree::ptree& pt);
+  ///@}
 
   /**
-   * @brief Check if an HLT prescale update is required
-   * @param hltCounter  list of "HLT counters" from CTP fragment (only one used)
+   * Implementation of IEventProcessor::executeRun which calls IEventProcessor::nextEvent
+   * @param maxevt number of events to process, -1 means all
    */
-  StatusCode checkHltPrescaleUpdate(std::vector<uint32_t>& hltCounter);
+  virtual StatusCode executeRun(int maxevt=-1);
 
   /**
-   * @brief Do HLT prescale update
-   * @param lumiBlock  LB for which the update should be done
-   */
-  StatusCode hltPrescaleUpdate(uint32_t lumiBlock);
-  
-  /**
-   * @brief Helper to fill histograms from HLT result
-   * @param hlt_result          reference to dataflow HLTResult object
+   * Implementation of IEventProcessor::nextEvent which implements the event loop
+   * @param maxevt number of events to process, -1 means all
    */
-  void fillHltResultHistograms(const hltinterface::HLTResult& hlt_result);
-  
-  /// Check if running in partition
-  bool validPartition() const {
-    return (m_partitionName.value()!="None" && m_partitionName.value()!="NONE");  
-  }
+  virtual StatusCode nextEvent(int maxevt=-1);
 
   /**
-   * @brief Helper to set PSC error word
-   * @param hlt_result    reference to dataflow HLTResult object; filled on return
-   * @param pscErrorCode  PSC Error code which should be set
+   * Implementation of IEventProcessor::executeEvent which processes a single event
+   * @param par generic parameter
    */
-  void HltSetPscError(hltinterface::HLTResult& hlt_result,
-                      hltonl::PSCErrorCode pscErrorCode) const;
+  virtual StatusCode executeEvent(void* par);
 
   /**
-   * @brief Helper to build an empty dataflow HLT Result object
-   * @param hlt_result          reference to dataflow HLTResult object; filled on return
-   * @param run_no              for ROB fragment 
-   * @param lvl1_id             for ROB fragment 
-   * @param bunch_crossing_id   for ROB fragment
-   * @param l1_Trigger_Type     for ROB fragment
-   * @param l1_detev_type       for ROB fragment
-   * @param pscErrorCode        PSC Error code which should be set
+   * Implementation of IEventProcessor::stopRun (obsolete for online runnning)
    */
-  void HltEmptyResultROB(hltinterface::HLTResult& hlt_result,
-			 uint32_t run_no, uint32_t lvl1_id, uint32_t bunch_crossing_id, 
-			 uint32_t l1_Trigger_Type, uint32_t l1_detev_type,
-			 hltonl::PSCErrorCode pscErrorCode);
+  virtual StatusCode stopRun();
 
-  /**
-   * @brief Helper to build the dataflow HLT Result object.
-   * @return value              error code hltonl::PSCErrorCode 
-   * @param hlt_result          reference to dataflow HLTResult object; filled on return
-   * @param run_no              for ROB fragment 
-   * @param lvl1_id             for ROB fragment 
-   * @param bunch_crossing_id   for ROB fragment
-   * @param l1_Trigger_Type     for ROB fragment
-   * @param l1_detev_type       for ROB fragment
-   * @param trigger_info        trigger info words for the HLT
-   * @param stream_tags         stream tags generated during HLT processing
-   */
-  hltonl::PSCErrorCode HltResultROBs(hltinterface::HLTResult& hlt_result,
-				       uint32_t run_no, uint32_t lvl1_id, uint32_t bunch_crossing_id, 
-				       uint32_t l1_Trigger_Type, uint32_t l1_detev_type,
-				       const std::vector<TriggerInfo::number_type>& trigger_info, 
-				       const std::vector<TriggerInfo::StreamTag>& stream_tags,
-				       const std::vector<xAOD::EventInfo::StreamTag>& xsts);
-
-  /// Helper to build an empty HLTResult object
-  void HltEmptyResultROB(hltinterface::HLTResult& hlt_result,
-                         hltonl::PSCErrorCode pscErrorCode);
-  /// Helper to build HLTResult object from Steering result
-  void HltResult(hltinterface::HLTResult& hlt_result,
-                 const EventInfo* pEvent,
-                 const xAOD::EventInfo* xev);
-  /// Helpers to book histograms
-  void bookHistograms();
-  void HltBookHistograms();
-  void bookAllHistograms();
+private:
+  // ------------------------- Helper methods ----------------------------------
+
+  /// Check if running in partition
+  bool validPartition() const;
+
+  /// Read DataFlow configuration properties
   void updateDFProps();
-  // Call a simple IAlgorithm (usually member) function on all algorithms
-  StatusCode callOnAlgs(const std::function<StatusCode(IAlgorithm&)> & func,
-                        const std::string & fname, bool failureIsError = false);
-  StatusCode prepareAlgs(const EventInfo& evinfo);
-  /// Helper to reset necessary data at prepareForRun
-  StatusCode internalPrepareResets();
-  /// Helper to do whatever is necessary with RunParams (prepare) ptree
-  const CondAttrListCollection *
-  processRunParams(const boost::property_tree::ptree & pt);
-  // Helper to update internally kept data from new sor
-  void updInternal(const coral::AttributeList & sor_attrlist);
-  // Helper to get update the metadata store with a new metadata record
-  void updMetadaStore(const coral::AttributeList & sor_attrlist);
-  /// Helper to clear per-event stores
+
+  /// Do whatever is necessary with RunParams (prepare) ptree
+  const CondAttrListCollection* processRunParams(const boost::property_tree::ptree& pt);
+
+  // Update internally kept data from new sor
+  void updateInternal(const coral::AttributeList & sor_attrlist);
+
+  // Update internally kept data from new sor
+  void updateMetadataStore(const coral::AttributeList & sor_attrlist) const;
+
+  /// Clear per-event stores
   StatusCode clearTemporaryStores();
-  /// Helper to update the detector mask
-  void updDetMask(const std::pair<uint64_t, uint64_t>& dm);
-  /// Helper to update the SOR time stamp
-  void updSorTime(unsigned long long st);
-  /// Helper to extract the single attr list off the SOR CondAttrListCollection
-  const coral::AttributeList &
-  getSorAttrList(const CondAttrListCollection * sor) const;
-  /// Update the HLTConfigSvc (only required to succeed with DB based config)
-  StatusCode updHLTConfigSvc();
-  /// Set the EventInfo in the event store and return it
-  const EventInfo * prepEventInfo() const;
-  /// Set the xAOD::EventInfo in the event store
-  StatusCode prepXAODEventInfo() const;
-  /// Update the magnet field from IS when necessary and possible
-  StatusCode updMagField(const boost::property_tree::ptree& pt) const;
-  /// Reset selected proxies / IOV folders
-  StatusCode resetCoolValidity();
-  /// Helper to log a message with some details when ready to run
-  void readyMsg() const;
-  /// Helper to fill in HLTResult with stream tags
-  void setStreamTags(hltinterface::HLTResult& hltr,
-                  const std::vector<TriggerInfo::StreamTag>& stream_tags) const;
-  void mergeStreamTags(hltinterface::HLTResult& hltr,
-                     const std::vector<xAOD::EventInfo::StreamTag>& xsts) const;
-  /// get the right hlt decision, setting debug stream tag if necessary
-  hltonl::AcceptFlag processHltDecision(hltinterface::HLTResult& hltr) const;
-  /// Serializes Steering's result into hltinterface's result robs
-  hltonl::PSCErrorCode serializeRobs(hltinterface::HLTResult& hltr, bool& serOk,
-                                     HLT::HLTResult* dobj, uint32_t rn,
-                                     uint32_t l1id, uint32_t bcid,
-                                     uint32_t l1tt, uint32_t dett);
-  // Check whether a rob fits the space left. If not, issue an error
-  bool checkRobSize(uint32_t robsize, uint32_t spaceleft, uint32_t maxsize);
-  // Check consistency of the info received in the EventId and the CTP fragment
-  bool checkEventIdConsistency(const hltinterface::EventId& evId) const;
-  // serialize rob from steering's HLTResult
-  bool serializeRob(uint32_t*& tmpstor,
-                    eformat::write::ROBFragment& rob,
-                    HLT::HLTResult& dobj,
-                    unsigned int robid,
-                    int payload_max);
-  // add rob to hltinterface::HLTResult
-  void addRobToHLTResult(hltinterface::HLTResult& hltr,
-                         eformat::write::ROBFragment& rob,
-                         uint32_t*& next_fragment,
-                         uint32_t& spaceleft); /* don't pass original
-                         fragment_pointer or max_result_size (notice parameters
-                         passed by reference) */
-  // Get monitoring information for navigation sizes of HLT EDM
-  void recordEDMSizeInfo(size_t nav_size, bool serializationOk) const;
-  // check if a ROB is enabled for readout in OKS
-  bool isRobEnabled(uint32_t robid) const;
-  // check if a Sub Detector is enabled for readout in OKS
-  bool isSubDetectorEnabled(uint32_t subdetid) const;
-  // filter a set of robs according to whether or not they are enabled
-  std::set<uint32_t> filterRobs(const std::set<uint32_t>& robs) const;
-  // filter a set of dets according to whether or not they are enabled
-  std::set<eformat::SubDetector>
-  filterDets(const std::set<uint32_t>& dets) const;
-
-  // act on failure to process event
-  void failedEvent(hltinterface::HLTResult& hlt_result,
-                   hltonl::PSCErrorCode ecode,
-                   const std::string& emsg,
-                   bool empty_result = true);
-
-  // get a vector with the ids of the expected L1R robs that are missing
-  std::vector<uint32_t>
-  missingL1Robs(const std::vector<eformat::ROBFragment<const uint32_t*>>& l1r)
-  const;
-
-  // check whether a subdetector is in the run, according to the current detmask
-  bool isSubDetectorIn(eformat::SubDetector sd) const;
-
-  // Helper to create EventContext
-  StatusCode installEventContext (const EventInfo* pEvent, EventID::number_type run);
-
-  /** Handles to required services/tools **/
-  typedef ServiceHandle<IIncidentSvc> IIncidentSvc_t;
-  IIncidentSvc_t         m_incidentSvc;
-
-  typedef ServiceHandle<StoreGateSvc> StoreGateSvc_t;
-  StoreGateSvc_t         m_evtStore;
-  StoreGateSvc_t         m_detectorStore;
-  StoreGateSvc_t         m_inputMetaDataStore;
-
-  typedef ServiceHandle<IROBDataProviderSvc> IIROBDataProviderSvc_t;
-  IIROBDataProviderSvc_t m_robDataProviderSvc;
-
-  typedef ServiceHandle<ITHistSvc> ITHistSvc_t;
-  ITHistSvc_t            m_THistSvc;
-
-  ServiceHandle<IAlgExecStateSvc> m_aess;
-
-  ToolHandle<TrigISHelper>            m_isHelper;
-  ToolHandle<TrigCOOLUpdateHelper>    m_coolHelper;
-
-  /** Pointers to optional services/tools **/
-  TrigConf::IHLTConfigSvc* m_hltConfigSvc{0};
-  IAlgContextSvc*          m_algContextSvc{0};
-
-  IntegerProperty          m_lvl1CTPROBid ;       // Source ID for CTP ROB fragment
-  BooleanProperty          m_doMonitoring;        // Monitoring
-
-  /// Helper classes for error codes
-  hltonl::MapPscErrorCode  m_mapPscError;
-  hltonl::MapResultStatusCode m_mapResultStatus;
-  hltonl::MapAcceptFlag       m_mapAccept;
-
-  EventID::number_type      m_currentRun{0};   //!< current run number
-  EventID::number_type      m_currentLB{0};    //!< current lumiblock
-  const EventInfo*          m_currentEvent{0}; //!< current EventInfo object in StoreGate
-  
-  /// Start of Run Time: posix time in seconds since 1970/01/01
-  /// Start of Run Time: time stamp ns - ns time offset for time_stamp, 32 bit unsigned
-  std::vector<EventID::number_type> m_sorTime_stamp;
-
-  /// detector mask0,1,2,3 - bit field indicating which TTC zones have been
-  /// built into the event, one bit per zone, 128 bit total
-  /// significance increases from first to last
-  typedef EventID::number_type numt;
-  std::tuple<numt, numt, numt, numt> m_detector_mask;
 
-  uint32_t                  m_l1_hltPrescaleUpdateLB;    //!< LB of prescale update from CTP fragment
-  
-  // --------------------------- Monitoring Histograms --------------------------
-  TH1F*                     m_hist_eventAcceptFlags{0};            //!< Accept flags for processed events
-  TH1F*                     m_hist_frameworkErrorCodes{0};         //!< PSC error codes
-  TH1F*                     m_hist_Hlt_result_size{0};             //!< size of HLT result
-  TH1F*                     m_hist_Hlt_result_status{0};           //!< Status flags in HLT result
-  TH1F*                     m_hist_numStreamTags{0};               //!< Number of StreamTags from HLT
-  TH1F*                     m_hist_streamTagTypes{0};              //!< StreamTag types from HLT   
-  TH1F*                     m_hist_streamTagNames{0};              //!< StreamTag names from HLT
-  TH1F*                     m_hist_num_partial_eb_robs{0};         //!< Number of ROBs for partial event building from HLT   
-  TH1F*                     m_hist_num_partial_eb_SubDetectors{0}; //!< Number of SubDetectors for partial event building from HLT 
-  TH1F*                     m_hist_partial_eb_SubDetectors_ROBs{0};//!< SubDetectors for partial event building derived from ROB list
-  TH1F*                     m_hist_partial_eb_SubDetectors_SDs{0}; //!< SubDetectors for partial event building derived from SubDetector list
-  TH1F*                     m_hist_Hlt_result_size_physics{0};           //!< size of HLT result in physics Main
-  TH1F*                     m_hist_Hlt_result_size_express{0};           //!< size of HLT result in express stream
-  TH1F*                     m_hist_Hlt_result_size_DataScouting{0};      //!< size of HLT result in express stream
-  TProfile*                 m_hist_HltResultSizes_Stream_physics{0};     //!< HLT Result sizes for physiscs streams
-  TProfile*                 m_hist_HltResultSizes_Stream_DataScouting{0};//!< HLT Result sizes for DataScouting streams
-  TProfile*                 m_hist_HltEdmSizes_No_Truncation{0};   //!< HLT EDM sizes for all events without a truncated HLT result 
-  TProfile*                 m_hist_HltEdmSizes_With_Truncation{0}; //!< HLT EDM sizes for all events with a truncated HLT result 
-  TProfile*                 m_hist_HltEdmSizes_TruncatedResult_Retained_Collections{0}; //!< HLT EDM sizes for all collections which were retained in a truncated HLT result
-  TProfile*                 m_hist_HltEdmSizes_TruncatedResult_Truncated_Collections{0};//!< HLT EDM sizes for all collections which were truncated in a truncated HLT result
-  // --------------------------- Properties -------------------------------------
-  BooleanProperty           m_setMagFieldFromPtree; //!< Read magnet currents from ptree
-  StringProperty            m_applicationName;      //!< Application Name (="None" or "athenaHLT" for simulated data, "HLTMPPU-xx"? in online environment) */
-  StringProperty            m_partitionName;        //!< Partition Name (="None" for offline, real partion name in online environment)
-  BooleanProperty           m_forceHltReject;      // force reject of all events 
-  BooleanProperty           m_forceHltAccept;      // force accept of all events
-  StringProperty            m_HltResultName;       // name of HLT result in StoreGate
-  StringProperty            m_HltDebugStreamName;  // stream name for Debug events 
-  StringProperty            m_HltForcedStreamName; // stream name for forced accept events
-  IntegerProperty           m_predefinedLumiBlock;
-  IntegerProperty           m_prepareForRunSleep;    //!< max random sleep during prepareForRun in sec
-
-  typedef SimpleProperty< std::vector<uint32_t> > Uint32ArrayProperty;
-  Uint32ArrayProperty       m_enabledROBs;         //!< list of all enabled ROBs which can be retrieved
-  Uint32ArrayProperty       m_enabledSubDetectors; //!< list of all enabled Sub Detectors which can be retrieved
-  Uint32ArrayProperty       m_mandatoryL1ROBs;     //!< list of mandatory ROB IDs coming from the RoIB (must come in L1R seed)
-
-  StringArrayProperty       m_hltEdmCollectionNames; //!< names of all HLT EDM collections for histogram label 
-  
-  StringProperty            m_jobOptionsType;        //!< JobOptions type (="NONE" or "DB", same as in PSC)
-
-  Histo1DProperty           m_histProp_Hlt_result_size;
-  Histo1DProperty           m_histProp_Hlt_result_size_physics;
-  Histo1DProperty           m_histProp_Hlt_result_size_express;
-  Histo1DProperty           m_histProp_Hlt_result_size_DataScouting;
-  Histo1DProperty           m_histProp_numStreamTags;              
-  Histo1DProperty           m_histProp_streamTagNames;  
-  Histo1DProperty           m_histProp_num_partial_eb_robs;
-  Histo1DProperty           m_histProp_Hlt_Edm_Sizes;       //!< HLT EDM sizes profile plots 
-
-  int                       m_total_evt{0};
-  int                       m_failed_evt{0};
-  int                       m_invalid_lvl1_result{0};
-  int                       m_invalid_hlt_result{0};
-  int                       m_truncated_hlt_result{0};
-  int                       m_truncated_hlt_result_to_debug{0};
-  int                       m_truncated_hlt_result_not_to_debug{0};
-
-  // for CTP Lvl1 Rob
-  std::vector<uint32_t>     m_ctpRobIdVec ;
-  // event number - 32 bit unsigned
-  uint32_t                  m_lvl1id{0}  ;
-  // run number - 32 bit unsigned
-  EventID::number_type      m_run_no{0} ;
-  // bunch crossing ID,  32 bit unsigned
-  EventID::number_type      m_bunch_crossing_id{0} ;
-  // time stamp - posix time in seconds from 1970, 32 bit unsigned
-  EventID::number_type      m_time_stamp{0} ;
-  // time stamp ns - ns time offset for time_stamp, 32 bit unsigned
-  EventID::number_type      m_time_stamp_ns_offset{0} ;
-  // luminosity block identifier, 32 bit unsigned
-  EventID::number_type      m_lumi_block{0} ;
-  // status element
-  TriggerInfo::number_type  m_l1_Status_Element{0} ;
-  // LVL1 trigger type
-  TriggerInfo::number_type  m_l1_Trigger_Type{0} ;
-  // LVL1 trigger info
-  std::vector<TriggerInfo::number_type> m_l1_Trigger_Info ;
-  // LVL1 detev type
-  uint32_t                  m_l1_detev_type{0} ;
+  /// Update the detector mask
+  void updateDetMask(const std::pair<uint64_t, uint64_t>& dm);
 
-  /// Reference to a THistSvc which implements also the Hlt additions
-  SmartIF<IHltTHistSvc>     m_hltTHistSvc;
+  /// Extract the single attr list off the SOR CondAttrListCollection
+  const coral::AttributeList& getSorAttrList(const CondAttrListCollection* sor) const;
 
-  /// Reference to a ROBDataProviderSvc which implements also the Hlt additions
-  SmartIF<ITrigROBDataProviderSvc> m_hltROBDataProviderSvc;
+  /// Print the SOR record
+  void printSORAttrList(const coral::AttributeList& atr) const;
 
-  /// Check integrity of CTP ROB and put event to debug stream when it fails
-  BooleanProperty           m_lvl1CTPROBcheck ;
+  /// Handle a failure to process an event
+  void failedEvent(EventContext* eventContext,
+                   const xAOD::EventInfo* eventInfo=nullptr,
+                   HLT::HLTResult* hltResult=nullptr) const;
 
-  /// Monitoring
-  TH1F*                     m_hist_l1_robs{0};
+  // Build an HLT result FullEventFragment and serialise it into uint32[]
+  std::unique_ptr<uint32_t[]> fullHltResult(const xAOD::EventInfo* eventInfo,
+                                            HLT::HLTResult* hltResult) const;
 
-  /// Flag to write events with truncated HLT result to a special debug stream
-  BooleanProperty           m_writeHltTruncationToDebug ;
-  /// Debug stream name for events with a truncated HLT result 
-  StringProperty            m_HltTruncationDebugStreamName; 
-  /// Stream names for which events should be not send to the debug stream even when the HLT result is truncated
-  StringArrayProperty       m_excludeFromHltTruncationDebugStream; 
-  /// Monitoring histogram for truncated HLT results
-  TH1F*                     m_hist_Hlt_truncated_result{0};
+  /// Send an HLT result to the DataCollector
+  void eventDone(std::unique_ptr<uint32_t[]> hltResult) const;
 
-  /// we need this maintain the data
-  uint32_t                  m_status_words[3] = {0};
+  /// The method executed by the event timeout monitoring thread
+  void runEventTimer();
 
-  EventContext m_eventContext;
-};
+  // ------------------------- Reimplemented AthenaHiveEventLoopMgr helpers ----
+  /// Create event context
+  StatusCode createEventContext(EventContext*& eventContext) const;
 
-//=========================================================================
-inline StatusCode HltEventLoopMgr::start()
-{
-  // This method might be called by ServiceManager::start and does nothing.
-  // The real start method is prepareForRun and invoked by the PSC.
-  return StatusCode::SUCCESS;
-}
+  /// Drain the scheduler from all actions that may be queued
+  int drainScheduler();
 
-//=========================================================================
-inline void
-HltEventLoopMgr::HltSetPscError(hltinterface::HLTResult& hlt_result,
-                                hltonl::PSCErrorCode pscErrorCode) const
-{
-  hlt_result.psc_errors.push_back(pscErrorCode);
+  /// Clear an event slot in the whiteboard
+  StatusCode clearWBSlot(int evtSlot) const;
+
+  // ------------------------- Handles to required services/tools --------------
+  ServiceHandle<IIncidentSvc>        m_incidentSvc;
+  ServiceHandle<StoreGateSvc>        m_evtStore;
+  ServiceHandle<StoreGateSvc>        m_detectorStore;
+  ServiceHandle<StoreGateSvc>        m_inputMetaDataStore;
+  ServiceHandle<IROBDataProviderSvc> m_robDataProviderSvc;
+  ServiceHandle<ITHistSvc>           m_THistSvc;
+  ServiceHandle<IEvtSelector>        m_evtSelector;
+  ServiceHandle<IConversionSvc>      m_outputCnvSvc;
+
+  /// Reference to the Whiteboard interface
+  SmartIF<IHiveWhiteBoard> m_whiteboard;
+  /// Reference to the Algorithm resource pool
+  SmartIF<IAlgResourcePool> m_algResourcePool;
+  /// Reference to the Algorithm Execution State Svc
+  SmartIF<IAlgExecStateSvc> m_aess;
+  /// A shortcut for the scheduler
+  SmartIF<IScheduler> m_schedulerSvc;
+
+  /// Helper tool for COOL updates
+  ToolHandle<TrigCOOLUpdateHelper> m_coolHelper;
+
+  /// Tool to create HLTResult
+  ToolHandle<HLT::ResultBuilderMT> m_hltResultBuilder;
+
+  /// EventInfo -> xAOD::EventInfo conversion tool
+  ToolHandle<xAODMaker::IEventInfoCnvTool> m_eventInfoCnvTool;
+
+  // ------------------------- Optional services/tools -------------------------
+  /// Reference to a THistSvc which implements also the Hlt additions
+  SmartIF<IHltTHistSvc> m_hltTHistSvc;
+  /// Reference to a ROBDataProviderSvc which implements also the Hlt additions
+  SmartIF<ITrigROBDataProviderSvc> m_hltROBDataProviderSvc;
+
+  // ------------------------- Properties --------------------------------------
+  /// Application Name (="None" or "athenaHLT" for simulated data, "HLTMPPU-xx"? in online environment)
+  StringProperty m_applicationName;
+  /// Partition Name (="None" for offline, real partion name in online environment)
+  StringProperty m_partitionName;
+  /// JobOptions type (="NONE" or "DB", same as in PSC)
+  StringProperty m_jobOptionsType;
+  /// Name of the scheduler to be used
+  StringProperty m_schedulerName;
+  /// Name of the Whiteboard to be used
+  StringProperty m_whiteboardName;
+  /// Vector of top level algorithm names
+  Gaudi::Property<std::vector<std::string> > m_topAlgNames;
+
+  /// list of all enabled ROBs which can be retrieved
+  SimpleProperty<std::vector<uint32_t> > m_enabledROBs;
+  /// list of all enabled Sub Detectors which can be retrieved
+  SimpleProperty<std::vector<uint32_t> > m_enabledSubDetectors;
+
+  /// Hard event processing timeout
+  FloatProperty m_hardTimeout;
+  /// Hard event processing timeout
+  FloatProperty m_softTimeoutFraction;
+
+  /// StoreGate key for xAOD::EventInfo WriteHandle (needed for manual conversion from old EventInfo)
+  SG::WriteHandleKey<xAOD::EventInfo> m_xEventInfoWHKey;
+
+  // ------------------------- Other private members ---------------------------
+  /// typedef used for detector mask fields
+  typedef EventID::number_type numt;
+  /**
+   * Detector mask0,1,2,3 - bit field indicating which TTC zones have been built into the event,
+   * one bit per zone, 128 bit total, significance increases from first to last
+   */
+  std::tuple<numt, numt, numt, numt> m_detector_mask;
+
+  /// Current run number
+  EventID::number_type m_currentRun{0};
+  /// Number of events which started processing
+  size_t m_nevt;
+  /// Current run number
+  int m_threadPoolSize;
+
+  /// Event selector context
+  IEvtSelector::Context* m_evtSelContext;
+
+  /// Vector of top level algorithms
+  std::vector<SmartIF<IAlgorithm> > m_topAlgList;
+
+  /// Vector of event start-processing time stamps in each slot
+  std::vector<std::chrono::steady_clock::time_point> m_eventTimerStartPoint;
+  /// Vector of flags to tell if a slot is idle or processing
+  std::vector<bool> m_isSlotProcessing; // be aware of vector<bool> specialisation
+  /// Timeout mutex
+  std::mutex m_timeoutMutex;
+  /// Timeout condition variable
+  std::condition_variable m_timeoutCond;
+  /// Timeout thread
+  std::unique_ptr<std::thread> m_timeoutThread;
+  /// Soft timeout value
+  int m_softTimeoutValue;
+  /// Flag set to false if timer thread should be stopped
+  std::atomic<bool> m_runEventTimer;
+};
+
+//==============================================================================
+inline bool HltEventLoopMgr::validPartition() const {
+  return (m_partitionName.value()!="None" && m_partitionName.value()!="NONE");
 }
 
 #endif // TRIGSERVICES_HLTEVENTLOOPMGR_H
diff --git a/HLT/Trigger/TrigControl/TrigServices/python/TriggerUnixStandardSetup.py b/HLT/Trigger/TrigControl/TrigServices/python/TriggerUnixStandardSetup.py
index a23e44b44b7d34c0ee87a0518d9a406aa16663d0..9829367063c546023f1863e763f2db0c29390c08 100644
--- a/HLT/Trigger/TrigControl/TrigServices/python/TriggerUnixStandardSetup.py
+++ b/HLT/Trigger/TrigControl/TrigServices/python/TriggerUnixStandardSetup.py
@@ -87,8 +87,8 @@ def _setupCommonServices():
         svcMgr += CoreDumpSvc()
         
     # Configure COOL update helper tool
-    from TrigServices.TrigServicesConfig import TrigCOOLUpdateHelper
-    _eventLoopMgr(svcMgr).CoolUpdateTool = TrigCOOLUpdateHelper()
+    # from TrigServices.TrigServicesConfig import TrigCOOLUpdateHelper
+    # _eventLoopMgr(svcMgr).CoolUpdateTool = TrigCOOLUpdateHelper()
             
     # Setup online THistSvc unless specifically configured otherwise
     if _Conf.useOnlineTHistSvc:
diff --git a/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonBegin.py b/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonBegin.py
index ab547b95b65e5f37b3e2dfb7e37ca5b60555ed6e..bddc77849fa2ad16e95f5e50c9fd4cea76687b9c 100644
--- a/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonBegin.py
+++ b/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonBegin.py
@@ -8,10 +8,10 @@ include( "TrigServices/MessageSvc.py" )
 include( "TrigServices/TrigServicesEventLoopMgr.py" )
 
 ## HLT standard service configuration
-from TrigServices.TriggerUnixStandardSetup import setupHLTServicesBegin
-setupHLTServicesBegin()
+# from TrigServices.TriggerUnixStandardSetup import setupHLTServicesBegin
+# setupHLTServicesBegin()
 ## clean-up: avoid running multiple times this method
-del setupHLTServicesBegin
+# del setupHLTServicesBegin
 
 #==============================================================
 #
diff --git a/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonEnd.py b/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonEnd.py
index dc98afa1a7abf99c39dfa4ce1e1672de1ff623ad..2cd3fa3055226dad589ffef020f348b06a80402a 100644
--- a/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonEnd.py
+++ b/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesCommonEnd.py
@@ -5,13 +5,13 @@
 #==============================================================
 
 ## get a handle on the ServiceMgr
-from AthenaCommon.AppMgr import ServiceMgr as svcMgr
+# from AthenaCommon.AppMgr import ServiceMgr as svcMgr
 
 ## HLT standard service configuration 
-from TrigServices.TriggerUnixStandardSetup import setupHLTServicesEnd
-setupHLTServicesEnd()
+# from TrigServices.TriggerUnixStandardSetup import setupHLTServicesEnd
+# setupHLTServicesEnd()
 ## clean-up: avoid running multiple times this method
-del setupHLTServicesEnd
+# del setupHLTServicesEnd
 #==============================================================
 #
 # End of HLT common configuration file: TrigServicesCommonEnd.py
diff --git a/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesEventLoopMgr.py b/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesEventLoopMgr.py
index 17aac25c1038ace58536e9730fb257620600f4b0..5c35f23b170f2ec711f0db90b3d74eb092c56e45 100644
--- a/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesEventLoopMgr.py
+++ b/HLT/Trigger/TrigControl/TrigServices/share/TrigServicesEventLoopMgr.py
@@ -3,25 +3,179 @@
 # TrigServicesEventLoopMgr configuration file
 #
 #==============================================================
+from AthenaCommon import CfgMgr
 from AthenaCommon.AppMgr import theApp
 from AthenaCommon.AppMgr import ServiceMgr as svcMgr
-from AthenaCommon.Constants import *
+from AthenaCommon.AppMgr import ToolSvc
+
+# from AthenaCommon.Constants import *
+
+# ==============================================================================
+# Set up from StoreGateHiveExample.py and AthExHiveOpts.py and AtlasThreadedJob.py
+# ==============================================================================
+#nThreads = 1
+#numStores = 1
+#numAlgsInFlight = nThreads
+
+#from AthenaCommon.ConcurrencyFlags import jobproperties as jps
+#jps.ConcurrencyFlags.NumThreads = nThreads
+#jps.ConcurrencyFlags.NumConcurrentEvents = numStores
+
+# from GaudiCommonSvc.GaudiCommonSvcConf import AlgContextSvc
+# svcMgr += AlgContextSvc("AlgContextSvc")
+# svcMgr.AlgContextSvc.Check = True
+
+from StoreGate.StoreGateConf import SG__HiveMgrSvc
+svcMgr += SG__HiveMgrSvc("EventDataSvc")
+#svcMgr.EventDataSvc.NSlots = numStores
+#svcMgr.EventDataSvc.OutputLevel = VERBOSE
+
+from GaudiHive.GaudiHiveConf import AlgResourcePool
+arp=AlgResourcePool( OutputLevel = INFO )
+arp.TopAlg=["AthMasterSeq"] #this should enable control flow
+svcMgr += arp
+
+from AthenaCommon.AlgScheduler import AlgScheduler
+#AlgScheduler.setThreadPoolSize(nThreads)
+AlgScheduler.ShowDataDependencies(True)
+AlgScheduler.ShowControlFlow(True)
+AlgScheduler.OutputLevel=VERBOSE
+
+from StoreGate.StoreGateConf import StoreGateSvc
+svcMgr += StoreGateSvc()
+svcMgr.StoreGateSvc.OutputLevel = VERBOSE
+svcMgr.StoreGateSvc.Dump = True
+
+from StoreGate.StoreGateConf import SGImplSvc
+svcMgr += SGImplSvc("SGImplSvc")
+svcMgr.SGImplSvc.OutputLevel = VERBOSE
+
+# ThreadPoolService thread local initialization
+from GaudiHive.GaudiHiveConf import ThreadPoolSvc
+svcMgr += ThreadPoolSvc("ThreadPoolSvc")
+svcMgr.ThreadPoolSvc.ThreadInitTools = ["ThreadInitTool"]
+
+from AthenaCommon.AlgSequence import AlgSequence
+topSequence = AlgSequence()
+#algCardinality = nThreads
+
+# if (algCardinality != 1):
+#     for alg in topSequence:
+#        name = alg.name()
+#        alg.Cardinality = algCardinality
+
+from SGComps.SGCompsConf import SGInputLoader
+topSequence += SGInputLoader( FailIfNoProxy=False )
+
+theAuditorSvc = svcMgr.AuditorSvc
+theApp.AuditAlgorithms=True
+from SGComps.SGCompsConf import SGCommitAuditor
+theAuditorSvc += SGCommitAuditor()
+
+# for easier browsing of verbose logs
+ClassIDSvc = Service("ClassIDSvc")
+ClassIDSvc.OutputLevel = DEBUG
+
+# ==============================================================================
+# Event selector and input service
+# ==============================================================================
+from TrigByteStreamCnvSvc.TrigByteStreamCnvSvcConf import TrigByteStreamInputSvc
+inputSvc = TrigByteStreamInputSvc("ByteStreamInputSvc")
+svcMgr += inputSvc
+
+from TrigByteStreamCnvSvc.TrigByteStreamCnvSvcConf import TrigEventSelectorByteStream
+evtSel = TrigEventSelectorByteStream("EventSelector")
+evtSel.ByteStreamInputSvc = inputSvc
+svcMgr += evtSel
+theApp.EvtSel = "EventSelector"
+
+# ==============================================================================
+# Output conversion service
+# ==============================================================================
+from TrigByteStreamCnvSvc.TrigByteStreamCnvSvcConf import TrigByteStreamCnvSvc
+outputCnvSvc = TrigByteStreamCnvSvc("TrigByteStreamCnvSvc")
+svcMgr += outputCnvSvc
+
+# ==============================================================================
+# Some extra services
+# ==============================================================================
+## basic Gaudi services from AtlasUnixStandardJob.py
+import GaudiSvc.GaudiSvcConf as GaudiSvcConf
+svcMgr += GaudiSvcConf.IncidentSvc()
+svcMgr += GaudiSvcConf.EvtPersistencySvc( "EventPersistencySvc" )
+svcMgr += GaudiSvcConf.HistogramSvc( "HistogramDataSvc" )
+svcMgr += GaudiSvcConf.NTupleSvc()
+svcMgr += GaudiSvcConf.ToolSvc()
+svcMgr += GaudiSvcConf.RndmGenSvc()
+svcMgr += GaudiSvcConf.ChronoStatSvc()
+
+#####
+
+from StoreGate.StoreGateConf import StoreGateSvc
+svcMgr += StoreGateSvc("DetectorStore")
+
+# ProxyProviderSvc services configuration
+svcMgr += CfgMgr.ProxyProviderSvc()
+
+# --- ByteStreamAddressProviderSvc configuration
+svcMgr += CfgMgr.ByteStreamAddressProviderSvc()
+svcMgr.ProxyProviderSvc.ProviderNames += [ "ByteStreamAddressProviderSvc" ]
+#theApp.CreateSvc += [ svcMgr.ByteStreamAddressProviderSvc.getFullName() ]
+
+# Initialization of DetDescrCnvSvc
+svcMgr += CfgMgr.DetDescrCnvSvc(
+    # specify primary Identifier dictionary to be used
+    IdDictName = "IdDictParser/ATLAS_IDS.xml"
+    )
+theApp.CreateSvc += [ svcMgr.DetDescrCnvSvc.getFullName() ]
+svcMgr.EventPersistencySvc.CnvServices += [ "DetDescrCnvSvc" ]
+
+# --- ByteStreamCnvSvc configuration
+svcMgr += CfgMgr.ByteStreamCnvSvc("ByteStreamCnvSvc")
+svcMgr.EventPersistencySvc.CnvServices += [ "ByteStreamCnvSvc" ]
+
+# dictionary services from AtlasUnixStandardJob.py
+# the dict loader
+import AthenaServices.AthenaServicesConf as AthenaServicesConf
+if not hasattr(svcMgr, 'AthDictLoaderSvc'):
+    svcMgr += AthenaServicesConf.AthDictLoaderSvc()
+theApp.CreateSvc += [svcMgr.AthDictLoaderSvc.getFullJobOptName()]
+
+# the dict checker
+if not hasattr(svcMgr, 'AthenaSealSvc'):
+    svcMgr += AthenaServicesConf.AthenaSealSvc()
+theApp.CreateSvc += [svcMgr.AthenaSealSvc.getFullJobOptName()]
+
+# ==============================================================================
+#  Message format
+# ==============================================================================
+msgFmt = "% F%40W%S %4W%e%s %7W%R %T %0W%M"
+svcMgr.MessageSvc.Format = msgFmt
+
+# ==============================================================================
+# General setup
+# ==============================================================================
 
 # make the HltEventLoopMgr service available
 svcMgr.HltEventLoopMgr = theApp.service( "HltEventLoopMgr" )     # already instantiated
 HltEventLoopMgr = svcMgr.HltEventLoopMgr
+HltEventLoopMgr.WhiteboardSvc = "EventDataSvc"
+HltEventLoopMgr.SchedulerSvc = AlgScheduler.getScheduler().getName()
+HltEventLoopMgr.EvtSel = evtSel
+HltEventLoopMgr.OutputCnvSvc = outputCnvSvc
+
 
 # configure here Level-1 CTP ROB identifier which is used in HLT
-HltEventLoopMgr.Lvl1CTPROBid = 0x770001
+# HltEventLoopMgr.Lvl1CTPROBid = 0x770001
 
 # request that events with invalid or missing CTP ROBs are skipped by the HltEventLoopMgr
 # (default: don't skip these events)
-HltEventLoopMgr.Lvl1CTPROBcheck = TRUE
+# HltEventLoopMgr.Lvl1CTPROBcheck = TRUE
 
 #
 # name of the HLT Result object in StoreGate
 #
-HltEventLoopMgr.HltResultName = "HLTResult_HLT"
+# HltEventLoopMgr.HltResultName = "HLTResult_HLT"
 
 #
 # handling of truncated HLT Results
@@ -32,47 +186,44 @@ HltEventLoopMgr.HltResultName = "HLTResult_HLT"
 #HltEventLoopMgr.HltTruncationDebugStreamName = "TruncatedHLTResult"
 
 # list of stream names which should not be send to the truncation DEBUG stream (default ["CostMonitoring"]) 
-HltEventLoopMgr.ExcludeFromHltTruncationDebugStream = ["CostMonitoring"]
+# HltEventLoopMgr.ExcludeFromHltTruncationDebugStream = ["CostMonitoring"]
 
 #
 # properties for the HLT result size histograms
 # --> set upper edge of histogram to maximum allowed number of words in HLT
 #
-# HltEventLoopMgr.histHltResultSize=("HltResultSize",0,500000,100)
-# HltEventLoopMgr.histHltResultSizePhysics=("HltResultSize-(Stream (Main_physics))",0,500000,100)
-# HltEventLoopMgr.histHltResultSizeExpress=("HltResultSize-(Stream (express_express))",0,250000,100)
-# HltEventLoopMgr.histHltResultSizeDS=("HltResultSize-(Streams (DataScouting_*_calibration))",0,125000,100)
+# HltEventLoopMgr.histHltResultSize=("HltResultSize",0,125000,100)
 
 #
 # Configuration of EDM size monitoring plots
 #
-try:
-    from TrigEDMConfig.TriggerEDM import EDMDetails,getTypeAndKey,keyToLabel
-    from TrigEDMConfig.TriggerEDM import TriggerHLTList
-    
-    # TODO update to use import TriggerHLTList directly
-    #from TrigEDMConfig.TriggerEDM import TriggerL2List,TriggerEFList
-    #TriggerHLTList = list(set(TriggerL2List).union(TriggerEFList))
-    
-    l = []
-    for item in TriggerHLTList:
-        if ('BS' in item[1].split()) or ('DS' in item[1].split()):
-            t,k = getTypeAndKey(item[0])
-            ctype = t
-            if EDMDetails[t].has_key('collection'):
-                ctype = EDMDetails[t]['collection']
-            l += [ctype+'__'+keyToLabel(k)]
-    # add a bin for not accounted collections
-    l += ['not__configured']
-
-    HltEventLoopMgr.HltEDMCollectionNames = l
-    number_of_collections=len( HltEventLoopMgr.HltEDMCollectionNames )
-    HltEventLoopMgr.histHltEdmSizes=("HltEDMSizes",0., 15000., number_of_collections)
-except ImportError,e:
-    print " +----------------------------------------------------------------------+ "
-    print " | No initial configuration for EDM monitoring plots will be available! | "
-    print " +----------------------------------------------------------------------+ "
-    print e
+# try:
+    # from TrigEDMConfig.TriggerEDM import EDMDetails,getTypeAndKey,keyToLabel
+    # from TrigEDMConfig.TriggerEDM import TriggerHLTList
+    # 
+    # # TODO update to use import TriggerHLTList directly
+    # #from TrigEDMConfig.TriggerEDM import TriggerL2List,TriggerEFList
+    # #TriggerHLTList = list(set(TriggerL2List).union(TriggerEFList))
+    # 
+    # l = []
+    # for item in TriggerHLTList:
+        # if ('BS' in item[1].split()) or ('DS' in item[1].split()):
+            # t,k = getTypeAndKey(item[0])
+            # ctype = t
+            # if EDMDetails[t].has_key('collection'):
+                # ctype = EDMDetails[t]['collection']
+            # l += [ctype+'__'+keyToLabel(k)]
+    # # add a bin for not accounted collections
+    # l += ['not__configured']
+# 
+    # HltEventLoopMgr.HltEDMCollectionNames = l
+    # number_of_collections=len( HltEventLoopMgr.HltEDMCollectionNames )
+    # HltEventLoopMgr.histHltEdmSizes=("HltEDMSizes",0., 15000., number_of_collections)
+# except ImportError,e:
+    # print " +----------------------------------------------------------------------+ "
+    # print " | No initial configuration for EDM monitoring plots will be available! | "
+    # print " +----------------------------------------------------------------------+ "
+    # print e
 #==============================================================
 #
 # End of TrigServicesEventLoopMgr configuration file
diff --git a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx
index 8fb7371777cf078249488c6b5ccdad919204c9bc..39836737a2d16024b4b45e6a205cc9878248383c 100644
--- a/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx
+++ b/HLT/Trigger/TrigControl/TrigServices/src/HltEventLoopMgr.cxx
@@ -2,2504 +2,944 @@
   Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
 */
 
-// Gaudi includes
-#include "GaudiKernel/IAlgorithm.h"
-#include "GaudiKernel/Incident.h"
-#include "GaudiKernel/IIncidentSvc.h"
-#include "GaudiKernel/IEvtSelector.h"
-#include "GaudiKernel/IJobOptionsSvc.h"
-#include "GaudiKernel/ITHistSvc.h"
-#include "GaudiKernel/Timing.h"
-#include "GaudiKernel/IAlgContextSvc.h"
-#include "GaudiKernel/IAlgExecStateSvc.h"
-#include "GaudiKernel/IAlgManager.h"
-#include "GaudiKernel/ServiceLocatorHelper.h"
-#include "GaudiKernel/SmartIF.h"
-#include "GaudiKernel/EventContext.h"
-
-// Athena includes
-#include "AthenaKernel/ExtendedEventContext.h"
-#include "AthenaKernel/EventContextClid.h"
-#include "StoreGate/StoreGateSvc.h"
-#include "EventInfo/EventIncident.h"
-#include "EventInfo/EventInfo.h"
-#include "EventInfo/EventType.h"
-#include "xAODEventInfo/EventAuxInfo.h"
-#include "ByteStreamData/ByteStreamMetadata.h"
-#include "ByteStreamCnvSvcBase/IROBDataProviderSvc.h"
-#include "AthenaPoolUtilities/CondAttrListCollection.h"
-#include "CLIDSvc/CLASS_DEF.h"
-
-// omni redefines this macro, so we save it
-namespace {
-static std::string CMT_PACKAGE_VERSION = PACKAGE_VERSION;
-}
-
 // Trigger includes
 #include "TrigServices/HltEventLoopMgr.h"
-#include "TrigServices/TrigISHelper.h"
-#include "TrigServices/TrigHLTIssues.h"
 #include "TrigCOOLUpdateHelper.h"
+#include "TrigKernel/HltExceptions.h"
 #include "TrigSORFromPtreeHelper.h"
-#include "TrigConfInterfaces/IHLTConfigSvc.h"
-#include "TrigInterfaces/Incidents.h"
-#include "TrigMonitorBase/TrigLockedHist.h"
-#include "TrigKernel/HltAcceptFlag.h"
-#include "TrigKernel/HltResultStatusCode.h"
-#include "TrigKernel/HltExtraStatusCode.h"
-#include "TrigKernel/IHltTHistSvc.h"
 #include "TrigSteeringEvent/HLTResult.h"
+#include "TrigSteeringEvent/HLTResultMT.h"
+
+// Athena includes
+#include "AthenaKernel/EventContextClid.h"
+#include "ByteStreamCnvSvcBase/IROBDataProviderSvc.h"
+#include "ByteStreamData/ByteStreamMetadata.h"
+#include "EventInfo/EventInfo.h"
+#include "StoreGate/StoreGateSvc.h"
+#include "xAODEventInfo/EventInfo.h"
+#include "xAODEventInfo/EventAuxInfo.h"
 #include "TrigSteeringEvent/HLTExtraData.h"
-#include "TrigNavigation/TrigEDMSizes.h"
+
+// Gaudi includes
+#include "GaudiKernel/EventIDBase.h"
+#include "GaudiKernel/ConcurrencyFlags.h"
+#include "GaudiKernel/IAlgExecStateSvc.h"
+#include "GaudiKernel/IAlgManager.h"
+#include "GaudiKernel/IAlgorithm.h"
+#include "GaudiKernel/IAlgResourcePool.h"
+#include "GaudiKernel/IConversionSvc.h"
+#include "GaudiKernel/IEvtSelector.h"
+#include "GaudiKernel/IHiveWhiteBoard.h"
+#include "GaudiKernel/IJobOptionsSvc.h"
+#include "GaudiKernel/IProperty.h"
+#include "GaudiKernel/IScheduler.h"
+#include "GaudiKernel/ITHistSvc.h"
+#include "GaudiKernel/ThreadLocalContext.h"
 
 // TDAQ includes
-#include "ers/ers.h"
-#include "eformat/eformat.h"
-#include "eformat/write/ROBFragment.h"
-#include "TTCInfo/LumiBlock.h"
-#include "ddc/DdcFloatInfoNamed.h"
-#include "hltinterface/HLTInterface.h"
-#include "hltinterface/EventId.h"
-#include "hltinterface/HLTResult.h"
-#include "CTPfragment/CTPfragment.h"
-#include "CTPfragment/CTPExtraWordsFormat.h"
-#include "CTPfragment/Issue.h"
-
-// ROOT includes
-#include "TH1F.h"
-#include "TH2I.h"
-#include "TProfile.h"
-#include "TClass.h"
-
-// Other includes
-#include <set>
-#include <string>
-#include <algorithm>
-#include <ctime>
-#include <mutex>
-#include <sys/types.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <boost/property_tree/ptree.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/lexical_cast.hpp>
-
-#undef PACKAGE_VERSION      // use the CMT_PACKAGE_VERSION std::string instead
+#include "eformat/StreamTag.h"
+#include "hltinterface/DataCollector.h"
+#include "owl/time.h"
+
+// System includes
+#include <sstream>
 
 #define ST_WHERE "HltEventLoopMgr::" << __func__ << "(): "
 
 using namespace boost::property_tree;
-using std::string;
-using std::function;
-using std::begin;
-using std::end;
 using SOR = TrigSORFromPtreeHelper::SOR;
 
-namespace
-{
-  //=========================================================================
-  const eformat::helper::Status SW_UNCLASSIFIED(eformat::UNCLASSIFIED, 0),
-                                SW_FAIL(eformat::DATA_CORRUPTION, 0),
-                                SW_TRUNCATION(eformat::INTERNAL_OVERFLOW, 0);
-  constexpr unsigned 
-      INITIAL_ROB_SIZE_MARGIN = 4; /* margin for the rob size, to account for 
-                                      possible additional status words that may
-                                      still be unknonw */
-
-  //=========================================================================
-  constexpr std::array<uint32_t, 7> L1R_MANDATORY_ROBS =
-    {{
-      0x7300a8, 0x7300a9, 0x7300aa, 0x7300ab, // TDAQ_CALO_CLUSTER_PROC_ROI ROBs
-      0x7500ac, 0x7500ad,                     // TDAQ_CALO_JET_PROC_ROI ROBs
-      0x760001                                // TDAQ_MUON_CTP_INTERFACE ROB
-    }}; // default list of IDs of ROBs that must come in the L1R from the RoIB
-
-  //=========================================================================
-  constexpr std::array<uint32_t, 12> L1R_SKIP_ROB_CHECK =
-    {{
-      0x7300a8, 0x7300a9, 0x7300aa, 0x7300ab, // TDAQ_CALO_CLUSTER_PROC_ROI ROBs
-      0x7500ac, 0x7500ad,                     // TDAQ_CALO_JET_PROC_ROI ROBs
-      0x760001,                               // TDAQ_MUON_CTP_INTERFACE ROB
-      0x770001,                               // TDAQ_CTP ROB
-      0x910081, 0x910091, 0x910082, 0x910092  // TDAQ_CALO_TOPO_PROC ROBs
-    }}; //concrete IDs still unknown for TDAQ_FTK and TDAQ_CALO_FEAT_EXTRACT_ROI
-
-  //=========================================================================
-  constexpr std::array<eformat::SubDetector, 7> L1R_SKIP_SD_CHECK =
-    {{
-      eformat::TDAQ_CALO_CLUSTER_PROC_ROI,
-      eformat::TDAQ_CALO_JET_PROC_ROI,
-      eformat::TDAQ_HLT,
-      eformat::TDAQ_FTK,
-      eformat::TDAQ_CALO_TOPO_PROC,
-      eformat::TDAQ_CALO_DIGITAL_PROC,
-      eformat::TDAQ_CALO_FEAT_EXTRACT_ROI
-    }};
-
-  //=========================================================================
-  constexpr std::array<eformat::SubDetector, 8> L1R_BINS =
-    {{
-      eformat::TDAQ_CALO_CLUSTER_PROC_ROI,
-      eformat::TDAQ_CALO_JET_PROC_ROI,
-      eformat::TDAQ_MUON_CTP_INTERFACE,
-      eformat::TDAQ_CTP,
-      eformat::TDAQ_FTK,
-      eformat::TDAQ_CALO_TOPO_PROC,
-      eformat::TDAQ_CALO_DIGITAL_PROC,
-      eformat::TDAQ_CALO_FEAT_EXTRACT_ROI
-    }};
-
-  //=========================================================================
-  constexpr const char * UNEXPECTED_L1R_ROB_LABEL = "Unexpected_ROB";
-  constexpr const char * MISSING_L1R_CTP_LABEL = "Missing_CTP_Fragment";
-
-  //=========================================================================
-  std::mutex timeout_mutex; // To synchronize main and time out threads
-
-  //=========================================================================
-  bool skipEnabledCheck(eformat::SubDetector sd)
-  {
-    // Skip check for HLT Result ROBs (for DataScouting)
-    if (sd == eformat::TDAQ_HLT) return true;
-    
-    // Skip check for certain L1 input ROBs
-    return std::find(begin(L1R_SKIP_SD_CHECK),
-                     end(L1R_SKIP_SD_CHECK),
-                     sd) != end(L1R_SKIP_SD_CHECK);
-  }
-
-  //=========================================================================
-  bool skipEnabledCheck(uint32_t robid)
-  {
-    // Skip check for HLT Result ROBs (for DataScouting)
-    if (eformat::helper::SourceIdentifier(robid).subdetector_id() == eformat::TDAQ_HLT) return true;
-    
-    // Skip check for certain L1 input ROBs
-    return std::find(begin(L1R_SKIP_ROB_CHECK),
-                     end(L1R_SKIP_ROB_CHECK),
-                     robid) != end(L1R_SKIP_ROB_CHECK);
-  }
-
-  //=========================================================================
-  std::string
-  missingL1RobsMsg(const std::vector<uint32_t>& rob_ids)
-  {
-    std::ostringstream ost;
-    if(!rob_ids.empty())
-    {
-      ost << "L1 result ROBs missing: ";
-
-      ost << "0x" << std::hex << std::setfill('0') << std::setw(6);
-      std::copy(std::begin(rob_ids),
-                std::end(rob_ids) - 1, // leave one to avoid delimiter
-                std::ostream_iterator<uint32_t>{ost, ", 0x"});
-      ost << rob_ids.back() << "."; // append without delimiter
-    }
-
-    return ost.str();
-  }
-
-  //=========================================================================
-  void fillEdmHist(TProfile * hist, const std::string& colname,
-                   const HLT::TrigEDMSizes::EDMObjectInfo& info)
-  {
-    if(hist)
-      hist->Fill(colname.c_str(), static_cast<double>(info.words));
-  }
-
-  //=========================================================================
-  void addDebugStreamTag(hltinterface::HLTResult& hlt_result,
-                         const std::string& tagname)
-  {
-    hlt_result.stream_tag.emplace_back(tagname, eformat::DEBUG_TAG, false);
-  }
-
-  //=========================================================================
-  std::unique_ptr<eformat::write::ROBFragment>
-  initRob(uint16_t modid, uint32_t rn, uint32_t l1id, uint32_t bcid,
-          uint32_t l1tt, uint32_t dett, uint32_t * status_words)
-  {
-    using namespace eformat;
-    using write::ROBFragment;
-
-    auto src = helper::SourceIdentifier{TDAQ_HLT, modid}.code();
-    auto robp = std::unique_ptr<ROBFragment>{
-        new ROBFragment{src, rn, l1id, bcid, l1tt, dett, 0, 0, STATUS_FRONT}};
-
-    status_words[0] = SW_UNCLASSIFIED.code();
-    status_words[1] = hltonl::NORMAL_HLT_RESULT;
-    status_words[2] = hltonl::PSC_ERROR_UNCLASSIFIED;
-
-    robp->status(1, status_words);
-    robp->rod_status(1, status_words);
-
-    return robp;
-  }
-
-  //=========================================================================
-  // Class that resets a pointer upon destruction, locking given mutex
-  template <typename T, typename MUTEX>
-  class PtrResetter
-  {
-  public:
-    explicit PtrResetter(T*& ptr, MUTEX& mut)
-      : m_ptr{ptr}
-      , m_mut(mut) // cannot use uniform init due to gcc4.8 bug
-    {}
-    ~PtrResetter() // this is where the work happens
-    {
-      std::lock_guard<MUTEX>{m_mut};
-      m_ptr = nullptr;
-    }
-    PtrResetter(const PtrResetter&) = delete;
-    PtrResetter operator=(const PtrResetter&) = delete;
-    // no need to delete move ops explicitly in this case - not generated
-
-  private:
-    T*& m_ptr;
-    MUTEX& m_mut;
-  };
-}
-
-
-//=========================================================================
-// Standard Constructor
-//=========================================================================
-HltEventLoopMgr::HltEventLoopMgr(const std::string& nam,
-    ISvcLocator* svcLoc)
-: MinimalEventLoopMgr(nam, svcLoc),
-  m_incidentSvc ( "IncidentSvc",  nam ),
-  m_evtStore( "StoreGateSvc", nam ),
-  m_detectorStore( "DetectorStore", nam ),
-  m_inputMetaDataStore( "StoreGateSvc/InputMetaDataStore", nam ),
-  m_robDataProviderSvc( "ROBDataProviderSvc",nam ),
-  m_THistSvc( "THistSvc", nam ),
-  m_aess( "AlgExecStateSvc", nam),
-  m_isHelper( "TrigISHelper", this),
-  m_coolHelper( "TrigCOOLUpdateHelper", this),
-  m_sorTime_stamp(2,0),
+// =============================================================================
+// Standard constructor
+// =============================================================================
+HltEventLoopMgr::HltEventLoopMgr(const std::string& name, ISvcLocator* svcLoc)
+: base_class(name, svcLoc),
+  m_incidentSvc("IncidentSvc", name),
+  m_evtStore("StoreGateSvc", name),
+  m_detectorStore("DetectorStore", name),
+  m_inputMetaDataStore("StoreGateSvc/InputMetaDataStore", name),
+  m_robDataProviderSvc("ROBDataProviderSvc", name),
+  m_THistSvc("THistSvc", name),
+  m_evtSelector("EvtSel", name),
+  m_outputCnvSvc("OutputCnvSvc", name),
+  m_coolHelper("TrigCOOLUpdateHelper", this),
+  m_hltResultBuilder("HLT::ResultBuilderMT/ResultBuilder", this),
+  m_eventInfoCnvTool("xAODMaker::EventInfoCnvTool/EventInfoCnvTool", this),
   m_detector_mask(0xffffffff, 0xffffffff, 0, 0),
-  m_l1_hltPrescaleUpdateLB(0xffffffff),
-  m_histProp_Hlt_result_size(Gaudi::Histo1DDef("HltResultSize",0,500000,100)),
-  m_histProp_Hlt_result_size_physics(Gaudi::Histo1DDef("HltResultSize-(Stream (Main_physics))",0,500000,100)),
-  m_histProp_Hlt_result_size_express(Gaudi::Histo1DDef("HltResultSize-(Stream (express_express))",0,250000,100)),
-  m_histProp_Hlt_result_size_DataScouting(Gaudi::Histo1DDef("HltResultSize-(Streams (DataScouting_*_calibration))",0,125000,100)),
-  m_histProp_numStreamTags(Gaudi::Histo1DDef("NumberOfStreamTags",-.5,19.5,20)),
-  m_histProp_streamTagNames(Gaudi::Histo1DDef("StreamTagNames",-.5,.5,1)),
-  m_histProp_num_partial_eb_robs(Gaudi::Histo1DDef("NumberROBsPartialEB",-.5,199.5,200)),
-  m_histProp_Hlt_Edm_Sizes(Gaudi::Histo1DDef("HltEDMSizes",0.,10000.,100))
+  m_nevt(0),
+  m_threadPoolSize(-1),
+  m_evtSelContext(nullptr),
+  m_softTimeoutValue(10000),
+  m_runEventTimer(true)
 {
-  m_mandatoryL1ROBs.value() = {begin(L1R_MANDATORY_ROBS), end(L1R_MANDATORY_ROBS)};
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
 
-  // General properties for event loop managers
-  declareProperty("predefinedLumiBlock",      m_predefinedLumiBlock=0);
-  declareProperty("Lvl1CTPROBid",             m_lvl1CTPROBid=0x770001);
+  declareProperty("JobOptionsType",           m_jobOptionsType="NONE");
   declareProperty("ApplicationName",          m_applicationName="None");
   declareProperty("PartitionName",            m_partitionName="None");
-  declareProperty("setMagFieldFromPtree",     m_setMagFieldFromPtree=false);
   declareProperty("enabledROBs",              m_enabledROBs);
   declareProperty("enabledSubDetectors",      m_enabledSubDetectors);
-  declareProperty("MandatoryL1ROBs",          m_mandatoryL1ROBs, "List of mandatory ROB IDs coming from the RoIB (must come in L1R seed)");
-  declareProperty("HltEDMCollectionNames",    m_hltEdmCollectionNames, "Names of all HLT EDM Collections");
-  declareProperty("JobOptionsType",           m_jobOptionsType="NONE");
-  declareProperty("doMonitoring",             m_doMonitoring=true, "Produce framework monitoring histograms");
-  declareProperty("histHltResultSize",        m_histProp_Hlt_result_size, "Histogram for HLT result size in words (overall)");
-  declareProperty("histHltResultSizePhysics", m_histProp_Hlt_result_size_physics, "Histogram for HLT result size in words for physics stream ");
-  declareProperty("histHltResultSizeExpress", m_histProp_Hlt_result_size_express, "Histogram for HLT result size in words for express stream ");
-  declareProperty("histHltResultSizeDS",      m_histProp_Hlt_result_size_DataScouting, "Histogram for HLT result size in words for DataScouting stream ");
-  declareProperty("histNumberOfStreamTags",   m_histProp_numStreamTags, "Histogram with number of stream tags");
-  declareProperty("histStreamTagNames",       m_histProp_streamTagNames,"Histogram with stream tag names");  
-  declareProperty("histNumberROBsPartialEB",  m_histProp_num_partial_eb_robs, "Histogram with number of ROBs for PEB" );
-  declareProperty("histHltEdmSizes",          m_histProp_Hlt_Edm_Sizes, "Histogram with sizes of HLT EDM collections" );
-  declareProperty("ForceHltReject",           m_forceHltReject=false);
-  declareProperty("ForceHltAccept",           m_forceHltAccept=false);
-  declareProperty("HltResultName",            m_HltResultName="HLTResult_HLT");
-  declareProperty("HltDebugStreamName",       m_HltDebugStreamName ="HLTMissingData");
-  declareProperty("HltForcedStreamName",      m_HltForcedStreamName ="HLTEventAcceptForced");
+  declareProperty("EvtSel",                   m_evtSelector);
+  declareProperty("OutputCnvSvc",             m_outputCnvSvc);
   declareProperty("CoolUpdateTool",           m_coolHelper);
-  declareProperty("maxPrepareForRunSleepSec", m_prepareForRunSleep = 0, "Max number of seconds to sleep at the beginning of prepareForRun");
-  declareProperty("Lvl1CTPROBcheck",          m_lvl1CTPROBcheck=true);
-  declareProperty("WriteTruncatedHLTtoDebug", m_writeHltTruncationToDebug=true);
-  declareProperty("HltTruncationDebugStreamName",  m_HltTruncationDebugStreamName ="TruncatedHLTResult");
-  declareProperty("ExcludeFromHltTruncationDebugStream",  m_excludeFromHltTruncationDebugStream );
+  declareProperty("ResultBuilder",            m_hltResultBuilder);
+  declareProperty("EventInfoCnvTool",         m_eventInfoCnvTool);
+  declareProperty("SchedulerSvc",             m_schedulerName="AvalancheSchedulerSvc",
+                  "Name of the scheduler to be used");
+  declareProperty("WhiteboardSvc",            m_whiteboardName="EventDataSvc",
+                  "Name of the Whiteboard to be used");
+  declareProperty("TopAlg",                   m_topAlgNames={},
+                  "List of top level algorithms names");
+  declareProperty("xEventInfoWHKey",          m_xEventInfoWHKey="EventInfo");
+  declareProperty("HardTimeout",              m_hardTimeout=10*60*1000/*=10min*/,
+                  "Hard event processing timeout in milliseconds");
+  declareProperty("SoftTimeoutFraction",      m_softTimeoutFraction=0.8,
+                  "Fraction of the hard timeout to be set as the soft timeout");
+
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
 }
 
-//=========================================================================
-// Standard Destructor
-//=========================================================================
+// =============================================================================
+// Standard destructor
+// =============================================================================
 HltEventLoopMgr::~HltEventLoopMgr()
 {
 }
 
-//=========================================================================
-// implementation of IInterface: queryInterface
-//=========================================================================
-StatusCode HltEventLoopMgr::queryInterface(const InterfaceID& riid, void** ppvInterface)
-{
-  if(!ppvInterface)
-      return StatusCode::FAILURE;
-
-  if(ITrigEventLoopMgr::interfaceID().versionMatch(riid))
-    *ppvInterface = static_cast<ITrigEventLoopMgr*>(this);
-  else
-    return MinimalEventLoopMgr::queryInterface(riid, ppvInterface);
-
-  addRef();
-  return StatusCode::SUCCESS;
-}
-
-//=========================================================================
-// implementation of IService::sysInitalize
-//=========================================================================
-StatusCode HltEventLoopMgr::sysInitialize()
-{
-
-  // initialize the base class
-  StatusCode sc = MinimalEventLoopMgr::sysInitialize();
-  sc.setChecked();
-  return sc;
-}
-
-void HltEventLoopMgr::updateDFProps()
-{
-  ServiceHandle<IJobOptionsSvc> p_jobOptionsSvc("JobOptionsSvc", name());
-  if ((p_jobOptionsSvc.retrieve()).isFailure()) {
-    msgStream() << MSG::WARNING << "Could not find JobOptionsSvc to set "
-                << "DataFlow properties" << endmsg;
-  } else {
-    auto dfprops = p_jobOptionsSvc->getProperties("DataFlowConfig");
-
-    // Application name
-    auto pname = "DF_ApplicationName";
-    const auto * prop = Gaudi::Utils::getProperty(dfprops, pname);
-    if(prop && m_applicationName.assign(*prop)) {
-      msgStream() << MSG::DEBUG << " ---> Read from DataFlow configuration: "
-                  << m_applicationName << endmsg;
-    } else {
-      msgStream() << MSG::WARNING << "Could not set Property '" << pname
-                  << "' from DataFlow." << endmsg;
-    }
-
-    // Partition name
-    pname = "DF_PartitionName";
-    prop = Gaudi::Utils::getProperty(dfprops, pname);
-    if (prop && m_partitionName.assign(*prop)) {
-      msgStream() << MSG::DEBUG << " ---> Read from DataFlow configuration: "
-                  << m_partitionName << endmsg;
-    } else {
-      msgStream() << MSG::WARNING << "Could not set Property '" << pname
-                  << "' from DataFlow." << endmsg;
-    }
-
-    // get the list of enabled ROBs
-    pname = "DF_Enabled_ROB_IDs";
-    prop = Gaudi::Utils::getProperty(dfprops, pname);
-    if (prop && m_enabledROBs.assign(*prop)) {
-      msgStream() << MSG::DEBUG << " ---> Read from DataFlow configuration: "
-                  << m_enabledROBs.value().size() << " enabled ROB IDs."
-                  << endmsg;
-    } else {
-      // this is only info, because it is normal in athenaHLT
-      msgStream() << MSG::INFO << "Could not set Property '" << pname
-                  << "' from DataFlow." << endmsg;
-    }
-
-    // get the list of enabled Sub Detectors
-    pname = "DF_Enabled_SubDet_IDs";
-    prop = Gaudi::Utils::getProperty(dfprops, pname);
-    if (prop && m_enabledSubDetectors.assign(*prop)) {
-      msgStream() << MSG::DEBUG << " ---> Read from DataFlow configuration: "
-                  << m_enabledSubDetectors.value().size()
-                  << " enabled Sub Detector IDs." << endmsg;
-    } else {
-      // this is only info, because it is normal in athenaHLT
-      msgStream() << MSG::INFO << "Could not set Property '"
-                  << pname << "' from DataFlow." << endmsg;
-    }
-  }
-
-  p_jobOptionsSvc.release().ignore();
-}
-
-//=========================================================================
-// implementation of IService::initalize
-//=========================================================================
+// =============================================================================
+// Reimplementation of AthService::initalize (IStateful interface)
+// =============================================================================
 StatusCode HltEventLoopMgr::initialize()
 {
-  // initialize the base class
-  StatusCode sc = MinimalEventLoopMgr::initialize();
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
 
-  // leave this after initialization of base class, otherwise msgSvc is not correctly set up
-  //            -----
-  msgStream() << MSG::INFO << " ---> HltEventLoopMgr = " << name() << " initialize "
-      << " - package version " << CMT_PACKAGE_VERSION << endmsg ;
-  if (sc.isFailure()) {
-    msgStream() << MSG::ERROR << "Failed to initialize base class MinimalEventLoopMgr" << endmsg;
-    return sc;
-  }
+  ATH_MSG_INFO(" ---> HltEventLoopMgr = " << name() << " initialize - package version " << PACKAGE_VERSION);
 
+  //----------------------------------------------------------------------------
+  // Setup properties
+  //----------------------------------------------------------------------------
+
+  // read DataFlow configuration properties
   updateDFProps();
 
   // JobOptions type
-  SmartIF<IProperty> propMgr ( Gaudi::createApplicationMgr() );
-  if( propMgr.isValid() ) {
+  SmartIF<IProperty> propMgr = serviceLocator()->service<IProperty>("ApplicationMgr");
+  if (propMgr.isValid()) {
     try {
       if (m_jobOptionsType.assign( propMgr->getProperty("JobOptionsType") ))
-        msgStream() << MSG::DEBUG << " ---> Read from DataFlow configuration: " << m_jobOptionsType << endmsg;
+        ATH_MSG_DEBUG(" ---> Read from DataFlow configuration: " << m_jobOptionsType);
     }
     catch (...) {
-      msgStream() << MSG::WARNING << "Could not set Property '" << m_jobOptionsType.name() << "' from DataFlow." << endmsg;
+      ATH_MSG_WARNING("Could not set Property '" << m_jobOptionsType.name() << "' from DataFlow");
+    }
+
+    if ( m_topAlgNames.value().empty() ) {
+      if (setProperty(propMgr->getProperty("TopAlg")).isFailure()) {
+        ATH_MSG_WARNING("Could not set the TopAlg property from ApplicationMgr");
+      }
     }
   }
   else {
-    msgStream() << MSG::WARNING << "Error retrieving IProperty interface of ApplicationMgr" << endmsg;
+    ATH_MSG_WARNING("Error retrieving IProperty interface of ApplicationMgr" );
   }
 
-  // print properties
-  msgStream() << MSG::INFO << " ---> predefinedLumiBlock    = " << m_predefinedLumiBlock << endmsg ;
-  msgStream() << MSG::INFO << " ---> Lvl1 CTP ROB Id        = " << m_lvl1CTPROBid 
-      << " SourceID in hex = 0x" << MSG::hex << m_lvl1CTPROBid.value() << MSG::dec << endmsg ;
-  msgStream() << MSG::INFO << " ---> ApplicationName        = " << m_applicationName << endmsg ;
-  msgStream() << MSG::INFO << " ---> PartitionName          = " << m_partitionName << endmsg ;
-  msgStream() << MSG::INFO << " ---> JobOptionsType         = " << m_jobOptionsType << endmsg ;
-
-  msgStream() << MSG::INFO << " ---> Enabled ROBs: size = "
-              << m_enabledROBs.value().size();
-  if (m_enabledROBs.value().size() == 0)
-  {
-    msgStream() << MSG::INFO << ". No check will be performed ";
+  // get JobOptionsSvc to read the configuration of NumConcurrentEvents and NumThreads
+  ServiceHandle<IJobOptionsSvc> jobOptionsSvc("JobOptionsSvc", name());
+  if ((jobOptionsSvc.retrieve()).isFailure()) {
+    ATH_MSG_WARNING("Could not find JobOptionsSvc to read configuration");
   }
-  msgStream() << endmsg;
 
-  msgStream() << MSG::INFO << " ---> Enabled Sub Detectors: size = "
-              << m_enabledSubDetectors.value().size();
-  if (m_enabledSubDetectors.value().size() == 0)
-  {
-     msgStream() << ". No check will be performed " << endmsg;
-  }
-  msgStream() << endmsg;
-
-  msgStream() << MSG::INFO << " ---> Fill monitoring histograms             = " << m_doMonitoring << endmsg ;
-  msgStream() << MSG::INFO << " ---> Hist: histHltResultSize (overall)      = " << m_histProp_Hlt_result_size << endmsg ;
-  msgStream() << MSG::INFO << " ---> Hist: histHltResultSize (physics)      = " << m_histProp_Hlt_result_size_physics << endmsg ;
-  msgStream() << MSG::INFO << " ---> Hist: histHltResultSize (express)      = " << m_histProp_Hlt_result_size_express << endmsg ;
-  msgStream() << MSG::INFO << " ---> Hist: histHltResultSize (DataScouting) = " << m_histProp_Hlt_result_size_DataScouting << endmsg ;
-  msgStream() << MSG::INFO << " ---> Hist: histNumberOfStreamTags           = " << m_histProp_numStreamTags << endmsg ;
-  msgStream() << MSG::INFO << " ---> Hist: histStreamTagNames               = " << m_histProp_streamTagNames << endmsg ;
-  msgStream() << MSG::INFO << " ---> Hist: histNumberROBsPartialEB          = " << m_histProp_num_partial_eb_robs << endmsg ;
-  msgStream() << MSG::INFO << " ---> Hist: histHltEdmSizes                  = " << m_histProp_Hlt_Edm_Sizes << endmsg;
-  msgStream() << MSG::INFO << " ---> HLT EDM Collection Names               = " << m_hltEdmCollectionNames << endmsg;
-  msgStream() << MSG::INFO << " ---> HltResult SG key                       = " << m_HltResultName << endmsg ;
-  msgStream() << MSG::INFO << " ---> HLT debug stream name                  = " << m_HltDebugStreamName << endmsg ;
-  msgStream() << MSG::INFO << " ---> HLT stream for forced events           = " << m_HltForcedStreamName << endmsg ;
-  msgStream() << MSG::INFO << " ---> ForceHltReject                         = " << m_forceHltReject << endmsg ;
-  msgStream() << MSG::INFO << " ---> ForceHltAccept                         = " << m_forceHltAccept << endmsg;
-
-  if (m_forceHltReject.value()) {
-    msgStream() << MSG::INFO << " +------------------------------------------+ "  << endmsg ;
-    msgStream() << MSG::INFO << " | >>>   ForceHltReject is enabled !    <<< | "  << endmsg ;
-    msgStream() << MSG::INFO << " | It takes precedence over ForceHltAccept  | "  << endmsg ;
-    msgStream() << MSG::INFO << " +------------------------------------------+ "  << endmsg ;
+  // print properties
+  ATH_MSG_INFO(" ---> ApplicationName        = " << m_applicationName);
+  ATH_MSG_INFO(" ---> PartitionName          = " << m_partitionName);
+  ATH_MSG_INFO(" ---> JobOptionsType         = " << m_jobOptionsType);
+  ATH_MSG_INFO(" ---> HardTimeout            = " << m_hardTimeout);
+  ATH_MSG_INFO(" ---> SoftTimeoutFraction    = " << m_softTimeoutFraction);
+  if (jobOptionsSvc.isValid()) {
+    const Gaudi::Details::PropertyBase* prop = jobOptionsSvc->getClientProperty("EventDataSvc","NSlots");
+    if (prop)
+      ATH_MSG_INFO(" ---> NumConcurrentEvents    = " << *prop);
+    else
+      ATH_MSG_WARNING("Failed to retrieve the job property EventDataSvc.NSlots");
+    prop = jobOptionsSvc->getClientProperty("AvalancheSchedulerSvc","ThreadPoolSize");
+    if (prop)
+      ATH_MSG_INFO(" ---> NumThreads             = " << *prop);
+    else
+      ATH_MSG_WARNING("Failed to retrieve the job property AvalancheSchedulerSvc.ThreadPoolSize");
+  }
+  ATH_MSG_INFO(" ---> Enabled ROBs: size = " << m_enabledROBs.value().size()
+               << (m_enabledROBs.value().size()==0 ? ". No check will be performed" : " "));
+  ATH_MSG_INFO(" ---> Enabled Sub Detectors: size = " << m_enabledSubDetectors.value().size()
+               << (m_enabledSubDetectors.value().size()==0 ? ". No check will be performed" : " "));
+
+  //----------------------------------------------------------------------------
+  // Create and initialise the top level algorithms
+  //----------------------------------------------------------------------------
+  SmartIF<IAlgManager> algMgr = serviceLocator()->as<IAlgManager>();
+  if (!algMgr.isValid()) {
+    ATH_MSG_FATAL("Failed to retrieve AlgManager - cannot initialise top level algorithms");
+    return StatusCode::FAILURE;
   }
-
-  msgStream() << MSG::INFO << " ---> Write events with truncated HLT result to debug stream  = " << m_writeHltTruncationToDebug << endmsg;
-  msgStream() << MSG::INFO << " ---> Debug stream name for events with truncated HLT result  = " << m_HltTruncationDebugStreamName << endmsg;
-  msgStream() << MSG::INFO << " ---> Stream names of events with a truncated HLT result which will not be send to the debug stream  = " << m_excludeFromHltTruncationDebugStream << endmsg;
-
-  //-------------------------------------------------------------------------
-  // Setup the StoreGateSvc
-  //-------------------------------------------------------------------------
-  sc = m_evtStore.retrieve();
-  if(sc.isFailure())
-  {
-    msgStream() << MSG::FATAL << "Error retrieving StoreGateSvc "+m_evtStore << endmsg;
-    return sc;
+  std::vector<SmartIF<IAlgorithm>> topAlgList;
+  topAlgList.reserve(m_topAlgNames.value().size());
+  for (const auto& it : m_topAlgNames.value()) {
+    Gaudi::Utils::TypeNameString item{it};
+    std::string item_name = item.name();
+    SmartIF<IAlgorithm> alg = algMgr->algorithm(item_name, /*createIf=*/ false);
+    if (alg.isValid()) {
+      ATH_MSG_DEBUG("Top Algorithm " << item_name << " already exists");
+    }
+    else {
+      ATH_MSG_DEBUG("Creating Top Algorithm " << item.type() << " with name " << item_name);
+      IAlgorithm* ialg = nullptr;
+      ATH_CHECK(algMgr->createAlgorithm(item.type(), item_name, ialg));
+      alg = ialg; // manage reference counting
+    }
+    m_topAlgList.push_back(alg);
   }
 
-  //-------------------------------------------------------------------------
-  // Setup the DetectorStore
-  //-------------------------------------------------------------------------
-  sc = m_detectorStore.retrieve();
-  if(sc.isFailure())
-  {
-    msgStream() << MSG::FATAL << "Error retrieving DetectorStore "+m_detectorStore << endmsg;
-    return sc;
+  for (auto& ita : m_topAlgList) {
+    ATH_CHECK(ita->sysInitialize());
   }
 
-  //-------------------------------------------------------------------------
-  // Setup the InputMetaDataStore
-  //-------------------------------------------------------------------------
-  sc = m_inputMetaDataStore.retrieve();
-  if(sc.isFailure())
-  {
-    msgStream() << MSG::FATAL << "Error retrieving InputMetaDataStore"+m_inputMetaDataStore << endmsg;
-    return sc;
+  //----------------------------------------------------------------------------
+  // Setup stuff for hive - taken from AthenaHiveEventLoopMgr
+  //----------------------------------------------------------------------------
+  m_whiteboard = serviceLocator()->service(m_whiteboardName);
+  if( !m_whiteboard.isValid() )  {
+    ATH_MSG_FATAL("Error retrieving " << m_whiteboardName << " interface IHiveWhiteBoard");
+    return StatusCode::FAILURE;
   }
+  ATH_MSG_DEBUG("Initialised " << m_whiteboardName << " interface IHiveWhiteBoard");
 
-  //--------------------------------------------------------------------------
-  // Setup the IncidentSvc
-  //--------------------------------------------------------------------------
-  sc = m_incidentSvc.retrieve();
-  if(sc.isFailure())
-  {
-    msgStream() << MSG::FATAL << "Error retrieving IncidentSvc "+m_incidentSvc << endmsg;
-    return sc;
+  ATH_MSG_DEBUG("Commented out scheduler initialisation was here, now it's moved to hltUpdateAfterFork");
+  /*
+  m_schedulerSvc = serviceLocator()->service(m_schedulerName);
+  if ( !m_schedulerSvc.isValid()){
+    ATH_MSG_FATAL("Error retrieving " << m_schedulerName << " interface ISchedulerSvc");
+    return StatusCode::FAILURE;
   }
-
-  //--------------------------------------------------------------------------
-  // Setup the ROBDataProviderSvc 
-  //--------------------------------------------------------------------------
-  sc = m_robDataProviderSvc.retrieve();
-  if(sc.isFailure())
-  {
-    msgStream() << MSG::FATAL << "Error retrieving ROBDataProviderSvc "+m_robDataProviderSvc << endmsg;
-    return sc;
+  ATH_MSG_DEBUG("initialised " << m_schedulerName << " interface ISchedulerSvc");
+  */
+  m_algResourcePool = serviceLocator()->service("AlgResourcePool");
+  if( !m_algResourcePool.isValid() ) {
+    ATH_MSG_FATAL("Error retrieving AlgResourcePool");
+    return StatusCode::FAILURE;
   }
+  ATH_MSG_DEBUG("initialised AlgResourcePool");
 
-  //--------------------------------------------------------------------------
-  // Setup the Histogram Service
-  //--------------------------------------------------------------------------
-  sc = m_THistSvc.retrieve();
-  if(sc.isFailure())
-  {
-    msgStream() << MSG::FATAL << "Error retrieving THistSvc "+m_THistSvc << endmsg;
-    return sc;
+  m_aess = serviceLocator()->service("AlgExecStateSvc");
+  if( !m_aess.isValid() ) {
+    ATH_MSG_FATAL("Error retrieving AlgExecStateSvc");
+    return StatusCode::FAILURE;
   }
+  ATH_MSG_DEBUG("initialised AlgExecStateSvc");
 
-  ATH_CHECK(m_aess.retrieve());
 
-  //--------------------------------------------------------------------------
-  // Setup the TrigISHelper
-  //--------------------------------------------------------------------------
-  sc = m_isHelper.retrieve();
-  if(sc.isFailure())
-  {
-    msgStream() << MSG::FATAL << "Error retrieving TrigISHelper "+m_isHelper << endmsg;
-    return sc;
-  }
-  sc = m_isHelper->setProperty(m_partitionName);
-  if(sc.isFailure())
-  {
-    msgStream() << MSG::FATAL << "Error setting " << m_partitionName.name()
-                    << " of " << m_isHelper << endmsg;
-    return sc;
-  }
+  //----------------------------------------------------------------------------
+  // Setup the IncidentSvc
+  //----------------------------------------------------------------------------
+  ATH_CHECK(m_incidentSvc.retrieve());
 
-  //--------------------------------------------------------------------------
-  // COOL helper
-  //--------------------------------------------------------------------------
-  if (m_coolHelper.retrieve().isFailure()) {
-    msgStream() << MSG::FATAL << "Error retrieving" << m_coolHelper << endmsg;
-    return StatusCode::FAILURE;
-  }
+  //----------------------------------------------------------------------------
+  // Setup the StoreGateSvc
+  //----------------------------------------------------------------------------
+  ATH_CHECK(m_evtStore.retrieve());
 
-  //--------------------------------------------------------------------------
-  // Setup optional services/tools
-  //--------------------------------------------------------------------------
-  if (service("AlgContextSvc", m_algContextSvc, /*createIf=*/ false).isFailure()) {
-    m_algContextSvc = 0;
-    msgStream() << MSG::DEBUG << "No AlgContextSvc available" << endmsg;
-  }
+  //----------------------------------------------------------------------------
+  // Setup the DetectorStore
+  //----------------------------------------------------------------------------
+  ATH_CHECK(m_detectorStore.retrieve());
 
-  // The remainder of this method used to be in the L2/EF specialization
+  //----------------------------------------------------------------------------
+  // Setup the InputMetaDataStore
+  //----------------------------------------------------------------------------
+  ATH_CHECK(m_inputMetaDataStore.retrieve());
 
-  // fill CTP ROB id vector
-  m_ctpRobIdVec.clear();
-  if (m_lvl1CTPROBid.value() != 0) {
-    m_ctpRobIdVec.push_back( m_lvl1CTPROBid.value() );
-  }
+  //----------------------------------------------------------------------------
+  // Setup the ROBDataProviderSvc
+  //----------------------------------------------------------------------------
+  ATH_CHECK(m_robDataProviderSvc.retrieve());
 
-  // print properties
-  msgStream() << MSG::INFO << " ---> HltEventLoopMgr            = " << name() << " special properties <--- " << endmsg ;
-  msgStream() << MSG::INFO << " ---> Lvl1 CTP ROB Id vec.        = 0x" << MSG::hex << m_ctpRobIdVec[0] << MSG::dec
-      << " size of vector = " << m_ctpRobIdVec.size() << endmsg ;
-  msgStream() << MSG::INFO << " ---> Check for invalid CTP ROBs  = " << m_lvl1CTPROBcheck << endmsg ;
-
-//-------------------------------------------------------------------------
-// Reset counters
-//-------------------------------------------------------------------------
-  m_total_evt                         = 0;
-  m_failed_evt                        = 0;
-  m_invalid_lvl1_result               = 0;
-  m_invalid_hlt_result                = 0;
-  m_truncated_hlt_result              = 0;
-  m_truncated_hlt_result_to_debug     = 0;
-  m_truncated_hlt_result_not_to_debug = 0;
-
-//--------------------------------------------------------------------------
-// Setup the HLT Histogram Service when configured
-//--------------------------------------------------------------------------
+  //----------------------------------------------------------------------------
+  // Setup the Histogram Service
+  //----------------------------------------------------------------------------
+  ATH_CHECK(m_THistSvc.retrieve());
+
+  //----------------------------------------------------------------------------
+  // Setup the Event Selector
+  //----------------------------------------------------------------------------
+  ATH_CHECK(m_evtSelector.retrieve());
+  ATH_CHECK(m_evtSelector->createContext(m_evtSelContext));
+
+  //----------------------------------------------------------------------------
+  // Setup the Output Conversion Service
+  //----------------------------------------------------------------------------
+  ATH_CHECK(m_outputCnvSvc.retrieve());
+
+  //----------------------------------------------------------------------------
+  // Setup the COOL helper
+  //----------------------------------------------------------------------------
+  ATH_CHECK(m_coolHelper.retrieve());
+
+  //----------------------------------------------------------------------------
+  // Setup the HLT result builder
+  //----------------------------------------------------------------------------
+  ATH_CHECK(m_hltResultBuilder.retrieve());
+
+  //----------------------------------------------------------------------------
+  // Setup the EventInfo conversion tool and WriteHandleKey
+  //----------------------------------------------------------------------------
+  ATH_CHECK(m_eventInfoCnvTool.retrieve());
+  ATH_CHECK(m_xEventInfoWHKey.initialize());
+
+  //----------------------------------------------------------------------------
+  // Setup the HLT Histogram Service when configured
+  //----------------------------------------------------------------------------
   if ( &*m_THistSvc ) {
     m_hltTHistSvc = SmartIF<IHltTHistSvc>( &*m_THistSvc );
-    if (m_hltTHistSvc.isValid()) {
-      msgStream() << MSG::INFO << "A THistSvc implementing the HLT interface IHltTHistSvc was found."
-    << endmsg;
-    } else {
-      msgStream() << MSG::INFO << "No THistSvc implementing the HLT interface IHltTHistSvc was found."
-    << endmsg;
-    }
+    if (m_hltTHistSvc.isValid())
+      ATH_MSG_INFO("A THistSvc implementing the HLT interface IHltTHistSvc was found");
+    else
+      ATH_MSG_INFO("No THistSvc implementing the HLT interface IHltTHistSvc was found");
   }
 
-//--------------------------------------------------------------------------
-// Setup the HLT ROB Data Provider Service when configured
-//--------------------------------------------------------------------------
+  //----------------------------------------------------------------------------
+  // Setup the HLT ROB Data Provider Service when configured
+  //----------------------------------------------------------------------------
   if ( &*m_robDataProviderSvc ) {
     m_hltROBDataProviderSvc = SmartIF<ITrigROBDataProviderSvc>( &*m_robDataProviderSvc );
-    if (m_hltROBDataProviderSvc.isValid()) {
-      msgStream() << MSG::INFO << "A ROBDataProviderSvc implementing the HLT interface ITrigROBDataProviderSvc was found."
-    << endmsg;
-    } else {
-      msgStream() << MSG::INFO << "No ROBDataProviderSvc implementing the HLT interface ITrigROBDataProviderSvc was found."
-    << endmsg;
-    }
+    if (m_hltROBDataProviderSvc.isValid())
+      ATH_MSG_INFO("A ROBDataProviderSvc implementing the HLT interface ITrigROBDataProviderSvc was found");
+    else
+      ATH_MSG_INFO("No ROBDataProviderSvc implementing the HLT interface ITrigROBDataProviderSvc was found");
   }
 
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
   return StatusCode::SUCCESS;
 }
 
-//=========================================================================
-// implementation of IService::sysFinalize
-//=========================================================================
-StatusCode HltEventLoopMgr::sysFinalize()
-{
-  // initialize the base class
-  StatusCode sc = MinimalEventLoopMgr::sysFinalize();
-  sc.setChecked();
-  return sc;
-}
-
-//=========================================================================
-// implementation of IService::finalize
-//=========================================================================
-StatusCode HltEventLoopMgr::finalize()
-{
-  MsgStream log(msgSvc(), name());
-  log << MSG::INFO << " ---> HltEventLoopMgr = " << name() << " finalize " << endmsg;
-  log << MSG::INFO << " Total number of events processed :                                     " << m_total_evt << endmsg;
-  log << MSG::INFO << "    Events with error in event processing                               " << m_failed_evt << endmsg;
-  log << MSG::INFO << "    Events with invalid Lvl1 Result                                     " << m_invalid_lvl1_result << endmsg;
-  log << MSG::INFO << "    Events with invalid Hlt Result                                      " << m_invalid_hlt_result << endmsg;
-  log << MSG::INFO << "    Events with truncated Hlt Result payload                            " << m_truncated_hlt_result << endmsg;   
-  log << MSG::INFO << "    Events with truncated Hlt Result payload (send to debug stream)     " << m_truncated_hlt_result_to_debug << endmsg;   
-  log << MSG::INFO << "    Events with truncated Hlt Result payload (not send to debug stream) " << m_truncated_hlt_result_not_to_debug << endmsg;   
-
-  // Need to release now. Automatic release in destructor is too late since services are already gone.
-  m_hltTHistSvc.reset();
-  m_hltROBDataProviderSvc.reset();
-
-  StatusCode sc = MinimalEventLoopMgr::finalize();
-  if (sc.isFailure()) {
-    msgStream() << MSG::ERROR << "Error in MinimalEventLoopMgr Finalize" << endmsg;
-  }
-
-
-  // Release all interfaces
-  m_incidentSvc.release().ignore();
-  m_robDataProviderSvc.release().ignore();
-  m_evtStore.release().ignore();
-  m_detectorStore.release().ignore();
-  m_inputMetaDataStore.release().ignore();
-  m_THistSvc.release().ignore();
-  m_isHelper.release().ignore();
-
-  return sc;
-}
-
-//=========================================================================
-// implementation of IService::sysReinitialize
-//=========================================================================
-StatusCode HltEventLoopMgr::sysReinitialize()
+// =============================================================================
+// Reimplementation of AthService::start (IStateful interface)
+// =============================================================================
+StatusCode HltEventLoopMgr::start()
 {
-  // initialize the base class
-  StatusCode sc = MinimalEventLoopMgr::sysReinitialize();
-  sc.setChecked();
-
-  return sc;
-}
+  ATH_CHECK(AthService::start());
 
-//=========================================================================
-// implementation of IService::reinitialize
-//=========================================================================
-StatusCode HltEventLoopMgr::reinitialize()
-{
-  MsgStream log(msgSvc(), name());
-  log << MSG::INFO << " ---> HltEventLoopMgr = " << name() << " reinitialize " << endmsg;
-
-//-------------------------------------------------------------------------
-// Reset counters
-//-------------------------------------------------------------------------
-  m_total_evt                         = 0;
-  m_failed_evt                        = 0;
-  m_invalid_lvl1_result               = 0;
-  m_invalid_hlt_result                = 0;
-  m_truncated_hlt_result              = 0;
-  m_truncated_hlt_result_to_debug     = 0;
-  m_truncated_hlt_result_not_to_debug = 0;
-
-  StatusCode sc = MinimalEventLoopMgr::reinitialize();
-  if (sc.isFailure()) {
-    msgStream() << MSG::ERROR << "Error in MinimalEventLoopMgr Reinitialize" << endmsg;
+  // start top level algorithms
+  for (auto& ita : m_topAlgList) {
+    ATH_CHECK(ita->sysStart());
   }
 
-  return sc;
-}
-
-StatusCode HltEventLoopMgr::executeAlgorithms()
-{
-  // Reset all algorithms
-  m_aess->reset(m_eventContext);
-
-  // Call the execute() method of all top algorithms
-  StatusCode sc;
-  for(auto alg : m_topAlgList) {
-    sc = alg->sysExecute(m_eventContext);
-    if(sc.isFailure()) {
-      msgStream() << MSG::ERROR << "Execution of algorithm " << alg->name()
-                  << " failed" << endmsg;
-      return sc;
-    }
-  }
   return StatusCode::SUCCESS;
 }
 
-
-//=========================================================================
-// implementation of IEventProcessor::executeEvent(void* par) ---> for "online" running
-//=========================================================================
-StatusCode HltEventLoopMgr::executeEvent(void* par)
-{
-  StatusCode  sc;
-  if (msgLevel() <= MSG::DEBUG) {  
-    msgStream() << MSG::DEBUG << " ---> HltEventLoopMgr = " << name()
-		    << " executeEvent(par): par = 0x" << MSG::hex << par << MSG::dec << endmsg;
-  }
-
-  {
-    std::lock_guard<std::mutex>{timeout_mutex};
-
-    resetTimeout(Athena::Timeout::instance());
-    sc = m_evtStore->retrieve(m_currentEvent);
-  }
-
-  if( sc.isFailure() ) {
-    msgStream() << MSG::ERROR << "Expected an EventInfo object." << endmsg;
-    return StatusCode::FAILURE;
-  } else {
-    const auto eventrn = m_currentEvent->event_ID()->run_number();
-    if ( (m_currentRun != eventrn))
-      msgStream() << (m_currentRun ? MSG::WARNING : MSG::DEBUG)
-                  << "Run number changed from " << m_currentRun << " to "
-                  << eventrn << " Complete EventID   = "
-                  << *(m_currentEvent->event_ID()) << endmsg;
-  }
-  
-  //-----------------------------------------------------------------------
-  // Create EventContext
-  //-----------------------------------------------------------------------
-  ATH_CHECK(installEventContext(m_currentEvent, m_currentRun));
-
-  //-----------------------------------------------------------------------
-  // obtain the HLT conditions update counters from the CTP fragment
-  //-----------------------------------------------------------------------
-  std::vector<uint32_t> l1_hltCounters(1,0);    // HLT counters from CTP fragment
-  std::vector<uint32_t> l1_extraPayload;        // extra paylaod from CTP fragment
-
-  // find the CTP ROB and get the HLT conditions update counters
-  bool b_invalidCTPRob = false;
-  std::vector<uint32_t> ctpRobIdVec(1,m_lvl1CTPROBid.value());
-  std::vector<const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment*> ctpRobFragmentVec;
-  m_robDataProviderSvc->getROBData(ctpRobIdVec,ctpRobFragmentVec);
-  if( ctpRobFragmentVec.size() == 1 ) {
-    try {
-      // get the HLT Counter
-      l1_hltCounters[0] = CTPfragment::hltCounter( ctpRobFragmentVec[0] );
-      l1_extraPayload = CTPfragment::extraPayloadWords( ctpRobFragmentVec[0] );
-    }
-    catch (CTPfragment::NullFragmentPointer& ex) {
-      b_invalidCTPRob=true;
-      msgStream() << MSG::ERROR << ex.what() << endmsg;
-    }
-    catch (CTPfragment::Inconsistency& ex) {
-      b_invalidCTPRob=true;
-      msgStream() << MSG::ERROR << ex.what() << endmsg;
-    }
-    catch (CTPfragment::TimeOutOfRange& ex) {
-      b_invalidCTPRob=true;
-      msgStream() << MSG::ERROR << ex.what() << endmsg;
-    }
-    catch (CTPfragment::TriggerWordsOutOfRange& ex) {
-      b_invalidCTPRob=true;
-      msgStream() << MSG::ERROR << ex.what() << endmsg;
-    }
-    catch (CTPfragment::GenericIssue& ex) {
-      b_invalidCTPRob=true;
-      msgStream() << MSG::ERROR << ex.what() << endmsg;
-    }
-    catch (eformat::Issue& ex) {
-      std::string issue_msg = std::string("Uncaught eformat issue:    ")+std::string(ex.what());
-      b_invalidCTPRob=true;
-      msgStream() << MSG::ERROR << issue_msg << endmsg;
-    }
-    catch (ers::Issue& ex) {
-      std::string issue_msg = std::string("Uncaught ERS issue:        ")+std::string(ex.what());
-      b_invalidCTPRob=true;
-      msgStream() << MSG::ERROR << issue_msg << endmsg;   
-    }
-    catch (std::exception& ex) {
-      std::string issue_msg = std::string("Uncaught std exception:    ")+std::string(ex.what());
-      b_invalidCTPRob=true;
-      msgStream() << MSG::ERROR << issue_msg << endmsg;     
-    }
-    catch (...) {
-      b_invalidCTPRob=true;
-      msgStream() << MSG::ERROR << "Uncaught unknown exception" << endmsg;
-    }
-  } else {
-    // no valid CTP fragment found
-    std::string issue_msg = std::string("No valid CTP fragment found.  ") ;
-    b_invalidCTPRob=true;
-    msgStream() << MSG::ERROR << issue_msg << endmsg;     
-  }
-
-  //-----------------------------------------------------------------------
-  // create an empty HLT Result Object and register it in StoreGate
-  // (if this fails, steering will try to create a HLT result object)
-  //-----------------------------------------------------------------------
-  auto pHltResult = new HLT::HLTResult;
-  pHltResult->setLvl1Id(m_currentEvent->event_ID()->event_number());
-  HLT::HLTExtraData& extraData = pHltResult->getExtraData();
-  extraData.appName = applicationName();
-  extraData.statusCode |= hltonl::HLT_PRESCALE_UPDATE;  // OK
-
-  // Record it in StoreGate (object can be modified)
-  sc = m_evtStore->record(pHltResult, m_HltResultName, true);
-  if(sc.isFailure()) {
-    msgStream() << MSG::ERROR << "Error declaring HLT Result object in SG" << endmsg;
-  }
-
-  //-----------------------------------------------------------------------
-  // Decode CTP extra payload words
-  //-----------------------------------------------------------------------
-  CTPfragment::ExtraPayload ctp_payload;
-  try {
-    ctp_payload = CTPfragment::ExtraPayload(l1_extraPayload);
-  }
-  catch (CTPfragment::ExtraPayloadTooLong& ex) {
-    b_invalidCTPRob=true;
-    msgStream() << MSG::ERROR << "Invalid CTP fragment. Exception = " << ex.what() << endmsg;
-  }
-
-  if ( msgLevel() <= MSG::DEBUG ) {
-    msgStream() << MSG::DEBUG << "CTP extra payload (" << l1_extraPayload.size() << " words): ";
-    for (std::size_t i=0; i<l1_extraPayload.size(); ++i) msgStream() << " " << l1_extraPayload[i];
-
-    msgStream() << ctp_payload << endmsg;
-  }
-
-  // Schedule COOL updates
-  m_coolHelper->setFolderUpdates(ctp_payload.getFolderUpdates());
-
-  //-----------------------------------------------------------------------
-  // Check if an HLT conditions update is required
-  //-----------------------------------------------------------------------
-  if (!b_invalidCTPRob) {
-    sc = checkHltPrescaleUpdate(l1_hltCounters);
-    if(sc.isFailure()) {
-      std::vector<uint32_t>& vExtraData = pHltResult->getExtras();
-      // set the HLT PSK flag to 0 to indicate error
-      vExtraData[vExtraData.size()-2] = 0;       // one word for prescale counter (=1 ok, =0 error)
-      msgStream() << MSG::FATAL << "HLT Conditions update failed" << endmsg;
-      throw ers::HLTAbort(ERS_HERE, name()+": HLT Conditions update failed");
-    }
-  }
-
-  // Fire BeginEvent "Incident"
-  m_incidentSvc->fireIncident(EventIncident(*m_currentEvent, name(),"BeginEvent"));
-
-  //-----------------------------------------------------------------------
-  // COOL updates for LB changes
-  //-----------------------------------------------------------------------
-  if ( m_currentLB != m_currentEvent->event_ID()->lumi_block() ) {  // LB change
-    m_currentLB = m_currentEvent->event_ID()->lumi_block();
-
-    if ( m_coolHelper->hltCoolUpdate(m_currentLB, m_currentRun,
-                                     m_sorTime_stamp[0], m_sorTime_stamp[1]).isFailure() ) {
-      msgStream() << MSG::FATAL << "COOL update failed. Aborting." << endmsg;
-      throw ers::HLTAbort(ERS_HERE, name()+": Failure during COOL update");
-    }
-  }
-
-  // Execute Algorithms
-  bool eventFailed = false;
-  try {
-    sc = executeAlgorithms();
-  }
-  catch ( const std::exception& e ) {
-    msgStream() << MSG::ERROR << "Caught a standard exception "
-                << e.what() << endmsg;
-    sc = StatusCode::FAILURE;
-  }
-  catch (...) {
-    msgStream() << MSG::ERROR << "Unknown exception" << endmsg;
-    sc = StatusCode::FAILURE;
-  }
-
-  if (sc.isSuccess()) {
-    // Call the execute() method of all output streams
-    for (auto o : m_outStreamList ) {
-      sc = o->sysExecute(m_eventContext);
-      if(sc.isFailure())  {
-        msgStream() << MSG::WARNING << "Execution of output stream " << o->name() << " failed" << endmsg;
-        eventFailed = true;
-      }
-    }
-  }
-  else {
-    eventFailed = true;
-  }     
-
-  // Fire EndEvent "Incident"
-  m_incidentSvc->fireIncident(EventIncident(*m_currentEvent, name(),"EndEvent"));
-
-  return eventFailed ? StatusCode::FAILURE : StatusCode::SUCCESS;
-}
-
-
-//=========================================================================
-// prepare for run step
-//=========================================================================
-StatusCode HltEventLoopMgr::prepareForRun(const ptree & pt)
-{
-  try
-  {
-    
-    (void)TClass::GetClass("vector<unsigned short>"); // preload to overcome an issue with dangling references in serialization
-    (void)TClass::GetClass("vector<unsigned long>");
-
-    const SOR * sor;
-    if(internalPrepareResets().isFailure() || // do the necessary resets and
-       !(sor = processRunParams(pt))) // update SOR in det store and get it back
-      return StatusCode::FAILURE;
-
-    auto & soral = getSorAttrList(sor);
-    updInternal(soral);     // update internally kept info
-    updMetadaStore(soral);  // update metadata store
-
-    const EventInfo * evinfo;
-    if(updMagField(pt).isFailure() ||     // update mag field when appropriate
-       updHLTConfigSvc().isFailure() ||   // update config svc when appropriate
-       resetCoolValidity().isFailure() || // reset selected proxies/IOV folders
-       prepXAODEventInfo().isFailure() || // update xAOD event data in SG
-       !(evinfo = prepEventInfo()))       // update old event data in SG
-      return StatusCode::FAILURE;
-
-    bookAllHistograms();
-
-    if(prepareAlgs(*evinfo).isSuccess())
-      return StatusCode::SUCCESS;
-  }
-  catch(const ptree_bad_path & e)
-  {
-    msgStream() << MSG::ERROR << ST_WHERE
-                << "Bad ptree path: \""
-                << e.path<ptree::path_type>().dump() << "\" - " << e.what()
-                << endmsg;
-  }
-  catch(const ptree_bad_data & e)
-  {
-    msgStream() << MSG::ERROR << ST_WHERE
-                << "Bad ptree data: \""
-                << e.data<ptree::data_type>() << "\" - " << e.what() << endmsg;
-  }
-  catch(const std::runtime_error& e)
-  {
-    msgStream() << MSG::ERROR << ST_WHERE
-                << "Runtime error: " << e.what() << endmsg;
-  }
-
-  return StatusCode::FAILURE;
-}
-
-StatusCode HltEventLoopMgr::installEventContext(const EventInfo* pEvent, EventID::number_type run)
-{
-  if (pEvent) m_eventContext.setEventID( *((EventIDBase*) pEvent->event_ID()) );
-  m_eventContext.set(m_total_evt ,0);
-
-  m_eventContext.setExtension( Atlas::ExtendedEventContext( m_evtStore->hiveProxyDict(), run) );
-  Gaudi::Hive::setCurrentContext( m_eventContext );
-
-  m_aess->reset(m_eventContext);
-  ATH_CHECK(m_evtStore->record(std::make_unique<EventContext> (m_eventContext), "EventContext"));
-
-  return StatusCode::SUCCESS;
-}
-
-
-//=========================================================================
-// allow for updates after forking the workers and issue an incident
-// to inform the clients
-//=========================================================================
-StatusCode HltEventLoopMgr::hltUpdateAfterFork(const ptree & pt)
-{
-  updateDFProps();
-
-  //-----------------------------------------------------------------------
-  // Fire "UpdateAfterFork" "Incident"
-  //-----------------------------------------------------------------------
-  int worker_id  = atoi( (pt.get_child("workerId").data()).c_str() );
-  int process_id = getpid();
-  m_incidentSvc->fireIncident(HLT::Incidents::UpdateAfterFork(worker_id,process_id,name()));
-
-  readyMsg(); // The event processing will start now
-
-  return StatusCode::SUCCESS;
-}
-
-//=========================================================================
-// Hlt: process one event/RoI  ---> for "online" running
-//=========================================================================
-StatusCode HltEventLoopMgr::processRoIs (
-            const std::vector<eformat::ROBFragment<const uint32_t*>>& l1_result,
-            hltinterface::HLTResult& hlt_result,
-            const hltinterface::EventId& evId)
-{
-  PtrResetter<const EventInfo, std::mutex> currentEventResetter{m_currentEvent,
-                                                                timeout_mutex};
-  StatusCode sc;
-
-  //-----------------------------------------------------------------------
-  // increase event counter
-  //-----------------------------------------------------------------------
-  m_total_evt++;
-
-  if ( msgLevel() <= MSG::DEBUG ) {
-    msgStream() << MSG::DEBUG << " " << endmsg;
-    msgStream() << MSG::DEBUG << " +------------+" << endmsg;
-    msgStream() << MSG::DEBUG << " | processRoI | for " << name()
-                << " and event number = " << m_total_evt  << " called."
-                << endmsg;
-    msgStream() << MSG::DEBUG << " +------------+" << endmsg;
-  }
-
-  //-----------------------------------------------------------------------
-  // If HLT THistSvc flush N-tuple buffer
-  //-----------------------------------------------------------------------
-  if ( m_hltTHistSvc.isValid() ) {
-    (m_hltTHistSvc->send()).ignore() ;
-    if ( msgLevel() <= MSG::DEBUG ) {
-      msgStream() << MSG::DEBUG << " ---> THistSvc->send(): m_hltTHistSvc = "
-                  << m_hltTHistSvc << endmsg;
-    }
-  }
-
-  //-----------------------------------------------------------------------
-  // reset event qualifiers
-  //-----------------------------------------------------------------------
-  m_lvl1id               = 0; // Level-1 ID=event no., 32 bit unsigned
-  m_run_no               = 0; // run number,           32 bit unsigned
-  m_bunch_crossing_id    = 0; // bunch crossing ID,    32 bit unsigned
-  m_l1_Status_Element    = 0;
-  m_l1_Trigger_Type      = 0;
-  m_l1_detev_type        = 0;
-  m_time_stamp           = 0; // time stamp - posix time in seconds from 1970,   32 bit unsigned
-  m_time_stamp_ns_offset = 0; // time stamp ns - ns time offset for time_stamp,  32 bit unsigned
-  m_lumi_block           = 0; // luminosity block identifier,                    32 bit unsigned
-  m_l1_Trigger_Info.assign(16,0);  // triggerInfo
-
-  // clear hlt_result structure
-  // -------------------------
-  hlt_result.trigger_info.clear();
-  hlt_result.stream_tag.clear();
-  hlt_result.psc_errors.clear();
-  (*hlt_result.fragment_pointer) = 0;
-
-  //-----------------------------------------------------------------------
-  // Check received Lvl1 result (Integrity is checked by HLTPU)
-  // get basic event parameters
-  // Store LVL1 Result in ROBDataProviderSvc cache
-  // Get extended information from the CTP ROB
-  //-----------------------------------------------------------------------
-  if( l1_result.size() == 0 ) {   // no Lvl1 result robs
-    m_invalid_lvl1_result++;
-
-    failedEvent(hlt_result,
-                hltonl::PSC_ERROR_NO_L1_RESULT,
-                "No Lvl1 result ROBs received.");
-
-    return StatusCode::RECOVERABLE;
-  }
-
-  // *-- SubDetectors in received L1 ROB list
-  if (m_doMonitoring.value()) {
-    scoped_lock_histogram lock;
-    for(const auto& rob : l1_result)
-    {
-      auto sid = eformat::helper::SourceIdentifier(rob.rob_source_id());
-      auto label = std::string{UNEXPECTED_L1R_ROB_LABEL};
-      if(std::find(begin(L1R_BINS), end(L1R_BINS), sid.subdetector_id())
-         != end(L1R_BINS))
-        label = sid.human_detector();
-      m_hist_l1_robs->Fill(label.c_str(), 1.);
-    }
-  }
-
-  const OFFLINE_FRAGMENTS_NAMESPACE::DataType* buffer;
-  // at least 1 Lvl1 rob, set basic parameters
-  m_lvl1id               = l1_result[0].rod_lvl1_id();  // Level-1 ID=event no., 32 bit unsigned
-  m_run_no               = l1_result[0].rod_run_no();   // run number,           32 bit unsigned
-  m_bunch_crossing_id    = l1_result[0].rod_bc_id();    // bunch crossing ID,    32 bit unsigned
-  l1_result[0].status(buffer);
-  m_l1_Status_Element    = *buffer;
-  m_l1_Trigger_Type      = l1_result[0].rod_lvl1_trigger_type();
-  m_l1_detev_type        = l1_result[0].rod_detev_type();
-  m_time_stamp           = 0; // time stamp - posix time in seconds from 1970,   32 bit unsigned
-  m_time_stamp_ns_offset = 0; // time stamp ns - ns time offset for time_stamp,  32 bit unsigned
-  m_lumi_block           = 0; // luminosity block identifier,                    32 bit unsigned
-  m_l1_Trigger_Info.assign(16,0);  // triggerInfo can be obtained from CTP fragment
-
-  // put Lvl1 result in ROBDataProviderSvc cache
-  m_robDataProviderSvc->setNextEvent(l1_result);
-
-  // find the CTP ROB and get the complete event info data
-  std::vector<const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment*> ctpRobFragmentVec;
-  m_robDataProviderSvc->getROBData(m_ctpRobIdVec,ctpRobFragmentVec);
-  bool b_invalidCTPRob = false;
-  std::ostringstream ost;
-  if( ctpRobFragmentVec.size() == 1 ) {
-    try {
-      m_lvl1id            = ctpRobFragmentVec[0]->rod_lvl1_id();  // Level-1 ID=event no., 32 bit unsigned
-      m_run_no            = ctpRobFragmentVec[0]->rod_run_no();   // run number,           32 bit unsigned
-      m_bunch_crossing_id = ctpRobFragmentVec[0]->rod_bc_id();    // bunch crossing ID,    32 bit unsigned
-      ctpRobFragmentVec[0]->status(buffer);
-      m_l1_Status_Element = *buffer;
-      m_l1_Trigger_Type   = ctpRobFragmentVec[0]->rod_lvl1_trigger_type();
-      m_l1_detev_type     = ctpRobFragmentVec[0]->rod_detev_type();
-      // get time_stamp - posix time in seconds from 1970, and time_stamp_ns - ns time offset for time_stamp
-      CTPfragment::time( ctpRobFragmentVec[0], m_time_stamp, m_time_stamp_ns_offset );
-      // luminosity block identifier, 32 bit unsigned
-      m_lumi_block = CTPfragment::lumiBlockNumber( ctpRobFragmentVec[0] );
-      // get the L1 trigger info
-      m_l1_Trigger_Info   = CTPfragment::triggerDecision( ctpRobFragmentVec[0] );
-
-      b_invalidCTPRob = !checkEventIdConsistency(evId);
-     }
-    catch (CTPfragment::NullFragmentPointer& ex) {
-      m_invalid_lvl1_result++;
-      if (m_lvl1CTPROBcheck) {
-        b_invalidCTPRob=true;
-        ost << " Invalid CTP fragment. Exception = " << ex.what();
-      }
-      msgStream() << MSG::ERROR << ex.what() << endmsg;
-    }
-    catch (CTPfragment::Inconsistency& ex) {
-      m_invalid_lvl1_result++;
-      if (m_lvl1CTPROBcheck) {
-        b_invalidCTPRob=true;
-        ost << " Invalid CTP fragment. Exception = " << ex.what();
-      }
-      msgStream() << MSG::ERROR << ex.what() << endmsg;
-    }
-    catch (CTPfragment::TimeOutOfRange& ex) {
-      m_invalid_lvl1_result++;
-      if (m_lvl1CTPROBcheck) {
-        b_invalidCTPRob=true;
-        ost << " Invalid CTP fragment. Exception = " << ex.what();
-      }
-      msgStream() << MSG::ERROR << ex.what() << endmsg;
-    }
-    catch (CTPfragment::TriggerWordsOutOfRange& ex) {
-      m_invalid_lvl1_result++;
-      if (m_lvl1CTPROBcheck) {
-        b_invalidCTPRob=true;
-        ost << " Invalid CTP fragment. Exception = " << ex.what();
-      }
-      msgStream() << MSG::ERROR << ex.what() << endmsg;
-    }
-    catch (CTPfragment::GenericIssue& ex) {
-      m_invalid_lvl1_result++;
-      if (m_lvl1CTPROBcheck) {
-        b_invalidCTPRob=true;
-        ost << " Invalid CTP fragment. Exception = " << ex.what();
-      }
-      msgStream() << MSG::ERROR << ex.what() << endmsg;
-    }
-    catch (eformat::Issue& ex) {
-      m_invalid_lvl1_result++;
-      std::string issue_msg = std::string("Uncaught eformat issue:    ")+std::string(ex.what());
-      if (m_lvl1CTPROBcheck) {
-        b_invalidCTPRob=true;
-        ost << " Invalid CTP fragment. Exception = " << ex.what();
-      }
-      msgStream() << MSG::ERROR << issue_msg << endmsg;
-    }
-    catch (ers::Issue& ex) {
-      m_invalid_lvl1_result++;
-      std::string issue_msg = std::string("Uncaught ERS issue:        ")+std::string(ex.what());
-      if (m_lvl1CTPROBcheck) {
-        b_invalidCTPRob=true;
-        ost << " Invalid CTP fragment. Exception = " << ex.what();
-      }
-      msgStream() << MSG::ERROR << issue_msg << endmsg;
-    }
-    catch (std::exception& ex) {
-      m_invalid_lvl1_result++;
-      std::string issue_msg = std::string("Uncaught std exception:    ")+std::string(ex.what());
-      if (m_lvl1CTPROBcheck) {
-        b_invalidCTPRob=true;
-        ost << " Invalid CTP fragment. Exception = " << ex.what();
-      }
-      msgStream() << MSG::ERROR << issue_msg << endmsg;
-    }
-    catch (...) {
-      m_invalid_lvl1_result++;
-      if (m_lvl1CTPROBcheck) {
-        b_invalidCTPRob=true;
-        ost << " Invalid CTP fragment. Uncaught unknown exception.";
-      }
-      msgStream() << MSG::ERROR << "Uncaught unknown exception." << endmsg;
-    }
-  } else {
-    // no valid CTP fragment found
-    m_invalid_lvl1_result++;
-    if (m_doMonitoring.value()) m_hist_l1_robs->Fill(MISSING_L1R_CTP_LABEL, 1.);
-
-    std::string issue_msg = std::string("No valid CTP fragment found.  ") ;
-    if (m_hltROBDataProviderSvc.isValid()) issue_msg = issue_msg + std::string("\n") +
-                m_hltROBDataProviderSvc->dumpROBcache() ;
-    if (m_lvl1CTPROBcheck) {
-      b_invalidCTPRob=true;
-      ost << " No valid CTP fragment found. " ;
-    }
-    msgStream() << MSG::ERROR << issue_msg << endmsg;     
-  }
-
-  // in case a check of the CTP Rob is requested and an invalid fragment was found
-  // skip the event and put it on the debug stream
-  // -----------------------------------------------------------------------------
-  if (m_lvl1CTPROBcheck && b_invalidCTPRob) {
-    ost << " Skip event requested. ";
-    failedEvent(hlt_result,
-                hltonl::PSC_ERROR_INVALID_CTP_RESULT,
-                ost.str());
-
-    return StatusCode::RECOVERABLE;
-  }
-
-  // Check for other missing L1 ROBs
-  auto missing_l1_robs = missingL1Robs(l1_result);
-  if(!missing_l1_robs.empty())
-  {
-    ++m_invalid_lvl1_result;
-    failedEvent(hlt_result, hltonl::PSC_ERROR_NO_L1_RESULT,
-                missingL1RobsMsg(missing_l1_robs));
-
-    return StatusCode::RECOVERABLE;
-  }
-
-  //-----------------------------------------------------------------------
-  // Clear the event store, if used in the event loop
-  //-----------------------------------------------------------------------
-  sc = m_evtStore->clearStore();
-  if ( msgLevel() <= MSG::DEBUG ) {
-    msgStream() << MSG::DEBUG << " ---> Clear of Event data store " << sc << endmsg;
-  }
-  if(sc.isFailure()) {
-    failedEvent(hlt_result, hltonl::PSC_ERROR_SG_CLEAR_FAILED,
-                "Clear of Event data store failed.");
-    return sc;
-  }
-
-  // create an EventInfo Object to fire the incidents and register in evt store
-  auto pEvent = new EventInfo(new EventID(m_run_no,
-                                          evId.globalId,
-                                          m_time_stamp,
-                                          m_time_stamp_ns_offset,
-                                          m_lumi_block,
-                                          m_bunch_crossing_id,
-                                          std::get<0>(m_detector_mask),
-                                          std::get<1>(m_detector_mask),
-                                          std::get<2>(m_detector_mask),
-                                          std::get<3>(m_detector_mask)),
-                              new EventType(),
-                              new TriggerInfo(m_l1_Status_Element,
-                                              m_lvl1id,
-                                              m_l1_Trigger_Type,
-                                              m_l1_Trigger_Info));
-
-  if ( msgLevel() <= MSG::DEBUG ) {
-    msgStream() << MSG::DEBUG << " +-----------+ " << endmsg;
-    msgStream() << MSG::DEBUG << " | New Event | Run = " << m_run_no 
-		<< " / Level-1 ID = "      << m_lvl1id 
-		<< " / global Event ID = " << evId.globalId
-		<< endmsg;
-    msgStream() << MSG::DEBUG << " +-----------+ " << endmsg;
-    msgStream() << MSG::DEBUG << " Complete EventID    = " << *(pEvent->event_ID()) << endmsg;
-    msgStream() << MSG::DEBUG << "        EventType    = " << ((pEvent->event_type())->typeToString()) << endmsg;
-    msgStream() << MSG::DEBUG << "      TriggerInfo    = " << *(pEvent->trigger_info()) << endmsg;
-    msgStream() << MSG::DEBUG << " Current Run number  = " << m_currentRun << endmsg;
-  }
-
-  // Record it in StoreGate
-  if(m_evtStore->record(pEvent, "EventInfo").isFailure())
-  {
-    failedEvent(hlt_result, hltonl::PSC_ERROR_NO_EVENTINFO,
-        "Error recording EventInfo object in SG");
-
-    return StatusCode::FAILURE;
-  }
-
-  //-----------------------------------------------------------------------
-  // process the RoI(s)/Event
-  //-----------------------------------------------------------------------
-  sc = executeEvent(NULL);
-  if(sc.isFailure()) {
-    failedEvent(hlt_result, hltonl::PSC_ERROR_UNCLASSIFIED,
-                "An unknown error occured during event processing",
-                false /* no empty result */);
-  }
-
-  // Get the xAOD::EventInfo from SG
-  xAOD::EventInfo * xev{nullptr};
-  if(m_evtStore->retrieve(xev, "EventInfo").isFailure())
-  {
-    msgStream() << MSG::WARNING << ST_WHERE
-                << "Could not retrieve xAOD::EventInfo in store gate. "
-                << "If running in HelloWorld algorithms, this is OK."
-                << endmsg;
-  }
-
-  if (msgLevel() <= MSG::DEBUG)
-    msgStream() << MSG::DEBUG << " new xAOD::EventInfo: " << xev << endmsg;
-
-  //-----------------------------------------------------------------------
-  // build HLT result
-  //-----------------------------------------------------------------------
-  HltResult(hlt_result, pEvent, xev);
-  // fill histograms
-  fillHltResultHistograms(hlt_result);
-
-  return sc;
-}
-
-//=========================================================================
-// implementation of IService::stop() ---> for "online" running
-//=========================================================================
+// =============================================================================
+// Reimplementation of AthService::stop (IStateful interface)
+// =============================================================================
 StatusCode HltEventLoopMgr::stop()
 {
-  // Do nothing if we are already stopped
-  if ( FSMState() != Gaudi::StateMachine::RUNNING )
-    return StatusCode::SUCCESS;
-
-  if (msgLevel() <= MSG::DEBUG) {  
-    msgStream() << MSG::DEBUG << " ---> HltEventLoopMgr = " << name() << " stop() " << endmsg;
+  // Stop top level algorithms
+  for (auto& ita : m_topAlgList) {
+    ATH_CHECK(ita->sysStop());
   }
 
-  //-----------------------------------------------------------------------
-  // Fire EndRun "Incident"
-  //-----------------------------------------------------------------------
-  m_incidentSvc->fireIncident(Incident(name(), IncidentType::EndRun));
-
-  //-----------------------------------------------------------------------
-  // Call endRun() and stop() of all algorithms
-  //-----------------------------------------------------------------------
-  auto suc1 = callOnAlgs(&IAlgorithm::sysEndRun, "sysEndRun").isSuccess();
-  auto suc2 = callOnAlgs(&IAlgorithm::sysStop, "sysStop").isSuccess();
-
-  return (suc1 && suc2) ? StatusCode::SUCCESS : StatusCode::FAILURE;
+  return AthService::stop();
 }
 
-//=========================================================================
-// implementation of ITrigEventLoopMgr::timeOutReached ---> for "online" running
-//=========================================================================
-/**
- * Called by the PSC once the HLTPU signals the timeout warning.
- *
- * !!! This method is executed in the context of the timeout thread !!!
- * !!! Make sure the code is thread-safe                            !!!
- *
- */
-StatusCode HltEventLoopMgr::timeOutReached(const ptree& pt)
+// =============================================================================
+// Reimplementation of AthService::finalize (IStateful interface)
+// =============================================================================
+StatusCode HltEventLoopMgr::finalize()
 {
-  IAlgorithm* alg = m_algContextSvc ? m_algContextSvc->currentAlg() : 0;
-
-  // add current algorithm info
-  std::ostringstream tmsg;
-  tmsg << "Timeout warning received"
-       << (alg ? (" while executing '"+alg->name()+"'. ") : ". ");
+  ATH_MSG_INFO(" ---> HltEventLoopMgr = " << name() << " finalize ");
+  ATH_MSG_INFO(" Total number of events processed " << m_nevt);
 
-  // set timeout and add current event info
-  {
-    std::lock_guard<std::mutex>{timeout_mutex};
+  // Need to release now - automatic release in destructor is too late since services are already gone
+  m_hltTHistSvc.reset();
+  m_hltROBDataProviderSvc.reset();
 
-    setTimeout(Athena::Timeout::instance());
-    if (m_currentEvent)
-      tmsg << " On event " << *m_currentEvent->event_ID() << ". ";
-    else
-      tmsg << " Unknown event - outside of event processing? ";
+  // Finalise top level algorithms
+  for (auto& ita : m_topAlgList) {
+    if (ita->sysFinalize().isFailure())
+      ATH_MSG_WARNING("Finalisation of algorithm " << ita->name() << " failed");
   }
-
-  // add time interval info
-  auto starts = pt.get_optional<long long>("StartTime_s");
-  if(starts)
-  {
-    auto ends = std::chrono::duration_cast<std::chrono::seconds>(
-        std::chrono::steady_clock::now().time_since_epoch()).count();
-    tmsg << (ends - *starts) << " seconds elapsed since ";
+  // Release top level algorithms
+  SmartIF<IAlgManager> algMgr = serviceLocator()->as<IAlgManager>();
+  if (!algMgr.isValid()) {
+    ATH_MSG_WARNING("Failed to retrieve AlgManager - cannot finalise top level algorithms");
   }
-  else
-    tmsg << "No information of when ";
-
-  tmsg << "the HLTPU last started counting.";
-
-  // log timeout message
-  ERS_HLT_WARNING(tmsg.str());
-
-  // Also fire timeout incident (this seems to cause problems, see #66066)
-  // m_incidentSvc->fireIncident( HLT::Incidents::EventTimeout(name()) );  
-
-  return StatusCode::SUCCESS;
-}
-
-
-
-//=========================================================================
-// implementation of ITrigEventLoopMgr::checkHltPrescaleUpdate() ---> for "online" running
-//=========================================================================
-StatusCode HltEventLoopMgr::checkHltPrescaleUpdate(std::vector<uint32_t>& hltCounter)
-{
-  if (msgLevel() <= MSG::DEBUG) {  
-    msgStream() << MSG::DEBUG << " ---> HltEventLoopMgr = " << name()
-		    << " hltConditionsUpdate(std::vector<uint32_t>&): size of input = " << hltCounter.size() << ": ";
-    for (size_t i=0; i<hltCounter.size(); ++i) msgStream() << hltCounter[i] << " ";
-    msgStream() << endmsg;
-  }
-  if ( hltCounter.empty() ) return StatusCode::SUCCESS;  
-
-  // First (and only used) element is LB of the prescale update
-  uint32_t new_hltPrescaleUpdateLB = hltCounter[0];
-
-  // Only update if counter (lumiblock for update) changed (or first event)
-  if ( m_l1_hltPrescaleUpdateLB != new_hltPrescaleUpdateLB ) {    
-    m_l1_hltPrescaleUpdateLB = new_hltPrescaleUpdateLB;
-
-    // Retrieve EventInfo object
-    const EventInfo* pEvent(0);
-    StatusCode sc = m_evtStore->retrieve(pEvent);
-    if(sc.isFailure()) {
-      msgStream() << MSG::ERROR << "Unable to retrieve EventInfo object" << endmsg;
-      return sc;
+  else {
+    for (auto& ita : m_topAlgList) {
+      if (algMgr->removeAlgorithm(ita).isFailure())
+        ATH_MSG_WARNING("Problems removing Algorithm " << ita->name());
     }
-
-    msgStream() << MSG::INFO << "Prescale update requested for lumiblock "
-        << m_l1_hltPrescaleUpdateLB << ". Current event: " << *pEvent->event_ID() << endmsg;
-
-    // Perform prescale update right away (including on first event)
-    sc = hltPrescaleUpdate(m_l1_hltPrescaleUpdateLB);
-    return sc;
   }
+  m_topAlgList.clear();
+
+  // Release service handles
+  if (m_incidentSvc.release().isFailure())
+    ATH_MSG_WARNING("Failed to release service " << m_incidentSvc.typeAndName());
+  if (m_robDataProviderSvc.release().isFailure())
+    ATH_MSG_WARNING("Failed to release service " << m_robDataProviderSvc.typeAndName());
+  if (m_evtStore.release().isFailure())
+    ATH_MSG_WARNING("Failed to release service " << m_evtStore.typeAndName());
+  if (m_detectorStore.release().isFailure())
+    ATH_MSG_WARNING("Failed to release service " << m_detectorStore.typeAndName());
+  if (m_inputMetaDataStore.release().isFailure())
+    ATH_MSG_WARNING("Failed to release service " << m_inputMetaDataStore.typeAndName());
+  if (m_THistSvc.release().isFailure())
+    ATH_MSG_WARNING("Failed to release service " << m_THistSvc.typeAndName());
+  if (m_evtSelector.release().isFailure())
+    ATH_MSG_WARNING("Failed to release service " << m_evtSelector.typeAndName());
+  if (m_outputCnvSvc.release().isFailure())
+    ATH_MSG_WARNING("Failed to release service " << m_outputCnvSvc.typeAndName());
+
+  // Release tool handles
+  if (m_coolHelper.release().isFailure())
+    ATH_MSG_WARNING("Failed to release tool " << m_coolHelper.typeAndName());
+  if (m_hltResultBuilder.release().isFailure())
+    ATH_MSG_WARNING("Failed to release tool " << m_hltResultBuilder.typeAndName());
+  if (m_eventInfoCnvTool.release().isFailure())
+    ATH_MSG_WARNING("Failed to release tool " << m_eventInfoCnvTool.typeAndName());
+
+  // Release SmartIFs
+  m_whiteboard.reset();
+  m_algResourcePool.reset();
+  m_aess.reset();
+  m_schedulerSvc.reset();
+  m_hltTHistSvc.reset();
+  m_hltROBDataProviderSvc.reset();
 
   return StatusCode::SUCCESS;
 }
 
-
-//=========================================================================
-// implementation of ITrigEventLoopMgr::hltPrescaleUpdate() ---> for "online" running
-//=========================================================================
-StatusCode HltEventLoopMgr::hltPrescaleUpdate(uint32_t lumiBlock)
-{
-  if ( !m_hltConfigSvc ) {
-    return StatusCode::SUCCESS;
-  }
-
-  // ID must be unqiue across runs until DbProxy gets restarted
-  unsigned int id = m_currentRun*10000 + lumiBlock;
-  msgStream() << MSG::INFO << " ---> HltEventLoopMgr = " << name()
-                  << " calling HLTConfigSvc::updatePrescaleSets(" << id << ")" << endmsg;
-  StatusCode sc = m_hltConfigSvc->updatePrescaleSets(id);
-
-  return sc;
-}
-
-//=========================================================================
-// check that a ROB ID is enabled for readout in OKS  ---> for "online" running
-//=========================================================================
-bool HltEventLoopMgr::isRobEnabled(uint32_t robid) const
+// =============================================================================
+// Reimplementation of AthService::reinitalize (IStateful interface)
+// =============================================================================
+StatusCode HltEventLoopMgr::reinitialize()
 {
-  bool b_enabled = true;
+  ATH_CHECK(AthService::reinitialize());
 
-  // check if given ROB is actually enabled for readout
-  // Consider some ROBs from SubDetectorGroup TDAQ as always enabled
-  if ((m_enabledROBs.value().size() != 0) &&
-      !skipEnabledCheck(robid))
-  {
-    auto rob_enabled_it = std::find(m_enabledROBs.value().begin(),
-                                    m_enabledROBs.value().end(),
-                                    robid);
-    if(rob_enabled_it == m_enabledROBs.value().end())
-    {
-      if(msgLevel() <= MSG::DEBUG)
-        msgStream() << MSG::DEBUG << "---> ROB Id : 0x" << MSG::hex << robid
-                    << MSG::dec << " will not be retrieved, since it is not on "
-                                   "the list of enabled ROBs." << endmsg;
-
-      b_enabled = false;
-    }
+  // reinitialise top level algorithms
+  for (auto& ita : m_topAlgList) {
+    ATH_CHECK(ita->sysReinitialize());
   }
 
-  return b_enabled;
+  return StatusCode::SUCCESS;
 }
 
-//=========================================================================
-// check that a Sub Detector ID is enabled for readout in OKS  ---> for "online" running
-//=========================================================================
-bool HltEventLoopMgr::isSubDetectorEnabled(uint32_t subdetid) const
+// =============================================================================
+// Reimplementation of AthService::restart (IStateful interface)
+// =============================================================================
+StatusCode HltEventLoopMgr::restart()
 {
-  bool b_enabled = true;
+  ATH_CHECK(AthService::restart());
 
-  // check if given subdetector is actually enabled for readout
-  if ((m_enabledSubDetectors.value().size() != 0) &&
-      !skipEnabledCheck(static_cast<eformat::SubDetector>(subdetid)))
-  {
-    auto sd_enabled_it = std::find(m_enabledSubDetectors.value().begin(),
-                                   m_enabledSubDetectors.value().end(),
-                                   subdetid);
-    if(sd_enabled_it == m_enabledSubDetectors.value().end())
-    {
-      if(msgLevel() <= MSG::DEBUG)
-        msgStream() << MSG::DEBUG << "---> Sub Detector Id : 0x" << MSG::hex
-                    << subdetid << MSG::dec << " will not be retrieved, since "
-                    "it is not on the list of enabled Sub Detectors." << endmsg;
-      b_enabled = false;
-    }
+  // restart top level algorithms
+  for (auto& ita : m_topAlgList) {
+    m_aess->resetErrorCount(ita);
+    ATH_CHECK(ita->sysRestart());
   }
 
-  return b_enabled;
-}
-
-//=========================================================================
-// filter a set of robs according to whether or not they are enabled
-//=========================================================================
-std::set<uint32_t>
-HltEventLoopMgr::filterRobs(const std::set<uint32_t>& robs) const
-{
-  auto ret = decltype(robs){};
-  for(const auto& r : robs)
-    if(isRobEnabled(r))
-      ret.insert(r);
-
-  return ret;
-}
-
-//=========================================================================
-// filter a set of dets according to whether or not they are enabled
-//=========================================================================
-std::set<eformat::SubDetector>
-HltEventLoopMgr::filterDets(const std::set<uint32_t>& dets) const
-{
-  auto ret = std::set<eformat::SubDetector>{};
-  for(const auto& d : dets)
-    if(isSubDetectorEnabled(d))
-      ret.insert(static_cast<eformat::SubDetector>(d));
-
-  return ret;
-}
-
-//=========================================================================
-// Obsolete methods for online running
-//=========================================================================
-StatusCode HltEventLoopMgr::nextEvent(int maxevt)
-{
-  msgStream() << MSG::ERROR << " +-------------------------------------------------------------------------+ " << endmsg;
-  msgStream() << MSG::ERROR << " | method --->  HltEventLoopMgr::nextEvent(int maxevt) <--- called         | " << endmsg;
-  msgStream() << MSG::ERROR << " | This method can not be used in trigger since the event loop is          | " << endmsg;
-  msgStream() << MSG::ERROR << " | controlled by the data flow software.                                   | " << endmsg;
-  msgStream() << MSG::ERROR << " | Method is not implemented                                               | " << endmsg;
-  msgStream() << MSG::ERROR << " +-------------------------------------------------------------------------+ " << endmsg;
-  msgStream() << MSG::ERROR << " maxevt = " << maxevt << endmsg;
-  msgStream() << MSG::ERROR << " Type info = " << System::typeinfoName(typeid(*this)) << endmsg;
-  return StatusCode::FAILURE;
-}
-
-StatusCode HltEventLoopMgr::executeRun(int)
-{
-  msgStream() << MSG::ERROR << " +-------------------------------------------------------------------------+ " << endmsg;
-  msgStream() << MSG::ERROR << " | method --->  HltEventLoopMgr::executeRun(int) <--- called               | " << endmsg;
-  msgStream() << MSG::ERROR << " | This method can not be used in trigger since the event loop is          | " << endmsg;
-  msgStream() << MSG::ERROR << " | controlled by the data flow software.                                   | " << endmsg;
-  msgStream() << MSG::ERROR << " | Method is not implemented                                               | " << endmsg;
-  msgStream() << MSG::ERROR << " +-------------------------------------------------------------------------+ " << endmsg;
-  msgStream() << MSG::ERROR << " Type info = " << System::typeinfoName(typeid(*this)) << endmsg;
-  return StatusCode::FAILURE;
-}
-
-StatusCode HltEventLoopMgr::stopRun()
-{
-  msgStream() << MSG::ERROR << " +-------------------------------------------------------------------------+ " << endmsg;
-  msgStream() << MSG::ERROR << " | method --->  HltEventLoopMgr::stopRun() <--- called                     | " << endmsg;
-  msgStream() << MSG::ERROR << " | This method is not implemented for online usage. Call stop() instead.   | " << endmsg;
-  msgStream() << MSG::ERROR << " +-------------------------------------------------------------------------+ " << endmsg;
-  msgStream() << MSG::ERROR << " Type info = " << System::typeinfoName(typeid(*this)) << endmsg;
-  return StatusCode::FAILURE;
+  return StatusCode::SUCCESS;
 }
 
-//=========================================================================
-// HltEmptyResultROB()
-//=========================================================================
-void HltEventLoopMgr::HltEmptyResultROB(hltinterface::HLTResult& hlt_result,
-    uint32_t run_no, uint32_t lvl1_id, uint32_t bunch_crossing_id,
-    uint32_t l1_Trigger_Type, uint32_t l1_detev_type,
-    hltonl::PSCErrorCode pscErrorCode)
-{
-  if ( msgLevel() <= MSG::DEBUG ) {
-    msgStream() << MSG::DEBUG << "---> HltEmptyResultROB() for " << name() 
-		    << " and sub detector = " << eformat::helper::SubDetectorDictionary.string(eformat::TDAQ_HLT)
-		    << " called " << endmsg;
-  }
-
-  //
-  // Set the PSC error words
-  // -----------------------
-  //
-  HltSetPscError(hlt_result, pscErrorCode);
-
-  //
-  // Create a dummy HLT result ROB
-  // -----------------------------
-  //
-
-  // the second status element
-  hltonl::ResultStatusCode hlt_status = hltonl::DUMMY_HLT_RESULT ;
-
-  // Build the third status elements for the dummy HLT result
-  // number of status words used (in case of PSC error = 3, otherwise = 2)
-  uint32_t n_status_word = 3;
-  m_status_words[0] = SW_FAIL.code();
-  m_status_words[1] = hlt_status;
-  m_status_words[2] = pscErrorCode; //this means "dummy HLT result, with no data due PSC error"
-
-  if (!pscErrorCode) {
-    m_status_words[0] = SW_UNCLASSIFIED.code(); //this means "dummy HLT result, with no data, no PSC error"
-    n_status_word = 2;
-  }
-
-  // Build an empty HLT result
-  eformat::helper::SourceIdentifier src(eformat::TDAQ_HLT, 0);
-  eformat::write::ROBFragment rob(src.code(), run_no, lvl1_id, bunch_crossing_id, l1_Trigger_Type, l1_detev_type,
-      0, 0, eformat::STATUS_FRONT);
-  rob.status(n_status_word, m_status_words);
-  rob.rod_status(n_status_word, m_status_words);
-
-  // find the maximum allowed payload
-  int hltr_max_payload = hlt_result.max_result_size - rob.size_word() ;
-  if ( hlt_result.max_result_size <= rob.size_word() ) {
-    msgStream() << MSG::ERROR
-        << "Can not create empty HLT result ROB with available ROB buffer size ! Available buffer size = "
-        << hlt_result.max_result_size << " Number of header words used by empty ROB = " << rob.size_word()
-        << endmsg;
-    return;
-  }
-
-  // Create a dummy HLT result and check data size
-  uint32_t* hltr_data(0);
-  int       hltr_data_size = 0;
-  HLT::HLTResult emptyHLTResult;
-  emptyHLTResult.setLvl1Id(lvl1_id);
-
-  HLT::HLTExtraData& extraData = emptyHLTResult.getExtraData();
-  extraData.appName = applicationName();
-  extraData.statusCode &= ~hltonl::HLT_PRESCALE_UPDATE;  // error (clear bit)
-
-  bool serializationOk = emptyHLTResult.serialize( hltr_data, hltr_data_size, hltr_max_payload);
-
-  if ( !serializationOk ) {
-    // Update status words for dummy HLT result
-    hlt_status = hltonl::DUMMY_HLT_RESULT_TRUNCATED;
-    m_status_words[0] = SW_TRUNCATION.code() ;
-    m_status_words[1] = hlt_status ;
-  }
-
-  if (( hltr_data_size > hltr_max_payload)) { // consistency check
-    msgStream() << MSG::ERROR 
-        << "Inconsistency for created dummy HLT result ROB. Returned data size = " << hltr_data_size
-        << " is greater than allowed max. payload size = " << hltr_max_payload << "."
-        << endmsg;
-    hltr_data_size = hltr_max_payload;
-
-    // Update status words for dummy HLT result
-    hlt_status = hltonl::DUMMY_HLT_RESULT_TRUNCATED;
-    m_status_words[0] = SW_TRUNCATION.code();
-    m_status_words[1] = hlt_status ;
-  }
-
-  // build the fragment
-  rob.status(n_status_word, m_status_words);
-  rob.rod_status(n_status_word, m_status_words);
-  rob.rod_data(hltr_data_size, hltr_data);
-
-  //
-  // store the dummy HLT ROB fragment in the hlt_result structure
-  // ------------------------------------------------------------ 
-  //
-  // The maximum possible space is already allocated by the HLTMPPU
-  // copy the ROB contents into the allocated memory
-  auto next_fragment = hlt_result.fragment_pointer;
-  auto spaceleft = hlt_result.max_result_size;
-  addRobToHLTResult(hlt_result, rob, next_fragment, spaceleft);
-
-  // delete the data array
-  if (hltr_data != 0) delete[] hltr_data;
-
-  return;
-} // end method HltEventLoopMgr::HltEmptyResultROB
-
-//=========================================================================
-// HltEmptyResultROB()  ---> for "online" running
-//=========================================================================
-void HltEventLoopMgr::HltEmptyResultROB(hltinterface::HLTResult& hlt_result, hltonl::PSCErrorCode pscErrorCode)
+// =============================================================================
+// Implementation of ITrigEventLoopMgr::prepareForRun
+// =============================================================================
+StatusCode HltEventLoopMgr::prepareForRun(const ptree& pt)
 {
-  if ( msgLevel() <= MSG::DEBUG ) {
-    msgStream() << MSG::DEBUG << "---> HltEmptyResultROB() for "
-                << name() << " called " << endmsg;
-  }
-
-  HltEmptyResultROB(hlt_result,
-                    m_run_no, m_lvl1id, m_bunch_crossing_id,
-                    m_l1_Trigger_Type, m_l1_detev_type,
-                    pscErrorCode);
-  return;
-} //  end method HltEventLoopMgr::HltEmptyResult
-
-//=========================================================================
-// HltResultROBs()
-//=========================================================================
-hltonl::PSCErrorCode HltEventLoopMgr::HltResultROBs(
-    hltinterface::HLTResult& hlt_result,
-    uint32_t run_no, uint32_t lvl1_id, uint32_t bunch_crossing_id,
-    uint32_t l1_Trigger_Type, uint32_t l1_detev_type,
-    const std::vector<TriggerInfo::number_type>& trigger_info,
-    const std::vector<TriggerInfo::StreamTag>& stream_tags,
-    const std::vector<xAOD::EventInfo::StreamTag>& xsts)
-{
-  HLT::HLTResult* dobj{0};
-  auto hlt_decision = hltonl::PSC_FORCED_REJECT;
-  auto ecode = hltonl::PSC_ERROR_UNCLASSIFIED;
-  if(!m_forceHltReject)
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  try
   {
-    // preliminary hlt_result setup
-    setStreamTags(hlt_result, stream_tags);
-    mergeStreamTags(hlt_result, xsts);
-    hlt_result.trigger_info = trigger_info;
-
-    // Get Pesa HLT Result from Steering
-    StatusCode sc;
-    if(!(m_evtStore->transientContains<HLT::HLTResult>(m_HltResultName)) ||
-       (sc = m_evtStore->retrieve(dobj,m_HltResultName)).isFailure())
-    {
-      hlt_decision = hltonl::PSC_DEBUG;
-      msgStream() << MSG::ERROR << ST_WHERE
-                  << "Error retrieving HLTResult from StoreGate with key = "
-                  << m_HltResultName << endmsg;
-
-      ecode = sc.isFailure() ? hltonl::PSC_ERROR_NO_HLTRESULT_RETRIEVED
-                             : hltonl::PSC_ERROR_NO_HLTRESULT_FOUND;
-    }
-    else if((hlt_decision = processHltDecision(hlt_result)) !=
-            hltonl::STEERING_REJECT)
-    {
-      // Got Steering's HLT Result and confirmed the event should be accepted
-      auto serializationOk = true;
-      ecode = serializeRobs(hlt_result, serializationOk, dobj, run_no, lvl1_id,
-                            bunch_crossing_id, l1_Trigger_Type, l1_detev_type);
-      if(!ecode)
-        recordEDMSizeInfo(dobj->getNavigationResult().size(), serializationOk);
-
-      // The HLT result got truncated, put the event on a special debug stream if requested 
-      if (!serializationOk) {
-	m_truncated_hlt_result++;
-    if (m_doMonitoring.value()) m_hist_Hlt_truncated_result->Fill(1.);
-
- 	if ((!m_HltTruncationDebugStreamName.value().empty()) &&
-	    (m_writeHltTruncationToDebug.value())) {
-      	  // check if event should be not send to the debug stream (e.g. Cost Monitoring)
-	  bool sendToDebug(true);
-	  for (auto it_st : hlt_result.stream_tag) {
-	    auto p = std::find(m_excludeFromHltTruncationDebugStream.value().begin(), 
-			       m_excludeFromHltTruncationDebugStream.value().end(),
-			       (it_st).name);
-	    if (p != m_excludeFromHltTruncationDebugStream.value().end()) sendToDebug=false;
-	  }
-	  if (sendToDebug) {
-	    m_truncated_hlt_result_to_debug++;	 
-        if (m_doMonitoring.value()) m_hist_Hlt_truncated_result->Fill(2.);
-	    hlt_result.stream_tag.clear();
-	    addDebugStreamTag(hlt_result, m_HltTruncationDebugStreamName);
-	    msgStream() << MSG::ERROR << ST_WHERE
-			<< "HLTResult was truncated. Event send to debug stream  = "
-			<< m_HltTruncationDebugStreamName << endmsg;
-	  } else {
-	    m_truncated_hlt_result_not_to_debug++;	 
-        if (m_doMonitoring.value()) m_hist_Hlt_truncated_result->Fill(3.);
-	    msgStream() << MSG::WARNING << ST_WHERE
-			<< "HLTResult was truncated. Event was NOT send to debug stream  = "
-			<< m_HltTruncationDebugStreamName
-			<< " because an exclusion stream tag name matched from = " << m_excludeFromHltTruncationDebugStream.value()  
-			<< endmsg;
-	  }
-	} else {
-	  m_truncated_hlt_result_not_to_debug++;
-      if (m_doMonitoring.value()) m_hist_Hlt_truncated_result->Fill(3.);
-	}
-      }
-    }
-  }
-
-  if (m_doMonitoring.value())
-    m_hist_eventAcceptFlags->Fill(static_cast<float>(m_mapAccept.codeToHash(hlt_decision)));
-
-  if(msgLevel() <= MSG::DEBUG) {
-    msgStream() << MSG::DEBUG << ST_WHERE << "Decision = "
-                << hltonl::PrintHltAcceptFlag(hlt_decision) << "\n"
-                << hlt_result << endmsg;
-    if(dobj) {
-      const auto& extraData = dobj->getExtraData();
-      msgStream() << MSG::DEBUG << ST_WHERE
-                  << "HltResult extra data: Host name = " << extraData.appName
-                  << ", status code = " << extraData.statusCode << endmsg;
+    // (void)TClass::GetClass("vector<unsigned short>"); // preload to overcome an issue with dangling references in serialization
+    // (void)TClass::GetClass("vector<unsigned long>");
+
+    // do the necessary resets
+    // internalPrepareResets() was here
+    StatusCode sc = clearTemporaryStores();
+    if (sc.isFailure()) {
+      ATH_MSG_ERROR("Clearing temporary stores failed");
+      return sc;
     }
-  }
-
-  return ecode;
-} // end method HltEventLoopMgr::HltResultROBs
 
-//=========================================================================
-// HltResult()  ---> for "online" running
-//=========================================================================
-void HltEventLoopMgr::HltResult(hltinterface::HLTResult& hlt_result,
-                                const EventInfo* pEvent,
-                                const xAOD::EventInfo * xev)
-{
-  if ( msgLevel() <= MSG::DEBUG ) {
-    msgStream() << MSG::DEBUG << "---> HltResult() for " << name() << " called " << endmsg;
-  }
-
-  using xev_stags_t = decltype(xev->streamTags());
-  auto xev_stags = xev ? xev->streamTags() : xev_stags_t{};
-
-  hltonl::PSCErrorCode hlt_psc_error = HltResultROBs(hlt_result,
-                         m_run_no, m_lvl1id, m_bunch_crossing_id,
-                         m_l1_Trigger_Type, m_l1_detev_type,
-                         pEvent->trigger_info()->eventFilterInfo(),
-                         pEvent->trigger_info()->streamTags(),
-                         xev_stags);
-  // If there was an error when building the HLT result ROB,
-  // put the event on the debug stream and try to create a dummy result ROB
-  if (hlt_psc_error) {
-    // put event on debug stream
-    addDebugStreamTag(hlt_result, m_HltDebugStreamName.value());
-    // make empty HLT result ROB
-    HltEmptyResultROB(hlt_result,hlt_psc_error);
-    // increase counter
-    m_invalid_hlt_result++;
-  }
-
-  return;
-} //  end method HltEventLoopMgr::HltResult
+    const SOR* sor;
+    // update SOR in det store and get it back
+    if(!(sor = processRunParams(pt)))
+      return StatusCode::FAILURE;
 
-//=========================================================================
-void HltEventLoopMgr::bookHistograms()
-{
-  if ( msgLevel() <= MSG::DEBUG ) {
-    msgStream() << MSG::DEBUG << "---> bookHistograms() for " << name()
-                    << " called. Do monitoring = " << m_doMonitoring.value() << endmsg;
-  }
+    auto& soral = getSorAttrList(sor);
 
-  // return if no monitoring is requested
-  if ( !m_doMonitoring.value() ) { return; }
+    updateInternal(soral);     // update internally kept info
+    updateMetadataStore(soral);  // update metadata store
 
-  std::vector<TH1F**> regHistsTH1F;
-  regHistsTH1F.reserve(14);
-  std::vector<TProfile**> regHistsTProfile;
-  regHistsTProfile.reserve(4);
+    /*
+    const EventInfo * evinfo;
+    if(updMagField(pt).isFailure() ||     // update mag field when appropriate
+       updHLTConfigSvc().isFailure() ||   // update config svc when appropriate
+       resetCoolValidity().isFailure() || // reset selected proxies/IOV folders
+       prepXAODEventInfo().isFailure() || // update xAOD event data in SG
+       !(evinfo = prepEventInfo()))       // update old event data in SG
+      return StatusCode::FAILURE;
 
-  // monitoring information root directory
-  const std::string histPath = std::string("/EXPERT/") + name() + "/";
+    bookAllHistograms();
 
-  //     +--------------------+
-  // *-- | Event accept flags |
-  //     +--------------------+
-  uint32_t n_bins_eventAcceptFlags = hltonl::NUM_ACCEPTANCE_FLAGS;
-  m_hist_eventAcceptFlags = new TH1F ("EventAcceptFlags",
-                                      "EventAcceptFlags;;entries", 
-                                      n_bins_eventAcceptFlags, 0.5, 
-                                      n_bins_eventAcceptFlags+0.5);
+    ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+    if(prepareAlgs(*evinfo).isSuccess())
+      return StatusCode::SUCCESS;
+    */
 
-  for (const auto& m : m_mapAccept) {
-    m_hist_eventAcceptFlags->GetXaxis()->SetBinLabel( m.second.second , (m.second.first).c_str() );
-  }
-  regHistsTH1F.push_back(&m_hist_eventAcceptFlags);
-
-  //     +-----------------------+
-  // *-- | HLT result properties |
-  //     +-----------------------+
-  // *-- HLT result size plot
-  m_hist_Hlt_result_size = new TH1F ((m_histProp_Hlt_result_size.value().title()).c_str(),
-                                     (m_histProp_Hlt_result_size.value().title() + ";words;entries").c_str(),
-                                     m_histProp_Hlt_result_size.value().bins(),
-                                     m_histProp_Hlt_result_size.value().lowEdge(),
-                                     m_histProp_Hlt_result_size.value().highEdge());
-
-  regHistsTH1F.push_back(&m_hist_Hlt_result_size);
-
-  // *-- HLT result status codes
-  uint32_t n_bins_ResultStatus = hltonl::NUM_HLT_STATUS_CODES;
-  m_hist_Hlt_result_status = new TH1F ("HltResultStatusCodes", "HltResultStatusCodes;;entries", 
-                                       n_bins_ResultStatus, 0.5, n_bins_ResultStatus+0.5);
-
-  // do not print label for normal HLT result with no errors, it is not filled
-  for (hltonl::MapResultStatusCode::EnumMap::const_iterator map_it = m_mapResultStatus.begin(); map_it != m_mapResultStatus.end(); ++map_it) {
-    if ( (*map_it).first == hltonl ::NORMAL_HLT_RESULT ) {
-      m_hist_Hlt_result_status->GetXaxis()->SetBinLabel( ((*map_it).second).second, (((*map_it).second).first+" (bin not filled)").c_str() );
-    } else {
-      m_hist_Hlt_result_status->GetXaxis()->SetBinLabel( ((*map_it).second).second, (((*map_it).second).first).c_str() );
-    }
-  }
-  regHistsTH1F.push_back(&m_hist_Hlt_result_status);
-
-  // *-- HLT result truncation
-  uint32_t n_bins_ResultTruncation = 3;
-  m_hist_Hlt_truncated_result = new TH1F ("HltResultTruncation",
-                                          "HltResultTruncation;;entries", 
-                                          n_bins_ResultTruncation, 0.5, n_bins_ResultTruncation+0.5);
-
-  m_hist_Hlt_truncated_result->GetXaxis()->SetBinLabel( 1, std::string("Truncated HLT result").c_str() );
-  m_hist_Hlt_truncated_result->GetXaxis()->SetBinLabel( 2, std::string("Truncated HLT result (send to debug stream)").c_str() );
-  m_hist_Hlt_truncated_result->GetXaxis()->SetBinLabel( 3, std::string("Truncated HLT result (not send to debug stream)").c_str() );
-  regHistsTH1F.push_back(&m_hist_Hlt_truncated_result);
-
-  // *-- HLT result size plot (Stream Physics Main)
-  m_hist_Hlt_result_size_physics = 
-    new TH1F ((m_histProp_Hlt_result_size_physics.value().title()).c_str(),
-              (m_histProp_Hlt_result_size_physics.value().title() + ";words;entries").c_str(),
-              m_histProp_Hlt_result_size_physics.value().bins(),
-              m_histProp_Hlt_result_size_physics.value().lowEdge(),
-              m_histProp_Hlt_result_size_physics.value().highEdge());
-
-  regHistsTH1F.push_back(&m_hist_Hlt_result_size_physics);
-
-
-  // *-- HLT result size plot (Stream Express)
-  m_hist_Hlt_result_size_express = 
-    new TH1F ((m_histProp_Hlt_result_size_express.value().title()).c_str(),
-              (m_histProp_Hlt_result_size_express.value().title() + ";words;entries").c_str(),
-              m_histProp_Hlt_result_size_express.value().bins(),
-              m_histProp_Hlt_result_size_express.value().lowEdge(),
-              m_histProp_Hlt_result_size_express.value().highEdge());
-
-  regHistsTH1F.push_back(&m_hist_Hlt_result_size_express);
-
-
-  // *-- HLT result size plot (Stream calibration, DataScouting results)
-  m_hist_Hlt_result_size_DataScouting = 
-    new TH1F ((m_histProp_Hlt_result_size_DataScouting.value().title()).c_str(),
-              (m_histProp_Hlt_result_size_DataScouting.value().title() + ";words;entries").c_str(),
-              m_histProp_Hlt_result_size_DataScouting.value().bins(),
-              m_histProp_Hlt_result_size_DataScouting.value().lowEdge(),
-              m_histProp_Hlt_result_size_DataScouting.value().highEdge());
-
-  regHistsTH1F.push_back(&m_hist_Hlt_result_size_DataScouting);
-
-
-  // *-- HLT result size profile plot for all stream types "physics"
-  m_hist_HltResultSizes_Stream_physics = new TProfile( "Average Hlt Result size for physics streams",
-                                                       "Average Hlt Result size for physics streams;Stream Name;Average size in words",
-                                                       1,
-                                                       (double) 0., (double) 1.,
-                                                       (double) 0., (double) 3000000.);
-
-  m_hist_HltResultSizes_Stream_physics->GetXaxis()->SetBinLabel(1, "NoTag");
-  m_hist_HltResultSizes_Stream_physics->SetCanExtend(TH1::kAllAxes);
-  regHistsTProfile.push_back(&m_hist_HltResultSizes_Stream_physics);
-
-  // *-- HLT result size profile plot for all stream names "DataScouting"
-  m_hist_HltResultSizes_Stream_DataScouting = new TProfile( "Average Hlt Result size for data scouting streams",
-                                                            "Average Hlt Result size for data scouting streams;Stream Name;Average size in words",
-                                                            1,
-                                                            (double) 0., (double) 1.,
-                                                            (double) 0., (double) 3000000.);
-
-  m_hist_HltResultSizes_Stream_DataScouting->GetXaxis()->SetBinLabel(1, "NoTag");
-  m_hist_HltResultSizes_Stream_DataScouting->SetCanExtend(TH1::kAllAxes);
-  regHistsTProfile.push_back(&m_hist_HltResultSizes_Stream_DataScouting);
-
-  //     +-----------------------+
-  // *-- | framework error codes |
-  //     +-----------------------+
-  uint32_t n_bins_error = hltonl::NUM_PSC_ERROR_CODES;
-  m_hist_frameworkErrorCodes = new TH1F ("FrameworkErrorCodes",
-                                         "FrameworkErrorCodes;;entries", 
-                                         n_bins_error, 0.5, n_bins_error+0.5);
-
-  for (const auto& m : m_mapPscError) {
-    m_hist_frameworkErrorCodes->GetXaxis()->SetBinLabel( m.second.second , (m.second.first).c_str() );
+    ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+    return StatusCode::SUCCESS;
   }
-  regHistsTH1F.push_back(&m_hist_frameworkErrorCodes);
-  
-  //     +-------------+
-  // *-- | Stream Tags |
-  //     +-------------+
-  // *-- number of set stream tags
-  m_hist_numStreamTags = new TH1F ((m_histProp_numStreamTags.value().title()).c_str(),
-                                   (m_histProp_numStreamTags.value().title() + ";tags;entries").c_str(),
-                                   m_histProp_numStreamTags.value().bins(),
-                                   m_histProp_numStreamTags.value().lowEdge(),
-                                   m_histProp_numStreamTags.value().highEdge());
-  regHistsTH1F.push_back(&m_hist_numStreamTags);
-
-
-  // *-- stream tag types
-  uint32_t n_bins_tag = eformat::helper::TagTypeDictionary.size() + 1;
-  m_hist_streamTagTypes = new TH1F ("StreamTagTypes",
-                                    "StreamTagTypes;tags;entries", n_bins_tag, -0.5 , n_bins_tag-0.5);
-  
-  using eformat::helper::tagtype_to_string;
-  for(uint32_t i=0; i < n_bins_tag; i++ ) { // StreamTag labels
-    uint32_t bit = (1u << i);
-    m_hist_streamTagTypes->GetXaxis()->SetBinLabel( i+1, tagtype_to_string( static_cast<eformat::TagType>(bit) ).c_str() );
+  catch(const ptree_bad_path & e)
+  {
+    ATH_MSG_ERROR(ST_WHERE << "Bad ptree path: \"" << e.path<ptree::path_type>().dump() << "\" - " << e.what());
   }
-  m_hist_streamTagTypes->GetXaxis()->SetBinLabel(n_bins_tag, "NoTag(=Rejected)");
-  regHistsTH1F.push_back(&m_hist_streamTagTypes);
-
-
-  // *-- stream tag names
-  m_hist_streamTagNames = new TH1F ((m_histProp_streamTagNames.value().title()).c_str(),
-                                    (m_histProp_streamTagNames.value().title() + ";tags;entries").c_str(),
-                                    m_histProp_streamTagNames.value().bins(),
-                                    m_histProp_streamTagNames.value().lowEdge(),
-                                    m_histProp_streamTagNames.value().highEdge());
-  if (m_histProp_streamTagNames.value().bins()>0) {
-    m_hist_streamTagNames->GetXaxis()->SetBinLabel(1,std::string("NoTag").c_str() );
+  catch(const ptree_bad_data & e)
+  {
+    ATH_MSG_ERROR(ST_WHERE << "Bad ptree data: \"" << e.data<ptree::data_type>() << "\" - " << e.what());
   }
-  m_hist_streamTagNames->SetCanExtend(TH1::kAllAxes);
-  regHistsTH1F.push_back(&m_hist_streamTagNames);
-
-  //     +------------------------+
-  // *-- | Partial event building |
-  //     +------------------------+
-  // *-- number of bins for sub detector plots (55 SubDet max.)
-  uint32_t n_bins_partEBSubDet = eformat::helper::SubDetectorDictionary.size();
-
-  // *-- number of ROBs for partial event building
-  m_hist_num_partial_eb_robs = new TH1F ((m_histProp_num_partial_eb_robs.value().title()).c_str(),
-                                         (m_histProp_num_partial_eb_robs.value().title() + ";robs;entries").c_str(),
-                                         m_histProp_num_partial_eb_robs.value().bins(),
-                                         m_histProp_num_partial_eb_robs.value().lowEdge(),
-                                         m_histProp_num_partial_eb_robs.value().highEdge());
-
-  regHistsTH1F.push_back(&m_hist_num_partial_eb_robs);
-
-
-  // *-- number of SubDetectors used in partial event building
-  m_hist_num_partial_eb_SubDetectors = new TH1F ("NumberSubDetectorsPartialEB",
-                                                 "NumberSubDetectorsPartialEB;subdet;entries",
-                                                 n_bins_partEBSubDet,-0.5,(float) n_bins_partEBSubDet-0.5);
-  regHistsTH1F.push_back(&m_hist_num_partial_eb_SubDetectors);
-
-  // *-- SubDetectors used in partial event building: ROB list
-  m_hist_partial_eb_SubDetectors_ROBs = new TH1F ("SubDetectorsPartialEBFromROBList",
-                                                  "SubDetectorsPartialEBFromROBList;;entries",
-                                                  n_bins_partEBSubDet,0.,(float) n_bins_partEBSubDet);
-  uint32_t n_tmp_bin = 1;
-  for (const auto& sub : eformat::helper::SubDetectorDictionary) {
-    m_hist_partial_eb_SubDetectors_ROBs->GetXaxis()->SetBinLabel( n_tmp_bin++, sub.second.c_str() );
+  catch(const std::runtime_error& e)
+  {
+    ATH_MSG_ERROR(ST_WHERE << "Runtime error: " << e.what());
   }
-  regHistsTH1F.push_back(&m_hist_partial_eb_SubDetectors_ROBs);
 
-  // *-- SubDetectors used in partial event building: SD list
-  m_hist_partial_eb_SubDetectors_SDs = new TH1F ("SubDetectorsPartialEBFromSDList",
-                                                 "SubDetectorsPartialEBFromSDList;;entries",
-                                                 n_bins_partEBSubDet,0.,(float) n_bins_partEBSubDet);
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::FAILURE;
+}
+
+// =============================================================================
+// Implementation of ITrigEventLoopMgr::hltUpdateAfterFork
+// =============================================================================
+StatusCode HltEventLoopMgr::hltUpdateAfterFork(const ptree& /*pt*/)
+{
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
 
-  n_tmp_bin = 1;
-  for (const auto& sub: eformat::helper::SubDetectorDictionary) {
-    m_hist_partial_eb_SubDetectors_SDs->GetXaxis()->SetBinLabel( n_tmp_bin++, sub.second.c_str() );
-  }
-  regHistsTH1F.push_back(&m_hist_partial_eb_SubDetectors_SDs);
-
-
-  //     +---------------+
-  // *-- | HLT EDM Sizes |
-  //     +---------------+
-  // *-- EDM sizes for all events without a truncated HLT result
-  m_hist_HltEdmSizes_No_Truncation = 
-    new TProfile( (m_histProp_Hlt_Edm_Sizes.value().title()+":Events_Without_Truncation").c_str(),
-                  (m_histProp_Hlt_Edm_Sizes.value().title()+":Events_Without_Truncation;;Average size in words").c_str(),
-                  m_histProp_Hlt_Edm_Sizes.value().bins(), 0., m_histProp_Hlt_Edm_Sizes.value().bins(),
-                  m_histProp_Hlt_Edm_Sizes.value().lowEdge(), m_histProp_Hlt_Edm_Sizes.value().highEdge());
-
-  n_tmp_bin = 1;
-  for (const std::string& col_name : m_hltEdmCollectionNames.value()) {
-    m_hist_HltEdmSizes_No_Truncation->GetXaxis()->SetBinLabel( n_tmp_bin++, col_name.c_str() );
-  }
-  regHistsTProfile.push_back(&m_hist_HltEdmSizes_No_Truncation);
-
-  // *-- EDM sizes for all events with a truncated HLT result
-  m_hist_HltEdmSizes_With_Truncation = 
-    new TProfile( (m_histProp_Hlt_Edm_Sizes.value().title()+":Events_With_Truncation").c_str(),
-                  (m_histProp_Hlt_Edm_Sizes.value().title()+":Events_With_Truncation;;Average size in words").c_str(),
-                  m_histProp_Hlt_Edm_Sizes.value().bins(), 0., m_histProp_Hlt_Edm_Sizes.value().bins(),
-                  m_histProp_Hlt_Edm_Sizes.value().lowEdge(), m_histProp_Hlt_Edm_Sizes.value().highEdge());
-
-  n_tmp_bin = 1;
-  for (const std::string& col_name : m_hltEdmCollectionNames.value()) {
-    m_hist_HltEdmSizes_With_Truncation->GetXaxis()->SetBinLabel( n_tmp_bin++, col_name.c_str() );
-  }
-  regHistsTProfile.push_back(&m_hist_HltEdmSizes_With_Truncation);
-
-  // *-- Sizes of collections which were retained for events with a truncated HLT result
-  m_hist_HltEdmSizes_TruncatedResult_Retained_Collections = 
-    new TProfile( "Events_With_HLTResult_Truncation:Size_of_Not_Truncated_Collections",
-                  "Events_With_HLTResult_Truncation:Size_of_Not_Truncated_Collections;;Average size in words",
-                  m_histProp_Hlt_Edm_Sizes.value().bins(), 0., m_histProp_Hlt_Edm_Sizes.value().bins(),
-                  m_histProp_Hlt_Edm_Sizes.value().lowEdge(), m_histProp_Hlt_Edm_Sizes.value().highEdge());
-
-  n_tmp_bin = 1;
-  for (const std::string& col_name : m_hltEdmCollectionNames.value()) {
-    m_hist_HltEdmSizes_TruncatedResult_Retained_Collections->GetXaxis()->SetBinLabel( n_tmp_bin++, col_name.c_str() );
+  ATH_MSG_DEBUG("Initialising the scheduler after forking");
+  m_schedulerSvc = serviceLocator()->service(m_schedulerName, /*createIf=*/ true);
+  if ( !m_schedulerSvc.isValid()){
+    ATH_MSG_FATAL("Error retrieving " << m_schedulerName << " interface ISchedulerSvc");
+    return StatusCode::FAILURE;
   }
-  regHistsTProfile.push_back(&m_hist_HltEdmSizes_TruncatedResult_Retained_Collections);
-
-  // *-- Sizes of collections which were truncated for events with a truncated HLT result
-  m_hist_HltEdmSizes_TruncatedResult_Truncated_Collections = 
-    new TProfile( "Events_With_HLTResult_Truncation:Size_of_Truncated_Collections",
-                  "Events_With_HLTResult_Truncation:Size_of_Truncated_Collections;;Average size in words",
-                  m_histProp_Hlt_Edm_Sizes.value().bins(), 0., m_histProp_Hlt_Edm_Sizes.value().bins(),
-                  m_histProp_Hlt_Edm_Sizes.value().lowEdge(),
-                  m_histProp_Hlt_Edm_Sizes.value().highEdge());
-
-  n_tmp_bin = 1;
-  for (const std::string& col_name : m_hltEdmCollectionNames.value()) {
-    m_hist_HltEdmSizes_TruncatedResult_Truncated_Collections->GetXaxis()->SetBinLabel( n_tmp_bin++, col_name.c_str() );
+  ATH_MSG_DEBUG("Initialised " << m_schedulerName << " interface ISchedulerSvc");
+
+  ATH_MSG_DEBUG("Trying a stop-start of CoreDumpSvc");
+  SmartIF<IService> svc = serviceLocator()->service("CoreDumpSvc", /*createIf=*/ false);
+  if (svc.isValid()) {
+    svc->stop();
+    svc->start();
+    ATH_MSG_DEBUG("Done a stop-start of CoreDumpSvc");
   }
-  regHistsTProfile.push_back(&m_hist_HltEdmSizes_TruncatedResult_Truncated_Collections);
-
-  //     +---------------------+
-  // *-- | register histograms |
-  //     +---------------------+
-  // *-- TH1F
-  for (TH1F** hist : regHistsTH1F) {
-    if ( *hist && m_THistSvc->regHist(histPath + (*hist)->GetName(), (*hist)).isFailure() ) {
-      msgStream() << MSG::WARNING << "Cannot register histogram " << (*hist)->GetName() << endmsg;
-      delete (*hist);
-      *hist = 0;
-    }
+  else {
+    ATH_MSG_WARNING("Could not retrieve CoreDumpSvc");
   }
-  // *-- TProfile
-  for (TProfile** hist : regHistsTProfile) {
-    if ( *hist && m_THistSvc->regHist(histPath + (*hist)->GetName(), (*hist)).isFailure() ) {
-      msgStream() << MSG::WARNING << "Cannot register histogram " << (*hist)->GetName() << endmsg;
-      delete (*hist);
-      *hist = 0;
-    }
+
+  // Start the timeout thread
+  ATH_MSG_DEBUG("Starting the timeout thread");
+  m_timeoutThread.reset(new std::thread(std::bind(&HltEventLoopMgr::runEventTimer,this)));
+
+  // Initialise vector of time points for event timeout monitoring
+  {
+    std::unique_lock<std::mutex> lock(m_timeoutMutex);
+    m_eventTimerStartPoint.clear();
+    m_eventTimerStartPoint.resize(m_whiteboard->getNumberOfStores(), std::chrono::steady_clock::time_point());
+    m_isSlotProcessing.resize(m_whiteboard->getNumberOfStores(), false);
   }
+  m_timeoutCond.notify_all();
+
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
 }
 
-//=========================================================================
-void HltEventLoopMgr::HltBookHistograms()
+// =============================================================================
+// Implementation of IEventProcessor::executeRun
+// =============================================================================
+StatusCode HltEventLoopMgr::executeRun(int maxevt)
 {
-  if ( msgLevel() <= MSG::DEBUG ) {
-    msgStream() << MSG::DEBUG << "---> HltBookHistograms() for " << name()
-        << " called. Do monitoring = " << m_doMonitoring.value() << endmsg;
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  StatusCode sc = nextEvent(maxevt);
+  if (sc.isFailure()) {
+    ATH_MSG_ERROR("Event loop failed");
+    // some special cleanup here?
   }
 
-  // return if no monitoring is requested
-  if ( !m_doMonitoring.value() ) { return; }
+  // do some cleanup here
 
-  // monitoring information root directory
-  std::string path = std::string("/EXPERT/") + name() + "/";
-
-  // *-- SubDetectors from l1 ROBs
-  auto nbins = L1R_BINS.size() + 2;
-  m_hist_l1_robs = new TH1F ("HLTROBsReceivedFromL1",
-                             "HLTROBsReceivedFromL1;;entries",
-                             nbins,
-                             0.,
-                             static_cast<double>(nbins));
-
-  // Set labels from L1R_BINS
-  unsigned short i = 0;
-  while(i < L1R_BINS.size())
+  // Stop the timer thread
   {
-    auto sid = eformat::helper::SourceIdentifier(L1R_BINS[i], 0);
-    m_hist_l1_robs->GetXaxis()->SetBinLabel(++i, sid.human_detector().c_str());
+    ATH_MSG_DEBUG("Stopping the timeout thread");
+    std::unique_lock<std::mutex> lock(m_timeoutMutex);
+    m_runEventTimer = false;
   }
+  m_timeoutCond.notify_all();
+  m_timeoutThread->join();
+  ATH_MSG_DEBUG("The timeout thread finished");
 
-  // Add a label for unexpected robs and another for missing CTP fragment
-  m_hist_l1_robs->GetXaxis()->SetBinLabel(++i, UNEXPECTED_L1R_ROB_LABEL);
-  m_hist_l1_robs->GetXaxis()->SetBinLabel(++i, MISSING_L1R_CTP_LABEL);
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return sc;
+}
 
-  // Register it
-  if(m_THistSvc->regHist(path + m_hist_l1_robs->GetName(), m_hist_l1_robs).isFailure())
-  {
-    msgStream() << MSG::WARNING << "Can not register monitoring histogram: "
-                << m_hist_l1_robs->GetName() << endmsg;
-  }
-} //  end method HltEventLoopMgr::HltBookHistograms
+// =============================================================================
+// Implementation of IEventProcessor::nextEvent
+// maxevt is not used - we always want to process all events delivered
+// =============================================================================
+StatusCode HltEventLoopMgr::nextEvent(int /*maxevt*/)
+{
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+
+  ATH_MSG_INFO("Starting loop on events");
+  bool loop_ended = false;
+  bool events_available = true; // DataCollector has more events
+
+  while (!loop_ended) {
+    ATH_MSG_DEBUG("Free slots = " << m_schedulerSvc->freeSlots());
+    if (m_schedulerSvc->freeSlots()>0 && events_available) {
+      ATH_MSG_DEBUG("Free slots = " << m_schedulerSvc->freeSlots() << ". Reading the next event.");
+
+      eformat::write::FullEventFragment l1r; // to be removed
+
+      //------------------------------------------------------------------------
+      // Create new EventContext
+      //------------------------------------------------------------------------
+      ++m_nevt;
+      EventContext* evtContext = nullptr;
+      if (createEventContext(evtContext).isFailure()){
+        ATH_MSG_ERROR("Failed to create event context");
+        // what do we do now? we haven't requested the next event from DataCollector yet,
+        // we have a failure while not processing an event
+        failedEvent(evtContext);
+        continue;
+      }
 
-//=========================================================================
-void HltEventLoopMgr::fillHltResultHistograms(const hltinterface::HLTResult& hlt_result)
-{
-  if ( msgLevel() <= MSG::DEBUG ) {
-    msgStream() << MSG::DEBUG << "---> fillHltResultHistograms(hltinterface::HLTResult& hlt_result) for " << name() << " called " << endmsg;
-  }
+      // do we need this duplication? it's selected already in createEventContext
+      if (m_whiteboard->selectStore(evtContext->slot()).isFailure()){
+        ATH_MSG_ERROR("Slot " << evtContext->slot() << " could not be selected for the WhiteBoard");
+        // what do we do now? we haven't requested the next event from DataCollector yet,
+        // we have a failure while not processing an event
+        failedEvent(evtContext);
+        continue;
+      }
 
-  // return if no monitoring is requested
-  if ( !m_doMonitoring.value() ) { return; }
+      // Record EventContext in current whiteboard
+      if (m_evtStore->record(std::make_unique<EventContext> (*evtContext), "EventContext").isFailure()) {
+        ATH_MSG_ERROR("Error recording event context object");
+        // what do we do now? we haven't requested the next event from DataCollector yet,
+        // we have a failure while not processing an event
+        failedEvent(evtContext);
+        continue;
+      }
 
-  //     +-----------------------+
-  // *-- | HLT result properties |
-  //     +-----------------------+
-  if ( (hlt_result.fragment_pointer != 0) && ( (*hlt_result.fragment_pointer) != 0 ) ) {
-    eformat::ROBFragment<uint32_t*> hltrob(hlt_result.fragment_pointer);
-    uint16_t hltrob_moduleID = eformat::helper::SourceIdentifier( hltrob.rob_source_id() ).module_id();
+      // Not so nice behind-the-scenes way to inform some services about the current context.
+      // If possible, services should use EventContext from the event store as recorded above.
+      Gaudi::Hive::setCurrentContext(*evtContext);
+
+      //------------------------------------------------------------------------
+      // Create a new address for EventInfo to facilitate automatic conversion from input data
+      //------------------------------------------------------------------------
+      IOpaqueAddress* addr = nullptr;
+      if (m_evtSelector->createAddress(*m_evtSelContext, addr).isFailure()) {
+        ATH_MSG_ERROR("Could not create an IOpaqueAddress");
+        // we have not read a new event yet, should we try to create any output?
+        failedEvent(evtContext);
+        continue;
+      }
 
-    // *-- HLT result size plots
-    if (hltrob_moduleID == 0) {
-      lock_histogram_operation<TH1F>(m_hist_Hlt_result_size)->Fill( (float) hltrob.fragment_size_word() ) ;
-    }
+      //------------------------------------------------------------------------
+      // Get the next event
+      //------------------------------------------------------------------------
+      StatusCode sc = StatusCode::SUCCESS;
+      try {
+        sc = m_evtSelector->next(*m_evtSelContext);
+      }
+      catch (const hltonl::Exception::NoMoreEvents& e) {
+        sc = StatusCode::SUCCESS;
+        events_available = false;
+        sc = clearWBSlot(evtContext->slot());
+        if (sc.isFailure()) {
+          ATH_MSG_WARNING("Failed to clear the whiteboard slot " << evtContext->slot()
+                          << " after NoMoreEvents detected");
+          // do we need to do anything here?
+        }
+        continue;
+      }
+      catch (...) {
+        sc = StatusCode::FAILURE;
+      }
+      if (sc.isFailure()) {
+        ATH_MSG_ERROR("Failed to get the next event");
+        // we called getNext and some failure happened, but we don't know the event number
+        // should we return anything to the DataCollector?
+        failedEvent(evtContext);
+        continue;
+      }
 
-    int xbins_physics = m_hist_HltResultSizes_Stream_physics->GetNbinsX();
-    int xbins_DS = m_hist_HltResultSizes_Stream_DataScouting->GetNbinsX();
-    {
-      scoped_lock_histogram lock;
-      for (const eformat::read::ROBFragment& rob : hlt_result.hltResult_robs) {
-        uint16_t moduleID = eformat::helper::SourceIdentifier( rob.rob_source_id() ).module_id();
-        for (const eformat::helper::StreamTag& st : hlt_result.stream_tag) {
-          // only normal HLT Results
-          if (moduleID == 0) {
-            if (st.type == "physics") {
-              if (st.name == "Main") m_hist_Hlt_result_size_physics->Fill( (float) rob.fragment_size_word() ) ;
-              m_hist_HltResultSizes_Stream_physics->Fill( st.name.c_str(), (double) rob.fragment_size_word() ) ;
-            }
-            if (st.type == "express") {
-              m_hist_Hlt_result_size_express->Fill( (float) rob.fragment_size_word() ) ;
-            }
-          }
-          // DataScouting HLT ROBs
-          if (moduleID != 0) {
-            if ((st.type == "calibration") && ((st.name).find("DataScouting_") != std::string::npos)) {
-              m_hist_Hlt_result_size_DataScouting->Fill( (float) rob.fragment_size_word() ) ;
-              m_hist_HltResultSizes_Stream_DataScouting->Fill( st.name.c_str(), (double) rob.fragment_size_word() ) ;
-            }
-          }
+      //------------------------------------------------------------------------
+      // Set event processing start time for timeout monitoring and reset timeout flag
+      //------------------------------------------------------------------------
+      {
+        std::unique_lock<std::mutex> lock(m_timeoutMutex);
+        m_eventTimerStartPoint[evtContext->slot()] = std::chrono::steady_clock::now();
+        m_isSlotProcessing[evtContext->slot()] = true;
+        resetTimeout(Athena::Timeout::instance(*evtContext));
+      }
+      m_timeoutCond.notify_all();
+
+      //------------------------------------------------------------------------
+      // Load event proxies and get event info
+      //------------------------------------------------------------------------
+
+      if (addr != nullptr) {
+        /* do we need this???
+        sc = m_evtStore->recordAddress(addr);
+        if (sc.isFailure()) {
+          ATH_MSG_WARNING("Failed to record IOpaqueAddress in the event store");
+          // we cannot get the EventInfo, so we don't know the event number
+          // should we return anything to the DataCollector?
+          // failedEvent(evtContext);
         }
-    }
+        */
+        sc = m_evtStore->loadEventProxies();
+        if (sc.isFailure()) {
+          ATH_MSG_ERROR("Failed to load event proxies");
+          // we cannot get the EventInfo, so we don't know the event number
+          // should we return anything to the DataCollector?
+          failedEvent(evtContext);
+        }
+      }
 
-      // deflate bins for profile histograms if needed
-      if ( m_hist_HltResultSizes_Stream_physics->GetNbinsX()!=xbins_physics ) {
-        m_hist_HltResultSizes_Stream_physics->LabelsDeflate("X");
+      const EventInfo* oldEventInfo = nullptr;
+      sc = m_evtStore->retrieve(oldEventInfo);
+      if (sc.isFailure()) {
+        ATH_MSG_ERROR("Failed to retrieve EventInfo");
+        // we cannot get the EventInfo, so we don't know the event number
+        // should we return anything to the DataCollector?
+        failedEvent(evtContext);
       }
-      if ( m_hist_HltResultSizes_Stream_DataScouting->GetNbinsX()!=xbins_DS ) {
-        m_hist_HltResultSizes_Stream_DataScouting->LabelsDeflate("X");
+
+      // convert EventInfo to xAOD::EventInfo using a cnv tool explicitly, like in EventInfoCnvAlg
+      // - this should be done by an automatic conversion through proxy in the future,
+      // replacing the code above and below
+      SG::WriteHandle<xAOD::EventInfo> eventInfoWH(m_xEventInfoWHKey, *evtContext);
+      if (eventInfoWH.record(
+        std::make_unique<xAOD::EventInfo>(),
+        std::make_unique<xAOD::EventAuxInfo>()
+      ).isFailure()) {
+        ATH_MSG_ERROR("Failed to record xAOD::EventInfo in event store");
+        failedEvent(evtContext);
       }
-    }
 
-    // *-- HLT result status codes
-    if ((hltrob.nstatus() > 1) && (hltrob_moduleID == 0)) {
-      scoped_lock_histogram lock;
-      const uint32_t* it;
-      hltrob.status(it);
-      m_hist_Hlt_result_status->Fill( (float) m_mapResultStatus.codeToHash( (hltonl::ResultStatusCode) *(it+1)) );
-    }
-  }
+      xAOD::EventInfo* eventInfo = eventInfoWH.ptr();
+      if (m_eventInfoCnvTool->convert(oldEventInfo, eventInfo).isFailure()) {
+        ATH_MSG_ERROR("Failed to convert EventInfo to xAOD::EventInfo");
+        failedEvent(evtContext);
+      }
 
-  //     +-----------------------+
-  // *-- | framework error codes |
-  //     +-----------------------+
-  if (hlt_result.psc_errors.size() > 0)  {
-    scoped_lock_histogram lock;
-    for (uint32_t ec : hlt_result.psc_errors) {
-      m_hist_frameworkErrorCodes->Fill( (float) m_mapPscError.codeToHash( (hltonl::PSCErrorCode) ec) );
-    }
-  }
+      ATH_MSG_DEBUG("Retrieved event info for the new event " << *eventInfo);
+
+      // create EventIDBase for the EventContext
+      EventIDBase eid(eventInfo->runNumber(),
+                      eventInfo->eventNumber(),
+                      eventInfo->timeStamp(),
+                      eventInfo->timeStampNSOffset(),
+                      eventInfo->lumiBlock(),
+                      eventInfo->bcid());
+      evtContext->setEventID(eid);
+
+      // set run number for conditions
+      evtContext->template getExtension<Atlas::ExtendedEventContext>()->setConditionsRun(m_currentRun);
+
+      // update thread-local EventContext after setting EventID and conditions runNumber
+      Gaudi::Hive::setCurrentContext(*evtContext);
+
+      //------------------------------------------------------------------------
+      // Record an empty HLT Result
+      //------------------------------------------------------------------------
+      // auto hltResult = new HLT::HLTResultMT;
+      // hltResult->getExtraData().appName = m_applicationName.value();
+      // m_evtStore->record(hltResult, m_HltResultName, /*allowMods=*/ true);
+
+      //------------------------------------------------------------------------
+      // Process the event
+      //------------------------------------------------------------------------
+      if (executeEvent(evtContext).isFailure()) {
+        ATH_MSG_ERROR("Error processing event");
+        failedEvent(evtContext,eventInfo);
+        continue;
+      }
 
-  //     +-------------+
-  // *-- | Stream Tags |
-  //     +-------------+
-  //     number of set stream tags
-  m_hist_numStreamTags->Fill( (float) hlt_result.stream_tag.size() );
+      //------------------------------------------------------------------------
+      // Set ThreadLocalContext to an invalid context
+      //------------------------------------------------------------------------
+      // We have passed the event to the scheduler and we are entering back a context-less environment
+      Gaudi::Hive::setCurrentContext( EventContext() );
 
-  //     stream tag types
-  if(hlt_result.stream_tag.empty()) {
-    m_hist_streamTagTypes->Fill( (float) m_hist_streamTagTypes->GetXaxis()->GetNbins() - 1. );
-  }
-  using namespace eformat::helper;
-  for(int32_t i=0; i < m_hist_streamTagTypes->GetXaxis()->GetNbins(); i++) {
-    uint32_t bit = (1u<<i);
-    if( contains_type(hlt_result.stream_tag, static_cast<eformat::TagType>(bit)) ) {
-      m_hist_streamTagTypes->Fill( (float) i);
     }
-  }
-
-  //     stream tag names
-  if(hlt_result.stream_tag.empty()) {
-    m_hist_streamTagNames->Fill(0.);
-  } else {
-    int xbins = m_hist_streamTagNames->GetNbinsX();
-    scoped_lock_histogram lock;      
-    for(const eformat::helper::StreamTag& st: hlt_result.stream_tag) {
-      m_hist_streamTagNames->Fill(st.name.c_str(),1.);
+    else {
+      ATH_MSG_DEBUG("No free slots or no more events to process - draining the scheduler");
+      int ir = drainScheduler();
+      if (ir<0) {
+        ATH_MSG_ERROR("Error draining scheduler");
+        continue;
+      }
+      else if (ir==0 && !events_available) {
+        ATH_MSG_INFO("All events processed, finalising the event loop");
+        loop_ended = true;
+      }
     }
-    // Remove extra empty bins if needed
-    if ( m_hist_streamTagNames->GetNbinsX()!=xbins )
-      m_hist_streamTagNames->LabelsDeflate("X");
-  }
-
-  //     +------------------------+
-  // *-- | Partial Event Building |
-  //     +------------------------+
-  // *-- loop over stream tags and get total number of ROBs and SDs
-  uint32_t num_robs(0), num_sd(0);
-  std::set<uint32_t> peb_robs;
-  std::set<eformat::SubDetector> peb_sd;
-  for (const eformat::helper::StreamTag& st : hlt_result.stream_tag) {
-    num_robs = num_robs + (st.robs).size();
-    num_sd = num_sd + (st.dets).size();
-    peb_robs.insert( (st.robs).begin(),(st.robs).end() );
-    peb_sd.insert(   (st.dets).begin(),(st.dets).end() );
   }
 
-  // *-- number of ROBs for partial event building
-  m_hist_num_partial_eb_robs->Fill( (float) num_robs);
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
 
-  // *-- number of SubDetectors for partial event building
-  m_hist_num_partial_eb_SubDetectors->Fill( (float) num_sd);
+// =============================================================================
+// Implementation of IEventProcessor::stopRun (obsolete for online runnning)
+// =============================================================================
+StatusCode HltEventLoopMgr::stopRun() {
+  ATH_MSG_FATAL("Misconfiguration - the method HltEventLoopMgr::stopRun() cannot be used online");
+  return StatusCode::FAILURE;
+}
 
-  // *-- SubDetectors for partial event building in ROB list
-  for(uint32_t rob : peb_robs) {
-    m_hist_partial_eb_SubDetectors_ROBs->Fill(eformat::helper::SourceIdentifier(rob).human_detector().c_str(),1.);
-  }  
+// =============================================================================
+// Implementation of IEventProcessor::executeEvent
+// =============================================================================
+StatusCode HltEventLoopMgr::executeEvent(void* pEvtContext)
+{
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
 
-  // *-- SubDetectors for partial event building in SD list
-  for (const eformat::SubDetector& sd : peb_sd) {
-    m_hist_partial_eb_SubDetectors_SDs->Fill(eformat::helper::SourceIdentifier(sd,0).human_detector().c_str(),1.);
+  EventContext* evtContext = static_cast<EventContext*>(pEvtContext);
+  if (!evtContext) {
+    ATH_MSG_ERROR("Failed to cast the call parameter to EventContext*");
+    return StatusCode::FAILURE;
   }
 
-  return;
-} // end method HltEventLoopMgr::fillHltResultHistograms
+  resetTimeout(Athena::Timeout::instance(*evtContext));
 
-//=========================================================================
-void HltEventLoopMgr::bookAllHistograms()
-{
-  // Book the monitoring histograms
-  HltBookHistograms(); // (histograms that were booked differently in l2/ef)
-  // Book own histograms
-  bookHistograms();
-}
+  // Now add event to the scheduler
+  ATH_MSG_DEBUG("Adding event " << evtContext->evt() << ", slot " << evtContext->slot() << " to the scheduler");
+  StatusCode addEventStatus = m_schedulerSvc->pushNewEvent(evtContext);
 
-//=========================================================================
-StatusCode
-HltEventLoopMgr::callOnAlgs(const function<StatusCode(IAlgorithm&)> & func,
-                            const string & fname, bool failureIsError)
-{
-  StatusCode sc;
-  for(auto alg : m_topAlgList)
-  {
-    if(func(*alg).isFailure())
-    {
-      msgStream() << (failureIsError ? MSG::ERROR : MSG::WARNING) << ST_WHERE
-                  << "Calling " << fname << "() on algorithm " << alg->name()
-                  << " failed" << endmsg;
-      sc = StatusCode::FAILURE;
-      if(failureIsError)
-        break;
-    }
+  // If this fails, we need to wait for something to complete
+  if (!addEventStatus.isSuccess()){
+    ATH_MSG_ERROR("Failed adding event " << evtContext->evt() << ", slot " << evtContext->slot()
+                  << " to the scheduler");
+    return StatusCode::FAILURE;
   }
 
-  return sc;
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
 }
 
-//=========================================================================
-StatusCode HltEventLoopMgr::prepareAlgs(const EventInfo& evinfo)
+// =============================================================================
+void HltEventLoopMgr::updateDFProps()
 {
-  auto suc1 = callOnAlgs(&IAlgorithm::sysStart, "sysStart").isSuccess();
-  m_incidentSvc->fireIncident(EventIncident(evinfo, name(),
-                                            IncidentType::BeginRun));
-  auto suc2 = callOnAlgs(&IAlgorithm::sysBeginRun, "sysBeginRun").isSuccess();
-  m_incidentSvc->fireIncident(EventIncident(evinfo, name(), "EndOfBeginRun"));
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  ServiceHandle<IJobOptionsSvc> p_jobOptionsSvc("JobOptionsSvc", name());
+  if ((p_jobOptionsSvc.retrieve()).isFailure()) {
+    ATH_MSG_WARNING("Could not find JobOptionsSvc to set DataFlow properties");
+  } else {
+    auto dfprops = p_jobOptionsSvc->getProperties("DataFlowConfig");
 
-  return (suc1 && suc2) ? StatusCode::SUCCESS : StatusCode::FAILURE;
-}
+    // Application name
+    auto pname = "DF_ApplicationName";
+    const auto * prop = Gaudi::Utils::getProperty(dfprops, pname);
+    if(prop && m_applicationName.assign(*prop)) {
+      ATH_MSG_DEBUG(" ---> Read from DataFlow configuration: " << m_applicationName);
+    } else {
+      ATH_MSG_WARNING("Could not set Property '" << pname << "' from DataFlow");
+    }
 
-//=========================================================================
-StatusCode HltEventLoopMgr::internalPrepareResets()
-{
-  m_currentEvent = nullptr; // no time out would make sense here, so not locking
-  m_currentLB = 0;
-  if (m_predefinedLumiBlock > 0)
-  {
-    m_currentLB = m_predefinedLumiBlock;
-    msgStream() << MSG::DEBUG << ST_WHERE
-                << "Using predefined lumi block " << m_currentLB << endmsg;
-  }
+    // Partition name
+    pname = "DF_PartitionName";
+    prop = Gaudi::Utils::getProperty(dfprops, pname);
+    if (prop && m_partitionName.assign(*prop)) {
+      ATH_MSG_DEBUG(" ---> Read from DataFlow configuration: " << m_partitionName);
+    } else {
+      ATH_MSG_WARNING("Could not set Property '" << pname << "' from DataFlow");
+    }
+
+    // get the list of enabled ROBs
+    pname = "DF_Enabled_ROB_IDs";
+    prop = Gaudi::Utils::getProperty(dfprops, pname);
+    if (prop && m_enabledROBs.assign(*prop)) {
+      ATH_MSG_DEBUG(" ---> Read from DataFlow configuration: "
+                    << m_enabledROBs.value().size() << " enabled ROB IDs");
+    } else {
+      // this is only info, because it is normal in athenaHLT
+      ATH_MSG_INFO("Could not set Property '" << pname << "' from DataFlow");
+    }
 
-  // The real CTP counter only has 16 bits and never reaches this value
-  m_l1_hltPrescaleUpdateLB = 0xffffffff;
+    // get the list of enabled Sub Detectors
+    pname = "DF_Enabled_SubDet_IDs";
+    prop = Gaudi::Utils::getProperty(dfprops, pname);
+    if (prop && m_enabledSubDetectors.assign(*prop)) {
+      ATH_MSG_DEBUG(" ---> Read from DataFlow configuration: "
+                    << m_enabledSubDetectors.value().size() << " enabled Sub Detector IDs");
+    } else {
+      // this is only info, because it is normal in athenaHLT
+      ATH_MSG_INFO("Could not set Property '" << pname << "' from DataFlow");
+    }
+  }
 
-  return clearTemporaryStores();
+  p_jobOptionsSvc.release().ignore();
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
 }
 
-//=========================================================================
-const SOR * HltEventLoopMgr::processRunParams(const ptree & pt)
+// =============================================================================
+const SOR* HltEventLoopMgr::processRunParams(const ptree & pt)
 {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
   // update the run number
   m_currentRun = pt.get<uint32_t>("RunParams.run_number");
 
-  ATH_CHECK(installEventContext(nullptr, m_currentRun), nullptr);
+  // need to provide an event context extended with a run number, down the line passed to IOVDBSvc::signalBeginRun
+  EventContext runStartEventContext = {}; // with invalid evt number and slot number
+  runStartEventContext.setExtension(Atlas::ExtendedEventContext(m_evtStore->hiveProxyDict(), m_currentRun));
 
   // Fill SOR parameters from the ptree
   TrigSORFromPtreeHelper sorhelp{msgStream()};
-  auto sor = sorhelp.fillSOR(pt.get_child("RunParams"), m_eventContext);
-  if(!sor)
-    msgStream() << MSG::ERROR << ST_WHERE
-                << "setup of SOR from ptree failed" << endmsg;
+  const SOR* sor = sorhelp.fillSOR(pt.get_child("RunParams"),runStartEventContext);
+  if(!sor) {
+    ATH_MSG_ERROR(ST_WHERE << "setup of SOR from ptree failed");
+  }
 
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
   return sor;
 }
 
-//=========================================================================
-void HltEventLoopMgr::updInternal(const coral::AttributeList & sor_attrlist)
+// =============================================================================
+void HltEventLoopMgr::updateInternal(const coral::AttributeList & sor_attrlist)
 {
   auto detMaskFst = sor_attrlist["DetectorMaskFst"].data<unsigned long long>();
   auto detMaskSnd = sor_attrlist["DetectorMaskSnd"].data<unsigned long long>();
-  updDetMask({detMaskFst, detMaskSnd});
+  updateDetMask({detMaskFst, detMaskSnd});
 
-  auto sorTime = sor_attrlist["SORTime"].data<unsigned long long>();
-  updSorTime(sorTime);
+  // auto sorTime = sor_attrlist["SORTime"].data<unsigned long long>();
+  // updSorTime(sorTime);
 
   if(msgLevel() <= MSG::DEBUG)
   {
     // save current stream flags for later reset
     // cast needed (stream thing returns long, but doesn't take it back)
-    auto previous_stream_flags =
-        static_cast<std::ios::fmtflags>(msgStream().flags());
-    msgStream() << MSG::DEBUG << ST_WHERE
-                << "Full detector mask (128 bits) = 0x"
-                << MSG::hex << std::setfill('0')
-                << std::setw(8) << std::get<3>(m_detector_mask)
-                << std::setw(8) << std::get<2>(m_detector_mask)
-                << std::setw(8) << std::get<1>(m_detector_mask)
-                << std::setw(8) << std::get<0>(m_detector_mask) << endmsg;
+    auto previous_stream_flags = static_cast<std::ios::fmtflags>(msgStream().flags());
+    ATH_MSG_DEBUG(ST_WHERE
+                  << "Full detector mask (128 bits) = 0x"
+                  << MSG::hex << std::setfill('0')
+                  << std::setw(8) << std::get<3>(m_detector_mask)
+                  << std::setw(8) << std::get<2>(m_detector_mask)
+                  << std::setw(8) << std::get<1>(m_detector_mask)
+                  << std::setw(8) << std::get<0>(m_detector_mask));
     msgStream().flags(previous_stream_flags);
 
-    msgStream() << MSG::DEBUG << ST_WHERE
-                << "sorTimeStamp[0] [sec] = " << m_sorTime_stamp[0] << endmsg;
-    msgStream() << MSG::DEBUG << ST_WHERE
-                << "sorTimeStamp[1] [ns]  = " << m_sorTime_stamp[1] << endmsg;
+    // ATH_MSG_DEBUG(ST_WHERE << "sorTimeStamp[0] [sec] = " << m_sorTime_stamp[0]);
+    // ATH_MSG_DEBUG(ST_WHERE << "sorTimeStamp[1] [ns]  = " << m_sorTime_stamp[1]);
   }
 }
 
-//=========================================================================
-void HltEventLoopMgr::updMetadaStore(const coral::AttributeList & sor_attrlist)
+// =============================================================================
+void HltEventLoopMgr::updateMetadataStore(const coral::AttributeList & sor_attrlist) const
 {
   // least significant part is "snd" in sor but "fst" for ByteStreamMetadata
   auto bs_dm_fst = sor_attrlist["DetectorMaskSnd"].data<unsigned long long>();
@@ -2523,613 +963,416 @@ void HltEventLoopMgr::updMetadaStore(const coral::AttributeList & sor_attrlist)
     std::vector<std::string>());
 
   // Record ByteStreamMetadata in MetaData Store
-  if(m_inputMetaDataStore->record(metadata,"ByteStreamMetadata").isFailure())
-  {
-    msgStream() << MSG::WARNING << ST_WHERE
-                << "Unable to record MetaData in InputMetaDataStore."
-                << endmsg;
+  if(m_inputMetaDataStore->record(metadata,"ByteStreamMetadata").isFailure()) {
+    ATH_MSG_WARNING(ST_WHERE << "Unable to record MetaData in InputMetaDataStore");
     delete metadata;
   }
-  else
-    msgStream() << MSG::DEBUG << ST_WHERE
-                << "Recorded MetaData in InputMetaDataStore." << endmsg;
+  else {
+    ATH_MSG_DEBUG(ST_WHERE << "Recorded MetaData in InputMetaDataStore");
+  }
+
 }
 
-//=========================================================================
+// ==============================================================================
 StatusCode HltEventLoopMgr::clearTemporaryStores()
 {
-  //-----------------------------------------------------------------------
+  //----------------------------------------------------------------------------
   // Clear the event store, if used in the event loop
-  //-----------------------------------------------------------------------
+  //----------------------------------------------------------------------------
   auto sc = m_evtStore->clearStore();
-  msgStream() << MSG::DEBUG << ST_WHERE
-              << "clear of Event Store " << sc << endmsg;
+  ATH_MSG_DEBUG(ST_WHERE << "clear of Event Store " << sc);
   if(sc.isFailure()) {
-    msgStream() << MSG::ERROR << ST_WHERE
-                << "clear of Event Store failed" << endmsg;
+    ATH_MSG_ERROR(ST_WHERE << "clear of Event Store failed");
     return sc;
   }
 
-  //-----------------------------------------------------------------------
+  //----------------------------------------------------------------------------
   // Clear the InputMetaDataStore
-  //-----------------------------------------------------------------------
+  //----------------------------------------------------------------------------
   sc = m_inputMetaDataStore->clearStore();
-  msgStream() << MSG::DEBUG << ST_WHERE
-              << "clear of InputMetaDataStore store " << sc << endmsg;
+  ATH_MSG_DEBUG(ST_WHERE << "clear of InputMetaDataStore store " << sc);
   if(sc.isFailure())
-    msgStream() << MSG::ERROR << ST_WHERE
-                << "clear of InputMetaDataStore failed" << endmsg;
+    ATH_MSG_ERROR(ST_WHERE << "clear of InputMetaDataStore failed");
 
   return sc;
 }
 
-//=========================================================================
-void HltEventLoopMgr::updDetMask(const std::pair<uint64_t, uint64_t>& dm)
+// =============================================================================
+void HltEventLoopMgr::updateDetMask(const std::pair<uint64_t, uint64_t>& dm)
 {
   m_detector_mask = std::make_tuple(
-                        // least significant 4 bytes
-                        static_cast<EventID::number_type>(dm.second),
-                        // next least significant 4 bytes
-                        static_cast<EventID::number_type>(dm.second >> 32),
-                        // next least significant 4 bytes
-                        static_cast<EventID::number_type>(dm.first),
-                        // most significant 4 bytes
-                        static_cast<EventID::number_type>(dm.first >> 32));
+                      // least significant 4 bytes
+                      static_cast<EventID::number_type>(dm.second),
+                      // next least significant 4 bytes
+                      static_cast<EventID::number_type>(dm.second >> 32),
+                      // next least significant 4 bytes
+                      static_cast<EventID::number_type>(dm.first),
+                      // most significant 4 bytes
+                      static_cast<EventID::number_type>(dm.first >> 32)
+                    );
 }
 
-//=========================================================================
-void HltEventLoopMgr::updSorTime(unsigned long long st)
-{
-  m_sorTime_stamp[0]=0;
-  m_sorTime_stamp[1]=0;
-  if(st)
-  {
-    m_sorTime_stamp[0] = (unsigned int)(st/1000000000);
-    m_sorTime_stamp[1] = (unsigned int)(st-m_sorTime_stamp[0]*1000000000);
-  }
-}
-
-namespace
-{
-  // Helper to print SOR record
-  void printSORAttrList(const coral::AttributeList& atr,
-                        MsgStream& log, const MSG::Level& lvl)
-  {
-    unsigned long long sorTime_ns(atr["SORTime"].data<unsigned long long>());
-
-    // Human readable format of SOR time if available
-    time_t sorTime_sec = sorTime_ns/1000000000;
-    const auto sorTime_readable = OWLTime(sorTime_sec);
-
-    log << lvl << "SOR parameters:" << endmsg;
-    log << "   RunNumber        = "
-        << atr["RunNumber"].data<unsigned int>() << endmsg;
-    log << "   SORTime [ns]     = "
-        << sorTime_ns << " (" << sorTime_readable << ") " << endmsg;
-
-    // save current stream flags for later reset
-    // cast needed (stream thing returns long, but doesn't take it back)
-    auto previous_stream_flags = static_cast<std::ios::fmtflags>(log.flags());
-    auto dmfst = atr["DetectorMaskFst"].data<unsigned long long>();
-    auto dmsnd = atr["DetectorMaskSnd"].data<unsigned long long>();
-    log << MSG::hex << std::setfill('0');
-    log << "   DetectorMaskFst     = 0x" << std::setw(16) << dmfst << endmsg;
-    log << "   DetectorMaskSnd     = 0x" << std::setw(16) << dmsnd << endmsg;
-    log << "   (complete DetectorMask = 0x"
-        << std::setw(16) << dmfst << std::setw(16) << dmsnd << ")" << endmsg;
-    // reset stream flags
-    log.flags(previous_stream_flags);
-
-    log << "   RunType          = "
-        << atr["RunType"].data<std::string>() << endmsg;
-    log << "   RecordingEnabled = "
-        << (atr["RecordingEnabled"].data<bool>() ? "true" : "false") << endmsg;
-  }
-}
-
-//=========================================================================
-const coral::AttributeList &
-HltEventLoopMgr::getSorAttrList(const SOR * sor) const
+// ==============================================================================
+const coral::AttributeList& HltEventLoopMgr::getSorAttrList(const SOR* sor) const
 {
   if(sor->size() != 1)
   {
     // This branch should never be entered (the CondAttrListCollection
-    //corresponding to the SOR should contain one single AttrList). Since
-    //that's required by code ahead but not checked at compile time, we
-    //explicitly guard against any potential future mistake with this check
-    msgStream() << MSG::ERROR << ST_WHERE
-                << "Wrong SOR: size = " << sor->size() << endmsg;
-    throw std::runtime_error("SOR record should have one and one only attribute"
-                             " list, but it has " + sor->size());
+    // corresponding to the SOR should contain one single AttrList). Since
+    // that's required by code ahead but not checked at compile time, we
+    // explicitly guard against any potential future mistake with this check
+    ATH_MSG_ERROR(ST_WHERE << "Wrong SOR: size = " << sor->size());
+    throw std::runtime_error("SOR record should have one and one only attribute list, but it has " + sor->size());
   }
 
   const auto & soral = sor->begin()->second;
-  printSORAttrList(soral, msgStream(), MSG::INFO);
+  printSORAttrList(soral);
   return soral;
 }
 
-//=========================================================================
-StatusCode HltEventLoopMgr::updHLTConfigSvc()
-{
-  // Get HLTConfigSvc if available and do sanity check
-  service("TrigConf::HLTConfigSvc/HLTConfigSvc",
-          m_hltConfigSvc, /*createIf=*/false).ignore();
-
-  if ( (m_hltConfigSvc==0) && (m_jobOptionsType.value()=="DB") ) {
-    msgStream() << MSG::ERROR << ST_WHERE
-                << "JobOptionsType==DB but could not retrieve HLTConfigSvc"
-                << endmsg;
-    return StatusCode::FAILURE;
-  }
-
-  return StatusCode::SUCCESS;
-}
-
-//=========================================================================
-const EventInfo * HltEventLoopMgr::prepEventInfo() const
-{
-  const EventInfo * pEvent =
-      new EventInfo(new EventID(m_currentRun,
-                                0,
-                                m_sorTime_stamp[0],
-                                m_sorTime_stamp[1],
-                                m_currentLB,
-                                0,
-                                std::get<0>(m_detector_mask),
-                                std::get<1>(m_detector_mask),
-                                std::get<2>(m_detector_mask),
-                                std::get<3>(m_detector_mask)),
-                    new EventType());
-
-  // Record it in StoreGate
-  if(m_evtStore->record(pEvent,"EventInfo").isFailure())
-  {
-    msgStream() << MSG::ERROR << ST_WHERE
-                << "Could not record EventInfo object" << endmsg;
-    return nullptr;
-  }
-
-  msgStream() << MSG::DEBUG << ST_WHERE
-              << "Recorded EventInfo object: "
-              << *pEvent->event_ID() << endmsg;
-
-  return pEvent;
-}
-
-//=========================================================================
-StatusCode HltEventLoopMgr::prepXAODEventInfo() const
-{
-  auto aux = new xAOD::EventAuxInfo;
-  auto ev = new xAOD::EventInfo;
-  ev->setStore(aux);
-  ev->setRunNumber(m_currentRun);
-  ev->setEventNumber(0);
-  ev->setLumiBlock(m_currentLB);
-  ev->setTimeStamp(m_sorTime_stamp[0]);
-  ev->setTimeStampNSOffset(m_sorTime_stamp[1]);
-  ev->setBCID(0);
-  ev->setDetectorMask0(std::get<0>(m_detector_mask));
-  ev->setDetectorMask1(std::get<1>(m_detector_mask));
-  ev->setDetectorMask2(std::get<2>(m_detector_mask));
-  ev->setDetectorMask3(std::get<3>(m_detector_mask));
-
-  // Record it in StoreGate
-  if(m_evtStore->record(aux, "EventInfoAux.").isFailure() ||
-     m_evtStore->record(ev, "EventInfo").isFailure())
-  {
-    msgStream() << MSG::ERROR << ST_WHERE
-                << "Could not record xAOD::EventInfo object" << endmsg;
-
-    return StatusCode::FAILURE;
-  }
-
-  msgStream() << MSG::DEBUG << ST_WHERE
-              << "Recorded xAOD::EventInfo object: "
-              << *ev << endmsg;
-
-  return StatusCode::SUCCESS;
+// ==============================================================================
+void HltEventLoopMgr::printSORAttrList(const coral::AttributeList& atr) const
+{
+  unsigned long long sorTime_ns(atr["SORTime"].data<unsigned long long>());
+
+  // Human readable format of SOR time if available
+  time_t sorTime_sec = sorTime_ns/1000000000;
+  const auto sorTime_readable = OWLTime(sorTime_sec);
+
+  ATH_MSG_INFO("SOR parameters:");
+  ATH_MSG_INFO("   RunNumber             = " << atr["RunNumber"].data<unsigned int>());
+  ATH_MSG_INFO("   SORTime [ns]          = " << sorTime_ns << " (" << sorTime_readable << ") ");
+
+  // Use string stream for fixed-width hex detector mask formatting
+  auto dmfst = atr["DetectorMaskFst"].data<unsigned long long>();
+  auto dmsnd = atr["DetectorMaskSnd"].data<unsigned long long>();
+  std::ostringstream ss;
+  ss.setf(std::ios_base::hex,std::ios_base::basefield);
+  ss << std::setw(16) << std::setfill('0') << dmfst;
+  ATH_MSG_INFO("   DetectorMaskFst       = 0x" << ss.str());
+  ss.str(""); // reset the string stream
+  ss << std::setw(16) << std::setfill('0') << dmsnd;
+  ATH_MSG_INFO("   DetectorMaskSnd       = 0x" << ss.str());
+  ss.str(""); // reset the string stream
+  ss << std::setw(16) << std::setfill('0') << dmfst;
+  ss << std::setw(16) << std::setfill('0') << dmsnd;
+  ATH_MSG_INFO("   Complete DetectorMask = 0x" << ss.str());
+
+  ATH_MSG_INFO("   RunType               = " << atr["RunType"].data<std::string>());
+  ATH_MSG_INFO("   RecordingEnabled      = " << (atr["RecordingEnabled"].data<bool>() ? "true" : "false"));
 }
 
-//=========================================================================
-StatusCode HltEventLoopMgr::updMagField(const ptree& pt) const
-{
-  if(m_setMagFieldFromPtree && validPartition())
-  {
-    try
-    {
-      auto tor_cur = pt.get<float>("Magnets.ToroidsCurrent.value");
-      auto sol_cur = pt.get<float>("Magnets.SolenoidCurrent.value");
-
-      IProperty* magfsvc(0);
-      service("AtlasFieldSvc", magfsvc, /*createIf=*/false).ignore();
-      if ( magfsvc==0 ) {
-        msgStream() << MSG::ERROR << ST_WHERE
-                    << "Cannot retrieve AtlasFieldSvc" << endmsg;
-        return StatusCode::FAILURE;
-      }
-
-      auto sc = Gaudi::Utils::setProperty(magfsvc, "UseSoleCurrent", sol_cur);
-      if ( sc.isFailure() ) {
-        msgStream() << MSG::ERROR << ST_WHERE
-                    << "Cannot set property AtlasFieldSvc.UseSoleCurrent"
-                    << endmsg;
-        return StatusCode::FAILURE;
+// ==============================================================================
+void HltEventLoopMgr::failedEvent(EventContext* eventContext,
+                                  const xAOD::EventInfo* eventInfo,
+                                  HLT::HLTResult* hltResult) const
+{
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+
+  // in case EventInfo is unavailable we try to make a temporary one just to build the HLT result
+  // - this unique_ptr deletes it when going out of scope
+  std::unique_ptr<xAOD::EventInfo> tmpEventInfo;
+
+  if (eventContext) {
+    // try to retrieve the event info from event store
+    if (m_whiteboard->selectStore(eventContext->slot()).isSuccess()) {
+      if (!eventInfo && m_evtStore->retrieve(eventInfo).isFailure()) {
+        EventIDBase eid = eventContext->eventID();
+        ATH_MSG_WARNING("Failed to retrieve event info. Will try to build one from EventContext (" << *eventContext
+                        << ") with eventID = " << eid);
+        tmpEventInfo = std::make_unique<xAOD::EventInfo>();
+        tmpEventInfo->setRunNumber(eid.run_number());
+        tmpEventInfo->setEventNumber(eid.event_number());
+        tmpEventInfo->setTimeStamp(eid.time_stamp());
+        tmpEventInfo->setTimeStampNSOffset(eid.time_stamp_ns_offset());
+        tmpEventInfo->setLumiBlock(eid.lumi_block());
+        tmpEventInfo->setBCID(eid.bunch_crossing_id());
+        eventInfo = tmpEventInfo.get();
       }
-
-      sc = Gaudi::Utils::setProperty(magfsvc, "UseToroCurrent", tor_cur);
-      if ( sc.isFailure() ) {
-        msgStream() << MSG::ERROR << ST_WHERE
-                    << "Cannot set property AtlasFieldSvc.UseToroCurrent"
-                    << endmsg;
-        return StatusCode::FAILURE;
+      if (!hltResult && m_evtStore->retrieve(hltResult).isFailure()) {
+        ATH_MSG_DEBUG("Failed to retrieve HLT result");
       }
-
-      msgStream() << MSG::INFO << "*****************************************" << endmsg;
-      msgStream() << MSG::INFO << "  Auto-configuration of magnetic field:  " << endmsg;
-      msgStream() << MSG::INFO << "    solenoid current from IS = " << sol_cur << endmsg;
-      msgStream() << MSG::INFO << "     torroid current from IS = " << tor_cur << endmsg;
-      msgStream() << MSG::INFO << "*****************************************" << endmsg;
     }
-    catch(ptree_bad_path& e)
-    {
-      msgStream() << MSG::ERROR << ST_WHERE
-                  << "Magnet auto-configuration failed: " << e.what() << endmsg;
-      return StatusCode::FAILURE;
+    else {
+      ATH_MSG_DEBUG("Failed to select whiteboard store for slot " << eventContext->slot());
     }
   }
-  else
-  {
-    msgStream() << MSG::DEBUG << ST_WHERE
-                << "Magnetic fields not available" << endmsg;
-  }
 
-  return StatusCode::SUCCESS;
-}
+  if (!eventContext && !eventInfo) {
+    ATH_MSG_ERROR("Failure occurred while we don't have either EventContext or EventInfo, so don't know which event "
+                    << "was being processed. No result will be produced for this event.");
+    return;
+  }
 
-//=========================================================================
-StatusCode HltEventLoopMgr::resetCoolValidity()
-{
-  if ( m_coolHelper->resetBeginRunFolders(m_currentRun).isFailure() ) {
-    msgStream() << MSG::ERROR << ST_WHERE
-                << "Reset of at least one proxy failed" << endmsg;
-    return StatusCode::FAILURE;
+  if (eventContext && clearWBSlot(eventContext->slot()).isFailure()) {
+    ATH_MSG_WARNING("Failed to clear the whiteboard slot " << eventContext->slot());
   }
 
-  return StatusCode::SUCCESS;
-}
+  // need to create and return a result with debug stream flags
+  // for now, only creating a dummy result
+  std::unique_ptr<uint32_t[]> hltr = fullHltResult(eventInfo,hltResult);
 
-//=========================================================================
-void HltEventLoopMgr::readyMsg() const
-{
-  if (msgLevel() <= MSG::INFO)
-  {
-    LumiBlock lb;
-    lb.LumiBlockNumber = 0;
-    if(validPartition() &&
-       m_isHelper->findValue(TrigISHelper::LumiBlock, lb).isFailure())
-    { // Lumiblock only used for information. Do not make this a failure.
-      msgStream() << MSG::WARNING << ST_WHERE
-                  << "Cannot read lumiblock number from IS" << endmsg;
-    }
+  // send the result
+  eventDone(std::move(hltr));
 
-    const auto& ilbn = lb.LumiBlockNumber;
-    msgStream() << MSG::INFO  << ST_WHERE
-                << "Ready to start event processing. Run = "
-                <<  m_currentRun << " (LB = "
-                << (ilbn ? boost::lexical_cast<string>(ilbn) : string{"??"})
-                << ")" << endmsg;
-  }
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
 }
 
-//=========================================================================
-void HltEventLoopMgr::
-setStreamTags(hltinterface::HLTResult& hltr,
-              const std::vector<TriggerInfo::StreamTag>& stream_tags) const
+// ==============================================================================
+std::unique_ptr<uint32_t[]> HltEventLoopMgr::fullHltResult(const xAOD::EventInfo* eventInfo,
+                                                           HLT::HLTResult* hltResult) const
 {
-  hltr.stream_tag.reserve(stream_tags.size());
-  for(const auto& st : stream_tags)
-  {
-    // get robs, filtering disabled ones
-    auto robs = filterRobs(st.robs());
-    // get subdetectors, filtering disabled ones
-    auto dets = filterDets(st.dets());
-
-    hltr.stream_tag.emplace_back(st.name(), st.type(), st.obeysLumiblock(),
-                                 robs, dets);
-  }
+  // method to be removed
+  return nullptr;
 }
 
-//=========================================================================
-void HltEventLoopMgr::
-mergeStreamTags(hltinterface::HLTResult& hltr,
-                const std::vector<xAOD::EventInfo::StreamTag>& xsts) const
+// ==============================================================================
+// This method is now trivial and could be removed
+void HltEventLoopMgr::eventDone(std::unique_ptr<uint32_t[]> hltResult) const
 {
-  auto& stags = hltr.stream_tag;
-  for(const auto& st : xsts)
-  {
-    // get robs, filtering disabled ones
-    auto robs = filterRobs(st.robs());
-    // get subdetectors, filtering disabled ones
-    auto dets = filterDets(st.dets());
-
-    // is there already a tag with the same type, name and obeysLumi flag?
-    auto it = find_if(begin(stags), end(stags),
-                      [&st](const eformat::helper::StreamTag& current){
-      return current.name == st.name() &&
-             current.type == st.type() &&
-             current.obeys_lumiblock == st.obeysLumiblock();
-    });
-
-    if(it != stags.end()) // if so, unite robs and dets
-    {
-      it->robs.insert(begin(robs), end(robs));
-      it->dets.insert(begin(dets), end(dets));
-    }
-    else // otherwise, add the tag
-      stags.emplace_back(st.name(), st.type(), st.obeysLumiblock(), robs, dets);
-  }
+  // method to be removed
 }
 
-//=========================================================================
-hltonl::AcceptFlag
-HltEventLoopMgr::processHltDecision(hltinterface::HLTResult& hltr) const
-{
-  if(m_forceHltAccept)
-  {
-    // we force accept independently of what the Steering decided for the event
-    addDebugStreamTag(hltr, m_HltForcedStreamName.value());
-    return hltonl::PSC_FORCED_ACCEPT;
+// ==============================================================================
+void HltEventLoopMgr::runEventTimer()
+{
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  auto softDuration = std::chrono::milliseconds(m_softTimeoutValue);
+  std::unique_lock<std::mutex> lock(m_timeoutMutex);
+  while (m_runEventTimer) {
+    m_timeoutCond.wait_for(lock,std::chrono::seconds(1));
+    auto now=std::chrono::steady_clock::now();
+    for (size_t i=0; i<m_eventTimerStartPoint.size(); ++i) {
+      // iterate over all slots and check for timeout
+      if (!m_isSlotProcessing.at(i)) continue;
+      if (now > m_eventTimerStartPoint.at(i) + softDuration) {
+        EventContext ctx(i,0); // we only need the slot number for Athena::Timeout instance
+        // don't duplicate the actions if the timeout was already reached
+        if (!Athena::Timeout::instance(ctx).reached()) {
+          auto procTime = now - m_eventTimerStartPoint.at(i);
+          auto procTimeMillisec = std::chrono::duration_cast<std::chrono::milliseconds>(procTime);
+          ATH_MSG_WARNING("Soft timeout in slot " << i << ". Processing time = "
+                          << procTimeMillisec.count() << " ms");
+          setTimeout(Athena::Timeout::instance(ctx));
+        }
+      }
+    }
   }
-
-  return hltr.stream_tag.size() ? hltonl::STEERING_ACCEPT
-                                : hltonl::STEERING_REJECT;
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
 }
 
-//=========================================================================
-hltonl::PSCErrorCode
-HltEventLoopMgr::serializeRobs(hltinterface::HLTResult& hltr, bool& serOk,
-                               HLT::HLTResult* dobj, uint32_t rn, uint32_t l1id,
-                               uint32_t bcid, uint32_t l1tt, uint32_t dett)
+// ==============================================================================
+StatusCode HltEventLoopMgr::createEventContext(EventContext*& evtContext) const
 {
-  auto fp = hltr.fragment_pointer;
-  auto spaceleft = hltr.max_result_size;
-  
-  // obtain the module ids that need serialization
-  auto modids = dobj->listOfModIDs(); // hope for copy ellision
+  evtContext = new EventContext(m_nevt, m_whiteboard->allocateStore(m_nevt));
 
-  if(find(begin(modids), end(modids), 0) == end(modids))
-  {
-    const auto& sts = hltr.stream_tag;
-    using ST = decltype(sts[0]);
-    auto pred = [](const ST& st){ return st.type == "debug"; };
-
-    if (m_forceHltAccept ||
-        find_if(begin(sts), end(sts), pred) != end(sts))
-    {
-      modids.push_back(0);
-    }
-  }
+  m_aess->reset(*evtContext);
 
-  // loop over module ids and build a rob for each one
-  for(const auto& modid : modids)
-  {
-    // Initialize a ROB
-    auto robp = initRob(modid, rn, l1id, bcid, l1tt, dett, m_status_words);
-    auto initial_robsize = robp->size_word() + INITIAL_ROB_SIZE_MARGIN;
-    if(!checkRobSize(initial_robsize, spaceleft, hltr.max_result_size))
-      return hltonl::PSC_ERROR_ROB_BUILD_FAILED;
-    
-    // serialize data and fill rob up
-    uint32_t* tmp{nullptr};
-    serOk &= serializeRob(tmp, *robp, *dobj, modid,
-                          spaceleft - initial_robsize);
-
-    // Hold this until we've copied it into the HLTResult
-    auto tmpstor = std::unique_ptr<uint32_t[]>{tmp};
-
-    // copy it in and delete temporary data, updating spaceleft
-    addRobToHLTResult(hltr, *robp, fp, spaceleft);
+  StatusCode sc = m_whiteboard->selectStore(evtContext->slot());
+  if (sc.isFailure()){
+    ATH_MSG_WARNING("Slot " << evtContext->slot() << " could not be selected for the WhiteBoard");
+  } else {
+    evtContext->setExtension( Atlas::ExtendedEventContext( m_evtStore->hiveProxyDict() ) );
+    ATH_MSG_DEBUG("created EventContext, num: " << evtContext->evt()  << "  in slot: " << evtContext->slot());
   }
-
-  return hltonl::PSC_ERROR_UNCLASSIFIED;
+  return sc;
 }
 
-//=========================================================================
-bool HltEventLoopMgr::serializeRob(uint32_t*& tmpstor,
-                                   eformat::write::ROBFragment& rob,
-                                   HLT::HLTResult& dobj,
-                                   unsigned int modid,
-                                   int payload_max)
+// ==============================================================================
+int HltEventLoopMgr::drainScheduler()
 {
-  // find the remaining space for this rob's payload
-  int payload = 0;
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
 
-  // serialize current rob
-  auto ret = dobj.serialize(tmpstor, payload, payload_max, modid);
+  // method copied from AthenaHiveEventLoopMgr
 
-  if(payload > payload_max)
-  {
-    msgStream() << MSG::ERROR << ST_WHERE
-                << "Serialized ROB's size (" << payload << ") is bigger "
-                   "than max allowed size (" << payload_max << ")"
-                << endmsg;
+  StatusCode sc(StatusCode::SUCCESS);
 
-    payload = payload_max;
-    ret = false;
-  }
+  // maybe we can do better
+  std::vector<EventContext*> finishedEvtContexts;
 
-  if(!ret) // otherwise, it's already correct
-  {
-    m_status_words[0] = SW_TRUNCATION.code();
-    m_status_words[1] = hltonl::NORMAL_HLT_RESULT_TRUNCATED;
-    rob.status(2, m_status_words);
-    rob.rod_status(2, m_status_words);
-  }
+  EventContext* finishedEvtContext(nullptr);
 
-  rob.rod_data(payload, tmpstor);
+  // Here we wait not to loose cpu resources
+  // ATH_MSG_DEBUG("drainScheduler: [" << finishedEvts << "] Waiting for a context");
+  ATH_MSG_DEBUG("drainScheduler: Waiting for a context");
+  sc = m_schedulerSvc->popFinishedEvent(finishedEvtContext);
 
-  return ret;
-}
+  // We got past it: cache the pointer
+  if (sc.isSuccess()){
+    ATH_MSG_DEBUG("drainScheduler: scheduler not empty: Context "
+	    << finishedEvtContext);
+    finishedEvtContexts.push_back(finishedEvtContext);
+  } else{
+    // no more events left in scheduler to be drained
+    ATH_MSG_DEBUG("drainScheduler: scheduler empty");
+    return 0;
+  }
 
-//=========================================================================
-void HltEventLoopMgr::addRobToHLTResult(hltinterface::HLTResult& hltr,
-                                        eformat::write::ROBFragment& rob,
-                                        uint32_t*& next_fragment, // don't pass original fragment pointer!
-                                        uint32_t& spaceleft)
-{
-  // Store the HLT ROB fragment in the HLT result
-  // (Maximum possible space is already allocated by the HLTMPPU)
-  auto copied = eformat::write::copy(*rob.bind(), next_fragment, rob.size_word());
-  hltr.hltResult_robs.emplace_back(next_fragment);
-
-  next_fragment += copied;
-  spaceleft -= copied;
-
-  if(copied == 0 || copied != rob.size_word())  {
-    msgStream() << MSG::ERROR
-                << "Memory copy operation for HLT result ROB failed. "
-                   "Returned number of copied words = " << copied
-                << ". Number of words in ROB which should be copied = "
-                << rob.size_word() << "." << endmsg;
+  // Let's see if we can pop other event contexts
+  while (m_schedulerSvc->tryPopFinishedEvent(finishedEvtContext).isSuccess()){
+    finishedEvtContexts.push_back(finishedEvtContext);
   }
-}
 
-//=========================================================================
-void HltEventLoopMgr::recordEDMSizeInfo(size_t nav_size,
-                                        bool serializationOk) const
-{
-  if (m_evtStore->transientContains<HLT::TrigEDMSizes>("TrigEDMSizes")) {
-    const HLT::TrigEDMSizes* dobjNavSizes(0);
-    if ( m_evtStore->retrieve(dobjNavSizes).isSuccess() ) {
-      for(const auto& navSizeInfo : dobjNavSizes->info())
-      {
-        std::string colname(navSizeInfo.collection+"__"+navSizeInfo.label);
-        // Protection for invalid collection names in TProfile
-        // (avoid bug in TProfile memory alloc)
-        auto it_col_name = std::find(m_hltEdmCollectionNames.value().begin(),
-                                     m_hltEdmCollectionNames.value().end(),
-                                     colname);
-        if(it_col_name == m_hltEdmCollectionNames.value().end())
-        {
-          if ( msgLevel() <= MSG::DEBUG )
-            msgStream() << MSG::DEBUG << "EDM collection name = " << colname
-                        << " is not in the configured list of EDM collections."
-                        << endmsg;
-
-          colname=m_hltEdmCollectionNames.value().back();
-        }
+  // Now we flush them
+  bool fail(false);
+  for (auto& thisFinishedEvtContext : finishedEvtContexts) {
+    if (!thisFinishedEvtContext) {
+      ATH_MSG_FATAL("Detected nullptr EventContext while clearing WB!");
+      fail = true;
+      continue;
+    }
 
-        auto * edmhist = serializationOk ? m_hist_HltEdmSizes_No_Truncation
-                                         : m_hist_HltEdmSizes_With_Truncation;
-        fillEdmHist(edmhist, colname, navSizeInfo);
+    // Set ThreadLocalContext to the currently processed finished context
+    Gaudi::Hive::setCurrentContext(thisFinishedEvtContext);
 
-        if(!serializationOk)
-        {
-          edmhist = navSizeInfo.isTruncated(nav_size) ?
-              m_hist_HltEdmSizes_TruncatedResult_Truncated_Collections :
-              m_hist_HltEdmSizes_TruncatedResult_Retained_Collections;
-          fillEdmHist(edmhist, colname, navSizeInfo);
-        }
-      }
+    if (m_aess->eventStatus(*thisFinishedEvtContext) != EventStatus::Success) {
+      ATH_MSG_FATAL("Failed event detected on " << thisFinishedEvtContext
+                    << " with fail mode: " << m_aess->eventStatus(*thisFinishedEvtContext));
+      delete thisFinishedEvtContext;
+      fail = true;
+      continue;
     }
-    else
-      msgStream() << MSG::WARNING << "cannot access EDM sizes information"
-                  << endmsg;
-  }
-}
 
-//=========================================================================
-bool HltEventLoopMgr::checkRobSize(uint32_t robsize, uint32_t spaceleft,
-                                   uint32_t maxsize)
-{
-  if(spaceleft <= robsize)
-  {
-    msgStream() << MSG::ERROR << ST_WHERE
-                << "Can not create HLT result ROB with available ROB "
-                   "buffer size ! Total available buffer size = "
-                << maxsize << "; buffer size left = " << spaceleft
-                << "; Number of header words used by empty ROB = "
-                << robsize << endmsg;
-
-    return false;
-  }
+    // EventID::number_type n_run(0);
+    // EventID::number_type n_evt(0);
+
+    //-------------------------------------------
+    // Do we need the event info here ???
+    //-------------------------------------------
+
+    const xAOD::EventInfo* eventInfo = nullptr;
+    if (m_whiteboard->selectStore(thisFinishedEvtContext->slot()).isSuccess()) {
+      if (m_evtStore->retrieve(eventInfo).isFailure()) {
+        ATH_MSG_ERROR(__FUNCTION__ << ": Failed to retrieve EventInfo");
+        delete thisFinishedEvtContext;
+        fail = true;
+        continue;
+      } else {
+        // n_run = eventInfo->runNumber();
+        // n_evt = eventInfo->eventNumber();
+      }
+    } else {
+      ATH_MSG_ERROR("DrainSched: unable to select store " << thisFinishedEvtContext->slot());
+      delete thisFinishedEvtContext;
+      fail = true;
+      continue;
+    }
 
-  return true;
-}
+    // m_incidentSvc->fireIncident(Incident(name(), IncidentType::EndEvent,
+    // 					 *thisFinishedEvtContext ));
 
-//=========================================================================
-bool HltEventLoopMgr::
-checkEventIdConsistency(const hltinterface::EventId& evId) const
-{
-  if(evId.l1Id != m_lvl1id || evId.lbNumber != m_lumi_block)
-  {
-    msgStream() << MSG::WARNING << ST_WHERE
-                << "EventId information does not match CTP fragment contents: "
-                << "EventId = {globalId: " << evId.globalId << ", l1Id: "
-                << evId.l1Id << ", lbNumber: " << evId.lbNumber
-                << "}, but the CTP fragment included l1Id = " << m_lvl1id
-                << " and lumiblock = " << m_lumi_block << "." << endmsg;
-    return false;
-  }
 
-  return true;
-}
+    // if (!hltResult) {
+    //   failedEvent(thisFinishedEvtContext,eventInfo);
+    //   continue;
+    // }
 
-//=========================================================================
-void HltEventLoopMgr::failedEvent(hltinterface::HLTResult& hlt_result,
-                                  hltonl::PSCErrorCode ecode,
-                                  const std::string& emsg,
-                                  bool empty_result)
-{
-  m_failed_evt++;
+    //-------------------------------------------
+    // HLT output handling goes here
+    // Call the conversion svc etc.
+    // Handle any possible errors
+    //-------------------------------------------
+    // Call the result builder to record HLTResultMT in SG
+    if (m_hltResultBuilder->buildResult(*thisFinishedEvtContext).isFailure()) {
+      ATH_MSG_ERROR("Failed to create the HLT result object");
+      // what now?
+    }
+    // Connect output (create the output container) - the argument is currently not used
+    if (m_outputCnvSvc->connectOutput("").isFailure()) {
+      ATH_MSG_ERROR("Conversion service failed to connectOutput");
+      // what now?
+    }
+    IOpaqueAddress* addr = nullptr;
+    // is this the best way? also maybe should be retrieved in initialize and stored?
+    auto hltResultCLID = ClassID_traits<HLT::HLTResultMT>::ID();
+    DataObject* hltResultDO = m_evtStore->accessData(hltResultCLID,m_hltResultBuilder->resultName());
+    if (!hltResultDO) {
+      ATH_MSG_ERROR("Failed to retrieve the HLTResult DataObject");
+      // what now?
+    }
+    if (m_outputCnvSvc->createRep(hltResultDO,addr).isFailure()) {
+      ATH_MSG_ERROR("Conversion service failed to convert HLTResult");
+      // what now?
+    }
+    // Commit output (write/send the output data) - the arguments are currently not used
+    if (m_outputCnvSvc->commitOutput("",true).isFailure()) {
+      ATH_MSG_ERROR("Conversion service failed to commitOutput");
+      // what now?
+    }
 
-  addDebugStreamTag(hlt_result, m_HltDebugStreamName.value());
-  if(empty_result)
-  {
-    HltEmptyResultROB(hlt_result, ecode);
-    fillHltResultHistograms(hlt_result);
-  }
+    { // flag idle slot to the timeout thread and reset the timer
+      std::unique_lock<std::mutex> lock(m_timeoutMutex);
+      m_eventTimerStartPoint[thisFinishedEvtContext->slot()] = std::chrono::steady_clock::now();
+      m_isSlotProcessing[thisFinishedEvtContext->slot()] = false;
+      resetTimeout(Athena::Timeout::instance(*thisFinishedEvtContext));
+    }
+    m_timeoutCond.notify_all();
 
-  msgStream() << MSG::ERROR << ST_WHERE
-              << emsg << " PSC error code = "
-              << hltonl::PrintPscErrorCode(ecode)
-              << "\n" << hlt_result << "\n" << endmsg;
-}
+    ATH_MSG_DEBUG("Clearing slot " << thisFinishedEvtContext->slot()
+                  << " (event " << thisFinishedEvtContext->evt() << ") of the whiteboard");
 
-//=========================================================================
-std::vector<uint32_t> HltEventLoopMgr::
-missingL1Robs(const std::vector<eformat::ROBFragment<const uint32_t*>>& l1r)
-const
-{
-  using eformat::helper::SourceIdentifier;
-  using ROB = eformat::ROBFragment<const uint32_t*>;
+    StatusCode sc = clearWBSlot(thisFinishedEvtContext->slot());
+    if (!sc.isSuccess()) {
+      ATH_MSG_ERROR("Whiteboard slot " << thisFinishedEvtContext->slot() << " could not be properly cleared");
+      fail = true;
+      delete thisFinishedEvtContext;
+      continue;
+    }
 
-  std::vector<uint32_t> ret{};
-  for(const auto& robid : m_mandatoryL1ROBs.value())
-  {
-    if(isSubDetectorIn(SourceIdentifier(robid).subdetector_id()))
-    {
-      auto it = std::find_if(begin(l1r), end(l1r), [robid](const ROB& rob){
-        return rob.rob_source_id() == robid;
-      });
-      if(it == end(l1r))
-        ret.push_back(robid);
+/*
+    finishedEvts++;
+
+    writeHistograms().ignore();
+    ++m_proc;
+
+    if (m_doEvtHeartbeat) {
+      if(!m_useTools)
+        ATH_MSG_INFO("  ===>>>  done processing event #" << n_evt << ", run #" << n_run
+                     << " on slot " << thisFinishedEvtContext->slot() << ",  "
+                     << m_proc << " events processed so far  <<<===");
+      else
+	ATH_MSG_INFO("  ===>>>  done processing event #" << n_evt << ", run #" << n_run
+	             << " on slot " << thisFinishedEvtContext->slot() << ",  "
+	             << m_nev << " events read and " << m_proc
+	             << " events processed so far <<<===");
+      std::ofstream outfile( "eventLoopHeartBeat.txt");
+      if ( !outfile ) {
+	ATH_MSG_ERROR(" unable to open: eventLoopHeartBeat.txt");
+	fail = true;
+	delete thisFinishedEvtContext;
+	continue;
+      } else {
+	outfile << "  done processing event #" << n_evt << ", run #" << n_run
+		<< " " << m_nev << " events read so far  <<<===" << std::endl;
+	outfile.close();
+      }
     }
+*/
+    ATH_MSG_DEBUG("drainScheduler thisFinishedEvtContext: " << thisFinishedEvtContext);
+
+
+    m_incidentSvc->fireIncident(Incident(name(),
+                                         IncidentType::EndProcessing,
+                                         *thisFinishedEvtContext));
+
+    delete thisFinishedEvtContext;
+
+    // Set ThreadLocalContext to an invalid context as we entering a context-less environment
+    Gaudi::Hive::setCurrentContext( EventContext() );
   }
 
-  return ret;
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return (  fail ? -1 : 1 );
 }
 
-//=========================================================================
-bool HltEventLoopMgr::isSubDetectorIn(eformat::SubDetector sd) const
+// ==============================================================================
+StatusCode HltEventLoopMgr::clearWBSlot(int evtSlot) const
 {
-  uint64_t most = std::get<3>(m_detector_mask);
-  most <<= 32;
-  most |= std::get<2>(m_detector_mask);
-
-  uint64_t least = std::get<1>(m_detector_mask);
-  least <<= 32;
-  least |= std::get<0>(m_detector_mask);
-
-  return eformat::helper::DetectorMask{least, most}.is_set(sd);
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  StatusCode sc = m_whiteboard->clearStore(evtSlot);
+  if( !sc.isSuccess() )  {
+    ATH_MSG_WARNING("Clear of Event data store failed");
+  }
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__ << ", returning m_whiteboard->freeStore(evtSlot=" << evtSlot << ")");
+  return m_whiteboard->freeStore(evtSlot);
 }
diff --git a/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx b/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx
index 77d8f687d4a23b6fb51b032eeef9b99645a3d1e1..85a1766f21a13aea199ffccd7a64a2cb56eb65de 100644
--- a/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx
+++ b/HLT/Trigger/TrigControl/TrigServices/src/TrigMonTHistSvc.cxx
@@ -132,6 +132,8 @@ StatusCode TrigMonTHistSvc::regHist(const std::string& id, TH1* hist_ptr) {
 
 
 
+
+
 StatusCode TrigMonTHistSvc::regTree(const std::string& id) {
   return THistSvcHLT::regTree(id);
 }
diff --git a/HLT/Trigger/TrigControl/TrigServices/src/components/TrigServices_entries.cxx b/HLT/Trigger/TrigControl/TrigServices/src/components/TrigServices_entries.cxx
index 1bf48550a1225b2142e67a6b8b45b6bdd7a44d58..898cf7b342fafec0cdcd8cbb02b73fa2248ebca1 100644
--- a/HLT/Trigger/TrigControl/TrigServices/src/components/TrigServices_entries.cxx
+++ b/HLT/Trigger/TrigControl/TrigServices/src/components/TrigServices_entries.cxx
@@ -5,7 +5,6 @@
 #include "TrigServices/TrigIS.h"
 #include "TrigServices/TrigISHelper.h"
 #include "../TrigCOOLUpdateHelper.h"
-#include "../THistSvcHLT.h"
 
 DECLARE_COMPONENT( TrigMessageSvc )
 DECLARE_COMPONENT( TrigMonTHistSvc )
@@ -13,6 +12,5 @@ DECLARE_COMPONENT( TrigIS )
 DECLARE_COMPONENT( HltEventLoopMgr )
 DECLARE_COMPONENT( HltROBDataProviderSvc )
 DECLARE_COMPONENT( TrigISHelper )
-DECLARE_COMPONENT( TrigCOOLUpdateHelper )  
-DECLARE_COMPONENT( THistSvcHLT )  
-
+DECLARE_COMPONENT( TrigCOOLUpdateHelper )
+DECLARE_COMPONENT( THistSvcHLT )
diff --git a/Projects/Athena/package_filters.txt b/Projects/Athena/package_filters.txt
index cd306a1de015fd862d2dfe4f39c8a9447d43972f..5f83a2584f5749e987a155036c0c6e311865ebfa 100644
--- a/Projects/Athena/package_filters.txt
+++ b/Projects/Athena/package_filters.txt
@@ -9,10 +9,11 @@
 - Projects/.*
 
 # Remove most HLT packages
-+ HLT/Trigger/TrigTransforms/TrigTransform
-+ HLT/Event/ByteStreamEmonSvc
-- HLT/.*
-- Trigger/TrigValidation/TrigP1Test
+# We currently build the HLT as part of Athena. Uncomment the following three lines to revert:
+#+ HLT/Trigger/TrigTransforms/TrigTransform
+#- HLT/.*
+#- Trigger/TrigValidation/TrigP1Test
+- HLT/HLTTestApps
 - HLT/HLToks
 - Trigger/ALP
 - Event/DFStreamEventSelector
diff --git a/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/HLTResultMT.h b/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/HLTResultMT.h
new file mode 100644
index 0000000000000000000000000000000000000000..6cd6de32ca5acada8212497d2d04edf757d1ffbc
--- /dev/null
+++ b/Trigger/TrigEvent/TrigSteeringEvent/TrigSteeringEvent/HLTResultMT.h
@@ -0,0 +1,65 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGSTEERINGEVENT_HLTResultMT_H
+#define TRIGSTEERINGEVENT_HLTResultMT_H
+
+#include "AthenaKernel/CLASS_DEF.h"
+#include "eformat/StreamTag.h"
+#include <vector>
+#include <unordered_map>
+
+namespace HLT {
+
+  /** @class HLTResultMT
+   *  @brief A container class for data required to build online output from HLT.
+   * 
+   *  It is not intended to modify the stored data, but may perform extra checks and debug printouts in the
+   *  getter/setter methods.
+   **/
+  class HLTResultMT {
+  public:
+    /// Standard constructor
+    HLTResultMT(std::vector<eformat::helper::StreamTag> streamTags = {},
+                std::vector<uint32_t> hltBits = {},
+                std::unordered_map<uint16_t, std::vector<uint32_t> > data = {});
+    /// Standard destructor
+    virtual ~HLTResultMT();
+
+    /// Stream tags getter
+    const std::vector<eformat::helper::StreamTag>& getStreamTags() const;
+    /// Stream tags setter
+    void setStreamTags(const std::vector<eformat::helper::StreamTag>& streamTags);
+    /// Append a stream tag
+    void addStreamTag(const eformat::helper::StreamTag& streamTag);
+
+    /// HLT bits getter
+    const std::vector<uint32_t>& getHltBits() const;
+    /// HLT bits setter
+    void setHltBits(const std::vector<uint32_t>& bits);
+    /// Append a word with HLT bits
+    void addHltBitsWord(const uint32_t& word);
+
+    /// Serialised data getter
+    const std::unordered_map<uint16_t, std::vector<uint32_t> >& getSerialisedData() const;
+    /// Serialised data getter for a given module ID
+    const std::vector<uint32_t>& getSerialisedData(uint16_t moduleId) const;
+    /// Serialised data setter
+    void setSerialisedData(const std::unordered_map<uint16_t, std::vector<uint32_t> >& data);
+    /// Append serialised data for a given module ID
+    void addSerialisedData(const uint16_t moduleId, const std::vector<uint32_t>& data);
+
+  private:
+    /// Stream tags of the event
+    std::vector<eformat::helper::StreamTag> m_streamTags;
+    /// Serialised HLT bits (flagging which chains passed)
+    std::vector<uint32_t> m_hltBits;
+    /// Serialised result (ROBFragment payload) for each module ID (0 for full result, >0 for data scouting)
+    std::unordered_map<uint16_t, std::vector<uint32_t> > m_data;
+  };
+} // namespace HLT
+
+CLASS_DEF(HLT::HLTResultMT, 172156324, 1)
+
+#endif // TRIGSTEERINGEVENT_HLTResultMT_H
diff --git a/Trigger/TrigEvent/TrigSteeringEvent/src/HltResultMT.cxx b/Trigger/TrigEvent/TrigSteeringEvent/src/HltResultMT.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..2759bfc81b35c47ecb0e21aca9b9d2b79a43901a
--- /dev/null
+++ b/Trigger/TrigEvent/TrigSteeringEvent/src/HltResultMT.cxx
@@ -0,0 +1,86 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrigSteeringEvent/HLTResultMT.h"
+
+// =============================================================================
+// Standard constructor
+// =============================================================================
+HLT::HLTResultMT::HLTResultMT(std::vector<eformat::helper::StreamTag> streamTags,
+                         std::vector<uint32_t> hltBits,
+                         std::unordered_map<uint16_t, std::vector<uint32_t> > data)
+: m_streamTags(streamTags),
+  m_hltBits(hltBits),
+  m_data(data) {}
+
+// =============================================================================
+// Standard destructor
+// =============================================================================
+HLT::HLTResultMT::~HLTResultMT() {}
+
+// =============================================================================
+// Getter/setter methods for stream tags
+// =============================================================================
+const std::vector<eformat::helper::StreamTag>& HLT::HLTResultMT::getStreamTags() const {
+  return m_streamTags;
+}
+
+// -----------------------------------------------------------------------------
+void HLT::HLTResultMT::setStreamTags(const std::vector<eformat::helper::StreamTag>& streamTags) {
+  // copy assignment
+  m_streamTags = streamTags;
+}
+
+// -----------------------------------------------------------------------------
+void HLT::HLTResultMT::addStreamTag(const eformat::helper::StreamTag& streamTag) {
+  m_streamTags.push_back(streamTag);
+}
+
+// =============================================================================
+// Getter/setter methods for trigger bits
+// =============================================================================
+const std::vector<uint32_t>& HLT::HLTResultMT::getHltBits() const {
+  return m_hltBits;
+}
+
+// -----------------------------------------------------------------------------
+void HLT::HLTResultMT::setHltBits(const std::vector<uint32_t>& bits) {
+  // copy assignment
+  m_hltBits = bits;
+}
+
+// -----------------------------------------------------------------------------
+void HLT::HLTResultMT::addHltBitsWord(const uint32_t& word) {
+  m_hltBits.push_back(word);
+}
+
+// =============================================================================
+// Getter/setter methods for serialised data
+// =============================================================================
+/// Serialised data getter
+const std::unordered_map<uint16_t, std::vector<uint32_t> >& HLT::HLTResultMT::getSerialisedData() const {
+  return m_data;
+}
+
+// -----------------------------------------------------------------------------
+const std::vector<uint32_t>& HLT::HLTResultMT::getSerialisedData(uint16_t moduleId) const {
+  // this can throw std::out_of_range - implement messaging (std::cerr or ATH_MSG_ERR) to avoid exception
+  return m_data.at(moduleId);
+}
+
+// -----------------------------------------------------------------------------
+void HLT::HLTResultMT::setSerialisedData(const std::unordered_map<uint16_t, std::vector<uint32_t> >& data) {
+  // copy assignment (WARNING, data may be large!)
+  m_data = data;
+}
+
+// -----------------------------------------------------------------------------
+void HLT::HLTResultMT::addSerialisedData(const uint16_t moduleId, const std::vector<uint32_t>& data) {
+  if (m_data.find(moduleId)!=m_data.cend()) {
+    // implement error printout and handling here !!! use either std::cerr or ATH_MSG_ERR
+  }
+  else {
+    m_data[moduleId] = data;
+  }
+}
diff --git a/Trigger/TrigSteer/TrigHLTResultByteStream/TrigHLTResultByteStream/HLTResultMTByteStreamCnv.h b/Trigger/TrigSteer/TrigHLTResultByteStream/TrigHLTResultByteStream/HLTResultMTByteStreamCnv.h
new file mode 100644
index 0000000000000000000000000000000000000000..64064674bae8b3d9a39653c235123bb952d56abb
--- /dev/null
+++ b/Trigger/TrigSteer/TrigHLTResultByteStream/TrigHLTResultByteStream/HLTResultMTByteStreamCnv.h
@@ -0,0 +1,44 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGHLTRESULTBYTESTREAM_HLTResultMTByteStreamCnv_H
+#define TRIGHLTRESULTBYTESTREAM_HLTResultMTByteStreamCnv_H
+
+#include "AthenaBaseComps/AthMessaging.h"
+#include "GaudiKernel/Converter.h"
+
+// Externals
+extern unsigned char ByteStream_StorageType;
+
+namespace HLT {
+  /** @class HLTResultMTByteStreamCnv
+   *  @brief ByteStream converter for HLTResultMT
+   **/
+  class HLTResultMTByteStreamCnv : public Converter, public AthMessaging {
+  public:
+    /// Standard constructor
+    HLTResultMTByteStreamCnv(ISvcLocator* svcLoc);
+    /// Standard destructor
+    virtual ~HLTResultMTByteStreamCnv();
+
+    // ------------------------- Converter methods -----------------------------
+    virtual StatusCode initialize() override;
+    virtual StatusCode finalize() override;
+
+    /// Create RDO (HLTResultMT) from ByteStream
+    virtual StatusCode createObj(IOpaqueAddress* pAddr, DataObject*& pObj) override;
+    /// Create ByteStream from RDO (HLTResultMT)
+    virtual StatusCode createRep(DataObject* pObj, IOpaqueAddress*& pAddr) override;
+
+    // ------------------------- Converter definition helpers ------------------
+    /// Storage type used by this converter
+    static unsigned char storageType() {return ByteStream_StorageType;} 
+    /// CLID of the class HLTResultMT converted by this converter
+    static const CLID& classID();
+
+    long repSvcType() const override { return i_repSvcType(); } //!< return repSvcType
+  };
+} // namespace HLT
+
+#endif // TRIGHLTRESULTBYTESTREAM_HLTResultMTByteStreamCnv_H
diff --git a/Trigger/TrigSteer/TrigHLTResultByteStream/src/HLTResultMTByteStreamCnv.cxx b/Trigger/TrigSteer/TrigHLTResultByteStream/src/HLTResultMTByteStreamCnv.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..4430e93e7af14581a70916f19958f853af5bee27
--- /dev/null
+++ b/Trigger/TrigSteer/TrigHLTResultByteStream/src/HLTResultMTByteStreamCnv.cxx
@@ -0,0 +1,65 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrigHLTResultByteStream/HLTResultMTByteStreamCnv.h"
+#include "TrigSteeringEvent/HLTResultMT.h"
+
+#include "AthenaBaseComps/AthMsgStreamMacros.h"
+#include "AthenaKernel/ClassID_traits.h"
+
+// =============================================================================
+// Standard constructor
+// =============================================================================
+HLT::HLTResultMTByteStreamCnv::HLTResultMTByteStreamCnv(ISvcLocator* svcLoc) :
+  Converter(ByteStream_StorageType, classID(), svcLoc),
+  AthMessaging(msgSvc(), "HLTResultMTByteStreamCnv") {}
+
+// =============================================================================
+// Standard destructor
+// =============================================================================
+HLT::HLTResultMTByteStreamCnv::~HLTResultMTByteStreamCnv() {}
+
+// =============================================================================
+// Implementation of Converter::initialize
+// =============================================================================
+StatusCode HLT::HLTResultMTByteStreamCnv::initialize() {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of Converter::finalize
+// =============================================================================
+StatusCode HLT::HLTResultMTByteStreamCnv::finalize() {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of Converter::createObj
+// =============================================================================
+StatusCode HLT::HLTResultMTByteStreamCnv::createObj(IOpaqueAddress* pAddr, DataObject*& pObj) {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of Converter::createRep
+// =============================================================================
+StatusCode HLT::HLTResultMTByteStreamCnv::createRep(DataObject* pObj, IOpaqueAddress*& pAddr) {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// CLID
+// =============================================================================
+const CLID& HLT::HLTResultMTByteStreamCnv::classID() {
+  return ClassID_traits<HLT::HLTResultMT>::ID();
+}
+
diff --git a/Trigger/TrigSteer/TrigHLTResultByteStream/src/components/TrigHLTResultByteStream_entries.cxx b/Trigger/TrigSteer/TrigHLTResultByteStream/src/components/TrigHLTResultByteStream_entries.cxx
index fbcb8e97fa2fec95b0ae970bc610eedafc514bb7..65f438152d9d5f2157fc6a645e23bf1088e7fa39 100644
--- a/Trigger/TrigSteer/TrigHLTResultByteStream/src/components/TrigHLTResultByteStream_entries.cxx
+++ b/Trigger/TrigSteer/TrigHLTResultByteStream/src/components/TrigHLTResultByteStream_entries.cxx
@@ -1,7 +1,9 @@
 
 #include "TrigHLTResultByteStream/HLTResultByteStreamCnv.h"
+#include "TrigHLTResultByteStream/HLTResultMTByteStreamCnv.h"
 #include "TrigHLTResultByteStream/HLTResultByteStreamTool.h"
 
 DECLARE_CONVERTER( HLT::HLTResultByteStreamCnv )
+DECLARE_CONVERTER( HLT::HLTResultMTByteStreamCnv )
 DECLARE_COMPONENT( HLT::HLTResultByteStreamTool )
 
diff --git a/Trigger/TrigSteer/TrigSteering/TrigSteering/ResultBuilderMT.h b/Trigger/TrigSteer/TrigSteering/TrigSteering/ResultBuilderMT.h
new file mode 100644
index 0000000000000000000000000000000000000000..8a475954210929aabb8bc5bb3cf8baade7042781
--- /dev/null
+++ b/Trigger/TrigSteer/TrigSteering/TrigSteering/ResultBuilderMT.h
@@ -0,0 +1,39 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef TRIGSTEERING_RESULTBUILDERMT_H
+#define TRIGSTEERING_RESULTBUILDERMT_H
+
+#include "TrigSteeringEvent/HLTResultMT.h"
+#include "AthenaBaseComps/AthAlgTool.h"
+#include "StoreGate/WriteHandle.h"
+
+namespace HLT {
+  /** @class ResultBuilderMT
+   *  @brief Tool to create the HLTResultMT at the end of each event
+   **/
+  class ResultBuilderMT : public AthAlgTool {
+  public:
+    /// Standard constructor
+    ResultBuilderMT(const std::string& type, const std::string& name, const IInterface* parent);
+    /// Standard destructor
+    virtual ~ResultBuilderMT();
+
+    // ------------------------- IStateful methods -----------------------------
+    virtual StatusCode initialize() override;
+    virtual StatusCode finalize() override;
+
+    // ------------------------- Specific methods of this tool -----------------
+    /// Builds the HLTResultMT and records it in the event store
+    StatusCode buildResult(const EventContext& eventContext) const;
+    /// Return name of the HLTResultMT
+    const std::string& resultName() const {return m_hltResultWHKey.key();}
+
+  private:
+    /// StoreGate key for the HLTResultMT
+    SG::WriteHandleKey<HLT::HLTResultMT> m_hltResultWHKey;
+  };
+} // namespace HLT
+
+#endif // TRIGSTEERING_RESULTBUILDERMT_H
diff --git a/Trigger/TrigSteer/TrigSteering/src/ResultBuilderMT.cxx b/Trigger/TrigSteer/TrigSteering/src/ResultBuilderMT.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6c619ebc7788cb9058bd74e7f30090aac276d5b3
--- /dev/null
+++ b/Trigger/TrigSteer/TrigSteering/src/ResultBuilderMT.cxx
@@ -0,0 +1,49 @@
+/*
+  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "TrigSteering/ResultBuilderMT.h"
+
+// =============================================================================
+// Standard constructor
+// =============================================================================
+HLT::ResultBuilderMT::ResultBuilderMT(const std::string& type, const std::string& name, const IInterface* parent)
+  : AthAlgTool(type, name, parent) {
+  declareProperty("HLTResultWHKey", m_hltResultWHKey="HLTResult");
+}
+
+// =============================================================================
+// Standard destructor
+// =============================================================================
+HLT::ResultBuilderMT::~ResultBuilderMT() {}
+
+// =============================================================================
+// Implementation of IStateful::initialize
+// =============================================================================
+StatusCode HLT::ResultBuilderMT::initialize() {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  ATH_CHECK(m_hltResultWHKey.initialize());
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// Implementation of IStateful::finalize
+// =============================================================================
+StatusCode HLT::ResultBuilderMT::finalize() {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
+
+// =============================================================================
+// The main method of the tool
+// =============================================================================
+StatusCode HLT::ResultBuilderMT::buildResult(const EventContext& eventContext) const {
+  ATH_MSG_VERBOSE("start of " << __FUNCTION__);
+  auto hltResult = SG::makeHandle(m_hltResultWHKey,eventContext);
+  ATH_CHECK( hltResult.record(std::make_unique<HLT::HLTResultMT>()) );
+  ATH_MSG_DEBUG("Recorded HLTResultMT with key " << m_hltResultWHKey.key());
+  ATH_MSG_VERBOSE("end of " << __FUNCTION__);
+  return StatusCode::SUCCESS;
+}
diff --git a/Trigger/TrigSteer/TrigSteering/src/components/TrigSteering_entries.cxx b/Trigger/TrigSteer/TrigSteering/src/components/TrigSteering_entries.cxx
index 1a4885a3b340871659d78bcc6c99c8d37218eb89..399686097590d30a578ab14ea076a1ef9c47b511 100644
--- a/Trigger/TrigSteer/TrigSteering/src/components/TrigSteering_entries.cxx
+++ b/Trigger/TrigSteer/TrigSteering/src/components/TrigSteering_entries.cxx
@@ -6,6 +6,7 @@
 #include "TrigSteering/LoopbackConverterFromPersistency.h"
 #include "TrigSteering/Lvl2ConverterFromPersistency.h"
 #include "TrigSteering/ResultBuilder.h"
+#include "TrigSteering/ResultBuilderMT.h"
 #include "TrigSteering/RandomScaler.h"
 //#include "TrigSteering/PeriodicScaler.h"
 #include "TrigSteering/ScalerSvc.h"
@@ -26,6 +27,7 @@ DECLARE_COMPONENT( HLT::TrigSteer )
 DECLARE_COMPONENT( HLT::ScalerSvc )
 
 DECLARE_COMPONENT( HLT::ResultBuilder )
+DECLARE_COMPONENT( HLT::ResultBuilderMT )
 DECLARE_COMPONENT( HLT::RandomScaler )
 DECLARE_COMPONENT( HLT::Lvl1ResultAccessTool )
 DECLARE_COMPONENT( HLT::HLTResultAccessTool )