Eina Promises
Eina

Promises are a programming paradigm that simplifies synchronization when concurrent execution is present. More...

## Topics

| Eina Futures
| Methods and structures dealing with Eina_Future.

## Data Structures

struct | Eina_Promise
| An opaque structure representing a piece of data that will be available at a later point. More...

## Functions

EINA_API Eina_Promise * | eina_promise_new (Eina_Future_Scheduler *scheduler, Eina_Promise_Cancel_Cb cancel_cb, const void *data)
| Creates a new promise.
EINA_API Eina_Promise * | eina_promise_continue_new (const Eina_Future *dead_future, Eina_Promise_Cancel_Cb cancel_cb, const void *data)
| Creates a new promise from a dead_future.
EINA_API void | eina_promise_resolve (Eina_Promise *p, Eina_Value value)
| Resolves a promise.
EINA_API void | eina_promise_reject (Eina_Promise *p, Eina_Error err)
| Rejects a promise.

## Variables

EINA_API const Eina_Value_Type | EINA_VALUE_TYPE_PROMISE
| Value type for Eina_Value's containing an Eina_Promise.

## Detailed Description

Promises are a programming paradigm that simplifies synchronization when concurrent execution is present.

Since C does not natively support Promises the Eina library provides the Eina_Promise and Eina_Future objects.

In procedural languages like C if you need a value which is not yet available, for instance because it takes a long time to calculate or has to be fetched from a remote server, you typically have to wait.

Other languages however can return a Promise and continue execution immediately. A promise acts as a placeholder for the requested value: the value is not available yet but will be at some point in the future.

With a promise in hand you can attach callbacks to be triggered when the value becomes available (i.e. when the promise is fulfilled) and then continue your calculations. You can even pass the promise to other methods which will then be executed as values become available, forming complex chains.

An Eina_Promise can be considered as an object with the sole purpose of emitting the "Promise Resolved" event. Eina_Future are callbacks attached to this object to be called when the event is emitted. The promised value is passed to the callbacks whenever it's available.

Here's a typical example:

#include <Ecore.h>
static void
_promise_cancel(void *data, Eina_Promise *p EINA_UNUSED)
{
Ctx *ctx = data;
// In case the promise is canceled we must stop the timer!
ecore_timer_del(ctx->timer);
free(ctx);
}
static Eina_Bool
_promise_resolve(void *data)
{
Ctx *ctx = data;
Eina_Value v;
eina_value_setup(&v, EINA_VALUE_TYPE_STRING);
eina_value_set(&v, "Promise resolved");
eina_promise_resolve(ctx->p, v);
free(ctx);
return EINA_FALSE;
}
Eina_Promise *
promise_create(Eina_Future_Scheduler *scheduler)
{
Ctx *ctx = malloc(sizeof(Ctx));
// A timer is scheduled in order to resolve the promise
ctx->timer = ecore_timer_add(122, _promise_resolve, ctx);
// The _promise_cancel() will be used to clean ctx if the promise is canceled.
ctx->p = eina_promise_new(scheduler, _promise_cancel, ctx);
return ctx->p;
}
ecore_timer_del
void * ecore_timer_del(Ecore_Timer *timer)
Deletes the specified timer from the timer list.
Definition ecore_timer.c:238
ecore_timer_add
Ecore_Timer * ecore_timer_add(double in, Ecore_Task_Cb func, const void *data)
Creates a timer to call the given function in the given period of time.
Definition ecore_timer.c:189
Eina_Future_Scheduler
struct _Eina_Future_Scheduler Eina_Future_Scheduler
Convenience wrapper over _Eina_Future_Scheduler.
Definition eina_promise.h:57
eina_promise_resolve
EINA_API void eina_promise_resolve(Eina_Promise *p, Eina_Value value)
Resolves a promise.
Definition eina_promise.c:788
eina_promise_new
EINA_API Eina_Promise * eina_promise_new(Eina_Future_Scheduler *scheduler, Eina_Promise_Cancel_Cb cancel_cb, const void *data)
Creates a new promise.
Definition eina_promise.c:743
EINA_FALSE
#define EINA_FALSE
boolean value FALSE (numerical value 0)
Definition eina_types.h:533
Eina_Bool
unsigned char Eina_Bool
Type to mimic a boolean.
Definition eina_types.h:527
EINA_UNUSED
#define EINA_UNUSED
Used to indicate that a function parameter is purposely unused.
Definition eina_types.h:339
Eina_Value
struct _Eina_Value Eina_Value
Store generic values.
Definition eina_value.h:307
EINA_VALUE_TYPE_STRING
EINA_API const Eina_Value_Type * EINA_VALUE_TYPE_STRING
manages string type.
Definition eina_value.c:5608
Eina_Promise
An opaque structure representing a piece of data that will be available at a later point.

## Function Documentation

## eina_promise_new()

EINA_API Eina_Promise * eina_promise_new | ( | Eina_Future_Scheduler * | scheduler,
|  | Eina_Promise_Cancel_Cb | cancel_cb,
|  | const void * | data )

Creates a new promise.

This function creates a new promise which can be used to create a future using eina_future_new(). Every time a promise is created an Eina_Promise_Cancel_Cb must be provided which is used to free resources that were created.

A promise may be canceled directly by calling:

eina_future_cancel(eina_future_new(eina_promise_new(...)))
eina_future_cancel
EINA_API void eina_future_cancel(Eina_Future *f)
Cancels a future.
Definition eina_promise.c:781
eina_future_new
EINA_API Eina_Future * eina_future_new(Eina_Promise *p)
Creates a new future.
Definition eina_promise.c:867

That is, canceling any future that is chained to receive the results.

However promises can be canceled indirectly by other entities. These other entities will call eina_future_cancel() themselves, however you may not be aware of that. Some common sources of indirect cancellations:

- A subsystem was shutdown, canceling all pending futures (i.e.: ecore_shutdown())

- An EO object was linked to the promise or future, then if the object dies (last reference is gone), then the pending promises and futures will be canceled.

- Some other entity (library provider or library user) chained and canceled his future, which will result in your future being canceled.

Since a promise may be canceled indirectly (by code sections that goes beyond your scope) you should always provide a cancel callback, even if you think you'll not need it.

If you already have a value and want to create a future that will resolve to it directly use the eina_future_resolved(), it has the same effect as creating a promise and immediately resolving it.

Parameters

  [in,out] | scheduler | The scheduler.
  [in] | cancel_cb | A callback used to inform that the promise was canceled. Use this callback to `free` `data`. `cancel_cb` must not be `NULL` !
  [in] | data | Data to `cancel_cb`.

Returns
  A promise or `NULL` on error.

See also
  eina_future_cancel()
  eina_future_new()
  eina_promise_continue_new()
  eina_promise_resolve()
  eina_promise_reject()
  eina_promise_as_value()
  Eina_Future_Scheduler
  Eina_Future_Schedule_Entry
  Eina_Future_Scheduler_Cb

References DBG, EINA_SAFETY_ON_NULL_RETURN_VAL, _Eina_Future_Scheduler::recall, and _Eina_Future_Scheduler::schedule.

Referenced by eina_future_as_value(), eina_future_rejected(), eina_future_resolved(), and eina_promise_all_iterator().

## eina_promise_continue_new()

EINA_API Eina_Promise * eina_promise_continue_new | ( | const Eina_Future * | dead_future,
|  | Eina_Promise_Cancel_Cb | cancel_cb,
|  | const void * | data )

Creates a new promise from a dead_future.

This function creates a new promise from a future currently being resolved which can be used to create a Eina_Value with eina_promise_as_value(). Every time a promise is created an Eina_Promise_Cancel_Cb must be provided which is used to free resources that were created.

A promise may be canceled directly by calling:

eina_future_cancel(eina_future_new(eina_promise_new(...)))

That is, canceling any future that is chained to receive the results.

However promises can be canceled indirectly by other entities. These other entities will call eina_future_cancel() themselves, however you may not be aware of that. Some common sources of indirect cancellations:

- A subsystem was shutdown, canceling all pending futures (i.e.: ecore_shutdown())

- An EO object was linked to the promise or future, then if the object dies (last reference is gone), then the pending promises and futures will be canceled.

- Some other entity (library provider or library user) chained and canceled his future, which will result in your future being canceled.

Since a promise may be canceled indirectly (by code sections that goes beyond your scope) you should always provide a cancel callback, even if you think you'll not need it.

Here's a typical example:

Eina_Value
_future_resolve(void *data, const Eina_Value v, const Eina_Future *dead_future)
{
Eina_Promise *p;
p = eina_promise_continue_new(dead_future, _promise_cancel, NULL);
return eina_promise_as_value(p);
}
Eina_Promise
struct _Eina_Promise Eina_Promise
Convenience wrapper.
Definition eina_promise.h:20
Eina_Future
struct _Eina_Future Eina_Future
Convenience wrapper.
Definition eina_promise.h:28
eina_promise_as_value
EINA_API Eina_Value eina_promise_as_value(Eina_Promise *p)
Creates a new Eina_Value from a promise.
Definition eina_promise.c:622
eina_promise_continue_new
EINA_API Eina_Promise * eina_promise_continue_new(const Eina_Future *dead_future, Eina_Promise_Cancel_Cb cancel_cb, const void *data)
Creates a new promise from a dead_future.
Definition eina_promise.c:762

If you already have a value and want to create a future that will resolve to it directly use the eina_future_resolved(), it has the same effect as creating a promise and immediately resolving it.

Note
  This function is to be used solely inside of a future resolve callback with the Eina_Value being returned from it.

Parameters

  [in] | dead_future | The future being resolved to get a scheduler from.
  [in] | cancel_cb | A callback used to inform that the promise was canceled. Use this callback to `free` `data`. `cancel_cb` must not be `NULL`.
  [in] | data | Data to `cancel_cb`.

Returns
  A promise or `NULL` on error.

See also
  eina_future_cancel()
  eina_future_new()
  eina_promise_new()
  eina_promise_resolve()
  eina_promise_reject()
  eina_promise_as_value()
  Eina_Future_Scheduler
  Eina_Future_Schedule_Entry
  Eina_Future_Scheduler_Cb

References DBG, EINA_SAFETY_ON_NULL_RETURN_VAL, and EINA_SAFETY_ON_TRUE_RETURN_VAL.

## eina_promise_resolve()

EINA_API void eina_promise_resolve | ( | Eina_Promise * | p,
|  | Eina_Value | value )

Resolves a promise.

This function schedules a resolve event in a safe context (main loop or some platform defined safe context), whenever possible the future callbacks will be dispatched.

Parameters

  [in,out] | p | A promise to resolve.
  [in] | value | The value to be delivered.

Note that the `value` contents must survive this function scope, that is, do not use stack allocated blobs, arrays, structures or types that keep references to memory you give. Values will be automatically cleaned up using `eina_value_flush()` once they are unused (no more future or futures returned a new value).

See also
  eina_promise_new()
  eina_promise_reject()
  eina_promise_as_value()

Referenced by eina_future_resolved().

## eina_promise_reject()

EINA_API void eina_promise_reject | ( | Eina_Promise * | p,
|  | Eina_Error | err )

Rejects a promise.

This function schedules a reject event in a safe context (main loop or some platform defined safe context), whenever possible the future callbacks will be dispatched.

Parameters

  [in,out] | p | A promise to reject.
  [in] | err | An Eina_Error value

Note
  Internally this function will create an Eina_Value with type EINA_VALUE_TYPE_ERROR.

See also
  eina_promise_new()
  eina_promise_resolve()
  eina_promise_as_value()

References DBG, eina_error_msg_get(), EINA_SAFETY_ON_FALSE_GOTO, and EINA_VALUE_TYPE_ERROR.

Referenced by eina_future_rejected().