Live data from Hacker News

Clojure Concurrency Tutorial

purelyfunctional.tv

41–43 of 43 posts

Re: Clojure Concurrency Tutorial

#41
post #31

Earlier quoted context omitted.

As I recall it, goroutines are in fact cooperative with implicit yield points. The implicit behavior is what I believe go means by “for all intents and purposes” Particularly, I believe all function calls are implicitly yield, which means you can usually pretend that its preemptive through normal coding practices; but you can still never yield through a while(1){} (i think there was a proposal to add implicit yield o…

The implicit yield points you're talking about is sleep or wait ( noop in other terms). It's also not exactly a yield, it calls the scheduler to tell it to schedule (meaning the scheduler could decide to run again the exact same goroutine that noop-ed). Finally, goroutines are not just cooperative, they also run in parallel in a pool of threads.

>The implicit yield points you're talking about is sleep or wait (noop in other terms)

Isn’t sleep() usually defined as not giving up control? It’s semantically a busyspin for n seconds. That is, it’s explicitly not a yield point; it's a blocking call, and it doesn’t give control back to scheduler.

And isn't wait() usually defined as, semantically, a non-blocking spinloop with a condition (hence notify() or poll())?

Which makes sleep(), wait(), yield() and noops very different.

I suppose in go, if yield() is implicit on any function call, then sleep() will immediately call yield() before actually sleeping (but once started, it’ll hold control until finished)

I'm pretty sure the implicit yield points are actually yield(), though I haven't verified; it's the only one of the sleep/wait/yield semantics that would be sensible to be implicit as far as I can tell.

>It's also not exactly a yield, it calls the scheduler to tell it to schedule

As far as I was aware, thats exactly what yield means; it yields execution control back to the scheduler. I suppose in eg, a generator, it yields control back to the caller, but afaik thats fundamentally the same meaning (the caller is the scheduler). Can you expand?

>Finally, goroutines are not just cooperative, they also run in parallel in a pool of threads.

Sure, but is that relevant? I assume async.core also trivially supports thread pooling, and is presumably equivalent to go’s pool. The only real difference is go implicitly instiates the pool, while core.async presumably makes it an explicit function to call

Re: Clojure Concurrency Tutorial

#42
post #41

Earlier quoted context omitted.

The implicit yield points you're talking about is sleep or wait ( noop in other terms). It's also not exactly a yield, it calls the scheduler to tell it to schedule (meaning the scheduler could decide to run again the exact same goroutine that noop-ed). Finally, goroutines are not just cooperative, they also run in parallel in a pool of threads.

>The implicit yield points you're talking about is sleep or wait (noop in other terms) Isn’t sleep() usually defined as not giving up control ? It’s semantically a busyspin for n seconds. That is, it’s explicitly not a yield point; it's a blocking call, and it doesn’t give control back to scheduler. And isn't wait() usually defined as, semantically, a non-blocking spinloop with a condition (hence notify() or poll())?…

In Go, time.Sleep don't hold the thread. That's the cool part. In Go a noop gives the control back to the scheduler which will then reuse the thread for any goroutine that needs cpu -- ie. one that isnt noop-ing. So if you sleep or wait for 10 seconds, 10 seconds of cpu will be given to other goroutines.

Re: Clojure Concurrency Tutorial

#43
post #30

Earlier quoted context omitted.

Please see my other comment about using the same channels and calling I/O-heavy (blocking) functions from a `(thread)` instead of from a go block. You indeed shouldn't call blocking functions from go blocks, but core.async gives you the option of freely mixing separate threads and go blocks.

Having to use full threads in some cases and core.async in others pretty much defeats the purpose. Core.async is just nowhere near as good as goroutines. It'll continue to be like that until Project Loom finally has a release.

I think you misunderstood what I wrote.

Core.async lets you freely mix both. You use the same channels, the only difference being that your coroutine blocks will be wrapped in `go` and use `<!` (parks coroutine if it needs to block), while your full threads with be wrapped in `thread` and use `<!!` (blocks). It makes the tradeoffs explicit (the tradeoff always exists) and isn't a problem at all.

Post reply on HN