forked from enlightenment/efl
Coroutines are cooperative tasks, in the sense that the caller will stop until the target function runs. The target function must either yield control back to the caller (main thread), or exit. There is no preemption of the two tasks, thus no special care needs to be taken regarding shared data. If the target coroutine yields control using eina_coro_yield(), then it will be paused until it's manually ran again by caller (main thread), which is executed with eina_coro_run(). Another common usage is to await for another task to be completed, this can be done by waiting for a future to be resolved. It will automatically yield and inform the caller of the future so it can schedule properly instead of keep calling the task. Waiting for many tasks can be achieved by using eina_future_all() or eina_future_race(). This is done with eina_coro_await(). Due portability it was implemented using Eina_Thread, Eina_Lock and Eina_Condition. Regular threads will ensure that the state is fully preserved (stack, registers) in a platform independent way. Each thread will wait on its own turn using the Eina_Lock and Eina_Condition, thus it's guaranteed that only one is being executed at the same time. The API is small and should allow different implementations shall we need them, like manually saving the stack and registers, then restoring those -- problem is doing that in a portable way, setjmp()/longjmp() won't save the stack, makecontext()/swapcontext() doesn't work right on MacOS... Hooks can be used to be informed when the main routine exits and then enters, likewise when the coroutine enters and exits. These will be used, for instance, to automatically get, adopt and return Efl_Domain_Data needed to make Efl_Object work in such environment. The flow is simple: - main exit (called from main thread) - coroutine enter (called from worker thread) - coroutine exit (called from worker thread) - main enter (called from main thead) Performance may not be optimal, however this is meant as easy-to-use and it shouldn't be an issue in real life. It will be mostly exposed in two layers: - Efl.Loop.coro: will wrap eina_coro and and schedule using its main loop instance, returns an Eina_Future so it's easy to chain. - Eina_Promise/Eina_Future "async/await"-like behavior: will allow to write "synchronous" code that can wait for promises to be resolved. When eina_future_await(), it will actually register a new Eina_Future in the chain and then eina_coro_yield(). Once the future is called back it will call eina_coro_run() and allow the coroutine to resume. This is done on top fo eina_coro_await(). |
||
---|---|---|
.. | ||
.gitignore | ||
CMakeLists.txt | ||
cxx_compile_test.cxx | ||
eina_suite.c | ||
eina_suite.h | ||
eina_suite.x | ||
eina_test_abi.c | ||
eina_test_accessor.c | ||
eina_test_array.c | ||
eina_test_barrier.c | ||
eina_test_benchmark.c | ||
eina_test_bezier.c | ||
eina_test_binbuf.c | ||
eina_test_binshare.c | ||
eina_test_clist.c | ||
eina_test_convert.c | ||
eina_test_coro.c | ||
eina_test_counter.c | ||
eina_test_cow.c | ||
eina_test_crc.c | ||
eina_test_error.c | ||
eina_test_file.c | ||
eina_test_fp.c | ||
eina_test_freeq.c | ||
eina_test_hash.c | ||
eina_test_inarray.c | ||
eina_test_inlist.c | ||
eina_test_iterator.c | ||
eina_test_lalloc.c | ||
eina_test_list.c | ||
eina_test_lock.c | ||
eina_test_log.c | ||
eina_test_magic.c | ||
eina_test_main.c | ||
eina_test_matrix.c | ||
eina_test_matrixsparse.c | ||
eina_test_mempool.c | ||
eina_test_module.c | ||
eina_test_module_dummy.c | ||
eina_test_quad.c | ||
eina_test_quadtree.c | ||
eina_test_quaternion.c | ||
eina_test_rbtree.c | ||
eina_test_rectangle.c | ||
eina_test_safepointer.c | ||
eina_test_sched.c | ||
eina_test_simple_xml_parser.c | ||
eina_test_slice.c | ||
eina_test_slstr.c | ||
eina_test_str.c | ||
eina_test_strbuf.c | ||
eina_test_stringshare.c | ||
eina_test_tiler.c | ||
eina_test_tmpstr.c | ||
eina_test_trash.c | ||
eina_test_ustr.c | ||
eina_test_ustringshare.c | ||
eina_test_util.c | ||
eina_test_value.c | ||
eina_test_vector.c | ||
eina_test_xattr.c | ||
sample.gpx |