#ifndef common_h #define common_h 1 #include #include #include #include #include #include #include #include using namespace std::literals; void track(std::source_location l = std::source_location::current()) noexcept { std::printf("%s:%u %s\n", l.file_name(), l.line(), l.function_name()); } void function() { track(); } auto lambda = []() { track(); }; struct functor_type { void operator()() const { track(); } }; struct struct_type { void method() const { track(); } }; template void basic_test(fiber &&f) { if (f.joinable()) f.join(); } template concept has_detach = requires(F f) { f.detach(); }; template int common_main() { auto hi = [&](std::string_view sv) { std::cout << "0x" << std::hex << std::setfill('0') << std::setw(16) << reinterpret_cast((const void *)get_id()) << ": " << sv << '\n'; }; try { std::cout << "empty fiber test:\n"; fiber empty; std::cout << "empty.get_id() = " << empty.get_id() << '\n' << "empty.joinable() = " << std::boolalpha << empty.joinable() << '\n'; if (empty.joinable()) empty.join(); } catch (const std::exception &e) { std::cerr << "caught: " << e.what() << '\n'; } try { std::cout << "\nnull fiber test:\n"; fiber null([] {}); std::cout << "null.get_id() = " << null.get_id() << '\n' << "null.joinable() = " << std::boolalpha << null.joinable() << '\n'; if (null.joinable()) null.join(); } catch (const std::exception &e) { std::cerr << "caught: " << e.what() << '\n'; } std::cout << "\ncall test:\n"; basic_test(fiber(function)); basic_test(fiber(lambda)); basic_test(fiber(functor_type())); basic_test(fiber(&struct_type::method, struct_type())); std::cout << "\nyield test:\n"; auto lambda_yield = [&](std::string_view sv) { for (char s : sv) { std::cout << s << " -> " << std::flush; yield(); } }; fiber n(lambda_yield, "0123456789"), l(lambda_yield, "abc"); n.join(); l.join(); std::cout << '\n'; std::cout << "\nrecursive test:\n"; auto recursive = [&](auto &&self, char c = '1') -> void { std::string level(4 * (c - '0' + 1), '-'); hi(level + "> recursive call " + c); if (c < '4') fiber([&] { self(self, c + 1); }).join(); hi('<' + level + " recursive return " + c); }; recursive(recursive); try { std::cout << "\nself join test:\n"; fiber self( [&] { try { self.join(); } catch (const std::exception &e) { std::cerr << "caught: " << e.what() << '\n'; } }); std::cout << "self.get_id() = " << self.get_id() << '\n' << "self.joinable() = " << std::boolalpha << self.joinable() << '\n'; if (self.joinable()) self.join(); } catch (...) { std::cerr << "caught: unknown exception\n"; } if constexpr (has_detach) { std::cout << "\ndetach test:\n"; auto slow = [&] { hi("detached thread start"); hi("detached thread stop"); }; fiber(slow).detach(); fiber([] {}).join(); // help slow fiber to finish... } return 0; } #endif // common_h