class AtomicLinkedList {
public:
AtomicLinkedList() {}
+ AtomicLinkedList(const AtomicLinkedList&) = delete;
+ AtomicLinkedList& operator=(const AtomicLinkedList&) = delete;
+ AtomicLinkedList(AtomicLinkedList&& other) noexcept {
+ auto tmp = other.head_.load();
+ other.head_ = head_.load();
+ head_ = tmp;
+ }
+ AtomicLinkedList& operator=(AtomicLinkedList&& other) noexcept {
+ auto tmp = other.head_.load();
+ other.head_ = head_.load();
+ head_ = tmp;
+
+ return *this;
+ }
/**
* Note: list must be empty on destruction.
typedef AddTaskHelper<F> Helper;
auto fiber = getFiber();
- if (currentFiber_) {
- fiber->localData_ = currentFiber_->localData_;
- }
+ initLocalData(*fiber);
if (Helper::allocateInBuffer) {
auto funcLoc = static_cast<typename Helper::Func*>(fiber->getUserBuffer());
void FiberManager::addTaskRemote(F&& func) {
auto task = [&]() {
auto currentFm = getFiberManagerUnsafe();
- if (currentFm && currentFm->currentFiber_) {
+ if (currentFm &&
+ currentFm->currentFiber_ &&
+ currentFm->localType_ == localType_) {
return folly::make_unique<RemoteTask>(
std::forward<F>(func),
currentFm->currentFiber_->localData_);
"finally(Try<T>&&): T must be convertible from func()'s return type");
auto fiber = getFiber();
- if (currentFiber_) {
- fiber->localData_ = currentFiber_->localData_;
- }
+ initLocalData(*fiber);
typedef AddTaskFinallyHelper<F,G> Helper;
template <typename T>
T& FiberManager::local() {
- if (currentFiber_) {
+ if (std::type_index(typeid(T)) == localType_ && currentFiber_) {
return currentFiber_->localData_.get<T>();
}
return localThread<T>();
return t;
}
+inline void FiberManager::initLocalData(Fiber& fiber) {
+ auto fm = getFiberManagerUnsafe();
+ if (fm && fm->currentFiber_ && fm->localType_ == localType_) {
+ fiber.localData_ = fm->currentFiber_->localData_;
+ }
+}
+
+template <typename LocalT>
+FiberManager FiberManager::create(
+ std::unique_ptr<LoopController> loopController,
+ Options options) {
+ FiberManager fm(std::move(loopController), std::move(options));
+ fm.localType_ = typeid(LocalT);
+ return fm;
+}
+
template <typename F>
typename FirstArgOf<F>::type::value_type
inline await(F&& func) {
throw;
}
}),
- timeoutManager_(std::make_shared<TimeoutController>(*loopController_)) {
+ timeoutManager_(std::make_shared<TimeoutController>(*loopController_)),
+ localType_(typeid(void)) {
loopController_->setFiberManager(this);
}
#include <functional>
#include <memory>
#include <queue>
+#include <typeindex>
#include <unordered_set>
#include <vector>
typedef std::function<void(std::exception_ptr, std::string)>
ExceptionCallback;
+ FiberManager(const FiberManager&) = delete;
+ FiberManager& operator=(const FiberManager&) = delete;
+ FiberManager(FiberManager&&) = default;
+ FiberManager& operator=(FiberManager&&) = default;
+
/**
* Initializes, but doesn't start FiberManager loop
*
+ * @param loopController
* @param options FiberManager options
*/
explicit FiberManager(std::unique_ptr<LoopController> loopController,
Options options = Options());
+ /**
+ * Initializes, but doesn't start FiberManager loop
+ *
+ * @param loopController
+ * @param options FiberManager options
+ * @tparam LocalT only local of this type may be stored on fibers.
+ * Locals of other types will be considered thread-locals.
+ */
+ template <typename LocalT>
+ static FiberManager create(std::unique_ptr<LoopController> loopController,
+ Options options = Options());
+
+
~FiberManager();
/**
*/
Fiber* getFiber();
+ /**
+ * Sets local data for given fiber if all conditions are met.
+ */
+ void initLocalData(Fiber& fiber);
+
/**
* Function passed to the await call.
*/
std::shared_ptr<TimeoutController> timeoutManager_;
+ /**
+ * Only local of this type will be available for fibers.
+ */
+ std::type_index localType_;
+
void runReadyFiber(Fiber* fiber);
void remoteReadyInsert(Fiber* fiber);
};
template <typename Data>
void testFiberLocal() {
- FiberManager fm(folly::make_unique<SimpleLoopController>());
+ auto fm =
+ FiberManager::create<Data>(folly::make_unique<SimpleLoopController>());
fm.addTask([]() {
EXPECT_EQ(42, local<Data>().value);