feat/support_fiber #2
@ -43,7 +43,7 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++")
|
||||
# set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static-libstdc++")
|
||||
|
||||
set(STATIC_BINARY_FLAGS "-static-libgcc -static-libstdc++")
|
||||
set(STATIC_BINARY_FLAGS "-static-libgcc -static-libstdc++")
|
||||
set(WHOLE_ARCHIVE_PREFIX "-Wl,--whole-archive")
|
||||
set(WHOLE_ARCHIVE_SUFFIX "-Wl,--no-whole-archive")
|
||||
endif()
|
||||
@ -62,7 +62,9 @@ get_git_commit_hash(GIT_COMMIT_HASH)
|
||||
get_git_commit_date(GIT_COMMIT_DATE)
|
||||
get_git_commit_subject(GIT_COMMIT_SUBJECT)
|
||||
|
||||
set(THIRD_PARTY_INCLUDE_DIRS "third_party/json" "third_party/inja" "third_party/sigslot" "${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include")
|
||||
set(THIRD_PARTY_INCLUDE_DIRS
|
||||
"third_party/json" "third_party/inja" "third_party/sigslot"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include")
|
||||
include_directories(${THIRD_PARTY_INCLUDE_DIRS})
|
||||
add_subdirectory("third_party/zlib")
|
||||
add_subdirectory("third_party/fmt")
|
||||
@ -74,7 +76,9 @@ add_subdirectory("third_party/glog")
|
||||
add_subdirectory("third_party/context")
|
||||
|
||||
set(CURL_DISABLE_TESTS ON)
|
||||
set(CURL_CA_PATH "none" CACHE STRING "" FORCE)
|
||||
set(CURL_CA_PATH
|
||||
"none"
|
||||
CACHE STRING "" FORCE)
|
||||
set(CURL_ENABLE_SSL
|
||||
OFF
|
||||
CACHE BOOL "" FORCE)
|
||||
@ -260,8 +264,6 @@ if(TILE_BUILD_TESTS)
|
||||
target_sources(${PROJECT_NAME}_test_all PRIVATE ${test_file})
|
||||
endmacro()
|
||||
|
||||
tile_add_test(fiber_detail_fiber_test "tile/fiber/detail/fiber_test.cc")
|
||||
|
||||
tile_add_test(base_internal_meta_test "tile/base/internal/meta_test.cc")
|
||||
# tile_add_test(net_internal_http_engine_test
|
||||
# "tile/net/internal/http_engine_test.cc")
|
||||
@ -349,8 +351,6 @@ if(TILE_BUILD_BENCHMARKS)
|
||||
target_sources(tile_bm_all PRIVATE ${benchmark_file})
|
||||
endmacro()
|
||||
|
||||
tile_add_bm(fiber_detail_fiber_benchmark
|
||||
"tile/fiber/detail/fiber_benchmark.cc")
|
||||
tile_add_bm(base_casting_benchmark "tile/base/casting_benchmark.cc")
|
||||
tile_add_bm(base_thread_mutex_benchmark "tile/base/thread/mutex_benchmark.cc")
|
||||
tile_add_bm(base_encoding_benchmark "tile/base/encoding_benchmark.cc")
|
||||
|
@ -24,21 +24,22 @@ struct alignas(hardware_destructive_interference_size) Fiber::FiberContext {
|
||||
};
|
||||
|
||||
void FiberEntry(fcontext_transfer_t t) {
|
||||
|
||||
std::function<void()> *fn = static_cast<std::function<void()> *>(t.data);
|
||||
TILE_CHECK_NE(t.data, nullptr);
|
||||
TILE_CHECK_NE(t.fctx, nullptr);
|
||||
Fiber *self = nullptr;
|
||||
|
||||
try {
|
||||
// From Resume()
|
||||
t = jump_fcontext(t.fctx, nullptr);
|
||||
auto self = reinterpret_cast<Fiber *>(t.data);
|
||||
self = reinterpret_cast<Fiber *>(t.data);
|
||||
self->caller_->ctx_ = t.fctx;
|
||||
|
||||
(*fn)();
|
||||
} catch (const std::exception &e) {
|
||||
TILE_LOG_ERROR("Exception caught in fiber: {}", e.what());
|
||||
}
|
||||
self->state_ = FiberState::Terminated;
|
||||
|
||||
if (GetMasterFiber() != GetCurrentFiber()) {
|
||||
GetMasterFiber()->Resume();
|
||||
@ -66,7 +67,6 @@ void SetUpMasterFiber(Fiber *fiber) noexcept { tls_master_fiber = fiber; }
|
||||
|
||||
std::unique_ptr<Fiber> Fiber::Create(std::function<void()> proc) noexcept {
|
||||
return std::unique_ptr<Fiber>(new Fiber(std::move(proc)));
|
||||
// return make_unique<Fiber>(std::move(proc));
|
||||
}
|
||||
|
||||
Fiber::Fiber(std::function<void()> proc)
|
||||
|
@ -27,8 +27,12 @@ enum class FiberState {
|
||||
Terminated,
|
||||
};
|
||||
|
||||
class Scheduler;
|
||||
|
||||
class alignas(hardware_destructive_interference_size) Fiber {
|
||||
public:
|
||||
using Id = std::uint64_t;
|
||||
|
||||
static std::unique_ptr<Fiber>
|
||||
Create(std::function<void()> proc = nullptr) noexcept;
|
||||
|
||||
@ -43,6 +47,8 @@ public:
|
||||
void ResumeOn(std::function<void()> &&cb) noexcept;
|
||||
void Yield();
|
||||
|
||||
Scheduler *scheduler() const { return scheduler_; }
|
||||
|
||||
private:
|
||||
TILE_FRIEND_TEST(Fiber, Base);
|
||||
friend Scheduler;
|
||||
@ -59,6 +65,7 @@ private:
|
||||
FiberState state_{FiberState::Runnable};
|
||||
void *ctx_{nullptr};
|
||||
Fiber *caller_{nullptr};
|
||||
Scheduler *scheduler_{nullptr};
|
||||
};
|
||||
Fiber *GetCurrentFiber() noexcept;
|
||||
Fiber *GetMasterFiber() noexcept;
|
||||
|
28
tile/fiber/detail/scheduler.cc
Normal file
28
tile/fiber/detail/scheduler.cc
Normal file
@ -0,0 +1,28 @@
|
||||
#include "tile/fiber/detail/scheduler.h"
|
||||
|
||||
namespace tile {
|
||||
namespace fiber {
|
||||
namespace detail {
|
||||
static thread_local Scheduler *current_scheduler = nullptr;
|
||||
|
||||
void Scheduler::SwitchTo(Fiber *self, Fiber *to) {
|
||||
TILE_CHECK_EQ(self, GetCurrentFiber());
|
||||
|
||||
TILE_CHECK(to->state_ == FiberState::Runnable,
|
||||
"Fiber `to` is not in Runnable.");
|
||||
TILE_CHECK_NE(self, to, "Switch to yourself result in U.B.");
|
||||
|
||||
to->Resume();
|
||||
|
||||
TILE_CHECK_EQ(self, GetCurrentFiber());
|
||||
}
|
||||
|
||||
void Scheduler::Yield(Fiber *self) {
|
||||
auto master = GetMasterFiber();
|
||||
|
||||
master->state_ = FiberState::Runnable;
|
||||
SwitchTo(self, master);
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace fiber
|
||||
} // namespace tile
|
@ -11,6 +11,8 @@ namespace detail {
|
||||
|
||||
class Scheduler {
|
||||
public:
|
||||
static Scheduler *Current() noexcept;
|
||||
|
||||
void SwitchTo(Fiber *self, Fiber *to);
|
||||
void Yield(Fiber *self);
|
||||
};
|
||||
|
23
tile/fiber/this_fiber.cc
Normal file
23
tile/fiber/this_fiber.cc
Normal file
@ -0,0 +1,23 @@
|
||||
#include "tile/fiber/this_fiber.h"
|
||||
|
||||
namespace tile {
|
||||
namespace this_fiber {
|
||||
|
||||
void Yield() {
|
||||
auto self = fiber::detail::GetCurrentFiber();
|
||||
TILE_CHECK(self, "Yield() should be called in a fiber.");
|
||||
self->scheduler()->Yield(self);
|
||||
}
|
||||
|
||||
void SleepUntil(std::chrono::steady_clock::time_point expires_at) {}
|
||||
|
||||
void SleepFor(std::chrono::nanoseconds expires_in) {
|
||||
SleepUntil(ReadSteadyClock() + expires_in);
|
||||
}
|
||||
|
||||
Fiber::Id GetId() {
|
||||
auto self = fiber::detail::GetCurrentFiber();
|
||||
TILE_CHECK(self, "GetId() should be called in a fiber.");
|
||||
}
|
||||
} // namespace this_fiber
|
||||
} // namespace tile
|
29
tile/fiber/this_fiber.h
Normal file
29
tile/fiber/this_fiber.h
Normal file
@ -0,0 +1,29 @@
|
||||
#include "tile/fiber/detail/fiber.h"
|
||||
#include "tile/fiber/detail/scheduler.h"
|
||||
|
||||
#include "tile/base/chrono.h"
|
||||
|
||||
namespace tile {
|
||||
namespace this_fiber {
|
||||
|
||||
using Fiber = fiber::detail::Fiber;
|
||||
|
||||
void Yield();
|
||||
|
||||
void SleepUntil(std::chrono::steady_clock::time_point expires_at);
|
||||
void SleepFor(std::chrono::nanoseconds expires_in);
|
||||
|
||||
template <typename Clock, typename Duration>
|
||||
void SleepFor(std::chrono::time_point<Clock, Duration> expires_at) {
|
||||
SleepUntil(ReadSteadyClock() + (expires_at - Clock::now()));
|
||||
}
|
||||
|
||||
template <typename Rep, typename Period>
|
||||
void SleepFor(std::chrono::duration<Rep, Period> expires_in) {
|
||||
return SleepFor(static_cast<std::chrono::nanoseconds>(expires_in));
|
||||
}
|
||||
|
||||
Fiber::Id GetId();
|
||||
|
||||
} // namespace this_fiber
|
||||
} // namespace tile
|
Loading…
x
Reference in New Issue
Block a user