feat/support_fiber #2

Merged
tqcq merged 57 commits from feat/support_fiber into master 2024-06-21 10:33:52 +08:00
7 changed files with 160 additions and 1 deletions
Showing only changes of commit 31ca7c9f6b - Show all commits

View File

@ -21,6 +21,9 @@ option(TILE_WITH_OPENSSL "Build with openssl" OFF)
option(TILE_BUILD_SHARED "Build shared library" ON)
option(TILE_BUILD_STATIC "Build static library" ON)
# set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "time")
# set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "time")
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(TILE_BUILD_TESTS ON)
set(TILE_BUILD_BENCHMARKS ON)
@ -207,6 +210,9 @@ endif()
add_library(tile OBJECT ${TILE_SRCS})
set_target_properties(tile PROPERTIES VERSION ${PROJECT_VERSION}
target_precompile_headers(tile PUBLIC inja/inja.h)
target_precompile_headers(tile PUBLIC inja/string_view.h)
target_precompile_headers(tile PUBLIC json/nlohann/json.hpp)
SOVERSION "${tile_VERSION_MAJRO}")
# target_sources(tile PRIVATE ${TILE_SRCS})
target_include_directories(
@ -358,6 +364,7 @@ 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")

View File

@ -0,0 +1,45 @@
#include "tile/base/random.h"
#include "tile/fiber/detail/fiber.h"
#include "benchmark/benchmark.h"
namespace tile {
namespace fiber {
namespace detail {
void Benchmark_FiberSwitch(benchmark::State &state) {
constexpr int kFiberCount = 10000;
std::unique_ptr<Fiber> master;
std::unique_ptr<Fiber> worker[kFiberCount];
int cnt = 0;
master = Fiber::Create([&]() {
while (state.KeepRunning()) {
++cnt;
worker[Random(kFiberCount - 1)]->Resume();
}
cnt = -1;
for (int i = 0; i != kFiberCount; ++i) {
worker[i]->Resume();
}
});
for (int i = 0; i != kFiberCount; ++i) {
worker[i] = Fiber::Create([&, i]() {
while (cnt != -1) {
master->Resume();
}
});
}
SetUpMasterFiber(master.get());
SetUpCurrentFiber(nullptr);
master->Resume();
}
BENCHMARK(Benchmark_FiberSwitch);
} // namespace detail
} // namespace fiber
} // namespace tile

View File

@ -20,9 +20,25 @@ void Scheduler::SwitchTo(Fiber *self, Fiber *to) {
void Scheduler::Yield(Fiber *self) {
auto master = GetMasterFiber();
TILE_CHECK(self, "self fiber is nullptr.");
TILE_CHECK(master, "Master fiber is not set.");
master->state_ = FiberState::Runnable;
self->state_ = FiberState::Running;
SwitchTo(self, master);
}
void Scheduler::Halt(Fiber *self) {
TILE_CHECK_EQ(self, GetCurrentFiber(), "Fiber is not current fiber.");
TILE_CHECK(self->state() == FiberState::Running, "Fiber is not running.");
auto master = GetMasterFiber();
self->state_ = FiberState::Waiting;
master->Resume();
TILE_CHECK_EQ(self, GetCurrentFiber());
}
} // namespace detail
} // namespace fiber
} // namespace tile

View File

@ -15,6 +15,7 @@ public:
void SwitchTo(Fiber *self, Fiber *to);
void Yield(Fiber *self);
void Halt(Fiber *self);
};
} // namespace detail
} // namespace fiber

View File

@ -11,7 +11,7 @@ namespace detail {
TEST(Fiber, Resume) {
constexpr int kFiberCount = 1000;
constexpr int kSwitchCount = 100000;
constexpr int kSwitchCount = 1000 * 1000;
std::unique_ptr<Fiber> master;
std::unique_ptr<Fiber> worker[kFiberCount];

View File

@ -0,0 +1,42 @@
#include "tile/fiber/detail/waitable.h"
#include "tile/base/thread/scoped_lock.h"
namespace tile {
namespace fiber {
namespace detail {
WaitList::WaitList() {}
WaitList::~WaitList() {}
bool WaitList::AddWaiter(WaitListNode *node) {
ScopedLock _(lock_);
TILE_CHECK(node->waiter);
waiters_.push_back(node);
return true;
}
Fiber *WaitList::WakeOne() {
ScopedLock _(lock_);
while (true) {
if (waiters_.empty()) {
return nullptr;
}
WaitListNode *waiter = waiters_.front();
waiters_.pop_front();
if (!waiter) {
return nullptr;
}
if (waiter->satisfied.exchange(true, std::memory_order_relaxed)) {
continue;
;
}
return waiter->waiter;
}
}
} // namespace detail
} // namespace fiber
} // namespace tile

View File

@ -0,0 +1,48 @@
#ifndef TILE_FIBER_DETAIL_WAITABLE_H
#define TILE_FIBER_DETAIL_WAITABLE_H
#pragma once
#include "tile/base/internal/singly_linked_list.h"
#include "tile/base/thread/spinlock.h"
#include <list>
namespace tile {
namespace fiber {
namespace detail {
class Fiber;
class Scheduler;
struct WaitListNode {
Fiber *waiter = nullptr;
tile::internal::SinglyLinkedListEntry chain;
std::atomic<bool> satisfied{false};
};
class WaitList {
public:
WaitList();
~WaitList();
bool AddWaiter(WaitListNode *node);
// Remove the waiter from the list.
// return true if the waiter is removed, otherwise return nullptr.
Fiber *WakeOne();
WaitList(const WaitList &) = delete;
WaitList &operator=(const WaitList &) = delete;
private:
Spinlock lock_;
std::list<WaitListNode *> waiters_;
// tile::internal::SinglyLinkedList<WaitListNode, &WaitListNode::chain>
// waiters_;
};
} // namespace detail
} // namespace fiber
} // namespace tile
#endif // TILE_FIBER_DETAIL_WAITABLE_H