You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The os namespace (to be renamed posix) is tackling the problem of providing a cross-platform abstraction over the operating system facilities from a, in my opinion, wrong angle. In this essay I will briefly explain why.
The aim here is having a single level of abstraction that works well enough both for direct consumers (users of std.os namespace) or indirect consumers (eg. using std.fs abstractions built on std.os) without leaking too many details about the underlying implementation. The current approach tries to clump everything under the posix name, a name that carries a heavy baggage of do's and dont's that other platforms (mainly Windows) may not agree with.
A few examples:
rename doesn't follow the posix semantics on Windows, unless you have a very recent Windows 10 version and FILE_RENAME_FLAG_POSIX_SEMANTICS is used.
open accepts a well-defined set of options that's not even shared across all the posix-compatible and for Windows this means we're pinky-swearing to faithfully translate all of them into something equivalent. What if there's no direct equivalent? If you promise posix compatibility I'd expect something akin to mingw.
What we're interested in is getting a handle on a given file, with a given set of flags.
stat doesn't exist on Windows, GetFileAttributesEx or equivalents are used and the resulting infos are chopped into a posix stat structure. It's a clear case of square peg in a round hole as many fields are unix-specific.
What we're interested in is getting a basic set of infos about the file, platform-specific extra stuff may be retrieved/modified with a companion function.
preadv/pwritev are not available on Windows and, at the moment at least, you get a nice compile error trying to use them.
What we're interested in is a {write,read}Many function, implemented using p{write,read}v or ReadFileScatter/WriteFileGather.
iovec is a posix thing, I just want to write/read a [][]u8!
copy_file_range is a Linux-only syscall with a fallback on pwrite/pread that in turn falls back on ReadFile/WriteFile on Windows.
IMO this doesn't even belong to os as it can be safely implemented somewhere in fs, calling copy_file_range or other platform-specific APIs as needed.
It's not portable! It's not part of the posix standard!
copy_file_range is all about efficiency as it's done at the FS level, if the fallback path is triggered you get a disappointing read/write pair (not even a loop!)
The point is that we should aim at breaking free from the posix rules and write our own, a full-blown posix compatibility layer is not something that belongs to the stdlib. I see Rust took this very same approach (I'm looking at the filsystem-related part), their API surface is small and comprises all the common bits required by the users (external ones and ones working on the stdlib). A small note lets the user know what platform-specific method is used, but that's it.
The gist of this proposal is:
No more posix compatibility layer
os becomes the home of all the cross-platform native interactions with the OS. No fallbacks, no posix names, no posix guarantees.
No fallbacks really means no half-assed fallbacks, if something can be implemented across all the different platforms with a consistent set of characteristics it belongs to os, otherwise down the platform-specific namespace it goes.
✔️ writeMany implemented with WriteFileGather and pwritev
❌ copy_file_range cannot be implemented as zero-copy on Windows! (On other posix-compatible systems sendfile may be used, but the gains are really small unless you're copying a lot of data (I'm using it to copy whole files in std: Make file copy ops use zero-copy mechanisms #6516))
The
osnamespace (to be renamedposix) is tackling the problem of providing a cross-platform abstraction over the operating system facilities from a, in my opinion, wrong angle. In this essay I will briefly explain why.The aim here is having a single level of abstraction that works well enough both for direct consumers (users of
std.osnamespace) or indirect consumers (eg. usingstd.fsabstractions built onstd.os) without leaking too many details about the underlying implementation. The current approach tries to clump everything under theposixname, a name that carries a heavy baggage of do's and dont's that other platforms (mainly Windows) may not agree with.A few examples:
renamedoesn't follow the posix semantics on Windows, unless you have a very recent Windows 10 version andFILE_RENAME_FLAG_POSIX_SEMANTICSis used.openaccepts a well-defined set of options that's not even shared across all the posix-compatible and for Windows this means we're pinky-swearing to faithfully translate all of them into something equivalent. What if there's no direct equivalent? If you promise posix compatibility I'd expect something akin tomingw.statdoesn't exist on Windows,GetFileAttributesExor equivalents are used and the resulting infos are chopped into a posixstatstructure. It's a clear case of square peg in a round hole as many fields are unix-specific.preadv/pwritevare not available on Windows and, at the moment at least, you get a nice compile error trying to use them.{write,read}Manyfunction, implemented usingp{write,read}vorReadFileScatter/WriteFileGather.iovecis a posix thing, I just want to write/read a[][]u8!copy_file_rangeis a Linux-only syscall with a fallback onpwrite/preadthat in turn falls back onReadFile/WriteFileon Windows.osas it can be safely implemented somewhere infs, callingcopy_file_rangeor other platform-specific APIs as needed.copy_file_rangeis all about efficiency as it's done at the FS level, if the fallback path is triggered you get a disappointing read/write pair (not even a loop!)The point is that we should aim at breaking free from the posix rules and write our own, a full-blown posix compatibility layer is not something that belongs to the stdlib. I see Rust took this very same approach (I'm looking at the filsystem-related part), their API surface is small and comprises all the common bits required by the users (external ones and ones working on the stdlib). A small note lets the user know what platform-specific method is used, but that's it.
The gist of this proposal is:
osbecomes the home of all the cross-platform native interactions with the OS. No fallbacks, no posix names, no posix guarantees.os, otherwise down the platform-specific namespace it goes.writeManyimplemented withWriteFileGatherandpwritevcopy_file_rangecannot be implemented as zero-copy on Windows! (On other posix-compatible systemssendfilemay be used, but the gains are really small unless you're copying a lot of data (I'm using it to copy whole files in std: Make file copy ops use zero-copy mechanisms #6516))Thanks for watching.