diff --git a/.clang-tidy b/.clang-tidy index 92b5539a6dea15afbc68f4f0a9e754cede89359b..85e06ebcdd923aa1d2cf58e592c901e027d934db 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,16 +1,19 @@ ---- -Checks: 'clang-diagnostic-*,clang-analyzer-*,-clang-analyzer-alpha*' -HeaderFilterRegex: '' -AnalyzeTemporaryDtors: false -User: flo -CheckOptions: - - key: google-readability-braces-around-statements.ShortStatementLines - value: '1' - - key: google-readability-function-size.StatementThreshold - value: '800' - - key: google-readability-namespace-comments.ShortNamespaceLines - value: '10' - - key: google-readability-namespace-comments.SpacesBeforeComments - value: '2' -... +Checks: > + bugprone-*, + cert-*, + linuxkernel-*, + modernize-*, + performance-*, + portability-*, + readability-*, + -cert-err58-cpp, + -clang-diagnostic-empty-translation-unit, + -readability-braces-around-statements, + -readability-implicit-bool-conversion, + -readability-isolate-declaration, + -readability-magic-numbers, +WarningsAsErrors: > + clang-*, + readability-*, + performance-*, diff --git a/Makefile b/Makefile index d46c8401deb1c76db6b36a619bf279c011ee1977..8e4a770fac4c19e016359def81e5fc30f711b439 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,12 @@ SHELL = bash +# https://stackoverflow.com/a/39124162/194894 +word-dot = $(word $2,$(subst ., ,$1)) + +MESON_VERSION=$(shell meson --version) +MESON_MAJOR_VERSION=$(call word-dot, $(MESON_VERSION), 1) +MESON_MINOR_VERSION=$(call word-dot, $(MESON_VERSION), 2) + .PHONY: all build check check-format clean distclean\ doc release debug stresstest test @@ -25,6 +32,15 @@ debug: SMOKE_TEST_NINJA_TARGETS += iwyu +# Meson >= 0.52 will automatically generate a clang-tidy target if a +# .clang-tidy file is found. +# Source version check: https://stackoverflow.com/a/3732456/194894 +ifeq ($(shell [ $(MESON_MINOR_VERSION) -ge 52 ] && echo true), true) +SMOKE_TEST_NINJA_TARGETS += clang-tidy +else +$(warning old mesion version $(MESON_VERSION) detected, meson >= 0.52 required for clang-tidy) +endif + smoke-test: all check-format check-license cd build && meson test --suite smoke $(NINJA) -C build $(SMOKE_TEST_NINJA_TARGETS) diff --git a/apps/Main.cpp b/apps/Main.cpp index 85c91dfed2edda423923f0af73a18fa3dce7bde7..d74f1ea740e163a2044a9cae18a2d4b4d186f027 100644 --- a/apps/Main.cpp +++ b/apps/Main.cpp @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // Copyright © 2020 Florian Schmaus -#include <stdlib.h> // for exit, EXIT_SUCCESS - +#include <cstdlib> // for exit, EXIT_SUCCESS #include <iostream> // for basic_ostream::operator<< #include "BinaryPrivateSemaphore.hpp" // for BPS @@ -12,14 +11,14 @@ #include "Runtime.hpp" // for Runtime #include "emper-common.h" // for UNUSED_ARG -typedef struct { +using fibParams = struct { int n; int* result; PS* sem; -} fibParams; +}; static void fib(void* voidParams) { - fibParams* params = static_cast<fibParams*>(voidParams); + auto* params = static_cast<fibParams*>(voidParams); int n = params->n; int* result = params->result; PS* sem = params->sem; @@ -71,7 +70,7 @@ static void fibKickoff() { exit(EXIT_SUCCESS); } -int main(UNUSED_ARG int argc, UNUSED_ARG char* argv[]) { +auto main(UNUSED_ARG int argc, UNUSED_ARG char* argv[]) -> int { // const unsigned nthreads = std::thread::hardware_concurrency(); const unsigned nthreads = 2; diff --git a/apps/WorkerSleepExample.cpp b/apps/WorkerSleepExample.cpp index 06d1ebc9a0310f4e38f354aeaab79be65b45b59a..f3426d91e859fc88090c99749a75d7df673762c6 100644 --- a/apps/WorkerSleepExample.cpp +++ b/apps/WorkerSleepExample.cpp @@ -1,8 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // Copyright © 2020 Florian Schmaus -#include <stdlib.h> // for exit, EXIT_SUCCESS - #include <chrono> // for milliseconds, operator+, hig... +#include <cstdlib> // for exit, EXIT_SUCCESS #include <iostream> // for operator<<, basic_ostream, endl #include <ratio> // for ratio @@ -53,7 +52,7 @@ static void alphaFiber() { exit(EXIT_SUCCESS); } -int main(UNUSED_ARG int argc, UNUSED_ARG char* argv[]) { +auto main(UNUSED_ARG int argc, UNUSED_ARG char* argv[]) -> int { Runtime runtime; Fiber* fibFiber = Fiber::from(&alphaFiber); diff --git a/emper/Actor.hpp b/emper/Actor.hpp index 03719caa09880cfe38dd3bc27713af523caf1de2..a436899c7269ad3af78e6f6562bea326252c9855 100644 --- a/emper/Actor.hpp +++ b/emper/Actor.hpp @@ -23,7 +23,7 @@ class Actor { UnboundedBlockingMpscQueue<T> queue; - bool switchState(State oldState, State newState) { + auto switchState(State oldState, State newState) -> bool { return state.compare_exchange_strong(oldState, newState, std::memory_order_acq_rel); } @@ -64,9 +64,9 @@ class Actor { void tell(T t) { queue.put(t); } - size_t pendingMailboxItems() { return queue.size(); } + auto pendingMailboxItems() -> size_t { return queue.size(); } - bool waitUntilIdle(long timeout) { + auto waitUntilIdle(long timeout) -> bool { const auto start = std::chrono::steady_clock::now(); const auto deadline = start + std::chrono::milliseconds(timeout); while (!(queue.size() == 0 && state.load(std::memory_order_acquire) == Retrieving)) { diff --git a/emper/BinaryPrivateSemaphore.cpp b/emper/BinaryPrivateSemaphore.cpp index 77810cd809eba1c84eed73b6ecfd7f91f643de66..65cb65c62b9a4627b2ce939a10f47ad981321ef2 100644 --- a/emper/BinaryPrivateSemaphore.cpp +++ b/emper/BinaryPrivateSemaphore.cpp @@ -40,7 +40,7 @@ void BinaryPrivateSemaphore::wait() { }); } -Context* BinaryPrivateSemaphore::signalInternal() { +auto BinaryPrivateSemaphore::signalInternal() -> Context* { State currentState = bpsState.load(); assert(currentState != signaled); diff --git a/emper/BinaryPrivateSemaphore.hpp b/emper/BinaryPrivateSemaphore.hpp index 379761b8fb334456350ff8b0e91b5f00eff868bd..54410bca5b1bb1c96ca74a0938696d42fa7e62e8 100644 --- a/emper/BinaryPrivateSemaphore.hpp +++ b/emper/BinaryPrivateSemaphore.hpp @@ -18,10 +18,18 @@ class BinaryPrivateSemaphore : public PrivateSemaphore { std::atomic<State> bpsState; - Context* blockedContext; + // It would be OK to not initialize this member, since it is only + // set after the State is set accordingly and then only read if + // this state is found. However clang-tidy then starts to complain + // about clang-analyzer-optin.cplusplus.UninitializedObject, and + // furthermore, all call sites of wait() yield a + // clang-analyzer-optin.cplusplus.VirtualCall (it appears + // clang-tidy only checks if the object is fully initialized, not + // if the vcall is actually performed in a constructor. + Context* blockedContext = nullptr; protected: - Context* signalInternal() override; + auto signalInternal() -> Context* override; public: BinaryPrivateSemaphore() : bpsState(initial) {} @@ -29,4 +37,4 @@ class BinaryPrivateSemaphore : public PrivateSemaphore { void wait() override; }; -typedef BinaryPrivateSemaphore BPS; +using BPS = BinaryPrivateSemaphore; diff --git a/emper/Blockable.hpp b/emper/Blockable.hpp index 19311be8b03467b97450d6aaf1808d95944a38bd..3bab4824f33aff238616a30eec0f26b025e76af9 100644 --- a/emper/Blockable.hpp +++ b/emper/Blockable.hpp @@ -2,6 +2,8 @@ // Copyright © 2020 Florian Schmaus #pragma once +#include <utility> + #include "Common.hpp" #include "Context.hpp" #include "ContextManager.hpp" @@ -17,9 +19,13 @@ class Blockable : public Logger<logSubsystem> { Blockable(Runtime& runtime) : runtime(runtime), contextManager(runtime.getContextManager()) {} + // Older clang-tidy versions show a + // performance-unnecessary-value-param, newer versions do not show + // this error if std::move() is used (as we do). + // NOLINTNEXTLINE(performance-unnecessary-value-param) void block(func_t freshContextHook) { LOGD("block() blockedContext is " << Context::getCurrentContext()); - contextManager.saveAndStartNew(freshContextHook); + contextManager.saveAndStartNew(std::move(freshContextHook)); } void unblock(Context* context) { diff --git a/emper/Common.hpp b/emper/Common.hpp index 2e8f778850532bd449e066558602cdefc8348055..a78233cd2154bcf61ac1e3cd79475fa0b3620d27 100644 --- a/emper/Common.hpp +++ b/emper/Common.hpp @@ -4,7 +4,7 @@ #include <functional> -typedef std::function<void(void)> func_t; +using func_t = std::function<void()>; #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) @@ -22,4 +22,4 @@ typedef std::function<void(void)> func_t; [[noreturn]] void die(const char* message, bool usePerror); -typedef unsigned int WORD; +using WORD = unsigned int; diff --git a/emper/Context.cpp b/emper/Context.cpp index 4071269575eee24960c160d7af5cee6823c08aff..e497a6530b10a671557b42186a17b33434d22ce0 100644 --- a/emper/Context.cpp +++ b/emper/Context.cpp @@ -6,7 +6,7 @@ thread_local Context* Context::currentContext; -std::ostream& operator<<(std::ostream& strm, const Context& context) { +auto operator<<(std::ostream& strm, const Context& context) -> std::ostream& { strm << "Context " << &context << " [tos: " << context.tos << " bos: " << &context.context /* diff --git a/emper/Context.hpp b/emper/Context.hpp index 0df18a892724b694c8f8520bd48bb35cdf512c25..7fa56a377732962f72e9d41959eb6e04b97ab702 100644 --- a/emper/Context.hpp +++ b/emper/Context.hpp @@ -2,12 +2,13 @@ // Copyright © 2020 Florian Schmaus #pragma once -#include <stdint.h> // for uintptr_t - -#include <cassert> // for assert -#include <cstring> // for memset -#include <functional> // for function -#include <iosfwd> // for ostream +#include <cassert> // for assert +#include <cstdint> // for uintptr_t +#include <cstring> // for memset +#include <functional> // for function +#include <iosfwd> // for ostream +#include <type_traits> // for remove_reference<>::type +#include <utility> #include "Common.hpp" // for func_t, DIE, ALIGN_TO_CACHE_LINE #include "Debug.hpp" // for LOGD, LogSubsystem, LogSubsystem::C, Logger @@ -38,9 +39,10 @@ class ALIGN_TO_CACHE_LINE Context : Logger<LogSubsystem::C> { // Allign the stack to a cache line, so that it isn't shared with // the other members of this class. + // NOLINTNEXTLINE(modernize-avoid-c-arrays) ALIGN_TO_CACHE_LINE char context[CONTEXT_SIZE]; - friend std::ostream& operator<<(std::ostream&, const Context&); + friend auto operator<<(std::ostream&, const Context&) -> std::ostream&; /** * The first function that a newly started context will @@ -57,7 +59,8 @@ class ALIGN_TO_CACHE_LINE Context : Logger<LogSubsystem::C> { // cppcheck-suppress noExplicitConstructor selfInitialization Context(func_t mainFunction) // Align the Top-of-Stack (tos) to 16 byte. - : tos((void*)((uintptr_t)(context + CONTEXT_SIZE) & (~0xf))), mainFunction(mainFunction) { + : tos((void*)((uintptr_t)(context + CONTEXT_SIZE) & (~0xf))), + mainFunction(std::move(std::move(mainFunction))) { // valgrindStackId = VALGRIND_STACK_REGISTER(context, context + CONTEXT_SI); #ifndef NDEBUG @@ -89,6 +92,7 @@ class ALIGN_TO_CACHE_LINE Context : Logger<LogSubsystem::C> { *(alphaSavedIp) = reinterpret_cast<void*>(f); } + // NOLINTNEXTLINE(modernize-use-equals-default) ~Context() { // VALGRIND_STACK_DEREGISTER(valgrindStackId); } @@ -97,9 +101,9 @@ class ALIGN_TO_CACHE_LINE Context : Logger<LogSubsystem::C> { startAndResumeHook = []() {}; } - inline void setHook(func_t hook) { startAndResumeHook = hook; } + inline void setHook(func_t hook) { startAndResumeHook = std::move(hook); } - inline const void* getTos() const { return tos; } + [[nodiscard]] inline auto getTos() const -> const void* { return tos; } /** * Start this context. @@ -145,5 +149,5 @@ class ALIGN_TO_CACHE_LINE Context : Logger<LogSubsystem::C> { switch_and_load_context(&(context->savedStackpointer)); } - inline static Context* getCurrentContext() { return currentContext; } + inline static auto getCurrentContext() -> Context* { return currentContext; } }; diff --git a/emper/ContextManager.cpp b/emper/ContextManager.cpp index e39c00213047b7a541f50aaa5391e0331e0710f5..9883763e73bc97c8307cd52f02d5d3a8030f895c 100644 --- a/emper/ContextManager.cpp +++ b/emper/ContextManager.cpp @@ -2,9 +2,9 @@ // Copyright © 2020 Florian Schmaus #include "ContextManager.hpp" -#include <assert.h> // for assert - -#include <new> // for operator new, operator delete +#include <cassert> // for assert +#include <new> // for operator new, operator delete +#include <utility> #include "Context.hpp" // for Context #include "Debug.hpp" // for LOGD @@ -14,7 +14,7 @@ ContextManager::ContextManager(Runtime& runtime) : MemoryManager(runtime), runtime(runtime) { auto newWorkerHook = [this]() { for (unsigned int i = 0; i < CONTEXT_MANAGER_FIRST_LAYER_QUEUE_SIZE * 2; ++i) { - Context* context = new Context(this->runtime.dispatcher.getDispatchLoop()); + auto* context = new Context(this->runtime.dispatcher.getDispatchLoop()); putFreeContext(context); } }; @@ -23,7 +23,7 @@ ContextManager::ContextManager(Runtime& runtime) : MemoryManager(runtime), runti runtime.addNewWorkerHook(newWorkerHook); } -Context* ContextManager::getFreeContext() { +auto ContextManager::getFreeContext() -> Context* { #ifdef CM_WITH_MEMORY_MANAGER bool malloced; void* memory = getMemory(&malloced); @@ -54,7 +54,7 @@ void ContextManager::start() { */ void ContextManager::saveAndStartNew(func_t freshContextHook) { Context* freeContext = getFreeContext(); - freeContext->setHook(freshContextHook); + freeContext->setHook(std::move(freshContextHook)); Context::getCurrentContext()->saveAndStart(freeContext); } diff --git a/emper/ContextManager.hpp b/emper/ContextManager.hpp index 8e4e28a73050e0b1720990423d897323fd41859e..57dcaaa7c8a09ad240cedc80c6e8a694e1493df7 100644 --- a/emper/ContextManager.hpp +++ b/emper/ContextManager.hpp @@ -22,9 +22,9 @@ class ContextManager public: ContextManager(Runtime& runtime); - Context* getFreeContext(); + auto getFreeContext() -> Context*; - void putFreeContext(Context* context); + static void putFreeContext(Context* context); [[noreturn]] void start(); diff --git a/emper/CountingPrivateSemaphore.cpp b/emper/CountingPrivateSemaphore.cpp index 7011ac89054aa0dd036772173dfb0b4ed8470a2e..a74246a3ad540b112118fb6e8feefbe6065880bf 100644 --- a/emper/CountingPrivateSemaphore.cpp +++ b/emper/CountingPrivateSemaphore.cpp @@ -31,13 +31,15 @@ void CountingPrivateSemaphore::wait() { } } -Context* CountingPrivateSemaphore::signalInternal() { +auto CountingPrivateSemaphore::signalInternal() -> Context* { unsigned int oldCounter = counter.fetch_sub(1); assert(oldCounter >= 1); // If the counter is still non-zero after the decrement, somebody // else is responsible for scheduling the fiber. - if (oldCounter > 1) return nullptr; + if (oldCounter > 1) { + return nullptr; + } if (blockedContext.load() != nullptr && counter == 0) { // Try to swap out a blocked context, it is fine if this diff --git a/emper/CountingPrivateSemaphore.hpp b/emper/CountingPrivateSemaphore.hpp index 9ed3c3ead9919d3bba172a97e4ec5500f0dfce1c..ad3511da4fa0789fbee7e458b255c1dd6229938f 100644 --- a/emper/CountingPrivateSemaphore.hpp +++ b/emper/CountingPrivateSemaphore.hpp @@ -16,19 +16,19 @@ class CountingPrivateSemaphore : public PrivateSemaphore { std::atomic_uint counter; std::atomic<Context*> blockedContext; - inline Context* signalInternal() override; + inline auto signalInternal() -> Context* override; public: CountingPrivateSemaphore(); explicit CountingPrivateSemaphore(unsigned int counter); - inline unsigned int getCounter() { return counter.load(); }; + inline auto getCounter() -> unsigned int { return counter.load(); }; void incrementCounterByOne(); void incrementCounter(unsigned int count); - virtual void wait() override; + void wait() override; }; -typedef CountingPrivateSemaphore CPS; +using CPS = CountingPrivateSemaphore; diff --git a/emper/Debug.hpp b/emper/Debug.hpp index 2880007eb127f6ef4f0c6d72e5310ee1e57e9e47..dbf47c1c19ef845a3a656f4c3729e81b0425790e 100644 --- a/emper/Debug.hpp +++ b/emper/Debug.hpp @@ -17,54 +17,37 @@ #include <iostream> // IWYU pragma: keep #include <sstream> // IWYU pragma: keep -#define DBG(x) \ - do { \ - std::cerr << x << std::endl; \ - } while (false) -#define WDBG(x) \ - do { \ - std::stringstream sst; \ - sst << x; \ - worker_log("", sst.str()); \ - } while (false) +// If we apply clang-format to the following region, then clang-format +// will create multi-line macros. However clang-tidy's NOLINTNEXTLINE +// would then not work. :( + +// clang-format off + +// NOLINTNEXTLINE(bugprone-macro-parentheses) +#define DBG(x) do { std::cerr << x << std::endl; } while (false) +// NOLINTNEXTLINE(bugprone-macro-parentheses) +#define WDBG(x) do { std::stringstream sst; sst << x; worker_log("", sst.str()); } while (false) // To avoid "error: there are no arguments to ‘logD’ that depend on a // template parameter, so a declaration of ‘logD’ must be available" // we use "this->logD()" instead of simply "logD()" below. -#define LOGD(x) \ - do { \ - std::stringstream sst; \ - sst << x; \ - this->logD(sst.str()); \ - } while (false) -#define LOGDD(x) \ - do { \ - std::stringstream sst; \ - sst << x; \ - this->logDD(sst.str()); \ - } while (false) +// NOLINTNEXTLINE(bugprone-macro-parentheses) +#define LOGD(x) do { std::stringstream sst; sst << x; this->logD(sst.str()); } while (false) +// NOLINTNEXTLINE(bugprone-macro-parentheses) +#define LOGDD(x) do { std::stringstream sst; sst << x; this->logDD(sst.str()); } while (false) #endif -#define LOGI(x) \ - do { \ - std::cerr << "Info: " << x << std::endl; \ - } while (false) -#define LOGW(x) \ - do { \ - std::cerr << "Warning: " << x << std::endl; \ - } while (false) -#define LOGE(x) \ - do { \ - std::cerr << "Error: " << x << std::endl; \ - } while (false) - -#define ABORT(x) \ - do { \ - std::stringstream sst; \ - sst << x; \ - logI(sst.str()); \ - abort(); \ - } while (false) +// NOLINTNEXTLINE(bugprone-macro-parentheses) +#define LOGI(x) do { std::cerr << "Info: " << x << std::endl; } while (false) +// NOLINTNEXTLINE(bugprone-macro-parentheses) +#define LOGW(x) do { std::cerr << "Warning: " << x << std::endl; } while (false) +// NOLINTNEXTLINE(bugprone-macro-parentheses) +#define LOGE(x) do {std::cerr << "Error: " << x << std::endl; } while (false) + +// NOLINTNEXTLINE(bugprone-macro-parentheses) +#define ABORT(x) do { std::stringstream sst; sst << x; logI(sst.str()); abort(); } while (false) + +// clang-format on #define IGNORE_UNUSED_FUNCTION \ _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wunused-function\"") @@ -104,7 +87,7 @@ static const std::map<LogSubsystem, LogLevel> LOG_CONFIG = { template <LogSubsystem logSubsystem> class Logger { private: - static constexpr char const* getTagFor(LogSubsystem system) { + static constexpr auto getTagFor(LogSubsystem system) -> char const* { switch (system) { case LogSubsystem::PS: return "PS "; @@ -127,7 +110,7 @@ class Logger { } } - static constexpr bool shouldPrefixThis(LogSubsystem system) { + static constexpr auto shouldPrefixThis(LogSubsystem system) -> bool { switch (system) { case LogSubsystem::RUNTI: case LogSubsystem::SCHED: diff --git a/emper/Dispatcher.cpp b/emper/Dispatcher.cpp index 4179b274f436e9b77c76a57fbccaa4d2e3f7b390..0bef0cc50eb8ac37a53e42e9528cac5689749684 100644 --- a/emper/Dispatcher.cpp +++ b/emper/Dispatcher.cpp @@ -2,12 +2,12 @@ // Copyright © 2020 Florian Schmaus #include "Dispatcher.hpp" -#include <functional> // for _Bind_helper<>::type, bind - #include "Runtime.hpp" // for Runtime thread_local const Fiber* Dispatcher::currentFiber; -func_t Dispatcher::getDispatchLoop() { return std::bind(&Dispatcher::dispatchLoop, this); } +auto Dispatcher::getDispatchLoop() -> func_t { + return [this] { dispatchLoop(); }; +} void Dispatcher::putRuntimeWorkerToSleep() { runtime.dispatcherLoopSleep(); } diff --git a/emper/Dispatcher.hpp b/emper/Dispatcher.hpp index d85d22853ce119c8bdf3c1da9d07e6a61065d5a9..f21b2a422c4b1439779d13514d8d478876f438f3 100644 --- a/emper/Dispatcher.hpp +++ b/emper/Dispatcher.hpp @@ -2,9 +2,8 @@ // Copyright © 2020 Florian Schmaus #pragma once -#include <assert.h> // for assert - -#include <new> // for operator delete +#include <cassert> // for assert +#include <new> // for operator delete #include "Common.hpp" // for func_t #include "Debug.hpp" // for LOGD, LogSubsystem, LogSubsystem::DISP @@ -22,7 +21,7 @@ class Dispatcher : public Logger<LogSubsystem::DISP> { virtual void dispatchLoop() = 0; - func_t getDispatchLoop(); + auto getDispatchLoop() -> func_t; inline void dispatch(const Fiber* fiber) { LOGD("executing fiber " << fiber); @@ -30,34 +29,34 @@ class Dispatcher : public Logger<LogSubsystem::DISP> { fiber->run(); } - static inline bool isRunnable(Fiber* fiber) { return fiber->setRunnableFalse(); } + static inline auto isRunnable(Fiber* fiber) -> bool { return fiber->setRunnableFalse(); } - static inline workeraffinity_t* getAffinityBuffer(Fiber* fiber) { + static inline auto getAffinityBuffer(Fiber* fiber) -> workeraffinity_t* { return fiber->getAffinityBuffer(); } - static inline unsigned int decreaseRefCount(Fiber* fiber) { + static inline auto decreaseRefCount(Fiber* fiber) -> unsigned int { return fiber->doAtomicDecrRefCount(); } - inline void recycle(const Fiber* fiber) { delete fiber; } + static inline void recycle(const Fiber* fiber) { delete fiber; } void putRuntimeWorkerToSleep(); public: Dispatcher(Runtime& runtime) : runtime(runtime) {} - static const Fiber& getCurrentFiber() { + static auto getCurrentFiber() -> const Fiber& { const Fiber* fiber = getCurrentFiberPtr(); return *fiber; } - static const Fiber* getCurrentFiberPtr() { + static auto getCurrentFiberPtr() -> const Fiber* { assert(currentFiber); return currentFiber; } - static bool isDispatchedControlFlow() { return currentFiber != nullptr; } + static auto isDispatchedControlFlow() -> bool { return currentFiber != nullptr; } friend ContextManager; }; diff --git a/emper/Fiber.cpp b/emper/Fiber.cpp index b4b406efeabf0c39bebe02d299958829f3d7700b..61423875051d605f86cf323f3771f94541dddd91 100644 --- a/emper/Fiber.cpp +++ b/emper/Fiber.cpp @@ -11,8 +11,8 @@ void Fiber::run() const { function(arg); } -std::ostream& operator<<(std::ostream& strm, const Fiber& fiber) { - strm << "Fiber [ptr=" << &fiber << " func=" << fiber.function.target<void(void*)>() +auto operator<<(std::ostream& strm, const Fiber& fiber) -> std::ostream& { + strm << "Fiber [ptr=" << &fiber << " func=" << (fiber.function.target<void(void*)>() != nullptr) << " arg=" << fiber.arg; if (fiber.affinity) { diff --git a/emper/Fiber.hpp b/emper/Fiber.hpp index a679352ccb4d18083752e95c66aa986c05f82edf..2e95c8a8c8f462b31c04183bc4900a52b76e3e73 100644 --- a/emper/Fiber.hpp +++ b/emper/Fiber.hpp @@ -2,12 +2,14 @@ // Copyright © 2020 Florian Schmaus #pragma once -#include <atomic> // for atomic_uint, atomic, __atomic_base, memory... -#include <cassert> // for assert -#include <climits> // for UINT_MAX -#include <functional> // for function -#include <iosfwd> // for ostream -#include <new> // for operator new +#include <atomic> // for atomic_uint, atomic, __atomic_base, memory... +#include <cassert> // for assert +#include <climits> // for UINT_MAX +#include <functional> // for function +#include <iosfwd> // for ostream +#include <new> // for operator new +#include <type_traits> // for remove_reference<>::type // IWYU pragma: keep +#include <utility> #include "Common.hpp" // for ALIGN_TO_CACHE_LINE #include "Debug.hpp" // for LogSubsystem, LogSubsystem::F, Logger @@ -23,8 +25,8 @@ class MpscQueue; class ALIGN_TO_CACHE_LINE Fiber : public Logger<LogSubsystem::F> { public: - typedef std::function<FIBER_FUN_TEMPLATE_ARG> fiber_fun_t; - typedef std::function<FIBER_FUN0_TEMPLATE_ARG> fiber_fun0_t; + using fiber_fun_t = std::function<void(void*)>; + using fiber_fun0_t = std::function<void()>; static const workeraffinity_t NOT_AFFINE = -1; @@ -52,16 +54,16 @@ class ALIGN_TO_CACHE_LINE Fiber : public Logger<LogSubsystem::F> { protected: Fiber(fiber_fun_t function, void* arg, workeraffinity_t* affinity) - : function(function), arg(arg), affinity(affinity){}; + : function(std::move(function)), arg(arg), affinity(affinity){}; // cppcheck-suppress uninitMemberVar - explicit Fiber(fiber_fun0_t function, workeraffinity_t* affinity) + explicit Fiber(const fiber_fun0_t& function, workeraffinity_t* affinity) : Fiber([function](UNUSED_ARG void* arg) { function(); }, nullptr, affinity) {} - Fiber(fiber_fun_t function, void* arg) : Fiber(function, arg, nullptr){}; + Fiber(fiber_fun_t function, void* arg) : Fiber(std::move(function), arg, nullptr){}; // cppcheck-suppress uninitMemberVar - explicit Fiber(fiber_fun0_t function) : Fiber(function, nullptr) {} + explicit Fiber(const fiber_fun0_t& function) : Fiber(function, nullptr) {} virtual ~Fiber() = default; @@ -70,11 +72,11 @@ class ALIGN_TO_CACHE_LINE Fiber : public Logger<LogSubsystem::F> { private: inline void setMpscNext(Fiber* next) { mpscNext = next; } - inline Fiber* getMpscNext() { return mpscNext; } + inline auto getMpscNext() -> Fiber* { return mpscNext; } - inline workeraffinity_t* getAffinityBuffer() const { return affinity; } + [[nodiscard]] inline auto getAffinityBuffer() const -> workeraffinity_t* { return affinity; } - inline bool setRunnableFalse() { + inline auto setRunnableFalse() -> bool { bool res = runnable.load(std::memory_order_relaxed); if (!res) { // Fast path: 'runnable' was already set to false. No need @@ -86,12 +88,12 @@ class ALIGN_TO_CACHE_LINE Fiber : public Logger<LogSubsystem::F> { return runnable.exchange(false); } - inline unsigned int doAtomicIncrRefCount() { + inline auto doAtomicIncrRefCount() -> unsigned int { assert(referenceCounter < UINT_MAX); return ++referenceCounter; } - inline unsigned int doAtomicDecrRefCount() { + inline auto doAtomicDecrRefCount() -> unsigned int { assert(referenceCounter > 0); return --referenceCounter; } @@ -104,9 +106,9 @@ class ALIGN_TO_CACHE_LINE Fiber : public Logger<LogSubsystem::F> { friend class LawsScheduler; public: - unsigned int getFlag() const { return flag; } + [[nodiscard]] auto getFlag() const -> unsigned int { return flag; } - workeraffinity_t getAffinity() const { + [[nodiscard]] auto getAffinity() const -> workeraffinity_t { if (affinity == nullptr) { return NOT_AFFINE; } @@ -115,17 +117,19 @@ class ALIGN_TO_CACHE_LINE Fiber : public Logger<LogSubsystem::F> { void print() const; - friend std::ostream& operator<<(std::ostream&, const Fiber&); + friend auto operator<<(std::ostream&, const Fiber&) -> std::ostream&; - static inline Fiber* from(fiber_fun_t function, void* arg) { return new Fiber(function, arg); } + static inline auto from(fiber_fun_t function, void* arg) -> Fiber* { + return new Fiber(std::move(function), arg); + } - static inline Fiber* from(fiber_fun0_t function) { return new Fiber(function); } + static inline auto from(const fiber_fun0_t& function) -> Fiber* { return new Fiber(function); } - static inline Fiber* from(fiber_fun_t function, void* arg, workeraffinity_t* affinity) { - return new Fiber(function, arg, affinity); + static inline auto from(fiber_fun_t function, void* arg, workeraffinity_t* affinity) -> Fiber* { + return new Fiber(std::move(function), arg, affinity); } - static inline Fiber* from(fiber_fun0_t function, workeraffinity_t* affinity) { + static inline auto from(const fiber_fun0_t& function, workeraffinity_t* affinity) -> Fiber* { return new Fiber(function, affinity); } }; diff --git a/emper/FiberManager.cpp b/emper/FiberManager.cpp index d13f91cf6ae67dbde126518ef1015a55fd1ab026..028b88a1e1d8f6d423219155de2ec34651f4ab26 100644 --- a/emper/FiberManager.cpp +++ b/emper/FiberManager.cpp @@ -10,7 +10,7 @@ class Runtime; FiberManager::FiberManager(Runtime& runtime) : MemoryManager(runtime) {} -void* FiberManager::getFiberMemory() { +auto FiberManager::getFiberMemory() -> void* { #ifdef FM_WITH_MEMORY_MANAGER bool malloced; return getMemory(&malloced); diff --git a/emper/FiberManager.hpp b/emper/FiberManager.hpp index 09b6be653c77609800f926b805bfe56e346db152..a3d1413ac0cce335f09d03178d5369ff8818c23b 100644 --- a/emper/FiberManager.hpp +++ b/emper/FiberManager.hpp @@ -9,9 +9,9 @@ class Runtime; class FiberManager : protected MemoryManager<Fiber, 128, 64> { private: - void* getFiberMemory(); + static auto getFiberMemory() -> void*; - void putFiberMemory(Fiber* fiber); + static void putFiberMemory(Fiber* fiber); public: FiberManager(Runtime& runtime); diff --git a/emper/MemoryManager.hpp b/emper/MemoryManager.hpp index 07ee208bb30772548ca2b8a8e446c5764f21aab8..c25d0ab8eed9252a295cdfb88a05c088bab059fb 100644 --- a/emper/MemoryManager.hpp +++ b/emper/MemoryManager.hpp @@ -18,7 +18,7 @@ class MemoryManager { static thread_local adt::WsClQueue<void*, WS_QUEUE_SIZE> queue; - static void* mallocMemory() { + static auto mallocMemory() -> void* { void* memory; int res = posix_memalign(&memory, alignof(T), sizeof(T)); if (res != 0) { @@ -30,7 +30,7 @@ class MemoryManager { public: MemoryManager(Runtime& runtime); - void* getMemory(bool* malloced) { + auto getMemory(bool* malloced) -> void* { *malloced = false; void* memory = workerExclusiveQueue.get(); if (memory) return memory; diff --git a/emper/PrivateSemaphore.hpp b/emper/PrivateSemaphore.hpp index 2b095cdbc078b80a49144bbc06198de780bdc5e6..5fa679db7f0904ccec6226b5077da27a09605098 100644 --- a/emper/PrivateSemaphore.hpp +++ b/emper/PrivateSemaphore.hpp @@ -19,7 +19,7 @@ class PrivateSemaphore : protected Blockable<LogSubsystem::PS> { [[noreturn]] void unblockAndExit(Context* context) { contextManager.discardAndResume(context); } - virtual Context* signalInternal() = 0; + virtual auto signalInternal() -> Context* = 0; virtual void debugLog(const std::string& string) const { Logger::logD(string); } @@ -45,4 +45,4 @@ class PrivateSemaphore : protected Blockable<LogSubsystem::PS> { } }; -typedef PrivateSemaphore PS; +using PS = PrivateSemaphore; diff --git a/emper/Runtime.cpp b/emper/Runtime.cpp index 830b63924cdec4d30c25cf741ce61b22707bbed7..47157ff483dfb2ebd0f33583ac894dd377aecf27 100644 --- a/emper/Runtime.cpp +++ b/emper/Runtime.cpp @@ -2,8 +2,9 @@ // Copyright © 2020 Florian Schmaus #include "Runtime.hpp" -#include <errno.h> // for errno #include <pthread.h> // for pthread_t, pthread_attr_init + +#include <cerrno> // for errno // Non portable. #include <sched.h> // for cpu_set_t, CPU_SET, CPU_ZERO #include <sys/sysinfo.h> // for get_nprocs @@ -11,7 +12,6 @@ #include <unistd.h> // for syscall #include <cstdlib> // for rand, srand, abort -#include <ctime> // for time #include <memory> // for __shared_ptr_access, shared_ptr #include <ostream> // for operator<<, basic_ostream<>:... @@ -30,19 +30,18 @@ thread_local unsigned int Runtime::seed; thread_local workerid_t Runtime::workerId; RuntimeStrategy& Runtime::DEFAULT_STRATEGY = WsStrategy::INSTANCE; -Runtime::Runtime(workerid_t workerCount, RuntimeStrategy& strategy) +Runtime::Runtime(workerid_t workerCount, RuntimeStrategy& strategy, unsigned int seed) : workerCount(workerCount), workerLatch(workerCount), strategy(strategy), scheduler(strategy.getScheduler(*this)), dispatcher(strategy.getDispatcher(*this)), contextManager(*(new ContextManager(*this))), + randomEngine(seed), atLeastOneWorkerIsSleeping(false) { threads = new pthread_t[workerCount]; workerIds = new workerid_t[workerCount]; - std::srand(std::time(0)); - const int nprocs = get_nprocs(); { @@ -101,7 +100,7 @@ Runtime::~Runtime() { DBG("Runtime " << this << " terminated"); } -void* Runtime::workerLoop(void* voidWorkerId) { +auto Runtime::workerLoop(void* voidWorkerId) -> void* { workerId = *(workerid_t*)voidWorkerId; LOGD("Worker loop started by thread " << syscall(SYS_gettid)); @@ -112,9 +111,9 @@ void* Runtime::workerLoop(void* voidWorkerId) { } // Initialze the workers PRNG seed. - seed = std::rand(); + seed = uniformIntDistribution(randomEngine); - for (auto f : newWorkerHooks) f(); + for (const auto& f : newWorkerHooks) f(); workerLatch.count_down_and_wait(); @@ -124,7 +123,7 @@ void* Runtime::workerLoop(void* voidWorkerId) { return nullptr; } -Fiber* Runtime::nextFiber() { return scheduler.nextFiber(); } +auto Runtime::nextFiber() -> Fiber* { return scheduler.nextFiber(); } void Runtime::waitUntilFinished() { for (workerid_t i = 0; i < workerCount; ++i) { @@ -147,7 +146,7 @@ void Runtime::printLastRuntimeStats() { currentRuntime->printStats(); } -bool Runtime::inRuntime() { return dispatcher.isDispatchedControlFlow(); } +auto Runtime::inRuntime() -> bool { return Dispatcher::isDispatchedControlFlow(); } void Runtime::executeAndWait(std::function<void()> f) { if (inRuntime()) { diff --git a/emper/Runtime.hpp b/emper/Runtime.hpp index e573a9a1ffe14c57747566fa6ce089d910178d89..4234655148e49ba4937d9adc1288f97e7db6bc55 100644 --- a/emper/Runtime.hpp +++ b/emper/Runtime.hpp @@ -3,15 +3,16 @@ #pragma once #include <pthread.h> // for pthread_t -#include <stddef.h> // for size_t -#include <stdint.h> // for intptr_t #include <atomic> // for atomic, memory_order_relaxed #include <condition_variable> // for condition_variable +#include <cstddef> // for size_t +#include <cstdint> // for intptr_t #include <functional> // for function #include <mutex> // for mutex, lock_guard, unique_lock -#include <thread> // for thread -#include <vector> // for vector +#include <random> +#include <thread> // for thread +#include <vector> // for vector #include "Common.hpp" // for ALIGN_TO_CACHE_LINE #include "Debug.hpp" // for LogSubsystem, LogSubsystem::RUNTI, Logger @@ -45,7 +46,10 @@ class Runtime : public Logger<LogSubsystem::RUNTI> { pthread_t* threads; workerid_t* workerIds; - void* workerLoop(void* workerId); + std::default_random_engine randomEngine; + std::uniform_int_distribution<unsigned int> uniformIntDistribution; + + auto workerLoop(void* workerId) -> void*; std::mutex workerSleepMutex; std::condition_variable workerSleepConditionVariable; @@ -56,7 +60,7 @@ class Runtime : public Logger<LogSubsystem::RUNTI> { static void printLastRuntimeStats(); protected: - void addNewWorkerHook(std::function<void(void)> hook) { newWorkerHooks.push_back(hook); }; + void addNewWorkerHook(const std::function<void(void)>& hook) { newWorkerHooks.push_back(hook); }; inline void notifyAboutNewWork() { if (!atLeastOneWorkerIsSleeping.load(std::memory_order_relaxed)) return; @@ -79,35 +83,37 @@ class Runtime : public Logger<LogSubsystem::RUNTI> { Runtime(RuntimeStrategy& strategy) : Runtime(std::thread::hardware_concurrency(), strategy) {} - Runtime(workerid_t workerCount, RuntimeStrategy& strategy); + Runtime(workerid_t workerCount, RuntimeStrategy& strategy, + unsigned int seed = std::random_device()()); ~Runtime(); inline void schedule(Fiber& fiber) { scheduler.schedule(fiber); } - Fiber* nextFiber(); + auto nextFiber() -> Fiber*; // https://stackoverflow.com/a/3747462/194894 - static inline int rand() { + static inline auto rand() -> int { seed = 214013 * seed + 2531011; - return (seed >> 16) & 0x7FFF; + auto shifted_seed = seed >> 16; + return *reinterpret_cast<int*>(&shifted_seed) & 0x7FFF; } - static inline workerid_t getWorkerId() { return workerId; } + static inline auto getWorkerId() -> workerid_t { return workerId; } - inline workerid_t getWorkerCount() const { return workerCount; } + [[nodiscard]] inline auto getWorkerCount() const -> workerid_t { return workerCount; } - static inline Runtime* getRuntime() { return currentRuntime; } + static inline auto getRuntime() -> Runtime* { return currentRuntime; } - inline ContextManager& getContextManager() { return contextManager; } + inline auto getContextManager() -> ContextManager& { return contextManager; } - inline RuntimeStrategy& getStrategy() { return strategy; } + inline auto getStrategy() -> RuntimeStrategy& { return strategy; } void waitUntilFinished(); void printStats(); - bool inRuntime(); + static auto inRuntime() -> bool; void executeAndWait(std::function<void()> f); diff --git a/emper/RuntimeStrategy.hpp b/emper/RuntimeStrategy.hpp index 77217e846d1a6f4113eebedf76123e8b218ca864..c3d0d1a5ffbf01c781e4c099fd6d2b0e357eb481 100644 --- a/emper/RuntimeStrategy.hpp +++ b/emper/RuntimeStrategy.hpp @@ -13,10 +13,10 @@ class RuntimeStrategy { friend class Runtime; private: - virtual Scheduler& getScheduler(Runtime& runtime) = 0; + virtual auto getScheduler(Runtime& runtime) -> Scheduler& = 0; - virtual Dispatcher& getDispatcher(Runtime& runtime) = 0; + virtual auto getDispatcher(Runtime& runtime) -> Dispatcher& = 0; public: - virtual std::shared_ptr<RuntimeStrategyStats> getStats() = 0; + virtual auto getStats() -> std::shared_ptr<RuntimeStrategyStats> = 0; }; diff --git a/emper/RuntimeStrategyStats.hpp b/emper/RuntimeStrategyStats.hpp index df1aeb7f1b394371fe0f747a24c575c1110dc19e..fcd66652f42168d0f10a0505e2e58308db1a183a 100644 --- a/emper/RuntimeStrategyStats.hpp +++ b/emper/RuntimeStrategyStats.hpp @@ -4,5 +4,6 @@ class RuntimeStrategyStats { public: + virtual ~RuntimeStrategyStats() = default; virtual void print() = 0; }; diff --git a/emper/Scheduler.cpp b/emper/Scheduler.cpp index cda111cfea8158c7b4c4e4c2512438ee9a0e56d6..aa8c43e950c4a8e416af8cdc5bb402ea094f2d56 100644 --- a/emper/Scheduler.cpp +++ b/emper/Scheduler.cpp @@ -6,6 +6,8 @@ Scheduler::Scheduler(Runtime& runtime) : runtime(runtime) {} -void Scheduler::addNewWorkerHook(std::function<void(void)> hook) { runtime.addNewWorkerHook(hook); } +void Scheduler::addNewWorkerHook(const std::function<void(void)>& hook) { + runtime.addNewWorkerHook(hook); +} void Scheduler::notifyRuntimeAboutNewWork() { runtime.notifyAboutNewWork(); } diff --git a/emper/Scheduler.hpp b/emper/Scheduler.hpp index d735c771a0890c5fe757757deea450427d4d6aea..e4cdcd3ba5cdd9e510ceb074b340068a85da1788 100644 --- a/emper/Scheduler.hpp +++ b/emper/Scheduler.hpp @@ -15,9 +15,9 @@ class Scheduler : public Logger<LogSubsystem::SCHED> { Runtime& runtime; Scheduler(Runtime& runtime); - void addNewWorkerHook(std::function<void(void)> hook); + void addNewWorkerHook(const std::function<void(void)>& hook); - static inline workeraffinity_t* getAffinityBuffer(Fiber& fiber) { + static inline auto getAffinityBuffer(Fiber& fiber) -> workeraffinity_t* { return fiber.getAffinityBuffer(); } @@ -28,5 +28,5 @@ class Scheduler : public Logger<LogSubsystem::SCHED> { public: virtual void schedule(Fiber& fiber) = 0; - virtual Fiber* nextFiber() = 0; + virtual auto nextFiber() -> Fiber* = 0; }; diff --git a/emper/Semaphore.hpp b/emper/Semaphore.hpp index bfb3e018a5136faa3216ee1a910274a484ed4d91..8753855df08538232196619eec98d917d0da42b1 100644 --- a/emper/Semaphore.hpp +++ b/emper/Semaphore.hpp @@ -16,7 +16,7 @@ class Semaphore { std::mutex mutex; public: - bool acquire() { + auto acquire() -> bool { bool blocked; mutex.lock(); if (count > 0) { @@ -33,7 +33,7 @@ class Semaphore { return blocked; } - bool release() { + auto release() -> bool { mutex.lock(); bool waiterListEmpty = waiterList.empty(); if (waiterListEmpty) { diff --git a/emper/SynchronizedFiber.hpp b/emper/SynchronizedFiber.hpp index 844d78b8ec367f4ab8348d3120d3fc25161c8df0..cca30c8e1ac611758646a8bbbb3c2641d6a85bdb 100644 --- a/emper/SynchronizedFiber.hpp +++ b/emper/SynchronizedFiber.hpp @@ -2,6 +2,8 @@ // Copyright © 2020 Florian Schmaus #pragma once +#include <utility> + #include "BinaryPrivateSemaphore.hpp" #include "CountingPrivateSemaphore.hpp" #include "Fiber.hpp" @@ -13,19 +15,19 @@ class SynchronizedFiber : public Fiber { SynchronizedFiber(fiber_fun_t function, void* arg, workeraffinity_t* affinity, PrivateSemaphore& semaphore) - : Fiber(function, arg, affinity), semaphore(semaphore){}; + : Fiber(std::move(function), arg, affinity), semaphore(semaphore){}; // cppcheck-suppress uninitMemberVar - explicit SynchronizedFiber(fiber_fun0_t function, workeraffinity_t* affinity, + explicit SynchronizedFiber(const fiber_fun0_t& function, workeraffinity_t* affinity, PrivateSemaphore& semaphore) : SynchronizedFiber([function](UNUSED_ARG void* arg) { function(); }, nullptr, affinity, semaphore) {} SynchronizedFiber(fiber_fun_t function, void* arg, PrivateSemaphore& semaphore) - : SynchronizedFiber(function, arg, nullptr, semaphore){}; + : SynchronizedFiber(std::move(function), arg, nullptr, semaphore){}; // cppcheck-suppress uninitMemberVar - explicit SynchronizedFiber(fiber_fun0_t function, PrivateSemaphore& semaphore) + explicit SynchronizedFiber(const fiber_fun0_t& function, PrivateSemaphore& semaphore) : SynchronizedFiber(function, nullptr, semaphore) {} void run() const override { @@ -34,42 +36,46 @@ class SynchronizedFiber : public Fiber { } public: - static inline Fiber* from(fiber_fun_t function, void* arg, BinaryPrivateSemaphore& semaphore) { - return new SynchronizedFiber(function, arg, semaphore); + static inline auto from(fiber_fun_t function, void* arg, BinaryPrivateSemaphore& semaphore) + -> Fiber* { + return new SynchronizedFiber(std::move(function), arg, semaphore); } - static inline Fiber* from(fiber_fun0_t function, BinaryPrivateSemaphore& semaphore) { + static inline auto from(const fiber_fun0_t& function, BinaryPrivateSemaphore& semaphore) + -> Fiber* { return new SynchronizedFiber(function, semaphore); } - static inline Fiber* from(fiber_fun_t function, void* arg, workeraffinity_t* affinity, - BinaryPrivateSemaphore& semaphore) { - return new SynchronizedFiber(function, arg, affinity, semaphore); + static inline auto from(fiber_fun_t function, void* arg, workeraffinity_t* affinity, + BinaryPrivateSemaphore& semaphore) -> Fiber* { + return new SynchronizedFiber(std::move(function), arg, affinity, semaphore); } - static inline Fiber* from(fiber_fun0_t function, workeraffinity_t* affinity, - BinaryPrivateSemaphore& semaphore) { + static inline auto from(const fiber_fun0_t& function, workeraffinity_t* affinity, + BinaryPrivateSemaphore& semaphore) -> Fiber* { return new SynchronizedFiber(function, affinity, semaphore); } - static inline Fiber* from(fiber_fun_t function, void* arg, CountingPrivateSemaphore& semaphore) { + static inline auto from(fiber_fun_t function, void* arg, CountingPrivateSemaphore& semaphore) + -> Fiber* { semaphore.incrementCounterByOne(); - return new SynchronizedFiber(function, arg, semaphore); + return new SynchronizedFiber(std::move(function), arg, semaphore); } - static inline Fiber* from(fiber_fun0_t function, CountingPrivateSemaphore& semaphore) { + static inline auto from(const fiber_fun0_t& function, CountingPrivateSemaphore& semaphore) + -> Fiber* { semaphore.incrementCounterByOne(); return new SynchronizedFiber(function, semaphore); } - static inline Fiber* from(fiber_fun_t function, void* arg, workeraffinity_t* affinity, - CountingPrivateSemaphore& semaphore) { + static inline auto from(fiber_fun_t function, void* arg, workeraffinity_t* affinity, + CountingPrivateSemaphore& semaphore) -> Fiber* { semaphore.incrementCounterByOne(); - return new SynchronizedFiber(function, arg, affinity, semaphore); + return new SynchronizedFiber(std::move(function), arg, affinity, semaphore); } - static inline Fiber* from(fiber_fun0_t function, workeraffinity_t* affinity, - CountingPrivateSemaphore& semaphore) { + static inline auto from(const fiber_fun0_t& function, workeraffinity_t* affinity, + CountingPrivateSemaphore& semaphore) -> Fiber* { semaphore.incrementCounterByOne(); return new SynchronizedFiber(function, affinity, semaphore); } diff --git a/emper/UnboundedBlockingMpscQueue.hpp b/emper/UnboundedBlockingMpscQueue.hpp index 3ffc90737c5f19a4bf3e8abbe32dfc371a7b47d0..c662ded7145da47b83cb33a43be25749a73e5eff 100644 --- a/emper/UnboundedBlockingMpscQueue.hpp +++ b/emper/UnboundedBlockingMpscQueue.hpp @@ -26,7 +26,7 @@ class UnboundedBlockingMpscQueue : public Blockable<LogSubsystem::U_B_MPSC_Q> { } } - void tryToGetElement(std::function<void(void)> postRetrieve) { + void tryToGetElement(const std::function<void(void)>& postRetrieve) { // tPopped indicates that 't' is a popped and usable value. // Therefore if we tryToGet a new 't' while 't' is available the current 't' // would be overridden and dropped. @@ -56,7 +56,7 @@ class UnboundedBlockingMpscQueue : public Blockable<LogSubsystem::U_B_MPSC_Q> { } } - T get(std::function<void(void)> postRetrieve) { + auto get(const std::function<void(void)>& postRetrieve) -> T { tPopped = false; tryToGetElement(postRetrieve); @@ -84,7 +84,7 @@ class UnboundedBlockingMpscQueue : public Blockable<LogSubsystem::U_B_MPSC_Q> { return t; } - size_t size() { + auto size() -> size_t { std::lock_guard<std::mutex> lock(queueMutex); return mpscQueue.size(); } diff --git a/emper/c_emper.cpp b/emper/c_emper.cpp index 61e7ee8049a6e5ebfc13463c054a5b9df6aae91d..d528eb9153b2f12b99aeae718f5b52faf1bfc550 100644 --- a/emper/c_emper.cpp +++ b/emper/c_emper.cpp @@ -9,8 +9,8 @@ #include "emper-common.h" // for workeraffinity_t #include "emper.h" // for fiber, cps, bps, runtime -runtime* init_runtime(void) { - Runtime* r = new Runtime(); +auto init_runtime(void) -> runtime* { + auto* r = new Runtime(); return reinterpret_cast<runtime*>(r); } @@ -19,22 +19,22 @@ void wait_until_runtime_finished() { r->waitUntilFinished(); } -fiber* fiber_from(void (*function)(void*), void* arg) { +auto fiber_from(void (*function)(void*), void* arg) -> fiber* { Fiber* f = Fiber::from(function, arg); return reinterpret_cast<fiber*>(f); } -fiber* fiber_from0(void (*function)(void)) { +auto fiber_from0(void (*function)()) -> fiber* { Fiber* f = Fiber::from(function); return reinterpret_cast<fiber*>(f); } -fiber* aff_fiber_from(void (*function)(void*), void* arg, workeraffinity_t* affinity) { +auto aff_fiber_from(void (*function)(void*), void* arg, workeraffinity_t* affinity) -> fiber* { Fiber* f = Fiber::from(function, arg, affinity); return reinterpret_cast<fiber*>(f); } -fiber* aff_fiber_from0(void (*function)(void), workeraffinity_t* affinity) { +auto aff_fiber_from0(void (*function)(), workeraffinity_t* affinity) -> fiber* { Fiber* f = Fiber::from(function, affinity); return reinterpret_cast<fiber*>(f); } @@ -47,54 +47,51 @@ void init_affinity(workeraffinity_t affinity[], unsigned int n) { void schedule(fiber* fiber) { Runtime* runtime = Runtime::getRuntime(); - Fiber* f = reinterpret_cast<Fiber*>(fiber); + auto* f = reinterpret_cast<Fiber*>(fiber); runtime->schedule(*f); } -bps* new_binary_sem() { +auto new_binary_sem() -> bps* { BPS* sem = new BPS(); return reinterpret_cast<bps*>(sem); } void signal_bps(bps* sem) { - BinaryPrivateSemaphore* binaryPrivateSemaphore = reinterpret_cast<BinaryPrivateSemaphore*>(sem); + auto* binaryPrivateSemaphore = reinterpret_cast<BinaryPrivateSemaphore*>(sem); binaryPrivateSemaphore->signal(); } void signal_and_exit_bps(bps* sem) { - BinaryPrivateSemaphore* binaryPrivateSemaphore = reinterpret_cast<BinaryPrivateSemaphore*>(sem); + auto* binaryPrivateSemaphore = reinterpret_cast<BinaryPrivateSemaphore*>(sem); binaryPrivateSemaphore->signalAndExit(); } void wait_bps(bps* sem) { - BinaryPrivateSemaphore* binaryPrivateSemaphore = reinterpret_cast<BinaryPrivateSemaphore*>(sem); + auto* binaryPrivateSemaphore = reinterpret_cast<BinaryPrivateSemaphore*>(sem); binaryPrivateSemaphore->wait(); } -cps* new_counting_sem() { +auto new_counting_sem() -> cps* { CPS* sem = new CPS(); return reinterpret_cast<cps*>(sem); } -cps* new_counting_sem_with(unsigned int i) { +auto new_counting_sem_with(unsigned int i) -> cps* { CPS* sem = new CPS(i); return reinterpret_cast<cps*>(sem); } void signal_cps(cps* sem) { - CountingPrivateSemaphore* countingPrivateSemaphore = - reinterpret_cast<CountingPrivateSemaphore*>(sem); + auto* countingPrivateSemaphore = reinterpret_cast<CountingPrivateSemaphore*>(sem); countingPrivateSemaphore->signal(); } void signal_and_exit_cps(cps* sem) { - CountingPrivateSemaphore* countingPrivateSemaphore = - reinterpret_cast<CountingPrivateSemaphore*>(sem); + auto* countingPrivateSemaphore = reinterpret_cast<CountingPrivateSemaphore*>(sem); countingPrivateSemaphore->signalAndExit(); } void wait_cps(cps* sem) { - CountingPrivateSemaphore* countingPrivateSemaphore = - reinterpret_cast<CountingPrivateSemaphore*>(sem); + auto* countingPrivateSemaphore = reinterpret_cast<CountingPrivateSemaphore*>(sem); countingPrivateSemaphore->wait(); } diff --git a/emper/include/emper-common.h b/emper/include/emper-common.h index 38d57a445857835cdb108862bd81fe3506f64043..2f3866e74a452a49aac787a46995fe9375eae51e 100644 --- a/emper/include/emper-common.h +++ b/emper/include/emper-common.h @@ -12,8 +12,8 @@ #endif -typedef uint8_t workerid_t; -typedef int16_t workeraffinity_t; +typedef uint8_t workerid_t; // NOLINT(modernize-use-using) +typedef int16_t workeraffinity_t; // NOLINT(modernize-use-using) #define UNUSED_ARG __attribute__((unused)) #define ATTR_UNUSED __attribute__((unused)) diff --git a/emper/include/emper.h b/emper/include/emper.h index 5b16f7970c30b99d23a43560927c0edd7ca6a1cb..05a907c3bca564e610799aecca638707fb711572 100644 --- a/emper/include/emper.h +++ b/emper/include/emper.h @@ -4,34 +4,40 @@ #include "emper-common.h" -typedef struct runtime runtime; +typedef struct runtime runtime; // NOLINT(modernize-use-using) -typedef struct fiber fiber; +typedef struct fiber fiber; // NOLINT(modernize-use-using) -typedef struct bps bps; +typedef struct bps bps; // NOLINT(modernize-use-using) -typedef struct cps cps; +typedef struct cps cps; // NOLINT(modernize-use-using) #ifdef __cplusplus extern "C" { #endif +// NOLINTNEXTLINE(modernize-use-trailing-return-type) runtime* init_runtime(void); void wait_until_runtime_finished(); +// NOLINTNEXTLINE(modernize-use-trailing-return-type) fiber* fiber_from(void (*function)(void*), void* arg); -fiber* fiber_from0(void (*function)(void)); +// NOLINTNEXTLINE(modernize-use-trailing-return-type) +fiber* fiber_from0(void (*function)()); +// NOLINTNEXTLINE(modernize-use-trailing-return-type) fiber* aff_fiber_from(void (*function)(void*), void* arg, workeraffinity_t* affinity); -fiber* aff_fiber_from0(void (*function)(void), workeraffinity_t* affinity); +// NOLINTNEXTLINE(modernize-use-trailing-return-type) +fiber* aff_fiber_from0(void (*function)(), workeraffinity_t* affinity); void init_affinity(workeraffinity_t affinity[], unsigned int n); void schedule(fiber* fiber); +// NOLINTNEXTLINE(modernize-use-trailing-return-type) bps* new_binary_sem(void); void signal_bps(bps* sem); @@ -40,8 +46,10 @@ void signal_and_exit_bps(bps* sem); void wait_bps(bps* sem); +// NOLINTNEXTLINE(modernize-use-trailing-return-type) cps* new_counting_sem(void); +// NOLINTNEXTLINE(modernize-use-trailing-return-type) cps* new_counting_sem_with(unsigned int i); void signal_cps(cps* sem); diff --git a/emper/include/emper.hpp b/emper/include/emper.hpp index 17ce953001c5f37dcbc54abc03858cb29bc9be8d..82e1f259a784354baa923ddd31a3cb65887bb88b 100644 --- a/emper/include/emper.hpp +++ b/emper/include/emper.hpp @@ -4,6 +4,7 @@ #include <cassert> #include <functional> +#include <utility> #include "Fiber.hpp" #include "Runtime.hpp" @@ -16,21 +17,21 @@ void async(Fiber* fiber) { } void async(Fiber::fiber_fun_t function, void* arg) { - Fiber* fiber = Fiber::from(function, arg); + Fiber* fiber = Fiber::from(std::move(function), arg); async(fiber); } -void async(Fiber::fiber_fun0_t function) { +void async(const Fiber::fiber_fun0_t& function) { Fiber* fiber = Fiber::from(function); async(fiber); } void async(Fiber::fiber_fun_t function, void* arg, workeraffinity_t* affinity) { - Fiber* fiber = Fiber::from(function, arg, affinity); + Fiber* fiber = Fiber::from(std::move(function), arg, affinity); async(fiber); } -void async(Fiber::fiber_fun0_t function, workeraffinity_t* affinity) { +void async(const Fiber::fiber_fun0_t& function, workeraffinity_t* affinity) { Fiber* fiber = Fiber::from(function, affinity); async(fiber); } diff --git a/emper/lib/DebugUtil.cpp b/emper/lib/DebugUtil.cpp index bcc87a864cb8929ea747f168ef6fadd1b68a87f2..9b0d19e19180f097ddb05f66c499b87a2223d8ef 100644 --- a/emper/lib/DebugUtil.cpp +++ b/emper/lib/DebugUtil.cpp @@ -3,13 +3,15 @@ #include "DebugUtil.hpp" #include <execinfo.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> #include <unistd.h> +#include <csignal> +#include <cstdio> +#include <cstdlib> + static void handler(int sig) { const int backtrace_size = 20; + // NOLINTNEXTLINE(modernize-avoid-c-arrays) void* array[backtrace_size]; size_t size = backtrace(array, backtrace_size); diff --git a/emper/lib/adt/BoundedBumpArray.hpp b/emper/lib/adt/BoundedBumpArray.hpp index 7487991a3b3a766cad3cf3a455a4991e126eb52a..41c20a4f79f51daa787d7ea2f88592062d657a44 100644 --- a/emper/lib/adt/BoundedBumpArray.hpp +++ b/emper/lib/adt/BoundedBumpArray.hpp @@ -2,6 +2,8 @@ // Copyright © 2020 Florian Schmaus #pragma once +#include <cstddef> + namespace adt { template <typename T, size_t N> @@ -11,21 +13,22 @@ class BoundedBumpArray { size_t nextFreeElement = 0; + // NOLINTNEXTLINE(modernize-avoid-c-arrays) T* array[N]; public: - bool isFull() { return nextFreeElement + 1 == N; } + auto isFull() -> bool { return nextFreeElement + 1 == N; } - bool isEmpty() { return nextFreeElement == 0; } + auto isEmpty() -> bool { return nextFreeElement == 0; } - bool put(T* t) { + auto put(T* t) -> bool { if (isFull()) return false; array[nextFreeElement++] = t; return true; } - T* get() { + auto get() -> T* { if (isEmpty()) return nullptr; return array[--nextFreeElement]; diff --git a/emper/lib/adt/LockedQueue.hpp b/emper/lib/adt/LockedQueue.hpp index 4b10b7f204740aa66ed40f803158d16f752b0d56..53264aff6d90525f419c63450b6ac410e21b00ec 100644 --- a/emper/lib/adt/LockedQueue.hpp +++ b/emper/lib/adt/LockedQueue.hpp @@ -17,12 +17,14 @@ class LockedQueue { std::deque<I> deque; public: - bool isFull() const { + // We can not mark this method 'const' as std::lock_guard modifies + // the mutex. + auto isFull() -> bool { std::lock_guard<std::mutex> lock(queue_mutex); return deque.size() == SIZE; } - bool pushBottom(const I item) { + auto pushBottom(const I item) -> bool { std::lock_guard<std::mutex> lock(queue_mutex); if (deque.size() == SIZE) return false; @@ -32,7 +34,7 @@ class LockedQueue { return true; } - bool popTop(I* itemPtr) { + auto popTop(I* itemPtr) -> bool { std::lock_guard<std::mutex> lock(queue_mutex); if (deque.empty()) return false; @@ -44,7 +46,7 @@ class LockedQueue { return true; } - bool popBottom(I* itemPtr) { + auto popBottom(I* itemPtr) -> bool { std::lock_guard<std::mutex> lock(queue_mutex); if (deque.empty()) return false; diff --git a/emper/lib/adt/LockedUnboundedQueue.hpp b/emper/lib/adt/LockedUnboundedQueue.hpp index d858333e798c772a98d4535228141175b13ae100..3a33dc62aae654df274924ef040e5361f33b8c7d 100644 --- a/emper/lib/adt/LockedUnboundedQueue.hpp +++ b/emper/lib/adt/LockedUnboundedQueue.hpp @@ -2,6 +2,9 @@ // Copyright © 2020 Florian Schmaus #pragma once +#include <deque> +#include <mutex> + namespace adt { template <typename I> @@ -17,7 +20,7 @@ class LockedUnboundedQueue { deque.push_front(item); } - I* dequeue() { + auto dequeue() -> I* { std::lock_guard<std::mutex> lock(queue_mutex); if (deque.empty()) { return nullptr; diff --git a/emper/lib/adt/MpscQueue.hpp b/emper/lib/adt/MpscQueue.hpp index be344337a33439dbe0cdfacfd5b68e3f6e232af9..b95fa58f4769287510e8f256f45dc790b0850646 100644 --- a/emper/lib/adt/MpscQueue.hpp +++ b/emper/lib/adt/MpscQueue.hpp @@ -25,7 +25,7 @@ class MpscQueue { prev->setMpscNext(item); } - T* dequeue() { + auto dequeue() -> T* { T* next = head->getMpscNext(); if (next == nullptr) { // The queue is empty. diff --git a/emper/lib/adt/WsClQueue.hpp b/emper/lib/adt/WsClQueue.hpp index a695055621dfbf67fe7caa497c90d803af29e366..23c1c19deb51e74b37b88cfd2fc6e19097fedb1c 100644 --- a/emper/lib/adt/WsClQueue.hpp +++ b/emper/lib/adt/WsClQueue.hpp @@ -30,11 +30,12 @@ namespace adt { * of pushes, pops and steals executing at a rate of 4 billtion * operations per second", so overflows should be no problem. */ -template <typename _PAYLOAD, const uintptr_t _CAPACITY> +template <typename PAYLOAD, const uintptr_t CAPACITY> class WsClQueue { ALIGN_TO_CACHE_LINE std::atomic<uint64_t> bottom; ALIGN_TO_CACHE_LINE std::atomic<uint64_t> top; - _PAYLOAD queue[_CAPACITY]; + // NOLINTNEXTLINE(modernize-avoid-c-arrays) + PAYLOAD queue[CAPACITY]; public: // 'bottom' and 'top' are initialized to '1', instead of '0' as @@ -43,22 +44,24 @@ class WsClQueue { // an underflow if bottom is '0'. The paper's queue uses Java // 'long' for bottom and top and is thus safe since it's signed. WsClQueue() : bottom(1), top(1) {} - bool pushBottom(const _PAYLOAD item); - bool popTop(_PAYLOAD *item); - bool popBottom(_PAYLOAD *item); - bool isFull() const; - bool isEmpty() const; + // TODO: Decide what to do regarding the following suppressed lint. + // NOLINTNEXTLINE(readability-avoid-const-params-in-decls) + auto pushBottom(const PAYLOAD item) -> bool; + auto popTop(PAYLOAD *item) -> bool; + auto popBottom(PAYLOAD *item) -> bool; + [[nodiscard]] auto isFull() const -> bool; + [[nodiscard]] auto isEmpty() const -> bool; void print() const; - inline uintptr_t capacity() const { return _CAPACITY; } - inline uint64_t usedSlots() const { return bottom - top; } - inline uintptr_t freeSlots() const { return capacity() - usedSlots(); } + [[nodiscard]] inline auto capacity() const -> uintptr_t { return CAPACITY; } + [[nodiscard]] inline auto usedSlots() const -> uint64_t { return bottom - top; } + [[nodiscard]] inline auto freeSlots() const -> uintptr_t { return capacity() - usedSlots(); } }; -template <typename _PAYLOAD, const uintptr_t _CAPACITY> -bool WsClQueue<_PAYLOAD, _CAPACITY>::pushBottom(const _PAYLOAD item) { +template <typename PAYLOAD, const uintptr_t CAPACITY> +auto WsClQueue<PAYLOAD, CAPACITY>::pushBottom(const PAYLOAD item) -> bool { if (isFull()) return false; - queue[bottom % _CAPACITY] = item; + queue[bottom % CAPACITY] = item; // Write fence / memory barrier atomic_thread_fence(std::memory_order_release); @@ -67,8 +70,8 @@ bool WsClQueue<_PAYLOAD, _CAPACITY>::pushBottom(const _PAYLOAD item) { return true; } -template <typename _PAYLOAD, const uintptr_t _CAPACITY> -bool WsClQueue<_PAYLOAD, _CAPACITY>::popTop(_PAYLOAD *item) { +template <typename PAYLOAD, const uintptr_t CAPACITY> +auto WsClQueue<PAYLOAD, CAPACITY>::popTop(PAYLOAD *item) -> bool { start: uint64_t oldTop = top; if (bottom <= oldTop) return false; @@ -76,7 +79,7 @@ start: // Read fence / memory barrier atomic_thread_fence(std::memory_order_acquire); - *item = queue[oldTop % _CAPACITY]; + *item = queue[oldTop % CAPACITY]; uint64_t newTop = oldTop + 1; // Read fence / memory barrier @@ -91,8 +94,8 @@ start: return true; } -template <typename _PAYLOAD, const uintptr_t _CAPACITY> -bool WsClQueue<_PAYLOAD, _CAPACITY>::popBottom(_PAYLOAD *item) { +template <typename PAYLOAD, const uintptr_t CAPACITY> +auto WsClQueue<PAYLOAD, CAPACITY>::popBottom(PAYLOAD *item) -> bool { uint64_t localBottom = --bottom; uint64_t localTop = top; if (localTop > localBottom) { @@ -101,7 +104,7 @@ bool WsClQueue<_PAYLOAD, _CAPACITY>::popBottom(_PAYLOAD *item) { return false; } - *item = queue[localBottom % _CAPACITY]; + *item = queue[localBottom % CAPACITY]; if (localBottom > localTop) return true; // bool res = top.compare_exchange_weak(localTop, localTop + 1, std::memory_order_release, @@ -116,13 +119,13 @@ bool WsClQueue<_PAYLOAD, _CAPACITY>::popBottom(_PAYLOAD *item) { return res; } -template <typename _PAYLOAD, const uintptr_t _CAPACITY> -bool WsClQueue<_PAYLOAD, _CAPACITY>::isFull() const { - return usedSlots() >= _CAPACITY; +template <typename PAYLOAD, const uintptr_t CAPACITY> +auto WsClQueue<PAYLOAD, CAPACITY>::isFull() const -> bool { + return usedSlots() >= CAPACITY; } -template <typename _PAYLOAD, const uintptr_t _CAPACITY> -bool WsClQueue<_PAYLOAD, _CAPACITY>::isEmpty() const { +template <typename PAYLOAD, const uintptr_t CAPACITY> +auto WsClQueue<PAYLOAD, CAPACITY>::isEmpty() const -> bool { return top >= bottom; } diff --git a/emper/lib/adt/WsClV2Queue.hpp b/emper/lib/adt/WsClV2Queue.hpp index 6f392f8bd3e2ce081a73c1d51b1be5ccb911cea1..afc41b809057dd70914c43109f44fb9c4ca24b93 100644 --- a/emper/lib/adt/WsClV2Queue.hpp +++ b/emper/lib/adt/WsClV2Queue.hpp @@ -36,10 +36,11 @@ class WsClV2Queue { // popBottom() methods, which are only used by the same // thread. Thus we don't need to make it atomic. // TODO should this become a std::atomic? - ALIGN_TO_CACHE_LINE uint64_t bottom; + ALIGN_TO_CACHE_LINE uint64_t bottom{1}; ALIGN_TO_CACHE_LINE std::atomic<uint64_t> top; + // NOLINTNEXTLINE(modernize-avoid-c-arrays) ITEM_TYPE queue[CAPACITY]; public: @@ -48,20 +49,20 @@ class WsClV2Queue { // because popBottom will decrement bottom, which will result in // an underflow if bottom is '0'. The paper's queue uses Java // 'long' for bottom and top and is thus safe since it's signed. - WsClV2Queue() : bottom(1), top(1) {} - bool pushBottom(const ITEM_TYPE item); - bool popBottom(ITEM_TYPE *item); - bool popTop(ITEM_TYPE *item); - bool isFull() const; - bool isEmpty() const; + WsClV2Queue() : top(1) {} + auto pushBottom(ITEM_TYPE item) -> bool; + auto popBottom(ITEM_TYPE *item) -> bool; + auto popTop(ITEM_TYPE *item) -> bool; + [[nodiscard]] auto isFull() const -> bool; + [[nodiscard]] auto isEmpty() const -> bool; void print() const; - inline uintptr_t capacity() const { return CAPACITY; } - inline uint64_t usedSlots() const { return bottom - top; } - inline uintptr_t freeSlots() const { return capacity() - usedSlots(); } + [[nodiscard]] inline auto capacity() const -> uintptr_t { return CAPACITY; } + [[nodiscard]] inline auto usedSlots() const -> uint64_t { return bottom - top; } + [[nodiscard]] inline auto freeSlots() const -> uintptr_t { return capacity() - usedSlots(); } }; template <typename ITEM_TYPE, const uintptr_t CAPACITY> -bool WsClV2Queue<ITEM_TYPE, CAPACITY>::pushBottom(const ITEM_TYPE item) { +auto WsClV2Queue<ITEM_TYPE, CAPACITY>::pushBottom(const ITEM_TYPE item) -> bool { // Check if queue is full. if (isFull()) return false; @@ -77,7 +78,7 @@ bool WsClV2Queue<ITEM_TYPE, CAPACITY>::pushBottom(const ITEM_TYPE item) { } template <typename ITEM_TYPE, const uintptr_t CAPACITY> -bool WsClV2Queue<ITEM_TYPE, CAPACITY>::popBottom(ITEM_TYPE *item) { +auto WsClV2Queue<ITEM_TYPE, CAPACITY>::popBottom(ITEM_TYPE *item) -> bool { // TODO: new bottom value must be flushed out of the store buffer const uint64_t localBottom = --bottom; uint64_t localTop = top.load(std::memory_order_acquire); @@ -105,7 +106,7 @@ bool WsClV2Queue<ITEM_TYPE, CAPACITY>::popBottom(ITEM_TYPE *item) { } template <typename ITEM_TYPE, const uintptr_t CAPACITY> -bool WsClV2Queue<ITEM_TYPE, CAPACITY>::popTop(ITEM_TYPE *item) { +auto WsClV2Queue<ITEM_TYPE, CAPACITY>::popTop(ITEM_TYPE *item) -> bool { start: uint64_t localTop = top.load(std::memory_order_acquire); @@ -136,12 +137,12 @@ start: } template <typename ITEM_TYPE, const uintptr_t CAPACITY> -bool WsClV2Queue<ITEM_TYPE, CAPACITY>::isFull() const { +auto WsClV2Queue<ITEM_TYPE, CAPACITY>::isFull() const -> bool { return usedSlots() >= CAPACITY; } template <typename ITEM_TYPE, const uintptr_t CAPACITY> -bool WsClV2Queue<ITEM_TYPE, CAPACITY>::isEmpty() const { +auto WsClV2Queue<ITEM_TYPE, CAPACITY>::isEmpty() const -> bool { return top >= bottom; } diff --git a/emper/lib/sync/Semaphore.hpp b/emper/lib/sync/Semaphore.hpp index 13fa714b504a1aacdc44a463c37cf3fd24722139..ae07235448041e634992c0c2f6ce33b6959cde8b 100644 --- a/emper/lib/sync/Semaphore.hpp +++ b/emper/lib/sync/Semaphore.hpp @@ -5,11 +5,7 @@ #include <condition_variable> #include <mutex> -namespace emper { - -namespace lib { - -namespace sync { +namespace emper::lib::sync { class Semaphore { private: @@ -39,8 +35,4 @@ class Semaphore { } }; -} // namespace sync - -} // namespace lib - -} // namespace emper +} // namespace emper::lib::sync diff --git a/emper/strategies/laws/LawsScheduler.cpp b/emper/strategies/laws/LawsScheduler.cpp index 83f270ec08d7319773f270c5849bf4d71f19dac0..98031bc76c61ef1b51a4efe03335851270fc9867 100644 --- a/emper/strategies/laws/LawsScheduler.cpp +++ b/emper/strategies/laws/LawsScheduler.cpp @@ -71,7 +71,7 @@ scheduleToLocalWsQueue: #endif } -Fiber* LawsScheduler::nextFiber() { +auto LawsScheduler::nextFiber() -> Fiber* { Fiber* fiber = priorityQueue.dequeue(); if (fiber != nullptr) { // We fetched a fiber from your local priority queue. diff --git a/emper/strategies/laws/LawsScheduler.hpp b/emper/strategies/laws/LawsScheduler.hpp index 61b95288cf80821fe260073a135e4803ce4eef64..931dd0e5a5412c63bf44dcdda8b7e896afbe5d9b 100644 --- a/emper/strategies/laws/LawsScheduler.hpp +++ b/emper/strategies/laws/LawsScheduler.hpp @@ -2,7 +2,7 @@ // Copyright © 2020 Florian Schmaus #pragma once -#include <stddef.h> +#include <cstddef> #include "Fiber.hpp" #include "Scheduler.hpp" @@ -21,14 +21,7 @@ class LawsScheduler : public Scheduler { using WsQueue = adt::WsClQueue<Fiber*, SIZE>; #endif - typedef -#ifdef EMPER_LOCKED_MPSC_QUEUE - adt::LockedUnboundedQueue -#else - adt::MpscQueue -#endif - <Fiber> - LawsMpscQueue; + using LawsMpscQueue = adt::MpscQueue<Fiber>; public: static const int QUEUE_SIZE = 1024; @@ -58,5 +51,5 @@ class LawsScheduler : public Scheduler { void schedule(Fiber& fiber) override; - Fiber* nextFiber() override; + auto nextFiber() -> Fiber* override; }; diff --git a/emper/strategies/laws/LawsStrategy.cpp b/emper/strategies/laws/LawsStrategy.cpp index eba0340a6701832de1bbbb770c13747ab4371fe6..5b2745dfb375c671261b135a257878be9ffc0566 100644 --- a/emper/strategies/laws/LawsStrategy.cpp +++ b/emper/strategies/laws/LawsStrategy.cpp @@ -8,16 +8,16 @@ LawsStrategy LawsStrategy::INSTANCE; -Scheduler& LawsStrategy::getScheduler(Runtime& runtime) { +auto LawsStrategy::getScheduler(Runtime& runtime) -> Scheduler& { Scheduler* scheduler = new LawsScheduler(runtime, *this); return *scheduler; } -Dispatcher& LawsStrategy::getDispatcher(Runtime& runtime) { +auto LawsStrategy::getDispatcher(Runtime& runtime) -> Dispatcher& { Dispatcher* dispatcher = new LawsDispatcher(runtime, *this); return *dispatcher; } -std::shared_ptr<RuntimeStrategyStats> LawsStrategy::getStats() { +auto LawsStrategy::getStats() -> std::shared_ptr<RuntimeStrategyStats> { return std::make_shared<LawsStrategyStats>(*this); } diff --git a/emper/strategies/laws/LawsStrategy.hpp b/emper/strategies/laws/LawsStrategy.hpp index a65027a486bf5ff05da25fafc080537fe420cec3..3ec3e14e6c0fe8e0ffa17ee1b5f9cffc0b30d8ab 100644 --- a/emper/strategies/laws/LawsStrategy.hpp +++ b/emper/strategies/laws/LawsStrategy.hpp @@ -40,12 +40,12 @@ class LawsStrategy : public RuntimeStrategy { dispatchedFiberStolen(0), dispatchedFiberFromMainThread(0) {} - Scheduler& getScheduler(Runtime& runtime); + auto getScheduler(Runtime& runtime) -> Scheduler& override; - Dispatcher& getDispatcher(Runtime& runtime); + auto getDispatcher(Runtime& runtime) -> Dispatcher& override; public: - virtual std::shared_ptr<RuntimeStrategyStats> getStats(); + auto getStats() -> std::shared_ptr<RuntimeStrategyStats> override; static LawsStrategy INSTANCE; diff --git a/emper/strategies/laws/LawsStrategyStats.cpp b/emper/strategies/laws/LawsStrategyStats.cpp index 16e42c3df980baa38faefed21cbc2bdf8db86c4b..7e0aac9ac70b1a68342f26b12fd6f1f4cacd3343 100644 --- a/emper/strategies/laws/LawsStrategyStats.cpp +++ b/emper/strategies/laws/LawsStrategyStats.cpp @@ -15,21 +15,27 @@ LawsStrategyStats::LawsStrategyStats(LawsStrategy& lawsStrategy) dispatchedFiberStolen(lawsStrategy.dispatchedFiberStolen), dispatchedFiberFromMainThread(lawsStrategy.dispatchedFiberFromMainThread) {} -uint64_t LawsStrategyStats::getScheduledFibersToRemotePriority() const { +auto LawsStrategyStats::getScheduledFibersToRemotePriority() const -> uint64_t { return scheduledFibersToRemotePriority; } -uint64_t LawsStrategyStats::getScheduledFibersToLocal() const { return scheduledFibersToLocal; } +auto LawsStrategyStats::getScheduledFibersToLocal() const -> uint64_t { + return scheduledFibersToLocal; +} -uint64_t LawsStrategyStats::getDispatchedFiberFromPriority() const { +auto LawsStrategyStats::getDispatchedFiberFromPriority() const -> uint64_t { return dispatchedFiberFromPriority; } -uint64_t LawsStrategyStats::getDispatchedFiberFromLocal() const { return dispatchedFiberFromLocal; } +auto LawsStrategyStats::getDispatchedFiberFromLocal() const -> uint64_t { + return dispatchedFiberFromLocal; +} -uint64_t LawsStrategyStats::getDispatchedFiberStolen() const { return dispatchedFiberStolen; } +auto LawsStrategyStats::getDispatchedFiberStolen() const -> uint64_t { + return dispatchedFiberStolen; +} -uint64_t LawsStrategyStats::getDispatchedFiberFromMainThread() const { +auto LawsStrategyStats::getDispatchedFiberFromMainThread() const -> uint64_t { return dispatchedFiberFromMainThread; } diff --git a/emper/strategies/laws/LawsStrategyStats.hpp b/emper/strategies/laws/LawsStrategyStats.hpp index c3231d5230ebb3b133558b7b0ec0db0ff1688386..ca0ae2c268659d5b80478615a6f30dc06052b396 100644 --- a/emper/strategies/laws/LawsStrategyStats.hpp +++ b/emper/strategies/laws/LawsStrategyStats.hpp @@ -20,12 +20,12 @@ class LawsStrategyStats : public RuntimeStrategyStats { public: LawsStrategyStats(LawsStrategy& lawsStrategy); - uint64_t getScheduledFibersToRemotePriority() const; - uint64_t getScheduledFibersToLocal() const; - uint64_t getDispatchedFiberFromPriority() const; - uint64_t getDispatchedFiberFromLocal() const; - uint64_t getDispatchedFiberStolen() const; - uint64_t getDispatchedFiberFromMainThread() const; + [[nodiscard]] auto getScheduledFibersToRemotePriority() const -> uint64_t; + [[nodiscard]] auto getScheduledFibersToLocal() const -> uint64_t; + [[nodiscard]] auto getDispatchedFiberFromPriority() const -> uint64_t; + [[nodiscard]] auto getDispatchedFiberFromLocal() const -> uint64_t; + [[nodiscard]] auto getDispatchedFiberStolen() const -> uint64_t; + [[nodiscard]] auto getDispatchedFiberFromMainThread() const -> uint64_t; - virtual void print(); + void print() override; }; diff --git a/emper/strategies/ws/WsScheduler.cpp b/emper/strategies/ws/WsScheduler.cpp index 73c9dacdad565797043224aa0e27dda32b25c020..a64f50107cb513777b616c7ffb983be67151b1f4 100644 --- a/emper/strategies/ws/WsScheduler.cpp +++ b/emper/strategies/ws/WsScheduler.cpp @@ -44,7 +44,7 @@ void WsScheduler::schedule(Fiber& fiber) { #endif } -Fiber* WsScheduler::nextFiber() { +auto WsScheduler::nextFiber() -> Fiber* { Fiber* fiber; bool poped = queue.popBottom(&fiber); diff --git a/emper/strategies/ws/WsScheduler.hpp b/emper/strategies/ws/WsScheduler.hpp index 06d4590056c919ac09662b09cf285775eb66a36c..da1db2bb9a1378744d4f317216bddc8dc6f0f2b8 100644 --- a/emper/strategies/ws/WsScheduler.hpp +++ b/emper/strategies/ws/WsScheduler.hpp @@ -2,7 +2,7 @@ // Copyright © 2020 Florian Schmaus #pragma once -#include <stddef.h> // for size_t +#include <cstddef> // for size_t #include "Scheduler.hpp" // for Scheduler #include "emper-common.h" // for ATTR_UNUSED @@ -43,5 +43,5 @@ class WsScheduler : public Scheduler { void schedule(Fiber& fiber) override; - Fiber* nextFiber() override; + auto nextFiber() -> Fiber* override; }; diff --git a/emper/strategies/ws/WsStrategy.cpp b/emper/strategies/ws/WsStrategy.cpp index 54138fc27725825cc8476a03f8754de64d1bdb9f..ded25e63613c8918feed8581659f46d1aedb4b13 100644 --- a/emper/strategies/ws/WsStrategy.cpp +++ b/emper/strategies/ws/WsStrategy.cpp @@ -11,16 +11,16 @@ class RuntimeStrategyStats; WsStrategy WsStrategy::INSTANCE; -Scheduler& WsStrategy::getScheduler(Runtime& runtime) { +auto WsStrategy::getScheduler(Runtime& runtime) -> Scheduler& { Scheduler* scheduler = new WsScheduler(runtime, *this); return *scheduler; } -Dispatcher& WsStrategy::getDispatcher(Runtime& runtime) { +auto WsStrategy::getDispatcher(Runtime& runtime) -> Dispatcher& { Dispatcher* dispatcher = new WsDispatcher(runtime); return *dispatcher; } -std::shared_ptr<RuntimeStrategyStats> WsStrategy::getStats() { +auto WsStrategy::getStats() -> std::shared_ptr<RuntimeStrategyStats> { return std::make_shared<WsStrategyStats>(*this); } diff --git a/emper/strategies/ws/WsStrategy.hpp b/emper/strategies/ws/WsStrategy.hpp index 24451bc0833fc6337d89153a4940f9338af50e44..f6e963ca73f70b2787fe600cdcf36ead6430136c 100644 --- a/emper/strategies/ws/WsStrategy.hpp +++ b/emper/strategies/ws/WsStrategy.hpp @@ -24,12 +24,12 @@ class WsStrategy : public RuntimeStrategy { WsStrategy() : scheduledFibers(0), nextFiberFromLocal(0), nextFiberStolen(0) {} - Scheduler& getScheduler(Runtime& runtime); + auto getScheduler(Runtime& runtime) -> Scheduler& override; - Dispatcher& getDispatcher(Runtime& runtime); + auto getDispatcher(Runtime& runtime) -> Dispatcher& override; public: - virtual std::shared_ptr<RuntimeStrategyStats> getStats(); + auto getStats() -> std::shared_ptr<RuntimeStrategyStats> override; static WsStrategy INSTANCE; diff --git a/emper/strategies/ws/WsStrategyStats.cpp b/emper/strategies/ws/WsStrategyStats.cpp index 41cb6ae53c870d2131f7b0aae83566b3996d1017..e20cf34fc7957652a588349a43ee29e186ac70d8 100644 --- a/emper/strategies/ws/WsStrategyStats.cpp +++ b/emper/strategies/ws/WsStrategyStats.cpp @@ -12,11 +12,11 @@ WsStrategyStats::WsStrategyStats(WsStrategy& wsStrategy) nextFiberFromLocal(wsStrategy.nextFiberFromLocal), nextFiberStolen(wsStrategy.nextFiberStolen) {} -uint64_t WsStrategyStats::getScheduledFibers() const { return scheduledFibers; } +auto WsStrategyStats::getScheduledFibers() const -> uint64_t { return scheduledFibers; } -uint64_t WsStrategyStats::getNextFiberFromLocal() const { return nextFiberFromLocal; } +auto WsStrategyStats::getNextFiberFromLocal() const -> uint64_t { return nextFiberFromLocal; } -uint64_t WsStrategyStats::getNextFiberStolen() const { return nextFiberStolen; } +auto WsStrategyStats::getNextFiberStolen() const -> uint64_t { return nextFiberStolen; } void WsStrategyStats::print() { std::cout << "WsStrategyStats" diff --git a/emper/strategies/ws/WsStrategyStats.hpp b/emper/strategies/ws/WsStrategyStats.hpp index ba92b37a73a89e3a06e643d3ee3290d29604e896..85249a5e027c2a36ac722a6c9a0594774d0c02a0 100644 --- a/emper/strategies/ws/WsStrategyStats.hpp +++ b/emper/strategies/ws/WsStrategyStats.hpp @@ -17,9 +17,9 @@ class WsStrategyStats : public RuntimeStrategyStats { public: WsStrategyStats(WsStrategy& wsStrategy); - uint64_t getScheduledFibers() const; - uint64_t getNextFiberFromLocal() const; - uint64_t getNextFiberStolen() const; + [[nodiscard]] auto getScheduledFibers() const -> uint64_t; + [[nodiscard]] auto getNextFiberFromLocal() const -> uint64_t; + [[nodiscard]] auto getNextFiberStolen() const -> uint64_t; - virtual void print(); + void print() override; }; diff --git a/eval/Locality.cpp b/eval/Locality.cpp index 625e7d97c437a0bf017a852ac3f8e5d84c3ad153..7783846090252f62ae1b91fa81034b8c027b1a85 100644 --- a/eval/Locality.cpp +++ b/eval/Locality.cpp @@ -1,11 +1,11 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // Copyright © 2020 Florian Schmaus -#include <stdlib.h> // for abort, exit, EXIT_SUCCESS #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 <new> // for operator new #include <random> // for mt19937, uniform_int_dis... @@ -51,6 +51,7 @@ struct State { FiberMetadata* fiberMetadata; // std::map<unsigned int, std::vector<FiberMetadata>> fiberMetadata; + // NOLINTNEXTLINE(cert-msc32-c,cert-msc51-cpp) State(Runtime& runtime, unsigned int fiberCount, unsigned int bytesPerFiber, unsigned int rounds, unsigned int seed) : fiberCount(fiberCount), bytesPerFiber(bytesPerFiber), rounds(rounds), runtime(runtime) { @@ -75,9 +76,10 @@ struct State { #endif } - uint8_t getNextRandom() { return UINT8_UNIFORM_DISTRIBUTION(randomGenerator); } + auto getNextRandom() -> uint8_t { return UINT8_UNIFORM_DISTRIBUTION(randomGenerator); } - FiberMetadata* getFiberMetadata(unsigned int fiberNum, unsigned int roundNum) { + [[nodiscard]] auto getFiberMetadata(unsigned int fiberNum, unsigned int roundNum) const + -> FiberMetadata* { return fiberMetadata + (fiberNum * fiberCount) + roundNum; } }; @@ -101,7 +103,7 @@ static void performRound(State& state, uint8_t roundData = state.getNextRandom(); CPS cps(state.fiberCount); - FiberArgs* fiberArgs = new FiberArgs[state.fiberCount]; + auto* fiberArgs = new FiberArgs[state.fiberCount]; DBG("Starting round " << round); @@ -116,7 +118,7 @@ static void performRound(State& state, Fiber* fiber = Fiber::from( [](void* fiberArgsPtr) { - FiberArgs* fiberArgs = (FiberArgs*)fiberArgsPtr; + auto* fiberArgs = (FiberArgs*)fiberArgsPtr; #ifdef FIBER_METADATA FiberMetadata* fiberMetadata = fiberArgs->fiberMetadata; @@ -213,7 +215,7 @@ enum RuntimeVariant { wslh, }; -int main(UNUSED_ARG int argc, UNUSED_ARG char* argv[]) { +auto main(UNUSED_ARG int argc, UNUSED_ARG char* argv[]) -> int { enableStacktraceOnAborts(); RuntimeVariant runtimeVariant = ws; diff --git a/eval/SpawnALot.cpp b/eval/SpawnALot.cpp index 4f0b0a90dc0c00661e6c67f1cfe78c574c4cee50..4aa6bb199adbb72f998b7861cb609822c49bd387 100644 --- a/eval/SpawnALot.cpp +++ b/eval/SpawnALot.cpp @@ -1,9 +1,8 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // Copyright © 2020 Florian Schmaus -#include <stdint.h> // for uint8_t, uint64_t -#include <stdlib.h> // for EXIT_SUCCESS - #include <chrono> // for nanoseconds, time_point, dur... +#include <cstdint> // for uint8_t, uint64_t +#include <cstdlib> // for EXIT_SUCCESS #include <iostream> // for operator<<, basic_ostream #include <thread> // for thread @@ -21,7 +20,7 @@ static void spawnALotThreadsRecursiveTFun(unsigned int depth, unsigned int width unsigned int current_depth) { if (current_depth == depth) return; - std::thread* threads = new std::thread[width]; + auto* threads = new std::thread[width]; const unsigned int new_depth = current_depth + 1; for (unsigned int i = 0; i < width; ++i) { threads[i] = std::thread(spawnALotThreadsRecursiveTFun, depth, width, new_depth); @@ -39,8 +38,8 @@ static void spawnALotThreadsRecursive(unsigned int depth, unsigned int width) { } static void spawnALotThreadsNonRecursive(uint64_t count) { - uint8_t* flags = new uint8_t[count * CACHE_LINE_SIZE]; - std::thread* threads = new std::thread[count]; + auto* flags = new uint8_t[count * CACHE_LINE_SIZE]; + auto* threads = new std::thread[count]; for (uint64_t i = 0; i < count; ++i) { threads[i] = std::thread([&flags, i] { flags[i * CACHE_LINE_SIZE] = 1; }); } @@ -72,7 +71,7 @@ struct SpawnALotFibersData { }; static void spawnALotFibersRecursiveFFun(void* dataPtr) { - SpawnALotFibersData* data = (SpawnALotFibersData*)dataPtr; + auto* data = (SpawnALotFibersData*)dataPtr; if (data->current_depth < data->depth) { CPS childSem(data->width); SpawnALotFibersData newData(data, childSem); @@ -99,7 +98,7 @@ static void spawnALotFibersRecursive(Runtime& runtime, unsigned int depth, unsig } static void spawnALotFibersNonRecursive(Runtime& runtime, uint64_t count) { - uint8_t* flags = new uint8_t[count * CACHE_LINE_SIZE]; + auto* flags = new uint8_t[count * CACHE_LINE_SIZE]; CPS cps(count); for (uint64_t i = 0; i < count; ++i) { @@ -115,7 +114,7 @@ static void spawnALotFibersNonRecursive(Runtime& runtime, uint64_t count) { delete[] flags; } -int main(UNUSED_ARG int argc, UNUSED_ARG char* argv[]) { +auto main(UNUSED_ARG int argc, UNUSED_ARG char* argv[]) -> int { enableStacktraceOnAborts(); const uint64_t count = 1024; diff --git a/eval/TimeToSpawn.cpp b/eval/TimeToSpawn.cpp index 69792336f371efb234dd3089de165029aeda31f3..36e4d7d7edc4e26f667b55c6edc3438fb7641c5f 100644 --- a/eval/TimeToSpawn.cpp +++ b/eval/TimeToSpawn.cpp @@ -10,7 +10,7 @@ #include "Runtime.hpp" // for Runtime #include "emper-common.h" // for UNUSED_ARG -static std::chrono::nanoseconds threadTimeToSpawn() { +static auto threadTimeToSpawn() -> std::chrono::nanoseconds { std::chrono::time_point<std::chrono::high_resolution_clock> end; auto start = std::chrono::high_resolution_clock::now(); std::thread t([&end] { end = std::chrono::high_resolution_clock::now(); }); @@ -19,7 +19,7 @@ static std::chrono::nanoseconds threadTimeToSpawn() { return std::chrono::duration_cast<std::chrono::nanoseconds>(end - start); } -static std::chrono::nanoseconds fiberTimeToSpawn() { +static auto fiberTimeToSpawn() -> std::chrono::nanoseconds { std::chrono::nanoseconds res; Runtime runtime; @@ -49,7 +49,7 @@ static std::chrono::nanoseconds fiberTimeToSpawn() { return res; } -int main(UNUSED_ARG int argc, UNUSED_ARG char* argv[]) { +auto main(UNUSED_ARG int argc, UNUSED_ARG char* argv[]) -> int { { auto ttts = threadTimeToSpawn(); std::cout << "Thread time to spawn: " << ttts.count() << " ns" << std::endl; diff --git a/tests/CppApiTest.cpp b/tests/CppApiTest.cpp index 71864a750bd61ab3f639c33333cfc0e3e3309dbb..b61ee9e0035eed9f719b4ec624e87c22b8ffdc18 100644 --- a/tests/CppApiTest.cpp +++ b/tests/CppApiTest.cpp @@ -1,8 +1,7 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // Copyright © 2020 Florian Schmaus -#include <stdlib.h> // for exit, EXIT_FAILURE, EXIT_SUC... - -#include <atomic> // for atomic_uint, __atomic_base +#include <atomic> // for atomic_uint, __atomic_base +#include <cstdlib> // for exit, EXIT_FAILURE, EXIT_SUC... #include "CountingPrivateSemaphore.hpp" // for CountingPrivateSemaphore #include "Runtime.hpp" // for Runtime @@ -13,7 +12,7 @@ static std::atomic_uint counter; static void increaseCounterByOne() { counter++; } -static void mainFiber(void) { +static void mainFiber() { const unsigned int FIBER_COUNT = 100; CountingPrivateSemaphore cps; @@ -31,7 +30,7 @@ static void mainFiber(void) { exit(EXIT_SUCCESS); } -int main(UNUSED_ARG int arg, UNUSED_ARG char *argv[]) { +auto main(UNUSED_ARG int arg, UNUSED_ARG char *argv[]) -> int { Runtime runtime; async(&mainFiber); diff --git a/tests/SimpleActorTest.cpp b/tests/SimpleActorTest.cpp index 92e5491a107a4f00f73add8ed9d6f748ce06382c..1aa84dbbc4750bcf604d42b4dffe957dd3ee199b 100644 --- a/tests/SimpleActorTest.cpp +++ b/tests/SimpleActorTest.cpp @@ -1,9 +1,8 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // Copyright © 2020 Florian Schmaus -#include <stdlib.h> // for exit, EXIT_FAILURE, EXIT_SUC... - #include <atomic> // for atomic_thread_fence, memory_... #include <cstdint> // for uint64_t +#include <cstdlib> // for exit, EXIT_FAILURE, EXIT_SUC... #include <iostream> // for operator<<, basic_ostream #include "Actor.hpp" // for Actor @@ -20,12 +19,12 @@ class SumActor : public Actor<uint64_t> { uint64_t sum = 0; protected: - virtual void receive(uint64_t t) override { sum += t; } + void receive(uint64_t t) override { sum += t; } public: SumActor(Runtime& runtime) : Actor(runtime) {} - uint64_t getSum() { + [[nodiscard]] auto getSum() const -> uint64_t { std::atomic_thread_fence(std::memory_order::memory_order_acquire); return sum; } @@ -72,7 +71,7 @@ static void mainFiber(void* runtime_ptr) { exit(EXIT_SUCCESS); } -int main(UNUSED_ARG int arg, UNUSED_ARG char* argv[]) { +auto main(UNUSED_ARG int arg, UNUSED_ARG char* argv[]) -> int { Runtime runtime; Fiber* fiber = Fiber::from(mainFiber, (void*)&runtime); diff --git a/tests/SimpleFibTest.cpp b/tests/SimpleFibTest.cpp index f97f947649133ce0aca4a3ba0d8698ad08ccbad5..aace0206fb37e4c5b9545c49e796fbaf0779ab44 100644 --- a/tests/SimpleFibTest.cpp +++ b/tests/SimpleFibTest.cpp @@ -1,6 +1,6 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // Copyright © 2020 Florian Schmaus -#include <stdlib.h> // for exit, EXIT_FAILURE, EXIT_SUC... +#include <cstdlib> // for exit, EXIT_FAILURE, EXIT_SUC... #include "BinaryPrivateSemaphore.hpp" // for BPS #include "CountingPrivateSemaphore.hpp" // for CPS @@ -9,14 +9,14 @@ #include "Runtime.hpp" // for Runtime #include "emper-common.h" // for UNUSED_ARG -typedef struct { +using fibParams = struct { int n; int* result; PS* sem; -} fibParams; +}; static void fib(void* voidParams) { - fibParams* params = static_cast<fibParams*>(voidParams); + auto* params = static_cast<fibParams*>(voidParams); int n = params->n; int* result = params->result; PS* sem = params->sem; @@ -52,7 +52,7 @@ static void fib(void* voidParams) { sem->signalAndExit(); } -int main(UNUSED_ARG int argc, UNUSED_ARG char* argv[]) { +auto main(UNUSED_ARG int argc, UNUSED_ARG char* argv[]) -> int { Runtime runtime; Fiber* fibFiber = Fiber::from( diff --git a/tests/SimpleLawsTest.cpp b/tests/SimpleLawsTest.cpp index ca524c35d7e6f3d350755088d145e13c8dbf4cf4..7369dee0dac9897358d31e1ba6c2fd9ad8dc86d6 100644 --- a/tests/SimpleLawsTest.cpp +++ b/tests/SimpleLawsTest.cpp @@ -1,10 +1,9 @@ // SPDX-License-Identifier: LGPL-3.0-or-later // Copyright © 2020 Florian Schmaus -#include <stdint.h> // for uint64_t, UINT64_MAX -#include <stdlib.h> // for free, exit, EXIT_FAILURE -#include <string.h> // for memset - #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 <new> // for operator new[] #include <random> // for mt19937_64, random_device @@ -22,28 +21,27 @@ static const unsigned int ROUND_COUNT = 10; static const unsigned int FIBER_LOOPS = 10; static const unsigned int PAYLOAD_COUNT = 4096; -typedef struct ALIGN_TO_CACHE_LINE { +using FiberData = struct ALIGN_TO_CACHE_LINE { // 4096 * 8 byte (64 bit) = 32 KiB = L1 cache size of most systems + // NOLINTNEXTLINE(modernize-avoid-c-arrays) uint64_t payload[PAYLOAD_COUNT]; CPS* cps; unsigned int fiberNum; -} FiberData; +}; -typedef struct ALIGN_TO_CACHE_LINE { - workeraffinity_t affinity; -} AlignedWorkerAffinity; +using AlignedWorkerAffinity = struct ALIGN_TO_CACHE_LINE { workeraffinity_t affinity; }; static void fiberFun(void* voidFiberData) { - FiberData* fiberData = static_cast<FiberData*>(voidFiberData); + auto* fiberData = static_cast<FiberData*>(voidFiberData); std::random_device randomDevice; std::mt19937_64 randomGenerator(randomDevice()); std::uniform_int_distribution<unsigned long long> randomDistribution(0, UINT64_MAX); for (unsigned int i = 0; i < FIBER_LOOPS; ++i) { - for (unsigned int j = 0; j < PAYLOAD_COUNT; ++j) { + for (unsigned long& j : fiberData->payload) { unsigned long long r = randomDistribution(randomGenerator); - fiberData->payload[j] += r; + j += r; } } @@ -54,8 +52,8 @@ static void alphaFun() { Runtime* runtime = Runtime::getRuntime(); const unsigned int FIBER_COUNT = runtime->getWorkerCount() + 3; - AlignedWorkerAffinity* affinities = new AlignedWorkerAffinity[FIBER_COUNT]; - FiberData* fiberData = new FiberData[FIBER_COUNT]; + auto* affinities = new AlignedWorkerAffinity[FIBER_COUNT]; + auto* fiberData = new FiberData[FIBER_COUNT]; for (unsigned int i = 0; i < FIBER_COUNT; ++i) { FiberData& currentFiberData = fiberData[i]; @@ -85,8 +83,8 @@ static void alphaFun() { Fiber* fiber = Fiber::from( [myFiberData, &finalResult]() { uint64_t mySum = 0; - for (unsigned int i = 0; i < PAYLOAD_COUNT; ++i) { - mySum += myFiberData->payload[i]; + for (unsigned long i : myFiberData->payload) { + mySum += i; } finalResult += mySum; @@ -105,7 +103,7 @@ static void alphaFun() { exit(EXIT_SUCCESS); } -int main(UNUSED_ARG int args, UNUSED_ARG char* argv[]) { +auto main(UNUSED_ARG int args, UNUSED_ARG char* argv[]) -> int { RuntimeStrategy& lawsStrategy = LawsStrategy::INSTANCE; Runtime runtime(lawsStrategy); diff --git a/tests/SimplestFibTest.cpp b/tests/SimplestFibTest.cpp index 3e5c5f4cc41ca0b6ae967a976e4d5403b08e95d7..6ff8afde24566564788586f753f98afd14969c10 100644 --- a/tests/SimplestFibTest.cpp +++ b/tests/SimplestFibTest.cpp @@ -12,14 +12,14 @@ #include "emper-common.h" // for UNUSED_ARG #include "emper.hpp" // for async -typedef struct { +using fibParams = struct { int n; int* result; PS* sem; -} fibParams; +}; static void fib(void* voidParams) { - fibParams* params = static_cast<fibParams*>(voidParams); + auto* params = static_cast<fibParams*>(voidParams); int n = params->n; int* result = params->result; if (!result) { @@ -77,7 +77,7 @@ static void fibKickoff() { exit(EXIT_SUCCESS); } -int main(UNUSED_ARG int argc, UNUSED_ARG char* argv[]) { +auto main(UNUSED_ARG int argc, UNUSED_ARG char* argv[]) -> int { // const unsigned nthreads = std::thread::hardware_concurrency(); const unsigned nthreads = 2; diff --git a/tools/clang-tidy-fix b/tools/clang-tidy-fix new file mode 100755 index 0000000000000000000000000000000000000000..5a5f9282771509b329a646b52e8bb54df2c5b65f --- /dev/null +++ b/tools/clang-tidy-fix @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +# Pretty fancy method to get reliable the absolute path of a shell +# script, *even if it is sourced*. Credits go to GreenFox on +# stackoverflow: http://stackoverflow.com/a/12197518/194894 +pushd . > /dev/null +SCRIPTDIR="${BASH_SOURCE[0]}"; +while([ -h "${SCRIPTDIR}" ]); do + cd "`dirname "${SCRIPTDIR}"`" + SCRIPTDIR="$(readlink "`basename "${SCRIPTDIR}"`")"; +done +cd "`dirname "${SCRIPTDIR}"`" > /dev/null +SCRIPTDIR="`pwd`"; +popd > /dev/null + +echoerr() { echo "$@" 1>&2; } + +CLANG_TIDY_BIN="clang-tidy" +ATTEMPT_TO_AUTOFIX=true +DEBUG=false +export DEBUG + +VERBOSE=false +export VERBOSE + +while getopts :c:dnv OPT; do + case $OPT in + d) + set -x + DEBUG=true + ;; + c) + CLANG_TIDY_BIN="${OPTARG}" + ;; + n) + ATTEMPT_TO_AUTOFIX=false + ;; + v) + VERBOSE=true + ;; + *) + echo "usage: ${0##*/} [-d]" + exit 2 + esac +done +shift $(( OPTIND - 1 )) +OPTIND=1 + +export ROOTDIR +ROOTDIR=$(readlink -f "${SCRIPTDIR}/..") + +readonly TEMP_DIR="/var/tmp" + +CLANG_TIDY_FILES=$(mktemp --tmpdir="${TEMP_DIR}") +export CLANG_TIDY_FILES +UNFIXABLE_CLANG_TIDY_FILES=$(mktemp --tmpdir="${TEMP_DIR}") +export UNFIXABLE_CLANG_TIDY_FILES + +cleanup() { + if $DEBUG; then + echo "Debug activated, preserving temprorary files" + echo "CLANG_TIDY_FILES=${CLANG_TIDY_FILES}" + echo "UNFIXABLE_CLANG_TIDY_FILES=${UNFIXABLE_CLANG_TIDY_FILES}" + else + rm "${CLANG_TIDY_FILES}" + rm "${UNFIXABLE_CLANG_TIDY_FILES}" + fi +} +trap cleanup exit + +check_needs_fixing() { + if $DEBUG; then + set -x + fi + + local file="${1}" + + if ! ${CLANG_TIDY} "${file}"; then + echo "${file}" >> "${CLANG_TIDY_FILES}" + fi +} +export -f check_needs_fixing + +attempt_to_fix() { + if $DEBUG; then + set -x + fi + + local file="${1}" + + for attempt in {1..10}; do + if $VERBOSE; then + echo "Performing ${attempt}. attempt to fix ${file}" + fi + if ${CLANG_TIDY} --fix --format-style=file "${file}"; then + exit + fi + done + + echo "${file}" >> "${UNFIXABLE_CLANG_TIDY_FILES}" + exit 1 +} +export -f attempt_to_fix + +if $DEBUG; then + MAX_PROCS=1 +else + MAX_PROCS=$(nproc) +fi + +readonly BUILDDIR="${ROOTDIR}/build" +if [[ ! -d "${BUILDDIR}" ]]; then + echoerr "${BUILDDIR} does not exists, run make first" + exit 1 +fi + +CLANG_TIDY_OPTS=() +CLANG_TIDY_OPTS=("-p=${BUILDDIR}") +if ! $VERBOSE; then + CLANG_TIDY_OPTS+=("--quiet") +fi + +# shellcheck disable=SC2124 +readonly CLANG_TIDY="${CLANG_TIDY_BIN} ${CLANG_TIDY_OPTS[@]}" +export CLANG_TIDY + +set +e +find "${ROOTDIR}" \( -path '*/\.*' -o -path "./build*" -o -path "./build-*" -o -path "./test/3rd-party*" \) -prune -o \ + -type f -regextype posix-extended -regex '.*\.(c|h|cpp|hpp)' -print0 |\ + xargs --null --max-args=1 --max-procs="${MAX_PROCS}" -I {} \ + bash -c 'check_needs_fixing "$@"' _ "{}" +set -e +readonly CHECK_NEEDS_FIXING_RETURN_VALUE="${?}" + +if [[ ! -s "${CLANG_TIDY_FILES}" ]]; then + exit "${CHECK_NEEDS_FIXING_RETURN_VALUE}" +fi + +CLANG_TIDY_FILES_NUM=$(<"${CLANG_TIDY_FILES}" wc -l) +echo "The following ${CLANG_TIDY_FILES_NUM} files have issues according to clang-tidy" +cat "${CLANG_TIDY_FILES}" + +if ! $ATTEMPT_TO_AUTOFIX; then + echo "Attempt to autofix disabled" + exit 1 +fi + +set +e +<"${CLANG_TIDY_FILES}" xargs --max-args=1 --max-procs="${MAX_PROCS}" -I {} \ + bash -c 'attempt_to_fix "$@"' _ "{}" +set -e +readonly ATTEMP_TO_FIX_RETURN_VALUE="${?}" + +if [[ "${ATTEMP_TO_FIX_RETURN_VALUE}" -ne 0 ]]; then + UNFIXABLE_CLANG_TIDY_FILES_NUM=$(<"${UNFIXABLE_CLANG_TIDY_FILES}" wc -l) + echoerr "The following ${UNFIXABLE_CLANG_TIDY_FILES_NUM} files could not be fixed" + cat "${UNFIXABLE_CLANG_TIDY_FILES}" >&2 + + exit "${ATTEMP_TO_FIX_RETURN_VALUE}" +fi