}
inline void FiberManager::runReadyFiber(Fiber* fiber) {
+ SCOPE_EXIT {
+ assert(currentFiber_ == nullptr);
+ assert(activeFiber_ == nullptr);
+ };
+
assert(fiber->state_ == Fiber::NOT_STARTED ||
fiber->state_ == Fiber::READY_TO_RUN);
currentFiber_ = fiber;
if (fiber->state_ == Fiber::AWAITING) {
awaitFunc_(*fiber);
awaitFunc_ = nullptr;
+ currentFiber_ = nullptr;
} else if (fiber->state_ == Fiber::INVALID) {
assert(fibersActive_ > 0);
--fibersActive_;
}
fiber->finallyFunc_ = nullptr;
}
+ // Make sure LocalData is not accessible from its destructor
+ currentFiber_ = nullptr;
fiber->localData_.reset();
if (fibersPoolSize_ < options_.maxFibersPoolSize) {
--fibersAllocated_;
}
} else if (fiber->state_ == Fiber::YIELDED) {
+ currentFiber_ = nullptr;
fiber->state_ = Fiber::READY_TO_RUN;
yieldedFibers_.push_back(*fiber);
}
- currentFiber_ = nullptr;
}
inline bool FiberManager::loopUntilNoReady() {
testFiberLocal<LargeData>();
}
+TEST(FiberManager, fiberLocalDestructor) {
+ struct CrazyData {
+ size_t data{42};
+
+ ~CrazyData() {
+ if (data == 41) {
+ addTask([]() {
+ EXPECT_EQ(42, local<CrazyData>().data);
+ // Make sure we don't have infinite loop
+ local<CrazyData>().data = 0;
+ });
+ }
+ }
+ };
+
+ FiberManager fm(LocalType<CrazyData>(),
+ folly::make_unique<SimpleLoopController>());
+
+ fm.addTask([]() {
+ local<CrazyData>().data = 41;
+ });
+
+ fm.loopUntilNoReady();
+ EXPECT_FALSE(fm.hasTasks());
+}
+
TEST(FiberManager, yieldTest) {
FiberManager manager(folly::make_unique<SimpleLoopController>());
auto& loopController =