Modules | Data Structures | Functions | Variables
Eina Promises

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

Modules

 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_Promiseeina_promise_new (Eina_Future_Scheduler *scheduler, Eina_Promise_Cancel_Cb cancel_cb, const void *data)
 Creates a new promise. More...
 
EINA_API Eina_Promiseeina_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. More...
 
EINA_API void eina_promise_resolve (Eina_Promise *p, Eina_Value value)
 Resolves a promise. More...
 
EINA_API void eina_promise_reject (Eina_Promise *p, Eina_Error err)
 Rejects a promise. More...
 

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_set(&v, "Promise resolved");
free(ctx);
return EINA_FALSE;
}
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;
}
void * ecore_timer_del(Ecore_Timer *timer)
Deletes the specified timer from the timer list.
Definition: ecore_timer.c:238
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_API void eina_promise_resolve(Eina_Promise *p, Eina_Value value)
Resolves a promise.
Definition: eina_promise.c:788
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
#define EINA_FALSE
boolean value FALSE (numerical value 0)
Definition: eina_types.h:533
unsigned char Eina_Bool
Type to mimic a boolean.
Definition: eina_types.h:527
#define EINA_UNUSED
Used to indicate that a function parameter is purposely unused.
Definition: eina_types.h:339
EINA_API const Eina_Value_Type * EINA_VALUE_TYPE_STRING
manages string type.
Definition: eina_value.c:5608
static Eina_Bool eina_value_set(Eina_Value *value,...)
Sets the generic value.
static Eina_Bool eina_value_setup(Eina_Value *value, const Eina_Value_Type *type)
Initializes generic value storage.
An opaque structure representing a piece of data that will be available at a later point.
This struct is used as a bridge between Eina and the future scheduler.
Definition: eina_promise.h:165
defines the contents of a value
Definition: eina_value.h:662

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_API void eina_future_cancel(Eina_Future *f)
Cancels a future.
Definition: eina_promise.c:781
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]schedulerThe scheduler.
[in]cancel_cbA callback used to inform that the promise was canceled. Use this callback to free data. cancel_cb must not be NULL !
[in]dataData 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_mempool_calloc(), 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:

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:

_future_resolve(void *data, const Eina_Value v, const Eina_Future *dead_future)
{
p = eina_promise_continue_new(dead_future, _promise_cancel, NULL);
}
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_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
An opaque structure representing a callback to be called when a promise is fulfilled.

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_futureThe future being resolved to get a scheduler from.
[in]cancel_cbA callback used to inform that the promise was canceled. Use this callback to free data. cancel_cb must not be NULL.
[in]dataData 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_mempool_calloc(), 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]pA promise to resolve.
[in]valueThe 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()

References eina_value_flush().

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]pA promise to reject.
[in]errAn 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, eina_value_flush(), eina_value_set(), eina_value_setup(), and EINA_VALUE_TYPE_ERROR.

Referenced by eina_future_rejected().