-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Add user-space IO.pipe #12245
base: master
Are you sure you want to change the base?
Add user-space IO.pipe #12245
Conversation
Note that because of backwards compatibility reasons, we can't change IO.pipe. It must be the other way around: we must add a new name that returns an in-memory pipe. For example IO.memory_pipe |
I wondered about this, since |
It's not about the type. People are probably using |
Ah, that I hadn’t considered. Do you have any examples? I’m wondering if there’s a way we can make that work by stitching the |
I don't have any examples, but I'm sure people are using |
It’s not that I don’t believe you. 😄 What I mean is that |
I mean |
Oh, I see. Since |
More of a question for @straight-shoota or @beta-ziliani In my opinion we shouldn't have kept So I guess it all depends on whether we want to keep true backwards compatibility or not. For instance, there's no |
That’s fair. And I may be projecting my own assumptions about what public API does and does not mean. Specifically, |
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.
Regardless of if this is a bad idea or not, Crystal::FiberChannel
also need to use the OS implementation.
BTW, this implementation also misses a very fundamental thing is that it does not block when there is nothing to read. It also have an infinite buffer, which is something real system pipes do not have - they start to block if you start to push a lot of data that doesn't get read.
So I'd say this isn't even an implementation of pipe. Like, at all.
while index < slice.size | ||
# TODO: Implement read blocking | ||
if byte = @buffer.shift? | ||
slice[index] = byte | ||
count = (index += 1) | ||
else | ||
break | ||
end | ||
end |
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.
One of the really big selling points of using a pipe over a raw deque or something is that it is threadsafe. This mean that all modifications to internal state need to be protected somehow. Probably by a mutex unless someone feels like implementing a lockfree queue implementation.
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.
Please see this comment.
slice.each do |byte| | ||
@buffer << byte | ||
end |
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.
Again, this really, really needs to be threadsafe.
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.
Please see this comment.
bytes = Bytes.new(@buffer.size) | ||
@buffer.each_with_index do |byte, index| | ||
bytes[index] = byte | ||
end |
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.
This make no sense. Since when do peek
return a copy of the whole buffer?
(and it also needs thread safety)
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.
This make no sense. Since when do
peek
return a copy of the whole buffer?
This is a draft and I mentioned in the PR description that this is still very much a WIP.
(and it also needs thread safety)
Please see this comment.
What's stopping it from using the implementation based on
It's not missing it. It's just not implemented yet. This is a draft.
How is this contributing to the conversation? Like, at all? |
This is very much a WIP (it doesn't even compile yet for
make std_spec
), but the intent here is to implement #12238.Since
Process
andSignal
currently depend on the file-descriptor-based implementation, we need to keep that functionality, but for most usage of it today (in the stdlib:IO::Stapled
andCrystal::FiberChannel
) We already have some of the right abstractions to hook up OS-level pipes to since we haveIO::FileDescriptor
.IO.pipe
currently returns a pair of those, so we can actually hang that onIO::FileDescriptor
directly:One nice thing is that, since
IO::FileDescriptor
inherits fromIO
, you can callIO::FileDescriptor.pipe
today and get that functionality.Closes #12238