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
Copy file name to clipboardExpand all lines: tutorials/migrate-v5.md
+44Lines changed: 44 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -159,6 +159,50 @@ listener.cancel();
159
159
160
160
When rewriting your own code that used `Task`, you can forget about checking for cancellation and leverage the power of coroutines - your task can be cancelled at any `co_await` point.
161
161
162
+
## Async in general
163
+
164
+
This section is useful for those who have done multithreading in mods, whether via creating threads manually or using `geode::Task`. The new async system provides a much easier way for concurrency, as a central system shared between Geode and mods. Specifically, there are two types of jobs that can run in parallel: **Async Tasks** and **Blocking Tasks**.
165
+
166
+
Async tasks are the most common ones, and they are useful for pretty much any concurrent tasks that aren't CPU heavy and don't block. For more examples on what you can do with them, see the [Arc README](https://github.com/dankmeme01/arc), but here's a small example of an asynchronous worker task that you previously could've only implemented with an `std::thread`:
167
+
```cpp
168
+
auto [tx, rx] = arc::mpsc::channel<int>();
169
+
170
+
auto handle = async::runtime().spawn([](auto rx) -> arc::Future<> {
// Then, in regular, sync code you can use the mpsc channel to communicate with the worker
178
+
(void) tx.trySend(1);
179
+
```
180
+
181
+
There are a few things you should strictly avoid doing inside async tasks:
182
+
* Blocking the thread (for networking use Arc sockets, for sleep use `arc::sleep`, for other blocks see below)
183
+
* Using `std::mutex` (or other sync primitives) across await boundaries - prefer to use `arc::Mutex` or ensure you unlock the mutex before doing `co_await`
184
+
* Running CPU intensive tasks or IO that isn't networking: decoding images, writing large files; these should be done as blocking tasks
185
+
186
+
For when blocking is required, you can use the **blocking task pool** (and you should prefer doing that over using your own thread pool!):
187
+
```cpp
188
+
auto handle = async::runtime().spawnBlocking<uint64_t>([] {
189
+
// simulate some expensive calculation
190
+
uint64_t x = 1;
191
+
for (int i = 0; i < 1024; i++) {
192
+
x = x * (x + i);
193
+
}
194
+
return x;
195
+
});
196
+
197
+
// The task now runs in parallel, and it will not be stopped if you discard the hnadle
198
+
// To get the output value, you have two ways:
199
+
200
+
// 1. await if inside an async task
201
+
uint64_t value = co_await handle;
202
+
// 2. block (only if NOT inside the async runtime!)
203
+
uint64_t value = handle.blockOn();
204
+
```
205
+
162
206
## `fmt::localtime`
163
207
164
208
We updated our `fmt` dependency to v12, which removed the `fmt::localtime` function. Now Geode provides a drop-in replacement for it:
0 commit comments