/*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-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.
fm.activeFiber_->preempt(Fiber::AWAITING);
}
-template <typename F>
-bool Baton::timed_wait(
- TimeoutController::Duration timeout,
+template <typename Rep, typename Period, typename F>
+bool Baton::try_wait_for(
+ const std::chrono::duration<Rep, Period>& timeout,
F&& mainContextFunc) {
auto fm = FiberManager::getFiberManagerUnsafe();
auto id =
fm->timeoutManager_->registerTimeout(std::ref(timeoutFunc), timeout);
- waitFiber(*fm, std::move(mainContextFunc));
+ waitFiber(*fm, static_cast<F&&>(mainContextFunc));
auto posted = waitingFiber_ == POSTED;
return posted;
}
-template <typename C, typename D>
-bool Baton::timed_wait(const std::chrono::time_point<C, D>& timeout) {
- auto now = C::now();
+template <typename Clock, typename Duration, typename F>
+bool Baton::try_wait_until(
+ const std::chrono::time_point<Clock, Duration>& deadline,
+ F&& mainContextFunc) {
+ auto now = Clock::now();
- if (LIKELY(now <= timeout)) {
- return timed_wait(
- std::chrono::duration_cast<std::chrono::milliseconds>(timeout - now));
+ if (LIKELY(now <= deadline)) {
+ return try_wait_for(deadline - now, static_cast<F&&>(mainContextFunc));
} else {
- return timed_wait(TimeoutController::Duration(0));
+ return try_wait_for(Duration{}, static_cast<F&&>(mainContextFunc));
}
}
} // namespace fibers
/*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-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.
timeoutHandler.cancelTimeout();
}
-bool Baton::timed_wait(TimeoutController::Duration timeout) {
- return timed_wait(timeout, []() {});
-}
-
void Baton::waitThread() {
if (spinWaitForEarlyPost()) {
assert(waitingFiber_.load(std::memory_order_acquire) == POSTED);
/*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-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.
void wait(F&& mainContextFunc);
/**
- * This is here only not break tao/locks. Please don't use it, because it is
- * inefficient when used on Fibers.
+ * Checks if the baton has been posted without blocking.
+ *
+ * @return true iff the baton has been posted.
*/
- template <typename C, typename D = typename C::duration>
- bool timed_wait(const std::chrono::time_point<C, D>& timeout);
+ bool try_wait();
/**
- * Puts active fiber to sleep. Returns when post is called.
+ * Puts active fiber to sleep. Returns when post is called or the timeout
+ * expires.
*
- * @param timeout Baton will be automatically awaken if timeout is hit
+ * @param timeout Baton will be automatically awaken if timeout expires
*
* @return true if was posted, false if timeout expired
*/
- bool timed_wait(TimeoutController::Duration timeout);
+ template <typename Rep, typename Period>
+ bool try_wait_for(const std::chrono::duration<Rep, Period>& timeout) {
+ return try_wait_for(timeout, [] {});
+ }
/**
- * Puts active fiber to sleep. Returns when post is called.
+ * Puts active fiber to sleep. Returns when post is called or the timeout
+ * expires.
*
- * @param timeout Baton will be automatically awaken if timeout is hit
+ * @param timeout Baton will be automatically awaken if timeout expires
* @param mainContextFunc this function is immediately executed on the main
* context.
*
* @return true if was posted, false if timeout expired
*/
- template <typename F>
- bool timed_wait(TimeoutController::Duration timeout, F&& mainContextFunc);
+ template <typename Rep, typename Period, typename F>
+ bool try_wait_for(
+ const std::chrono::duration<Rep, Period>& timeout,
+ F&& mainContextFunc);
/**
- * Checks if the baton has been posted without blocking.
- * @return true iff the baton has been posted.
+ * Puts active fiber to sleep. Returns when post is called or the deadline
+ * expires.
+ *
+ * @param timeout Baton will be automatically awaken if deadline expires
+ *
+ * @return true if was posted, false if timeout expired
*/
- bool try_wait();
+ template <typename Clock, typename Duration>
+ bool try_wait_until(
+ const std::chrono::time_point<Clock, Duration>& deadline) {
+ return try_wait_until(deadline, [] {});
+ }
+
+ /**
+ * Puts active fiber to sleep. Returns when post is called or the deadline
+ * expires.
+ *
+ * @param timeout Baton will be automatically awaken if deadline expires
+ * @param mainContextFunc this function is immediately executed on the main
+ * context.
+ *
+ * @return true if was posted, false if timeout expired
+ */
+ template <typename Clock, typename Duration, typename F>
+ bool try_wait_until(
+ const std::chrono::time_point<Clock, Duration>& deadline,
+ F&& mainContextFunc);
+
+ /**
+ * Puts active fiber to sleep. Returns when post is called or the deadline
+ * expires.
+ *
+ * @param timeout Baton will be automatically awaken if deadline expires
+ * @param mainContextFunc this function is immediately executed on the main
+ * context.
+ *
+ * @return true if was posted, false if timeout expired
+ */
+ template <typename Clock, typename Duration, typename F>
+ bool try_wait_for(
+ const std::chrono::time_point<Clock, Duration>& deadline,
+ F&& mainContextFunc);
+
+ /// Alias to try_wait_for. Deprecated.
+ template <typename Rep, typename Period>
+ bool timed_wait(const std::chrono::duration<Rep, Period>& timeout) {
+ return try_wait_for(timeout);
+ }
+
+ /// Alias to try_wait_for. Deprecated.
+ template <typename Rep, typename Period, typename F>
+ bool timed_wait(
+ const std::chrono::duration<Rep, Period>& timeout,
+ F&& mainContextFunc) {
+ return try_wait_for(timeout, static_cast<F&&>(mainContextFunc));
+ }
+
+ /// Alias to try_wait_until. Deprecated.
+ template <typename Clock, typename Duration>
+ bool timed_wait(const std::chrono::time_point<Clock, Duration>& deadline) {
+ return try_wait_until(deadline);
+ }
+
+ /// Alias to try_wait_until. Deprecated.
+ template <typename Clock, typename Duration, typename F>
+ bool timed_wait(
+ const std::chrono::time_point<Clock, Duration>& deadline,
+ F&& mainContextFunc) {
+ return try_wait_until(deadline, static_cast<F&&>(mainContextFunc));
+ }
/**
* Wakes up Fiber which was waiting on this Baton (or if no Fiber is waiting,
bool TimedMutex::timed_lock(
const std::chrono::duration<Rep, Period>& duration) {
auto result = lockHelper([&](MutexWaiter& waiter) {
- if (!waiter.baton.timed_wait(duration)) {
+ if (!waiter.baton.try_wait_for(duration)) {
// We timed out. Two cases:
// 1. We're still in the waiter list and we truly timed out
// 2. We're not in the waiter list anymore. This could happen if the baton
read_waiters_.push_back(waiter);
ulock.unlock();
- if (!waiter.baton.timed_wait(duration)) {
+ if (!waiter.baton.try_wait_for(duration)) {
// We timed out. Two cases:
// 1. We're still in the waiter list and we truly timed out
// 2. We're not in the waiter list anymore. This could happen if the baton
write_waiters_.push_back(waiter);
ulock.unlock();
- if (!waiter.baton.timed_wait(duration)) {
+ if (!waiter.baton.try_wait_for(duration)) {
// We timed out. Two cases:
// 1. We're still in the waiter list and we truly timed out
// 2. We're not in the waiter list anymore. This could happen if the baton
/*
- * Copyright 2017 Facebook, Inc.
+ * Copyright 2017-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.
manager.addTask([&]() {
Baton baton;
- auto res = baton.timed_wait(std::chrono::milliseconds(230));
+ auto res = baton.try_wait_for(std::chrono::milliseconds(230));
EXPECT_FALSE(res);
EXPECT_EQ(5, iterations);
manager.addTask([&]() {
Baton baton;
- auto res = baton.timed_wait(std::chrono::milliseconds(130));
+ auto res = baton.try_wait_for(std::chrono::milliseconds(130));
EXPECT_FALSE(res);
EXPECT_EQ(3, iterations);
Baton baton;
baton_ptr = &baton;
- auto res = baton.timed_wait(std::chrono::milliseconds(130));
+ auto res = baton.try_wait_for(std::chrono::milliseconds(130));
EXPECT_TRUE(res);
EXPECT_EQ(2, iterations);
Baton baton;
auto start = EventBaseLoopController::Clock::now();
- auto res = baton.timed_wait(std::chrono::milliseconds(timeout_ms));
+ auto res = baton.try_wait_for(std::chrono::milliseconds(timeout_ms));
auto finish = EventBaseLoopController::Clock::now();
EXPECT_FALSE(res);
evb.tryRunAfterDelay([&]() { baton.post(); }, 100);
auto start = EventBaseLoopController::Clock::now();
- auto res = baton.timed_wait(std::chrono::milliseconds(130));
+ auto res = baton.try_wait_for(std::chrono::milliseconds(130));
auto finish = EventBaseLoopController::Clock::now();
EXPECT_TRUE(res);
getFiberManager(*evb1).addTaskRemote([&] {
Baton baton;
- baton.timed_wait(std::chrono::milliseconds{100});
+ baton.try_wait_for(std::chrono::milliseconds{100});
done1 = true;
});
getFiberManager(evb2).addTaskRemote([&] {
Baton baton;
- baton.timed_wait(std::chrono::milliseconds{200});
+ baton.try_wait_for(std::chrono::milliseconds{200});
done2 = true;
});
mutex.unlock();
{
Baton b;
- b.timed_wait(std::chrono::milliseconds(1));
+ b.try_wait_for(std::chrono::milliseconds(1));
}
}
});
mutex.lock();
{
Baton b;
- b.timed_wait(std::chrono::milliseconds(1));
+ b.try_wait_for(std::chrono::milliseconds(1));
}
mutex.unlock();
{
Baton b;
- b.timed_wait(std::chrono::milliseconds(1));
+ b.try_wait_for(std::chrono::milliseconds(1));
}
}
});