On 04 Oct 2016, at 02:48, C Anthony Risinger <anthony@xtfx.me> wrote:

On Oct 3, 2016 7:09 PM, "Stephen J. Turnbull" <turnbull.stephen.fw@u.tsukuba.ac.jp> wrote:
>
> Rene Nejsum writes:
>
>  > I believe that you should be able to code concurrent code, without
>  > being to explicit about it, but let the runtime handle low-level
>  > timing, as long as you know your code will execute in the intended
>  > order.
>
> Isn't "concurrent code whose order of execution you know" an oxymoron?

They are referring to the synchronous nature of any independent control state. Whether it's a thread, a coroutine, a continuation, or whatever else doesn't really matter much. When a thing runs concurrently along side other things, it's still synchronous with respect to itself regardless of how many context switches occur before completion. Such things only need mechanisms to synchronize in order to cooperate.

I agree 100%. Ideally I think a language (would love it to be Python) should permit many (millions) of what we know as coroutines and then have as many threads as the CPU have cores to execute this coroutines, but I do not thing you as a programmer should be especially aware of this as you code. (Just like GC handles your alloc/free, the runtime should handle your “concurrency”)

People want to know how they are suppose to write unified, non-insane-and-ugly code in this a/sync python 2/3 world we now find ourselves in. I've been eagerly watching this thread for the answer, thus far to no avail.

Agree

Sans-io suggests we write bite-sized synchronous code that can be driven by a/sync consumers. While this is all well and good, how does one write said consuming library for both I/O styles without duplication?

The answer seems to be "write everything you ever wanted as async and throw some sync wrappers around it". Which means all the actual code I write will be peppered with async and await keywords.

Have a look at the examples in David Beazley’s curio, he is one of the most knowable Python people I have met, but that code is almost impossible to read and understand.

In Go I can spawn a new control state (goroutine) at any time against any function. This is clear in the code. In Erlang I can spawn a new control state (Erlang process) at any time and it's also clear. Erlang is a little different because it will preempt me, but the point is I am simply choosing a target function to run in a new context. Gevent and even threading module is another example of this pattern.

Having thought some more about it, I think that putting async i front of the object, could be kind of a channel i Go and other languages?

In all reality you don't typically need many suspension points other than around I/O, and occasionally heavy CPU, so I think folks are struggling to understand (I admit, myself included) why the runtime doesn't want to be more help and instead punts back to the developer.

Well put, we are definitely on the same page here, thank you.

br
/Rene


--

C Anthony