nymea-app/3rdParty/android/firebase_cpp_sdk/include/firebase/future.h

333 lines
12 KiB
C++

/*
* Copyright 2016 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FIREBASE_APP_CLIENT_CPP_SRC_INCLUDE_FIREBASE_FUTURE_H_
#define FIREBASE_APP_CLIENT_CPP_SRC_INCLUDE_FIREBASE_FUTURE_H_
#include <stddef.h>
#include <stdint.h>
#include <utility>
#include "firebase/internal/common.h"
#ifdef FIREBASE_USE_STD_FUNCTION
#include <functional>
#endif
namespace firebase {
// Predeclarations.
/// @cond FIREBASE_APP_INTERNAL
namespace detail {
class FutureApiInterface;
} // namespace detail
/// @endcond
/// Asynchronous call status.
enum FutureStatus {
/// Results are ready.
kFutureStatusComplete,
/// Result is still being processed.
kFutureStatusPending,
/// No result is pending.
/// FutureBase::Release() or move operator was called.
kFutureStatusInvalid
};
/// Handle that the API uses to identify an asynchronous call.
/// The exact interpretation of the handle is up to the API.
typedef uintptr_t FutureHandle;
/// @brief Type-independent return type of asynchronous calls.
///
/// @see Future for code samples.
///
/// @cond FIREBASE_APP_INTERNAL
/// Notes:
/// - Futures have pointers back to the API, but the API does not maintain
/// pointers to its Futures. Therefore, all Futures must be destroyed
/// *before* the API is destroyed.
/// - Futures can be moved or copied. Call results are reference counted,
/// and are destroyed when they are long longer referenced by any Futures.
/// - The actual `Status`, `Error`, and `Result` values are kept inside the
/// API. This makes synchronization and data management easier.
///
/// WARNING: This class should remain POD (plain old data). It should not have
/// virtual methods. Nor should the derived Future<T> class add any
/// data. Internally, we static_cast FutureBase to Future<T>,
/// so the underlying data should remain the same.
/// @endcond
class FutureBase {
public:
/// Function pointer for a completion callback. When we call this, we will
/// send the completed future, along with the user data that you specified
/// when you set up the callback.
typedef void (*CompletionCallback)(const FutureBase& result_data,
void* user_data);
/// Construct an untyped future.
FutureBase();
/// @cond FIREBASE_APP_INTERNAL
/// Construct an untyped future using the specified API and handle.
///
/// @param api API class used to provide the future implementation.
/// @param handle Handle to the future.
FutureBase(detail::FutureApiInterface* api, FutureHandle handle);
/// @endcond
~FutureBase();
/// Copy constructor and operator.
/// Increment the reference count when creating a copy of the future.
FutureBase(const FutureBase& rhs);
/// Copy an untyped future.
FutureBase& operator=(const FutureBase& rhs);
#if defined(FIREBASE_USE_MOVE_OPERATORS)
/// Move constructor and operator.
/// Move is more efficient than copy and delete because we don't touch the
/// reference counting in the API.
FutureBase(FutureBase&& rhs);
/// Copy an untyped future.
FutureBase& operator=(FutureBase&& rhs);
#endif // defined(FIREBASE_USE_MOVE_OPERATORS)
/// Explicitly release the internal resources for a future.
/// Future will become invalid.
void Release();
/// Completion status of the asynchronous call.
FutureStatus status() const;
/// When status() is kFutureStatusComplete, returns the API-defined
/// error code. Otherwise, return value is undefined.
int error() const;
/// When status() is kFutureStatusComplete, returns the API-defined error
/// message, as human-readable text, or an empty string if the API does not
/// provide a human readable description of the error.
///
/// @note The returned pointer is only valid for the lifetime of the Future
/// or its copies.
const char* error_message() const;
/// Result of the asynchronous call, or nullptr if the result is still
/// pending. Cast is required since GetFutureResult() returns void*.
const void* result_void() const;
/// Register a callback that will be called at most once, when the future is
/// completed.
///
/// If you call any OnCompletion() method more than once, only the most recent
/// callback you registered will be called.
///
/// When your callback is called, the user_data that you supplied here will be
/// passed back as the second parameter.
///
/// @param[in] callback Function pointer to your callback.
/// @param[in] user_data Optional user data. We will pass this back to your
/// callback.
void OnCompletion(CompletionCallback callback, void* user_data) const;
#if defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
/// Register a callback that will be called at most once, when the future is
/// completed.
///
/// If you call any OnCompletion() method more than once, only the most recent
/// callback you registered will be called.
///
/// @param[in] callback Function or lambda to call.
///
/// @note This method is not available when using STLPort on Android, as
/// std::function is not supported on STLPort.
void OnCompletion(std::function<void(const FutureBase&)> callback) const;
#endif // defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
/// Returns true if the two Futures reference the same result.
bool operator==(const FutureBase& rhs) const {
return api_ == rhs.api_ && handle_ == rhs.handle_;
}
/// Returns true if the two Futures reference different results.
bool operator!=(const FutureBase& rhs) const { return !operator==(rhs); }
#if defined(INTERNAL_EXPERIMENTAL)
/// Returns the API-specific handle. Should only be called by the API.
FutureHandle GetHandle() const { return handle_; }
#endif // defined(INTERNAL_EXPERIMENTAL)
protected:
/// @cond FIREBASE_APP_INTERNAL
/// Backpointer to the issuing API class.
/// Set to nullptr when Future is invalidated.
detail::FutureApiInterface* api_;
/// API-specified handle type.
FutureHandle handle_;
/// @endcond
};
/// @brief Type-specific version of FutureBase.
///
/// The Firebase C++ SDK uses this class to return results from asynchronous
/// operations. All Firebase C++ functions and method calls that operate
/// asynchronously return a Future, and provide a "LastResult" function to
/// retrieve the most recent Future result.
///
/// @code
/// // You can retrieve the Future from the function call directly, like this:
/// Future< SampleResultType > future = firebase::SampleAsyncOperation();
///
/// // Or you can retrieve it later, like this:
/// firebase::SampleAsyncOperation();
/// // [...]
/// Future< SampleResultType > future =
/// firebase::SampleAsyncOperationLastResult();
/// @endcode
///
/// When you have a Future from an asynchronous operation, it will eventually
/// complete. Once it is complete, you can check for errors (a nonzero error()
/// means an error occurred) and get the result data if no error occurred by
/// calling result().
///
/// There are two ways to find out that a Future has completed. You can poll
/// its status(), or set an OnCompletion() callback:
///
/// @code
/// // Check whether the status is kFutureStatusComplete.
/// if (future.status() == firebase::kFutureStatusComplete) {
/// if (future.error() == 0) {
/// DoSomethingWithResultData(future.result());
/// }
/// else {
/// LogMessage("Error %d: %s", future.error(), future.error_message());
/// }
/// }
///
/// // Or, set an OnCompletion callback, which accepts a C++11 lambda or
/// // function pointer. You can pass your own user data to the callback. In
/// // most cases, the callback will be running in a different thread, so take
/// // care to make sure your code is thread-safe.
/// future.OnCompletion([](const Future< SampleResultType >& completed_future,
/// void* user_data) {
/// // We are probably in a different thread right now.
/// if (completed_future.error() == 0) {
/// DoSomethingWithResultData(completed_future.result());
/// }
/// else {
/// LogMessage("Error %d: %s",
/// completed_future.error(),
/// completed_future.error_message());
/// }
/// }, user_data);
/// @endcode
///
/// @tparam ResultType The type of this Future's result.
//
// WARNING: This class should not have virtual methods or data members.
// See the warning in FutureBase for further details.
template <typename ResultType>
class Future : public FutureBase {
public:
/// Function pointer for a completion callback. When we call this, we will
/// send the completed future, along with the user data that you specified
/// when you set up the callback.
typedef void (*TypedCompletionCallback)(const Future<ResultType>& result_data,
void* user_data);
/// Construct a future.
Future() {}
/// @cond FIREBASE_APP_INTERNAL
/// Construct a future using the specified API and handle.
///
/// @param api API class used to provide the future implementation.
/// @param handle Handle to the future.
Future(detail::FutureApiInterface* api, FutureHandle handle)
: FutureBase(api, handle) {}
/// @endcond
/// Result of the asynchronous call, or nullptr if the result is still
/// pending. Allows the API to provide a type-specific interface.
///
const ResultType* result() const {
return static_cast<const ResultType*>(result_void());
}
/// Register a callback that will be called at most once, when the future is
/// completed.
///
/// If you call any OnCompletion() method more than once, only the most recent
/// callback you registered will be called.
///
/// When your callback is called, the user_data that you supplied here will be
/// passed back as the second parameter.
///
/// @param[in] callback Function pointer to your callback.
/// @param[in] user_data Optional user data. We will pass this back to your
/// callback.
///
/// @note This is the same callback as FutureBase::OnCompletion(), so you
/// can't expect to set both and have both run; again, only the most recently
/// registered one will run.
void OnCompletion(TypedCompletionCallback callback, void* user_data) const {
FutureBase::OnCompletion(reinterpret_cast<CompletionCallback>(callback),
user_data);
}
#if defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
/// Register a callback that will be called at most once, when the future is
/// completed.
///
/// If you call any OnCompletion() method more than once, only the most recent
/// callback you registered will be called.
///
/// @param[in] callback Function or lambda to call.
///
/// @note This method is not available when using STLPort on Android, as
/// std::function is not supported on STLPort.
///
/// @note This is the same callback as FutureBase::OnCompletion(), so you
/// can't expect to set both and have both run; again, only the most recently
/// registered one will run.
void OnCompletion(
std::function<void(const Future<ResultType>&)> callback) const {
FutureBase::OnCompletion(
*reinterpret_cast<std::function<void(const FutureBase&)>*>(&callback));
}
#endif // defined(FIREBASE_USE_STD_FUNCTION) || defined(DOXYGEN)
};
// NOLINTNEXTLINE - allow namespace overridden
} // namespace firebase
// Include the inline implementation.
#include "firebase/internal/future_impl.h"
#endif // FIREBASE_APP_CLIENT_CPP_SRC_INCLUDE_FIREBASE_FUTURE_H_