diff --git a/Makefile b/Makefile index f0c8625..889f395 100644 --- a/Makefile +++ b/Makefile @@ -19,5 +19,5 @@ obuild: $(FILES) clean: rm -f $(FILES) obuild -main.o: $(CUBESCRIPT_PATH)/cubescript.hh +main.o: tpool.hh $(CUBESCRIPT_PATH)/cubescript.hh globs.o: $(CUBESCRIPT_PATH)/cubescript.hh diff --git a/main.cc b/main.cc index 0dc4ae5..031e5ce 100644 --- a/main.cc +++ b/main.cc @@ -9,12 +9,13 @@ #include #include #include -#include #include #include #include +#include "tpool.hh" + void cs_register_globs(cscript::CsState &cs); using ostd::ConstCharRange; @@ -23,7 +24,6 @@ using ostd::Map; using ostd::String; using ostd::Uint32; using ostd::slice_until; -using ostd::Thread; using ostd::UniqueLock; using ostd::Mutex; using ostd::Condition; @@ -33,105 +33,6 @@ using cscript::TvalRange; using cscript::StackedValue; using cscript::Bytecode; -/* thread pool */ - -struct ThreadPool { - ThreadPool(): - cond(), mtx(), thrs(), tasks(nullptr), last_task(nullptr), - running(false) - {} - - ~ThreadPool() { - destroy(); - } - - static void *thr_func(void *ptr) { - static_cast(ptr)->run(); - return nullptr; - } - - bool init(ostd::Size size) { - running = true; - for (ostd::Size i = 0; i < size; ++i) { - Thread tid([this]() { run(); }); - if (!tid) { - return false; - } - thrs.push(ostd::move(tid)); - } - return true; - } - - void destroy() { - mtx.lock(); - if (!running) { - mtx.unlock(); - return; - } - running = false; - mtx.unlock(); - cond.broadcast(); - for (Thread &tid: thrs.iter()) { - tid.join(); - cond.broadcast(); - } - } - - void run() { - for (;;) { - UniqueLock l(mtx); - while (running && (tasks == nullptr)) { - cond.wait(l); - } - if (!running) { - l.unlock(); - ostd::this_thread::exit(); - } - Task *t = tasks; - tasks = t->next; - if (last_task == t) { - last_task = nullptr; - } - l.unlock(); - t->cb(); - delete t; - } - } - - void push(ostd::Function func) { - mtx.lock(); - Task *t = new Task(ostd::move(func)); - if (last_task) { - last_task->next = t; - } - last_task = t; - if (!tasks) { - tasks = t; - } - cond.signal(); - mtx.unlock(); - } - -private: - struct Task { - ostd::Function cb; - Task *next = nullptr; - Task() = delete; - Task(Task const &) = delete; - Task(Task &&) = delete; - Task(ostd::Function &&cbf): cb(ostd::move(cbf)) {} - Task &operator=(Task const &) = delete; - Task &operator=(Task &&) = delete; - }; - - Condition cond; - Mutex mtx; - Vector thrs; - Task *tasks; - Task *last_task; - bool volatile running; -}; - /* check funcs */ static bool ob_check_ts(ConstCharRange tname, Vector const &deps) { diff --git a/obuild.cfg b/obuild.cfg index 1eb2d81..dc02b54 100644 --- a/obuild.cfg +++ b/obuild.cfg @@ -24,7 +24,7 @@ action clean [ shell rm -f $FILES obuild_ob ] -depend main_ob.o [@CS_PATH/cubescript.hh] +depend main_ob.o [tpool.hh @CS_PATH/cubescript.hh] depend globs_ob.o [@CS_PATH/cubescript.hh] rule default obuild diff --git a/tpool.hh b/tpool.hh new file mode 100644 index 0000000..b87d1ad --- /dev/null +++ b/tpool.hh @@ -0,0 +1,109 @@ +#ifndef OBUILD_TPOOL_HH +#define OBUILD_TPOOL_HH + +#include + +using ostd::Thread; +using ostd::UniqueLock; +using ostd::Mutex; +using ostd::Condition; +using ostd::Vector; + +struct ThreadPool { + ThreadPool(): + cond(), mtx(), thrs(), tasks(nullptr), last_task(nullptr), + running(false) + {} + + ~ThreadPool() { + destroy(); + } + + static void *thr_func(void *ptr) { + static_cast(ptr)->run(); + return nullptr; + } + + bool init(ostd::Size size) { + running = true; + for (ostd::Size i = 0; i < size; ++i) { + Thread tid([this]() { run(); }); + if (!tid) { + return false; + } + thrs.push(ostd::move(tid)); + } + return true; + } + + void destroy() { + mtx.lock(); + if (!running) { + mtx.unlock(); + return; + } + running = false; + mtx.unlock(); + cond.broadcast(); + for (Thread &tid: thrs.iter()) { + tid.join(); + cond.broadcast(); + } + } + + void run() { + for (;;) { + UniqueLock l(mtx); + while (running && (tasks == nullptr)) { + cond.wait(l); + } + if (!running) { + l.unlock(); + ostd::this_thread::exit(); + } + Task *t = tasks; + tasks = t->next; + if (last_task == t) { + last_task = nullptr; + } + l.unlock(); + t->cb(); + delete t; + } + } + + void push(ostd::Function func) { + mtx.lock(); + Task *t = new Task(ostd::move(func)); + if (last_task) { + last_task->next = t; + } + last_task = t; + if (!tasks) { + tasks = t; + } + cond.signal(); + mtx.unlock(); + } + +private: + struct Task { + ostd::Function cb; + Task *next = nullptr; + Task() = delete; + Task(Task const &) = delete; + Task(Task &&) = delete; + Task(ostd::Function &&cbf): cb(ostd::move(cbf)) {} + Task &operator=(Task const &) = delete; + Task &operator=(Task &&) = delete; + }; + + Condition cond; + Mutex mtx; + Vector thrs; + Task *tasks; + Task *last_task; + bool volatile running; +}; + +#endif \ No newline at end of file