From e0e276d8c7938bc5b39ea963d8f21400233f26d2 Mon Sep 17 00:00:00 2001
From: Florian Schmaus <flow@cs.fau.de>
Date: Fri, 22 Jan 2021 12:52:55 +0100
Subject: [PATCH] Convert RuntimeStrategyFactory to std::function<>

---
 emper/Runtime.cpp                             | 17 ++++-----
 emper/Runtime.hpp                             | 13 ++++---
 emper/RuntimeBuilder.hpp                      | 13 +++----
 emper/strategies/laws/LawsStrategy.cpp        |  7 +++-
 emper/strategies/laws/LawsStrategy.hpp        |  5 ++-
 emper/strategies/laws/LawsStrategyFactory.cpp | 11 ------
 emper/strategies/laws/LawsStrategyFactory.hpp | 18 ---------
 emper/strategies/laws/meson.build             |  1 -
 emper/strategies/ws/WsStrategy.cpp            |  9 ++++-
 emper/strategies/ws/WsStrategy.hpp            |  3 ++
 emper/strategies/ws/WsStrategyFactory.cpp     | 11 ------
 emper/strategies/ws/WsStrategyFactory.hpp     | 15 --------
 emper/strategies/ws/meson.build               |  1 -
 eval/Locality.cpp                             | 37 ++++++++++---------
 tests/SimpleLawsTest.cpp                      | 22 +++++------
 15 files changed, 71 insertions(+), 112 deletions(-)
 delete mode 100644 emper/strategies/laws/LawsStrategyFactory.cpp
 delete mode 100644 emper/strategies/laws/LawsStrategyFactory.hpp
 delete mode 100644 emper/strategies/ws/WsStrategyFactory.cpp
 delete mode 100644 emper/strategies/ws/WsStrategyFactory.hpp

diff --git a/emper/Runtime.cpp b/emper/Runtime.cpp
index e0875232..f6f2596b 100644
--- a/emper/Runtime.cpp
+++ b/emper/Runtime.cpp
@@ -28,8 +28,7 @@
 #include "Fiber.hpp"	// for Fiber
 #include "FiberSource.hpp"
 #include "NextFiberResult.hpp"
-#include "RuntimeStrategy.hpp"	// for RuntimeStrategy
-#include "RuntimeStrategyFactory.hpp"
+#include "RuntimeStrategy.hpp"
 #include "RuntimeStrategyStats.hpp"	 // for RuntimeStrategyStats
 #include "WorkerLocalData.hpp"
 #include "emper-config.h"
@@ -43,9 +42,9 @@
 #include "stats/Worker.hpp"
 
 #ifdef EMPER_DEFAULT_SCHEDULING_STRATEGY_WORK_STEALING
-#include "strategies/ws/WsStrategyFactory.hpp"
+#include "strategies/ws/WsStrategy.hpp"
 #elif defined EMPER_DEFAULT_SCHEDULING_STRATEGY_LOCALITY_AWARE_WORK_STEALING
-#include "strategies/laws/LawsStrategyFactory.hpp"
+#include "strategies/laws/LawsStrategy.hpp"
 #else
 #error "Unknown default scheduling strategy"
 #endif
@@ -62,11 +61,11 @@
 std::mutex Runtime::currentRuntimeMutex;
 Runtime* Runtime::currentRuntime;
 
-RuntimeStrategyFactory& Runtime::DEFAULT_STRATEGY =
+Runtime::StrategyFactory Runtime::DEFAULT_STRATEGY_FACTORY =
 #ifdef EMPER_DEFAULT_SCHEDULING_STRATEGY_WORK_STEALING
-		WsStrategyFactory::INSTANCE
+		WsStrategy::getFactory()
 #elif defined EMPER_DEFAULT_SCHEDULING_STRATEGY_LOCALITY_AWARE_WORK_STEALING
-		LawsStrategyFactory::INSTANCE
+		LawsStrategy::getFactory()
 #else
 #error "Unknown default scheduling strategy"
 #endif
@@ -79,13 +78,13 @@ bool Runtime::guardPageTouchCausesExitSuccess = false;
 struct sigaction Runtime::oldact {};
 
 Runtime::Runtime(workerid_t workerCount, const std::vector<NewWorkerHook>& newWorkerHooks,
-								 bool pinWorkers, workerid_t pinningOffset, RuntimeStrategyFactory& strategyFactory,
+								 bool pinWorkers, workerid_t pinningOffset, const StrategyFactory& strategyFactory,
 								 unsigned int seed)
 		: workerCount(workerCount),
 			workerLatch(workerCount),
 			firstWorkerThreadExitLatch(workerCount),
 			secondWorkerThreadExitLatch(workerCount),
-			strategy(strategyFactory.constructRuntimeStrategy(*this)),
+			strategy(strategyFactory(*this)),
 			scheduler(strategy->getScheduler()),
 			dispatcher(strategy->getDispatcher()),
 			contextManager(*(new ContextManager(*this))),
diff --git a/emper/Runtime.hpp b/emper/Runtime.hpp
index 87ec2bf9..5daa0e97 100644
--- a/emper/Runtime.hpp
+++ b/emper/Runtime.hpp
@@ -36,7 +36,6 @@ class Dispatcher;
 class Fiber;
 struct NextFiberResult;
 class RuntimeStrategy;
-class RuntimeStrategyFactory;
 class RuntimeStrategyStats;
 template <typename D>
 class WorkerLocalData;
@@ -66,6 +65,8 @@ class Runtime : public Logger<LogSubsystem::RUNTI> {
  public:
 	using NewWorkerHook = std::function<void(workerid_t)>;
 
+	using StrategyFactory = std::function<RuntimeStrategy*(Runtime&)>;
+
  private:
 	static std::mutex currentRuntimeMutex;
 	static Runtime* currentRuntime;
@@ -113,7 +114,7 @@ class Runtime : public Logger<LogSubsystem::RUNTI> {
 	WorkerSleepStrategy workerSleepStrategy;
 	emper::WakeupStrategy wakeupStrategy;
 
-	static RuntimeStrategyFactory& DEFAULT_STRATEGY;
+	static StrategyFactory DEFAULT_STRATEGY_FACTORY;
 
 	static void printLastRuntimeStats(std::ostream& out = std::cout);
 
@@ -180,18 +181,18 @@ class Runtime : public Logger<LogSubsystem::RUNTI> {
  public:
 	Runtime() : Runtime(getDefaultWorkerCount()) {}
 
-	Runtime(workerid_t workerCount) : Runtime(workerCount, DEFAULT_STRATEGY) {}
+	Runtime(workerid_t workerCount) : Runtime(workerCount, DEFAULT_STRATEGY_FACTORY) {}
 
-	Runtime(RuntimeStrategyFactory& strategyFactory)
+	Runtime(const StrategyFactory& strategyFactory)
 			: Runtime(getDefaultWorkerCount(), strategyFactory) {}
 
-	Runtime(workerid_t workerCount, RuntimeStrategyFactory& strategyFactory,
+	Runtime(workerid_t workerCount, const StrategyFactory& strategyFactory,
 					unsigned int seed = std::random_device()())
 			: Runtime(workerCount, std::vector<NewWorkerHook>(), shouldPinWorkers(),
 								getDefaultPinningOffset(), strategyFactory, seed) {}
 
 	Runtime(workerid_t workerCount, const std::vector<NewWorkerHook>& newWorkerHooks, bool pinWorkers,
-					workerid_t pinningOffset, RuntimeStrategyFactory& strategyFactory, unsigned int seed);
+					workerid_t pinningOffset, const StrategyFactory& strategyFactory, unsigned int seed);
 
 	~Runtime();
 
diff --git a/emper/RuntimeBuilder.hpp b/emper/RuntimeBuilder.hpp
index 5e3e8b2e..b8acbc23 100644
--- a/emper/RuntimeBuilder.hpp
+++ b/emper/RuntimeBuilder.hpp
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: LGPL-3.0-or-later
-// Copyright © 2021 Florian Fischer
+// Copyright © 2021-2022 Florian Fischer, Florian Schmaus
 #pragma once
 
 #include <optional>
@@ -14,7 +14,7 @@ class RuntimeBuilder {
 
 	std::vector<Runtime::NewWorkerHook> newWorkerHooks;
 
-	RuntimeStrategyFactory* strategyFactory = nullptr;
+	std::optional<Runtime::StrategyFactory> strategyFactory = std::nullopt;
 
 	std::optional<bool> pinWorkers = std::nullopt;
 	std::optional<workerid_t> pinningOffset = std::nullopt;
@@ -42,8 +42,8 @@ class RuntimeBuilder {
 		return *this;
 	};
 
-	inline auto withStrategyFactory(RuntimeStrategyFactory* factory) -> RuntimeBuilder& {
-		this->strategyFactory = factory;
+	inline auto withStrategyFactory(Runtime::StrategyFactory strategyFactory) -> RuntimeBuilder& {
+		this->strategyFactory = strategyFactory;
 		return *this;
 	};
 
@@ -56,8 +56,7 @@ class RuntimeBuilder {
 		auto workerCount =
 				this->workerCount != 0 ? this->workerCount : Runtime::getDefaultWorkerCount();
 
-		auto* strategyFactory =
-				this->strategyFactory != nullptr ? this->strategyFactory : &Runtime::DEFAULT_STRATEGY;
+		auto strategyFactory = this->strategyFactory.value_or(Runtime::DEFAULT_STRATEGY_FACTORY);
 
 		auto pinWorkers = this->pinWorkers.value_or(Runtime::shouldPinWorkers());
 
@@ -65,6 +64,6 @@ class RuntimeBuilder {
 
 		auto seed = this->seed.value_or(std::random_device()());
 
-		return Runtime(workerCount, newWorkerHooks, pinWorkers, pinningOffset, *strategyFactory, seed);
+		return Runtime(workerCount, newWorkerHooks, pinWorkers, pinningOffset, strategyFactory, seed);
 	}
 };
diff --git a/emper/strategies/laws/LawsStrategy.cpp b/emper/strategies/laws/LawsStrategy.cpp
index 603391b4..3cf855f4 100644
--- a/emper/strategies/laws/LawsStrategy.cpp
+++ b/emper/strategies/laws/LawsStrategy.cpp
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: LGPL-3.0-or-later
-// Copyright © 2020-2021 Florian Schmaus
+// Copyright © 2020-2022 Florian Schmaus
 #include "LawsStrategy.hpp"
 
 #include <functional>
@@ -11,6 +11,11 @@
 
 thread_local LawsWorkerStats LawsStrategy::stats;
 
+auto LawsStrategy::getFactory() -> std::function<LawsStrategy*(Runtime&)> {
+	static auto factory = [](Runtime& runtime) { return new LawsStrategy(runtime); };
+	return factory;
+}
+
 LawsStrategy::LawsStrategy(Runtime& runtime)
 		: AbstractWorkStealingStrategy(runtime),
 			scheduler(runtime, *this),
diff --git a/emper/strategies/laws/LawsStrategy.hpp b/emper/strategies/laws/LawsStrategy.hpp
index c2eea7ed..dc124808 100644
--- a/emper/strategies/laws/LawsStrategy.hpp
+++ b/emper/strategies/laws/LawsStrategy.hpp
@@ -1,7 +1,8 @@
 // SPDX-License-Identifier: LGPL-3.0-or-later
-// Copyright © 2020-2021 Florian Schmaus
+// Copyright © 2020-2022 Florian Schmaus
 #pragma once
 
+#include <functional>
 #include <memory>
 
 #include "WorkerLocalData.hpp"
@@ -31,6 +32,8 @@ class LawsStrategy : public AbstractWorkStealingStrategy {
 	auto getDispatcher() -> LawsDispatcher& override;
 
  public:
+	static auto getFactory() -> std::function<LawsStrategy*(Runtime&)>;
+
 	auto getStats() -> std::shared_ptr<RuntimeStrategyStats> override;
 
 	friend LawsScheduler;
diff --git a/emper/strategies/laws/LawsStrategyFactory.cpp b/emper/strategies/laws/LawsStrategyFactory.cpp
deleted file mode 100644
index 1dc946c0..00000000
--- a/emper/strategies/laws/LawsStrategyFactory.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-// SPDX-License-Identifier: LGPL-3.0-or-later
-// Copyright © 2021 Florian Schmaus
-#include "strategies/laws/LawsStrategyFactory.hpp"
-
-class Runtime;
-
-LawsStrategyFactory LawsStrategyFactory::INSTANCE;
-
-auto LawsStrategyFactory::constructRuntimeStrategy(Runtime& runtime) -> LawsStrategy* {
-	return new LawsStrategy(runtime);
-}
diff --git a/emper/strategies/laws/LawsStrategyFactory.hpp b/emper/strategies/laws/LawsStrategyFactory.hpp
deleted file mode 100644
index 2ae89ea5..00000000
--- a/emper/strategies/laws/LawsStrategyFactory.hpp
+++ /dev/null
@@ -1,18 +0,0 @@
-// SPDX-License-Identifier: LGPL-3.0-or-later
-// Copyright © 2021 Florian Schmaus
-#pragma once
-
-#include "RuntimeStrategyFactory.hpp"
-#include "strategies/laws/LawsStrategy.hpp"
-
-class Runtime;
-
-class LawsStrategyFactory : public RuntimeStrategyFactory {
- private:
-	LawsStrategyFactory() = default;
-
- public:
-	auto constructRuntimeStrategy(Runtime& runtime) -> LawsStrategy* override;
-
-	static LawsStrategyFactory INSTANCE;
-};
diff --git a/emper/strategies/laws/meson.build b/emper/strategies/laws/meson.build
index b36183e6..3297836b 100644
--- a/emper/strategies/laws/meson.build
+++ b/emper/strategies/laws/meson.build
@@ -1,6 +1,5 @@
 emper_cpp_sources += files(
   'LawsStrategy.cpp',
-  'LawsStrategyFactory.cpp',
   'LawsStrategyStats.cpp',
   'LawsScheduler.cpp',
   'LawsDispatcher.cpp',
diff --git a/emper/strategies/ws/WsStrategy.cpp b/emper/strategies/ws/WsStrategy.cpp
index b6eb19e0..60c78df6 100644
--- a/emper/strategies/ws/WsStrategy.cpp
+++ b/emper/strategies/ws/WsStrategy.cpp
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: LGPL-3.0-or-later
-// Copyright © 2020-2021 Florian Schmaus
+// Copyright © 2020-2022 Florian Schmaus
 #include "WsStrategy.hpp"
 
 #include "WsDispatcher.hpp"
@@ -9,6 +9,13 @@
 class Runtime;
 class RuntimeStrategyStats;
 
+auto WsStrategy::getFactory() -> std::function<WsStrategy*(Runtime&)> {
+	static std::function<WsStrategy*(Runtime&)> factory = [](Runtime& runtime) {
+		return new WsStrategy(runtime);
+	};
+	return factory;
+}
+
 WsStrategy::WsStrategy(Runtime& runtime)
 		: AbstractWorkStealingStrategy(runtime), scheduler(runtime, *this), dispatcher(runtime) {}
 
diff --git a/emper/strategies/ws/WsStrategy.hpp b/emper/strategies/ws/WsStrategy.hpp
index 1a8d701a..05e27691 100644
--- a/emper/strategies/ws/WsStrategy.hpp
+++ b/emper/strategies/ws/WsStrategy.hpp
@@ -2,6 +2,7 @@
 // Copyright © 2020-2021 Florian Schmaus
 #pragma once
 
+#include <functional>
 #include <memory>
 
 #include "strategies/AbstractWorkStealingStrategy.hpp"
@@ -27,6 +28,8 @@ class WsStrategy final : public AbstractWorkStealingStrategy {
 	auto getDispatcher() -> WsDispatcher& override;
 
  public:
+	static auto getFactory() -> std::function<WsStrategy*(Runtime&)>;
+
 	auto getStats() -> std::shared_ptr<RuntimeStrategyStats> override;
 
 	friend WsScheduler;
diff --git a/emper/strategies/ws/WsStrategyFactory.cpp b/emper/strategies/ws/WsStrategyFactory.cpp
deleted file mode 100644
index fd5151d0..00000000
--- a/emper/strategies/ws/WsStrategyFactory.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-// SPDX-License-Identifier: LGPL-3.0-or-later
-// Copyright © 2021 Florian Schmaus
-#include "strategies/ws/WsStrategyFactory.hpp"
-
-class Runtime;
-
-WsStrategyFactory WsStrategyFactory::INSTANCE;
-
-auto WsStrategyFactory::constructRuntimeStrategy(Runtime& runtime) -> WsStrategy* {
-	return new WsStrategy(runtime);
-}
diff --git a/emper/strategies/ws/WsStrategyFactory.hpp b/emper/strategies/ws/WsStrategyFactory.hpp
deleted file mode 100644
index a3c7d04c..00000000
--- a/emper/strategies/ws/WsStrategyFactory.hpp
+++ /dev/null
@@ -1,15 +0,0 @@
-// SPDX-License-Identifier: LGPL-3.0-or-later
-// Copyright © 2021 Florian Schmaus
-#pragma once
-
-#include "RuntimeStrategyFactory.hpp"
-#include "strategies/ws/WsStrategy.hpp"
-
-class Runtime;
-
-class WsStrategyFactory : public RuntimeStrategyFactory {
- public:
-	auto constructRuntimeStrategy(Runtime& runtime) -> WsStrategy* override;
-
-	static WsStrategyFactory INSTANCE;
-};
diff --git a/emper/strategies/ws/meson.build b/emper/strategies/ws/meson.build
index 3cc10e2e..6554bc5a 100644
--- a/emper/strategies/ws/meson.build
+++ b/emper/strategies/ws/meson.build
@@ -1,6 +1,5 @@
 emper_cpp_sources += files(
   'WsStrategy.cpp',
-  'WsStrategyFactory.cpp',
   'WsStrategyStats.cpp',
   'WsScheduler.cpp',
   'WsDispatcher.cpp',
diff --git a/eval/Locality.cpp b/eval/Locality.cpp
index 67bb4149..b023cc32 100644
--- a/eval/Locality.cpp
+++ b/eval/Locality.cpp
@@ -1,23 +1,24 @@
 // SPDX-License-Identifier: LGPL-3.0-or-later
-// Copyright © 2020-2021 Florian Schmaus
+// Copyright © 2020-2022 Florian Schmaus
 #include <unistd.h>	 // for getopt, optarg
 
-#include <algorithm>	// for generate
-#include <chrono>			// for microseconds, high_resol...
-#include <cstdint>		// for uint8_t, UINT8_MAX
-#include <cstdlib>		// for abort, exit, EXIT_SUCCESS
-#include <iostream>		// for operator<<, basic_ostream
-#include <random>			// for mt19937, uniform_int_dis...
-#include <string>			// for string, operator<<, oper...
-
-#include "CountingPrivateSemaphore.hpp"							// for CPS
-#include "Debug.hpp"																// for DBG
-#include "Fiber.hpp"																// for Fiber, Fiber::NOT_AFFINE
-#include "PrivateSemaphore.hpp"											// for PS
-#include "Runtime.hpp"															// for Runtime
-#include "emper-common.h"														// for workeraffinity_t, UNUSED...
-#include "lib/DebugUtil.hpp"												// for enableStacktraceOnAborts
-#include "strategies/laws/LawsStrategyFactory.hpp"	// for LawsStrategy, LawsStrate...
+#include <algorithm>
+#include <chrono>
+#include <cstdint>
+#include <cstdlib>
+#include <functional>
+#include <iostream>
+#include <random>
+#include <string>
+
+#include "CountingPrivateSemaphore.hpp"	 // for CPS
+#include "Debug.hpp"										 // for DBG
+#include "Fiber.hpp"										 // for Fiber, Fiber::NOT_AFFINE
+#include "PrivateSemaphore.hpp"					 // for PS
+#include "Runtime.hpp"									 // for Runtime
+#include "emper-common.h"								 // for workeraffinity_t, UNUSED...
+#include "lib/DebugUtil.hpp"						 // for enableStacktraceOnAborts
+#include "strategies/laws/LawsStrategy.hpp"
 
 #define L1_CACHE_LINE_SIZE 64	 // 64 Bytes
 
@@ -255,7 +256,7 @@ auto main(UNUSED_ARG int argc, UNUSED_ARG char* argv[]) -> int {
 			runtime = new Runtime();
 			break;
 		case wslh:
-			runtime = new Runtime(LawsStrategyFactory::INSTANCE);
+			runtime = new Runtime(LawsStrategy::getFactory());
 			break;
 	}
 
diff --git a/tests/SimpleLawsTest.cpp b/tests/SimpleLawsTest.cpp
index 1aea69c9..47c87fe2 100644
--- a/tests/SimpleLawsTest.cpp
+++ b/tests/SimpleLawsTest.cpp
@@ -1,12 +1,13 @@
 // SPDX-License-Identifier: LGPL-3.0-or-later
-// Copyright © 2020-2021 Florian Schmaus
+// Copyright © 2020-2022 Florian Schmaus
 #include <array>
-#include <atomic>		 // for atomic, __atomic_base
-#include <cstdint>	 // for uint64_t, UINT64_MAX
-#include <cstdlib>	 // for free, exit, EXIT_FAILURE
-#include <cstring>	 // for memset
-#include <iostream>	 // for operator<<, endl, basic_...
-#include <random>		 // for mt19937_64, random_device
+#include <atomic>
+#include <cstdint>
+#include <cstdlib>
+#include <cstring>
+#include <functional>
+#include <iostream>
+#include <random>
 
 #include "Common.hpp"										 // for ALIGN_TO_CACHE_LINE
 #include "CountingPrivateSemaphore.hpp"	 // for CPS
@@ -14,12 +15,10 @@
 #include "Runtime.hpp"									 // for Runtime
 #include "emper-common.h"								 // for UNUSED_ARG, workeraffini...
 #include "lib/template_util.hpp"
-#include "strategies/laws/LawsStrategyFactory.hpp"
+#include "strategies/laws/LawsStrategy.hpp"
 
 namespace tu = emper::lib::template_util;
 
-class RuntimeStrategyFactory;
-
 static const unsigned int ROUND_COUNT = 10;
 static const unsigned int FIBER_LOOPS = 10;
 static const unsigned int PAYLOAD_COUNT = 4096;
@@ -108,8 +107,7 @@ static void alphaFun() {
 }
 
 auto main(UNUSED_ARG int args, UNUSED_ARG char* argv[]) -> int {
-	RuntimeStrategyFactory& lawsStrategyFactory = LawsStrategyFactory::INSTANCE;
-	Runtime runtime(lawsStrategyFactory);
+	Runtime runtime(LawsStrategy::getFactory());
 
 	Fiber* alphaFiber = Fiber::from(&alphaFun);
 
-- 
GitLab