4 ms·
Glad you mentioned this; to me, this is a very important requirement. I don't see lot of people understand the difference between YIELD and full-blown coroutin
by iambvk 13y ago
Glad you mentioned this; to me, this is a very important requirement.
I don't see lot of people understand the difference between YIELD and full-blown coroutines.
IMO YEILD is not very useful; it doesn't compose well with non-yield function. OTOH full-blown coroutines are super awesome.
Too bad C++11 still doesn't give full-blown coroutines.
- batguano 13y agoCould you explain what you mean by full-blown coroutines? Thanks!
- ricree 13y agoIf I had to guess, I think he's talking about coroutines that allow you to pass data as well as take it out. Python's PEP 342, which expanded python generators into truer coroutines, has a decent discussion on the differences. http://www.python.org/dev/peps/pep-0342/ http://www.python.org/dev/peps/pep-0342/
- anonymoushn 13y agoIf you have a function that can suspend its own execution and return data, you have a Python generator. If it can also receive data when it is resumed, you have an ES6 generator (or the C macros above!). If its subroutines can cause it to suspend, you have a full-blown coroutine. If it can be copied, you can build call/cc.
- _ZeD_ 13y agobut but... http://dabeaz.com/coroutines/ http://dabeaz.com/coroutines/
- anonymoushn 13y agoOops! "Python generator" should be "Python 2.4 generator." Versions of Python people actually use go with ES6.
- 616c 13y agoI had know idea call/cc was that powerful. Very cool, and thanks for the breakdown for someone who did not know the difference.
- iambvk 13y agoDidn't see your comment til now. So, here is the difference I see: Full-blown coroutines give us a way to write fully asynchronous code without using callbacks. For example, I could define ASYNC macro as follows: #define ASYNC(blocking_function_call) \ do { \ auto io_pool = GetIOThreadPool(); \ auto cpu_pool = GetCurrentThreadPool(); \ \ Detach_The_Thread_and_Enqueue_Coroutine_For_IO(io_pool); \ \ blocking_function_call; \ \ Detach_The_Thread_and_Enqueue_Coroutine_For_CPU(cpu_pool); \ } while (0) Now, I can make any blocking operation asyncrhonous. For example, open() or readdir() functions do not have asynchronous interfaces, but I can make them asynchronous by simply wrap it with ASYNC(...) macro. It works as follows: When we need to do a blocking operation, we suspend the coroutine and we enqueue it into a thread-pool that is designated to do blocking calls; the cpu thread is now free, so it can start executing other cpu-bound coroutines. When io thread has finished the job, it will enqueue the coroutine back to the CPU thread pool. What we have now is a fully asynchronous system where cpu threads can be kept busy with only cpu-bound work and io threads can be kept with io-bound work. This gives us full control over the concurrency. We could be confident that CPU threads are always available for compute work. We cannot do this with python "yield".