feat/support_fiber #2

Merged
tqcq merged 57 commits from feat/support_fiber into master 2024-06-21 10:33:52 +08:00
6 changed files with 71 additions and 50 deletions
Showing only changes of commit ab8c2bf2cc - Show all commits

View File

@ -204,7 +204,7 @@ if((NOT TILE_HAVE_GETIFADDRS) OR (NOT TILE_HAVE_FREEIFADDRS))
list(APPEND TILE_SRCS "tile/base/net/detail/android/ifaddrs.c") list(APPEND TILE_SRCS "tile/base/net/detail/android/ifaddrs.c")
endif() endif()
add_library(tile OBJECT ${TILE_SRCS} ${ASM_SRCS}) add_library(tile OBJECT ${TILE_SRCS})
set_target_properties(tile PROPERTIES VERSION ${PROJECT_VERSION} set_target_properties(tile PROPERTIES VERSION ${PROJECT_VERSION}
SOVERSION "${tile_VERSION_MAJRO}") SOVERSION "${tile_VERSION_MAJRO}")
# target_sources(tile PRIVATE ${TILE_SRCS}) # target_sources(tile PRIVATE ${TILE_SRCS})

View File

@ -10,7 +10,7 @@ cmake_minimum_required(VERSION 3.5...3.16)
project( project(
nova_context nova_context
VERSION 0.1.0 VERSION 0.1.0
LANGUAGES C) LANGUAGES C ASM)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
@ -197,6 +197,7 @@ set(ASM_SRC
unset(_asm_suffix) unset(_asm_suffix)
set_source_files_properties(${ASM_SRC} PROPERTIES LINKER_LANGUAGE C)
# POWERPC_32/SYSV Special case: https://github.com/boostorg/context/issues/120 # POWERPC_32/SYSV Special case: https://github.com/boostorg/context/issues/120
if((NOVA_CONTEXT_ARCHITECTURE STREQUAL ppc32) AND (NOVA_CONTEXT_ABI STREQUAL if((NOVA_CONTEXT_ARCHITECTURE STREQUAL ppc32) AND (NOVA_CONTEXT_ABI STREQUAL
sysv)) sysv))
@ -210,8 +211,8 @@ if(NOVA_CONTEXT_ASSEMBLER STREQUAL masm AND NOVA_CONTEXT_ARCHITECTURE STREQUAL
endif() endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL GNU) if(CMAKE_CXX_COMPILER_ID STREQUAL GNU)
set_source_files_properties(${ASM_SRC} PROPERTIES COMPILE_OPTIONS # set_source_files_properties(${ASM_SRC} PROPERTIES COMPILE_OPTIONS
"-x assembler-with-cpp") # "-x assembler-with-cpp")
endif() endif()
# Boost specific definitions # Boost specific definitions

View File

@ -57,6 +57,13 @@ auto format_as(const T &val)
return val.ToString(); return val.ToString();
} }
template <typename T>
auto format_as(T *ptr)
-> tile::enable_if_t<!std::is_void<tile::remove_cvref_t<T>>::value,
void *> {
return reinterpret_cast<void *>(ptr);
}
#define TILE_INSTANCE_CHRONO_FORMAT_AS(type, suffix) \ #define TILE_INSTANCE_CHRONO_FORMAT_AS(type, suffix) \
inline std::string format_as(const type &val) { \ inline std::string format_as(const type &val) { \
return tile::detail::format_as_impl(val, suffix); \ return tile::detail::format_as_impl(val, suffix); \
@ -80,4 +87,17 @@ TILE_INSTANCE_CHRONO_FORMAT_AS(std::chrono::years, "y")
#include "fmt/format.h" #include "fmt/format.h"
#include "fmt/ostream.h" #include "fmt/ostream.h"
inline std::ostream &operator<<(std::ostream &os, std::nullptr_t) {
return os << "nullptr";
}
// template <typename T,
// typename = tile::enable_if_t<
// !tile::detail::is_streamable<std::ostream, T *>::value &&
// !std::is_same<tile::remove_cvref_t<T *>,
// std::nullptr_t>::value>>
// std::ostream &operator<<(std::ostream &os, T *ptr) {
// return os << fmt::format("{}", fmt::ptr(ptr));
// }
#endif // TILE_BASE_INTERNAL_FORMAT_H #endif // TILE_BASE_INTERNAL_FORMAT_H

View File

@ -16,32 +16,38 @@ namespace detail {
static thread_local Fiber *tls_current_fiber = nullptr; static thread_local Fiber *tls_current_fiber = nullptr;
static thread_local Fiber *tls_master_fiber = nullptr; static thread_local Fiber *tls_master_fiber = nullptr;
constexpr auto kStackSize = 8192; constexpr std::size_t kStackSize = 8192;
constexpr auto kAlignSize = 16; constexpr std::size_t kAlignSize = 16;
void RunProc(void *arg) { void FiberEntry(fcontext_transfer_t t) {
auto proc = static_cast<std::function<void()> *>(arg); // TILE_LOG_INFO("FiberEntry creater {}, proc {}", t.fctx, t.data);
if (proc) { std::function<void()> *fn = static_cast<std::function<void()> *>(t.data);
(*proc)(); TILE_CHECK_NE(t.data, nullptr);
TILE_CHECK_NE(t.fctx, nullptr);
try {
t = jump_fcontext(t.fctx, nullptr);
(*fn)();
} catch (const std::exception &e) {
// TILE_LOG_ERROR("Exception caught in fiber: {}", e.what());
} }
Fiber::MasterFiber()->Resume(); TILE_CHECK_NE(t.fctx, nullptr);
// TILE_LOG_INFO("FiberEntry End. Resume to {}", t.fctx);
jump_fcontext(t.fctx, nullptr);
} }
void RunProc1(fcontext_transfer_t ft) { fcontext_t CreateFiber(void *stack, std::size_t stack_size,
auto t = jump_fcontext(ft.fctx, nullptr); std::function<void()> *fn) {
void *stack_top = static_cast<char *>(stack) + stack_size;
const fcontext_t fctx = make_fcontext(stack_top, stack_size, FiberEntry);
TILE_CHECK_NE(fctx, nullptr);
auto proc = static_cast<std::function<void()> *>(ft.data); return jump_fcontext(fctx, fn).fctx;
TILE_LOG_INFO("proc: {}", fmt::ptr(proc));
if (proc) {
(*proc)();
}
Fiber::MasterFiber()->Resume();
} }
struct alignas(hardware_destructive_interference_size) Fiber::FiberContext { struct alignas(hardware_destructive_interference_size) Fiber::FiberContext {
fcontext_t fctx; fcontext_t fctx;
// tile_ucontext_t uctx;
std::aligned_storage<kStackSize, kAlignSize>::type stack; std::aligned_storage<kStackSize, kAlignSize>::type stack;
std::function<void()> proc;
}; };
Fiber *Fiber::Current() noexcept { return tls_current_fiber; } Fiber *Fiber::Current() noexcept { return tls_current_fiber; }
@ -56,12 +62,13 @@ std::unique_ptr<Fiber> Fiber::Create(std::function<void()> proc) noexcept {
} }
Fiber::Fiber(std::function<void()> proc) Fiber::Fiber(std::function<void()> proc)
: ctx_(object_pool::Get<FiberContext>().Leak()), proc_(std::move(proc)) { : ctx_(object_pool::Get<FiberContext>().Leak()) {
// memset(&ctx_->uctx, 0, sizeof(tile_ucontext_t)); ctx_->proc = std::move(proc);
// memset(&ctx_->stack, 0, kStackSize); if (ctx_->proc) {
if (proc_) { ctx_->fctx = CreateFiber(&ctx_->stack, kStackSize, &ctx_->proc);
make_fcontext(&ctx_->stack, kStackSize, RunProc1); } else {
ctx_->fctx = nullptr;
} }
} }
@ -75,12 +82,14 @@ void Fiber::Resume() {
auto caller = Current(); auto caller = Current();
TILE_CHECK_NE(caller, this, "Can't `Resume()` self"); TILE_CHECK_NE(caller, this, "Can't `Resume()` self");
SetCurrent(this); SetCurrent(this);
// tile_ucontext_swap(&caller->ctx_->uctx, &ctx_->uctx); // TILE_LOG_INFO("Resume before proc: {}", fmt::ptr(&proc_));
TILE_LOG_INFO("proc: {}", fmt::ptr(&proc_)); ctx_->fctx = jump_fcontext(ctx_->fctx, nullptr).fctx;
jump_fcontext(ctx_->fctx, nullptr); // TILE_LOG_INFO("Resume after proc: {}", fmt::ptr(&proc_));
SetCurrent(caller); SetCurrent(caller);
} }
void Fiber::Yield() {}
} // namespace detail } // namespace detail
} // namespace fiber } // namespace fiber

View File

@ -43,21 +43,20 @@ public:
Fiber(Fiber &&other) noexcept = default; Fiber(Fiber &&other) noexcept = default;
Fiber &operator=(Fiber &&other) noexcept = default; Fiber &operator=(Fiber &&other) noexcept = default;
// for `Scheduler`
void Resume();
void Yield();
private: private:
TILE_FRIEND_TEST(Fiber, Base); TILE_FRIEND_TEST(Fiber, Base);
friend void RunProc(void *);
friend void RunProc1(struct fcontext_transfer);
friend Scheduler; friend Scheduler;
struct FiberContext; struct FiberContext;
friend class ::tile::PoolTraits<FiberContext>; friend class ::tile::PoolTraits<FiberContext>;
Fiber(std::function<void()> proc = nullptr); Fiber(std::function<void()> proc = nullptr);
void Resume();
private: private:
std::unique_ptr<FiberContext> ctx_; std::unique_ptr<FiberContext> ctx_;
std::function<void()> proc_;
FiberState state_{Ready}; FiberState state_{Ready};
}; };

View File

@ -13,27 +13,19 @@ TEST(Fiber, Base) {
// 0 -> master fiber // 0 -> master fiber
// [1, 9] -> worker fibers // [1, 9] -> worker fibers
std::vector<std::unique_ptr<Fiber>> fibers;
fibers.emplace_back(Fiber::Create()); auto master_fiber = Fiber::Create();
Fiber::SetMasterFiber(fibers[0].get()); Fiber::SetMasterFiber(master_fiber.get());
Fiber::SetCurrent(fibers[0].get()); Fiber::SetCurrent(master_fiber.get());
for (int i = 1; i != 10; ++i) {
fibers.emplace_back(Fiber::Create([&, i] {
while (cnt < kMaxCnt) { while (cnt < kMaxCnt) {
ASSERT_EQ(Fiber::Current(), fibers[i].get()); std::unique_ptr<Fiber> worker_fiber = Fiber::Create([&] {
ASSERT_EQ(Fiber::Current(), worker_fiber.get());
++cnt; ++cnt;
Fiber::MasterFiber()->Resume(); });
}
}));
}
while (cnt < kMaxCnt) {
int old = cnt; int old = cnt;
auto next_fiber = fibers[Random(1, 9)].get(); worker_fiber->Resume();
next_fiber->Resume();
++resume_cnt; ++resume_cnt;
ASSERT_EQ(old + 1, cnt); ASSERT_EQ(old + 1, cnt);
ASSERT_EQ(Fiber::Current(), Fiber::MasterFiber()); ASSERT_EQ(Fiber::Current(), Fiber::MasterFiber());