eo: make efl_future_then have a data pointer in addition of the object pointer.

Summary:
In the case when you have multiple future in flight related to one object, you
couldn't use the previous version of efl_future_then. Now all function calls
take a void* pointer that allow multiple future to have their private data
request data accessible in all the callback.

This should not break released API as Eo.h is not released yet and so
was efl_future_Eina_FutureXXX_then.

Depends on D7332

Reviewers: felipealmeida, segfaultxavi, vitor.sousa, SanghyeonLee, bu5hm4n

Reviewed By: segfaultxavi

Subscribers: #reviewers, #committers

Tags: #efl

Maniphest Tasks: T7472

Differential Revision: https://phab.enlightenment.org/D7379
This commit is contained in:
Cedric BAIL 2018-12-07 12:15:16 +01:00 committed by Xavi Artigas
parent e6f66e56fd
commit 33c00de365
12 changed files with 64 additions and 57 deletions

View File

@ -72,7 +72,7 @@ static void _efl_io_copier_read(Eo *o, Efl_Io_Copier_Data *pd);
while (0)
static Eina_Value
_efl_io_copier_timeout_inactivity_cb(Eo *o, const Eina_Value v)
_efl_io_copier_timeout_inactivity_cb(Eo *o, void *data EINA_UNUSED, const Eina_Value v)
{
Eina_Error err = ETIMEDOUT;
efl_event_callback_call(o, EFL_IO_COPIER_EVENT_ERROR, &err);
@ -86,12 +86,12 @@ _efl_io_copier_timeout_inactivity_reschedule(Eo *o, Efl_Io_Copier_Data *pd)
if (pd->timeout_inactivity <= 0.0) return;
efl_future_then(o, efl_loop_timeout(efl_loop_get(o), pd->timeout_inactivity),
.success = _efl_io_copier_timeout_inactivity_cb,
.storage = &pd->inactivity_timer);
.success = _efl_io_copier_timeout_inactivity_cb,
.storage = &pd->inactivity_timer);
}
static Eina_Value
_efl_io_copier_job(Eo *o, const Eina_Value v)
_efl_io_copier_job(Eo *o, void *data EINA_UNUSED, const Eina_Value v)
{
Efl_Io_Copier_Data *pd = efl_data_scope_get(o, MY_CLASS);
uint64_t old_read = pd->progress.read;
@ -138,14 +138,14 @@ _efl_io_copier_job_schedule(Eo *o, Efl_Io_Copier_Data *pd)
{
Eina_Value v = EINA_VALUE_EMPTY;
v = _efl_io_copier_job(o, v);
v = _efl_io_copier_job(o, NULL, v);
eina_value_flush(&v);
}
else
{
efl_future_then(o, efl_loop_job(efl_loop_get(o)),
.success = _efl_io_copier_job,
.storage = &pd->job);
.success = _efl_io_copier_job,
.storage = &pd->job);
}
}

View File

@ -1717,7 +1717,7 @@ _efl_net_dialer_http_efl_io_writer_can_write_set(Eo *o, Efl_Net_Dialer_Http_Data
efl_event_callback_call(o, EFL_IO_WRITER_EVENT_CAN_WRITE_CHANGED, NULL);
}
static Eina_Value _efl_net_dialer_http_pending_close(Eo *o, Eina_Value value);
static Eina_Value _efl_net_dialer_http_pending_close(Eo *o, void *data, Eina_Value value);
EOLIAN static Eina_Error
_efl_net_dialer_http_efl_io_closer_close(Eo *o, Efl_Net_Dialer_Http_Data *pd)
@ -1733,8 +1733,8 @@ _efl_net_dialer_http_efl_io_closer_close(Eo *o, Efl_Net_Dialer_Http_Data *pd)
if ((!pd->pending_close) && (pd->easy))
{
efl_future_then(o, efl_loop_job(efl_loop_get(o)),
.success = _efl_net_dialer_http_pending_close,
.storage = &pd->pending_close);
.success = _efl_net_dialer_http_pending_close,
.storage = &pd->pending_close);
DBG("dialer=%p closed from CURL callback, schedule close job=%p", o, pd->pending_close);
}
return 0;
@ -1766,7 +1766,7 @@ _efl_net_dialer_http_efl_io_closer_close(Eo *o, Efl_Net_Dialer_Http_Data *pd)
}
static Eina_Value
_efl_net_dialer_http_pending_close(Eo *o, const Eina_Value value EINA_UNUSED)
_efl_net_dialer_http_pending_close(Eo *o, void *data EINA_UNUSED, const Eina_Value value EINA_UNUSED)
{
Efl_Net_Dialer_Http_Data *pd = efl_data_scope_get(o, MY_CLASS);

View File

@ -128,7 +128,7 @@ _efl_net_dialer_ssl_ssl_context_get(const Eo *o EINA_UNUSED, Efl_Net_Dialer_Ssl_
}
static Eina_Value
_efl_net_dialer_ssl_connect_timeout(Eo *o, const Eina_Value v)
_efl_net_dialer_ssl_connect_timeout(Eo *o, void *data EINA_UNUSED, const Eina_Value v)
{
Eina_Error err = ETIMEDOUT;
@ -143,8 +143,8 @@ static void
_timeout_schedule(Eo *o, Efl_Net_Dialer_Ssl_Data *pd, double timeout)
{
efl_future_then(o, efl_loop_timeout(efl_loop_get(o), timeout),
.success = _efl_net_dialer_ssl_connect_timeout,
.storage = &pd->connect_timeout);
.success = _efl_net_dialer_ssl_connect_timeout,
.storage = &pd->connect_timeout);
}
EOLIAN static Eina_Error

View File

@ -90,7 +90,7 @@ _efl_net_dialer_tcp_efl_object_destructor(Eo *o, Efl_Net_Dialer_Tcp_Data *pd)
}
static Eina_Value
_efl_net_dialer_tcp_connect_timeout(Eo *o, const Eina_Value v)
_efl_net_dialer_tcp_connect_timeout(Eo *o, void *data EINA_UNUSED, const Eina_Value v)
{
Efl_Net_Dialer_Tcp_Data *pd = efl_data_scope_get(o, MY_CLASS);
Eina_Error err = ETIMEDOUT;
@ -108,8 +108,8 @@ static void
_timeout_schedule(Eo *o, Efl_Net_Dialer_Tcp_Data *pd)
{
efl_future_then(o, efl_loop_timeout(efl_loop_get(o), pd->timeout_dial),
.success = _efl_net_dialer_tcp_connect_timeout,
.storage = &pd->connect.timeout);
.success = _efl_net_dialer_tcp_connect_timeout,
.storage = &pd->connect.timeout);
}
static void

View File

@ -82,7 +82,7 @@ _efl_net_dialer_udp_efl_object_destructor(Eo *o, Efl_Net_Dialer_Udp_Data *pd)
}
static Eina_Value
_efl_net_dialer_udp_resolver_timeout(Eo *o, const Eina_Value v)
_efl_net_dialer_udp_resolver_timeout(Eo *o, void *data EINA_UNUSED, const Eina_Value v)
{
Efl_Net_Dialer_Udp_Data *pd = efl_data_scope_get(o, MY_CLASS);
Eina_Error err = ETIMEDOUT;
@ -104,8 +104,8 @@ static void
_timeout_schedule(Eo *o, Efl_Net_Dialer_Udp_Data *pd)
{
efl_future_then(o, efl_loop_timeout(efl_loop_get(o), pd->timeout_dial),
.success = _efl_net_dialer_udp_resolver_timeout,
.storage = &pd->resolver.timeout);
.success = _efl_net_dialer_udp_resolver_timeout,
.storage = &pd->resolver.timeout);
}
static Eina_Error

View File

@ -71,7 +71,7 @@ _efl_net_dialer_unix_efl_object_destructor(Eo *o, Efl_Net_Dialer_Unix_Data *pd)
}
static Eina_Value
_efl_net_dialer_unix_connect_timeout(Eo *o, const Eina_Value v)
_efl_net_dialer_unix_connect_timeout(Eo *o, void *data EINA_UNUSED, const Eina_Value v)
{
Efl_Net_Dialer_Unix_Data *pd = efl_data_scope_get(o, MY_CLASS);
Eina_Error err = ETIMEDOUT;
@ -130,8 +130,8 @@ static void
_timeout_schedule(Eo *o, Efl_Net_Dialer_Unix_Data *pd)
{
efl_future_then(o, efl_loop_timeout(efl_loop_get(o), pd->timeout_dial),
.success = _efl_net_dialer_unix_connect_timeout,
.storage = &pd->connect.timeout);
.success = _efl_net_dialer_unix_connect_timeout,
.storage = &pd->connect.timeout);
}
EOLIAN static Eina_Error

View File

@ -735,7 +735,7 @@ _efl_net_dialer_websocket_job_receive(Eo *o, Efl_Net_Dialer_Websocket_Data *pd)
}
static Eina_Value
_efl_net_dialer_websocket_job(Eo *o, const Eina_Value v)
_efl_net_dialer_websocket_job(Eo *o, void *data EINA_UNUSED, const Eina_Value v)
{
Efl_Net_Dialer_Websocket_Data *pd = efl_data_scope_get(o, MY_CLASS);
@ -765,8 +765,8 @@ _efl_net_dialer_websocket_job_schedule(Eo *o, Efl_Net_Dialer_Websocket_Data *pd)
if (!loop) return;
efl_future_then(o, efl_loop_job(loop),
.success = _efl_net_dialer_websocket_job,
.storage = &pd->job);
.success = _efl_net_dialer_websocket_job,
.storage = &pd->job);
}
static void
@ -1486,7 +1486,7 @@ _efl_net_dialer_websocket_binary_send(Eo *o, Efl_Net_Dialer_Websocket_Data *pd,
}
static Eina_Value
_efl_net_dialer_websocket_close_request_timeout(Eo *o, const Eina_Value v)
_efl_net_dialer_websocket_close_request_timeout(Eo *o, void *data EINA_UNUSED, const Eina_Value v)
{
DBG("server did not close the TCP socket, timeout");
efl_event_callback_call(o, EFL_IO_CLOSER_EVENT_CLOSED, NULL);
@ -1505,8 +1505,8 @@ _efl_net_dialer_websocket_close_request(Eo *o, Efl_Net_Dialer_Websocket_Data *pd
eina_future_cancel(pd->close_timeout);
efl_future_then(o, efl_loop_timeout(efl_loop_get(o), 2.0),
.success = _efl_net_dialer_websocket_close_request_timeout,
.storage = &pd->close_timeout);
.success = _efl_net_dialer_websocket_close_request_timeout,
.storage = &pd->close_timeout);
efl_io_writer_can_write_set(o, EINA_FALSE);

View File

@ -312,7 +312,7 @@ _efl_net_server_windows_efl_net_server_address_get(const Eo *o EINA_UNUSED, Efl_
}
static Eina_Value
_efl_net_server_windows_pending_announce_job(Eo *o, const Eina_Value v)
_efl_net_server_windows_pending_announce_job(Eo *o, void *data EINA_UNUSED, const Eina_Value v)
{
Efl_Net_Server_Windows_Data *pd = efl_data_scope_get(o, MY_CLASS);
Eo *client;
@ -339,8 +339,8 @@ _efl_net_server_windows_pending_announce_job_schedule(Eo *o, Efl_Net_Server_Wind
loop = efl_loop_get(o);
if (!loop) return;
efl_future_then(o, efl_loop_job(loop),
.success = _efl_net_server_windows_pending_announce_job,
.storage = &pd->pending_announcer_job);
.success = _efl_net_server_windows_pending_announce_job,
.storage = &pd->pending_announcer_job);
}
EOLIAN static void

View File

@ -1,38 +1,38 @@
#ifndef __EINA_PROMISE_PRIVATE_H__
#define __EINA_PROMISE_PRIVATE_H__
#define ERROR_DISPATCH(_cbs, _ret, _value, _data) \
#define ERROR_DISPATCH(_cbs, _ret, _value, ...) \
do { \
Eina_Error ERROR_DISPATCH__err; \
if (!(_cbs)->error) (_ret) = (_value); \
else \
{ \
eina_value_get(&(_value), &ERROR_DISPATCH__err); \
(_ret) = (_cbs)->error((_data), ERROR_DISPATCH__err); \
(_ret) = (_cbs)->error(__VA_ARGS__, ERROR_DISPATCH__err); \
} \
} while (0)
#define EASY_FUTURE_DISPATCH(_ret, _value, _dead_future, _cbs, _data) \
#define EASY_FUTURE_DISPATCH(_ret, _value, _dead_future, _cbs, ...) \
do { \
if ((_value).type == EINA_VALUE_TYPE_ERROR) ERROR_DISPATCH((_cbs), (_ret), (_value), (_data)); \
if ((_value).type == EINA_VALUE_TYPE_ERROR) ERROR_DISPATCH((_cbs), (_ret), (_value), __VA_ARGS__); \
else \
{ \
if ((!(_cbs)->success_type) || ((_cbs)->success_type && (_value).type == (_cbs)->success_type)) \
{ \
if (!(_cbs)->success) (_ret) = (_value); /* pass thru */ \
else (_ret) = (_cbs)->success((_data), (_value)); \
else (_ret) = (_cbs)->success(__VA_ARGS__, (_value)); \
} \
else \
{ \
Eina_Value EASY_FUTURE_DISPATCH__err = EINA_VALUE_EMPTY; \
ERR("Future %p, success cb: %p data: %p, expected success_type %p (%s), got %p (%s)", \
_dead_future, (_cbs)->success, (_data), \
ERR("Future %p, success cb: %p, expected success_type %p (%s), got %p (%s)", \
_dead_future, (_cbs)->success, \
(_cbs)->success_type, eina_value_type_name_get((_cbs)->success_type), \
(_value).type, (_value).type ? eina_value_type_name_get((_value).type) : NULL); \
if (eina_value_setup(&EASY_FUTURE_DISPATCH__err, EINA_VALUE_TYPE_ERROR)) eina_value_set(&EASY_FUTURE_DISPATCH__err, EINVAL); \
ERROR_DISPATCH((_cbs), (_ret), EASY_FUTURE_DISPATCH__err, (_data)); \
ERROR_DISPATCH((_cbs), (_ret), EASY_FUTURE_DISPATCH__err, __VA_ARGS__); \
} \
} \
if ((_cbs)->free) (_cbs)->free((_data), _dead_future); \
if ((_cbs)->free) (_cbs)->free(__VA_ARGS__, _dead_future); \
} while(0)
#endif

View File

@ -379,7 +379,7 @@ typedef struct _Efl_Future_Cb_Desc {
* using @c eina_value_flush() once they are unused (no more future or futures
* returned a new value).
*/
Eina_Value (*success)(Eo *o, const Eina_Value value);
Eina_Value (*success)(Eo *o, void *data, const Eina_Value value);
/**
* Called on error (value.type is @c EINA_VALUE_TYPE_ERROR).
*
@ -417,7 +417,7 @@ typedef struct _Efl_Future_Cb_Desc {
* using @c eina_value_flush() once they are unused (no more future or futures
* returned a new value).
*/
Eina_Value (*error)(Eo *o, Eina_Error error);
Eina_Value (*error)(Eo *o, void *data, Eina_Error error);
/**
* Called on @b all situations to notify future destruction.
*
@ -431,7 +431,7 @@ typedef struct _Efl_Future_Cb_Desc {
* @param o The object used to create the link in efl_future_cb_from_desc() or efl_future_chain_array().
* @param dead_future The future that's been freed.
*/
void (*free)(Eo *o, const Eina_Future *dead_future);
void (*free)(Eo *o, void *data, const Eina_Future *dead_future);
/**
* If provided, then @c success will only be called if the value type matches the given pointer.
*
@ -439,6 +439,13 @@ typedef struct _Efl_Future_Cb_Desc {
* then it will be propagated to the next future in the chain.
*/
const Eina_Value_Type *success_type;
/**
* Context data given to every callback.
*
* This must be freed @b only by @c free callback as it's called from every case,
* otherwise it may lead to memory leaks.
*/
const void *data;
/**
* This is used by Eo to cancel pending futures in case
* an Eo object is deleted. It can be @c NULL.
@ -476,7 +483,7 @@ typedef struct _Efl_Future_Cb_Desc {
* }
*
* static Eina_Value
* _file_ok(Eo *o EINA_UNUSED, const Eina_Value value)
* _file_ok(Eo *o EINA_UNUSED, void *data EINA_UNUSED, const Eina_Value value)
* {
* const char *data;
* //There's no need to check the value type since EO infra already has done so.
@ -487,7 +494,7 @@ typedef struct _Efl_Future_Cb_Desc {
* }
*
* static Eina_Value
* _file_err(Eo *o EINA_UNUSED, Eina_Error error)
* _file_err(Eo *o EINA_UNUSED, void *data EINA_UNUSED, Eina_Error error)
* {
* //In case the downloader is deleted before the future is resolved, the future will be canceled thus this callback will be called.
* fprintf(stderr, "Could not download the file. Reason: %s\n", eina_error_msg_get(error));
@ -495,7 +502,7 @@ typedef struct _Efl_Future_Cb_Desc {
* }
*
* static void
* _downlader_free(Eo *o, const Eina_Future *dead_future EINA_UNUSED)
* _downlader_free(Eo *o, void *data EINA_UNUSED, const Eina_Future *dead_future EINA_UNUSED)
* {
* Ecore_Timer *t = efl_key_data_get(o, "timer");
* //The download finished before the timer expired. Cancel it...

View File

@ -2080,7 +2080,7 @@ _efl_future_cb(void *data, const Eina_Value value, const Eina_Future *dead_futur
pd->pending_futures = eina_inlist_remove(pd->pending_futures,
EINA_INLIST_GET(pending));
efl_ref(o);
EASY_FUTURE_DISPATCH(ret, value, dead_future, &pending->desc, (void*) o);
EASY_FUTURE_DISPATCH(ret, value, dead_future, &pending->desc, (void*) o, (void*) pending->desc.data);
efl_unref(o);
_efl_pending_future_free(pending);
@ -2147,10 +2147,10 @@ efl_future_chain_array(Eo *obj,
{
if (descs[i].error)
{
Eina_Value r = descs[i].error(obj, ENOMEM);
Eina_Value r = descs[i].error(obj, (void*) descs[i].data, ENOMEM);
eina_value_flush(&r);
}
if (descs[i].free) descs[i].free(obj, NULL);
if (descs[i].free) descs[i].free(obj, (void*) descs[i].data, NULL);
}
return NULL;
}

View File

@ -808,7 +808,7 @@ EFL_START_TEST(efl_test_promise_future_race)
EFL_END_TEST
static Eina_Value
_eo_future1_ok(Eo *eo EINA_UNUSED, const Eina_Value v)
_eo_future1_ok(Eo *eo EINA_UNUSED, void *data EINA_UNUSED, const Eina_Value v)
{
const char *number;
@ -819,14 +819,14 @@ _eo_future1_ok(Eo *eo EINA_UNUSED, const Eina_Value v)
}
static Eina_Value
_eo_future1_err(Eo *eo EINA_UNUSED, Eina_Error err EINA_UNUSED)
_eo_future1_err(Eo *eo EINA_UNUSED, void *data EINA_UNUSED, Eina_Error err EINA_UNUSED)
{
//Should not happen
fail_if(EINA_TRUE);
}
static Eina_Value
_eo_future2_ok(Eo *eo EINA_UNUSED, const Eina_Value v)
_eo_future2_ok(Eo *eo EINA_UNUSED, void *data EINA_UNUSED, const Eina_Value v)
{
//Should not happen
fail_if(EINA_TRUE);
@ -834,7 +834,7 @@ _eo_future2_ok(Eo *eo EINA_UNUSED, const Eina_Value v)
}
static Eina_Value
_eo_future2_err(Eo *eo EINA_UNUSED, Eina_Error err)
_eo_future2_err(Eo *eo EINA_UNUSED, void *data EINA_UNUSED, Eina_Error err)
{
Eina_Value v;
@ -845,7 +845,7 @@ _eo_future2_err(Eo *eo EINA_UNUSED, Eina_Error err)
}
static void
_eo_future_free(Eo *eo, const Eina_Future *dead EINA_UNUSED)
_eo_future_free(Eo *eo, void *data EINA_UNUSED, const Eina_Future *dead EINA_UNUSED)
{
int *free_called = efl_key_data_get(eo, "free_called");
(*free_called)++;
@ -890,7 +890,7 @@ EFL_START_TEST(efl_test_promise_eo)
EFL_END_TEST
static Eina_Value
_eo_future_link_success(Eo *eo EINA_UNUSED, const Eina_Value v)
_eo_future_link_success(Eo *eo EINA_UNUSED, void *data EINA_UNUSED, const Eina_Value v)
{
//This should never happen
fail_if(EINA_TRUE);
@ -898,7 +898,7 @@ _eo_future_link_success(Eo *eo EINA_UNUSED, const Eina_Value v)
}
static Eina_Value
_eo_future_link_err(Eo *eo, Eina_Error err)
_eo_future_link_err(Eo *eo, void *data EINA_UNUSED, Eina_Error err)
{
int *err_called = efl_key_data_get(eo, "err_called");
Eina_Value v;