AWAITING, /**< Is currently blocked */
AWAITING_IMMEDIATE, /**< Was preempted to run an immediate function,
and will be resumed right away */
+ YIELDED, /**< The fiber yielded execution voluntarily */
};
State state_{INVALID}; /**< current Fiber state */
assert(fibersAllocated_ > 0);
--fibersAllocated_;
}
+ } else if (fiber->state_ == Fiber::YIELDED) {
+ fiber->state_ = Fiber::READY_TO_RUN;
+ yieldedFibers_.push_back(*fiber);
}
currentFiber_ = nullptr;
}
);
}
+ if (!yieldedFibers_.empty()) {
+ readyFibers_.splice(readyFibers_.end(), yieldedFibers_);
+ ensureLoopScheduled();
+ }
+
return fibersActive_ > 0;
}
return activeFiber_ != nullptr;
}
+inline void FiberManager::yield() {
+ assert(currentFiberManager_ == this);
+ assert(activeFiber_ != nullptr);
+ assert(activeFiber_->state_ == Fiber::RUNNING);
+ activeFiber_->preempt(Fiber::YIELDED);
+}
+
template <typename T>
T& FiberManager::local() {
if (std::type_index(typeid(T)) == localType_ && currentFiber_) {
#include <functional>
#include <memory>
#include <queue>
+#include <thread>
#include <typeindex>
#include <unordered_set>
#include <vector>
*/
size_t stackHighWatermark() const;
+ /**
+ * Yield execution of the currently running fiber. Must only be called from a
+ * fiber executing on this FiberManager. The calling fiber will be scheduled
+ * when all other fibers have had a chance to run and the event loop is
+ * serviced.
+ */
+ void yield();
+
static FiberManager& getFiberManager();
static FiberManager* getFiberManagerUnsafe();
Fiber* currentFiber_{nullptr};
FiberTailQueue readyFibers_; /**< queue of fibers ready to be executed */
+ FiberTailQueue yieldedFibers_; /**< queue of fibers which have yielded
+ execution */
FiberTailQueue fibersPool_; /**< pool of unitialized Fiber objects */
size_t fibersAllocated_{0}; /**< total number of fibers allocated */
return FiberManager::localThread<T>();
}
+inline void yield() {
+ auto fm = FiberManager::getFiberManagerUnsafe();
+ if (fm) {
+ fm->yield();
+ } else {
+ std::this_thread::yield();
+ }
+}
+
}}
#include "FiberManager-inl.h"