diff --git a/README.asciidoc b/README.asciidoc index f1edf816..ce41402d 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -68,22 +68,22 @@ int main() { taskScheduler.Init(); // Define the constants to test - constexpr uint64_t triangleNum = 47593243ull; - constexpr uint64_t numAdditionsPerTask = 10000ull; - constexpr uint64_t numTasks = (triangleNum + numAdditionsPerTask - 1ull) / numAdditionsPerTask; + constexpr uint64_t triangleNum = 47593243ULL; + constexpr uint64_t numAdditionsPerTask = 10000ULL; + constexpr uint64_t numTasks = (triangleNum + numAdditionsPerTask - 1ULL) / numAdditionsPerTask; // Create the tasks // FTL allows you to create Tasks on the stack. // However, in this case, that would cause a stack overflow ftl::Task *tasks = new ftl::Task[numTasks]; NumberSubset *subsets = new NumberSubset[numTasks]; - uint64_t nextNumber = 1ull; + uint64_t nextNumber = 1ULL; - for (uint64_t i = 0ull; i < numTasks; ++i) { + for (uint64_t i = 0ULL; i < numTasks; ++i) { NumberSubset *subset = &subsets[i]; subset->start = nextNumber; - subset->end = nextNumber + numAdditionsPerTask - 1ull; + subset->end = nextNumber + numAdditionsPerTask - 1ULL; if (subset->end > triangleNum) { subset->end = triangleNum; } @@ -104,13 +104,13 @@ int main() { taskScheduler.WaitForCounter(&counter); // Add the results - uint64_t result = 0ull; + uint64_t result = 0ULL; for (uint64_t i = 0; i < numTasks; ++i) { result += subsets[i].total; } // Test - assert(triangleNum * (triangleNum + 1ull) / 2ull == result); + assert(triangleNum * (triangleNum + 1ULL) / 2ULL == result); // Cleanup delete[] subsets; diff --git a/examples/triangle_num.cpp b/examples/triangle_num.cpp index c139346c..7ec6c13c 100644 --- a/examples/triangle_num.cpp +++ b/examples/triangle_num.cpp @@ -48,22 +48,22 @@ int main() { taskScheduler.Init(); // Define the constants to test - constexpr uint64_t triangleNum = 47593243ull; - constexpr uint64_t numAdditionsPerTask = 10000ull; - constexpr uint64_t numTasks = (triangleNum + numAdditionsPerTask - 1ull) / numAdditionsPerTask; + constexpr uint64_t triangleNum = 47593243ULL; + constexpr uint64_t numAdditionsPerTask = 10000ULL; + constexpr uint64_t numTasks = (triangleNum + numAdditionsPerTask - 1ULL) / numAdditionsPerTask; // Create the tasks // FTL allows you to create Tasks on the stack. // However, in this case, that would cause a stack overflow ftl::Task *tasks = new ftl::Task[numTasks]; NumberSubset *subsets = new NumberSubset[numTasks]; - uint64_t nextNumber = 1ull; + uint64_t nextNumber = 1ULL; - for (uint64_t i = 0ull; i < numTasks; ++i) { + for (uint64_t i = 0ULL; i < numTasks; ++i) { NumberSubset *subset = &subsets[i]; subset->start = nextNumber; - subset->end = nextNumber + numAdditionsPerTask - 1ull; + subset->end = nextNumber + numAdditionsPerTask - 1ULL; if (subset->end > triangleNum) { subset->end = triangleNum; } @@ -84,13 +84,13 @@ int main() { taskScheduler.WaitForCounter(&counter); // Add the results - uint64_t result = 0ull; + uint64_t result = 0ULL; for (uint64_t i = 0; i < numTasks; ++i) { result += subsets[i].total; } // Test - assert(triangleNum * (triangleNum + 1ull) / 2ull == result); + assert(triangleNum * (triangleNum + 1ULL) / 2ULL == result); // Cleanup delete[] subsets; diff --git a/include/ftl/atomic_counter.h b/include/ftl/atomic_counter.h index ff0f44f5..4e1b4e52 100644 --- a/include/ftl/atomic_counter.h +++ b/include/ftl/atomic_counter.h @@ -29,7 +29,7 @@ namespace ftl { /** - * FullAtomicCounter implements TaskCounter and adds the full function set + * FullAtomicCounter implements the full set of functions * of an atomic (with more overhead vs TaskCounter) */ class FullAtomicCounter : public BaseCounter { @@ -42,6 +42,7 @@ class FullAtomicCounter : public BaseCounter { FullAtomicCounter(FullAtomicCounter &&) noexcept = delete; FullAtomicCounter &operator=(FullAtomicCounter const &) = delete; FullAtomicCounter &operator=(FullAtomicCounter &&) noexcept = delete; + ~FullAtomicCounter() = default; public: /** @@ -137,7 +138,7 @@ class FullAtomicCounter : public BaseCounter { }; /** - * AtomicFlag implements TaskCounter and adds Set/Clear + * AtomicFlag implements a simple Set/Clear counter */ class AtomicFlag : public BaseCounter { public: @@ -149,6 +150,7 @@ class AtomicFlag : public BaseCounter { AtomicFlag(AtomicFlag &&) noexcept = delete; AtomicFlag &operator=(AtomicFlag const &) = delete; AtomicFlag &operator=(AtomicFlag &&) noexcept = delete; + ~AtomicFlag() = default; public: bool Set(std::memory_order const memoryOrder = std::memory_order_seq_cst) { diff --git a/include/ftl/base_counter.h b/include/ftl/base_counter.h index fcf5cb87..116bc9cb 100644 --- a/include/ftl/base_counter.h +++ b/include/ftl/base_counter.h @@ -26,8 +26,6 @@ #include #include -#include -#include namespace ftl { @@ -51,11 +49,13 @@ class TaskScheduler; /** * BaseCounter is a wrapper over a C++11 atomic_unsigned * It implements the base logic for the rest of the AtomicCounter-type classes + * + * You should never use this class directly. Use the other AtomicCounter-type classes */ class BaseCounter { public: - explicit BaseCounter(TaskScheduler *taskScheduler, unsigned const initialValue = 0, unsigned const fiberSlots = NUM_WAITING_FIBER_SLOTS); + explicit BaseCounter(TaskScheduler *taskScheduler, unsigned initialValue = 0, unsigned fiberSlots = NUM_WAITING_FIBER_SLOTS); BaseCounter(BaseCounter const &) = delete; BaseCounter(BaseCounter &&) noexcept = delete; diff --git a/include/ftl/callbacks.h b/include/ftl/callbacks.h index 86160c41..1685342b 100644 --- a/include/ftl/callbacks.h +++ b/include/ftl/callbacks.h @@ -33,10 +33,10 @@ enum class FiberState : int { Detached }; -typedef void (*ThreadCreationCallback)(void *context, unsigned threadCount); -typedef void (*FiberCreationCallback)(void *context, unsigned fiberCount); -typedef void (*ThreadEventCallback)(void *context, unsigned threadIndex); -typedef void (*FiberEventCallback)(void *context, unsigned fiberIndex, FiberState newState); +using ThreadCreationCallback = void (*)(void *context, unsigned threadCount); +using FiberCreationCallback = void (*)(void *context, unsigned fiberCount); +using ThreadEventCallback = void (*)(void *context, unsigned threadIndex); +using FiberEventCallback = void (*)(void *context, unsigned fiberIndex, FiberState newState); struct EventCallbacks { void *Context = nullptr; diff --git a/include/ftl/fibtex.h b/include/ftl/fibtex.h index 5d5c8785..348d0728 100644 --- a/include/ftl/fibtex.h +++ b/include/ftl/fibtex.h @@ -27,15 +27,7 @@ #include "ftl/atomic_counter.h" #include "ftl/task_scheduler.h" -#include -#include -#include - namespace ftl { -// Pull std helpers into ftl namespace -using std::adopt_lock; -using std::defer_lock; -using std::try_to_lock; /** * A fiber aware mutex. Does not block in the traditional way. Methods do not follow the lowerCamelCase convention diff --git a/include/ftl/task_counter.h b/include/ftl/task_counter.h index 9585198b..044677f6 100644 --- a/include/ftl/task_counter.h +++ b/include/ftl/task_counter.h @@ -46,6 +46,7 @@ class TaskCounter : public BaseCounter { TaskCounter(TaskCounter &&) noexcept = delete; TaskCounter &operator=(TaskCounter const &) = delete; TaskCounter &operator=(TaskCounter &&) noexcept = delete; + ~TaskCounter() = default; public: /** diff --git a/include/ftl/task_scheduler.h b/include/ftl/task_scheduler.h index 793f22bb..0fedb907 100644 --- a/include/ftl/task_scheduler.h +++ b/include/ftl/task_scheduler.h @@ -31,7 +31,6 @@ #include "ftl/wait_free_queue.h" #include -#include #include #include #include @@ -44,9 +43,6 @@ class AtomicFlag; class FullAtomicCounter; enum class EmptyQueueBehavior { - // Fixing this will break api. - // ReSharper disable CppInconsistentNaming - // Spin in a loop, actively searching for tasks Spin, // Same as spin, except yields to the OS after each round of searching @@ -132,6 +128,8 @@ class TaskScheduler { }; struct ReadyFiberBundle { + ReadyFiberBundle() = default; + // The fiber unsigned FiberIndex; // A flag used to signal if the fiber has been successfully switched out of and "cleaned up". See @CleanUpOldFiber() @@ -251,7 +249,6 @@ class TaskScheduler { * Yields execution to another task until counter == 0 * * @param counter The counter to check - * @param value The value to wait for * @param pinToCurrentThread If true, the task invoking this call will not resume on a different thread */ void WaitForCounter(TaskCounter *counter, bool pinToCurrentThread = false); @@ -260,7 +257,6 @@ class TaskScheduler { * Yields execution to another task until counter == 0 * * @param counter The counter to check - * @param value The value to wait for * @param pinToCurrentThread If true, the task invoking this call will not resume on a different thread */ void WaitForCounter(AtomicFlag *counter, bool pinToCurrentThread = false); @@ -371,8 +367,7 @@ class TaskScheduler { * for a new task * * @param pinnedThreadIndex The index of the thread this fiber is pinned to. If not pinned, this will equal kNoThreadPinning - * @param fiberIndex The index of the fiber to add - * @param fiberStoredFlag A flag used to signal if the fiber has been successfully switched out of and "cleaned + * @param bundle The fiber bundle to add * up" */ void AddReadyFiber(unsigned pinnedThreadIndex, ReadyFiberBundle *bundle); diff --git a/include/ftl/thread_abstraction.h b/include/ftl/thread_abstraction.h index d23f565c..48943585 100644 --- a/include/ftl/thread_abstraction.h +++ b/include/ftl/thread_abstraction.h @@ -31,17 +31,17 @@ // Forward declare the platform types so we don't have to include their heavy header files #if defined(FTL_WIN32_THREADS) -typedef void *HANDLE; -typedef unsigned long DWORD; +typedef void *HANDLE; // NOLINT(modernize-use-using) +typedef unsigned long DWORD; // NOLINT(modernize-use-using) #elif defined(FTL_POSIX_THREADS) # if defined(FTL_OS_LINUX) -typedef unsigned long int pthread_t; +typedef unsigned long int pthread_t; // NOLINT(modernize-use-using) # elif defined(FTL_OS_APPLE) struct _opaque_pthread_t; -typedef struct _opaque_pthread_t *__darwin_pthread_t; -typedef __darwin_pthread_t pthread_t; +typedef struct _opaque_pthread_t *__darwin_pthread_t; // NOLINT(modernize-use-using) +typedef __darwin_pthread_t pthread_t; // NOLINT(modernize-use-using) # endif #endif @@ -55,18 +55,18 @@ struct Win32Thread { DWORD Id; }; -typedef Win32Thread ThreadType; +typedef Win32Thread ThreadType; // NOLINT(modernize-use-using) -typedef unsigned int(__stdcall *ThreadStartRoutine)(void *arg); +typedef unsigned int(__stdcall *ThreadStartRoutine)(void *arg); // NOLINT(modernize-use-using) # define FTL_THREAD_FUNC_RETURN_TYPE unsigned int # define FTL_THREAD_FUNC_DECL FTL_THREAD_FUNC_RETURN_TYPE __stdcall # define FTL_THREAD_FUNC_END return 0 #elif defined(FTL_POSIX_THREADS) -typedef pthread_t ThreadType; +typedef pthread_t ThreadType; // NOLINT(modernize-use-using) -typedef void *(*ThreadStartRoutine)(void *arg); +typedef void *(*ThreadStartRoutine)(void *arg); // NOLINT(modernize-use-using) # define FTL_THREAD_FUNC_RETURN_TYPE void * # define FTL_THREAD_FUNC_DECL FTL_THREAD_FUNC_RETURN_TYPE # define FTL_THREAD_FUNC_END return nullptr @@ -81,6 +81,7 @@ typedef void *(*ThreadStartRoutine)(void *arg); * @param stackSize The size of the stack * @param startRoutine The start routine * @param arg The argument for the start routine + * @param name The name of the thread * @param returnThread The handle for the newly created thread. Undefined if thread creation fails * @return True if thread creation succeeds, false if it fails */ @@ -91,6 +92,7 @@ bool CreateThread(size_t stackSize, ThreadStartRoutine startRoutine, void *arg, * @param stackSize The size of the stack * @param startRoutine The start routine * @param arg The argument for the start routine + * @param name The name of the thread * @param coreAffinity The core affinity * @param returnThread The handle for the newly created thread. Undefined if thread creation fails * @return True if thread creation succeeds, false if it fails diff --git a/source/base_counter.cpp b/source/base_counter.cpp index 4941228f..85f114fb 100644 --- a/source/base_counter.cpp +++ b/source/base_counter.cpp @@ -27,9 +27,11 @@ #include "ftl/ftl_valgrind.h" #include "ftl/task_scheduler.h" +#include + namespace ftl { -BaseCounter::BaseCounter(TaskScheduler *const taskScheduler, unsigned const initialValue, unsigned const fiberSlots) +BaseCounter::BaseCounter(TaskScheduler *const taskScheduler, unsigned initialValue, unsigned fiberSlots) : m_taskScheduler(taskScheduler), m_value(initialValue), m_lock(0), m_fiberSlots(fiberSlots) { m_freeSlots = new std::atomic[fiberSlots]; m_waitingFibers = new WaitingFiberBundle[fiberSlots]; diff --git a/source/task_scheduler.cpp b/source/task_scheduler.cpp index ab82fa58..138e3d4b 100644 --- a/source/task_scheduler.cpp +++ b/source/task_scheduler.cpp @@ -68,7 +68,7 @@ FTL_THREAD_FUNC_RETURN_TYPE TaskScheduler::ThreadStartFunc(void *const arg) { // Execute user thread start callback, if set const EventCallbacks &callbacks = taskScheduler->m_callbacks; - if (callbacks.OnWorkerThreadStarted) { + if (callbacks.OnWorkerThreadStarted != nullptr) { callbacks.OnWorkerThreadStarted(callbacks.Context, index); } @@ -83,7 +83,7 @@ FTL_THREAD_FUNC_RETURN_TYPE TaskScheduler::ThreadStartFunc(void *const arg) { // And we've returned // Execute user thread end callback, if set - if (callbacks.OnWorkerThreadEnded) { + if (callbacks.OnWorkerThreadEnded != nullptr) { callbacks.OnWorkerThreadEnded(callbacks.Context, index); } @@ -95,13 +95,15 @@ FTL_THREAD_FUNC_RETURN_TYPE TaskScheduler::ThreadStartFunc(void *const arg) { // This Task is never used directly // However, a function pointer to it is the signal that the task is a Ready fiber, not a "real" task // See @FiberStartFunc() for more details -static void ReadyFiberDummyTask(TaskScheduler *, void *) { +static void ReadyFiberDummyTask(TaskScheduler *taskScheduler, void *arg) { + (void)taskScheduler; + (void)arg; } void TaskScheduler::FiberStartFunc(void *const arg) { TaskScheduler *taskScheduler = reinterpret_cast(arg); - if (taskScheduler->m_callbacks.OnFiberStateChanged) { + if (taskScheduler->m_callbacks.OnFiberStateChanged != nullptr) { taskScheduler->m_callbacks.OnFiberStateChanged(taskScheduler->m_callbacks.Context, taskScheduler->GetCurrentFiberIndex(), ftl::FiberState::Attached); } @@ -162,14 +164,14 @@ void TaskScheduler::FiberStartFunc(void *const arg) { tls->OldFiberDestination = FiberDestination::ToPool; const EventCallbacks &callbacks = taskScheduler->m_callbacks; - if (callbacks.OnFiberStateChanged) { + if (callbacks.OnFiberStateChanged != nullptr) { callbacks.OnFiberStateChanged(callbacks.Context, tls->OldFiberIndex, FiberState::Detached); } // Switch taskScheduler->m_fibers[tls->OldFiberIndex].SwitchToFiber(&taskScheduler->m_fibers[tls->CurrentFiberIndex]); - if (callbacks.OnFiberStateChanged) { + if (callbacks.OnFiberStateChanged != nullptr) { callbacks.OnFiberStateChanged(callbacks.Context, taskScheduler->GetCurrentFiberIndex(), FiberState::Attached); } @@ -241,7 +243,7 @@ void TaskScheduler::FiberStartFunc(void *const arg) { // Switch to the quit fibers - if (taskScheduler->m_callbacks.OnFiberStateChanged) { + if (taskScheduler->m_callbacks.OnFiberStateChanged != nullptr) { taskScheduler->m_callbacks.OnFiberStateChanged(taskScheduler->m_callbacks.Context, taskScheduler->GetCurrentFiberIndex(), ftl::FiberState::Detached); } @@ -329,10 +331,10 @@ int TaskScheduler::Init(TaskSchedulerInitOptions options) { m_threads[0].Id = static_cast(-1); #endif - if (m_callbacks.OnThreadsCreated) { + if (m_callbacks.OnThreadsCreated != nullptr) { m_callbacks.OnThreadsCreated(m_callbacks.Context, m_numThreads); } - if (m_callbacks.OnFibersCreated) { + if (m_callbacks.OnFibersCreated != nullptr) { m_callbacks.OnFibersCreated(m_callbacks.Context, options.FiberPoolSize); } @@ -366,8 +368,8 @@ int TaskScheduler::Init(TaskSchedulerInitOptions options) { } } - // Manually invoke callbacks for 'main' fiber - if (m_callbacks.OnFiberStateChanged) { + // Manually invoke callback for 'main' fiber + if (m_callbacks.OnFiberStateChanged != nullptr) { m_callbacks.OnFiberStateChanged(m_callbacks.Context, 0, FiberState::Attached); } @@ -395,7 +397,7 @@ TaskScheduler::~TaskScheduler() { // Jump to the quit fiber // Create a scope so index isn't used after we come back from the switch. It will be wrong if we started on a non-main thread { - if (m_callbacks.OnFiberStateChanged) { + if (m_callbacks.OnFiberStateChanged != nullptr) { m_callbacks.OnFiberStateChanged(m_callbacks.Context, GetCurrentFiberIndex(), FiberState::Detached); } @@ -450,6 +452,9 @@ void TaskScheduler::AddTasks(unsigned const numTasks, Task const *const tasks, T queue = &m_tls[GetCurrentThreadIndex()].HiPriTaskQueue; } else if (priority == TaskPriority::Low) { queue = &m_tls[GetCurrentThreadIndex()].LoPriTaskQueue; + } else { + FTL_ASSERT("Unknown task priority", false); + return; } for (unsigned i = 0; i < numTasks; ++i) { FTL_ASSERT("Task given to TaskScheduler:AddTasks has a nullptr Function", tasks[i].Function != nullptr); @@ -519,7 +524,7 @@ bool TaskScheduler::GetNextHiPriTask(TaskBundle *nextTask, std::vectorFiberIsSwitched; - if (m_callbacks.OnFiberStateChanged) { + if (m_callbacks.OnFiberStateChanged != nullptr) { m_callbacks.OnFiberStateChanged(m_callbacks.Context, currentFiberIndex, FiberState::Detached); } // Switch m_fibers[currentFiberIndex].SwitchToFiber(&m_fibers[freeFiberIndex]); - if (m_callbacks.OnFiberStateChanged) { + if (m_callbacks.OnFiberStateChanged != nullptr) { m_callbacks.OnFiberStateChanged(m_callbacks.Context, GetCurrentFiberIndex(), FiberState::Attached); } diff --git a/source/thread_abstraction.cpp b/source/thread_abstraction.cpp index 9389706c..8b19b4d3 100644 --- a/source/thread_abstraction.cpp +++ b/source/thread_abstraction.cpp @@ -187,7 +187,7 @@ bool CreateThread(size_t stackSize, ThreadStartRoutine startRoutine, void *arg, } void EndCurrentThread() { - pthread_exit(NULL); + pthread_exit(nullptr); } bool JoinThread(ThreadType thread) { @@ -208,6 +208,8 @@ bool SetCurrentThreadAffinity(size_t coreAffinity) { int ret = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuSet); if (ret != 0) { + // Clang-tidy can't figure out the #ifdefs + // NOLINTNEXTLINE(readability-simplify-boolean-expr) return false; } # else diff --git a/tests/utilities/event_callbacks.cpp b/tests/utilities/event_callbacks.cpp index 9186353f..ca600ee7 100644 --- a/tests/utilities/event_callbacks.cpp +++ b/tests/utilities/event_callbacks.cpp @@ -36,20 +36,26 @@ TEST_CASE("Fiber Event Callbacks", "[utility]") { struct TestCheckValues { std::atomic_int fiberEventNum; }; - TestCheckValues testValues; + TestCheckValues testValues{}; testValues.fiberEventNum.store(0, std::memory_order_seq_cst); options.Callbacks.Context = &testValues; - options.Callbacks.OnThreadsCreated = [](void *, unsigned threadCount) { + options.Callbacks.OnThreadsCreated = [](void *context, unsigned threadCount) { + (void)context; REQUIRE(threadCount == 1); }; - options.Callbacks.OnFibersCreated = [](void *, unsigned fiberCount) { + options.Callbacks.OnFibersCreated = [](void *context, unsigned fiberCount) { + (void)context; REQUIRE(fiberCount == 20); }; - options.Callbacks.OnWorkerThreadStarted = [](void *, unsigned) { + options.Callbacks.OnWorkerThreadStarted = [](void *context, unsigned threadIndex) { + (void)context; + (void)threadIndex; FAIL("This should never be called, since we don't create worker threads"); }; - options.Callbacks.OnWorkerThreadEnded = [](void *, unsigned) { + options.Callbacks.OnWorkerThreadEnded = [](void *context, unsigned fiberIndex) { + (void)context; + (void)fiberIndex; FAIL("This should never be called, since we don't create worker threads"); }; options.Callbacks.OnFiberStateChanged = [](void *context, unsigned fiberIndex, ftl::FiberState newState) { @@ -104,9 +110,11 @@ TEST_CASE("Fiber Event Callbacks", "[utility]") { REQUIRE(taskScheduler.Init(options) == 0); std::atomic_int taskRunCount(0); - ftl::Task testTask; + ftl::Task testTask{}; testTask.ArgData = &taskRunCount; - testTask.Function = [](ftl::TaskScheduler *, void *arg) { + testTask.Function = [](ftl::TaskScheduler *ts, void *arg) { + (void)ts; + std::atomic_int *runCount = static_cast(arg); runCount->fetch_add(1, std::memory_order_seq_cst); }; @@ -135,7 +143,7 @@ TEST_CASE("Thread Event Callbacks", "[utility]") { std::atomic_int fiberAttaches[kThreadCount]; std::atomic_int fiberDetaches[kThreadCount]; }; - TestCheckValues testValues; + TestCheckValues testValues{}; // Initialize for (unsigned i = 0; i < kThreadCount; ++i) { testValues.threadStarts[i].store(0); @@ -145,10 +153,12 @@ TEST_CASE("Thread Event Callbacks", "[utility]") { } options.Callbacks.Context = &testValues; - options.Callbacks.OnThreadsCreated = [](void *, unsigned threadCount) { + options.Callbacks.OnThreadsCreated = [](void *context, unsigned threadCount) { + (void)context; REQUIRE(threadCount == 4); }; - options.Callbacks.OnFibersCreated = [](void *, unsigned fiberCount) { + options.Callbacks.OnFibersCreated = [](void *context, unsigned fiberCount) { + (void)context; REQUIRE(fiberCount == 20); }; options.Callbacks.OnWorkerThreadStarted = [](void *context, unsigned threadIndex) { diff --git a/tests/utilities/fibtex.cpp b/tests/utilities/fibtex.cpp index 830db471..856313ef 100644 --- a/tests/utilities/fibtex.cpp +++ b/tests/utilities/fibtex.cpp @@ -28,10 +28,8 @@ #include "catch2/catch.hpp" -#include - struct MutexData { - MutexData(ftl::TaskScheduler *scheduler) + explicit MutexData(ftl::TaskScheduler *scheduler) : Lock(scheduler, 6), Counter(0) { } diff --git a/tests/utilities/thread_local.cpp b/tests/utilities/thread_local.cpp index a31d4a12..c0f9cd56 100644 --- a/tests/utilities/thread_local.cpp +++ b/tests/utilities/thread_local.cpp @@ -30,49 +30,53 @@ #include -ftl::ThreadLocal &SingleInitSingleton(ftl::TaskScheduler *scheduler) { - static ftl::ThreadLocal counter(scheduler); - - return counter; +void SimpleInit(ftl::TaskScheduler *scheduler, void *arg) { + (void)scheduler; + ftl::ThreadLocal *counter = static_cast *>(arg); + + // Double dereference + // First to get from ThreadLocal pointer to instance + // Second to get from ThreadLocal to our thread-specific instance of size_t + (*(*counter)) += 1; } -void SimpleInit(ftl::TaskScheduler *scheduler, void * /*arg*/) { - *SingleInitSingleton(scheduler) += 1; -} +void SideEffect(ftl::TaskScheduler *scheduler, void *arg) { + (void)scheduler; + ftl::ThreadLocal *counter = static_cast *>(arg); -static std::atomic g_sideEffectCount{0}; -ftl::ThreadLocal &SideEffectSingleton(ftl::TaskScheduler *scheduler) { - static ftl::ThreadLocal counter(scheduler, []() { return g_sideEffectCount++; }); - - return counter; + // Double dereference + // First to get from ThreadLocal pointer to instance + // Second to get from ThreadLocal to our thread-specific instance of size_t + (*(*counter)); } -void SideEffect(ftl::TaskScheduler *scheduler, void * /*arg*/) { - *SideEffectSingleton(scheduler); -} +static std::atomic g_sideEffectCount{0}; TEST_CASE("Thread Local", "[utility]") { ftl::TaskScheduler taskScheduler; REQUIRE(taskScheduler.Init() == 0); // Single Init - std::vector singleInitTask(taskScheduler.GetThreadCount(), ftl::Task{SimpleInit, nullptr}); + ftl::ThreadLocal simpleCounter(&taskScheduler); + + std::vector singleInitTask(taskScheduler.GetThreadCount(), ftl::Task{SimpleInit, &simpleCounter}); ftl::TaskCounter ac(&taskScheduler); taskScheduler.AddTasks(static_cast(singleInitTask.size()), singleInitTask.data(), ftl::TaskPriority::Low, &ac); taskScheduler.WaitForCounter(&ac); - auto singleInitVals = SingleInitSingleton(&taskScheduler).GetAllValues(); - + auto singleInitVals = simpleCounter.GetAllValues(); REQUIRE(taskScheduler.GetThreadCount() == std::accumulate(singleInitVals.begin(), singleInitVals.end(), size_t{0})); // Side Effects - std::vector sideEffectTask(10000, ftl::Task{SideEffect, nullptr}); + ftl::ThreadLocal sideEffectCounter(&taskScheduler, []() { return g_sideEffectCount++; }); + + std::vector sideEffectTask(10000, ftl::Task{SideEffect, &sideEffectCounter}); taskScheduler.AddTasks(static_cast(sideEffectTask.size()), sideEffectTask.data(), ftl::TaskPriority::Low, &ac); taskScheduler.WaitForCounter(&ac); - auto sideEffect = SideEffectSingleton(&taskScheduler).GetAllValues(); + auto sideEffect = sideEffectCounter.GetAllValues(); // The initializer will only fire once per thread, so there must be less than the thread count // in calls to it, but there should be at least one. diff --git a/third_party/boost_context/include/boost_context/fcontext.h b/third_party/boost_context/include/boost_context/fcontext.h index 6f282814..7ed2e015 100644 --- a/third_party/boost_context/include/boost_context/fcontext.h +++ b/third_party/boost_context/include/boost_context/fcontext.h @@ -10,11 +10,7 @@ #pragma once -#include -// intptr_t - -#include -// size_t +#include // size_t namespace boost_context {