Asynchronous Operations

The SDK provides a thread-safe, asynchronous, and reentrant public API. This means that these public API methods can return results produced asynchronously in the form of async_result. The async_result object represents an eventual completion or a failure of an asynchronous operation and its resulting value. All calls to the SDK are queued onto the SDKs event loop and processed in the FIFO (First In, First Out) order. After making a call, the SDK user application is responsible for either blocking the wait results or setting a function object execute when the asynchronous operation returns using the async_result and methods.

When a user application invokes an asynchronous method of the SDK, the SDK creates two objects: solver, which is used by the asynchronous operation to notify about its completion, and async_result, which is used by the application to get the completion notifications. Both of these objects share the same internal state. The user application must set function object callbacks to be executed when the operation succeeds or fails on the async_result. If the wait helper is used, this is done automatically. When the asynchronous operation completes the callbacks set by the user, it invokes the application. If the asynchronous operation ends before the callbacks are set by the user application, then the callbacks are invoked as soon as they are set, on the application’s thread. Otherwise, the callbacks are invoked when the operation is finished on the SDK’s event loop.

Thread Safe Types and Helper Methods

#include <dolbyio/comms/async_result.h>

The thread safe types which can be exposed by the user via the public API. They define thread safe versions of the Asynchronous Classes documented in the sections below. The helper method allows for synchronous usage of the asynchronous API when called from a different thread.

using dolbyio::comms::async_result = detail::async_result<T, thread_safe_solver_traits>

The thread-safe version of detail::async_result.

Template Parameters:

T – The result type that is wrapped by the underlying solver.

struct dolbyio::comms::thread_safe_solver_traits

Traits that allow for safe implementation of asynchronous classes. They allow public APIs to safely use the objects of these classes.

Public Types

using lock_type = std::mutex

The lock type of the solver, for the Public API this is a mutex.

using lock_guard_type = std::lock_guard<std::mutex>

The lock guard type of the solver, for the Pubcic API this is a lock_guard.

using callback_type = std::function<T>

The callback type for the callbacks attached to the solver. For the Public API this is a std::function object.

using dolbyio::comms::async_result_with_solver = dolbyio::comms::detail::async_result_with_solver<T, thread_safe_solver_traits>

Partial specialization of the dolbyio::comms::detail::solver template class, ensuring that the operations are thread-safe.

using dolbyio::comms::solver = dolbyio::comms::detail::solver<T, thread_safe_solver_traits>

Partial specialization of the dolbyio::comms::detail::solver template class, ensuring that the operations are thread-safe.

using dolbyio::comms::low_level_solver = detail::low_level_solver<T, thread_safe_solver_traits>

The thread-safe version of the detail::solver.

Template Parameters:

T – The result type that is wrapped by the underlying solver.

using dolbyio::comms::low_level_solver_ptr = detail::low_level_solver_ptr<T, thread_safe_solver_traits>

The thread-safe version of detail::solver_ptr.

Template Parameters:

T – The result type that is wrapped by the underlying solver.

template<typename T>
T dolbyio::comms::wait(async_result<T> &&asyncop)

Waits for the asynchronous operation to complete and returns the T type when the operation finishes. This call is synchronous and blocks the calling thread until the result is available. The method either returns an object of type T or throws an exception if the solver of async_result fails.

try {
  auto value = wait(some_async_operation());
}
catch (std::exception& e) {
  std::cerr << e.what() << std::endl;
}

Parameters:

asyncop – The async_result object that wraps a solver that contains the T return type.

Template Parameters:

T – The type of object that is returned asynchronously.

Throws:

dolbyio::comms::exception – or any subclass of exceptions.

Returns:

The object of type T.

Async Result Class

#include <dolbyio/comms/async_result_detail.h>

The async_result is a result that is returned to the SDK by all asynchronous calls, except calls that create the SDK and set the log level. Asynchronous operations can be chained together using async_result::then calls and must be terminated with async_result::on_error calls.

The solver class is used in the SDK internally and allows notifying the asynchronous operation end. The low_level_solver class defines a shared state used by the async_result and the solver. The solver class is not directly used by the SDK user. The solver class is used only by the asynchronous operation itself and the SDK interface does not require the user to create and manage the state of any asynchronous operation. The user only needs to consume the asynchronous work initiated by the SDK and react to its completion.

The low_level_solver should almost never be used directly, even if the user chooses to use SDK’s asynchronous operations framework to implement its own asynchronous operations. Using the async_result and solver pairs is easier and less error-prone. We recommend creating and using low_level_solver directly only for optimization opportunities if the application needs to share the solver between multiple entities using std::shared_ptr.

template<typename T, typename traits>
class dolbyio::comms::detail::async_result

An object that represents the eventual completion or failure of an asynchronous operation and its resulting value.

The asynchronous operation may be in one of these states:

  • Pending: when the asynchronous operation is pending

  • Resolved: when the asynchronous operation is finished

The asynchronous operation may produce a resource, which can be passed to the application, or may not produce anything and only serve and mutate a state. The first template parameter of the async_result object denotes the type of the resource produced by the async operation, with the void type used if the operation does not produce anything besides information about its completion. This type is called a value type of the async operation and the value type of the async_result.

The async_result object may be in one of these states:

  • Pending: The asynchronous operation is pending.

  • Resolved: The asynchronous operation is resolved.

  • Finalized: Introduced by a user of the async_result object by doing operations which consume the async_result object, such as moving the object (move-construction or move-assignment) or setting any callbacks. This state is independent of the asynchronous operation state and means that the async_result object has served its purpose of setting callbacks and can not be used anymore.

A function that executes asynchronously can return the async_result instance. The caller of the function may use the async_result object to set the callbacks for a success and failure notification. When the asynchronous operation is resolved, the respective callbacks are invoked.

If the async_result is resolved by the time the caller sets the callbacks, the callbacks are invoked immediately on the caller’s thread. Otherwise, the async_result is pending and the callbacks are invoked when the async operation finishes. It is forbidden to set callbacks on the finalized async_result.

The async_result interface allows setting the value of the callback (also called the result callback) and the local error callback. The result callback is invoked when the asynchronous operation changes state from pending to resolved with success. If the async operation generates errors and fails, the local error callback is invoked instead.

Setting the value callback constitutes chaining a new async operation. Even if the callback itself works fully synchronously, a new async_result object is created. If the value callback returns another async_result, the async operation created by chaining is resolved when the async operation returned by the value callback is resolved. Otherwise, the async operation created by chaining is resolved immediately after the value callback returns.

The consumer of the async_result object can also set the consume errors callback which is mutually exclusive with the value and local error callbacks. If the previous async operation in the chain resolves with failure, the consume errors callback is invoked. It receives the produced error and must return a placeholder or a substitute value of the type of the failed async operation. This value is passed down the chain to the next async operation as if it was successfully generated by the async operation that generated the error. If the previous async operation does not fail, its generated value is passed down the chain and the consume errors callback is not invoked.

If the async operation resolves with an error, the subsequent async operations get their local error callbacks invoked in the proper order, one by one, up to the async operation with the set consume errors callback or the final error callback. This mechanism is called error propagation. Note that the error propagation is synchronous and no error callbacks can return async_result types. There is also no backtracking; generating errors in the chain does not allow going back to the previous async operations and performing any rollback. These mechanisms, if needed, should be implemented by the user in terms of uni-directional chains of operations.

The final error callback is the last of the callbacks which can be set on the async_result. If set, the error callback ends the operations chain. This callback is invoked when the error is generated by or propagated to the last async operation. In case of the successful resolution of the last async operation in the chain, the final error callback is not invoked.

The async_result interface does not provide any possibility of aborting or cancelling the ongoing asynchronous operation. The interface also does not allow modifying the already constructed async operations chain. Such features, if needed, should be implemented by the user in terms of adding hooks in the value callbacks.

Template Parameters:
  • T – The type of the value produced by the asynchronous operation. If non-void, the value is passed as an rvalue reference to the result callback. Otherwise, the result callback does not take any arguments.

  • traits – The type of traits for configuring internal types used by the async_result. The traits should be provided as a structure which contains definitions of the following types:

    • The lock_type and the lock_guard_type. The lock_type needs to be constructible, while the lock_guard_type must have the std::lock_guard<lock_type> semantics. By using lock_type = std::mutex and lock_guard_type = std::lock_guard<std::mutex> the async_result is made thread-safe and the resolution can occur on a different thread than the one which sets the callbacks.

    • The callback_type that should be a template functor class constructible from a lambda. This type must support the bool() operator and move-assignment, but does not need to be copy-constructible and does not need a const operator. A simple implementation of the traits type would just define the callback_type using callback_type = std::function;

Public Functions

inline async_result(low_level_solver_ptr<T, traits> on_result, async_result_tags::low_level_tag)

A constructor that is used by the asynchronous operation initiator.

We do not recommend constructing the async_result manually using this constructor. The recommended way is to use the make() static method.

Parameters:

on_result – The shared pointer to the low_level_solver.

inline async_result(async_result<T, traits> &&other)

The move constructor.

Constructs the async_result by moving the internal state from another async_result. The result passed as an argument is left in the finalized state after the constructor returns.

Parameters:

other – A parameter moved from async_result.

template<typename TT = T, typename X = std::enable_if_t<!std::is_same<TT, void>::value && std::is_convertible<TT, T>::value, T>>
inline async_result(TT &&val, async_result_tags::resolved_tag = async_result_tags::resolved)

Constructs the resolved result.

The async_result is brought to the resolved state with the provided value at the moment of construction.

The second argument, the async_result_tags::resolved_tag, has a default value and only a single value can be used. Therefore, the argument can be almost always omitted in code. The only scenario where providing the tag is required is constructing the async_result carrying std::exception_ptr as the result of the operation to distinguish between the failed and resolved cases.

// Returns already-resolved result, carrying value 1:
async_result<int, traits> fun() { return 1; }

// Returs already-resolved result, carrying the exception pointer.
// Note that the result is resolved with success, and the value callback
// set in the then() method will be invoked:
async_result<std::exception_ptr, traits> fun2() {
  return {std::make_exception_ptr(std::runtime_error("")),
          async_result_tags::resolved};
}

Parameters:

val – The result of the operation

template<typename TT = T, typename X = std::enable_if_t<std::is_same_v<TT, void>, T>>
inline async_result()

Constructs the resolved result.

The async_result changes state to resolved at the moment of the construction.

template<typename TT = T, typename X = std::enable_if_t<std::is_same<TT, std::exception_ptr>::value, T>>
inline async_result(TT &&e, async_result_tags::failed_tag = async_result_tags::failed)

Constructs the failed result.

The async_result changes state to resolved with failure at the moment of the construction.

The second argument, the async_result_tags::failed_tag, has a default value and there’s only a single value which can be used, therefore the argument can almost always be omitted in the code. The only scenario where providing the tag is required is constructing the async_result carrying the std::exception_ptr as the result of the operation, to distinguish between the failed and resolved cases.

// Returns already-failed result:
async_result<int, traits> fun() {
  return std::make_exception_ptr(std::runtime_error(""));
}

// Returns already-failed result.
// Note that the result is resolved with failure, and the local error
// callback set in the then() method will be invoked. The error will be
// propagated to the chained results, if any:
async_result<std::exception_ptr, traits> fun2() {
  return {std::make_exception_ptr(std::runtime_error("")),
          async_result_tags::failed};
}

inline ~async_result()

The destructor.

The async_result object may be destroyed only after changing state to finalized.

inline async_result<T, traits> &operator=(async_result<T, traits> &&other)

The move assignment operator.

Moves the argument to the current async_result. The current async_result must be in the finalized state. The move assignment operator leaves the argument in the finalized state.

Parameters:

other – The parameter moved from async_result.

Returns:

The reference to the async_result.

template<typename U>
inline auto then(U &&cb, err_cb_type &&local_err_cb = {}) && -> typename detail::return_type_helper<typename detail::cb_type_helper<T, U>::cb_ret_type, traits>::async_result_type

Sets function objects as callbacks on the asynchronous completion.

If the async_result is in the pending state, then when the asynchronous operation finishes, depending on the result, one of the passed callbacks is invoked. If the async operation finishes successfully, then the result callback is invoked. If the async operation fails, the local error callback is invoked.

If the async_result is already in the resolved state by the time this method is invoked, the result or error callback is executed immediately.

This method consumes the current async_result and leaves the result in the finalized state.

This method constructs a new async_result. The type of the result depends on the return type of the provided result callback:

  • If the provided result callback returns async_result<X, Y>, then this method returns async_result<X, Y>. The async_result returned from then() is resolved when the instance returned by the callback function is resolved.

  • If the provided result callback returns any type Z (may be void), this method returns async_result<Z, traits>. The returned async result is resolved immediately when the callback function is invoked.

In any case, if the result callback is invoked and throws an exception, then the async_result returned from then() is resolved with failure.

// On success the following code prints `123`.
 method_returns_async_result()
   .then([](auto&&)
     { std::cerr << "1";
       return another_async_method()
              .then([](auto&&){ std::cerr << "2"; }); },
                     [](auto&& e) { // rethrow and handle exception })
              .then([](auto&&){ std::cerr << "3"; },
                    [](auto&& e) { // rethrow and handle exception });
     })
   .on_error([](auto&& e) { // rethrow and handle exception });

Parameters:
  • cb – The result callback function object.

  • local_err_cb – The local error function object. This functor should not throw any exceptions.

Returns:

The async_result representing the result of the callback invocation.

inline auto consume_errors(typename traits::template callback_type<T(std::exception_ptr&&)> &&err_cb) && -> async_result<T, traits>

Consumes errors produced during an asynchronous operation to not propagate the errors further.

The errors are consumed by the provided error callback function object. If the asynchronous operation is resolved with an error, the chained async operations cannot be executed and error callbacks are invoked. By using the consume_errors() call, the error propagation can be stopped. The caller captures the generated error and replaces the error with a result that is propagated to subsequent asynchronous operations. If the callback throws an error, that error is propagated to subsequent async results instead of the captured error. The callback function returns values of type T.

This method consumes the current async_result and changes its state to finalized.

This method constructs a new async_result of the same type as the current async_result’s type.

 method_returns_async_result().then([](auto&&){ // handle success })
                              .consume_errors(([]auto&&) { // handle
exception }) .then([](){ return another_async_method(); })
                              .on_error([](auto&&) { // handle exception
});

Parameters:

err_cb – The consume errors function object.

Returns:

The async_result which is resolved with a value of this result or, in a case of errors, the value returned by the consume errors callback.

inline void on_error(err_cb_type &&err_cb) &&

Sets the final error callback on the async_result.

This callback is executed when the async operation resolves with failure. If the async operation resolves with a result, the final error callback is never invoked. If the async_result is already in the resolved with failure state when this function is called, the final error callback is executed immediately.

This method consumes the current async_result and changes its state to finalized.

This method does not return anything and should be invoked to close the async operations chain. In order to handle errors in the middle of the async operations chain, use the local error callbacks or the consume errors callback.

The final error callback is allowed to throw exceptions of its own, but these exceptions are caught and ignored.

 method_returns_async_result().then([](auto&&){ // handle success })
                              .on_error([](auto&& e) { // rethrow and
handle exception });

Parameters:

err_cb – The final error function object.

inline explicit operator bool() const

Checks if the async_result is not finalized.

Returns:

False if the async_result is finalized, true otherwise.

Public Static Functions

static inline async_result_with_solver<T, traits> make()

Constructs an async_result paired with the solver.

We recommend using this method for constructing a new async_result by the initiator of the asynchronous operation. The method returns a pair of objects: the async_result and the associated solver. The async_result object should be returned to the caller, which is the consumer of the asynchronous operation’s result. The solver should be passed to the asynchronous code, which eventually resolves the solver when the operation is finished. Resolving the solver changes the state of the async_result to resolved.

 // Enqueues a job on the async operations queue, and returns the
 // async_result:
async_result<void> do_something() { auto [res, solver] =
async_result<void>::make();
   async_operations_queue.emplace_back(std::move(solver));
   return std::move(res);
 }

 // Real implementation of the async operation, executed at some point:
 void do_something_impl() {
   // do stuff

   // Causes the async_result<void> returned from do_something() to resolve
   // and invoke the callbacks:
   std::move(async_operations_queue.front()).resolve();
   async_operations_queue.pop_front();
 }

Returns:

A pair of the async_result and the associated solver.

template<typename T, typename traits>
class dolbyio::comms::detail::async_result_with_solver

The pair of the solver and the associated async_result.

A helper type used for initiating asynchronous operations. The recommended way of creating an async_result representing an asynchronous operation is to use the async_result::make() static method.

Template Parameters:
  • T – The type of the result

  • traits – The traits type. For more information, see the async_result documentation.

Public Functions

inline async_result_with_solver()

The constructor.

inline solver<T, traits> get_solver()

Gets the solver.

This function should be invoked only once, subsequent invocations yield an invalid solver.

Returns:

The solver for notifying about the completion of the operation.

inline async_result<T, traits> get_result()

Get the result.

This function should be invoked only once, subsequent invocations yield a finalized async_result.

Returns:

The async_result for connecting the completion callbacks.

Public Members

solver<T, traits> solver_
async_result<T, traits> result_
template<typename T, typename traits>
class dolbyio::comms::detail::solver

An interface that notifies about the completion of asynchronous operations.

When the asynchronous operation is finished, the fail() or resolve() method of the solver is invoked to bring the associated async_result to the resolved state or invoke the callbacks if the async_result has already been finalized. The solver class ensures that the resolution can happen only once, and that the destruction of the pending solver results in resolving the operation with failure.

The solver class implements move semantics and should be always passed by move to the entity which eventually resolves it. The moved-from state of the solver is invalid and the only allowed operations on the invalid solver are the destruction, move-assignment, and validity check.

Template Parameters:
  • T – The type of the result produced by the asynchronous operation.

  • traits – The traits type. For more information, refer to the documentation of the async_result class.

Public Functions

solver() noexcept = default

The default constructor.

Constructs an invalid solver. Invoking resolve() or fail() on this solver instance results in assertion failures.

inline solver(low_level_solver_ptr<T, traits> slv) noexcept

The constructor.

Constructs a solver. We do not recommend to invoke this constructor directly. The recommended way of creating solvers is to use the async_result::make() method which creates the solver and the associated async_result in a safe way.

inline ~solver()

The destructor.

If the solver is valid and has not been resolved or failed, the destructor fails the solver with the dolbyio::comms::async_operation_canceled exception.

inline void fail(std::exception_ptr &&e) &&

Notifies about the failed async operation.

This method causes the associated async_result to change the state to resolved with failure or the method invokes the callbacks in the failure paths directly if the associated async_result object is already in the finalized state. This method consumes the solver object and changes its state to invalid.

Parameters:

e – the exception.

template<typename TT = T, typename X = std::enable_if_t<std::is_same_v<void, TT>, TT>>
inline void resolve() &&

Notifies about the successful async operation.

This method causes the associated async_result to change the state to resolved with success or the method invokes the value callback directly if the associated async_result object is already in the finalized state. This method consumes the solver object and changes its state to invalid.

template<typename TT = T, typename X = std::enable_if_t<!std::is_same_v<void, TT>, TT>>
inline void resolve(TT &&val) &&

Notifies about the successful async operation.

This method causes the associated async_result to change the state to resolved with success or the method invokes the value callback directly if the associated async_result object is already in the finalized state. This method consumes the solver object and changes its state to invalid.

Parameters:

val – The value produced by the asynchronous operation.

inline explicit operator bool() const

Checks validity of the solver object.

Returns:

true if the solver is valid, false otherwise.

solver(solver<T, traits>&&) noexcept = default

Default move constructor for solver.

inline solver &operator=(solver<T, traits> &&other) noexcept

Move assignment operator for solver.

Parameters:

other – The solver to be moved from.

Returns:

solver Reference to the Solver which was moved too.

template<typename T, typename traits>
class dolbyio::comms::detail::low_level_solver

A shared state of the solver and async_result objects.

The class that stores a low-level building block for code that executes asynchronously. The class allows the caller of the asynchronous function to set the callbacks for notification informing that the function has finished. The class also allows executing code asynchronously to notify that it is finished.

The low_level_solver is templated over two types: the type of the produced value and the traits type. Refer to the documentation of the async_result class for the description of the traits type.

The low_level_solver provides a low-level API. The user of this class must adhere to the following rules:

We do not recommend using the low_level_solver directly. This solver is used as a state object shared between the async_result and the associated solver instance. Using these two types hides the complexity of the low_level_solver and provides a more convenient interface.

Template Parameters:
  • T – The type of the result produced by the low_level_solver.

  • traits – The traits type.

Public Functions

inline low_level_solver(async_result_tags::low_level_tag)

The constructor.

inline ~low_level_solver()

The destructor.

inline void set_callbacks_from(low_level_solver_ptr<T, traits> other)

Chains the current solver with another solver.

Use this method only if the current low_level_solver does not have any assigned callbacks, except for the local error callback. When the current low_level_solver is resolved, the resolve() or fail() method of the chained solver is called. If the current low_level_solver is already resolved, the result is propagated immediately to the chained solver.

Parameters:

other – The shared pointer to the next solver.

inline void resolve(T &&res)

Resolves the solver.

If there is a callback stored in the solver, the callback is executed immediately with the result. Otherwise, the result is stored for later consumption when the callback is set.

Parameters:

res – The value to be moved to the callback function.

inline void fail(std::exception_ptr &&error)

Fails the solver.

If the error callback is set for the solver, the solver is invoked. If the current solver is chained with another solver, the fail() method of the chained solver is invoked. If the current solver is not chained with the next solver, the error is stored to be propagated later.

Parameters:

error – The exception pointer that contains the exception.

inline bool set_callback(result_cb_type &&cb)

Sets a result callback.

If the resolve() method has already been called, the callback is executed immediately. Otherwise, the callback is stored to be invoked if the resolve() method is invoked on the solver.

Parameters:

cb – The function object to call when the result is resolved.

Returns:

True if the function object has been invoked immediately, false otherwise.

inline bool set_propagate_error_callback(err_cb_type &&cb)

Sets an error callback.

If the fail() method has already been called, the error callback is executed immediately. Otherwise, the callback is stored to be executed when the fail() method is called.

Parameters:

cb – The function object to be called in the case of an error.

Returns:

True if the function object has been invoked immediately, false otherwise.

inline bool set_error_callback(err_cb_type &&cb)

Sets the local error callback.

If the fail() method has already been called, the error callback is executed immediately. Otherwise, the callback is stored to be executed when the fail() method is called.

The local error callback differs from the error callback that is set by the set_propagate_error_callback(), where the chaining solvers reset the propagated error callbacks and, in case of errors, only the callback of the last solver is invoked. The local error callbacks are invoked for each solver in the chain.

The set_error_callback() function must not be invoked after set_propagate_error_callback() or set_callbacks_from().

Parameters:

cb – The function object to be called in the case of an error.

Returns:

True if the function object has been invoked immediately, false otherwise.

template<typename traits>
class dolbyio::comms::detail::low_level_solver<void, traits>

A specialized template of the low_level_solver class that wraps void results.

The low_level_solver provides a low-level API. The user of this class must adhere to the following rules:

We do not recommend using the low_level_solver directly.

Template Parameters:

traits – The traits type.

Public Functions

inline low_level_solver(async_result_tags::low_level_tag)

The constructor.

inline ~low_level_solver()

The destructor.

inline void set_callbacks_from(low_level_solver_ptr<void, traits> other)

Chains the current solver with another solver.

This method must be used only if the current low_level_solver does not have any callbacks assigned, except for the local error callback. When the current low_level_solver is resolved, the resolve() or fail() method of the chained solver is called. If the current low_level_solver is already resolved, the chained solver is resolved immediately.

Parameters:

other – The shared pointer to the next solver.

inline void resolve()

Resolves the solver.

If there is a callback stored in the solver, the callback is executed immediately. Otherwise, the callback is invoked when it is assigned.

inline void fail(std::exception_ptr &&error)

Fails the solver.

If the error callback is set for the solver, it is invoked. If the current solver is chained with another solver, the fail() method of that chained solver is invoked. If the current solver is not chained with the next solver, the error is stored to be propagated later.

Parameters:

error – The exception pointer that contains the exception.

inline bool set_callback(result_cb_type &&cb)

Sets a result callback.

If the resolve() method has already been called, the callback is executed immediately. Otherwise, the callback is stored to be invoked when the resolve() method is invoked on the solver.

Parameters:

cb – The function object to call when the result is resolved.

Returns:

True if the function object has been invoked immediately, false otherwise.

inline bool set_propagate_error_callback(err_cb_type &&cb)

Sets an error callback.

If the fail() method has already been called, the error callback is executed immediately. Otherwise, the callback is stored to be executed when the fail() method is called.

Parameters:

cb – The function object to be called in the case of an error.

Returns:

True if the function object has been invoked immediately, false otherwise.

inline bool set_error_callback(err_cb_type &&cb)

Sets the local error callback.

If the fail() method has already been called, the error callback is executed immediately. Otherwise, the callback is stored to be executed when the fail() method is called.

The local error callback differs from the error callback that is set by the set_propagate_error_callback(), where the chaining solvers reset the propagated error callbacks and, in case of errors, only the callback of the last solver is invoked. The local error callbacks are invoked for each solver in the chain.

The set_error_callback() function must not be invoked after set_propagate_error_callback() or set_callbacks_from().

Parameters:

cb – The function object to be called in the case of an error.

Returns:

True if the function object has been invoked immediately, false otherwise.

using dolbyio::comms::detail::low_level_solver_ptr = std::shared_ptr<low_level_solver<T, U>>

A shared pointer to the low_level_solver object.