typelevel / cats-effect

The pure asynchronous runtime for Scala
https://typelevel.org/cats-effect/
Apache License 2.0
1.99k stars 511 forks source link

Test `FileDescriptorPoller` API for goodness-of-fit with C libraries #3688

Open armanbilge opened 1 year ago

armanbilge commented 1 year ago

I just released 3.6-e9aeb8c, a milestone of Cats Effect v3.6.0 which introduces file descriptor I/O polling built-in to the runtime. The goal is to foster an ecosystem of wrappers for C libraries that can be used simultaneously in the same application, alongside Typelevel-native libraries such as Ember and Skunk.

Before releasing, we should test the proposed API for goodness-of-fit.

https://github.com/typelevel/cats-effect/blob/e9aeb8ccb53016a37588256f4c8086f8ef1612bc/core/native/src/main/scala/cats/effect/FileDescriptorPoller.scala#L19

Two integrations that I am interested in are:

hnaderi commented 1 year ago

@armanbilge I implemented a new runtime in http4s-curl based on FileDescriptorPoller and it works fine!

However I have some questions/feedbacks regarding the FileDescriptorPoller APIs:

armanbilge commented 1 year ago

Awesome, thank you so much for giving this an early try, that was a non-trivial implementation. Very helpful feedback; much appreciated!


Is it possible to register/unregister for read/write monitoring separately?

It's not unfortunately, this is a limitation of the Linux epoll API that forces this API to become the least-common-denominator.

For example, Currently changing FD from read to read and write requires cancelling the read loop, releasing FileDescriptorPollHandle and acquiring a new one and starting new loops

If you anticipate that you will eventually need both reading and writing on an FD then you should register it as read/write from the beginning. There is no harm to register an FD for reading+writing but not using it for reading or writing immediately.

On the other hand, every time you register/unregister FDs is expensive (epoll again). So better to do that as little as possible.


  • It is unclear what will happen if we get multiple FileDescriptorPollHandles for a single FD,

I guess this is undefined behavior. On Linux it will currently raise an error (epoll :), but this will become non-deterministic when we have a multi-threaded runtime. For kqueue and io_uring it would probably be fine ... I'll update the doc to say it's undefined.

  • what happens when FD state changes just before we get the handle? Does it call the function?

Yes, the FileDescriptorPollHandle tracks this and takes full responsibility for running the function you pass to it. The specific implementation details of this vary, but you do not need to worry about calling the function yourself. I can try and clarify this in the docs as well.


I hope that answers your questions!

lolgab commented 1 month ago

I confirm that the new API works correctly with SNUnit. The library was updated to use the new API, all tests pass and it is released.