summaryrefslogtreecommitdiff
path: root/threading.h
diff options
context:
space:
mode:
authorKeuin <[email protected]>2022-04-20 00:22:02 +0800
committerKeuin <[email protected]>2022-04-20 00:22:02 +0800
commit3fa4d41e9cac75df7514c2ff8dd27842aaafc4a7 (patch)
tree90e3222e900fee3a1417a230010dc0fb963aba9f /threading.h
parentee3b665441b2f83041416098049cc16b6b63d942 (diff)
Code refactor: make basic_viewport and aa_viewport no longer a child class. Move data into classes.
Code refactor: make threading.h more specific, reducing redundant data copies in memory. Code refactor: make camera parameters more clear and well-defined in viewport.h, ready to extend camera flexibility.
Diffstat (limited to 'threading.h')
-rw-r--r--threading.h41
1 files changed, 23 insertions, 18 deletions
diff --git a/threading.h b/threading.h
index 73a1741..6d79494 100644
--- a/threading.h
+++ b/threading.h
@@ -18,31 +18,36 @@
// Tasks should be added into the queue before starting.
// Once the task queue is empty, threads quit.
+template<typename T_Args, typename T_ImmuCtx, typename T_MutCtx>
+using task_func_t = void (*)(size_t, T_Args &, const T_ImmuCtx &, T_MutCtx &);
+
// internal usage
-template<typename T>
+template<typename T, typename U, typename V>
struct s_task {
- void (*f)(T &);
-
+ task_func_t<T, U, V> f;
T arg;
};
-template<typename T>
+template<typename T, typename U, typename V>
class thread_pool {
unsigned thread_count;
std::vector<std::thread> workers;
std::atomic<size_t> counter{0}; // index to the first available task in queue
- std::vector<s_task<T>> tasks;
+ std::vector<s_task<T, U, V>> tasks;
+ const U &shared_ctx; // reference to immutable shared context
+ V &mut_shared_ctx; // mutable shared context
void worker_main();
public:
- explicit thread_pool(unsigned thread_count) : thread_count{thread_count} {
+ explicit thread_pool(unsigned thread_count, const U &shared_ctx, V &mut_shared_ctx) :
+ thread_count{thread_count}, shared_ctx{shared_ctx}, mut_shared_ctx{mut_shared_ctx} {
std::cerr << "Using " << (counter.is_lock_free() ? "lock-free" : "locking") << " dispatcher." << std::endl;
}
// Thread unsafe!
- void submit_task(void (*f)(T &), T &&t);
+ void submit_task(task_func_t<T, U, V> f, T &&t);
void start();
@@ -50,36 +55,36 @@ public:
void wait();
};
-template<typename T>
-void thread_pool<T>::start() {
+template<typename T, typename U, typename V>
+void thread_pool<T, U, V>::start() {
if (workers.empty()) {
for (typeof(thread_count) i = 0; i < thread_count; ++i) {
- workers.emplace_back(std::thread{&thread_pool<T>::worker_main, this});
+ workers.emplace_back(std::thread{&thread_pool<T, U, V>::worker_main, this});
}
} else {
// TODO
}
}
-template<typename T>
-void thread_pool<T>::worker_main() {
+template<typename T, typename U, typename V>
+void thread_pool<T, U, V>::worker_main() {
const auto max_cnt = tasks.size();
while (true) {
const auto i = counter.fetch_add(1, std::memory_order_relaxed); // we only need atomicity
if (i >= max_cnt) break; // all tasks are done
auto &task = tasks[i];
- task.f(task.arg);
+ task.f(i, task.arg, shared_ctx, mut_shared_ctx);
}
}
// Do not submit after starting.
-template<typename T>
-void thread_pool<T>::submit_task(void (*f)(T &), T &&t) {
- tasks.push_back(s_task<T>{.f=f, .arg=std::move(t)});
+template<typename T, typename U, typename V>
+void thread_pool<T, U, V>::submit_task(task_func_t<T, U, V> f, T &&t) {
+ tasks.push_back(s_task<T, U, V>{.f=f, .arg=std::move(t)});
}
-template<typename T>
-void thread_pool<T>::wait() {
+template<typename T, typename U, typename V>
+void thread_pool<T, U, V>::wait() {
for (auto &th: workers) {
th.join();
}