Commit 1185bdd6 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Move co_reschedule_on_current_executor

Summary:
[Folly] Move `co_reschedule_on_current_executor`, placing it alongside `co_current_executor`.

(Note: this ignores all push blocking failures!)

Reviewed By: lewissbaker

Differential Revision: D15227871

fbshipit-source-id: 72c125ad792ebde6bb74e288b3404116cd279cb4
parent 8011691a
......@@ -15,6 +15,12 @@
*/
#pragma once
#include <utility>
#include <folly/Executor.h>
#include <folly/experimental/coro/ViaIfAsync.h>
#include <folly/io/async/Request.h>
namespace folly {
namespace coro {
......@@ -43,5 +49,62 @@ using co_current_executor_t = detail::co_current_executor_;
constexpr co_current_executor_t co_current_executor{
co_current_executor_t::secret_::token_};
namespace detail {
class co_reschedule_on_current_executor_ {
class Awaiter {
folly::Executor::KeepAlive<> executor_;
public:
explicit Awaiter(folly::Executor::KeepAlive<> executor) noexcept
: executor_(std::move(executor)) {}
bool await_ready() {
return false;
}
FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES void await_suspend(
std::experimental::coroutine_handle<> coro) {
executor_->add([coro, ctx = RequestContext::saveContext()]() mutable {
RequestContextScopeGuard contextScope{std::move(ctx)};
coro.resume();
});
}
void await_resume() {}
};
friend Awaiter co_viaIfAsync(
folly::Executor::KeepAlive<> executor,
co_reschedule_on_current_executor_) {
return Awaiter{std::move(executor)};
}
};
} // namespace detail
using co_reschedule_on_current_executor_t =
detail::co_reschedule_on_current_executor_;
// A SemiAwaitable object that allows you to reschedule the current coroutine
// onto the currently associated executor.
//
// This can be used as a form of cooperative multi-tasking for coroutines that
// wish to provide fair access to the execution resources. eg. to periodically
// give up their current execution slot to allow other tasks to run.
//
// Example:
// folly::coro::Task<void> doCpuIntensiveWorkFairly() {
// for (int i = 0; i < 1'000'000; ++i) {
// // Periodically reschedule to the executor.
// if ((i % 1024) == 1023) {
// co_await folly::coro::co_reschedule_on_current_executor;
// }
// doSomeWork(i);
// }
// }
inline constexpr co_reschedule_on_current_executor_t
co_reschedule_on_current_executor;
} // namespace coro
} // namespace folly
/*
* Copyright 2019-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
#include <folly/Executor.h>
#include <folly/io/async/Request.h>
#include <experimental/coroutine>
namespace folly {
namespace coro {
namespace detail {
class co_reschedule_on_current_executor_t {
class Awaiter {
folly::Executor::KeepAlive<> executor_;
public:
explicit Awaiter(folly::Executor::KeepAlive<> executor) noexcept
: executor_(std::move(executor)) {}
bool await_ready() {
return false;
}
FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES void await_suspend(
std::experimental::coroutine_handle<> coro) {
executor_->add([coro, ctx = RequestContext::saveContext()]() mutable {
RequestContextScopeGuard contextScope{std::move(ctx)};
coro.resume();
});
}
void await_resume() {}
};
friend Awaiter co_viaIfAsync(
folly::Executor::KeepAlive<> executor,
co_reschedule_on_current_executor_t) {
return Awaiter{std::move(executor)};
}
};
} // namespace detail
// A SemiAwaitable object that allows you to reschedule the current coroutine
// onto the currently associated executor.
//
// This can be used as a form of cooperative multi-tasking for coroutines that
// wish to provide fair access to the execution resources. eg. to periodically
// give up their current execution slot to allow other tasks to run.
//
// Example:
// folly::coro::Task<void> doCpuIntensiveWorkFairly() {
// for (int i = 0; i < 1'000'000; ++i) {
// // Periodically reschedule to the executor.
// if ((i % 1024) == 1023) {
// co_await folly::coro::co_reschedule_on_current_executor;
// }
// doSomeWork(i);
// }
// }
inline constexpr detail::co_reschedule_on_current_executor_t
co_reschedule_on_current_executor;
} // namespace coro
} // namespace folly
......@@ -23,9 +23,9 @@
#include <folly/experimental/coro/Baton.h>
#include <folly/experimental/coro/BlockingWait.h>
#include <folly/experimental/coro/Collect.h>
#include <folly/experimental/coro/CurrentExecutor.h>
#include <folly/experimental/coro/Generator.h>
#include <folly/experimental/coro/Mutex.h>
#include <folly/experimental/coro/Schedule.h>
#include <folly/experimental/coro/Task.h>
#include <folly/portability/GTest.h>
......
......@@ -20,7 +20,7 @@
#include <folly/experimental/coro/BlockingWait.h>
#include <folly/experimental/coro/Collect.h>
#include <folly/experimental/coro/Schedule.h>
#include <folly/experimental/coro/CurrentExecutor.h>
#include <folly/experimental/coro/Task.h>
#include <folly/portability/GTest.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment