diff --git a/Control/CxxUtils/CMakeLists.txt b/Control/CxxUtils/CMakeLists.txt
index fc349195ee855bd675a9651eda9d29efb1e3ba86..bb622480c55757e654f12cd08fae937ba9bb51f8 100644
--- a/Control/CxxUtils/CMakeLists.txt
+++ b/Control/CxxUtils/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
 
 # Declare the package name:
 atlas_subdir( CxxUtils )
@@ -132,7 +132,8 @@ foreach( test sincos_test ArrayScanner_test Arrayrep_test
       restrict_test vectorize_test get_unaligned_test aligned_vector_test
       vec_int_test vec_float_test vec_fb_int_test vec_fb_float_test
       ConcurrentHashmapImpl_test SimpleUpdater_test hexdump_test
-      FPControl_test LockedPointer_test nodiscard_test)
+      FPControl_test LockedPointer_test nodiscard_test span_test
+      reverse_wrapper_test )
    atlas_add_test( ${test}
       SOURCES test/${test}.cxx
       LOG_IGNORE_PATTERN "no version information available"
diff --git a/Control/CxxUtils/CxxUtils/reverse_wrapper.h b/Control/CxxUtils/CxxUtils/reverse_wrapper.h
new file mode 100644
index 0000000000000000000000000000000000000000..8b8d5a505555b60dcb5ad821d881dfb20b8afefc
--- /dev/null
+++ b/Control/CxxUtils/CxxUtils/reverse_wrapper.h
@@ -0,0 +1,52 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+/*
+ * Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration.
+ */
+/**
+ * @file CxxUtils/reverse_wrapper.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Jan, 2022
+ * @brief Helper for iterating over a container in reverse order.
+ *
+ * Given a container @c c, this code will iterate over the container
+ * in reverse order:
+ *
+ *@code
+ *   for (... elt : CxxUtils::make_reverse_wrapper (c)) {
+ @endcode
+ */
+
+
+#ifndef CXXUTILS_REVERSE_WRAPPER_H
+#define CXXUTILS_REVERSE_WRAPPER_H
+
+
+namespace CxxUtils {
+
+
+/**
+ * @brief Adapter for a container-like class to be used in a range-for
+ *        so as to iterate in the reverse direction.
+ */
+template <class C>
+class reverse_wrapper
+{
+public:
+  reverse_wrapper (C& r) : m_r (r) {}
+  auto begin() { return m_r.rbegin(); }
+  auto end() { return m_r.rend(); }
+  C& m_r;
+};
+
+
+/**
+ * @brief Make a @c reverse_wrapper for a given container-like object.
+ */
+template <class T>
+auto make_reverse_wrapper (T& r) { return reverse_wrapper(r); }
+
+
+} // namespace CxxUtils
+
+
+#endif // not CXXUTILS_REVERSE_WRAPPER_H
diff --git a/Control/CxxUtils/CxxUtils/span.h b/Control/CxxUtils/CxxUtils/span.h
new file mode 100644
index 0000000000000000000000000000000000000000..24a3d40e332d8b08d3092f92a37d0acfd1ab87de
--- /dev/null
+++ b/Control/CxxUtils/CxxUtils/span.h
@@ -0,0 +1,276 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+/*
+ * Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration.
+ */
+/**
+ * @file CxxUtils/span.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Jan, 2022
+ * @brief Simplified version of the C++20 std::span.
+ */
+
+
+#ifndef CXXUTILS_SPAN_H
+#define CXXUTILS_SPAN_H
+
+
+#include <cstdlib>
+#include <type_traits>
+#include <iterator>
+#include <cassert>
+
+
+namespace CxxUtils {
+
+
+/// Used to specify a subrange of indefinite size in subspan().
+inline constexpr size_t dynamic_extent = static_cast<size_t>(-1);
+
+
+/**
+ * @brief Simplified version of the C++20 std::span.
+ *
+ * This class is meant to be very similar to the C++20 std::span class.
+ * There are however a few differences.
+ *  - The option for a fixed-length span is not implemented; hence, there
+ *    is no second template argument.
+ *  - Constructors from arrays / std::array are not implemented.
+ *  - The external member functions as_bytes / as_writable_bytes and
+ *    deduction guides are not implemented.
+ *
+ * Contact the core sw group if any of these are a problem.
+ *
+ * In addition:
+ *  - The concept requirements on the constructors are not checked.
+ *  - Accessor methods are split into const / non-const versions.
+ *    This is required to avoid warnings from the thread-safety checker,
+ *    but be careful of potential incompatibilies with std::span.
+ *    Again, contact the core sw group if this is an issue.
+ */
+template <class T>
+class span
+{
+public:
+  /// Required typedefs.
+  using element_type           = T;
+  using value_type             = std::remove_cv_t<T>;
+  using size_type              = size_t;
+  using difference_type        = ptrdiff_t;
+  using pointer                = T*;
+  using const_pointer          = const T*;
+  using reference              = element_type&;
+  using const_reference        = const element_type&;
+  using iterator               = pointer;
+  using const_iterator         = const_pointer;
+  using reverse_iterator       = std::reverse_iterator<iterator>;
+  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+
+
+  /*
+   * @brief Default constructor.
+   * Makes an empty span.
+   */
+  span();
+
+
+  /**
+   * @brief Constructor from start and length.
+   * @param ptr Start of the span.
+   * @param sz Length of the span.
+   */
+  span (T* ptr, size_type sz);
+
+
+  /**
+   * @brief Constructor from start and end.
+   * @param beg Start of the span.
+   * @param end One past the end of the span.
+   */
+  span (T* beg, T* end);
+
+
+  // Default copy / assignment.
+  span (const span&) = default;
+  span& operator= (const span&) = default;
+
+  
+  /**
+   * @brief Return the size of the span.
+   */
+  constexpr size_type size() const noexcept;
+
+  
+  /**
+   * @brief Return the size of contents of the span, in bytes.
+   */
+  constexpr size_type size_bytes() const noexcept;
+
+  
+  /**
+   * @brief Test if the span is empty.
+   */
+  [[nodiscard]] constexpr bool empty() const noexcept;
+
+  
+  /**
+   * @brief Return a reference to the first element in the span.
+   */
+  constexpr reference front() noexcept;
+
+   
+  /**
+   * @brief Return a reference to the first element in the span.
+   */
+  constexpr const_reference front() const noexcept;
+
+  
+  /**
+   * @brief Return a reference to the last element in the span.
+   */
+  constexpr reference back() noexcept;
+
+  
+  /**
+   * @brief Return a reference to the last element in the span.
+   */
+  constexpr const_reference back() const noexcept;
+
+  
+  /**
+   * @brief Return a reference to the i-th element in the span.
+   * @param i Index of the element to return.
+   */
+  constexpr reference operator[] (size_type i) noexcept;
+
+  
+  /**
+   * @brief Return a reference to the i-th element in the span.
+   * @param i Index of the element to return.
+   */
+  constexpr const_reference operator[] (size_type i) const noexcept;
+
+  
+  /**
+   * @brief Return a pointer to the start of the span.
+   */
+  constexpr pointer data() noexcept;
+
+  
+  /**
+   * @brief Return a pointer to the start of the span.
+   */
+  constexpr const_pointer data() const noexcept;
+
+  
+  /**
+   * @brief Return a begin iterator.
+   */
+  constexpr iterator begin() noexcept;
+
+  
+  /**
+   * @brief Return a begin iterator.
+   */
+  constexpr const_iterator begin() const noexcept;
+
+  
+  /**
+   * @brief Return an end iterator.
+   */ 
+  constexpr iterator end() noexcept;
+
+  
+  /**
+   * @brief Return an end iterator.
+   */ 
+  constexpr const_iterator end() const noexcept;
+
+  
+  /**
+   * @brief Return a begin reverse iterator.
+   */
+  constexpr reverse_iterator rbegin() noexcept;
+
+  
+  /**
+   * @brief Return a begin reverse iterator.
+   */
+  constexpr const_reverse_iterator rbegin() const noexcept;
+
+  
+  /**
+   * @brief Return an end reverse iterator.
+   */
+  constexpr reverse_iterator rend() noexcept;
+
+
+  /**
+   * @brief Return an end reverse iterator.
+   */
+  constexpr const_reverse_iterator rend() const noexcept;
+
+
+  /**
+   * @brief Return a subspan from the start.
+   * @param n Number of elements in the subspan.
+   */
+  constexpr span first (size_type n) noexcept;
+
+  
+  /**
+   * @brief Return a subspan from the start.
+   * @param n Number of elements in the subspan.
+   */
+  constexpr span<const T> first (size_type n) const noexcept;
+
+  
+  /**
+   * @brief Return a subspan from the end.
+   * @param n Number of elements in the subspan.
+   */
+  constexpr span last (size_type n) noexcept;
+
+  
+  /**
+   * @brief Return a subspan from the end.
+   * @param n Number of elements in the subspan.
+   */
+  constexpr span<const T> last (size_type n) const noexcept;
+
+  
+  /**
+   * @brief Return a subspan.
+   * @param offs Starting element of the subspan.
+   * @param n Number of elements in the subspan.
+   *          If defaulted, take all remaining elements.
+   */
+  constexpr span
+  subspan (size_type offs, size_type n = dynamic_extent) noexcept;
+
+
+  /**
+   * @brief Return a subspan.
+   * @param offs Starting element of the subspan.
+   * @param n Number of elements in the subspan.
+   *          If defaulted, take all remaining elements.
+   */
+  constexpr span<const T>
+  subspan (size_type offs, size_type n = dynamic_extent) const noexcept;
+
+
+private:
+  /// Pointer to the start of the span.
+  T* m_ptr;
+
+  /// Number of elements in the span.
+  size_t m_size;
+};
+
+
+} // namespace CxxUtils
+
+
+#include "CxxUtils/span.icc"
+
+
+#endif // not CXXUTILS_SPAN_H
diff --git a/Control/CxxUtils/CxxUtils/span.icc b/Control/CxxUtils/CxxUtils/span.icc
new file mode 100644
index 0000000000000000000000000000000000000000..dc412903d9f12c4bd04eb56f2ae44d18510057c6
--- /dev/null
+++ b/Control/CxxUtils/CxxUtils/span.icc
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration.
+ */
+/**
+ * @file CxxUtils/span.icc
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Jan, 2022
+ * @brief Simplified version of the C++20 std::span.
+ */
+
+
+namespace CxxUtils {
+
+
+/*
+ * @brief Default constructor.
+ * Makes an empty span.
+ */
+template <class T>
+inline
+span<T>::span()
+  : m_ptr(nullptr),
+    m_size(0)
+{
+}
+
+
+/**
+  * @brief Constructor from start and length.
+  * @param ptr Start of the span.
+  * @param sz Length of the span.
+  */
+template <class T>
+inline
+span<T>::span (T* ptr, size_type sz)
+  : m_ptr(ptr),
+    m_size(sz)
+{
+}
+
+
+/**
+  * @brief Constructor from start and end.
+  * @param beg Start of the span.
+  * @param end One past the end of the span.
+  */
+template <class T>
+inline
+span<T>::span (T* beg, T* end)
+  : m_ptr(beg),
+    m_size (end-beg)
+{
+}
+
+
+/**
+  * @brief Return the size of the span.
+  */
+template <class T>
+inline
+constexpr typename span<T>::size_type
+span<T>::size() const noexcept
+{
+  return m_size;
+}
+
+
+/**
+  * @brief Return the size of contents of the span, in bytes.
+  */
+template <class T>
+inline
+constexpr typename span<T>::size_type
+span<T>::size_bytes() const noexcept
+{
+  return m_size * sizeof(element_type);
+}
+
+  
+/**
+  * @brief Test if the span is empty.
+  */
+template <class T>
+inline
+constexpr bool
+span<T>::empty() const noexcept
+{
+  return m_size == 0;
+}
+
+
+/**
+  * @brief Return a reference to the first element in the span.
+  */
+template <class T>
+inline
+constexpr typename span<T>::reference
+span<T>::front() noexcept
+{
+  assert (m_ptr != nullptr);
+  return *m_ptr;
+}
+
+   
+/**
+  * @brief Return a reference to the first element in the span.
+  */
+template <class T>
+inline
+constexpr typename span<T>::const_reference
+span<T>::front() const noexcept
+{
+  assert (m_ptr != nullptr);
+  return *m_ptr;
+}
+
+  
+/**
+  * @brief Return a reference to the last element in the span.
+  */
+template <class T>
+inline
+constexpr typename span<T>::reference
+span<T>::back() noexcept
+{
+  assert (m_ptr != nullptr);
+  return *(m_ptr + m_size-1);
+}
+
+  
+/**
+  * @brief Return a reference to the last element in the span.
+  */
+template <class T>
+inline
+constexpr typename span<T>::const_reference
+span<T>::back() const noexcept
+{
+  assert (m_ptr != nullptr);
+  return *(m_ptr + m_size-1);
+}
+
+  
+/**
+  * @brief Return a reference to the i-th element in the span.
+  * @param i Index of the element to return.
+  */
+template <class T>
+inline
+constexpr typename span<T>::reference
+span<T>::operator[] (size_type i) noexcept
+{
+  assert (i < m_size);
+  return m_ptr[i];
+}
+
+  
+/**
+  * @brief Return a reference to the i-th element in the span.
+  * @param i Index of the element to return.
+  */
+template <class T>
+inline
+constexpr typename span<T>::const_reference
+span<T>::operator[] (size_type i) const noexcept
+{
+  assert (i < m_size);
+  return m_ptr[i];
+}
+
+
+/**
+  * @brief Return a pointer to the start of the span.
+  */
+template <class T>
+inline
+constexpr typename span<T>::pointer
+span<T>::data() noexcept
+{
+  return m_ptr;
+}
+
+  
+/**
+  * @brief Return a pointer to the start of the span.
+  */
+template <class T>
+inline
+constexpr typename span<T>::const_pointer
+span<T>::data() const noexcept
+{
+  return m_ptr;
+}
+
+
+/**
+  * @brief Return a begin iterator.
+  */
+template <class T>
+inline
+constexpr typename span<T>::iterator
+span<T>::begin() noexcept
+{
+  return m_ptr;
+}
+
+  
+/**
+  * @brief Return a begin iterator.
+  */
+template <class T>
+inline
+constexpr typename span<T>::const_iterator
+span<T>::begin() const noexcept
+{
+  return m_ptr;
+} 
+
+
+/**
+  * @brief Return an end iterator.
+  */
+template <class T>
+inline
+constexpr typename span<T>::iterator
+span<T>::end() noexcept
+{
+  return m_ptr + m_size;
+}
+
+  
+/**
+  * @brief Return an end iterator.
+  */
+template <class T>
+inline
+constexpr typename span<T>::const_iterator
+span<T>::end() const noexcept
+{
+  return m_ptr + m_size;
+}
+
+
+/**
+  * @brief Return a begin reverse iterator.
+  */
+template <class T>
+inline
+constexpr typename span<T>::reverse_iterator
+span<T>::rbegin() noexcept
+{
+  return reverse_iterator (end());
+}
+
+  
+/**
+  * @brief Return a begin reverse iterator.
+  */
+template <class T>
+inline
+constexpr typename span<T>::const_reverse_iterator
+span<T>::rbegin() const noexcept
+{
+  return const_reverse_iterator (end());
+}
+
+
+/**
+  * @brief Return an end reverse iterator.
+  */
+template <class T>
+inline
+constexpr typename span<T>::reverse_iterator
+span<T>::rend() noexcept
+{
+  return reverse_iterator (begin());
+}
+
+
+/**
+  * @brief Return an end reverse iterator.
+  */
+template <class T>
+inline
+constexpr typename span<T>::const_reverse_iterator
+span<T>::rend() const noexcept
+{
+  return const_reverse_iterator (begin());
+}
+
+
+/**
+  * @brief Return a subspan from the start.
+  * @param n Number of elements in the subspan.
+  */
+template <class T>
+inline
+constexpr span<T>
+span<T>::first (size_type n) noexcept
+{
+  assert (n <= size());
+  return span (m_ptr, n);
+}
+
+  
+/**
+  * @brief Return a subspan from the start.
+  * @param n Number of elements in the subspan.
+  */
+template <class T>
+inline
+constexpr span<const T>
+span<T>::first (size_type n) const noexcept
+{
+  assert (n <= size());
+  return span<const T> (m_ptr, n);
+}
+
+
+/**
+  * @brief Return a subspan from the end.
+  * @param n Number of elements in the subspan.
+  */
+template <class T>
+inline
+constexpr span<T>
+span<T>::last (size_type n) noexcept
+{
+  assert (n <= size());
+  return span (m_ptr + (size() - n), n);
+}
+
+  
+/**
+  * @brief Return a subspan from the end.
+  * @param n Number of elements in the subspan.
+  */
+template <class T>
+inline
+constexpr span<const T>
+span<T>::last (size_type n) const noexcept
+{
+  assert (n <= size());
+  return span<const T> (m_ptr + (size() - n), n);
+}
+
+
+/**
+  * @brief Return a subspan.
+  * @param offs Starting element of the subspan.
+  * @param n Number of elements in the subspan.
+  *          If defaulted, take all remaining elements.
+  */
+template <class T>
+inline
+constexpr span<T>
+span<T>::subspan (size_type offs, size_type n /*= dynamic_extent*/) noexcept
+{
+  assert (offs <= size());
+  if (n == dynamic_extent)
+    n = size() - offs;
+  else {
+    assert (n <= size());
+    assert (offs + n <= size());
+  }
+  return span (m_ptr + offs, n);
+}
+
+
+/**
+  * @brief Return a subspan.
+  * @param offs Starting element of the subspan.
+  * @param n Number of elements in the subspan.
+  *          If defaulted, take all remaining elements.
+  */
+template <class T>
+inline
+constexpr span<const T>
+span<T>::subspan (size_type offs, size_type n /*= dynamic_extent*/) const noexcept
+{
+  assert (offs <= size());
+  if (n == dynamic_extent)
+    n = size() - offs;
+  else {
+    assert (n <= size());
+    assert (offs + n <= size());
+  }
+  return span<const T> (m_ptr + offs, n);
+}
+
+
+} // namespace CxxUtils
diff --git a/Control/CxxUtils/share/reverse_wrapper_test.ref b/Control/CxxUtils/share/reverse_wrapper_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..7e6cc08a9b6f55041b8cffb3686c8f7ef32f283a
--- /dev/null
+++ b/Control/CxxUtils/share/reverse_wrapper_test.ref
@@ -0,0 +1,2 @@
+CxxUtils/reverse_wrapper_test.cxx
+test1
diff --git a/Control/CxxUtils/share/span_test.ref b/Control/CxxUtils/share/span_test.ref
new file mode 100644
index 0000000000000000000000000000000000000000..b171da04655e0d2999dd2394c9190f86ad492016
--- /dev/null
+++ b/Control/CxxUtils/share/span_test.ref
@@ -0,0 +1,2 @@
+CxxUtils/span_test.cxx
+test1
diff --git a/Control/CxxUtils/test/reverse_wrapper_test.cxx b/Control/CxxUtils/test/reverse_wrapper_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..cefb2300f5d138eb36058b8ad082a4e445e8e50b
--- /dev/null
+++ b/Control/CxxUtils/test/reverse_wrapper_test.cxx
@@ -0,0 +1,36 @@
+/*
+  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+*/
+/**
+ * @file CxxUtils/tests/reverse_wrapper_test.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Jan, 2022
+ * @brief Unit tests for reverse_wrapper.
+ */
+
+
+#undef NDEBUG
+#include "CxxUtils/reverse_wrapper.h"
+#include <cassert>
+#include <iostream>
+#include <vector>
+
+
+void test1()
+{
+  std::cout << "test1\n";
+  std::vector<int> v { 1, 2, 3 };
+  int acc = 0;
+  for (int i : CxxUtils::make_reverse_wrapper (v)) {
+    acc = acc*2 + i;
+  }
+  assert (acc == 17);
+}
+
+
+int main()
+{
+  std::cout << "CxxUtils/reverse_wrapper_test.cxx\n";
+  test1();
+  return 0;
+}
diff --git a/Control/CxxUtils/test/span_test.cxx b/Control/CxxUtils/test/span_test.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..dbdad647331e1b45881fd6d919a9442d9d6cb7ea
--- /dev/null
+++ b/Control/CxxUtils/test/span_test.cxx
@@ -0,0 +1,95 @@
+/*
+  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+*/
+/**
+ * @file CxxUtils/tests/span_test.cxx
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Jan, 2022
+ * @brief Unit tests for span.
+ */
+
+
+#undef NDEBUG
+#include "CxxUtils/span.h"
+#include "CxxUtils/reverse_wrapper.h"
+#include <cassert>
+#include <iostream>
+
+
+template <class ELT, class T>
+void test1a(T& s2)
+{
+  assert (s2.size() == 8);
+  assert (s2.size_bytes() == 8*sizeof(float));
+  assert (!s2.empty());
+  assert (s2.front() == 0);
+  assert (s2.back() == 7);
+  assert (s2[3] == 3);
+  assert (s2.data()[4] == 4);
+  assert (*s2.begin() == 0);
+  assert (s2.end() - s2.begin() == 8);
+  assert (s2.begin() != s2.end());
+  assert (s2.begin()+8 == s2.end());
+  assert (*s2.rbegin() == 7);
+  assert (s2.rend() - s2.rbegin() == 8);
+  assert (s2.rbegin() != s2.rend());
+  assert (s2.rbegin()+8 == s2.rend());
+  float acc = 0;
+  for (float f : s2) {
+    acc = 2*acc + f;
+  }
+  assert (acc == 247);
+  acc = 0;
+  for (float f : CxxUtils::make_reverse_wrapper (s2)) {
+    acc = 2*acc + f;
+  }
+  assert (acc == 1538);
+
+  CxxUtils::span<ELT> s3 = s2.first (3);
+  assert (s3.size() == 3);
+  assert (s3[1] == 1);
+
+  CxxUtils::span<ELT> s4 = s2.last (3);
+  assert (s4.size() == 3);
+  assert (s4[1] == 6);
+
+  CxxUtils::span<ELT> s5 = s2.subspan (4);
+  assert (s5.size() == 4);
+  assert (s5[1] == 5);
+
+  CxxUtils::span<ELT> s6 = s2.subspan (2, 3);
+  assert (s6.size() == 3);
+  assert (s6[1] == 3);
+}
+
+
+void test1()
+{
+  std::cout << "test1\n";
+  CxxUtils::span<float> s1;
+  assert (s1.size() == 0);
+  assert (s1.size_bytes() == 0);
+  assert (s1.empty());
+
+  float ff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+  CxxUtils::span<float> s2 (ff, 8);
+  test1a<float> (s2);
+  const CxxUtils::span<float>& cs2 = s2;
+  test1a<const float> (cs2);
+
+  CxxUtils::span<float> s3 = s2;
+  test1a<float> (s3);
+  s1 = s2;
+  test1a<float> (s1);
+
+  CxxUtils::span<float> s4 (ff, ff+8);
+  test1a<float> (s4);
+}
+
+
+int main()
+{
+  std::cout << "CxxUtils/span_test.cxx\n";
+  test1();
+  return 0;
+}