diff options
author | Keuin <[email protected]> | 2022-04-20 00:22:02 +0800 |
---|---|---|
committer | Keuin <[email protected]> | 2022-04-20 00:22:02 +0800 |
commit | 3fa4d41e9cac75df7514c2ff8dd27842aaafc4a7 (patch) | |
tree | 90e3222e900fee3a1417a230010dc0fb963aba9f /threading.h | |
parent | ee3b665441b2f83041416098049cc16b6b63d942 (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.h | 41 |
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(); } |