mt-lang 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/docs/index.html +4 -3
- data/lib/milk_tea/base.rb +1 -1
- data/std/asset_pack.mt +267 -0
- data/std/async/libuv_runtime.mt +539 -0
- data/std/async/mailbox.mt +191 -0
- data/std/async/runtime.mt +87 -0
- data/std/async.mt +87 -0
- data/std/base64.mt +185 -0
- data/std/behavior_tree.mt +396 -0
- data/std/binary.mt +314 -0
- data/std/binary_heap.mt +157 -0
- data/std/bitset.mt +239 -0
- data/std/box2d.mt +535 -0
- data/std/bytes.mt +46 -0
- data/std/c/box2d.mt +1254 -0
- data/std/c/cgltf.mt +647 -0
- data/std/c/cjson.mt +106 -0
- data/std/c/crypto.mt +11 -0
- data/std/c/crypto_support.h +51 -0
- data/std/c/ctype.mt +19 -0
- data/std/c/ctype_bindgen.h +29 -0
- data/std/c/curl.mt +1223 -0
- data/std/c/enet.mt +473 -0
- data/std/c/errno.mt +41 -0
- data/std/c/errno_bindgen.h +53 -0
- data/std/c/flecs.mt +2945 -0
- data/std/c/fs.linux.mt +43 -0
- data/std/c/fs.windows.mt +43 -0
- data/std/c/fs_support.h +954 -0
- data/std/c/gl.mt +2065 -0
- data/std/c/gl_registry_helpers.h +10748 -0
- data/std/c/glfw.mt +499 -0
- data/std/c/libc.mt +167 -0
- data/std/c/libuv.mt +1491 -0
- data/std/c/math.mt +22 -0
- data/std/c/math_bindgen.h +31 -0
- data/std/c/miniaudio.mt +3420 -0
- data/std/c/pcre2.mt +735 -0
- data/std/c/process.mt +58 -0
- data/std/c/process_support.h +1147 -0
- data/std/c/raygui.mt +1602 -0
- data/std/c/raylib.mt +1245 -0
- data/std/c/raymath.mt +163 -0
- data/std/c/rlgl.mt +434 -0
- data/std/c/rpng.mt +60 -0
- data/std/c/rres.mt +187 -0
- data/std/c/sdl3.mt +4132 -0
- data/std/c/sqlite3.mt +951 -0
- data/std/c/stb_image.mt +52 -0
- data/std/c/stb_image_resize2.mt +128 -0
- data/std/c/stb_image_write.mt +19 -0
- data/std/c/stb_rect_pack.mt +38 -0
- data/std/c/stb_truetype.mt +175 -0
- data/std/c/stb_vorbis.mt +31 -0
- data/std/c/stdio.mt +90 -0
- data/std/c/steamworks.h +5769 -0
- data/std/c/steamworks.mt +4771 -0
- data/std/c/string.mt +16 -0
- data/std/c/string_bindgen.h +36 -0
- data/std/c/sync.mt +33 -0
- data/std/c/sync_support.h +219 -0
- data/std/c/terminal.mt +24 -0
- data/std/c/terminal_support.h +408 -0
- data/std/c/time.mt +26 -0
- data/std/c/tls.mt +24 -0
- data/std/c/tls_support.h +626 -0
- data/std/c/tracy.mt +53 -0
- data/std/c/zlib.mt +20 -0
- data/std/c/zlib_support.h +239 -0
- data/std/c/zstd.mt +231 -0
- data/std/cell.mt +60 -0
- data/std/cgltf.mt +115 -0
- data/std/cjson.mt +90 -0
- data/std/cli.mt +768 -0
- data/std/cookie.mt +198 -0
- data/std/counter.mt +160 -0
- data/std/crypto.mt +74 -0
- data/std/cstring.mt +13 -0
- data/std/ctype.mt +52 -0
- data/std/curl/runtime.mt +261 -0
- data/std/curl.mt +38 -0
- data/std/deque.mt +348 -0
- data/std/encoding.mt +93 -0
- data/std/enet.mt +133 -0
- data/std/env.mt +41 -0
- data/std/errno.mt +47 -0
- data/std/flecs.mt +978 -0
- data/std/fmt.mt +271 -0
- data/std/fs.linux.mt +696 -0
- data/std/fs.windows.mt +711 -0
- data/std/fsm.mt +267 -0
- data/std/gl.mt +2062 -0
- data/std/glfw.mt +471 -0
- data/std/goap.mt +342 -0
- data/std/graph.mt +521 -0
- data/std/gzip.mt +77 -0
- data/std/hash.mt +429 -0
- data/std/http/server.mt +810 -0
- data/std/http.mt +1227 -0
- data/std/intern.mt +53 -0
- data/std/jobs.mt +288 -0
- data/std/json.mt +627 -0
- data/std/libc.mt +34 -0
- data/std/libuv.mt +554 -0
- data/std/linear_algebra.mt +243 -0
- data/std/linked_map.mt +372 -0
- data/std/linked_map_view.mt +49 -0
- data/std/linked_set.mt +117 -0
- data/std/log.mt +69 -0
- data/std/map.mt +418 -0
- data/std/math.mt +24 -0
- data/std/mem/arena.mt +137 -0
- data/std/mem/endian.mt +51 -0
- data/std/mem/heap.mt +298 -0
- data/std/mem/pool.mt +164 -0
- data/std/mem/stack.mt +47 -0
- data/std/mem/tracking.mt +119 -0
- data/std/miniaudio.mt +1299 -0
- data/std/multiset.mt +191 -0
- data/std/net/channel.mt +727 -0
- data/std/net/clock.mt +237 -0
- data/std/net/discovery.mt +277 -0
- data/std/net/lobby.mt +813 -0
- data/std/net/manager.mt +539 -0
- data/std/net/mux.mt +839 -0
- data/std/net/nat.mt +122 -0
- data/std/net/packet.mt +219 -0
- data/std/net/punch.mt +162 -0
- data/std/net/rpc.mt +119 -0
- data/std/net/session.mt +1157 -0
- data/std/net/stun.mt +252 -0
- data/std/net/sync.mt +183 -0
- data/std/net/turn.mt +459 -0
- data/std/net.mt +2944 -0
- data/std/oauth2.mt +408 -0
- data/std/option.mt +51 -0
- data/std/ordered_map.mt +497 -0
- data/std/ordered_set.mt +348 -0
- data/std/path.mt +368 -0
- data/std/pcre2/runtime.mt +35 -0
- data/std/pcre2.mt +78 -0
- data/std/priority_queue.mt +55 -0
- data/std/process.mt +837 -0
- data/std/queue.mt +55 -0
- data/std/random.mt +146 -0
- data/std/raygui.mt +99 -0
- data/std/raylib/debug_console.mt +71 -0
- data/std/raylib/easing.mt +388 -0
- data/std/raylib/packed_assets.mt +255 -0
- data/std/raylib/runtime.mt +30 -0
- data/std/raylib/tracy_gpu.mt +37 -0
- data/std/raylib.mt +1510 -0
- data/std/raymath.mt +153 -0
- data/std/result.mt +89 -0
- data/std/rlgl.mt +268 -0
- data/std/rpng.mt +46 -0
- data/std/rres.mt +36 -0
- data/std/sdl3/runtime.mt +54 -0
- data/std/sdl3.mt +1731 -0
- data/std/serialize.mt +68 -0
- data/std/set.mt +124 -0
- data/std/spatial.mt +176 -0
- data/std/sqlite3.mt +151 -0
- data/std/stack.mt +55 -0
- data/std/stb_image.mt +47 -0
- data/std/stb_image_resize2.mt +41 -0
- data/std/stb_image_write.mt +17 -0
- data/std/stb_rect_pack.mt +15 -0
- data/std/stb_truetype.mt +77 -0
- data/std/stb_vorbis.mt +16 -0
- data/std/stdio.mt +88 -0
- data/std/steamworks.mt +1542 -0
- data/std/str.mt +293 -0
- data/std/string.mt +234 -0
- data/std/sync.mt +194 -0
- data/std/tar.mt +704 -0
- data/std/terminal.mt +1002 -0
- data/std/testing.mt +266 -0
- data/std/thread.mt +120 -0
- data/std/time.mt +105 -0
- data/std/tls.mt +616 -0
- data/std/toml.mt +1310 -0
- data/std/tracy.mt +42 -0
- data/std/uri.mt +118 -0
- data/std/url.mt +372 -0
- data/std/vec.mt +433 -0
- data/std/zstd.mt +94 -0
- metadata +187 -2
|
@@ -0,0 +1,539 @@
|
|
|
1
|
+
import std.libuv as libuv
|
|
2
|
+
import std.mem.heap as heap
|
|
3
|
+
|
|
4
|
+
public type NativeLoopHandle = libuv.uv_loop_t
|
|
5
|
+
|
|
6
|
+
type NativeHandle = libuv.uv_handle_t
|
|
7
|
+
type NativeTimerHandle = libuv.uv_timer_t
|
|
8
|
+
type NativeRequest = libuv.uv_req_t
|
|
9
|
+
type NativeWorkRequest = libuv.uv_work_t
|
|
10
|
+
|
|
11
|
+
public struct Runtime:
|
|
12
|
+
loop: ptr[NativeLoopHandle]?
|
|
13
|
+
active: bool
|
|
14
|
+
|
|
15
|
+
var current_runtime: Runtime = zero[Runtime]
|
|
16
|
+
var current_runtime_active: bool = false
|
|
17
|
+
|
|
18
|
+
struct SleepState:
|
|
19
|
+
ready: bool
|
|
20
|
+
status: int
|
|
21
|
+
waiter_frame: ptr[void]?
|
|
22
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
23
|
+
waiter_registered: bool
|
|
24
|
+
timer: ptr[NativeTimerHandle]?
|
|
25
|
+
closing: bool
|
|
26
|
+
closed: bool
|
|
27
|
+
released: bool
|
|
28
|
+
|
|
29
|
+
struct WorkState[T]:
|
|
30
|
+
ready: bool
|
|
31
|
+
status: int
|
|
32
|
+
waiter_frame: ptr[void]?
|
|
33
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
34
|
+
waiter_registered: bool
|
|
35
|
+
work: ptr[NativeWorkRequest]?
|
|
36
|
+
queued: bool
|
|
37
|
+
released: bool
|
|
38
|
+
execute: fn(state_frame: ptr[void]) -> void
|
|
39
|
+
run_work: fn() -> T
|
|
40
|
+
result: T
|
|
41
|
+
|
|
42
|
+
struct WorkStateBase:
|
|
43
|
+
ready: bool
|
|
44
|
+
status: int
|
|
45
|
+
waiter_frame: ptr[void]?
|
|
46
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
47
|
+
waiter_registered: bool
|
|
48
|
+
work: ptr[NativeWorkRequest]?
|
|
49
|
+
queued: bool
|
|
50
|
+
released: bool
|
|
51
|
+
execute: fn(state_frame: ptr[void]) -> void
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
function sleep_state(frame: ptr[void]) -> ptr[SleepState]:
|
|
55
|
+
return unsafe: ptr[SleepState]<-frame
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
function work_state[T](frame: ptr[void]) -> ptr[WorkState[T]]:
|
|
59
|
+
return unsafe: ptr[WorkState[T]]<-frame
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
function work_state_base(frame: ptr[void]) -> ptr[WorkStateBase]:
|
|
63
|
+
return unsafe: ptr[WorkStateBase]<-frame
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
function timer_as_handle(timer: ptr[NativeTimerHandle]) -> ptr[NativeHandle]:
|
|
67
|
+
return unsafe: ptr[NativeHandle]<-timer
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
function handle_as_timer(handle: ptr[NativeHandle]) -> ptr[NativeTimerHandle]:
|
|
71
|
+
return unsafe: ptr[NativeTimerHandle]<-handle
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
function req_as_work(req: ptr[NativeRequest]) -> ptr[NativeWorkRequest]:
|
|
75
|
+
return unsafe: ptr[NativeWorkRequest]<-req
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
function work_as_req(work: ptr[NativeWorkRequest]) -> ptr[NativeRequest]:
|
|
79
|
+
return unsafe: ptr[NativeRequest]<-work
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
function close_all_handles_cb(handle: ptr[NativeHandle], arg: ptr[void]) -> void:
|
|
83
|
+
if libuv.is_closing(handle) == 0:
|
|
84
|
+
libuv.close(handle, close_all_handles_close_cb)
|
|
85
|
+
unsafe: arg
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
function close_all_handles_close_cb(handle: ptr[NativeHandle]) -> void:
|
|
89
|
+
unsafe: ptr[void]<-handle
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
function noop_waiter(frame: ptr[void]) -> void:
|
|
93
|
+
unsafe: frame
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
function require_current_runtime() -> Runtime:
|
|
97
|
+
if not current_runtime_active:
|
|
98
|
+
fatal(c"async runtime requires an active runtime; use async.wait or async.run, or call the explicit *_on helpers")
|
|
99
|
+
return current_runtime
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
function require_live_runtime(runtime: Runtime) -> void:
|
|
103
|
+
if not runtime.active or runtime.loop == null:
|
|
104
|
+
fatal(c"async runtime requires a live runtime")
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
function live_loop(runtime: Runtime) -> ptr[NativeLoopHandle]:
|
|
108
|
+
require_live_runtime(runtime)
|
|
109
|
+
return unsafe: ptr[NativeLoopHandle]<-runtime.loop
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
public function current_runtime_handle() -> Runtime:
|
|
113
|
+
return require_current_runtime()
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
public function runtime_loop(runtime: Runtime) -> ptr[NativeLoopHandle]:
|
|
117
|
+
return live_loop(runtime)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
function activate_current_runtime(runtime: Runtime) -> void:
|
|
121
|
+
current_runtime = runtime
|
|
122
|
+
current_runtime_active = true
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
function deactivate_current_runtime() -> void:
|
|
126
|
+
current_runtime = zero[Runtime]
|
|
127
|
+
current_runtime_active = false
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
function sleep_task(state: ptr[SleepState]) -> Task[int]:
|
|
131
|
+
return unsafe: Task[int](
|
|
132
|
+
frame = ptr[void]<-state,
|
|
133
|
+
ready = sleep_ready,
|
|
134
|
+
set_waiter = sleep_set_waiter,
|
|
135
|
+
release = sleep_release,
|
|
136
|
+
take_result = sleep_take_result
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
function work_task[T](state: ptr[WorkState[T]]) -> Task[T]:
|
|
141
|
+
return unsafe: Task[T](
|
|
142
|
+
frame = ptr[void]<-state,
|
|
143
|
+
ready = work_ready[T],
|
|
144
|
+
set_waiter = work_set_waiter[T],
|
|
145
|
+
release = work_release[T],
|
|
146
|
+
take_result = work_take_result[T]
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
function sleep_timer_close(handle: ptr[NativeHandle]) -> void:
|
|
151
|
+
let state_raw = libuv.handle_get_data(handle) else:
|
|
152
|
+
unsafe: heap.release_bytes(ptr[void]<-handle_as_timer(handle))
|
|
153
|
+
return
|
|
154
|
+
|
|
155
|
+
let state = unsafe: ptr[SleepState]<-state_raw
|
|
156
|
+
unsafe:
|
|
157
|
+
state.closed = true
|
|
158
|
+
|
|
159
|
+
let timer = handle_as_timer(handle)
|
|
160
|
+
heap.release_bytes(ptr[void]<-timer)
|
|
161
|
+
state.timer = null
|
|
162
|
+
|
|
163
|
+
if state.released:
|
|
164
|
+
heap.release(state)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
function sleep_timer_fire(timer: ptr[NativeTimerHandle]) -> void:
|
|
168
|
+
let handle = timer_as_handle(timer)
|
|
169
|
+
let state_raw = libuv.handle_get_data(handle) else:
|
|
170
|
+
return
|
|
171
|
+
|
|
172
|
+
let state = unsafe: ptr[SleepState]<-state_raw
|
|
173
|
+
unsafe:
|
|
174
|
+
state.status = 0
|
|
175
|
+
state.ready = true
|
|
176
|
+
|
|
177
|
+
if not state.closing and not state.closed:
|
|
178
|
+
state.closing = true
|
|
179
|
+
libuv.timer_stop(timer)
|
|
180
|
+
libuv.close(handle, sleep_timer_close)
|
|
181
|
+
|
|
182
|
+
if state.waiter_registered:
|
|
183
|
+
state.waiter(ptr[void]<-state.waiter_frame)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
public function runtime_create() -> Runtime:
|
|
187
|
+
let loop_size = libuv.loop_size()
|
|
188
|
+
let loop = unsafe: ptr[NativeLoopHandle]<-heap.must_alloc_zeroed_bytes(1, loop_size)
|
|
189
|
+
let init_status = libuv.loop_init(loop)
|
|
190
|
+
if init_status != 0:
|
|
191
|
+
unsafe: heap.release_bytes(ptr[void]<-loop)
|
|
192
|
+
fatal(c"async libuv runtime could not initialize event loop")
|
|
193
|
+
|
|
194
|
+
return Runtime(loop = loop, active = true)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
public function runtime_activate(runtime: Runtime) -> void:
|
|
198
|
+
require_live_runtime(runtime)
|
|
199
|
+
activate_current_runtime(runtime)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
public function runtime_deactivate() -> void:
|
|
203
|
+
deactivate_current_runtime()
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
public function runtime_release(runtime: ref[Runtime]) -> void:
|
|
207
|
+
if release_runtime(runtime) != 0:
|
|
208
|
+
fatal(c"async runtime release failed")
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
public function runtime_poll(runtime: Runtime) -> int:
|
|
212
|
+
return libuv.run(live_loop(runtime), libuv.uv_run_mode.UV_RUN_ONCE)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
public function sleep_ready(frame: ptr[void]) -> bool:
|
|
216
|
+
return unsafe: sleep_state(frame).ready
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
public function sleep_set_waiter(
|
|
220
|
+
frame: ptr[void],
|
|
221
|
+
waiter_frame: ptr[void],
|
|
222
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
223
|
+
) -> void:
|
|
224
|
+
let state = sleep_state(frame)
|
|
225
|
+
unsafe:
|
|
226
|
+
if state.ready:
|
|
227
|
+
waiter(waiter_frame)
|
|
228
|
+
return
|
|
229
|
+
|
|
230
|
+
state.waiter_frame = waiter_frame
|
|
231
|
+
state.waiter = waiter
|
|
232
|
+
state.waiter_registered = true
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
public function sleep_release(frame: ptr[void]) -> void:
|
|
236
|
+
let state = sleep_state(frame)
|
|
237
|
+
|
|
238
|
+
unsafe:
|
|
239
|
+
if state.closed:
|
|
240
|
+
heap.release(state)
|
|
241
|
+
return
|
|
242
|
+
|
|
243
|
+
state.released = true
|
|
244
|
+
if state.timer == null:
|
|
245
|
+
heap.release(state)
|
|
246
|
+
return
|
|
247
|
+
|
|
248
|
+
if not state.closing:
|
|
249
|
+
state.closing = true
|
|
250
|
+
let handle = timer_as_handle(unsafe: ptr[NativeTimerHandle]<-state.timer)
|
|
251
|
+
libuv.close(handle, sleep_timer_close)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
public function sleep_take_result(frame: ptr[void]) -> int:
|
|
255
|
+
return unsafe: sleep_state(frame).status
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
public function work_ready[T](frame: ptr[void]) -> bool:
|
|
259
|
+
return work_state[T](frame).ready
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
function work_execute(req: ptr[NativeWorkRequest]) -> void:
|
|
263
|
+
let state_raw = libuv.req_get_data(work_as_req(req)) else:
|
|
264
|
+
return
|
|
265
|
+
|
|
266
|
+
let state = work_state_base(state_raw)
|
|
267
|
+
unsafe:
|
|
268
|
+
state.execute(ptr[void]<-state)
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
function work_complete(req: ptr[NativeWorkRequest], status_code: int) -> void:
|
|
272
|
+
let state_raw = libuv.req_get_data(work_as_req(req)) else:
|
|
273
|
+
unsafe: heap.release_bytes(ptr[void]<-req)
|
|
274
|
+
return
|
|
275
|
+
|
|
276
|
+
let state = work_state_base(state_raw)
|
|
277
|
+
unsafe:
|
|
278
|
+
state.status = status_code
|
|
279
|
+
state.ready = true
|
|
280
|
+
state.queued = false
|
|
281
|
+
|
|
282
|
+
if state.waiter_registered:
|
|
283
|
+
state.waiter(ptr[void]<-state.waiter_frame)
|
|
284
|
+
|
|
285
|
+
if state.released:
|
|
286
|
+
if state.work != null:
|
|
287
|
+
heap.release_bytes(ptr[void]<-state.work)
|
|
288
|
+
state.work = null
|
|
289
|
+
heap.release(state)
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
function work_execute_state[T](state_frame: ptr[void]) -> void:
|
|
293
|
+
let state = work_state[T](state_frame)
|
|
294
|
+
unsafe:
|
|
295
|
+
state.result = state.run_work()
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
public function work_set_waiter[T](
|
|
299
|
+
frame: ptr[void],
|
|
300
|
+
waiter_frame: ptr[void],
|
|
301
|
+
waiter: fn(frame: ptr[void]) -> void
|
|
302
|
+
) -> void:
|
|
303
|
+
let state = work_state[T](frame)
|
|
304
|
+
unsafe:
|
|
305
|
+
if state.ready:
|
|
306
|
+
waiter(waiter_frame)
|
|
307
|
+
return
|
|
308
|
+
|
|
309
|
+
state.waiter_frame = waiter_frame
|
|
310
|
+
state.waiter = waiter
|
|
311
|
+
state.waiter_registered = true
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
public function work_release[T](frame: ptr[void]) -> void:
|
|
315
|
+
let state = work_state[T](frame)
|
|
316
|
+
unsafe:
|
|
317
|
+
if state.ready:
|
|
318
|
+
if state.work != null:
|
|
319
|
+
heap.release_bytes(ptr[void]<-state.work)
|
|
320
|
+
state.work = null
|
|
321
|
+
heap.release(state)
|
|
322
|
+
return
|
|
323
|
+
|
|
324
|
+
state.released = true
|
|
325
|
+
if state.queued and state.work != null:
|
|
326
|
+
libuv.cancel(work_as_req(unsafe: ptr[NativeWorkRequest]<-state.work))
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
public function work_take_result[T](frame: ptr[void]) -> T:
|
|
330
|
+
let state = work_state[T](frame)
|
|
331
|
+
if state.status != 0:
|
|
332
|
+
fatal(c"async work failed")
|
|
333
|
+
return state.result
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
public function sleep_on(runtime: Runtime, timeout: ptr_uint) -> Task[int]:
|
|
337
|
+
let loop = live_loop(runtime)
|
|
338
|
+
|
|
339
|
+
let state = heap.must_alloc_zeroed[SleepState](1)
|
|
340
|
+
unsafe:
|
|
341
|
+
state.ready = false
|
|
342
|
+
state.status = 0
|
|
343
|
+
state.waiter_frame = null
|
|
344
|
+
state.waiter = noop_waiter
|
|
345
|
+
state.waiter_registered = false
|
|
346
|
+
state.timer = null
|
|
347
|
+
state.closing = false
|
|
348
|
+
state.closed = false
|
|
349
|
+
state.released = false
|
|
350
|
+
|
|
351
|
+
let timer_size = libuv.handle_size(libuv.uv_handle_type.UV_TIMER)
|
|
352
|
+
let timer = unsafe: ptr[NativeTimerHandle]<-heap.must_alloc_zeroed_bytes(1, timer_size)
|
|
353
|
+
unsafe: state.timer = timer
|
|
354
|
+
|
|
355
|
+
let init_status = libuv.timer_init(loop, timer)
|
|
356
|
+
if init_status != 0:
|
|
357
|
+
unsafe:
|
|
358
|
+
heap.release_bytes(ptr[void]<-timer)
|
|
359
|
+
state.timer = null
|
|
360
|
+
state.closed = true
|
|
361
|
+
state.ready = true
|
|
362
|
+
state.status = init_status
|
|
363
|
+
return sleep_task(state)
|
|
364
|
+
|
|
365
|
+
unsafe:
|
|
366
|
+
libuv.handle_set_data(timer_as_handle(timer), ptr[void]<-state)
|
|
367
|
+
|
|
368
|
+
let start_status = libuv.timer_start(timer, sleep_timer_fire, timeout, 0)
|
|
369
|
+
if start_status != 0:
|
|
370
|
+
unsafe:
|
|
371
|
+
state.status = start_status
|
|
372
|
+
state.ready = true
|
|
373
|
+
state.closing = true
|
|
374
|
+
libuv.close(timer_as_handle(timer), sleep_timer_close)
|
|
375
|
+
|
|
376
|
+
return sleep_task(state)
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
public function sleep(timeout: ptr_uint) -> Task[int]:
|
|
380
|
+
return sleep_on(require_current_runtime(), timeout)
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
public function create_runtime() -> Result[Runtime, int]:
|
|
384
|
+
let loop_size = libuv.loop_size()
|
|
385
|
+
let loop = unsafe: ptr[NativeLoopHandle]<-heap.must_alloc_zeroed_bytes(1, loop_size)
|
|
386
|
+
let init_status = libuv.loop_init(loop)
|
|
387
|
+
if init_status != 0:
|
|
388
|
+
unsafe: heap.release_bytes(ptr[void]<-loop)
|
|
389
|
+
return Result[Runtime, int].failure(error= init_status)
|
|
390
|
+
|
|
391
|
+
return Result[Runtime, int].success(value= Runtime(loop = loop, active = true))
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
public function release_runtime(runtime: ref[Runtime]) -> int:
|
|
395
|
+
if not runtime.active:
|
|
396
|
+
return 0
|
|
397
|
+
|
|
398
|
+
var is_current = false
|
|
399
|
+
if current_runtime_active and current_runtime.loop == runtime.loop:
|
|
400
|
+
is_current = true
|
|
401
|
+
|
|
402
|
+
if runtime.loop == null:
|
|
403
|
+
runtime.active = false
|
|
404
|
+
if is_current:
|
|
405
|
+
runtime_deactivate()
|
|
406
|
+
return 0
|
|
407
|
+
|
|
408
|
+
let loop = unsafe: ptr[NativeLoopHandle]<-runtime.loop
|
|
409
|
+
|
|
410
|
+
var dummy: int = 0
|
|
411
|
+
libuv.walk(loop, close_all_handles_cb, unsafe: ptr[void]<-ptr_of(dummy))
|
|
412
|
+
|
|
413
|
+
var close_status = libuv.loop_close(loop)
|
|
414
|
+
while close_status != 0:
|
|
415
|
+
libuv.run(loop, libuv.uv_run_mode.UV_RUN_DEFAULT)
|
|
416
|
+
close_status = libuv.loop_close(loop)
|
|
417
|
+
|
|
418
|
+
unsafe: heap.release_bytes(ptr[void]<-loop)
|
|
419
|
+
runtime.loop = null
|
|
420
|
+
runtime.active = false
|
|
421
|
+
|
|
422
|
+
if is_current:
|
|
423
|
+
runtime_deactivate()
|
|
424
|
+
|
|
425
|
+
return 0
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
public function work_on[T](runtime: Runtime, run_work: fn() -> T) -> Task[T]:
|
|
429
|
+
let loop = live_loop(runtime)
|
|
430
|
+
let state = heap.must_alloc_zeroed[WorkState[T]](1)
|
|
431
|
+
|
|
432
|
+
let req_size = libuv.req_size(libuv.uv_req_type.UV_WORK)
|
|
433
|
+
let req = unsafe: ptr[NativeWorkRequest]<-heap.must_alloc_zeroed_bytes(1, req_size)
|
|
434
|
+
|
|
435
|
+
unsafe:
|
|
436
|
+
state.ready = false
|
|
437
|
+
state.status = 0
|
|
438
|
+
state.execute = work_execute_state[T]
|
|
439
|
+
state.run_work = run_work
|
|
440
|
+
state.waiter_frame = null
|
|
441
|
+
state.waiter = noop_waiter
|
|
442
|
+
state.waiter_registered = false
|
|
443
|
+
state.work = req
|
|
444
|
+
state.queued = false
|
|
445
|
+
state.released = false
|
|
446
|
+
|
|
447
|
+
libuv.req_set_data(work_as_req(req), ptr[void]<-state)
|
|
448
|
+
|
|
449
|
+
let queue_status = libuv.queue_work(loop, req, work_execute, work_complete)
|
|
450
|
+
unsafe:
|
|
451
|
+
if queue_status != 0:
|
|
452
|
+
state.status = queue_status
|
|
453
|
+
state.ready = true
|
|
454
|
+
state.queued = false
|
|
455
|
+
else:
|
|
456
|
+
state.queued = true
|
|
457
|
+
|
|
458
|
+
return work_task[T](state)
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
public function work[T](run_work: fn() -> T) -> Task[T]:
|
|
462
|
+
return work_on[T](require_current_runtime(), run_work)
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
public function pump(runtime: Runtime) -> void:
|
|
466
|
+
require_live_runtime(runtime)
|
|
467
|
+
runtime_poll(runtime)
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
public function completed[T](task: Task[T]) -> bool:
|
|
471
|
+
return task.ready(task.frame)
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
public function result[T](task: Task[T]) -> T:
|
|
475
|
+
if not completed[T](task):
|
|
476
|
+
fatal(c"async.result called before task completed")
|
|
477
|
+
|
|
478
|
+
defer task.release(task.frame)
|
|
479
|
+
return task.take_result(task.frame)
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
public function wait_on[T](runtime: Runtime, task: Task[T]) -> T:
|
|
483
|
+
require_live_runtime(runtime)
|
|
484
|
+
while not task.ready(task.frame):
|
|
485
|
+
runtime_poll(runtime)
|
|
486
|
+
|
|
487
|
+
defer task.release(task.frame)
|
|
488
|
+
return task.take_result(task.frame)
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
public function run_on(runtime: Runtime, task: Task[void]) -> void:
|
|
492
|
+
require_live_runtime(runtime)
|
|
493
|
+
while not task.ready(task.frame):
|
|
494
|
+
runtime_poll(runtime)
|
|
495
|
+
|
|
496
|
+
task.take_result(task.frame)
|
|
497
|
+
task.release(task.frame)
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
public function wait[T](root: proc() -> Task[T]) -> T:
|
|
501
|
+
if current_runtime_active:
|
|
502
|
+
return wait_on[T](current_runtime, root())
|
|
503
|
+
|
|
504
|
+
var runtime = runtime_create()
|
|
505
|
+
runtime_activate(runtime)
|
|
506
|
+
defer runtime_release(ref_of(runtime))
|
|
507
|
+
return wait_on[T](runtime, root())
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
public function run(root: proc() -> Task[void]) -> void:
|
|
511
|
+
if current_runtime_active:
|
|
512
|
+
run_on(current_runtime, root())
|
|
513
|
+
return
|
|
514
|
+
|
|
515
|
+
var runtime = runtime_create()
|
|
516
|
+
runtime_activate(runtime)
|
|
517
|
+
defer runtime_release(ref_of(runtime))
|
|
518
|
+
run_on(runtime, root())
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
public function with_runtime[T](body: proc(runtime: Runtime) -> T) -> T:
|
|
522
|
+
if current_runtime_active:
|
|
523
|
+
return body(current_runtime)
|
|
524
|
+
|
|
525
|
+
var runtime = runtime_create()
|
|
526
|
+
runtime_activate(runtime)
|
|
527
|
+
defer runtime_release(ref_of(runtime))
|
|
528
|
+
return body(runtime)
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
public function run_with_runtime(body: proc(runtime: Runtime) -> void) -> void:
|
|
532
|
+
if current_runtime_active:
|
|
533
|
+
body(current_runtime)
|
|
534
|
+
return
|
|
535
|
+
|
|
536
|
+
var runtime = runtime_create()
|
|
537
|
+
runtime_activate(runtime)
|
|
538
|
+
defer runtime_release(ref_of(runtime))
|
|
539
|
+
body(runtime)
|