On Feb 9, 2014, at 10:50 AM, Kevin Gillette <
extempor...@gmail.com> wrote:
> That sounds about right. For channels and other synchronization, a simple approach would be to have each make call for channels internally call into an emulated runtime asking for an integer ID unique to channels; goroutine creation should also get an ID out of a separate pool. Then, all Go functions get broken up around scheduling points (if there are any), and end up as a sequence of JS functions wrapped in an outer closure -- the closure defines the local variables. Now, when a translated function reaches a channel communication point, it calls into the runtime, passing its goroutine ID and channel operations into an object keyed by channel ID which tracks ready state and read-and-write waiters. Care has to be taken to make sure that when a goroutine "resumes" it removes its channel associations from the runtime -- though as an optimization this could wait based on control flow such that, e.g. a select statement in a for loop doesn't need to continuously remove and re-add the same channels from the scheduler on each iteration, and can instead just wait until exiting the loop.
>
> mutexes and other synchonization can simply be implemented in terms of channels internally (runtime.Cond.Broadcast might require some forethought). runtime.Gosched and default clauses in selects could just internally be translated into a discarding receive from an unexported, closed global channel.
>
> Also needed would be some way to track channel references (perhaps manual reference counting) so that the runtime structures don't grow indefinitely.
I wonder if that’s more complicated than it needs to be. I don’t think that either a goroutine or a channel needs to be a global object. There is probably no need for any global runtime state. So garbage collection could take care of unused channels, and probably permanently-blocked goroutines as well. (Since JS is single-threaded, let’s take advantage of the simplifications that offers.)
What if a channel was just a JS object? When a goroutine comes to a channel send or receive that can’t complete immediately, it would just add its current continuation (i.e. the function that corresponds to the remainder of the goroutine) to the channel’s appropriate waiting list. If it encounters a synchronous channel operation that can complete immediately, it would get a continuation function from the waiting list, schedule its own continuation function with setTimeout(f, 0), and call the continuation from the waiting list.