Commit ee8ec319 by FritzFlorian

Combine root_tasks into one file.

parent 251e228d
......@@ -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:
......
......@@ -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)
......
......@@ -11,14 +11,14 @@ namespace pls {
namespace internal {
namespace scheduling {
template<typename Function>
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<typename Function>
class root_worker_task : public abstract_task {
root_task<Function>* master_task_;
public:
explicit root_worker_task(root_task<Function>* 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;
}
};
}
}
}
......
#ifndef PLS_ROOT_WORKER_TASK_H
#define PLS_ROOT_WORKER_TASK_H
#include "root_master_task.h"
namespace pls {
namespace internal {
namespace scheduling {
template<typename Function>
class root_worker_task : public abstract_task {
root_master_task<Function>* master_task_;
public:
explicit root_worker_task(root_master_task<Function>* 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
......@@ -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<typename Function>
void perform_work(Function work_section) {
root_master_task<Function> master{work_section};
root_task<Function> master{work_section};
root_worker_task<Function> worker{&master};
// Push root task on stacks
......
#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 {
......
#include "pls/internal/scheduling/root_master_task.h"
#include "pls/internal/scheduling/root_worker_task.h"
namespace pls {
namespace internal {
namespace scheduling {
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment