-
Notifications
You must be signed in to change notification settings - Fork 419
New channel implementation #415
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
858814a
to
20414a9
Compare
The most recent commit interoperates the new |
20414a9
to
32e712a
Compare
I'm not very fond of the select syntax, but I guess it's as close as you can get in ruby to go's syntax. |
The Agent gem uses Channel.select do |s|
s.case(tick, :receive) { print "tick.\n" }
s.case(boom, :receive) do
print "BOOM!\n"
exit
end
s.default do
print " .\n"
sleep(0.05)
end
end I have mixed feelings: The use of @sschepens Do you like the Agent syntax better? |
b98a313
to
2dd0a3c
Compare
@jdantonio No, I also feel it's redundant, I prefer your syntax, what i'm not fond of is having to receive and use the select object in the block, though I don't know if there's a way around it. |
Wow, looks very nice. I'll look at the code more deeply later. |
8569d36
to
00ba136
Compare
200354f
to
84e1ebc
Compare
84e1ebc
to
f7e3672
Compare
include Enumerable | ||
|
||
GOROUTINES = Concurrent::CachedThreadPool.new | ||
private_constant :GOROUTINES |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is extra pool created? It could use global IO pool afaik.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely it could. But since this is still early in development I wanted to keep these separate from the global pools, just in case, should channels exhibit any erratic behavior. I discuss this a little in channel.md. Should this ever move from Edge to Core I expect that they won't need a separate pool any more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Could you also add a TODO to the code if you are editing it?
Go-like Channels
This is a spike of a new channel implementation. It is not ready for merging. It is functional enough that I was able to replicate all the channel examples from Go by Example and A Tour of Go. The sample code can be found in
examples/a-tour-of-go-channels
andexamples/go-by-example-channels
. I'm very happy with this direction and think it should eventually replace the implementation currently in Edge. I've created the PR to solicit feedback from anyone interested in the topic.The primary model for this implementation is Go channels. Some features were also inspired by Clojure core.async, which may provide additional inspiration in the future. The
select
syntax was inspired by the Ruby Agent gem, but all code in this spike is original.Random Notes
Channel.go
function. It just posts to a thread pool.send
andreceive
, but I when with the Clojure termstake
andput
. They are functionally the same (and I've created aliases forsend
andreceive
), but I also implemented Clojure'soffer
andpool
so I remained consistent with terms.<<
for send/put since that aligns with thepost
methods of our executors. For receive/take I needed a unary operator, which limited my choices. I went with~
, e.g.bucket = ~channel
. I think it works well (see the code examples).receive
variants with the same method name in Ruby doesn't work. I implemented the 2-value form as a method callednext
. It returns two values.range
using Ruby's idiomaticeach
. I also includedEnumerable
inChannel
. Most of the enumerable methods will block until the channel is closed. This is OK, it aligns with Go'srange
and it mirrors the behavior of similar methods in Clojure'score.async
.:validator
option on theChannel
constructor. It follows the same rules asAgent
. Validation occursbefore
the given item is enqueued.ScheduledTask
andTimerTask
, they don't fit cleanly into channel operations. So I implemented Go-like timer and ticker channels. Unfortunately, Go's "timer" is analogous to ourScheduledTask
and Go's "ticker" is analogous to ourTimerTask
. I've retained Go's nomenclature.To-do
Examples
More examples can be found in examples/go-by-example-channels and examples/a-tour-of-go-channels.
A simple put/take example:
produces:
A more complext example:
produces:
Finally, tickers, timers, and select:
produces: