Commit e844b95a authored by Pranav Thulasiram Bhat's avatar Pranav Thulasiram Bhat Committed by Facebook GitHub Bot

Create Async interface for Baton

Summary:
Baton is the primitive that allows fibers to block. The goal of this diff is to provide an `Async` interface to blocking calls that operate on Batons.

Overloading `await` directly was one option, however, there are 3 blocking baton APIs (wait, try_wait_for and try_wait_until). Morover these APIs can accept arguments (something async::await doesn't do so far)

So, this diff adds a bunch of wrappers that return Async<> results that must be 'awaited' on. This keeps static-analysis happy, and performs the onFiber check.

Reviewed By: yfeldblum

Differential Revision: D21667887

fbshipit-source-id: 774c19d223ebb0932c043e4c09635c5e85cc8241
parent e1c7e6ce
/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* 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/fibers/Baton.h>
#include <folly/fibers/async/Async.h>
#include <glog/logging.h>
#include <utility>
namespace folly {
namespace fibers {
namespace async {
template <typename... Args>
Async<void> baton_wait(Baton& baton, Args&&... args) {
// Call into blocking API
baton.wait(std::forward<Args>(args)...);
return {};
}
template <typename... Args>
Async<bool> baton_try_wait_for(Baton& baton, Args&&... args) {
// Call into blocking API
return baton.try_wait_for(std::forward<Args>(args)...);
}
template <typename... Args>
Async<bool> baton_try_wait_until(Baton& baton, Args&&... args) {
// Call into blocking API
return baton.try_wait_until(std::forward<Args>(args)...);
}
} // namespace async
} // namespace fibers
} // namespace folly
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include <folly/fibers/TimedMutex.h> #include <folly/fibers/TimedMutex.h>
#include <folly/fibers/WhenN.h> #include <folly/fibers/WhenN.h>
#include <folly/fibers/async/Async.h> #include <folly/fibers/async/Async.h>
#include <folly/fibers/async/Baton.h>
#include <folly/io/async/ScopedEventBaseThread.h> #include <folly/io/async/ScopedEventBaseThread.h>
#include <folly/portability/GTest.h> #include <folly/portability/GTest.h>
...@@ -2676,3 +2677,35 @@ TEST(FiberManager, asyncAwait) { ...@@ -2676,3 +2677,35 @@ TEST(FiberManager, asyncAwait) {
}) })
.getVia(&evb)); .getVia(&evb));
} }
TEST(FiberManager, asyncBaton) {
folly::EventBase evb;
auto& fm = getFiberManager(evb);
std::chrono::steady_clock::time_point start;
EXPECT_NO_THROW(
fm.addTaskFuture([&]() {
constexpr auto kTimeout = std::chrono::milliseconds(230);
{
Baton baton;
baton.post();
EXPECT_NO_THROW(async::await(async::baton_wait(baton)));
}
{
Baton baton;
start = std::chrono::steady_clock::now();
auto res = async::await(async::baton_try_wait_for(baton, kTimeout));
EXPECT_FALSE(res);
EXPECT_LE(start + kTimeout, std::chrono::steady_clock::now());
}
{
Baton baton;
start = std::chrono::steady_clock::now();
auto res = async::await(
async::baton_try_wait_until(baton, start + kTimeout));
EXPECT_FALSE(res);
EXPECT_LE(start + kTimeout, std::chrono::steady_clock::now());
}
})
.getVia(&evb));
}
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