diff --git a/NOTES.md b/NOTES.md index d4b07ee..3015736 100644 --- a/NOTES.md +++ b/NOTES.md @@ -4,14 +4,43 @@ A collection of stuff that we noticed during development. Useful later on two write a project report and to go back in time to find out why certain decisions where made. -## 21.03.2018 - Allocation on stack/static memory +## 27.03.2019 - atomics + +C++ 11 offers atomics, however these require careful usage +and are not always lock free. We plan on doing more research +for these operations when we try to transform our code form using +spin locks to using more fine grained locks. + +Resources can be found [here](https://www.justsoftwaresolutions.co.uk/files/ndc_oslo_2016_safety_off.pdf) +and [here](http://www.modernescpp.com/index.php/c-core-guidelines-the-remaining-rules-to-lock-free-programming). + +## 27.03.2019 - variable sized lambdas + +When working with lambdas one faces the problem of them having not +a fixed size because they can capture variables from the surrounding +scope. + +To 'fix' this in normal C++ one would use a std::function, +wrapping the lambda by moving it onto the heap. This is of course +a problem when trying to prevent dynamic memory allocation. + +When we want static allocation we have two options: +1) keep the lambda on the stack and only call into it while it is valid +2) use templating to create variable sized classes for each lambda used + +Option 1) is preferable, as it does not create extra templating code +(longer compile time, can not separate code into CPP files). However +we can encounter situations where the lambda is not on the stack when +used, especially when working with sub-tasks. + +## 21.03.2019 - Allocation on stack/static memory We can use the [placement new](https://www.geeksforgeeks.org/placement-new-operator-cpp/) operator for our tasks and other stuff to manage memory. This can allow the pure 'stack based' approach without any memory management suggested by mike. -## 20.03.2018 - Prohibit New +## 20.03.2019 - Prohibit New We want to write this library without using any runtime memory allocation to better fit the needs of the embedded marked. @@ -24,7 +53,7 @@ by using a new implementation with a break point in it. That way we for example ruled out std::thread, as we found the dynamic memory allocation used in it. -## 20.03.2018 - callable objects and memory allocation / why we use no std::thread +## 20.03.2019 - callable objects and memory allocation / why we use no std::thread When working with any sort of functionality that can be passed to an object or function it is usually passed as: diff --git a/lib/pls/CMakeLists.txt b/lib/pls/CMakeLists.txt index 661d055..b4a6b66 100644 --- a/lib/pls/CMakeLists.txt +++ b/lib/pls/CMakeLists.txt @@ -8,7 +8,7 @@ add_library(pls STATIC src/internal/scheduling/scheduler.cpp include/pls/internal/scheduling/scheduler.h src/internal/scheduling/thread_state.cpp include/pls/internal/scheduling/thread_state.h src/internal/base/barrier.cpp include/pls/internal/base/barrier.h - src/internal/scheduling/root_master_task.cpp include/pls/internal/scheduling/root_master_task.h + src/internal/scheduling/root_task.cpp include/pls/internal/scheduling/root_task.h src/internal/base/aligned_stack.cpp include/pls/internal/base/aligned_stack.h include/pls/internal/base/system_details.h src/internal/scheduling/run_on_n_threads_task.cpp include/pls/internal/scheduling/run_on_n_threads_task.h) diff --git a/lib/pls/include/pls/internal/scheduling/root_master_task.h b/lib/pls/include/pls/internal/scheduling/root_task.h similarity index 77% rename from lib/pls/include/pls/internal/scheduling/root_master_task.h rename to lib/pls/include/pls/internal/scheduling/root_task.h index ba46408..4d551b6 100644 --- a/lib/pls/include/pls/internal/scheduling/root_master_task.h +++ b/lib/pls/include/pls/internal/scheduling/root_task.h @@ -11,14 +11,14 @@ namespace pls { namespace internal { namespace scheduling { template - class root_master_task : public abstract_task { + class root_task : public abstract_task { Function function_; bool finished_; // Improvement: Remove lock and replace by atomic variable (performance) base::spin_lock finished_lock_; public: - explicit root_master_task(Function function): + explicit root_task(Function function): abstract_task{0, 0}, function_{function}, finished_{false} {} @@ -44,6 +44,30 @@ namespace pls { return false; } }; + + template + class root_worker_task : public abstract_task { + root_task* master_task_; + + public: + explicit root_worker_task(root_task* master_task): + abstract_task{0, 0}, + master_task_{master_task} {} + + void execute() override { + do { + steal_work(); + } while (!master_task_->finished()); + } + + bool internal_stealing(abstract_task* /*other_task*/) override { + return false; + } + + bool split_task() override { + return false; + } + }; } } } diff --git a/lib/pls/include/pls/internal/scheduling/root_worker_task.h b/lib/pls/include/pls/internal/scheduling/root_worker_task.h deleted file mode 100644 index ff67cbd..0000000 --- a/lib/pls/include/pls/internal/scheduling/root_worker_task.h +++ /dev/null @@ -1,37 +0,0 @@ - -#ifndef PLS_ROOT_WORKER_TASK_H -#define PLS_ROOT_WORKER_TASK_H - -#include "root_master_task.h" - -namespace pls { - namespace internal { - namespace scheduling { - template - class root_worker_task : public abstract_task { - root_master_task* master_task_; - - public: - explicit root_worker_task(root_master_task* master_task): - abstract_task{0, 0}, - master_task_{master_task} {} - - void execute() override { - do { - steal_work(); - } while (!master_task_->finished()); - } - - bool internal_stealing(abstract_task* /*other_task*/) override { - return false; - } - - bool split_task() override { - return false; - } - }; - } - } -} - -#endif //PLS_ROOT_WORKER_TASK_H diff --git a/lib/pls/include/pls/internal/scheduling/scheduler.h b/lib/pls/include/pls/internal/scheduling/scheduler.h index b8f1f39..e1493ad 100644 --- a/lib/pls/include/pls/internal/scheduling/scheduler.h +++ b/lib/pls/include/pls/internal/scheduling/scheduler.h @@ -10,8 +10,7 @@ #include "pls/internal/base/barrier.h" #include "thread_state.h" -#include "root_master_task.h" -#include "root_worker_task.h" +#include "root_task.h" namespace pls { namespace internal { @@ -65,7 +64,7 @@ namespace pls { template void perform_work(Function work_section) { - root_master_task master{work_section}; + root_task master{work_section}; root_worker_task worker{&master}; // Push root task on stacks diff --git a/lib/pls/src/internal/scheduling/root_master_task.cpp b/lib/pls/src/internal/scheduling/root_task.cpp similarity index 80% rename from lib/pls/src/internal/scheduling/root_master_task.cpp rename to lib/pls/src/internal/scheduling/root_task.cpp index 8b87c3b..ec1b68b 100644 --- a/lib/pls/src/internal/scheduling/root_master_task.cpp +++ b/lib/pls/src/internal/scheduling/root_task.cpp @@ -1,5 +1,4 @@ -#include "pls/internal/scheduling/root_master_task.h" -#include "pls/internal/scheduling/root_worker_task.h" +#include "pls/internal/scheduling/root_task.h" namespace pls { namespace internal { diff --git a/lib/pls/src/internal/scheduling/root_worker_task.cpp b/lib/pls/src/internal/scheduling/root_worker_task.cpp deleted file mode 100644 index 8b87c3b..0000000 --- a/lib/pls/src/internal/scheduling/root_worker_task.cpp +++ /dev/null @@ -1,10 +0,0 @@ -#include "pls/internal/scheduling/root_master_task.h" -#include "pls/internal/scheduling/root_worker_task.h" - -namespace pls { - namespace internal { - namespace scheduling { - - } - } -}