Skip to content
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

OS_SOCKET is exported but only defined on windows (also a bad name) #3020

Closed
JeffBezanson opened this issue May 5, 2013 · 9 comments
Closed
Labels
domain:io Involving the I/O subsystem: libuv, read, write, etc.

Comments

@JeffBezanson
Copy link
Sponsor Member

Something that only exists on one platform is an implementation detail that shouldn't be exported.

Even if it existed everywhere, I still wouldn't want to write OS_SOCKET in my code. I'm also suspicious of OS_FD, UV_READABLE, and UV_WRITEABLE. An API is supposed to provide abstractions; we can talk about readable and writeable, but not UV, and not in all uppercase. For example, poll_fd(fd, tout, readable=true) would be ok. Aside from those details poll_fd seems like a good interface.

But I'm less sure about the likes of FDWatcher and start_watching. poll_fd seems to already provide the most useful tasks you can do with those. And if you need something else, you are up a creek, because you'll need a detailed incantation of WaitTask, FDWatcher, start_watching, TimeoutAsyncWork, start_timer, yield, and stop_watching.

Maybe we could have something like:

   ...
   waitfor(filedes, readable=true)
   waitfor(timeout(1000))
   waitfor(stream, readable=true, nbytes=1)
   yield()
   # here, check for which thing happened, or error
   ...

where waitfor sets up the current task to wait for something when it next yields. Combining all of these into a single blocking call would be fine too. Point is, it would be nice to express all the things you can wait for in a uniform way (RemoteRef refactoring is allowed too).

@Keno
Copy link
Member

Keno commented May 5, 2013

I agree that we need a better interface and that the names are bad, but I disagree in this case that it shouldn't be exported. After all, the API we are dealing with here is precisely used to interface with low-level platform specific libraries. The fact that Windows has two kinds of file descriptors, while Unix only has one is unfortunately a fact of life.

@StefanKarpinski
Copy link
Sponsor Member

It's an unfortunate fact that we should be hiding from Julia programmers, not foisting on them.

@Keno
Copy link
Member

Keno commented May 5, 2013

Sure, but not from those Julia programmers who want to monitor raw OS FD's, which is what this API is doing.

@JeffBezanson
Copy link
Sponsor Member Author

It should be called something like WindowsRawSocket.
Another option is to provide the ability to wrap a raw windows socket as a Socket, and then use a uniform API from there.

@vtjnash
Copy link
Sponsor Member

vtjnash commented May 5, 2013

The poll_fd interface seem to me to be wrapping too much. Perhaps there should be a RawFD object (which knows whether it is a socket or file -- name can be changed) which participates in the wait_* set of functions.

I've been thinking it would be nice to export the wait_* functions like such:
wait(x, :connectnotify)
by adding the method to base:
wait(x, what::Symbol) = wait(x, what, wait_filter_for[what])
Or it could also be called waitfor as suggested by Jeff.

Jeff's code block suggestion seems even better to me, with one caveat: it seems to me that the yield needs to be an explicit part of the waitfor call and not the task state. Otherwise you aren't allowed to call any potentially blocking call between calling waitfor and yield (such as readline()).

   ...
   x = WaitFor()
   push!(x, filedes, readable=true, issocket=false, writable=false)
   push!(x, timeout(1000))
   push!(x, stream, readable=true, nbytes=1) #(Jeff: why is readable necessary here?)
   push!(x, remote_ref)
   results = wait(x, :any)
   # results is a tuple of (object, result) pairs
   # check for which thing happened, or error
   ...

I tried to make this a single blocking call to extend my first suggestion above, but it seemed to lose much of its flexibility, including the ability to use named arguments, so I like the object-based approach better.
I wasn't sure how to specify which set of object constraints should be

@JeffBezanson
Copy link
Sponsor Member Author

+1 for absorbing poll_* into the general wait functions. As I said, a single blocking call is fine too. Maybe wait(Readable(stream,nb), Timeout(1000), FDReadable(fd)), which I think is what you describe as the object-based approach. Just sketching here.

@amitmurthy
Copy link
Contributor

+1 for a single wait call that can wait on a bunch of unrelated objects. In this case the result is just a tuple of true/false values specifying which of the events have been triggered.

For example:

events = wait(Readable(stream,nb), Timeout(1000), FDReadable(fd), FDwriteable(fd))
events can be (false, false, true, true)

@amitmurthy
Copy link
Contributor

Bump

@Keno
Copy link
Member

Keno commented Jun 18, 2013

Working on it.

@Keno Keno closed this as completed in 7310f55 Jun 18, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:io Involving the I/O subsystem: libuv, read, write, etc.
Projects
None yet
Development

No branches or pull requests

5 participants