| SRCS = src/BBBParser.cc src/SourceFile.cc src/toolchain.cc src/globals.cc src/sys.cc src/main.cc | |||||
| HDRS = src/BBBParser.h src/SourceFile.h src/toolchain.h src/globals.h src/sys.h src/parallel.h | |||||
| SRCS = \ | |||||
| src/BBBParser.cc src/SourceFile.cc src/toolchain.cc src/globals.cc \ | |||||
| src/sys.cc src/parallel.cc src/main.cc | |||||
| HDRS = src/BBBParser.h src/SourceFile.h src/toolchain.h src/globals.h \ | |||||
| src/sys.h src/parallel.h | |||||
| BUILD = build | BUILD = build | ||||
| OBJS = $(patsubst %,$(BUILD)/%.o,$(SRCS)) | OBJS = $(patsubst %,$(BUILD)/%.o,$(SRCS)) | ||||
| CFLAGS = -g -Wall -Wextra -Wno-unused-parameter | CFLAGS = -g -Wall -Wextra -Wno-unused-parameter | ||||
| LDLIBS = -lpthread | |||||
| $(BUILD)/%.cc.o: %.cc $(HDRS) | $(BUILD)/%.cc.o: %.cc $(HDRS) | ||||
| @mkdir -p $(@D) | @mkdir -p $(@D) |
| } | } | ||||
| void SourceFile::compile(const std::string &outDir) const { | void SourceFile::compile(const std::string &outDir) const { | ||||
| // TODO: Send this as a message to some printer thread instead, | |||||
| // because this happens in multiple threads | |||||
| std::cerr << "Compile " << objectPath(outDir) << '\n'; | std::cerr << "Compile " << objectPath(outDir) << '\n'; | ||||
| toolchain::compile(compileFlags(), type_, dir_, name_, outDir); | toolchain::compile(compileFlags(), type_, dir_, name_, outDir); | ||||
| #include "parallel.h" | #include "parallel.h" | ||||
| #include <thread> | #include <thread> | ||||
| #include <vector> | |||||
| #include <mutex> | |||||
| #include <condition_variable> | |||||
| namespace parallel { | |||||
| void runJobs( | |||||
| int jobs, const std::vector<void *> &elems, | |||||
| std::function<void(void *)> func) { | |||||
| int currentJobs = 0; | |||||
| std::mutex mut; | |||||
| std::unique_lock<std::mutex> lock(mut); | |||||
| std::condition_variable cond; | |||||
| for (void *elem: elems) { | |||||
| cond.wait(lock, [&] { return currentJobs < jobs; }); | |||||
| currentJobs += 1; | |||||
| std::thread thread([elem, jobs, ¤tJobs, &mut, &cond, &func] { | |||||
| func(elem); | |||||
| mut.lock(); | |||||
| currentJobs -= 1; | |||||
| mut.unlock(); | |||||
| cond.notify_one(); | |||||
| }); | |||||
| thread.detach(); | |||||
| } | |||||
| cond.wait(lock, [&] { return currentJobs == 0; }); | |||||
| } | |||||
| int coreCount() { | int coreCount() { | ||||
| return std::thread::hardware_concurrency(); | return std::thread::hardware_concurrency(); | ||||
| } | } | ||||
| } |
| #pragma once | #pragma once | ||||
| #include <thread> | |||||
| #include <functional> | |||||
| #include <vector> | |||||
| namespace parallel { | namespace parallel { | ||||
| void runJobs( | |||||
| int jobs, const std::vector<void *> &elems, | |||||
| std::function<void(void *)> func); | |||||
| template<typename Container, typename Func> | template<typename Container, typename Func> | ||||
| void parallel(int jobs, Container &cont, Func func) { | void parallel(int jobs, Container &cont, Func func) { | ||||
| // TODO: Actually run this in parallel | |||||
| for (auto &elem: cont) { | |||||
| func(elem); | |||||
| if (jobs == 1) { | |||||
| for (auto &elem: cont) { | |||||
| func(elem); | |||||
| } | |||||
| } else { | |||||
| std::vector<void *> elems; | |||||
| for (auto &elem: cont) { | |||||
| elems.push_back((void *)&elem); | |||||
| } | |||||
| runJobs(jobs, elems, [&func](void *el) { | |||||
| func(*(typename Container::value_type *)el); | |||||
| }); | |||||
| } | } | ||||
| } | } | ||||
| inline int coreCount() { | |||||
| return std::thread::hardware_concurrency(); | |||||
| } | |||||
| int coreCount(); | |||||
| } | } |