forked from enlightenment/efl
eina: Add eina_promise_race composition function
Added eina_promise_race function that composes multiple promise objects into a new promise which is fulfilled when one of the promises are fulfilled, or fails when one of the promises have failed.
This commit is contained in:
parent
d734cd4cad
commit
1c5ce16565
|
@ -104,6 +104,19 @@ struct _Eina_Promise_Iterator
|
|||
} data;
|
||||
};
|
||||
|
||||
typedef struct _Eina_Promise_Race_Value_Type _Eina_Promise_Race_Value_Type;
|
||||
struct _Eina_Promise_Race_Value_Type
|
||||
{
|
||||
void* value;
|
||||
unsigned int promise_index;
|
||||
unsigned int num_promises;
|
||||
struct _Eina_Promise_Race_Information
|
||||
{
|
||||
Eina_Promise* promise;
|
||||
_Eina_Promise_Default_Owner* self;
|
||||
} promises[];
|
||||
};
|
||||
|
||||
static void _eina_promise_free_progress_callback_node(void* node)
|
||||
{
|
||||
_Eina_Promise_Progress_Cb *progress_cb = node;
|
||||
|
@ -669,6 +682,96 @@ eina_promise_progress_notification(Eina_Promise_Owner* promise)
|
|||
return eina_promise_owner_promise_get(owner);
|
||||
}
|
||||
|
||||
// Race implementation
|
||||
static void
|
||||
_eina_promise_race_free(_Eina_Promise_Race_Value_Type* value)
|
||||
{
|
||||
unsigned i = 0;
|
||||
for (;i != value->num_promises; ++i)
|
||||
{
|
||||
eina_promise_unref(value->promises[i].promise);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_eina_promise_race_compose_then_cb(struct _Eina_Promise_Race_Information* info, void* value EINA_UNUSED)
|
||||
{
|
||||
_Eina_Promise_Default_Owner* race_promise;
|
||||
_Eina_Promise_Race_Value_Type *race_value;
|
||||
|
||||
race_promise = info->self;
|
||||
race_value = (_Eina_Promise_Race_Value_Type*)race_promise->value;
|
||||
|
||||
if (!race_promise->promise.has_finished)
|
||||
{
|
||||
race_value->value = value;
|
||||
race_value->promise_index = info - &race_value->promises[0];
|
||||
_eina_promise_finish(race_promise);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_eina_promise_race_compose_error_then_cb(struct _Eina_Promise_Race_Information* info, Eina_Error const* error)
|
||||
{
|
||||
_Eina_Promise_Default_Owner* race_promise;
|
||||
_Eina_Promise_Race_Value_Type *race_value;
|
||||
|
||||
race_promise = info->self;
|
||||
race_value = (_Eina_Promise_Race_Value_Type*)race_promise->value;
|
||||
|
||||
if (!race_promise->promise.has_finished)
|
||||
{
|
||||
race_value->promise_index = info - &race_value->promises[0];
|
||||
eina_promise_owner_error_set(&race_promise->owner_vtable, *error);
|
||||
}
|
||||
}
|
||||
|
||||
Eina_Promise *
|
||||
eina_promise_race(Eina_Iterator* it)
|
||||
{
|
||||
_Eina_Promise_Default_Owner *promise;
|
||||
Eina_Promise* current;
|
||||
Eina_Array* promises;
|
||||
struct _Eina_Promise_Race_Information *cur_promise, *last;
|
||||
_Eina_Promise_Race_Value_Type *value;
|
||||
int num_promises;
|
||||
|
||||
promises = eina_array_new(20);
|
||||
|
||||
EINA_ITERATOR_FOREACH(it, current)
|
||||
{
|
||||
eina_array_push(promises, current);
|
||||
}
|
||||
|
||||
eina_iterator_free(it);
|
||||
|
||||
num_promises = eina_array_count_get(promises);
|
||||
promise = (_Eina_Promise_Default_Owner*)
|
||||
eina_promise_default_add(sizeof(_Eina_Promise_Race_Value_Type) +
|
||||
sizeof(struct _Eina_Promise_Race_Information*)*num_promises);
|
||||
value = eina_promise_owner_buffer_get((Eina_Promise_Owner*)promise);
|
||||
value->value = NULL;
|
||||
value->promise_index = -1;
|
||||
value->num_promises = num_promises;
|
||||
|
||||
promise->promise.value_free_cb = (Eina_Promise_Free_Cb)&_eina_promise_race_free;
|
||||
|
||||
cur_promise = value->promises;
|
||||
last = value->promises + value->num_promises;
|
||||
for (int i = 0;cur_promise != last; ++cur_promise, ++i)
|
||||
{
|
||||
cur_promise->promise = eina_array_data_get(promises, i);
|
||||
cur_promise->self = promise;
|
||||
eina_promise_then(cur_promise->promise, (Eina_Promise_Cb)&_eina_promise_race_compose_then_cb,
|
||||
(Eina_Promise_Error_Cb)&_eina_promise_race_compose_error_then_cb, cur_promise);
|
||||
eina_promise_ref(cur_promise->promise); // We need to keep the value alive until this promise is freed
|
||||
}
|
||||
|
||||
eina_array_free(promises);
|
||||
|
||||
return &promise->promise.vtable;
|
||||
}
|
||||
|
||||
// API functions
|
||||
EAPI void
|
||||
eina_promise_then(Eina_Promise* promise, Eina_Promise_Cb callback,
|
||||
|
|
|
@ -224,13 +224,29 @@ 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
|
||||
* @brief Creates a new @Eina_Promise from other @Eina_Promise's
|
||||
*
|
||||
* The new @Eina_Promise is fulfilled when all promises
|
||||
* have also been fulfilled with success or when the
|
||||
* first one fails
|
||||
*
|
||||
* @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 Creates a new @Eina_Promise from other @Eina_Promises
|
||||
*
|
||||
* The new @Eina_Promise is fulfilled when the first promise
|
||||
* has been fulfilled with success or when the
|
||||
* first one fails
|
||||
*
|
||||
* @param promises An Eina_Iterator for all Eina_Promises
|
||||
* @return Returns a new Eina_Promise
|
||||
*/
|
||||
EAPI Eina_Promise* eina_promise_race(Eina_Iterator* promises);
|
||||
|
||||
/*
|
||||
* @brief Creates a new @Eina_Promise from another @Eina_Promise_Owner which
|
||||
* is fulfilled when @promise has a progress callback registered
|
||||
|
|
|
@ -336,6 +336,28 @@ START_TEST(eina_test_promise_ignored)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(eina_test_promise_race)
|
||||
{
|
||||
Eina_Promise_Owner* promise_owner;
|
||||
Eina_Promise* first[2] = {NULL, NULL};
|
||||
Eina_Promise* promise;
|
||||
Eina_Bool ran = EINA_FALSE;
|
||||
|
||||
eina_init();
|
||||
|
||||
promise_owner = eina_promise_default_add(0);
|
||||
first[0] = eina_promise_owner_promise_get(promise_owner);
|
||||
promise = eina_promise_race(eina_carray_iterator_new((void**)&first[0]));
|
||||
|
||||
eina_promise_then(promise, &_eina_test_promise_cb, NULL, &ran);
|
||||
eina_promise_owner_value_set(promise_owner, NULL, NULL);
|
||||
|
||||
ck_assert(ran == EINA_TRUE);
|
||||
|
||||
eina_shutdown();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void
|
||||
eina_test_promise(TCase *tc)
|
||||
{
|
||||
|
@ -350,4 +372,5 @@ eina_test_promise(TCase *tc)
|
|||
tcase_add_test(tc, eina_test_promise_progress_notify2);
|
||||
tcase_add_test(tc, eina_test_promise_progress_notify3);
|
||||
tcase_add_test(tc, eina_test_promise_ignored);
|
||||
tcase_add_test(tc, eina_test_promise_race);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue