Skip to content

Commit 8221cd2

Browse files
Googlera-maurice
authored andcommitted
Add blocking methods Wait() and Await() to FutureBase and Future
(respectively). Wait() just blocks until the future is completed, or a timeout expires. Await() blocks until the future is completed, or a timeout expires, and then returns a pointer to the future's result, or nullptr if the timeout expired. PiperOrigin-RevId: 267625598
1 parent b532c15 commit 8221cd2

File tree

4 files changed

+97
-1
lines changed

4 files changed

+97
-1
lines changed

app/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ set(common_SRCS
134134
src/callback.cc
135135
src/cleanup_notifier.cc
136136
src/function_registry.cc
137+
src/future.cc
137138
src/future_manager.cc
138139
src/path.cc
139140
src/reference_counted_future_impl.cc

app/src/future.cc

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright 2019 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "app/src/include/firebase/future.h"
18+
19+
#include "app/src/semaphore.h"
20+
21+
#if !defined(FIREBASE_NAMESPACE)
22+
#define FIREBASE_NAMESPACE firebase
23+
#endif
24+
25+
namespace FIREBASE_NAMESPACE {
26+
27+
namespace {
28+
29+
// Callback function installed by FutureBase::Wait().
30+
// This will be called when the future is complete.
31+
void WaitCallback(const FutureBase &, void *user_data) {
32+
Semaphore *semaphore = static_cast<Semaphore *>(user_data);
33+
// Wake up the thread that called Wait().
34+
semaphore->Post();
35+
}
36+
37+
} // anonymous namespace
38+
39+
const int FutureBase::kWaitTimeoutInfinite = -1;
40+
41+
bool FutureBase::Wait(int timeout_milliseconds) const {
42+
Semaphore semaphore(0);
43+
auto callback_handle = AddOnCompletion(WaitCallback, &semaphore);
44+
if (timeout_milliseconds == kWaitTimeoutInfinite) {
45+
semaphore.Wait();
46+
return true;
47+
} else {
48+
bool completed = semaphore.TimedWait(timeout_milliseconds);
49+
if (!completed) {
50+
RemoveOnCompletion(callback_handle);
51+
}
52+
return completed;
53+
}
54+
}
55+
56+
// NOLINTNEXTLINE - allow namespace overridden
57+
} // namespace FIREBASE_NAMESPACE

app/src/include/firebase/future.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,27 @@ class FutureBase {
146146
/// pending. Cast is required since GetFutureResult() returns void*.
147147
const void* result_void() const;
148148

149+
#if defined(INTERNAL_EXPERIMENTAL)
150+
/// Special timeout value indicating an infinite timeout.
151+
///
152+
/// Passing this value to FutureBase::Wait() or Future<T>::Await() will cause
153+
/// those methods to wait until the future is complete.
154+
///
155+
/// @Warning It is inadvisable to use this from code that could be called
156+
/// from an event loop.
157+
static const int kWaitTimeoutInfinite;
158+
159+
/// Block (i.e. suspend the current thread) until either the future is
160+
/// completed or the specified timeout period (in milliseconds) has elapsed.
161+
/// If `timeout_milliseconds` is `kWaitTimeoutInfinite`, then the timeout
162+
/// period is treated as being infinite, i.e. this will block until the
163+
/// future is completed.
164+
///
165+
/// @return True if the future completed, or
166+
/// false if the timeout period elapsed before the future completed.
167+
bool Wait(int timeout_milliseconds) const;
168+
#endif // defined(INTERNAL_EXPERIMENTAL)
169+
149170
/// Register a single callback that will be called at most once, when the
150171
/// future is completed.
151172
///
@@ -368,6 +389,22 @@ class Future : public FutureBase {
368389
return static_cast<const ResultType*>(result_void());
369390
}
370391

392+
#if defined(INTERNAL_EXPERIMENTAL)
393+
/// Waits (blocks) until either the future is completed, or the specified
394+
/// timeout period (in milliseconds) has elapsed, then returns the result of
395+
/// the asynchronous call.
396+
///
397+
/// This is a convenience method that calls Wait() and then returns result().
398+
///
399+
/// If `timeout_milliseconds` is `kWaitTimeoutInfinite`, then the timeout
400+
/// period is treated as being infinite, i.e. this will block until the
401+
/// future is completed.
402+
const ResultType* Await(int timeout_milliseconds) const {
403+
Wait(timeout_milliseconds);
404+
return result();
405+
}
406+
#endif // defined(INTERNAL_EXPERIMENTAL)
407+
371408
/// Register a single callback that will be called at most once, when the
372409
/// future is completed.
373410
///

app/src/thread_pthread.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,5 @@ void Thread::Detach() {
146146

147147
// NOLINTNEXTLINE - allow namespace overridden
148148
} // namespace FIREBASE_NAMESPACE
149-
#endif
149+
150+
#endif // defined(_STLPORT_VERSION)

0 commit comments

Comments
 (0)