Skip to content

Commit c600aa3

Browse files
committed
proofread
1 parent 9466b8d commit c600aa3

1 file changed

Lines changed: 9 additions & 9 deletions

File tree

collections/_posts/2022-09-17-typelevel-native.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ meta:
88
author: armanbilge
99
---
1010

11-
We recently published several major projects for the [Scala Native] platform, notably [Cats Effect], [FS2], and [http4s]. This blog post explores what this new platform means for the Typelevel ecosystem as well as how it works under-the-hood.
11+
We recently published several major Typelevel projects for the [Scala Native] platform, most notably [Cats Effect], [FS2], and [http4s]. This blog post explores what this new platform means for the Typelevel ecosystem as well as how it works under-the-hood.
1212

1313
### What is Scala Native?
1414

@@ -40,7 +40,7 @@ The burden of cross-building the Typelevel ecosystem for Scala Native fell almos
4040

4141
#### event loop runtime
4242

43-
**To cross-build Cats Effect for Native we had to get creative** because Scala Native currently does not support multithreading (although it will in the next major release). This is a similar situation to the JavaScript runtime, which is also fundamentally single-threaded. But an important difference is that JS runtimes are implemented with an [event loop] and offer callback-based APIs for scheduling timers and performing non-blocking I/O.
43+
**To cross-build Cats Effect for Native we had to get creative** because Scala Native currently does not support multithreading (although it will in the next major release). This is a similar situation to the JavaScript runtime, which is also fundamentally single-threaded. But an important difference is that JS runtimes are implemented with an [event loop] and offer callback-based APIs for scheduling timers and performing non-blocking I/O. An *event loop* is a type of runtime a that enables compute tasks, timers, and non-blocking I/O to be interleaved on a single thread.
4444

4545
Meanwhile, Scala Native core does not implement an event loop nor offer such APIs. There is the [scala-native-loop] project, which wraps the [libuv] event loop runtime, but we did not want to bake such an opinionated dependency into Cats Effect core.
4646

@@ -63,7 +63,7 @@ To demonstrate the API contract, consider invoking `poll(3.seconds)`:
6363

6464
*Oh, and don’t forget to tell me whether there are still outstanding I/O events (`true`) or not (`false`) so I know if I need to call you again. Thanks!*
6565

66-
Thus, with tasks, timers, and the capability to poll for I/O, we can express the event loop algorithm. A single iteration of the loop looks like this:
66+
With tasks, timers, and the capability to poll for I/O, we can express the event loop algorithm. A single iteration of the loop looks like this:
6767

6868
1. Check the current time and execute any expired timers.
6969

@@ -93,9 +93,9 @@ int epoll_wait(int epfd, struct epoll_event *events,
9393
int maxevents, int timeout);
9494
```
9595
96-
After creating an epoll instance (identified by a file descriptor) we can register sockets (also identified by file descriptors) with `epoll_ctl`. Typically we will register to be notified of the “read-ready” (`EPOLLIN`) and “write-ready” (`EPOLLOUT`) events on that socket. Finally, the actual polling is implemented with `epoll_wait`, which sleeps until the next I/O event is ready or the `timeout` expires.
96+
After creating an epoll instance (identified by a file descriptor) we can register sockets (also identified by file descriptors) with `epoll_ctl`. Typically we will register to be notified of the “read-ready” (`EPOLLIN`) and “write-ready” (`EPOLLOUT`) events on that socket. Finally, the actual polling is implemented with `epoll_wait`, which sleeps until the next I/O event is ready or the `timeout` expires. Thus we can use it to implement a `PollingExecutorScheduler`.
9797
98-
As previously mentioned, these sorts of polling APIs are ubiquitous and not just for working directly with sockets. For example, [libcurl](https://curl.se/libcurl/) (the C library behind the well-known CLI) exposes a function for polling for I/O on all ongoing HTTP connections.
98+
As previously mentioned, these sorts of polling APIs are ubiquitous and not just for working directly with sockets. For example, [libcurl](https://curl.se/libcurl/) (the C library behind the well-known CLI) exposes a function for polling for I/O on all ongoing HTTP requests.
9999
100100
```c
101101
#include <curl/curl.h>
@@ -111,7 +111,7 @@ Indeed, this function underpins the `CurlExecutorScheduler` in [http4s-curl].
111111

112112
On macOS and BSDs the [kqueue] API plays an analogous role to epoll. We will not talk about Windows today :)
113113

114-
Long story short, I did not want the FS2 codebase to absorb all of this cross-OS complexity. So in collaboration with Lee Tibbert we repurposed my cheeky [epollcat] experiment into an actual library implementing JDK NIO APIs (specifically, [`AsynchronousSocketChannel`] and friends). Since these are the same APIs used by the JVM implementation of `fs2-io`, it actually enables this code to be completely shared.
114+
**Long story short, I did not want the FS2 codebase to absorb all of this cross-OS complexity.** So in collaboration with Lee Tibbert we repurposed my cheeky [epollcat] experiment into an actual library implementing JDK NIO APIs (specifically, [`AsynchronousSocketChannel`] and friends). Since these are the same APIs used by the JVM implementation of `fs2-io`, it actually enables the `Socket` code to be completely shared with Native.
115115

116116
[epollcat] implements an `EpollExecutorScheduler` for Linux and a `KqueueExecutorScheduler` for macOS. They additionally provide an API for monitoring a socket file descriptor for read-ready and write-ready events.
117117

@@ -127,7 +127,7 @@ trait EventNotificationCallback {
127127

128128
These are then used to implement the callback-based `read` and `write` methods of the JDK `AsynchronousSocketChannel`.
129129

130-
It is worth pointing out that the JVM actually implements `AsynchronousSocketChannel` with an event loop as well. The difference is that on the JVM, this event loop is used only for I/O and runs on a separate thread from the compute pool used for fibers and the scheduler thread used for timers. Meanwhile, epollcat is an example of an I/O integrated runtime where fibers, timers, and I/O are all managed on a single thread.
130+
It is worth pointing out that the JVM actually implements `AsynchronousSocketChannel` with an event loop as well. The difference is that on the JVM, this event loop is used only for I/O and runs on a separate thread from the compute pool used for fibers and the scheduler thread used for timers. Meanwhile, epollcat is an example of an I/O integrated runtime where fibers, timers, and I/O are all interleaved on a single thread.
131131

132132
#### TLS
133133

@@ -149,8 +149,8 @@ Please try the Typelevel Native stack! And even better deploy it, and do so loud
149149

150150
Besides that, here is a brain-dump of project ideas and existing projects that would love contributors. I am happy to help folks get started on any of these, or ideas of your own!
151151

152-
* Creating example applications, templates, and tutorials.
153-
- If you are lacking inspiration, try cross-building existing examples such as [fs2-chat], [kitteh-redis], [Jobby].
152+
* Creating example applications, templates, and tutorials:
153+
- If you are short on inspiration, try cross-building existing examples such as [fs2-chat], [kitteh-redis], [Jobby].
154154
- Spread the word: [you-forgot-a-percentage-sign-or-a-colon].
155155

156156
* Cross-building existing libraries and developing new, Typelevel-stack ones:

0 commit comments

Comments
 (0)