From 6b214da3dbb56bc6a797aafe691cc3d3eca13201 Mon Sep 17 00:00:00 2001
From: Florian Fischer <florian.fischer@muhq.space>
Date: Tue, 21 Sep 2021 14:16:13 +0200
Subject: [PATCH] [Common] add CACHE_LINE_EXCLUSIVE macro

The macro uses std::aligned_storage to ensure the symbol
is properly cache line aligned and cache line sized.
This prevents cache line sharing with another symbol.

The actual symbol is initialized with the placement new operator
and for now must have a constructor without arguments.
---
 emper/Common.hpp                           | 6 +++++-
 emper/sleep_strategy/PipeSleepStrategy.hpp | 4 +---
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/emper/Common.hpp b/emper/Common.hpp
index 351a194b..6fd18884 100644
--- a/emper/Common.hpp
+++ b/emper/Common.hpp
@@ -3,7 +3,8 @@
 #pragma once
 
 #include <functional>
-#include <sstream>	// IWYU pragma: keep
+#include <sstream>			// IWYU pragma: keep
+#include <type_traits>	// IWYU pragma: keep
 
 #include "emper-config.h"	 // IWYU pragma: keep
 
@@ -30,6 +31,9 @@ using func_t = std::function<void()>;
 #define unlikely(x) __builtin_expect(!!(x), 0)
 
 #define ALIGN_TO_CACHE_LINE alignas(64)
+#define CACHE_LINE_EXCLUSIVE(T, symbol)            \
+	std::aligned_storage<64, 64>::type __symbol_mem; \
+	T& symbol = *new (&__symbol_mem) T()
 
 [[noreturn]] void die(const char* message, bool usePerror);
 
diff --git a/emper/sleep_strategy/PipeSleepStrategy.hpp b/emper/sleep_strategy/PipeSleepStrategy.hpp
index d96e6955..6a67cf98 100644
--- a/emper/sleep_strategy/PipeSleepStrategy.hpp
+++ b/emper/sleep_strategy/PipeSleepStrategy.hpp
@@ -9,7 +9,6 @@
 #include <cstdint>
 #include <iostream>
 #include <stdexcept>
-#include <type_traits>
 #include <vector>
 
 #include "CallerEnvironment.hpp"
@@ -128,8 +127,7 @@ class PipeSleepStrategy : AbstractWorkerSleepStrategy<PipeSleepStrategy>,
 	Stats stats;
 
 	// Make sure the shared counter lives in an exlusive cache line
-	std::aligned_storage<64, 64>::type sleepers_mem;
-	std::atomic<int64_t>& sleepers = *reinterpret_cast<std::atomic<int64_t>*>(&sleepers_mem);
+	CACHE_LINE_EXCLUSIVE(std::atomic<int64_t>, sleepers);
 
 	template <CallerEnvironment callerEnvironment>
 	[[nodiscard]] auto createHint() -> TaggedPtr;
-- 
GitLab