dvlsg / async-csp

CSP style channels using ES7 async/await
MIT License
317 stars 18 forks source link

How does the Data Flow example work? #1

Closed trusktr closed 8 years ago

trusktr commented 8 years ago

In the Data Flow example,

import Channel from 'async-csp';

let ch = new Channel();
await ch.put(1);
await ch.put(2);
await ch.put(3);
console.log(await ch.take()); //=> 1
console.log(await ch.take()); //=> 2
console.log(await ch.take()); //=> 3

How does that work? Doesn't execution pause at the first await line (await ch.put(1);), so the last 5 lines don't execute?

dvlsg commented 8 years ago

It should work since a Channel initialized without a size argument will allow Channel.DEFAULT_SIZE values to be put onto the channel before blocking. This is currently set to 8.

I noticed that as I use async-csp in my own projects, I almost never use a channel without a buffer. On the other hand, I have since learned that golang's default for channels is a buffer size of 0, so it may be best to emulate that for consistency. I am definitely open to suggestions.

In the interim, you should be able to use the following to get close to the behavior above:

import Channel from 'async-csp';
Channel.DEFAULT_SIZE = 1;

let ch = new Channel(); // you can also use let ch = new Channel(1); if you don't want to change DEFAULT_SIZE
await ch.put(1); // this will still not block, since the put will resolve when there is space on the Channel, and there is space for one element
ch.put(2); // this would have blocked, however, since the channel only has room for one value before buffering
ch.put(3);
console.log(await ch.take()); //=> 1
console.log(await ch.take()); //=> 2
console.log(await ch.take()); //=> 3
trusktr commented 8 years ago

Gotcha! I think some implementations (js-csp who's first example is ported from Go) make put block out-of-the-box unless you explicitly create a buffer​ or unblock by calling a take on the channel.

trusktr commented 8 years ago

Ah, wait, nevermind. It's clear in the js-csp example that take runs first, and waits for something to be put.

trusktr commented 8 years ago

Ah, here's what js-csp does, second bullet point in the list: http://jlongster.com/Taming-the-Asynchronous-Beast-with-CSP-in-JavaScript#Basic-Principles

Put blocks until something takes, and take blocks until something puts.

trusktr commented 8 years ago

I think that's good default functionality for async coordination.

dvlsg commented 8 years ago

I think I agree. I'll put it in my dev branch and sit on it for a while to consider, but I imagine I'll go forward with it for consistency's sake.

trusktr commented 8 years ago

Ah, for reference, here's where if officially mentions it: https://github.com/ubolonton/js-csp/blob/master/doc/basic.md#chanbufferorn-transducer-exhandler

trusktr commented 8 years ago

By the way, I like your async/await approach much better than the generator approach in js-csp. It's the next step. Plus I like the object methods rather than function calls (f.e. I like ch.put(something) better than cps.put(ch, something)).