Exemplo n.º 1
0
bool EventBase::runInEventBaseThread(void (*fn)(void*), void* arg) {
  // Send the message.
  // It will be received by the FunctionRunner in the EventBase's thread.

  // We try not to schedule nullptr callbacks
  if (!fn) {
    LOG(ERROR) << "EventBase " << this
               << ": Scheduling nullptr callbacks is not allowed";
    return false;
  }

  // Short-circuit if we are already in our event base
  if (inRunningEventBaseThread()) {
    runInLoop(new RunInLoopCallback(fn, arg));
    return true;

  }

  try {
    queue_->putMessage(std::make_pair(fn, arg));
  } catch (const std::exception& ex) {
    LOG(ERROR) << "EventBase " << this << ": failed to schedule function "
               << fn << "for EventBase thread: " << ex.what();
    return false;
  }

  return true;
}
Exemplo n.º 2
0
bool EventBase::runInEventBaseThread(const Cob& fn) {
  // Short-circuit if we are already in our event base
  if (inRunningEventBaseThread()) {
    runInLoop(fn);
    return true;
  }

  Cob* fnCopy;
  // Allocate a copy of the function so we can pass it to the other thread
  // The other thread will delete this copy once the function has been run
  try {
    fnCopy = new Cob(fn);
  } catch (const std::bad_alloc& ex) {
    LOG(ERROR) << "failed to allocate tr::function copy "
               << "for runInEventBaseThread()";
    return false;
  }

  if (!runInEventBaseThread(&EventBase::runTr1FunctionPtr, fnCopy)) {
    delete fnCopy;
    return false;
  }

  return true;
}
Exemplo n.º 3
0
bool EventBase::runInEventBaseThreadAndWait(Func fn) {
  if (inRunningEventBaseThread()) {
    LOG(ERROR) << "EventBase " << this << ": Waiting in the event loop is not "
               << "allowed";
    return false;
  }

  Baton<> ready;
  runInEventBaseThread([&ready, fn = std::move(fn)]() mutable {
    SCOPE_EXIT {
      ready.post();
    };
    // A trick to force the stored functor to be executed and then destructed
    // before posting the baton and waking the waiting thread.
    copy(std::move(fn))();
  });
Exemplo n.º 4
0
bool EventBase::runInEventBaseThreadAndWait(const Cob& fn) {
  if (inRunningEventBaseThread()) {
    LOG(ERROR) << "EventBase " << this << ": Waiting in the event loop is not "
               << "allowed";
    return false;
  }

  bool ready = false;
  std::mutex m;
  std::condition_variable cv;
  runInEventBaseThread([&] {
      SCOPE_EXIT {
        std::unique_lock<std::mutex> l(m);
        ready = true;
        l.unlock();
        cv.notify_one();
      };
      fn();
  });
Exemplo n.º 5
0
void EventBase::runInEventBaseThread(Func fn) noexcept {
  // Send the message.
  // It will be received by the FunctionRunner in the EventBase's thread.

  // We try not to schedule nullptr callbacks
  if (!fn) {
    DLOG(FATAL) << "EventBase " << this
                << ": Scheduling nullptr callbacks is not allowed";
    return;
  }

  // Short-circuit if we are already in our event base
  if (inRunningEventBaseThread()) {
    runInLoop(std::move(fn));
    return;
  }

  queue_->putMessage(std::move(fn));
}
Exemplo n.º 6
0
bool EventBase::runInEventBaseThreadAndWait(Func fn) {
    if (inRunningEventBaseThread()) {
        LOG(ERROR) << "EventBase " << this << ": Waiting in the event loop is not "
                   << "allowed";
        return false;
    }

    bool ready = false;
    std::mutex m;
    std::condition_variable cv;
    runInEventBaseThread([&] {
        SCOPE_EXIT {
            std::unique_lock<std::mutex> l(m);
            ready = true;
            cv.notify_one();
            // We cannot release the lock before notify_one, because a spurious
            // wakeup in the waiting thread may lead to cv and m going out of scope
            // prematurely.
        };
        fn();
    });
Exemplo n.º 7
0
void RequestChannel::sendRequestSync(
    RpcOptions& options,
    std::unique_ptr<RequestCallback> cb,
    std::unique_ptr<apache::thrift::ContextStack> ctx,
    std::unique_ptr<folly::IOBuf> buf,
    std::shared_ptr<apache::thrift::transport::THeader> header,
    RpcKind kind) {
  auto eb = getEventBase();
  // We intentionally only support sync_* calls from the EventBase thread.
  eb->checkIsInEventBaseThread();

  folly::fibers::Baton baton;
  auto scb =
      std::make_unique<ClientSyncBatonCallback>(std::move(cb), baton, kind);

  folly::exception_wrapper ew;
  auto const onFiber = folly::fibers::onFiber();
  auto const inEventBase = eb->inRunningEventBaseThread();
  baton.wait([&, onFiber, inEventBase] {
    try {
      switch (kind) {
        case RpcKind::SINGLE_REQUEST_NO_RESPONSE:
          sendOnewayRequest(
              options,
              std::move(scb),
              std::move(ctx),
              std::move(buf),
              std::move(header));
          break;
        case RpcKind::SINGLE_REQUEST_SINGLE_RESPONSE:
          sendRequest(
              options,
              std::move(scb),
              std::move(ctx),
              std::move(buf),
              std::move(header));
          break;
        case RpcKind::SINGLE_REQUEST_STREAMING_RESPONSE:
          sendStreamRequest(
              options,
              std::move(scb),
              std::move(ctx),
              std::move(buf),
              std::move(header));
          break;
        default:
          folly::assume_unreachable();
      }
    } catch (const std::exception& e) {
      ew = folly::exception_wrapper(std::current_exception(), e);
      baton.post();
    } catch (...) {
      ew = folly::exception_wrapper(std::current_exception());
      baton.post();
    }
    if (!onFiber || !inEventBase) {
      while (!baton.ready()) {
        eb->drive();
      }
    }
  });
  if (ew) {
    ew.throw_exception();
  }
}