• Matthieu Martin's avatar
    Allow python asyncio Future to wrap folly Fibers · ced29774
    Matthieu Martin authored
    Summary:
    This implements a new AsyncioLoopController for FiberManager, wrapping AsyncioExecutor.
    Thanks to recent simplication of LoopController, if I haven't missed anything, code is fairly simple, though not optimizer for thread-local.
    
    fiber_manager.pxd|pyx allow to link the life-time of AsyncioLoopController/FiberManager to the asyncio event loop.
    Code is similar to (and rely on) executor.pxd|pyd, which does the same for AsyncioExecutor.
    
    fibers.h|pxd provide a helper function for C++/python callers.
    Code is similar to futures.h|pyd, which does the same for folly Future.
    This is the main reason to keep a separate function/callback parameters. Not necessary for fibers, but a generic callback implementation can work for both fibers/future, which is convenient.
    
    There are a few lines that feel duplicated between future/fibers implementation, but it felt overkill to abstract further.
    
    Reviewed By: andriigrynenko
    
    Differential Revision: D7811432
    
    fbshipit-source-id: af0a07d7554acbab1fac44b7a9a6a98340501ef4
    ced29774
AsyncioLoopController-inl.h 1.55 KB
/*
 * Copyright 2018-present Facebook, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

namespace folly {
namespace python {

inline AsyncioLoopController::AsyncioLoopController(AsyncioExecutor* executor)
    : executor_(executor) {}

inline AsyncioLoopController::~AsyncioLoopController() {}

inline void AsyncioLoopController::setFiberManager(fibers::FiberManager* fm) {
  fm_ = fm;
}

inline void AsyncioLoopController::schedule() {
  // add() is thread-safe, so this isn't properly optimized for addTask()
  executor_->add([this]() { return runLoop(); });
}

inline void AsyncioLoopController::runLoop() {
  if (fm_->hasTasks()) {
    fm_->loopUntilNoReadyImpl();
  }
}

inline void AsyncioLoopController::scheduleThreadSafe() {
  executor_->add([this]() {
    if (fm_->shouldRunLoopRemote()) {
      return runLoop();
    }
  });
}

inline void AsyncioLoopController::timedSchedule(
    std::function<void()>,
    TimePoint) {
  throw std::logic_error("Time schedule isn't supported by asyncio executor");
}

} // namespace python
} // namespace folly