so the MAIN loop is actually an efl.app object. which inherits from
efl.loop. the idea is that other loops in threads will not be efl.app
objects. thread on the creator side return an efl.thread object.
inside the thread, like the mainloop, there is now an efl.appthread
object that is for all non-main-loop threads.
every thread (main loop or child) when it spawns a thread is the
parent. there are i/o pipes from parnet to child and back. so parents
are generally expected to, if they want to talk to child thread, so
use the efl.io interfaces on efl.thread, and the main loop's elf.app
class allows you to talk to stdio back to the parent process like the
efl.appthread does the same using the efl.io interfaces to talk to its
parent app or appthread. it's symmetrical
no tests here - sure. i have been holding off on tests until things
settle. that's why i haven't done them yet. those will come back in a
subsequent commit
for really quick examples on using this see:
https://phab.enlightenment.org/F2983118https://phab.enlightenment.org/F2983142
they are just my test code for this.
Please see this design document:
https://phab.enlightenment.org/w/efl-loops-threads/
also eina_procmis was not threadsafe so cannto use loops in different
threads at all until this was made safe. needed to disable the old
ecore_event using code in for ecore futures and create a new efl loop
message future and handler instead ... but now a quick experiment with
multiple loops in 10 threads plus mainloop have timers at least work.
i need to test more like fd handlers etc etc. but it's a step.
Efl.Future is an EO object which means even cancelling Efl.Future
objects requires EO. So this should be done before shutting down EO,
otherwise everything fails badly.
I believe Efl.Future is going to disappear soon, but the problem will
remain: if any promise/future uses EO or anything else outside of Eina
(so, basically anything) then it needs to be canceled before shutting
down the above layers. This is the same situation as with ecore events,
for which we've introduced ecore_event_type_flush.
Ping @cedric
This is a helper that creates a promise, then a future and immediately
resolves the promise, this will let the future be dispatched as usual,
from a clean main loop context.
Coverity reports that eina_safepointer_get returns a NULL promise here
(checked 20 out of 21 times). As eina_safepointer_get can return NULL,
we should check the validity of 'promise' here before trying to
derefernce it later.
Fixes Coverity CID1356625
@fix
Signed-off-by: Chris Michael <cp.michael@samsung.com>
Cancelling a promise will fulfill it but won't actually free the memory. This
memory is under custody of the owner, who must either call value_set or
error_set to finish it.
Now when dealing with pointer types, we will not get pointer to
pointer semantics in callbacks and eina_promise_owner_value_set
for Eina_Promise.
It will work as expected:
Eina_Promise_Owner* promise = eina_promise_add();
void* p = malloc(sizeof(T));
eina_promise_owner_value_set(promise, p, &free);
The call to eina_promise_then steals the first ref'count, so it is
possible that the promise is freed after the eina_promise_then,
so we need to eina_promise_ref before eina_promise_then.
We do properly unref promise while calling all the then callback. There
is no need to check it a second time (which actually lead to a 100%
bad access).
T3759
Eina_Error is not passed by pointer anymore, which could cause invalid
pointer access in promise compositions (all and race).
Also added Eina_Promise* to prototypes.
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.
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.
Fix value_set and error_set signatures which were receiving a
owner. They actually receive the promise and not the owner, this
caused wrong access to memory and were not visible by warnings because
the functions are casted.
This problem caused errors in which it seemed that promise had
actually error'ed when questioned it.
Add a promise object that will allows Eolian interface to include promises
as a way to have asynchronous value return and composibility.
To understand better, let see the coming usage in a .eo file:
class Foo {
methods {
bar {
params {
@inout promise: Promise<int>;
}
}
}
}
Which will create the following API interface:
void foo_bar(Eo* obj, Eina_Promise** promise);
and the equivalent declaration for implementation.
However, the API function will instantiate the Promise for the user
and the implementer of the class automatically. So the user of this
function will treat it as a @out parameter, while the developer of the
function will treat it like a @inout parameter.
So, the user will use this function like this:
Eina_Promise* promise; // No need to instantiate
foo_bar(obj, &promise);
eina_promise_then(promise, callback);
Signed-off-by: Cedric Bail <cedric@osg.samsung.com>