more build cleanups and emplace for channels

master
Daniel Kolesa 2017-05-05 02:00:02 +02:00
parent 1cc0577513
commit fc6935151d
2 changed files with 104 additions and 82 deletions

162
build.cc
View File

@ -27,25 +27,27 @@ namespace fs = ostd::filesystem;
/* ugly, but do not explicitly compile */ /* ugly, but do not explicitly compile */
#include "src/io.cc" #include "src/io.cc"
using strvec = std::vector<std::string>;
/* THESE VARIABLES CAN BE ALTERED */ /* THESE VARIABLES CAN BE ALTERED */
static std::string EXAMPLES[] = { static std::vector<std::string> EXAMPLES = {
"format", "listdir", "range", "range_pipe", "signal", "format", "listdir", "range", "range_pipe", "signal",
"stream1", "stream2", "coroutine1", "coroutine2", "concurrency" "stream1", "stream2", "coroutine1", "coroutine2", "concurrency"
}; };
static fs::path ASM_SOURCE_DIR = "src/asm"; static fs::path ASM_SOURCE_DIR = "src/asm";
static std::string ASM_SOURCES[] = { static strvec ASM_SOURCES = {
"jump_all_gas", "make_all_gas", "ontop_all_gas" "jump_all_gas", "make_all_gas", "ontop_all_gas"
}; };
static fs::path CXX_SOURCE_DIR = "src"; static fs::path CXX_SOURCE_DIR = "src";
static std::string CXX_SOURCES[] = { static strvec CXX_SOURCES = {
"context_stack", "environ", "io", "concurrency" "context_stack", "environ", "io", "concurrency"
}; };
static fs::path TEST_DIR = "tests"; static fs::path TEST_DIR = "tests";
static std::string TEST_CASES[] = { static strvec TEST_CASES = {
"algorithm", "range" "algorithm", "range"
}; };
@ -107,9 +109,7 @@ static void print_help(ostd::string_range arg0) {
); );
} }
static void exec_command( static void exec_command(std::string const &cmd, strvec const &args) {
std::string const &cmd, std::vector<std::string> const &args
) {
auto argp = std::make_unique<char *[]>(args.size() + 2); auto argp = std::make_unique<char *[]>(args.size() + 2);
argp[0] = const_cast<char *>(cmd.data()); argp[0] = const_cast<char *>(cmd.data());
for (std::size_t i = 0; i < args.size(); ++i) { for (std::size_t i = 0; i < args.size(); ++i) {
@ -134,9 +134,7 @@ static void exec_command(
} }
} }
static std::string get_command( static std::string get_command(std::string const &cmd, strvec const &args) {
std::string const &cmd, std::vector<std::string> const &args
) {
std::string ret = cmd; std::string ret = cmd;
for (auto &s: args) { for (auto &s: args) {
ret += ' '; ret += ' ';
@ -145,7 +143,7 @@ static std::string get_command(
return ret; return ret;
} }
static void add_args(std::vector<std::string> &args, std::string const &cmdl) { static void add_args(strvec &args, std::string const &cmdl) {
wordexp_t p; wordexp_t p;
if (wordexp(cmdl.data(), &p, 0)) { if (wordexp(cmdl.data(), &p, 0)) {
return; return;
@ -297,9 +295,7 @@ int main(int argc, char **argv) {
} }
}; };
auto exec_v = [&io_msgs]( auto exec_v = [&io_msgs](std::string const &cmd, strvec const &args) {
std::string const &cmd, std::vector<std::string> const &args
) {
if (verbose) { if (verbose) {
io_msgs.put(get_command(cmd, args)); io_msgs.put(get_command(cmd, args));
} }
@ -307,58 +303,70 @@ int main(int argc, char **argv) {
}; };
auto call_cxx = [&]( auto call_cxx = [&](
std::string const &input, std::string const &output, bool shared fs::path const &input, fs::path const &output, bool shared
) { ) {
std::vector<std::string> args; strvec args;
add_args(args, cxxflags); add_args(args, cxxflags);
auto ifs = input.string();
auto outp = output;
if (shared) { if (shared) {
echo_q("CXX (shared): %s", input); outp.replace_extension();
outp += "_dyn.o";
echo_q("CXX (shared): %s", ifs);
add_args(args, SHARED_CXXFLAGS); add_args(args, SHARED_CXXFLAGS);
} else { } else {
echo_q("CXX: %s", input); echo_q("CXX: %s", ifs);
} }
args.push_back("-c"); args.push_back("-c");
args.push_back("-o"); args.push_back("-o");
args.push_back(output); args.push_back(outp.string());
args.push_back(input); args.push_back(ifs);
exec_v(cxx, args); exec_v(cxx, args);
return outp;
}; };
/* mostly unnecessary to separately compile shared, but /* mostly unnecessary to separately compile shared, but
* the files may check for __PIC__ (at least mips32 does) * the files may check for __PIC__ (at least mips32 does)
*/ */
auto call_as = [&]( auto call_as = [&](
std::string const &input, std::string const &output, bool shared fs::path const &input, fs::path const &output, bool shared
) { ) {
std::vector<std::string> args; strvec args;
add_args(args, asflags); add_args(args, asflags);
auto ifs = input.string();
auto outp = output;
if (shared) { if (shared) {
echo_q("AS (shared): %s", input); outp.replace_extension();
outp += "_dyn.o";
echo_q("AS (shared): %s", ifs);
add_args(args, SHARED_ASFLAGS); add_args(args, SHARED_ASFLAGS);
} else { } else {
echo_q("AS: %s", input); echo_q("AS: %s", ifs);
} }
args.push_back("-c"); args.push_back("-c");
args.push_back("-o"); args.push_back("-o");
args.push_back(output); args.push_back(outp.string());
args.push_back(input); args.push_back(ifs);
exec_v(as, args); exec_v(as, args);
return outp;
}; };
auto call_ld = [&]( auto call_ld = [&](
std::string const &output, std::string const &output, strvec const &files, strvec const &flags
std::vector<std::string> const &files,
std::vector<std::string> const &flags
) { ) {
echo_q("LD: %s", output); echo_q("LD: %s", output);
std::vector<std::string> args; strvec args;
add_args(args, cxxflags); add_args(args, cxxflags);
args.push_back("-o"); args.push_back("-o");
@ -378,10 +386,9 @@ int main(int argc, char **argv) {
}; };
auto call_ldlib = [&]( auto call_ldlib = [&](
std::string const &output, std::vector<std::string> const &files, std::string const &output, strvec const &files, bool shared
bool shared
) { ) {
std::vector<std::string> args; strvec args;
if (shared) { if (shared) {
add_args(args, SHARED_CXXFLAGS); add_args(args, SHARED_CXXFLAGS);
add_args(args, SHARED_LDFLAGS); add_args(args, SHARED_LDFLAGS);
@ -402,7 +409,7 @@ int main(int argc, char **argv) {
auto ccf = path_with_ext(base, ".cc"); auto ccf = path_with_ext(base, ".cc");
auto obf = path_with_ext(base, ".o"); auto obf = path_with_ext(base, ".o");
call_cxx(ccf.string(), obf.string(), false); call_cxx(ccf, obf, false);
call_ld(base.string(), { obf.string() }, { default_lib }); call_ld(base.string(), { obf.string() }, { default_lib });
try_remove(obf); try_remove(obf);
@ -436,7 +443,7 @@ int main(int argc, char **argv) {
); );
f.close(); f.close();
call_cxx(ccf.string(), obf.string(), false); call_cxx(ccf, obf, false);
call_ld(base.string(), { obf.string() }, { default_lib }); call_ld(base.string(), { obf.string() }, { default_lib });
try_remove(obf); try_remove(obf);
}; };
@ -447,68 +454,61 @@ int main(int argc, char **argv) {
try_remove("test_runner.o"); try_remove("test_runner.o");
}; };
std::vector<std::string> asm_obj, cxx_obj, asm_dynobj, cxx_dynobj;
ostd::thread_pool tp; ostd::thread_pool tp;
tp.start(); tp.start();
std::queue<std::future<void>> futures; std::queue<std::future<fs::path>> future_obj, future_dynobj;
/* build object file in static and shared (PIC) variants */ /* build object files in static and shared (PIC) variants */
auto build_obj = [&tp, &futures, build_static, build_shared]( auto build_all = [&](
fs::path const &fpath, fs::path const &sext, auto &buildf, strvec &list, fs::path const &spath, fs::path const &sext, auto &buildf
auto &obj, auto &dynobj
) { ) {
auto srcf = path_with_ext(fpath, sext); auto build_obj = [&](fs::path const &fpath, bool shared) {
if (build_static) { auto srcf = path_with_ext(fpath, sext);
auto srco = path_with_ext(srcf, ".o"); auto srco = path_with_ext(srcf, ".o");
futures.push(tp.push([&, srcf, srco]() { auto &fq = (shared ? future_dynobj : future_obj);
buildf(srcf.string(), srco.string(), false); fq.push(tp.push([&buildf, srcf, srco, shared]() {
return buildf(srcf, srco, shared);
})); }));
obj.push_back(srco.string()); };
} for (auto sf: list) {
if (build_shared) { auto sp = spath / sf;
auto srco = srcf; if (build_static) {
srco.replace_extension(); build_obj(sp, false);
srco += "_dyn.o"; }
futures.push(tp.push([&, srcf, srco]() { if (build_shared) {
buildf(srcf.string(), srco.string(), true); build_obj(sp, true);
})); }
dynobj.push_back(srco.string());
} }
}; };
echo_q("Building the library..."); echo_q("Building the library...");
for (auto aso: ASM_SOURCES) { build_all(ASM_SOURCES, ASM_SOURCE_DIR, ".S", call_as);
build_obj(ASM_SOURCE_DIR / aso, ".S", call_as, asm_obj, asm_dynobj); build_all(CXX_SOURCES, CXX_SOURCE_DIR, ".cc", call_cxx);
}
for (auto cso: CXX_SOURCES) {
build_obj(CXX_SOURCE_DIR / cso, ".cc", call_cxx, cxx_obj, cxx_dynobj);
}
while (!futures.empty()) {
/* wait and propagate possible exception */
futures.front().get();
futures.pop();
}
if (build_static) { if (build_static) {
std::vector<std::string> all_obj; strvec objs;
all_obj.insert(all_obj.cend(), asm_obj.begin(), asm_obj.end()); while (!future_obj.empty()) {
all_obj.insert(all_obj.cend(), cxx_obj.begin(), cxx_obj.end()); objs.push_back(future_obj.front().get());
call_ldlib(OSTD_STATIC_LIB, all_obj, false); future_obj.pop();
}
call_ldlib(OSTD_STATIC_LIB, objs, false);
} }
if (build_shared) { if (build_shared) {
std::vector<std::string> all_obj; strvec objs;
all_obj.insert(all_obj.cend(), asm_dynobj.begin(), asm_dynobj.end()); while (!future_dynobj.empty()) {
all_obj.insert(all_obj.cend(), cxx_dynobj.begin(), cxx_dynobj.end()); objs.push_back(future_dynobj.front().get());
call_ldlib(OSTD_SHARED_LIB, all_obj, true); future_dynobj.pop();
}
call_ldlib(OSTD_SHARED_LIB, objs, true);
} }
std::queue<std::future<void>> future_bin;
if (build_examples) { if (build_examples) {
echo_q("Building examples..."); echo_q("Building examples...");
for (auto ex: EXAMPLES) { for (auto ex: EXAMPLES) {
futures.push(tp.push([&build_example, ex]() { future_bin.push(tp.push([&build_example, ex]() {
build_example(ex); build_example(ex);
})); }));
} }
@ -524,16 +524,16 @@ int main(int argc, char **argv) {
} }
} }
for (auto test: TEST_CASES) { for (auto test: TEST_CASES) {
futures.push(tp.push([&build_test, test]() { future_bin.push(tp.push([&build_test, test]() {
build_test(test); build_test(test);
})); }));
} }
} }
while (!futures.empty()) { while (!future_bin.empty()) {
/* wait and propagate possible exception */ /* wait and propagate possible exception */
futures.front().get(); future_bin.front().get();
futures.pop(); future_bin.pop();
} }
if (build_testsuite) { if (build_testsuite) {

View File

@ -115,12 +115,22 @@ struct channel {
* *
* @throws ostd::channel_error when the channel is closed. * @throws ostd::channel_error when the channel is closed.
* *
* @see put(T const &) * @see put(T const &), emplace()
*/ */
void put(T &&val) { void put(T &&val) {
p_state->put(std::move(val)); p_state->put(std::move(val));
} }
/** @brief Like put(), but constructs the element in-place.
*
* The arguments are to be passed to the element constructor.
* No copy or move operations are performed.
*/
template<typename ...A>
void emplace(A &&...args) {
p_state->emplace(std::forward<A>(args)...);
}
/** @brief Waits for a value and returns it. /** @brief Waits for a value and returns it.
* *
* If the queue is empty at the time of the call, this will block the * If the queue is empty at the time of the call, this will block the
@ -211,6 +221,18 @@ private:
p_cond.notify_one(); p_cond.notify_one();
} }
template<typename ...A>
void emplace(A &&...args) {
{
std::lock_guard<std::mutex> l{p_lock};
if (p_closed) {
throw channel_error{"emplace in a closed channel"};
}
p_messages.emplace(std::forward<A>(args)...);
}
p_cond.notify_one();
}
bool get(T &val, bool w) { bool get(T &val, bool w) {
std::unique_lock<std::mutex> l{p_lock}; std::unique_lock<std::mutex> l{p_lock};
if (w) { if (w) {