@@ -37,6 +37,7 @@ namespace FIREBASE_NAMESPACE {
3737// / @cond FIREBASE_APP_INTERNAL
3838namespace detail {
3939class 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