From 84734e5c8d2797f876b3b5617fbbfd812970d4b4 Mon Sep 17 00:00:00 2001
From: Florian Fischer <florian.fl.fischer@fau.de>
Date: Tue, 16 Feb 2021 18:16:08 +0100
Subject: [PATCH] [IO] replace the std::mutex.try_lock with our own std::atomic
 implementation

---
 emper/io/IoContext.cpp          |  4 ++--
 emper/io/IoContext.hpp          |  7 +++----
 emper/lib/adt/AtomicTryLock.hpp | 25 +++++++++++++++++++++++++
 3 files changed, 30 insertions(+), 6 deletions(-)
 create mode 100644 emper/lib/adt/AtomicTryLock.hpp

diff --git a/emper/io/IoContext.cpp b/emper/io/IoContext.cpp
index 6768524f..90a59923 100644
--- a/emper/io/IoContext.cpp
+++ b/emper/io/IoContext.cpp
@@ -179,7 +179,7 @@ template void IoContext::submit<CallerEnvironment::ANYWHERE>(Future &future);
 template <CallerEnvironment callerEnvironment>
 void IoContext::reapCompletions() {
 	// Someone else is currently reaping completions
-	if (unlikely(!cq_mutex.try_lock())) {
+	if (unlikely(!cq_lock.try_lock())) {
 		return;
 	}
 
@@ -254,7 +254,7 @@ void IoContext::reapCompletions() {
 	}
 
 unlock:
-	cq_mutex.unlock();
+	cq_lock.unlock();
 }
 
 // Show the compiler our template incarnations
diff --git a/emper/io/IoContext.hpp b/emper/io/IoContext.hpp
index 37081f41..4031c963 100644
--- a/emper/io/IoContext.hpp
+++ b/emper/io/IoContext.hpp
@@ -11,13 +11,13 @@
 #include <cstdint>		 // for uint64_t
 #include <functional>	 // for less
 #include <memory>			 // for allocator
-#include <mutex>			 // for mutex
 
 #include "CallerEnvironment.hpp"	// for CallerEnvironment, EMPER
 #include "Debug.hpp"							// for LogSubsystem, LogSubsystem::IO, Logger
 #include "Runtime.hpp"						// for Runtime
 #include "emper-config.h"					// for EMPER_IO_WORKER_URING_ENTRIES
 #include "io/Stats.hpp"						// for Stats
+#include "lib/adt/AtomicTryLock.hpp"
 #include "lib/adt/LockedSet.hpp"	// for LockedSet
 
 namespace emper::io {
@@ -44,9 +44,8 @@ class IoContext : public Logger<LogSubsystem::IO> {
 	// to the global IoContext
 	static void startGlobalCompleter(IoContext &globalIo);
 
-	// Mutex protecting the completion queue of ring.
-	// It is used with try_lock() in reapCompletions.
-	std::mutex cq_mutex;
+	// TryLock protecting the completion queue of ring.
+	lib::adt::AtomicTryLock cq_lock;
 	struct io_uring ring;
 
 	// eventfd registered with ring.
diff --git a/emper/lib/adt/AtomicTryLock.hpp b/emper/lib/adt/AtomicTryLock.hpp
new file mode 100644
index 00000000..222d80e7
--- /dev/null
+++ b/emper/lib/adt/AtomicTryLock.hpp
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: LGPL-3.0-or-later
+// Copyright © 2020 Florian Fischer
+#pragma once
+
+#include <atomic>
+
+#include "Common.hpp"
+
+namespace emper::lib::adt {
+
+class ALIGN_TO_CACHE_LINE AtomicTryLock {
+ private:
+	std::atomic<bool> locked;
+
+ public:
+	AtomicTryLock(bool locked = false) : locked(locked) {}
+
+	auto try_lock() -> bool {
+		bool previously_locked = locked.exchange(true, std::memory_order_acquire);
+		return !previously_locked;
+	}
+
+	void unlock() { locked.store(false, std::memory_order_release); }
+};
+}	 // namespace emper::lib::adt
-- 
GitLab