Skip to content

Commit 9cb83e7

Browse files
Googlera-maurice
authored andcommitted
Automated g4 rollback of changelist 267236680.
*** Reason for rollback *** Roll-forward (i.e. rollback of rollback) after fixing the breakage that caused the initial rollback. This CL has three fixes: (1) It incorporates the fixes by varconst@ in CL 267229592, which fixed a problem where some of the references to std::function were not inside "#if defined(FIREBASE_USE_STD_FUNCTION)". (2) It deletes an unnecessary (and wrong) friend declaration that was causing an ambiguity error; there's no need to declare the nested class intrusive_list::intrusive_list_iterator as a friend, since the containing class intrusive_list is already a friend, and the nested class has the same access as the containing class. The invalid friend declaration was implicitly declaring a non-nested class of the same name, causing later references to that name to be ambiguous. (3) It adds a missing "const" to the declarations of some copy-constructor and assignment operators (that are only declared, not defined). This CL is best reviewed by ticking the "Diff against rollback base revisions" box in Critique. *** Original change description *** Automated g4 rollback of changelist 267110370. *** Reason for rollback *** Fails to compile on Windows. Can test a fix via: blaze build --config=msvc //firebase/app/client/cpp:app_kokoro *** Original change description *** Add support for multiple completion handlers to Future. This includes support for both adding and removing callbacks, including removing callbacks added as std::function<...>. OnCompletion() does not remove completions added with AddCompletion(). The implementation uses... *** PiperOrigin-RevId: 267398802
1 parent fb7874c commit 9cb83e7

File tree

6 files changed

+1236
-139
lines changed

6 files changed

+1236
-139
lines changed

app/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ set(utility_common_HDRS
220220
src/embedded_file.h
221221
src/function_registry.h
222222
src/future_manager.h
223+
src/intrusive_list.h
223224
src/log.h
224225
src/mutex.h
225226
src/optional.h

app/src/include/firebase/future.h

Lines changed: 160 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ namespace FIREBASE_NAMESPACE {
3737
/// @cond FIREBASE_APP_INTERNAL
3838
namespace detail {
3939
class FutureApiInterface;
40+
class CompletionCallbackHandle;
4041
} // namespace detail
4142
/// @endcond
4243

@@ -84,6 +85,12 @@ class FutureBase {
8485
typedef void (*CompletionCallback)(const FutureBase& result_data,
8586
void* user_data);
8687

88+
#if defined(INTERNAL_EXPERIMENTAL)
89+
/// Handle, representing a completion callback, that can be passed to
90+
/// RemoveOnCompletion.
91+
using CompletionCallbackHandle = detail::CompletionCallbackHandle;
92+
#endif
93+
8794
/// Construct an untyped future.
8895
FutureBase();
8996

@@ -139,34 +146,113 @@ class FutureBase {
139146
/// pending. Cast is required since GetFutureResult() returns void*.
140147
const void* result_void() const;
141148

142-
/// Register a callback that will be called at most once, when the future is
143-
/// completed.
149+
/// Register a single callback that will be called at most once, when the
150+
/// future is completed.
151+
///
152+
/// If you call any OnCompletion() method more than once on the same future,
153+
/// only the most recent callback you registered with OnCompletion() will be
154+
/// called.
155+
#if defined(INTERNAL_EXPERIMENTAL)
156+
/// However completions registered with AddCompletion() will still be
157+
/// called even if there is a subsequent call to OnCompletion().
144158
///
145-
/// If you call any OnCompletion() method more than once, only the most recent
146-
/// callback you registered will be called.
159+
/// When the future completes, first the most recent callback registered with
160+
/// OnCompletion(), if any, will be called; then all callbacks registered with
161+
/// AddCompletion() will be called, in the order that they were registered.
162+
#endif
147163
///
148164
/// When your callback is called, the user_data that you supplied here will be
149165
/// passed back as the second parameter.
150166
///
151167
/// @param[in] callback Function pointer to your callback.
152168
/// @param[in] user_data Optional user data. We will pass this back to your
153169
/// callback.
154-
void OnCompletion(CompletionCallback callback, void* user_data) const;
170+
#if defined(INTERNAL_EXPERIMENTAL)
171+
/// @return A handle that can be passed to RemoveOnCompletion.
172+
CompletionCallbackHandle
173+
#else
174+
void
175+
#endif
176+
OnCompletion(CompletionCallback callback, void* user_data) const;
177+
178+
#if defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
179+
/// Register a single callback that will be called at most once, when the
180+
/// future is completed.
181+
///
182+
/// If you call any OnCompletion() method more than once on the same future,
183+
/// only the most recent callback you registered with OnCompletion() will be
184+
/// called.
185+
#if defined(INTERNAL_EXPERIMENTAL)
186+
/// However completions registered with AddCompletion() will still be
187+
/// called even if there is a subsequent call to OnCompletion().
188+
///
189+
/// When the future completes, first the most recent callback registered with
190+
/// OnCompletion(), if any, will be called; then all callbacks registered with
191+
/// AddCompletion() will be called, in the order that they were registered.
192+
#endif
193+
///
194+
/// @param[in] callback Function or lambda to call.
195+
///
196+
/// @note This method is not available when using STLPort on Android, as
197+
/// `std::function` is not supported on STLPort.
198+
#if defined(INTERNAL_EXPERIMENTAL)
199+
/// @return A handle that can be passed to RemoveOnCompletion.
200+
CompletionCallbackHandle
201+
#else
202+
void
203+
#endif
204+
OnCompletion(std::function<void(const FutureBase&)> callback) const;
205+
#endif // defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
206+
207+
#if defined(INTERNAL_EXPERIMENTAL)
208+
/// Like OnCompletion, but allows adding multiple callbacks.
209+
///
210+
/// If you call AddCompletion() more than once, all of the completions that
211+
/// you register will be called, when the future is completed. However, any
212+
/// callbacks which were subsequently removed by calling RemoveOnCompletion
213+
/// will not be called.
214+
///
215+
/// When the future completes, first the most recent callback registered with
216+
/// OnCompletion(), if any, will be called; then all callbacks registered with
217+
/// AddCompletion() will be called, in the order that they were registered.
218+
///
219+
/// @param[in] callback Function pointer to your callback.
220+
/// @param[in] user_data Optional user data. We will pass this back to your
221+
/// callback.
222+
/// @return A handle that can be passed to RemoveOnCompletion.
223+
CompletionCallbackHandle
224+
AddOnCompletion(CompletionCallback callback, void* user_data) const;
155225

156226
#if defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
157-
/// Register a callback that will be called at most once, when the future is
158-
/// completed.
227+
/// Like OnCompletion, but allows adding multiple callbacks.
159228
///
160-
/// If you call any OnCompletion() method more than once, only the most recent
161-
/// callback you registered will be called.
229+
/// If you call AddCompletion() more than once, all of the completions that
230+
/// you register will be called, when the future is completed. However, any
231+
/// callbacks which were subsequently removed by calling RemoveOnCompletion
232+
/// will not be called.
233+
///
234+
/// When the future completes, first the most recent callback registered with
235+
/// OnCompletion(), if any, will be called; then all callbacks registered with
236+
/// AddCompletion() will be called, in the order that they were registered.
162237
///
163238
/// @param[in] callback Function or lambda to call.
239+
/// @return A handle that can be passed to RemoveOnCompletion.
164240
///
165241
/// @note This method is not available when using STLPort on Android, as
166242
/// `std::function` is not supported on STLPort.
167-
void OnCompletion(std::function<void(const FutureBase&)> callback) const;
243+
CompletionCallbackHandle AddOnCompletion(
244+
std::function<void(const FutureBase&)> callback) const;
245+
168246
#endif // defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
169247

248+
/// Unregisters a callback that was previously registered with
249+
/// AddOnCompletion or OnCompletion.
250+
///
251+
/// @param[in] completion_handle The return value of a previous call to
252+
/// AddOnCompletion or OnCompletion.
253+
void RemoveOnCompletion(CompletionCallbackHandle completion_handle) const;
254+
#endif // defined(INTERNAL_EXPERIMENTAL)
255+
170256
/// Returns true if the two Futures reference the same result.
171257
bool operator==(const FutureBase& rhs) const {
172258
return api_ == rhs.api_ && handle_ == rhs.handle_;
@@ -282,11 +368,11 @@ class Future : public FutureBase {
282368
return static_cast<const ResultType*>(result_void());
283369
}
284370

285-
/// Register a callback that will be called at most once, when the future is
286-
/// completed.
371+
/// Register a single callback that will be called at most once, when the
372+
/// future is completed.
287373
///
288-
/// If you call any OnCompletion() method more than once, only the most recent
289-
/// callback you registered will be called.
374+
/// If you call any OnCompletion() method more than once on the same future,
375+
/// only the most recent callback you registered will be called.
290376
///
291377
/// When your callback is called, the user_data that you supplied here will be
292378
/// passed back as the second parameter.
@@ -298,17 +384,20 @@ class Future : public FutureBase {
298384
/// @note This is the same callback as FutureBase::OnCompletion(), so you
299385
/// can't expect to set both and have both run; again, only the most recently
300386
/// registered one will run.
301-
void OnCompletion(TypedCompletionCallback callback, void* user_data) const {
302-
FutureBase::OnCompletion(reinterpret_cast<CompletionCallback>(callback),
303-
user_data);
304-
}
387+
#if defined(INTERNAL_EXPERIMENTAL)
388+
/// @return A handle that can be passed to RemoveOnCompletion.
389+
inline CompletionCallbackHandle
390+
#else
391+
inline void
392+
#endif
393+
OnCompletion(TypedCompletionCallback callback, void* user_data) const;
305394

306395
#if defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
307-
/// Register a callback that will be called at most once, when the future is
308-
/// completed.
396+
/// Register a single callback that will be called at most once, when the
397+
/// future is completed.
309398
///
310-
/// If you call any OnCompletion() method more than once, only the most recent
311-
/// callback you registered will be called.
399+
/// If you call any OnCompletion() method more than once on the same future,
400+
/// only the most recent callback you registered will be called.
312401
///
313402
/// @param[in] callback Function or lambda to call.
314403
///
@@ -318,12 +407,56 @@ class Future : public FutureBase {
318407
/// @note This is the same callback as FutureBase::OnCompletion(), so you
319408
/// can't expect to set both and have both run; again, only the most recently
320409
/// registered one will run.
321-
void OnCompletion(
322-
std::function<void(const Future<ResultType>&)> callback) const {
323-
FutureBase::OnCompletion(
324-
*reinterpret_cast<std::function<void(const FutureBase&)>*>(&callback));
325-
}
410+
#if defined(INTERNAL_EXPERIMENTAL)
411+
/// @return A handle that can be passed to RemoveOnCompletion.
412+
inline CompletionCallbackHandle
413+
#else
414+
inline void
415+
#endif
416+
OnCompletion(std::function<void(const Future<ResultType>&)> callback) const;
417+
#endif // defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
418+
419+
#if defined(INTERNAL_EXPERIMENTAL)
420+
/// Like OnCompletion, but allows adding multiple callbacks.
421+
///
422+
/// If you call AddCompletion() more than once, all of the completions that
423+
/// you register will be called, when the future is completed. However, any
424+
/// callbacks which were subsequently removed by calling RemoveOnCompletion
425+
/// will not be called.
426+
///
427+
/// When the future completes, first the most recent callback registered with
428+
/// OnCompletion(), if any, will be called; then all callbacks registered with
429+
/// AddCompletion() will be called, in the order that they were registered.
430+
///
431+
/// @param[in] callback Function pointer to your callback.
432+
/// @param[in] user_data Optional user data. We will pass this back to your
433+
/// callback.
434+
/// @return A handle that can be passed to RemoveOnCompletion.
435+
inline CompletionCallbackHandle
436+
AddOnCompletion(TypedCompletionCallback callback, void* user_data) const;
437+
438+
#if defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
439+
/// Like OnCompletion, but allows adding multiple callbacks.
440+
///
441+
/// If you call AddCompletion() more than once, all of the completions that
442+
/// you register will be called, when the future is completed. However, any
443+
/// callbacks which were subsequently removed by calling RemoveOnCompletion
444+
/// will not be called.
445+
///
446+
/// When the future completes, first the most recent callback registered with
447+
/// OnCompletion(), if any, will be called; then all callbacks registered with
448+
/// AddCompletion() will be called, in the order that they were registered.
449+
///
450+
/// @param[in] callback Function or lambda to call.
451+
/// @return A handle that can be passed to RemoveOnCompletion.
452+
///
453+
/// @note This method is not available when using STLPort on Android, as
454+
/// `std::function` is not supported on STLPort.
455+
inline CompletionCallbackHandle
456+
AddOnCompletion(std::function<void(const Future<ResultType>&)> callback)
457+
const;
326458
#endif // defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
459+
#endif // defined(INTERNAL_EXPERIMENTAL)
327460
};
328461

329462
// NOLINTNEXTLINE - allow namespace overridden

0 commit comments

Comments
 (0)