|
1 |
| -# native-loop (PRE-RELEASE) |
2 |
| -Extensible event loop and async-oriented IO for Scala Native; powered by libuv. |
| 1 | +# scala-native-loop |
3 | 2 |
|
4 |
| -## UNDER CONSTRUCTION |
5 |
| - |
6 |
| -If you're looking for the new 0.4 rewrite, check the `04` branch. The current state of master is mostly extracted from the book [Modern Systems Programming in Scala Native](https://pragprog.com/book/rwscala/modern-systems-programming-with-scala-native). |
| 3 | +Async IO and event loop for Scala Native |
7 | 4 |
|
8 | 5 | ## What is it?
|
9 | 6 |
|
10 |
| -scala-native-loop provides a real, asynchronous ExecutionContext implementation for Scala Native. |
11 |
| -It's backed by libuv, the same C library that the node.js ecosystem runs on; in addition to basic |
12 |
| -Future dispatching, we can also use libuv to provide other basic functionality, like: |
13 |
| - |
14 |
| -- File IO |
15 |
| -- Pipe IO |
16 |
| -- TCP Sockets |
17 |
| -- UDP Sockets |
18 |
| -- Timers |
19 |
| - |
20 |
| -To provide a working API for practical, async Scala Native programs, we have two subprojects, |
21 |
| -`client` and `server`, which provide an async HTTP client and server, respectively, by integrating addtional C libraries: [nodejs/http-parser](https://github.com/nodejs/http-parser) for request parsing, and [curl](https://github.com/curl/curl) for a full featured client with HTTPS support. |
22 |
| - |
23 |
| -That said - providing a full-featured ecosystem in a single library isn't feasible - instead, we provide a `LoopExtension` trait that allows other C libraries to be integrated to the underlying event loop, in the same way that libcurl and http-parser are integrated; this opens up the possiblity of fully asynchronous bindings for postgres, redis, and many others. |
24 |
| - |
25 |
| -## Why is this here? |
26 |
| - |
27 |
| -To demonstrate the architectural style of a full, extensible async ecosystem for Scala Native, with an idiomatic Future-based API, implemented entirely as a library, and to start discussion about what we our priorities are. |
28 |
| - |
29 |
| -## LoopExtension trait |
30 |
| - |
31 |
| -To attach a new library to the event loop, all we need to do is provide the `LoopExtension` trait: |
32 |
| - |
33 |
| -``` |
34 |
| -trait LoopExtension { |
35 |
| - def activeRequests:Int |
36 |
| -} |
37 |
| -``` |
38 |
| - |
39 |
| -And then register the component at runtime with `EventLoop.addExtension()`. |
40 |
| - |
41 |
| -This is necessary because we need some way to know if there are pending IO tasks being managed by a C library, even if there are no outstanding Futures, and prevent the event loop from shutting down prematurely in that case. |
42 |
| - |
43 |
| -## Maintenance Status |
44 |
| - |
45 |
| -This code is a pre-release preview - I am cleaning up both the style and the implementation, |
46 |
| -aiming to align with Scala Native 0.4 for something more robust. |
47 |
| - |
48 |
| -For now, I'm filing issues to remind myself of work that needs to be done. |
49 |
| - |
50 |
| -I'll also create a few "discussion" issues for broader conversation. |
51 |
| - |
52 |
| -Please feel free to file additional issues with questions, comments, and concerns! |
53 |
| - |
54 |
| -## Server API Example |
55 |
| - |
56 |
| -``` |
57 |
| - def main(args:Array[String]):Unit = { |
58 |
| - Service() |
59 |
| - .getAsync("/async") { r => Future { |
60 |
| - s"got (async routed) request $r" |
61 |
| - }.map { message => OK( |
62 |
| - Map("asyncMessage" -> message) |
63 |
| - ) |
64 |
| - } |
65 |
| - } |
66 |
| - .getAsync("/fetch/example") { r => |
67 |
| - Curl.get(c"https://www.example.com").map { response => |
68 |
| - Response(200,"OK",Map(),response.body) |
69 |
| - } |
70 |
| - } |
71 |
| - .get("/") { r => OK { |
72 |
| - Map("default_message" -> s"got (default routed) request $r") |
73 |
| - } |
74 |
| - } |
75 |
| - .run(9999) |
76 |
| - uv_run(EventLoop.loop, UV_RUN_DEFAULT) |
77 |
| - } |
78 |
| -``` |
79 |
| - |
80 |
| -## Streaming API Example |
| 7 | +scala-native-loop provides asynchronous utilities for Scala Native. |
| 8 | +It's backed by libuv, the same C library that the Node.js ecosystem runs on. |
| 9 | +It currently offers: |
81 | 10 |
|
82 |
| -``` |
83 |
| - def main(args:Array[String]):Unit = { |
84 |
| - val p = FilePipe(c"./data.txt") |
85 |
| - .map { d => |
86 |
| - println(s"consumed $d") |
87 |
| - d |
88 |
| - }.addDestination(Tokenizer("\n")) |
89 |
| - .addDestination(Tokenizer(" ")) |
90 |
| - .map { d => d + "\n" } |
91 |
| - .addDestination(FileOutputPipe(c"./output.txt", false)) |
92 |
| - println("running") |
93 |
| - uv_run(EventLoop.loop,UV_RUN_DEFAULT) |
94 |
| - } |
95 |
| -``` |
| 11 | +- `scala.scalanative.loop.Timer`: to schedule callbacks to execute after a timeout |
| 12 | +- `scala.scalanative.loop.Poll`: to schedule callbacks when data is read/written on a file descriptor |
0 commit comments