summaryrefslogtreecommitdiff
path: root/src/lib/eina/eina_promise.c
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2016-04-17 15:47:33 -0300
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2016-05-06 12:41:42 -0300
commit236c13df34576c51473463d9f0ef5247810e89e3 (patch)
tree758791ba77606a9097b4a492f2eaf46ccb69bd68 /src/lib/eina/eina_promise.c
parent8df2686d9023cac7420fbad0f1d0db105c344d85 (diff)
eina: Add progress notify callback feature for Promise Owners
Add a way for users of the promise owner to get notified when a promise progress is registered. Also added a convenience composition function that creates a promise which is fulfilled when another promise has a progress notification.
Diffstat (limited to '')
-rw-r--r--src/lib/eina/eina_promise.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/lib/eina/eina_promise.c b/src/lib/eina/eina_promise.c
index 459f686e84..2f83dc44d5 100644
--- a/src/lib/eina/eina_promise.c
+++ b/src/lib/eina/eina_promise.c
@@ -9,6 +9,7 @@
9typedef struct _Eina_Promise_Then_Cb _Eina_Promise_Then_Cb; 9typedef struct _Eina_Promise_Then_Cb _Eina_Promise_Then_Cb;
10typedef struct _Eina_Promise_Progress_Cb _Eina_Promise_Progress_Cb; 10typedef struct _Eina_Promise_Progress_Cb _Eina_Promise_Progress_Cb;
11typedef struct _Eina_Promise_Cancel_Cb _Eina_Promise_Cancel_Cb; 11typedef struct _Eina_Promise_Cancel_Cb _Eina_Promise_Cancel_Cb;
12typedef struct _Eina_Promise_Owner_Progress_Notify_Data _Eina_Promise_Owner_Progress_Notify_Data;
12typedef struct _Eina_Promise_Default _Eina_Promise_Default; 13typedef struct _Eina_Promise_Default _Eina_Promise_Default;
13typedef struct _Eina_Promise_Default_Owner _Eina_Promise_Default_Owner; 14typedef struct _Eina_Promise_Default_Owner _Eina_Promise_Default_Owner;
14typedef struct _Eina_Promise_Iterator _Eina_Promise_Iterator; 15typedef struct _Eina_Promise_Iterator _Eina_Promise_Iterator;
@@ -40,6 +41,15 @@ struct _Eina_Promise_Cancel_Cb
40 void* data; 41 void* data;
41}; 42};
42 43
44struct _Eina_Promise_Owner_Progress_Notify_Data
45{
46 EINA_INLIST;
47
48 Eina_Promise_Progress_Notify_Cb callback;
49 Eina_Promise_Free_Cb free_cb;
50 void* data;
51};
52
43struct _Eina_Promise_Default 53struct _Eina_Promise_Default
44{ 54{
45 Eina_Promise vtable; 55 Eina_Promise vtable;
@@ -49,6 +59,7 @@ struct _Eina_Promise_Default
49 Eina_Inlist *then_callbacks; 59 Eina_Inlist *then_callbacks;
50 Eina_Inlist *progress_callbacks; 60 Eina_Inlist *progress_callbacks;
51 Eina_Inlist *cancel_callbacks; 61 Eina_Inlist *cancel_callbacks;
62 Eina_Inlist *progress_notify_callbacks;
52 Eina_Promise_Free_Cb value_free_cb; 63 Eina_Promise_Free_Cb value_free_cb;
53 64
54 int ref; 65 int ref;
@@ -89,6 +100,21 @@ static void _eina_promise_unref(_Eina_Promise_Default* promise);
89 100
90static void _eina_promise_iterator_setup(_Eina_Promise_Iterator* iterator, Eina_Array* promises); 101static void _eina_promise_iterator_setup(_Eina_Promise_Iterator* iterator, Eina_Array* promises);
91 102
103static void _eina_promise_free_callback_list(Eina_Inlist** list, void(*free_cb)(void* node))
104{
105 struct node
106 {
107 EINA_INLIST;
108 } *node;
109 Eina_Inlist *list2;
110
111 EINA_INLIST_FOREACH_SAFE(*list, list2, node)
112 {
113 free_cb(node);
114 }
115 *list = NULL;
116}
117
92static void 118static void
93_eina_promise_then_calls(_Eina_Promise_Default_Owner* promise) 119_eina_promise_then_calls(_Eina_Promise_Default_Owner* promise)
94{ 120{
@@ -188,6 +214,7 @@ _eina_promise_then(_Eina_Promise_Default* p, Eina_Promise_Cb callback,
188{ 214{
189 _Eina_Promise_Default_Owner* promise; 215 _Eina_Promise_Default_Owner* promise;
190 _Eina_Promise_Then_Cb* cb; 216 _Eina_Promise_Then_Cb* cb;
217 _Eina_Promise_Owner_Progress_Notify_Data* notify_data;
191 218
192 promise = EINA_PROMISE_GET_OWNER(p); 219 promise = EINA_PROMISE_GET_OWNER(p);
193 220
@@ -198,6 +225,12 @@ _eina_promise_then(_Eina_Promise_Default* p, Eina_Promise_Cb callback,
198 cb->data = data; 225 cb->data = data;
199 promise->promise.then_callbacks = eina_inlist_append(promise->promise.then_callbacks, EINA_INLIST_GET(cb)); 226 promise->promise.then_callbacks = eina_inlist_append(promise->promise.then_callbacks, EINA_INLIST_GET(cb));
200 227
228 EINA_INLIST_FOREACH(promise->promise.progress_notify_callbacks, notify_data)
229 {
230 (*notify_data->callback)(notify_data->data, &promise->owner_vtable);
231 }
232 _eina_promise_free_callback_list(&promise->promise.progress_notify_callbacks, &free);
233
201 if (!promise->promise.is_first_then) 234 if (!promise->promise.is_first_then)
202 { 235 {
203 _eina_promise_ref(p); 236 _eina_promise_ref(p);
@@ -263,11 +296,19 @@ static void
263_eina_promise_progress_cb_add(_Eina_Promise_Default* promise, Eina_Promise_Progress_Cb callback, void* data) 296_eina_promise_progress_cb_add(_Eina_Promise_Default* promise, Eina_Promise_Progress_Cb callback, void* data)
264{ 297{
265 _Eina_Promise_Progress_Cb* cb; 298 _Eina_Promise_Progress_Cb* cb;
299 _Eina_Promise_Owner_Progress_Notify_Data* notify_data;
300 _Eina_Promise_Default_Owner* owner = EINA_PROMISE_GET_OWNER(promise);
266 301
267 cb = malloc(sizeof(struct _Eina_Promise_Progress_Cb)); 302 cb = malloc(sizeof(struct _Eina_Promise_Progress_Cb));
268 cb->callback = callback; 303 cb->callback = callback;
269 cb->data = data; 304 cb->data = data;
270 promise->progress_callbacks = eina_inlist_append(promise->progress_callbacks, EINA_INLIST_GET(cb)); 305 promise->progress_callbacks = eina_inlist_append(promise->progress_callbacks, EINA_INLIST_GET(cb));
306
307 EINA_INLIST_FOREACH(owner->promise.progress_notify_callbacks, notify_data)
308 {
309 (*notify_data->callback)(notify_data->data, &owner->owner_vtable);
310 }
311 _eina_promise_free_callback_list(&owner->promise.progress_notify_callbacks, &free);
271} 312}
272 313
273static void 314static void
@@ -356,6 +397,20 @@ _eina_promise_owner_progress(_Eina_Promise_Default_Owner* promise, void* data)
356 } 397 }
357} 398}
358 399
400static void
401_eina_promise_owner_progress_notify(_Eina_Promise_Default_Owner* promise, Eina_Promise_Progress_Notify_Cb notify,
402 void* data, Eina_Promise_Free_Cb free_cb)
403{
404 _Eina_Promise_Owner_Progress_Notify_Data* cb
405 = malloc(sizeof(struct _Eina_Promise_Owner_Progress_Notify_Data));
406
407 cb->callback = notify;
408 cb->free_cb = free_cb;
409 cb->data = data;
410 promise->promise.progress_notify_callbacks =
411 eina_inlist_append(promise->promise.progress_notify_callbacks, EINA_INLIST_GET(cb));
412}
413
359Eina_Promise_Owner * 414Eina_Promise_Owner *
360eina_promise_default_add(int value_size) 415eina_promise_default_add(int value_size)
361{ 416{
@@ -378,6 +433,7 @@ eina_promise_default_add(int value_size)
378 p->promise.ref = 1; 433 p->promise.ref = 1;
379 memset(&p->promise.then_callbacks, 0, sizeof(p->promise.then_callbacks)); 434 memset(&p->promise.then_callbacks, 0, sizeof(p->promise.then_callbacks));
380 memset(&p->promise.progress_callbacks, 0, sizeof(p->promise.progress_callbacks)); 435 memset(&p->promise.progress_callbacks, 0, sizeof(p->promise.progress_callbacks));
436 memset(&p->promise.progress_notify_callbacks, 0, sizeof(p->promise.progress_notify_callbacks));
381 memset(&p->promise.cancel_callbacks, 0, sizeof(p->promise.cancel_callbacks)); 437 memset(&p->promise.cancel_callbacks, 0, sizeof(p->promise.cancel_callbacks));
382 p->promise.value_size = value_size; 438 p->promise.value_size = value_size;
383 p->promise.value_free_cb = NULL; 439 p->promise.value_free_cb = NULL;
@@ -392,6 +448,7 @@ eina_promise_default_add(int value_size)
392 p->owner_vtable.pending_is = EINA_FUNC_PROMISE_OWNER_PENDING_IS(_eina_promise_owner_pending_is); 448 p->owner_vtable.pending_is = EINA_FUNC_PROMISE_OWNER_PENDING_IS(_eina_promise_owner_pending_is);
393 p->owner_vtable.cancelled_is = EINA_FUNC_PROMISE_OWNER_CANCELLED_IS(_eina_promise_owner_cancelled_is); 449 p->owner_vtable.cancelled_is = EINA_FUNC_PROMISE_OWNER_CANCELLED_IS(_eina_promise_owner_cancelled_is);
394 p->owner_vtable.progress = EINA_FUNC_PROMISE_OWNER_PROGRESS(_eina_promise_owner_progress); 450 p->owner_vtable.progress = EINA_FUNC_PROMISE_OWNER_PROGRESS(_eina_promise_owner_progress);
451 p->owner_vtable.progress_notify = EINA_FUNC_PROMISE_OWNER_PROGRESS_NOTIFY(_eina_promise_owner_progress_notify);
395 452
396 return &p->owner_vtable; 453 return &p->owner_vtable;
397} 454}
@@ -540,6 +597,36 @@ _eina_promise_iterator_setup(_Eina_Promise_Iterator* it, Eina_Array* promises_ar
540 it->data.success_iterator_impl.free = FUNC_ITERATOR_FREE(_eina_promise_iterator_free); 597 it->data.success_iterator_impl.free = FUNC_ITERATOR_FREE(_eina_promise_iterator_free);
541} 598}
542 599
600static void
601_eina_promise_progress_notify_fulfilled(void* data, Eina_Promise_Owner* p EINA_UNUSED)
602{
603 Eina_Promise_Owner* owner = data;
604 eina_promise_owner_value_set(owner, NULL, NULL);
605}
606
607EAPI Eina_Error EINA_ERROR_PROMISE_NO_NOTIFY;
608
609static void
610_eina_promise_progress_notify_failed(void* data)
611{
612 Eina_Promise_Owner* owner = data;
613 if(eina_promise_owner_pending_is(owner))
614 eina_promise_owner_error_set(owner, EINA_ERROR_PROMISE_NO_NOTIFY);
615}
616
617EAPI Eina_Promise*
618eina_promise_progress_notification(Eina_Promise_Owner* promise)
619{
620 Eina_Promise_Owner* owner;
621
622 owner = eina_promise_default_add(0);
623
624 eina_promise_owner_progress_notify(promise, &_eina_promise_progress_notify_fulfilled, owner,
625 &_eina_promise_progress_notify_failed);
626
627 return eina_promise_owner_promise_get(owner);
628}
629
543// API functions 630// API functions
544EAPI void 631EAPI void
545eina_promise_then(Eina_Promise* promise, Eina_Promise_Cb callback, 632eina_promise_then(Eina_Promise* promise, Eina_Promise_Cb callback,
@@ -643,3 +730,17 @@ eina_promise_owner_progress(Eina_Promise_Owner const* promise, void* progress)
643{ 730{
644 promise->progress(promise, progress); 731 promise->progress(promise, progress);
645} 732}
733
734EAPI void
735eina_promise_owner_progress_notify(Eina_Promise_Owner* promise, Eina_Promise_Progress_Notify_Cb progress_cb,
736 void* data, Eina_Promise_Free_Cb free_cb)
737{
738 promise->progress_notify(promise, progress_cb, data, free_cb);
739}
740
741static const char EINA_ERROR_PROMISE_NO_NOTIFY_STR[] = "Out of memory";
742
743void _eina_promise_init()
744{
745 EINA_ERROR_PROMISE_NO_NOTIFY = eina_error_msg_static_register(EINA_ERROR_PROMISE_NO_NOTIFY_STR);
746}