Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 61 additions & 8 deletions app/src/include/firebase/internal/future_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,38 +152,91 @@ class CompletionCallbackHandle {
void (*user_data_delete_fn_)(void*);
};

template <typename T>
struct TypedCompletionCallbackData {
typename Future<T>::TypedCompletionCallback callback;
void* user_data;
};

template <typename T>
inline void TypedCompletionCallbackTrampoline(const FutureBase& future,
void* data_ptr) {
auto* data = static_cast<TypedCompletionCallbackData<T>*>(data_ptr);
if (data != nullptr && data->callback != nullptr) {
data->callback(static_cast<const Future<T>&>(future), data->user_data);
}
}

template <typename T>
inline void DeleteTypedCompletionCallbackData(void* data_ptr) {
delete static_cast<TypedCompletionCallbackData<T>*>(data_ptr);
}

} // namespace detail

template <class T>
void Future<T>::OnCompletion(TypedCompletionCallback callback,
void* user_data) const {
FutureBase::OnCompletion(reinterpret_cast<CompletionCallback>(callback),
user_data);
MutexLock lock(mutex_);
if (api_ != nullptr) {
if (callback == nullptr) {
api_->AddCompletionCallback(
handle_, [](const FutureBase&, void*) {}, nullptr, nullptr,
/*clear_existing_callbacks=*/true);
} else {
auto* data =
new detail::TypedCompletionCallbackData<T>{callback, user_data};
api_->AddCompletionCallback(
handle_, detail::TypedCompletionCallbackTrampoline<T>, data,
detail::DeleteTypedCompletionCallbackData<T>,
/*clear_existing_callbacks=*/true);
}
}
}

#if defined(FIREBASE_USE_STD_FUNCTION)
template <class ResultType>
inline void Future<ResultType>::OnCompletion(
std::function<void(const Future<ResultType>&)> callback) const {
FutureBase::OnCompletion(
*reinterpret_cast<std::function<void(const FutureBase&)>*>(&callback));
if (!callback) {
FutureBase::OnCompletion([](const FutureBase&, void*) {}, nullptr);
} else {
FutureBase::OnCompletion([callback](const FutureBase& future) {
callback(static_cast<const Future<ResultType>&>(future));
});
}
}
#endif // defined(FIREBASE_USE_STD_FUNCTION)

#if defined(INTERNAL_EXPERIMENTAL)
template <class T>
FutureBase::CompletionCallbackHandle Future<T>::AddOnCompletion(
TypedCompletionCallback callback, void* user_data) const {
return FutureBase::AddOnCompletion(
reinterpret_cast<CompletionCallback>(callback), user_data);
MutexLock lock(mutex_);
if (api_ != nullptr) {
if (callback == nullptr) {
return CompletionCallbackHandle();
}
auto* data =
new detail::TypedCompletionCallbackData<T>{callback, user_data};
return api_->AddCompletionCallback(
handle_, detail::TypedCompletionCallbackTrampoline<T>, data,
detail::DeleteTypedCompletionCallbackData<T>,
/*clear_existing_callbacks=*/false);
}
return CompletionCallbackHandle();
}

#if defined(FIREBASE_USE_STD_FUNCTION)
template <class ResultType>
inline FutureBase::CompletionCallbackHandle Future<ResultType>::AddOnCompletion(
std::function<void(const Future<ResultType>&)> callback) const {
return FutureBase::AddOnCompletion(
*reinterpret_cast<std::function<void(const FutureBase&)>*>(&callback));
if (!callback) {
return CompletionCallbackHandle();
}
return FutureBase::AddOnCompletion([callback](const FutureBase& future) {
callback(static_cast<const Future<ResultType>&>(future));
});
Comment thread
a-maurice marked this conversation as resolved.
}
#endif // defined(FIREBASE_USE_STD_FUNCTION)

Expand Down
Loading