--- /dev/null
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <Eina.h>
+
+#include <assert.h>
+
+typedef struct _Eina_Promise_Then_Cb _Eina_Promise_Then_Cb;
+typedef struct _Eina_Promise_Progress_Cb _Eina_Promise_Progress_Cb;
+typedef struct _Eina_Promise_Cancel_Cb _Eina_Promise_Cancel_Cb;
+typedef struct _Eina_Promise_Default _Eina_Promise_Default;
+typedef struct _Eina_Promise_Default_Owner _Eina_Promise_Default_Owner;
+typedef struct _Eina_Promise_Iterator _Eina_Promise_Iterator;
+typedef struct _Eina_Promise_Success_Iterator _Eina_Promise_Success_Iterator;
+
+struct _Eina_Promise_Then_Cb
+{
+ EINA_INLIST;
+
+ Eina_Promise_Cb callback;
+ Eina_Promise_Error_Cb error_cb;
+ void* data;
+};
+
+struct _Eina_Promise_Progress_Cb
+{
+ EINA_INLIST;
+
+ Eina_Promise_Progress_Cb callback;
+ void* data;
+};
+
+struct _Eina_Promise_Cancel_Cb
+{
+ EINA_INLIST;
+
+ Eina_Promise_Default_Cancel_Cb callback;
+ Eina_Promise_Free_Cb free;
+ void* data;
+};
+
+struct _Eina_Promise_Default
+{
+ Eina_Promise vtable;
+ Eina_Error error;
+ size_t value_size;
+
+ Eina_Inlist *then_callbacks;
+ Eina_Inlist *progress_callbacks;
+ Eina_Inlist *cancel_callbacks;
+ Eina_Promise_Free_Cb value_free_cb;
+
+ int ref;
+
+ Eina_Bool has_finished : 1;
+ Eina_Bool has_errored : 1;
+ Eina_Bool is_cancelled : 1;
+ Eina_Bool is_manual_then : 1;
+ Eina_Bool is_first_then : 1;
+};
+
+struct _Eina_Promise_Default_Owner
+{
+ Eina_Promise_Owner owner_vtable;
+ _Eina_Promise_Default promise;
+
+ char value[];
+};
+
+#define EINA_PROMISE_GET_OWNER(p) (_Eina_Promise_Default_Owner*)((unsigned char*)p - offsetof(struct _Eina_Promise_Default_Owner, promise))
+
+struct _Eina_Promise_Iterator
+{
+ Eina_Iterator* success_iterator;
+ struct _Eina_Promise_Success_Iterator
+ {
+ Eina_Iterator success_iterator_impl;
+ unsigned int promise_index;
+ unsigned int num_promises;
+ unsigned int promises_finished;
+ Eina_Promise* promises[];
+ } data;
+};
+
+static void _eina_promise_finish(_Eina_Promise_Default_Owner* promise);
+static void _eina_promise_ref(_Eina_Promise_Default* promise);
+static void _eina_promise_unref(_Eina_Promise_Default* promise);
+
+static void _eina_promise_iterator_setup(_Eina_Promise_Iterator* iterator, Eina_Array* promises);
+
+static void
+_eina_promise_then_calls(_Eina_Promise_Default_Owner* promise)
+{
+ _Eina_Promise_Then_Cb* callback;
+ Eina_Inlist* list2;
+ Eina_Bool error;
+
+ _eina_promise_ref(&promise->promise);
+ error = promise->promise.has_errored;
+
+ EINA_INLIST_FOREACH_SAFE(promise->promise.then_callbacks, list2, callback)
+ {
+ if (error)
+ {
+ if (callback->error_cb)
+ (*callback->error_cb)(callback->data, &promise->promise.error);
+ }
+ else if (callback->callback)
+ {
+ fprintf(stderr, "then callback\n");
+ (*callback->callback)(callback->data, &promise->value[0]);
+ }
+ _eina_promise_unref(&promise->promise);
+ }
+ _eina_promise_unref(&promise->promise);
+}
+
+static void
+_eina_promise_cancel_calls(_Eina_Promise_Default_Owner* promise, Eina_Bool call_cancel EINA_UNUSED)
+{
+ _Eina_Promise_Cancel_Cb* callback;
+ Eina_Inlist* list2;
+
+ EINA_INLIST_FOREACH_SAFE(promise->promise.cancel_callbacks, list2, callback)
+ {
+ if (callback->callback)
+ {
+ (*callback->callback)(callback->data, (Eina_Promise_Owner*)promise);
+ }
+ }
+
+ if (!promise->promise.is_manual_then)
+ {
+ _eina_promise_then_calls(promise);
+ }
+}
+
+static void
+_eina_promise_del(_Eina_Promise_Default_Owner* promise)
+{
+ if (promise->promise.has_finished)
+ {
+ if (promise->promise.value_free_cb)
+ promise->promise.value_free_cb((void*)&promise->value[0]);
+ }
+ else
+ {
+ _eina_promise_cancel_calls(promise, EINA_TRUE);
+ }
+}
+
+static void *
+_eina_promise_buffer_get(_Eina_Promise_Default_Owner* promise)
+{
+ return &promise->value[0];
+}
+
+static void *
+_eina_promise_value_get(_Eina_Promise_Default_Owner const* promise)
+{
+ if (promise->promise.has_finished)
+ {
+ return (void*)(promise->promise.value_size && !promise->promise.has_errored ?
+ &promise->value[0] : NULL);
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+static void
+_eina_promise_value_set(_Eina_Promise_Default_Owner* promise, void* data, Eina_Promise_Free_Cb free)
+{
+ if (data && promise->promise.value_size)
+ {
+ memcpy(&promise->value[0], data, promise->promise.value_size);
+ }
+
+ promise->promise.value_free_cb = free;
+
+ _eina_promise_finish(promise);
+}
+
+static void
+_eina_promise_then(_Eina_Promise_Default* p, Eina_Promise_Cb callback,
+ Eina_Promise_Error_Cb error_cb, void* data)
+{
+ _Eina_Promise_Default_Owner* promise;
+ _Eina_Promise_Then_Cb* cb;
+
+ promise = EINA_PROMISE_GET_OWNER(p);
+
+ cb = malloc(sizeof(struct _Eina_Promise_Then_Cb));
+
+ cb->callback = callback;
+ cb->error_cb = error_cb;
+ cb->data = data;
+ promise->promise.then_callbacks = eina_inlist_append(promise->promise.then_callbacks, EINA_INLIST_GET(cb));
+ fprintf(stderr, "appending then callback\n");
+
+ if (!promise->promise.is_first_then)
+ {
+ _eina_promise_ref(p);
+ promise->promise.is_first_then = EINA_FALSE;
+ }
+ if (promise->promise.has_finished)
+ {
+ _eina_promise_then_calls(promise);
+ }
+}
+
+static void
+_eina_promise_error_set(_Eina_Promise_Default_Owner* promise, Eina_Error error)
+{
+ promise->promise.error = error;
+ promise->promise.has_errored = EINA_TRUE;
+
+ _eina_promise_finish(promise);
+}
+
+static void
+_eina_promise_finish(_Eina_Promise_Default_Owner* promise)
+{
+ promise->promise.has_finished = EINA_TRUE;
+ if (!promise->promise.is_manual_then)
+ {
+ _eina_promise_then_calls(promise);
+ }
+}
+
+static Eina_Error
+_eina_promise_error_get(_Eina_Promise_Default_Owner const* promise)
+{
+ if (promise->promise.has_errored)
+ {
+ return promise->promise.error;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static Eina_Bool
+_eina_promise_pending_is(_Eina_Promise_Default const* promise)
+{
+ return !promise->has_finished;
+}
+
+static Eina_Bool
+_eina_promise_owner_pending_is(_Eina_Promise_Default_Owner const* promise)
+{
+ return !promise->promise.has_finished;
+}
+
+static Eina_Bool
+_eina_promise_owner_cancelled_is(_Eina_Promise_Default_Owner const* promise)
+{
+ return promise->promise.is_cancelled;
+}
+
+static void
+_eina_promise_progress_cb_add(_Eina_Promise_Default* promise, Eina_Promise_Progress_Cb callback, void* data)
+{
+ _Eina_Promise_Progress_Cb* cb;
+
+ cb = malloc(sizeof(struct _Eina_Promise_Progress_Cb));
+ cb->callback = callback;
+ cb->data = data;
+ promise->progress_callbacks = eina_inlist_append(promise->progress_callbacks, EINA_INLIST_GET(cb));
+}
+
+static void
+_eina_promise_cancel(_Eina_Promise_Default* promise)
+{
+ _Eina_Promise_Default_Owner* owner = EINA_PROMISE_GET_OWNER(promise);
+
+ if (!owner->promise.is_cancelled)
+ {
+ owner->promise.is_cancelled = EINA_TRUE;
+ owner->promise.has_finished = EINA_TRUE;
+ owner->promise.has_errored = EINA_TRUE;
+ _eina_promise_cancel_calls(owner, EINA_TRUE);
+ }
+}
+
+static size_t
+_eina_promise_value_size_get(_Eina_Promise_Default_Owner const* promise)
+{
+ return promise->promise.value_size;
+}
+
+static void
+_eina_promise_ref(_Eina_Promise_Default* p)
+{
+ ++p->ref;
+}
+
+static void
+_eina_promise_unref(_Eina_Promise_Default* p)
+{
+ if (p->ref == 1 && p->has_finished)
+ {
+ _eina_promise_del(EINA_PROMISE_GET_OWNER(p));
+ }
+ else
+ {
+ --p->ref;
+ }
+}
+
+static Eina_Promise *
+_eina_promise_owner_promise_get(_Eina_Promise_Default_Owner* p)
+{
+ return &p->promise.vtable;
+}
+
+void
+eina_promise_owner_default_cancel_cb_add(Eina_Promise_Owner* p,
+ Eina_Promise_Default_Cancel_Cb callback, void* data,
+ Eina_Promise_Free_Cb free_cb)
+{
+ _Eina_Promise_Default_Owner *promise;
+ _Eina_Promise_Cancel_Cb *cb;
+
+ promise = (_Eina_Promise_Default_Owner *)p;
+
+ cb = malloc(sizeof(struct _Eina_Promise_Cancel_Cb));
+
+ cb->callback = callback;
+ cb->free = free_cb;
+ cb->data = data;
+ promise->promise.cancel_callbacks = eina_inlist_append(promise->promise.cancel_callbacks, EINA_INLIST_GET(cb));
+
+ if (promise->promise.is_cancelled)
+ {
+ _eina_promise_cancel_calls(promise, EINA_TRUE);
+ }
+}
+
+static void
+_eina_promise_owner_progress(_Eina_Promise_Default_Owner* promise, void* data)
+{
+ _Eina_Promise_Progress_Cb* callback;
+ Eina_Inlist* list2;
+
+ EINA_INLIST_FOREACH_SAFE(promise->promise.progress_callbacks, list2, callback)
+ {
+ (*callback->callback)(callback->data, data);
+ }
+}
+
+Eina_Promise_Owner *
+eina_promise_default_add(int value_size)
+{
+ _Eina_Promise_Default_Owner* p;
+
+ p = malloc(sizeof(_Eina_Promise_Default_Owner) + value_size);
+ p->promise.vtable.version = EINA_PROMISE_VERSION;
+ p->promise.vtable.then = EINA_FUNC_PROMISE_THEN(_eina_promise_then);
+ p->promise.vtable.value_get = EINA_FUNC_PROMISE_VALUE_GET(_eina_promise_value_get);
+ p->promise.vtable.error_get = EINA_FUNC_PROMISE_ERROR_GET(_eina_promise_error_get);
+ p->promise.vtable.pending_is = EINA_FUNC_PROMISE_PENDING_IS(_eina_promise_pending_is);
+ p->promise.vtable.progress_cb_add = EINA_FUNC_PROMISE_PROGRESS_CB_ADD(_eina_promise_progress_cb_add);
+ p->promise.vtable.cancel = EINA_FUNC_PROMISE_CANCEL(_eina_promise_cancel);
+ p->promise.vtable.ref = EINA_FUNC_PROMISE_REF(_eina_promise_ref);
+ p->promise.vtable.unref = EINA_FUNC_PROMISE_UNREF(_eina_promise_unref);
+ p->promise.vtable.value_size_get = EINA_FUNC_PROMISE_VALUE_SIZE_GET(_eina_promise_value_size_get);
+ p->promise.has_finished = p->promise.has_errored =
+ p->promise.is_cancelled = p->promise.is_manual_then = EINA_FALSE;
+ p->promise.is_first_then = EINA_TRUE;
+ p->promise.ref = 1;
+ memset(&p->promise.then_callbacks, 0, sizeof(p->promise.then_callbacks));
+ memset(&p->promise.progress_callbacks, 0, sizeof(p->promise.progress_callbacks));
+ memset(&p->promise.cancel_callbacks, 0, sizeof(p->promise.cancel_callbacks));
+ p->promise.value_size = value_size;
+ p->promise.value_free_cb = NULL;
+
+ p->owner_vtable.version = EINA_PROMISE_VERSION;
+ p->owner_vtable.value_set = EINA_FUNC_PROMISE_OWNER_VALUE_SET(_eina_promise_value_set);
+ p->owner_vtable.error_set = EINA_FUNC_PROMISE_OWNER_ERROR_SET(_eina_promise_error_set);
+ p->owner_vtable.buffer_get = EINA_FUNC_PROMISE_OWNER_BUFFER_GET(_eina_promise_buffer_get);
+ p->owner_vtable.value_size_get = EINA_FUNC_PROMISE_OWNER_VALUE_SIZE_GET(_eina_promise_value_size_get);
+ p->owner_vtable.promise_get = EINA_FUNC_PROMISE_OWNER_PROMISE_GET(_eina_promise_owner_promise_get);
+ p->owner_vtable.pending_is = EINA_FUNC_PROMISE_OWNER_PENDING_IS(_eina_promise_owner_pending_is);
+ p->owner_vtable.cancelled_is = EINA_FUNC_PROMISE_OWNER_CANCELLED_IS(_eina_promise_owner_cancelled_is);
+ p->owner_vtable.progress = EINA_FUNC_PROMISE_OWNER_PROGRESS(_eina_promise_owner_progress);
+
+ return &p->owner_vtable;
+}
+
+void
+eina_promise_owner_default_manual_then_set(Eina_Promise_Owner* owner, Eina_Bool is_manual)
+{
+ _Eina_Promise_Default_Owner* p = (_Eina_Promise_Default_Owner*)owner;
+
+ p->promise.is_manual_then = is_manual;
+}
+
+void
+eina_promise_owner_default_call_then(Eina_Promise_Owner* promise)
+{
+ _Eina_Promise_Default_Owner* owner = (_Eina_Promise_Default_Owner*)promise;
+
+ _eina_promise_then_calls(owner);
+}
+
+static void
+_eina_promise_all_compose_then_cb(_Eina_Promise_Default_Owner* promise, void* value EINA_UNUSED)
+{
+ _Eina_Promise_Iterator* iterator;
+
+ if (!promise->promise.has_finished)
+ {
+ iterator = (_Eina_Promise_Iterator*)promise->value;
+ if (++iterator->data.promises_finished == iterator->data.num_promises)
+ {
+ _eina_promise_finish(promise);
+ }
+ }
+}
+
+static void
+_eina_promise_all_compose_error_then_cb(_Eina_Promise_Default_Owner* promise, Eina_Error const* error)
+{
+ if (!promise->promise.has_finished)
+ {
+ promise->promise.has_finished = promise->promise.has_errored = EINA_TRUE;
+ promise->promise.error = *error;
+ _eina_promise_finish(promise);
+ }
+}
+
+static void
+_eina_promise_all_free(_Eina_Promise_Iterator* value)
+{
+ unsigned i = 0;
+
+ eina_iterator_free(value->success_iterator);
+
+ for (;i != value->data.num_promises; ++i)
+ {
+ eina_promise_unref(value->data.promises[i]);
+ }
+}
+
+Eina_Promise *
+eina_promise_all(Eina_Iterator* it)
+{
+ _Eina_Promise_Default_Owner *promise;
+ Eina_Promise* current;
+ Eina_Array* promises;
+ Eina_Promise **cur_promise, **last;
+ _Eina_Promise_Iterator* internal_it;
+
+ promises = eina_array_new(20);
+
+ EINA_ITERATOR_FOREACH(it, current)
+ {
+ eina_array_push(promises, current);
+ }
+
+ eina_iterator_free(it);
+
+ promise = (_Eina_Promise_Default_Owner*)
+ eina_promise_default_add(sizeof(_Eina_Promise_Iterator) +
+ sizeof(_Eina_Promise_Default_Owner*)*eina_array_count_get(promises));
+ internal_it = (_Eina_Promise_Iterator*)&promise->value[0];
+ _eina_promise_iterator_setup(internal_it, promises);
+ eina_array_free(promises);
+
+ promise->promise.value_free_cb = (Eina_Promise_Free_Cb)&_eina_promise_all_free;
+
+ cur_promise = internal_it->data.promises;
+ last = internal_it->data.promises + internal_it->data.num_promises;
+ for (;cur_promise != last; ++cur_promise)
+ {
+ eina_promise_then(*cur_promise, (Eina_Promise_Cb)&_eina_promise_all_compose_then_cb,
+ (Eina_Promise_Error_Cb)&_eina_promise_all_compose_error_then_cb, promise);
+ eina_promise_ref(*cur_promise); // We need to keep the value alive until this promise is freed
+ }
+
+ return &promise->promise.vtable;
+}
+
+static Eina_Bool
+_eina_promise_iterator_next(_Eina_Promise_Success_Iterator *it, void **data)
+{
+ if (it->promise_index == it->num_promises)
+ return EINA_FALSE;
+
+ if (eina_promise_error_get(it->promises[it->promise_index]))
+ {
+ return EINA_FALSE;
+ }
+ else
+ {
+ *data = eina_promise_value_get(it->promises[it->promise_index++]);
+ return EINA_TRUE;
+ }
+}
+
+static void **
+_eina_promise_iterator_get_container(_Eina_Promise_Success_Iterator *it)
+{
+ return (void**)it->promises;
+}
+
+static void
+_eina_promise_iterator_free(_Eina_Promise_Success_Iterator *it EINA_UNUSED)
+{
+}
+
+static void
+_eina_promise_iterator_setup(_Eina_Promise_Iterator* it, Eina_Array* promises_array)
+{
+ Eina_Promise** promises;
+
+ it->success_iterator = &it->data.success_iterator_impl;
+ it->data.num_promises = eina_array_count_get(promises_array);
+ it->data.promise_index = 0;
+ it->data.promises_finished = 0;
+ promises = (Eina_Promise**)promises_array->data;
+
+ memcpy(&it->data.promises[0], promises, it->data.num_promises*sizeof(Eina_Promise*));
+
+ EINA_MAGIC_SET(&it->data.success_iterator_impl, EINA_MAGIC_ITERATOR);
+
+ it->data.success_iterator_impl.version = EINA_ITERATOR_VERSION;
+ it->data.success_iterator_impl.next = FUNC_ITERATOR_NEXT(_eina_promise_iterator_next);
+ it->data.success_iterator_impl.get_container = FUNC_ITERATOR_GET_CONTAINER(
+ _eina_promise_iterator_get_container);
+ it->data.success_iterator_impl.free = FUNC_ITERATOR_FREE(_eina_promise_iterator_free);
+}
+
+// API functions
+EAPI void
+eina_promise_then(Eina_Promise* promise, Eina_Promise_Cb callback,
+ Eina_Promise_Error_Cb error_cb, void* data)
+{
+ promise->then(promise, callback, error_cb, data);
+}
+
+EAPI void
+eina_promise_owner_value_set(Eina_Promise_Owner* promise, void* value, Eina_Promise_Free_Cb free)
+{
+ promise->value_set(promise, value, free);
+}
+
+EAPI void
+eina_promise_owner_error_set(Eina_Promise_Owner* promise, Eina_Error error)
+{
+ promise->error_set(promise, error);
+}
+
+EAPI void *
+eina_promise_value_get(Eina_Promise const* promise)
+{
+ return promise->value_get(promise);
+}
+
+EAPI Eina_Error
+eina_promise_error_get(Eina_Promise const* promise)
+{
+ return promise->error_get(promise);
+}
+
+EAPI Eina_Bool
+eina_promise_pending_is(Eina_Promise const* promise)
+{
+ return promise->pending_is(promise);
+}
+
+EAPI void
+eina_promise_progress_cb_add(Eina_Promise* promise, Eina_Promise_Progress_Cb callback, void* data)
+{
+ promise->progress_cb_add(promise, callback, data);
+}
+
+EAPI void
+eina_promise_cancel(Eina_Promise* promise)
+{
+ promise->cancel(promise);
+}
+
+EAPI void
+eina_promise_ref(Eina_Promise* promise)
+{
+ promise->ref(promise);
+}
+
+EAPI void
+eina_promise_unref(Eina_Promise* promise)
+{
+ promise->unref(promise);
+}
+
+EAPI void *
+eina_promise_owner_buffer_get(Eina_Promise_Owner* promise)
+{
+ return promise->buffer_get(promise);
+}
+
+EAPI void *
+eina_promise_buffer_get(Eina_Promise* promise)
+{
+ return promise->buffer_get(promise);
+}
+
+EAPI size_t
+eina_promise_value_size_get(Eina_Promise const* promise)
+{
+ return promise->value_size_get(promise);
+}
+
+EAPI Eina_Promise *
+eina_promise_owner_promise_get(Eina_Promise_Owner* promise)
+{
+ return promise->promise_get(promise);
+}
+
+EAPI Eina_Bool
+eina_promise_owner_pending_is(Eina_Promise_Owner const* promise)
+{
+ return promise->pending_is(promise);
+}
+
+EAPI Eina_Bool
+eina_promise_owner_cancelled_is(Eina_Promise_Owner const* promise)
+{
+ return promise->cancelled_is(promise);
+}
+
+EAPI void
+eina_promise_owner_progress(Eina_Promise_Owner const* promise, void* progress)
+{
+ promise->progress(promise, progress);
+}
--- /dev/null
+
+#ifdef EFL_BETA_API_SUPPORT
+
+struct _Eina_Promise;
+struct _Eina_Promise_Default;
+
+/*
+ * @def Eina_Promise
+ */
+typedef struct _Eina_Promise Eina_Promise;
+
+/*
+ * @def Eina_Promise
+ */
+typedef struct _Eina_Promise_Owner Eina_Promise_Owner;
+
+/*
+ * @brief Callback type for freeing Promise value and void* pointer data for callbacks
+ */
+typedef void(*Eina_Promise_Free_Cb)(void* value);
+
+/*
+ * @brief Function callback type for when using eina_promise_then
+ */
+typedef void(*Eina_Promise_Cb)(void* data, void* value);
+
+/*
+ * @brief Function callback type for when using eina_promise_then
+ */
+typedef void(*Eina_Promise_Error_Cb)(void* data, Eina_Error const* error);
+
+/*
+ * @brief Function callback type for progress information
+ */
+typedef void(*Eina_Promise_Progress_Cb)(void* data, void* value);
+
+/*
+ * @brief Function callback type for then function override
+ */
+typedef void(*Eina_Promise_Then_Cb)(Eina_Promise* promise, Eina_Promise_Cb callback,
+ Eina_Promise_Error_Cb error_cb, void* data);
+
+#define EINA_FUNC_PROMISE_THEN(Function) ((Eina_Promise_Then_Cb)Function)
+
+/*
+ * @brief Function callback type for promise's value_get function override
+ */
+typedef void*(*Eina_Promise_Value_Get_Cb)(Eina_Promise const* promise);
+
+#define EINA_FUNC_PROMISE_VALUE_GET(Function) ((Eina_Promise_Value_Get_Cb)Function)
+
+/*
+ * @brief Function callback type for promise's error_get function override
+ */
+typedef Eina_Error(*Eina_Promise_Error_Get_Cb)(Eina_Promise const* promise);
+
+#define EINA_FUNC_PROMISE_ERROR_GET(Function) ((Eina_Promise_Error_Get_Cb)Function)
+
+/*
+ * @brief Function callback type for promise's pending function override
+ */
+typedef Eina_Bool(*Eina_Promise_Pending_Is_Cb)(Eina_Promise const* promise);
+
+#define EINA_FUNC_PROMISE_PENDING_IS(Function) ((Eina_Promise_Pending_Is_Cb)Function)
+
+/*
+ * @brief Function callback type for promise's progress add function override
+ */
+typedef void(*Eina_Promise_Progress_Cb_Add_Cb)(Eina_Promise* promise, Eina_Promise_Progress_Cb callback, void* data);
+
+#define EINA_FUNC_PROMISE_PROGRESS_CB_ADD(Function) ((Eina_Promise_Progress_Cb_Add_Cb)Function)
+
+/*
+ * @brief Function callback type for promise's cancel function override
+ */
+typedef void(*Eina_Promise_Cancel_Cb)(Eina_Promise* promise);
+
+#define EINA_FUNC_PROMISE_CANCEL(Function) ((Eina_Promise_Cancel_Cb)Function)
+
+/*
+ * @brief Function callback type for promise's ref function override
+ */
+typedef void(*Eina_Promise_Ref_Cb)(Eina_Promise* promise);
+
+#define EINA_FUNC_PROMISE_REF(Function) ((Eina_Promise_Ref_Cb)Function)
+
+/*
+ * @brief Function callback type for promise's unref function override
+ */
+typedef void(*Eina_Promise_Unref_Cb)(Eina_Promise* promise);
+
+#define EINA_FUNC_PROMISE_UNREF(Function) ((Eina_Promise_Unref_Cb)Function)
+
+/*
+ * @brief Function callback type for promise's buffer_get function override
+ */
+typedef void*(*Eina_Promise_Buffer_Get_Cb)(Eina_Promise* promise);
+
+#define EINA_FUNC_PROMISE_BUFFER_GET(Function) ((Eina_Promise_Buffer_Get_Cb)Function)
+
+/*
+ * @brief Function callback type for promise's value_size_get function override
+ */
+typedef size_t(*Eina_Promise_Value_Size_Get_Cb)(Eina_Promise const* promise);
+
+#define EINA_FUNC_PROMISE_VALUE_SIZE_GET(Function) ((Eina_Promise_Value_Size_Get_Cb)Function)
+
+
+/*
+ * @brief Function callback type for promise owner's buffer_get function override
+ */
+typedef void*(*Eina_Promise_Owner_Buffer_Get_Cb)(Eina_Promise_Owner* promise);
+
+#define EINA_FUNC_PROMISE_OWNER_BUFFER_GET(Function) ((Eina_Promise_Owner_Buffer_Get_Cb)Function)
+
+/*
+ * @brief Function callback type for promise owner's value_size_get function override
+ */
+typedef size_t(*Eina_Promise_Owner_Value_Size_Get_Cb)(Eina_Promise_Owner const* promise);
+
+#define EINA_FUNC_PROMISE_OWNER_VALUE_SIZE_GET(Function) ((Eina_Promise_Owner_Value_Size_Get_Cb)Function)
+
+/*
+ * @brief Function callback type for promise owner's promise_get function override
+ */
+typedef void*(*Eina_Promise_Owner_Promise_Get_Cb)(Eina_Promise_Owner const* promise);
+
+#define EINA_FUNC_PROMISE_OWNER_PROMISE_GET(Function) ((Eina_Promise_Owner_Promise_Get_Cb)Function)
+
+/*
+ * @brief Function callback type for promise owner's value_set function override
+ */
+typedef void(*Eina_Promise_Owner_Value_Set_Cb)(Eina_Promise_Owner* promise, void* data, Eina_Promise_Free_Cb free_fun);
+
+#define EINA_FUNC_PROMISE_OWNER_VALUE_SET(Function) ((Eina_Promise_Owner_Value_Set_Cb)Function)
+
+/*
+ * @brief Function callback type for promise owner's error_set function override
+ */
+typedef void(*Eina_Promise_Owner_Error_Set_Cb)(Eina_Promise_Owner* promise, Eina_Error error);
+
+#define EINA_FUNC_PROMISE_OWNER_ERROR_SET(Function) ((Eina_Promise_Owner_Error_Set_Cb)Function)
+
+/*
+ * @brief Function callback type for promise owner's pending function override
+ */
+typedef Eina_Bool(*Eina_Promise_Owner_Pending_Is_Cb)(Eina_Promise_Owner const* promise);
+
+#define EINA_FUNC_PROMISE_OWNER_PENDING_IS(Function) ((Eina_Promise_Owner_Pending_Is_Cb)Function)
+
+/*
+ * @brief Function callback type for promise owner's cancelled function override
+ */
+typedef Eina_Bool(*Eina_Promise_Owner_Cancelled_Is_Cb)(Eina_Promise_Owner const* promise);
+
+#define EINA_FUNC_PROMISE_OWNER_CANCELLED_IS(Function) ((Eina_Promise_Owner_Cancelled_Is_Cb)Function)
+
+/*
+ * @brief Function callback type for promise owner's progress function override
+ */
+typedef Eina_Bool(*Eina_Promise_Owner_Progress_Cb)(Eina_Promise_Owner const* promise, void* progress);
+
+#define EINA_FUNC_PROMISE_OWNER_PROGRESS(Function) ((Eina_Promise_Owner_Progress_Cb)Function)
+
+
+#define EINA_PROMISE_VERSION 1
+
+struct _Eina_Promise
+{
+ int version;
+ Eina_Promise_Then_Cb then;
+ Eina_Promise_Value_Get_Cb value_get;
+ Eina_Promise_Error_Get_Cb error_get;
+ Eina_Promise_Pending_Is_Cb pending_is;
+ Eina_Promise_Progress_Cb_Add_Cb progress_cb_add;
+ Eina_Promise_Cancel_Cb cancel;
+ Eina_Promise_Ref_Cb ref;
+ Eina_Promise_Unref_Cb unref;
+ Eina_Promise_Value_Size_Get_Cb value_size_get;
+ Eina_Promise_Buffer_Get_Cb buffer_get;
+#define EINA_MAGIC_PROMISE 0x07932A5B
+ EINA_MAGIC;
+};
+
+struct _Eina_Promise_Owner
+{
+ int version;
+ Eina_Promise_Owner_Value_Set_Cb value_set;
+ Eina_Promise_Owner_Error_Set_Cb error_set;
+ Eina_Promise_Owner_Buffer_Get_Cb buffer_get;
+ Eina_Promise_Owner_Value_Size_Get_Cb value_size_get;
+ Eina_Promise_Owner_Promise_Get_Cb promise_get;
+ Eina_Promise_Owner_Pending_Is_Cb pending_is;
+ Eina_Promise_Owner_Cancelled_Is_Cb cancelled_is;
+ Eina_Promise_Owner_Progress_Cb progress;
+#define EINA_MAGIC_PROMISE_OWNER 0x07932A5C
+ EINA_MAGIC;
+};
+
+/*
+ * @brief Appends a callback to be called when the Eina_Promise is
+ * finished.
+ *
+ * @param promise The Eina_Promise to wait for
+ * @param callback Callback to be called when Eina_Promise is finished
+ * @param data Private data passed to the callback
+ */
+EAPI void eina_promise_then(Eina_Promise* promise, Eina_Promise_Cb callback,
+ Eina_Promise_Error_Cb error_cb, void* data);
+
+/*
+ * @brief Creates a new Eina_Promise from other Eina_Promises
+ *
+ * @param promises An Eina_Iterator for all Eina_Promises
+ * @return Returns a new Eina_Promise
+ */
+EAPI Eina_Promise* eina_promise_all(Eina_Iterator* promises);
+
+/*
+ * @brief Sets value for Eina_Promise_Owner
+ *
+ * This finishes the Promise and calls all eina_promise_then callbacks
+ * that have been registered on Eina_Promise. This function must be
+ * called only once per Eina_Promise_Owner
+ *
+ * @param promise The promise owner for which to set the value
+ * @param value The pointer to the value that is going to be copied, or NULL.
+ * @param free_cb Callback function to be used to free the value copied
+ */
+EAPI void eina_promise_owner_value_set(Eina_Promise_Owner* promise, void* value, Eina_Promise_Free_Cb free_cb);
+
+/*
+ * @brief Returns the pointer to the value
+ *
+ * If the Eina_Promise is not pending anymore and has not failed,
+ * returns the pointer to the value, otherwise returns NULL.
+ *
+ * @param promise The promise for which to get the value
+ * @return Value pointer or @NULL
+ */
+EAPI void* eina_promise_value_get(Eina_Promise const* promise);
+
+/*
+ * @brief Returns the pointer to the buffer that holds the value.
+ *
+ * If the promise is finished and has not failed, this function is the
+ * same as @eina_promise_value_get. Otherwise, instead of returning
+ * NULL as @eina_promise_value_get, this function always returns the
+ * buffer pointer to where the value will be hold.
+ *
+ * @param promise The promise for which to get the buffer pointer
+ * @return Buffer pointer
+ */
+EAPI void* eina_promise_buffer_get(Eina_Promise* promise);
+
+/*
+ * @brief Returns the pointer to the buffer that holds the value.
+ *
+ * This function always return the buffer pointer independently if the
+ * value has been set or not. This is useful to instantiate the value
+ * directly in the correct buffer, without needing to copy. Then the
+ * user can @eina_promise_owner_value_set with a NULL pointer for the
+ * value to avoid copying over the buffer.
+ *
+ * @param promise The promise owner for which to get the buffer pointer
+ * @return Buffer pointer
+ */
+EAPI void* eina_promise_owner_buffer_get(Eina_Promise_Owner* promise);
+
+/*
+ * @brief Sets an error to the Eina_Promise
+ *
+ * Sets an error to the promise, finishing the promise and calling all
+ * eina_promise_then callbacks registered.
+ *
+ * @param promise The promise owner for which to set the error
+ * @param error Eina_Error to be set
+ */
+EAPI void eina_promise_owner_error_set(Eina_Promise_Owner* promise, Eina_Error error);
+
+/*
+ * @brief Gets the error of the @Eina_Promise
+ *
+ * If the promise is finished and has been set with an error, it
+ * retuns the @Eina_Error, otherwise returns 0.
+ *
+ * @param promise The promise for which to get the error
+ * @return @Eina_Error set in @Eina_Promise
+ */
+EAPI Eina_Error eina_promise_error_get(Eina_Promise const* promise);
+
+/*
+ * @brief Gets the size of the value in eina_promise_value_get.
+ *
+ * @param promise The promise for which to get the value size
+ * @return The size of the value in eina_promise_value_get.
+ */
+EAPI size_t eina_promise_value_size_get(Eina_Promise const* promise);
+
+/*
+ * @brief Returns @EINA_TRUE if the promise is still pending and
+ * still waiting on a value to be set and @EINA_FALSE otherwise.
+ *
+ * @param promise The promise for which to get the pending status
+ * @return Returns @EINA_TRUE if the promise is still pending and
+ * still waiting on a value to be set and @EINA_FALSE otherwise.
+ */
+EAPI Eina_Bool eina_promise_pending_is(Eina_Promise const* promise);
+
+/*
+ * @brief Adds a progress callback that is called by the asynchronous
+ * call to inform of any progress made.
+ *
+ * @param promise The promise for which to register a progress callback
+ * @param progress The callback to be called when progress is made
+ * @param data The private data that will be passed to the progress callback
+ */
+EAPI void eina_promise_progress_cb_add(Eina_Promise* promise, Eina_Promise_Progress_Cb progress, void* data);
+
+/*
+ * @brief Increments the reference count for the Eina_Promise
+ *
+ * @param promise The promise for which to increment its reference
+ */
+EAPI void eina_promise_ref(Eina_Promise* promise);
+
+/*
+ * @brief Cancel asynchronous operation, if possible.
+ *
+ * @param promise The promise to cancel
+ */
+EAPI void eina_promise_cancel(Eina_Promise* promise);
+
+/*
+ * @brief Gets Promise from Promise_Owner
+ *
+ * This function returns an @Eina_Promise from an
+ * @Eina_Promise_Owner. The user of the asynchronous operation can
+ * query the value from the @Eina_Promise object, while the
+ * asynchronous operation should use the @Eina_Promise_Owner object to
+ * set the value, or error, and thus finish the promise.
+ *
+ * @param promise The promise owner to get promise from.
+ * @return Return the @Eina_Promise
+ */
+EAPI Eina_Promise* eina_promise_owner_promise_get(Eina_Promise_Owner* promise);
+
+/*
+ * @brief Returns @EINA_TRUE if the promise is still pending and
+ * still waiting on a value to be set and @EINA_FALSE otherwise.
+ *
+ * @param promise The promise owner for which to get the pending status
+ * @return Returns @EINA_TRUE if the promise is still pending and
+ * still waiting on a value to be set and @EINA_FALSE otherwise.
+ */
+EAPI Eina_Bool eina_promise_owner_pending_is(Eina_Promise_Owner const* promise);
+
+/*
+ * @brief Returns @EINA_TRUE if the promise was cancelled
+ * or @EINA_FALSE otherwise.
+ *
+ * @param promise The promise owner for which to get the cancelled status
+ * @return Returns @EINA_TRUE if the promise was cancelled
+ * or @EINA_FALSE otherwise.
+ */
+EAPI Eina_Bool eina_promise_owner_cancelled_is(Eina_Promise_Owner const* promise);
+
+/*
+ * @brief Calls progress callbacks in promise, if any exists, with
+ * the data.
+ *
+ * The progress callbacks registered in @Eina_Promise must not free
+ * the progress data pointer. The data pointer ownership must be dealt
+ * by the @Eina_Promise_Owner's user.
+ *
+ * @param promise The promise for which to get the cancelled status
+ * @param data The data to be passed to progress
+ */
+EAPI void eina_promise_owner_progress(Eina_Promise_Owner const* promise, void* progress);
+
+/*
+ * @brief Decrement the reference count for the Eina_Promise.
+
+ * The Eina_Promise, if its reference count drops to zero and is not
+ * pending, will be free'd immediately.
+ *
+ * @param promise The promise for which to decrement its reference
+ */
+EAPI void eina_promise_unref(Eina_Promise* promise);
+
+/*
+ * @brief Function callback type when promise is canceled
+ */
+typedef void(*Eina_Promise_Default_Cancel_Cb)(void* data, Eina_Promise_Owner* promise);
+
+/*
+ * @brief Creates a @Eina_Promise_Owner
+ *
+ * Create a @Eina_Promise_Owner with a value of size value_size. Which
+ * is a promise with ownership of the value to be set. It is used by
+ * the asynchronous operation to set the actual value when it becomes
+ * available. The Promise itself, returned by
+ * eina_promise_owner_promise_get, represents the asynchronicity of
+ * the value itself and is used solely to get the value and to handle
+ * users of the asynchronous value. That's why Promises have a
+ * reference count while Promise Owners do not, the
+ * eina_promise_owner_value_set must be done only once, and
+ * consequently, has a unique ownership of the owner lifetime, while
+ * the promise can be queried and used by multiple users.
+ *
+ * @param value_size Size of value-type that Eina_Promise will hold
+ * @return @Eina_Promise_Owner just instantiated
+ */
+EAPI Eina_Promise_Owner* eina_promise_default_add(int value_size);
+
+/*
+ * @brief Adds a cancel callback to be called when the promise is
+ * canceled by the usuer
+ *
+ * @param promise The promise for which to register a cancel callback
+ */
+EAPI void eina_promise_owner_default_cancel_cb_add(
+ Eina_Promise_Owner* promise, Eina_Promise_Default_Cancel_Cb cancel, void* data,
+ Eina_Promise_Free_Cb free_cb);
+
+/*
+ * @brief Commands the @Eina_Promise_Owner not to call the then
+ * callbacks automatically
+ *
+ * @param promise The promise for which to register a cancel callback
+ */
+EAPI void eina_promise_owner_default_manual_then_set(Eina_Promise_Owner* promise, Eina_Bool is_manual);
+
+/*
+ * @brief Calls the @Eina_Promise_Owner's then callbacks already registered
+ *
+ * @param promise The promise for which to register a cancel callback
+ */
+EAPI void eina_promise_owner_default_call_then(Eina_Promise_Owner* promise);
+
+#endif