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")
endif()
add_library(tile OBJECT ${TILE_SRCS} ${ASM_SRCS})
add_library(tile OBJECT ${TILE_SRCS})
set_target_properties(tile PROPERTIES VERSION ${PROJECT_VERSION}
SOVERSION "${tile_VERSION_MAJRO}")
# target_sources(tile PRIVATE ${TILE_SRCS})

View File

@ -10,7 +10,7 @@ cmake_minimum_required(VERSION 3.5...3.16)
project(
nova_context
VERSION 0.1.0
LANGUAGES C)
LANGUAGES C ASM)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
@ -197,6 +197,7 @@ set(ASM_SRC
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
if((NOVA_CONTEXT_ARCHITECTURE STREQUAL ppc32) AND (NOVA_CONTEXT_ABI STREQUAL
sysv))
@ -210,8 +211,8 @@ if(NOVA_CONTEXT_ASSEMBLER STREQUAL masm AND NOVA_CONTEXT_ARCHITECTURE STREQUAL
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL GNU)
set_source_files_properties(${ASM_SRC} PROPERTIES COMPILE_OPTIONS
"-x assembler-with-cpp")
# set_source_files_properties(${ASM_SRC} PROPERTIES COMPILE_OPTIONS
# "-x assembler-with-cpp")
endif()
# Boost specific definitions

View File

@ -57,6 +57,13 @@ auto format_as(const T &val)
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) \
inline std::string format_as(const type &val) { \
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/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

View File

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

View File

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

View File

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