From f3c3da02f080a61bfe67c58a79d6a3c6a31de673 Mon Sep 17 00:00:00 2001
From: scott snyder <sss@karma>
Date: Thu, 2 Sep 2021 13:25:53 -0400
Subject: [PATCH] CxxUtils: Add LockedPointer.

LockedPointer template class, to allow returning a held lock along
with a pointer in a movable object.
---
 Control/CxxUtils/CMakeLists.txt               |  2 +-
 Control/CxxUtils/CxxUtils/LockedPointer.h     | 55 +++++++++++++++++++
 Control/CxxUtils/share/LockedPointer_test.ref |  2 +
 Control/CxxUtils/test/LockedPointer_test.cxx  | 46 ++++++++++++++++
 4 files changed, 104 insertions(+), 1 deletion(-)
 create mode 100644 Control/CxxUtils/CxxUtils/LockedPointer.h
 create mode 100644 Control/CxxUtils/share/LockedPointer_test.ref
 create mode 100644 Control/CxxUtils/test/LockedPointer_test.cxx

diff --git a/Control/CxxUtils/CMakeLists.txt b/Control/CxxUtils/CMakeLists.txt
index e7899bebc55c..04e050bf1f22 100644
--- a/Control/CxxUtils/CMakeLists.txt
+++ b/Control/CxxUtils/CMakeLists.txt
@@ -132,7 +132,7 @@ 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 )
+      FPControl_test LockedPointer_test )
    atlas_add_test( ${test}
       SOURCES test/${test}.cxx
       LOG_IGNORE_PATTERN "no version information available"
diff --git a/Control/CxxUtils/CxxUtils/LockedPointer.h b/Control/CxxUtils/CxxUtils/LockedPointer.h
new file mode 100644
index 000000000000..efccbc849919
--- /dev/null
+++ b/Control/CxxUtils/CxxUtils/LockedPointer.h
@@ -0,0 +1,55 @@
+// This file's extension implies that it's C, but it's really -*- C++ -*-.
+/*
+ * Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration.
+ */
+/**
+ * @file CxxUtils/LockedPointer.h
+ * @author scott snyder <snyder@bnl.gov>
+ * @date Sep, 2021
+ * @brief A pointer together with a movable lock.
+ */
+
+
+#ifndef CXXUTILS_LOCKEDPOINTER_H
+#define CXXUTILS_LOCKEDPOINTER_H
+
+
+#include <mutex>
+
+
+namespace CxxUtils {
+
+
+/**
+ * @brief A pointer together with a movable lock.
+ *
+ * This class holds a pointer to T along with a unique_lock.
+ * It can be used where we want to return a pointer to an object
+ * protected by a lock, and so want to return the lock along
+ * with the pointer.
+ *
+ * Objects of this class may be moved but not copied (like unique_ptr).
+ */
+template <class T, class MUTEX=std::recursive_mutex>
+class LockedPointer
+{
+public:
+  LockedPointer (T& p, std::unique_lock<MUTEX>&& lock)
+    : m_lock (std::move (lock)),
+      m_p (p)
+  {
+  }
+
+  T* get() { return &m_p; }
+  T* operator->() { return &m_p; }
+  T& operator*() { return m_p; }
+
+private:
+  std::unique_lock<MUTEX> m_lock;
+  T& m_p;
+};
+
+} // namespace CxxUtils
+
+
+#endif // not CXXUTILS_LOCKEDPOINTER_H
diff --git a/Control/CxxUtils/share/LockedPointer_test.ref b/Control/CxxUtils/share/LockedPointer_test.ref
new file mode 100644
index 000000000000..562d2b65fa11
--- /dev/null
+++ b/Control/CxxUtils/share/LockedPointer_test.ref
@@ -0,0 +1,2 @@
+CxxUtils/LockedPointer_test
+test1
diff --git a/Control/CxxUtils/test/LockedPointer_test.cxx b/Control/CxxUtils/test/LockedPointer_test.cxx
new file mode 100644
index 000000000000..531d71d9106e
--- /dev/null
+++ b/Control/CxxUtils/test/LockedPointer_test.cxx
@@ -0,0 +1,46 @@
+/*
+  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+*/
+/**
+ * @file CxxUtils/test/LockedPointer_test.cxx
+ * @author scott snyder
+ * @date Sep 2021
+ * @brief Regression tests for LockedPointer.
+ */
+
+
+#undef NDEBUG
+#include "CxxUtils/LockedPointer.h"
+#include <mutex>
+#include <iostream>
+#include <cassert>
+
+
+void test1a (CxxUtils::LockedPointer<int> p)
+{
+  assert (*p == 42);
+}
+
+void test1()
+{
+  std::cout << "test1\n";
+
+  std::recursive_mutex m;
+  int x = 42;
+
+  {
+    std::unique_lock l (m);
+    CxxUtils::LockedPointer<int> p (x, std::move(l));
+    assert (*p == 42);
+    assert (*p.get() == 42);
+    test1a (std::move (p));
+  }
+}
+
+
+int main()
+{
+  std::cout << "CxxUtils/LockedPointer_test\n";
+  test1();
+  return 0;
+}
-- 
GitLab