Making Async play better with others
Anil Madhavapeddy
anil at recoil.org
Tue Nov 22 12:58:12 GMT 2011
On Mon, Nov 21, 2011 at 10:35:36PM -0500, Yaron Minsky wrote:
> So I guess that would mean ripping the Linux_ext module out of Core, right?
>
> While I agree about keeping conditional code localized and small, I don't
> quite see why the right answer is to have zero tolerance for conditional
> compilation of OCaml. Imagine that you have different APIs on different
> platforms that require non-trivially different logic. Now you're wedded to
> the idea of having non-trivial code that compiles conditionally. The only
> question is, will you write that code in C or in OCaml? Given that choice,
> I usually choose OCaml...
Ideally, there should be no platform-specific tests at all, but rather
feature-specific ones. The Core C bindings are pretty good about this, as
they already do #ifdef checks (e.g. CLOCK_PROCESS_CPUTIME_ID or HAS_IPV6).
Why not just build standalone OCaml modules which always implement the
same signature, but internally do some preprocessing for a particular
platform? For instance, TCP_CORK is directly exposed at the moment, and
is quite Linux-specific. Is this used for sendfile() or something else at
the moment? The OCaml module (Async.Tcp_file?) should probably be a
sendfile()-like interface, and internally implement it in the FreeBSD
(where it is called TCP_NOPUSH) or Linux style. Other platforms like
OpenBSD simply lack the flag, and would fallback to a portable but slower
read/write implementation that always works, but with the same semantics.
I like the fact that the OCaml Thread or Dynlink module simply isn't
present if the platform doesn't support threads, rather than there being a
dummy module that calls an exception whenever you invoke it. It would be
particularly unhelped to find random exceptions being raised all over the
place just because some code used a small Linux-specific feature.
> Another way of dealing with some of these things is with runtime-tests that
> key-off of the platform, potentially using first-class modules. i.e., you
> could have a value of the type:
>
> val os : [ `Windows of (module Windows_specific_API)
> | `Linux of (module Linux_specific_API)
> | `BSD of (module BSD_specific_API)
> | `Posix of (module Posix_specific_API) ]
It would be great to have this to test for *features* at runtime, but is
there any use of knowing what OS you are running under? It just makes it
more difficult to port it to new platforms.
It gets even more messy when you consider that some features (Dynlink or
high-res clocks) may only work reliably on mainstream architectures and
not so well on MIPS or Sparc64. I'd prefer something like:
val clock: [ `Realtime of (module Realtime_clock)
| `Posix of (module Posix_clock)
]
So the programmer would explicitly choose to upgrade to a better clock, at
the cost of some portability, but by default would get a Posix_clock.
Anil
More information about the core
mailing list