@salang/sa 0.1.2 → 0.1.4

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.
Files changed (282) hide show
  1. package/bin/sa.js +19 -1
  2. package/package.json +8 -7
  3. package/sa_std/alloc/layout.sal +12 -0
  4. package/sa_std/alloc/prelude.sa +1 -0
  5. package/sa_std/alloc/prelude.sal +1 -0
  6. package/sa_std/alloc/string.sa +3 -0
  7. package/sa_std/alloc/vec.sa +684 -0
  8. package/sa_std/alloc/vec.sal +4 -0
  9. package/sa_std/any.sa +130 -0
  10. package/sa_std/any.sal +23 -0
  11. package/sa_std/array.sa +1876 -0
  12. package/sa_std/ascii.sa +2 -0
  13. package/sa_std/ascii.sal +1 -0
  14. package/sa_std/async.sla +116 -0
  15. package/sa_std/binary_heap.sa +3003 -0
  16. package/sa_std/binary_heap.sal +7 -0
  17. package/sa_std/borrow.sa +171 -0
  18. package/sa_std/borrow.sal +13 -0
  19. package/sa_std/btree_map.sa +2210 -0
  20. package/sa_std/btree_map.sal +11 -0
  21. package/sa_std/btree_set.sa +1072 -0
  22. package/sa_std/btree_set.sal +6 -0
  23. package/sa_std/char.sa +1309 -0
  24. package/sa_std/char.sal +50 -0
  25. package/sa_std/cmp.sa +554 -0
  26. package/sa_std/cmp.sal +14 -0
  27. package/sa_std/collections/binary_heap.sa +1 -0
  28. package/sa_std/collections/btree_map.sa +1 -0
  29. package/sa_std/collections/btree_set.sa +1 -0
  30. package/sa_std/collections/hashmap.sa +1 -0
  31. package/sa_std/collections/hashset.sa +1 -0
  32. package/sa_std/collections/linked_list.sa +1120 -0
  33. package/sa_std/collections/linked_list.sal +10 -0
  34. package/sa_std/collections/prelude.sa +7 -0
  35. package/sa_std/collections/prelude.sal +1 -0
  36. package/sa_std/collections/vec_deque.sa +1 -0
  37. package/sa_std/collections.sal +13 -0
  38. package/sa_std/convert.sa +1115 -0
  39. package/sa_std/convert.sal +24 -0
  40. package/sa_std/core/arc.sa +233 -0
  41. package/sa_std/core/arc.sal +4 -0
  42. package/sa_std/core/ascii.sa +784 -0
  43. package/sa_std/core/ascii.sal +34 -0
  44. package/sa_std/core/bit.sa +41 -0
  45. package/sa_std/core/box.sa +1 -0
  46. package/sa_std/core/box.sal +2 -0
  47. package/sa_std/core/cell.sa +108 -0
  48. package/sa_std/core/cell.sal +5 -0
  49. package/sa_std/core/cleanup.sa +26 -0
  50. package/sa_std/core/control.sa +20 -0
  51. package/sa_std/core/derive.sa +60 -0
  52. package/sa_std/core/derive.sal +1 -0
  53. package/sa_std/core/dispatch.sa +7 -0
  54. package/sa_std/core/dispatch.sal +5 -0
  55. package/sa_std/core/future.sa +777 -0
  56. package/sa_std/core/future.sal +73 -0
  57. package/sa_std/core/hash.sa +48 -0
  58. package/sa_std/core/iter.sa +2805 -0
  59. package/sa_std/core/iter.sal +4 -0
  60. package/sa_std/core/loop.sa +60 -0
  61. package/sa_std/core/mem.sa +220 -0
  62. package/sa_std/core/option.sa +825 -0
  63. package/sa_std/core/option.sal +11 -0
  64. package/sa_std/core/panic.sa +23 -0
  65. package/sa_std/core/panic.sal +12 -0
  66. package/sa_std/core/prelude.sa +18 -0
  67. package/sa_std/core/prelude.sal +18 -0
  68. package/sa_std/core/rc.sa +225 -0
  69. package/sa_std/core/rc.sal +4 -0
  70. package/sa_std/core/refcell.sa +283 -0
  71. package/sa_std/core/refcell.sal +13 -0
  72. package/sa_std/core/result.sa +708 -0
  73. package/sa_std/core/result.sal +6 -0
  74. package/sa_std/core/rust_patterns.sal +295 -0
  75. package/sa_std/core/sa_core.sa +84 -0
  76. package/sa_std/core/slice.sa +4021 -0
  77. package/sa_std/core/slice.sal +7 -0
  78. package/sa_std/core/task.sa +112 -0
  79. package/sa_std/core/task.sal +15 -0
  80. package/sa_std/core/trait_object.sa +26 -0
  81. package/sa_std/core/trait_object.sal +4 -0
  82. package/sa_std/core/waker.sa +289 -0
  83. package/sa_std/core/waker.sal +31 -0
  84. package/sa_std/core/weak.sa +2 -0
  85. package/sa_std/core/weak.sal +4 -0
  86. package/sa_std/cow.sa +3 -0
  87. package/sa_std/cow.sal +2 -0
  88. package/sa_std/cstring.sa +3 -0
  89. package/sa_std/cstring.sal +2 -0
  90. package/sa_std/default.sa +99 -0
  91. package/sa_std/duration.sa +3 -0
  92. package/sa_std/duration.sal +2 -0
  93. package/sa_std/encoding/json.sa +259 -0
  94. package/sa_std/encoding/json.sai +54 -0
  95. package/sa_std/encoding/json.sal +35 -0
  96. package/sa_std/encoding/prelude.sa +1 -0
  97. package/sa_std/encoding/prelude.sal +0 -0
  98. package/sa_std/env.sa +390 -0
  99. package/sa_std/env.sai +25 -0
  100. package/sa_std/error.sa +253 -0
  101. package/sa_std/error.sal +44 -0
  102. package/sa_std/ffi/cstring.sa +3 -0
  103. package/sa_std/ffi/cstring.sal +1 -0
  104. package/sa_std/ffi/prelude.sa +2 -0
  105. package/sa_std/ffi/prelude.sal +2 -0
  106. package/sa_std/ffi.sa +635 -0
  107. package/sa_std/ffi.sal +51 -0
  108. package/sa_std/fmt.sa +2 -0
  109. package/sa_std/fmt.sai +18 -0
  110. package/sa_std/fmt.sal +35 -0
  111. package/sa_std/fs.sa +1023 -0
  112. package/sa_std/fs.sai +127 -0
  113. package/sa_std/fs.sal +51 -0
  114. package/sa_std/future.sa +2 -0
  115. package/sa_std/future.sal +1 -0
  116. package/sa_std/hash.sa +1486 -0
  117. package/sa_std/hash.sal +13 -0
  118. package/sa_std/hashmap.sa +1962 -0
  119. package/sa_std/hashmap.sal +20 -0
  120. package/sa_std/hashset.sa +1004 -0
  121. package/sa_std/hashset.sal +18 -0
  122. package/sa_std/http2.sa +78 -0
  123. package/sa_std/http2.sai +26 -0
  124. package/sa_std/http2.sal +36 -0
  125. package/sa_std/instant.sa +3 -0
  126. package/sa_std/instant.sal +2 -0
  127. package/sa_std/io/buf_reader.sa +43 -0
  128. package/sa_std/io/buf_writer.sa +35 -0
  129. package/sa_std/io/bufio.sa +4 -0
  130. package/sa_std/io/bufio.sal +4 -0
  131. package/sa_std/io/prelude.sa +1 -0
  132. package/sa_std/io/prelude.sal +1 -0
  133. package/sa_std/io/print.sa +2 -0
  134. package/sa_std/io/print.sai +3 -0
  135. package/sa_std/io.sa +925 -0
  136. package/sa_std/io.sai +25 -0
  137. package/sa_std/io.sal +84 -0
  138. package/sa_std/iter.sa +2 -0
  139. package/sa_std/iter.sal +1 -0
  140. package/sa_std/join_handle.sa +3 -0
  141. package/sa_std/join_handle.sal +2 -0
  142. package/sa_std/libsa_async.sa +80 -0
  143. package/sa_std/m_async.sa +137 -0
  144. package/sa_std/m_async.sal +30 -0
  145. package/sa_std/m_async.sla +2 -0
  146. package/sa_std/manually_drop.sa +3 -0
  147. package/sa_std/manually_drop.sal +2 -0
  148. package/sa_std/marker/phantom_data.sa +3 -0
  149. package/sa_std/marker/phantom_data.sal +1 -0
  150. package/sa_std/marker/prelude.sa +4 -0
  151. package/sa_std/marker/prelude.sal +4 -0
  152. package/sa_std/marker.sa +220 -0
  153. package/sa_std/marker.sal +15 -0
  154. package/sa_std/math.sa +84 -0
  155. package/sa_std/math.sai +10 -0
  156. package/sa_std/mem/manually_drop.sa +3 -0
  157. package/sa_std/mem/manually_drop.sal +1 -0
  158. package/sa_std/mem/prelude.sa +2 -0
  159. package/sa_std/mem/prelude.sal +2 -0
  160. package/sa_std/mem.sa +564 -0
  161. package/sa_std/mem.sal +40 -0
  162. package/sa_std/modstate.sai +19 -0
  163. package/sa_std/net.sa +4227 -0
  164. package/sa_std/net.sai +239 -0
  165. package/sa_std/net.sal +159 -0
  166. package/sa_std/netx.sa +85 -0
  167. package/sa_std/netx.sai +11 -0
  168. package/sa_std/netx.sal +39 -0
  169. package/sa_std/nonzero.sa +3 -0
  170. package/sa_std/nonzero.sal +2 -0
  171. package/sa_std/num/nonzero.sa +3 -0
  172. package/sa_std/num/nonzero.sal +1 -0
  173. package/sa_std/num/prelude.sa +3 -0
  174. package/sa_std/num/prelude.sal +3 -0
  175. package/sa_std/num.sa +17302 -0
  176. package/sa_std/num.sai +11 -0
  177. package/sa_std/num.sal +341 -0
  178. package/sa_std/ops.sa +1884 -0
  179. package/sa_std/ops.sal +68 -0
  180. package/sa_std/option.sa +2 -0
  181. package/sa_std/option.sal +1 -0
  182. package/sa_std/os/fd.sa +96 -0
  183. package/sa_std/os/fd.sai +7 -0
  184. package/sa_std/os/fd.sal +11 -0
  185. package/sa_std/os/prelude.sa +2 -0
  186. package/sa_std/os/prelude.sal +1 -0
  187. package/sa_std/os/unix_ffi.sa +271 -0
  188. package/sa_std/panic.sa +1 -0
  189. package/sa_std/panic.sal +1 -0
  190. package/sa_std/path.sa +3170 -0
  191. package/sa_std/path.sal +12 -0
  192. package/sa_std/phantom_data.sa +3 -0
  193. package/sa_std/phantom_data.sal +2 -0
  194. package/sa_std/pin.sa +79 -0
  195. package/sa_std/pin.sal +5 -0
  196. package/sa_std/plugin_async.sa +90 -0
  197. package/sa_std/plugin_async.sal +29 -0
  198. package/sa_std/plugin_async.sla +4 -0
  199. package/sa_std/plugin_http_async.sa +46 -0
  200. package/sa_std/plugin_http_server.sa +61 -0
  201. package/sa_std/plugin_http_server.sla +2 -0
  202. package/sa_std/plugin_sqlite.sa +106 -0
  203. package/sa_std/plugin_sqlite.sla +2 -0
  204. package/sa_std/prelude.sa +60 -0
  205. package/sa_std/prelude.sal +55 -0
  206. package/sa_std/process.sa +916 -0
  207. package/sa_std/process.sai +57 -0
  208. package/sa_std/process.sal +27 -0
  209. package/sa_std/ptr.sa +503 -0
  210. package/sa_std/ptr.sal +2 -0
  211. package/sa_std/result.sa +2 -0
  212. package/sa_std/result.sal +1 -0
  213. package/sa_std/rust_core.sa +51 -0
  214. package/sa_std/rust_core.sal +26 -0
  215. package/sa_std/sa.mod +7 -0
  216. package/sa_std/sort.sa +156 -0
  217. package/sa_std/str.sla +13 -0
  218. package/sa_std/string.sa +12240 -0
  219. package/sa_std/string.sai +25 -0
  220. package/sa_std/string.sal +17 -0
  221. package/sa_std/string_format.sa +269 -0
  222. package/sa_std/sync/atomic.sa +1500 -0
  223. package/sa_std/sync/atomic.sal +45 -0
  224. package/sa_std/sync/barrier.sa +105 -0
  225. package/sa_std/sync/barrier.sal +7 -0
  226. package/sa_std/sync/condvar.sa +240 -0
  227. package/sa_std/sync/condvar.sal +4 -0
  228. package/sa_std/sync/mpsc.sa +758 -0
  229. package/sa_std/sync/mpsc.sal +42 -0
  230. package/sa_std/sync/mpsc_list.sa +255 -0
  231. package/sa_std/sync/mpsc_list.sal +3 -0
  232. package/sa_std/sync/mutex.sa +182 -0
  233. package/sa_std/sync/mutex.sal +7 -0
  234. package/sa_std/sync/once.sa +371 -0
  235. package/sa_std/sync/once.sal +31 -0
  236. package/sa_std/sync/poison.sa +36 -0
  237. package/sa_std/sync/poison.sal +11 -0
  238. package/sa_std/sync/prelude.sa +8 -0
  239. package/sa_std/sync/prelude.sal +7 -0
  240. package/sa_std/sync/rwlock.sa +369 -0
  241. package/sa_std/sync/rwlock.sal +13 -0
  242. package/sa_std/task.sa +2 -0
  243. package/sa_std/task.sal +1 -0
  244. package/sa_std/term.sa +2 -0
  245. package/sa_std/term.sai +10 -0
  246. package/sa_std/term.sal +33 -0
  247. package/sa_std/testing/assert.sai +4 -0
  248. package/sa_std/testing/mock_io.sa +174 -0
  249. package/sa_std/testing/mock_io.sal +5 -0
  250. package/sa_std/testing/prelude.sa +2 -0
  251. package/sa_std/testing/prelude.sal +1 -0
  252. package/sa_std/text/prelude.sa +1 -0
  253. package/sa_std/text/prelude.sal +1 -0
  254. package/sa_std/text/regex.sa +2 -0
  255. package/sa_std/text/regex.sai +9 -0
  256. package/sa_std/text/regex.sal +33 -0
  257. package/sa_std/thread/join_handle.sa +3 -0
  258. package/sa_std/thread/join_handle.sal +1 -0
  259. package/sa_std/thread/prelude.sa +4 -0
  260. package/sa_std/thread/prelude.sal +3 -0
  261. package/sa_std/thread.sa +160 -0
  262. package/sa_std/thread.sai +11 -0
  263. package/sa_std/thread.sal +4 -0
  264. package/sa_std/thread_local.sa +45 -0
  265. package/sa_std/thread_local.sai +9 -0
  266. package/sa_std/time/duration.sa +3 -0
  267. package/sa_std/time/duration.sal +1 -0
  268. package/sa_std/time/instant.sa +3 -0
  269. package/sa_std/time/instant.sal +1 -0
  270. package/sa_std/time/prelude.sa +4 -0
  271. package/sa_std/time/prelude.sal +4 -0
  272. package/sa_std/time.sa +850 -0
  273. package/sa_std/time.sai +37 -0
  274. package/sa_std/time.sal +35 -0
  275. package/sa_std/time.sla +67 -0
  276. package/sa_std/tls_client.sai +39 -0
  277. package/sa_std/vec.sa +5754 -0
  278. package/sa_std/vec.sal +1 -0
  279. package/sa_std/vec_deque.sa +4925 -0
  280. package/sa_std/vec_deque.sal +8 -0
  281. package/sa_std/vec_runtime_macros.sa +11 -0
  282. package/sa_std/ws_client.sai +57 -0
@@ -0,0 +1,758 @@
1
+ // Bounded MPSC ring buffer built on inline storage and atomic indices.
2
+ // Payloads are raw u64 bits; callers cast at the boundary explicitly.
3
+ @import "mpsc.sal"
4
+ @import "../core/mem.sa"
5
+ @import "../num.sa"
6
+ @import "../time.sai"
7
+
8
+ @__mpsc_try_send(&chan: ptr, &value_slot: ptr) -> i32:
9
+ L_ENTRY:
10
+ cap = atomic_load chan+Mpsc_cap as u64 acquire
11
+ head = atomic_load chan+Mpsc_head as u64 acquire
12
+ tail = atomic_load chan+Mpsc_tail as u64 acquire
13
+ tail_ok = uge tail, head
14
+ br tail_ok -> L_MPSC_TRY_SEND_USED_OK, L_MPSC_TRY_SEND_CORRUPT
15
+
16
+ L_MPSC_TRY_SEND_CORRUPT:
17
+ used = add cap, 0
18
+ jmp L_MPSC_TRY_SEND_CHECK_FULL
19
+
20
+ L_MPSC_TRY_SEND_USED_OK:
21
+ used = sub tail, head
22
+
23
+ L_MPSC_TRY_SEND_CHECK_FULL:
24
+ full = uge used, cap
25
+ br full -> L_MPSC_TRY_SEND_FULL, L_MPSC_TRY_SEND_RESERVE
26
+
27
+ L_MPSC_TRY_SEND_FULL:
28
+ !full
29
+ !used
30
+ !tail_ok
31
+ !tail
32
+ !head
33
+ !cap
34
+ return 0
35
+
36
+ L_MPSC_TRY_SEND_RESERVE:
37
+ next_tail = add tail, 1
38
+ old_tail, ok = cmpxchg chan+Mpsc_tail, tail, next_tail as u64 acq_rel acquire
39
+ br ok -> L_MPSC_TRY_SEND_COMMIT, L_MPSC_TRY_SEND_RETRY
40
+
41
+ L_MPSC_TRY_SEND_RETRY:
42
+ !old_tail
43
+ !ok
44
+ !next_tail
45
+ !full
46
+ !used
47
+ !tail_ok
48
+ !tail
49
+ !head
50
+ !cap
51
+ return 0
52
+
53
+ L_MPSC_TRY_SEND_COMMIT:
54
+ slot_index = urem tail, cap
55
+ slot_base = ptr_add chan, Mpsc_data
56
+ slot_off = mul slot_index, Mpsc_SLOT_SIZE
57
+ slot = ptr_add slot_base, slot_off
58
+ message = load value_slot+0 as u64
59
+ store slot+Mpsc_SLOT_value, message as u64
60
+ atomic_store slot+Mpsc_SLOT_ready, Mpsc_SLOT_READY as u64 release
61
+ !message
62
+ !slot
63
+ !slot_index
64
+ !slot_off
65
+ !slot_base
66
+ !old_tail
67
+ !ok
68
+ !next_tail
69
+ !full
70
+ !used
71
+ !tail_ok
72
+ !tail
73
+ !head
74
+ !cap
75
+ return 1
76
+
77
+ @__mpsc_try_recv(&chan: ptr, &out_value_slot: ptr) -> i32:
78
+ L_ENTRY:
79
+ cap = atomic_load chan+Mpsc_cap as u64 acquire
80
+ head = atomic_load chan+Mpsc_head as u64 acquire
81
+ tail = atomic_load chan+Mpsc_tail as u64 acquire
82
+ tail_ok = uge tail, head
83
+ br tail_ok -> L_MPSC_TRY_RECV_ORDER_OK, L_MPSC_TRY_RECV_CORRUPT
84
+
85
+ L_MPSC_TRY_RECV_CORRUPT:
86
+ !tail_ok
87
+ !tail
88
+ !head
89
+ !cap
90
+ return 0
91
+
92
+ L_MPSC_TRY_RECV_ORDER_OK:
93
+ empty = eq head, tail
94
+ br empty -> L_MPSC_TRY_RECV_EMPTY, L_MPSC_TRY_RECV_CHECK
95
+
96
+ L_MPSC_TRY_RECV_EMPTY:
97
+ !empty
98
+ !tail_ok
99
+ !tail
100
+ !head
101
+ !cap
102
+ return 0
103
+
104
+ L_MPSC_TRY_RECV_CHECK:
105
+ slot_index = urem head, cap
106
+ slot_base = ptr_add chan, Mpsc_data
107
+ slot_off = mul slot_index, Mpsc_SLOT_SIZE
108
+ slot = ptr_add slot_base, slot_off
109
+ ready = atomic_load slot+Mpsc_SLOT_ready as u64 acquire
110
+ is_ready = eq ready, Mpsc_SLOT_READY
111
+ br is_ready -> L_MPSC_TRY_RECV_COMMIT, L_MPSC_TRY_RECV_WAIT
112
+
113
+ L_MPSC_TRY_RECV_WAIT:
114
+ !is_ready
115
+ !ready
116
+ !slot
117
+ !slot_index
118
+ !slot_off
119
+ !slot_base
120
+ !tail_ok
121
+ !tail
122
+ !head
123
+ !cap
124
+ return 0
125
+
126
+ L_MPSC_TRY_RECV_COMMIT:
127
+ message = load slot+Mpsc_SLOT_value as u64
128
+ atomic_store slot+Mpsc_SLOT_ready, Mpsc_SLOT_EMPTY as u64 release
129
+ next_head = add head, 1
130
+ atomic_store chan+Mpsc_head, next_head as u64 release
131
+ store out_value_slot+0, message as u64
132
+ !message
133
+ !next_head
134
+ !is_ready
135
+ !ready
136
+ !slot
137
+ !slot_index
138
+ !slot_off
139
+ !slot_base
140
+ !tail_ok
141
+ !tail
142
+ !head
143
+ !cap
144
+ return 1
145
+
146
+ [MACRO] MPSC_NEW %out_chan, %cap
147
+ // Keep the normalization branchless to avoid backend miscompilation
148
+ // when the cap is a constant and the whole control-flow diamond folds.
149
+ __mpsc_cap_is_zero_%out_chan = eq %cap, 0
150
+ __mpsc_cap_%out_chan = add %cap, __mpsc_cap_is_zero_%out_chan
151
+ EXPAND NUM_U64_CHECKED_MUL __mpsc_data_ok_%out_chan, __mpsc_data_bytes_%out_chan, __mpsc_cap_%out_chan, Mpsc_SLOT_SIZE
152
+ br __mpsc_data_ok_%out_chan -> L_MPSC_NEW_DATA_OK_%out_chan, L_MPSC_NEW_DATA_OVERFLOW_%out_chan
153
+ L_MPSC_NEW_DATA_OVERFLOW_%out_chan:
154
+ panic(1401)
155
+ L_MPSC_NEW_DATA_OK_%out_chan:
156
+ EXPAND NUM_U64_CHECKED_ADD __mpsc_total_ok_%out_chan, __mpsc_total_bytes_%out_chan, Mpsc_data, __mpsc_data_bytes_%out_chan
157
+ br __mpsc_total_ok_%out_chan -> L_MPSC_NEW_ALLOC_%out_chan, L_MPSC_NEW_TOTAL_OVERFLOW_%out_chan
158
+ L_MPSC_NEW_TOTAL_OVERFLOW_%out_chan:
159
+ panic(1402)
160
+ L_MPSC_NEW_ALLOC_%out_chan:
161
+ %out_chan = alloc __mpsc_total_bytes_%out_chan
162
+ call @sa_mem_set(&%out_chan, 0, __mpsc_total_bytes_%out_chan)
163
+ store %out_chan+Mpsc_cap, __mpsc_cap_%out_chan as u64
164
+ store %out_chan+Mpsc_head, 0 as u64
165
+ store %out_chan+Mpsc_tail, 0 as u64
166
+ !__mpsc_total_ok_%out_chan
167
+ !__mpsc_total_bytes_%out_chan
168
+ !__mpsc_data_ok_%out_chan
169
+ !__mpsc_data_bytes_%out_chan
170
+ !__mpsc_cap_%out_chan
171
+ !__mpsc_cap_is_zero_%out_chan
172
+ [END_MACRO]
173
+
174
+ // Concrete default capacity for Default-style construction.
175
+ // Not Rust's unbounded channel; keeps the existing bounded MPSC facade.
176
+ [MACRO] MPSC_DEFAULT %out_chan
177
+ EXPAND MPSC_NEW %out_chan, 16
178
+ [END_MACRO]
179
+
180
+ [MACRO] MPSC_SEND_ERROR_NEW %out_error, %value
181
+ %out_error = alloc SendErrorU64_SIZE
182
+ store %out_error+SendErrorU64_value, %value as u64
183
+ [END_MACRO]
184
+
185
+ [MACRO] MPSC_SEND_ERROR_VALUE %out_value, %error_reg
186
+ %out_value = load %error_reg+SendErrorU64_value as u64
187
+ [END_MACRO]
188
+
189
+ [MACRO] MPSC_TRY_SEND_ERROR_NEW %out_error, %kind, %value
190
+ %out_error = alloc TrySendErrorU64_SIZE
191
+ store %out_error+TrySendErrorU64_kind, %kind as u64
192
+ store %out_error+TrySendErrorU64_value, %value as u64
193
+ [END_MACRO]
194
+
195
+ [MACRO] MPSC_TRY_SEND_ERROR_KIND %out_kind, %error_reg
196
+ %out_kind = load %error_reg+TrySendErrorU64_kind as u64
197
+ [END_MACRO]
198
+
199
+ [MACRO] MPSC_TRY_SEND_ERROR_VALUE %out_value, %error_reg
200
+ %out_value = load %error_reg+TrySendErrorU64_value as u64
201
+ [END_MACRO]
202
+
203
+ [MACRO] MPSC_TRY_RECV_ERROR_NEW %out_error, %kind
204
+ %out_error = alloc TryRecvError_SIZE
205
+ store %out_error+TryRecvError_kind, %kind as u64
206
+ [END_MACRO]
207
+
208
+ [MACRO] MPSC_TRY_RECV_ERROR_KIND %out_kind, %error_reg
209
+ %out_kind = load %error_reg+TryRecvError_kind as u64
210
+ [END_MACRO]
211
+
212
+ [MACRO] MPSC_RECV_TIMEOUT_ERROR_NEW %out_error, %kind
213
+ %out_error = alloc RecvTimeoutError_SIZE
214
+ store %out_error+RecvTimeoutError_kind, %kind as u64
215
+ [END_MACRO]
216
+
217
+ [MACRO] MPSC_RECV_TIMEOUT_ERROR_KIND %out_kind, %error_reg
218
+ %out_kind = load %error_reg+RecvTimeoutError_kind as u64
219
+ [END_MACRO]
220
+ [MACRO] MPSC_FREE %chan
221
+ !%chan
222
+ [END_MACRO]
223
+
224
+ [MACRO] MPSC_CAPACITY %out_cap, %chan
225
+ %out_cap = atomic_load %chan+Mpsc_cap as u64 acquire
226
+ [END_MACRO]
227
+
228
+ [MACRO] MPSC_LEN %out_len, %chan
229
+ __mpsc_len_head_%out_len = atomic_load %chan+Mpsc_head as u64 acquire
230
+ __mpsc_len_tail_%out_len = atomic_load %chan+Mpsc_tail as u64 acquire
231
+ __mpsc_len_order_ok_%out_len = uge __mpsc_len_tail_%out_len, __mpsc_len_head_%out_len
232
+ br __mpsc_len_order_ok_%out_len -> L_MPSC_LEN_OK_%out_len, L_MPSC_LEN_CORRUPT_%out_len
233
+ L_MPSC_LEN_OK_%out_len:
234
+ %out_len = sub __mpsc_len_tail_%out_len, __mpsc_len_head_%out_len
235
+ !__mpsc_len_order_ok_%out_len
236
+ jmp L_MPSC_LEN_DONE_%out_len
237
+ L_MPSC_LEN_CORRUPT_%out_len:
238
+ %out_len = add 0, 0
239
+ !__mpsc_len_order_ok_%out_len
240
+ L_MPSC_LEN_DONE_%out_len:
241
+ !__mpsc_len_tail_%out_len
242
+ !__mpsc_len_head_%out_len
243
+ [END_MACRO]
244
+
245
+ [MACRO] MPSC_AVAILABLE %out_slots, %chan
246
+ __mpsc_avail_cap_%out_slots = atomic_load %chan+Mpsc_cap as u64 acquire
247
+ __mpsc_avail_head_%out_slots = atomic_load %chan+Mpsc_head as u64 acquire
248
+ __mpsc_avail_tail_%out_slots = atomic_load %chan+Mpsc_tail as u64 acquire
249
+ __mpsc_avail_order_ok_%out_slots = uge __mpsc_avail_tail_%out_slots, __mpsc_avail_head_%out_slots
250
+ br __mpsc_avail_order_ok_%out_slots -> L_MPSC_AVAIL_USED_OK_%out_slots, L_MPSC_AVAIL_CORRUPT_%out_slots
251
+ L_MPSC_AVAIL_USED_OK_%out_slots:
252
+ __mpsc_avail_used_%out_slots = sub __mpsc_avail_tail_%out_slots, __mpsc_avail_head_%out_slots
253
+ jmp L_MPSC_AVAIL_CALC_%out_slots
254
+ L_MPSC_AVAIL_CORRUPT_%out_slots:
255
+ __mpsc_avail_used_%out_slots = add __mpsc_avail_cap_%out_slots, 0
256
+ L_MPSC_AVAIL_CALC_%out_slots:
257
+ %out_slots = sub __mpsc_avail_cap_%out_slots, __mpsc_avail_used_%out_slots
258
+ !__mpsc_avail_used_%out_slots
259
+ !__mpsc_avail_order_ok_%out_slots
260
+ !__mpsc_avail_tail_%out_slots
261
+ !__mpsc_avail_head_%out_slots
262
+ !__mpsc_avail_cap_%out_slots
263
+ [END_MACRO]
264
+
265
+ [MACRO] MPSC_IS_EMPTY %out_bool, %chan
266
+ __mpsc_empty_head_%out_bool = atomic_load %chan+Mpsc_head as u64 acquire
267
+ __mpsc_empty_tail_%out_bool = atomic_load %chan+Mpsc_tail as u64 acquire
268
+ %out_bool = eq __mpsc_empty_head_%out_bool, __mpsc_empty_tail_%out_bool
269
+ !__mpsc_empty_tail_%out_bool
270
+ !__mpsc_empty_head_%out_bool
271
+ [END_MACRO]
272
+
273
+ [MACRO] MPSC_IS_FULL %out_bool, %chan
274
+ __mpsc_full_cap_%out_bool = atomic_load %chan+Mpsc_cap as u64 acquire
275
+ __mpsc_full_head_%out_bool = atomic_load %chan+Mpsc_head as u64 acquire
276
+ __mpsc_full_tail_%out_bool = atomic_load %chan+Mpsc_tail as u64 acquire
277
+ __mpsc_full_order_ok_%out_bool = uge __mpsc_full_tail_%out_bool, __mpsc_full_head_%out_bool
278
+ br __mpsc_full_order_ok_%out_bool -> L_MPSC_FULL_USED_OK_%out_bool, L_MPSC_FULL_CORRUPT_%out_bool
279
+ L_MPSC_FULL_USED_OK_%out_bool:
280
+ __mpsc_full_used_%out_bool = sub __mpsc_full_tail_%out_bool, __mpsc_full_head_%out_bool
281
+ jmp L_MPSC_FULL_CALC_%out_bool
282
+ L_MPSC_FULL_CORRUPT_%out_bool:
283
+ __mpsc_full_used_%out_bool = add __mpsc_full_cap_%out_bool, 0
284
+ L_MPSC_FULL_CALC_%out_bool:
285
+ %out_bool = uge __mpsc_full_used_%out_bool, __mpsc_full_cap_%out_bool
286
+ !__mpsc_full_used_%out_bool
287
+ !__mpsc_full_order_ok_%out_bool
288
+ !__mpsc_full_tail_%out_bool
289
+ !__mpsc_full_head_%out_bool
290
+ !__mpsc_full_cap_%out_bool
291
+ [END_MACRO]
292
+
293
+ [MACRO] MPSC_TRY_SEND_ERROR %out_ok, %out_error, %chan, %value
294
+ __mpsc_send_error_disconnected_%out_ok = eq %chan, 0
295
+ br __mpsc_send_error_disconnected_%out_ok -> L_MPSC_SEND_ERROR_DISCONNECTED_%out_ok, L_MPSC_SEND_ERROR_CALL_%out_ok
296
+ L_MPSC_SEND_ERROR_CALL_%out_ok:
297
+ EXPAND MPSC_TRY_SEND %out_ok, %chan, %value
298
+ br %out_ok -> L_MPSC_SEND_ERROR_OK_%out_ok, L_MPSC_SEND_ERROR_FULL_%out_ok
299
+ L_MPSC_SEND_ERROR_OK_%out_ok:
300
+ %out_error = add 0, 0
301
+ jmp L_MPSC_SEND_ERROR_DONE_%out_ok
302
+ L_MPSC_SEND_ERROR_FULL_%out_ok:
303
+ EXPAND MPSC_TRY_SEND_ERROR_NEW %out_error, TRY_SEND_ERROR_FULL, %value
304
+ jmp L_MPSC_SEND_ERROR_DONE_%out_ok
305
+ L_MPSC_SEND_ERROR_DISCONNECTED_%out_ok:
306
+ EXPAND MPSC_TRY_SEND_ERROR_NEW %out_error, TRY_SEND_ERROR_DISCONNECTED, %value
307
+ L_MPSC_SEND_ERROR_DONE_%out_ok:
308
+ !__mpsc_send_error_disconnected_%out_ok
309
+ [END_MACRO]
310
+
311
+ [MACRO] MPSC_TRY_RECV_ERROR %out_ok, %out_error, %out_value, %chan
312
+ __mpsc_recv_error_disconnected_%out_ok = eq %chan, 0
313
+ br __mpsc_recv_error_disconnected_%out_ok -> L_MPSC_RECV_ERROR_DISCONNECTED_%out_ok, L_MPSC_RECV_ERROR_CALL_%out_ok
314
+ L_MPSC_RECV_ERROR_CALL_%out_ok:
315
+ EXPAND MPSC_TRY_RECV %out_ok, %out_value, %chan
316
+ br %out_ok -> L_MPSC_RECV_ERROR_OK_%out_ok, L_MPSC_RECV_ERROR_EMPTY_%out_ok
317
+ L_MPSC_RECV_ERROR_OK_%out_ok:
318
+ %out_error = add 0, 0
319
+ jmp L_MPSC_RECV_ERROR_DONE_%out_ok
320
+ L_MPSC_RECV_ERROR_EMPTY_%out_ok:
321
+ EXPAND MPSC_TRY_RECV_ERROR_NEW %out_error, TRY_RECV_ERROR_EMPTY
322
+ jmp L_MPSC_RECV_ERROR_DONE_%out_ok
323
+ L_MPSC_RECV_ERROR_DISCONNECTED_%out_ok:
324
+ %out_value = add 0, 0
325
+ EXPAND MPSC_TRY_RECV_ERROR_NEW %out_error, TRY_RECV_ERROR_DISCONNECTED
326
+ L_MPSC_RECV_ERROR_DONE_%out_ok:
327
+ !__mpsc_recv_error_disconnected_%out_ok
328
+ [END_MACRO]
329
+ [MACRO] MPSC_TRY_SEND %out_ok, %chan, %value
330
+ __mpsc_value_slot_%out_ok = stack_alloc 8
331
+ store __mpsc_value_slot_%out_ok+0, %value as u64
332
+ __mpsc_ok_%out_ok = call @__mpsc_try_send(&%chan, &__mpsc_value_slot_%out_ok)
333
+ br __mpsc_ok_%out_ok -> L_MPSC_TRY_SEND_OK_%out_ok, L_MPSC_TRY_SEND_FAIL_%out_ok
334
+ L_MPSC_TRY_SEND_OK_%out_ok:
335
+ %out_ok = __mpsc_ok_%out_ok
336
+ jmp L_MPSC_TRY_SEND_DONE_%out_ok
337
+ L_MPSC_TRY_SEND_FAIL_%out_ok:
338
+ %out_ok = __mpsc_ok_%out_ok
339
+ jmp L_MPSC_TRY_SEND_DONE_%out_ok
340
+ L_MPSC_TRY_SEND_DONE_%out_ok:
341
+ [END_MACRO]
342
+
343
+ [MACRO] MPSC_SEND %chan, %value
344
+ // Keep the payload slot outside the retry loop so the allocation
345
+ // stays live across re-entry without creating phi conflicts.
346
+ __mpsc_value_slot_%value = stack_alloc 8
347
+ store __mpsc_value_slot_%value+0, %value as u64
348
+ L_MPSC_SEND_ENTRY_%value:
349
+ __mpsc_send_ok_%value = call @__mpsc_try_send(&%chan, &__mpsc_value_slot_%value)
350
+ br __mpsc_send_ok_%value -> L_MPSC_SEND_DONE_%value, L_MPSC_SEND_WAIT_%value
351
+ L_MPSC_SEND_WAIT_%value:
352
+ !__mpsc_send_ok_%value
353
+ call @sa_time_sleep_ns(1)
354
+ jmp L_MPSC_SEND_ENTRY_%value
355
+ L_MPSC_SEND_DONE_%value:
356
+ !%value
357
+ !__mpsc_send_ok_%value
358
+ [END_MACRO]
359
+
360
+ [MACRO] MPSC_TRY_RECV %out_ok, %out_value, %chan
361
+ __mpsc_value_slot_%out_ok = stack_alloc 8
362
+ __mpsc_ok_%out_ok = call @__mpsc_try_recv(&%chan, &__mpsc_value_slot_%out_ok)
363
+ br __mpsc_ok_%out_ok -> L_MPSC_TRY_RECV_OK_%out_ok, L_MPSC_TRY_RECV_FAIL_%out_ok
364
+ L_MPSC_TRY_RECV_OK_%out_ok:
365
+ %out_value = load __mpsc_value_slot_%out_ok+0 as u64
366
+ %out_ok = __mpsc_ok_%out_ok
367
+ jmp L_MPSC_TRY_RECV_DONE_%out_ok
368
+ L_MPSC_TRY_RECV_FAIL_%out_ok:
369
+ %out_value = 0 as u64
370
+ %out_ok = __mpsc_ok_%out_ok
371
+ jmp L_MPSC_TRY_RECV_DONE_%out_ok
372
+ L_MPSC_TRY_RECV_DONE_%out_ok:
373
+ [END_MACRO]
374
+
375
+ [MACRO] MPSC_RECV %out_value, %chan
376
+ // Keep the receive slot outside the retry loop for the same reason:
377
+ // the loop re-enters the same live allocation on every spin.
378
+ __mpsc_value_slot_%out_value = stack_alloc 8
379
+ L_MPSC_RECV_ENTRY_%out_value:
380
+ __mpsc_recv_ok_%out_value = call @__mpsc_try_recv(&%chan, &__mpsc_value_slot_%out_value)
381
+ br __mpsc_recv_ok_%out_value -> L_MPSC_RECV_DONE_%out_value, L_MPSC_RECV_WAIT_%out_value
382
+ L_MPSC_RECV_WAIT_%out_value:
383
+ !__mpsc_recv_ok_%out_value
384
+ call @sa_time_sleep_ns(1)
385
+ jmp L_MPSC_RECV_ENTRY_%out_value
386
+ L_MPSC_RECV_DONE_%out_value:
387
+ %out_value = load __mpsc_value_slot_%out_value+0 as u64
388
+ !__mpsc_recv_ok_%out_value
389
+ [END_MACRO]
390
+
391
+ // Concrete channel handle split: both ends share the same ring buffer pointer.
392
+ // Does not model disconnect/drop of half; free still goes through MPSC_FREE on channel.
393
+
394
+ [MACRO] MPSC_CHANNEL %out_tx, %out_rx, %cap
395
+ EXPAND MPSC_NEW __mpsc_ch_chan_%out_tx, %cap
396
+ %out_tx = alloc MpscSender_SIZE
397
+ %out_rx = alloc MpscReceiver_SIZE
398
+ store %out_tx+MpscSender_chan, __mpsc_ch_chan_%out_tx as ptr
399
+ store %out_rx+MpscReceiver_chan, __mpsc_ch_chan_%out_tx as ptr
400
+ !__mpsc_ch_chan_%out_tx
401
+ [END_MACRO]
402
+
403
+ [MACRO] MPSC_TX_IS_DISCONNECTED %out_bool, %tx
404
+ __mpsc_tx_disconnected_chan_%out_bool = load %tx+MpscSender_chan as ptr
405
+ %out_bool = eq __mpsc_tx_disconnected_chan_%out_bool, 0
406
+ !__mpsc_tx_disconnected_chan_%out_bool
407
+ [END_MACRO]
408
+
409
+ [MACRO] MPSC_RX_IS_DISCONNECTED %out_bool, %rx
410
+ __mpsc_rx_disconnected_chan_%out_bool = load %rx+MpscReceiver_chan as ptr
411
+ %out_bool = eq __mpsc_rx_disconnected_chan_%out_bool, 0
412
+ !__mpsc_rx_disconnected_chan_%out_bool
413
+ [END_MACRO]
414
+
415
+ [MACRO] MPSC_CHANNEL_IS_DISCONNECTED %out_bool, %tx, %rx
416
+ __mpsc_channel_tx_chan_%out_bool = load %tx+MpscSender_chan as ptr
417
+ __mpsc_channel_rx_chan_%out_bool = load %rx+MpscReceiver_chan as ptr
418
+ __mpsc_channel_tx_empty_%out_bool = eq __mpsc_channel_tx_chan_%out_bool, 0
419
+ __mpsc_channel_rx_empty_%out_bool = eq __mpsc_channel_rx_chan_%out_bool, 0
420
+ %out_bool = and __mpsc_channel_tx_empty_%out_bool, __mpsc_channel_rx_empty_%out_bool
421
+ !__mpsc_channel_rx_empty_%out_bool
422
+ !__mpsc_channel_tx_empty_%out_bool
423
+ !__mpsc_channel_rx_chan_%out_bool
424
+ !__mpsc_channel_tx_chan_%out_bool
425
+ [END_MACRO]
426
+ [MACRO] MPSC_TX_DROP %tx
427
+ store %tx+MpscSender_chan, 0 as ptr
428
+ [END_MACRO]
429
+
430
+ [MACRO] MPSC_RX_DROP %rx
431
+ store %rx+MpscReceiver_chan, 0 as ptr
432
+ [END_MACRO]
433
+
434
+ [MACRO] MPSC_TX_TRY_SEND %out_ok, %tx, %value
435
+ __mpsc_tx_chan_%out_ok = load %tx+MpscSender_chan as ptr
436
+ __mpsc_tx_disconnected_%out_ok = eq __mpsc_tx_chan_%out_ok, 0
437
+ br __mpsc_tx_disconnected_%out_ok -> L_MPSC_TX_TRY_SEND_FAIL_%out_ok, L_MPSC_TX_TRY_SEND_CALL_%out_ok
438
+ L_MPSC_TX_TRY_SEND_CALL_%out_ok:
439
+ EXPAND MPSC_TRY_SEND %out_ok, __mpsc_tx_chan_%out_ok, %value
440
+ !__mpsc_tx_disconnected_%out_ok
441
+ !__mpsc_tx_chan_%out_ok
442
+ jmp L_MPSC_TX_TRY_SEND_DONE_%out_ok
443
+ L_MPSC_TX_TRY_SEND_FAIL_%out_ok:
444
+ %out_ok = add 0, 0
445
+ !__mpsc_tx_disconnected_%out_ok
446
+ !__mpsc_tx_chan_%out_ok
447
+ L_MPSC_TX_TRY_SEND_DONE_%out_ok:
448
+ [END_MACRO]
449
+
450
+ [MACRO] MPSC_TX_SEND %tx, %value
451
+ __mpsc_tx_chan_s_%tx = load %tx+MpscSender_chan as ptr
452
+ __mpsc_tx_disconnected_s_%tx = eq __mpsc_tx_chan_s_%tx, 0
453
+ br __mpsc_tx_disconnected_s_%tx -> L_MPSC_TX_SEND_DONE_%tx, L_MPSC_TX_SEND_CALL_%tx
454
+ L_MPSC_TX_SEND_CALL_%tx:
455
+ EXPAND MPSC_SEND __mpsc_tx_chan_s_%tx, %value
456
+ !__mpsc_tx_disconnected_s_%tx
457
+ !__mpsc_tx_chan_s_%tx
458
+ L_MPSC_TX_SEND_DONE_%tx:
459
+ !__mpsc_tx_disconnected_s_%tx
460
+ !__mpsc_tx_chan_s_%tx
461
+ [END_MACRO]
462
+
463
+ [MACRO] MPSC_RX_TRY_RECV %out_ok, %out_value, %rx
464
+ __mpsc_rx_chan_%out_ok = load %rx+MpscReceiver_chan as ptr
465
+ __mpsc_rx_disconnected_%out_ok = eq __mpsc_rx_chan_%out_ok, 0
466
+ br __mpsc_rx_disconnected_%out_ok -> L_MPSC_RX_TRY_RECV_FAIL_%out_ok, L_MPSC_RX_TRY_RECV_CALL_%out_ok
467
+ L_MPSC_RX_TRY_RECV_CALL_%out_ok:
468
+ EXPAND MPSC_TRY_RECV %out_ok, %out_value, __mpsc_rx_chan_%out_ok
469
+ !__mpsc_rx_disconnected_%out_ok
470
+ !__mpsc_rx_chan_%out_ok
471
+ jmp L_MPSC_RX_TRY_RECV_DONE_%out_ok
472
+ L_MPSC_RX_TRY_RECV_FAIL_%out_ok:
473
+ %out_ok = add 0, 0
474
+ %out_value = add 0, 0
475
+ !__mpsc_rx_disconnected_%out_ok
476
+ !__mpsc_rx_chan_%out_ok
477
+ L_MPSC_RX_TRY_RECV_DONE_%out_ok:
478
+ [END_MACRO]
479
+
480
+ [MACRO] MPSC_RX_RECV %out_value, %rx
481
+ __mpsc_rx_chan_r_%out_value = load %rx+MpscReceiver_chan as ptr
482
+ __mpsc_rx_disconnected_r_%out_value = eq __mpsc_rx_chan_r_%out_value, 0
483
+ br __mpsc_rx_disconnected_r_%out_value -> L_MPSC_RX_RECV_EMPTY_%out_value, L_MPSC_RX_RECV_CALL_%out_value
484
+ L_MPSC_RX_RECV_CALL_%out_value:
485
+ EXPAND MPSC_RECV %out_value, __mpsc_rx_chan_r_%out_value
486
+ !__mpsc_rx_disconnected_r_%out_value
487
+ !__mpsc_rx_chan_r_%out_value
488
+ jmp L_MPSC_RX_RECV_DONE_%out_value
489
+ L_MPSC_RX_RECV_EMPTY_%out_value:
490
+ %out_value = add 0, 0
491
+ L_MPSC_RX_RECV_DONE_%out_value:
492
+ !__mpsc_rx_disconnected_r_%out_value
493
+ !__mpsc_rx_chan_r_%out_value
494
+ [END_MACRO]
495
+
496
+ [MACRO] MPSC_CHANNEL_FREE %tx, %rx
497
+ __mpsc_cf_chan_%tx = load %tx+MpscSender_chan as ptr
498
+ EXPAND MPSC_FREE __mpsc_cf_chan_%tx
499
+ EXPAND MPSC_TX_DROP %tx
500
+ EXPAND MPSC_RX_DROP %rx
501
+ [END_MACRO]
502
+ // Unbounded-style channel: large fixed capacity ring (not growable; SA subset).
503
+ [MACRO] MPSC_UNBOUNDED %out_tx, %out_rx
504
+ EXPAND MPSC_CHANNEL %out_tx, %out_rx, 1024
505
+ [END_MACRO]
506
+
507
+ [MACRO] MPSC_CHANNEL_DEFAULT %out_tx, %out_rx
508
+ EXPAND MPSC_CHANNEL %out_tx, %out_rx, 16
509
+ [END_MACRO]
510
+
511
+ @__mpsc_try_recv_timeout_ns(&chan: ptr, &out_value_slot: ptr, timeout_ns: u64) -> i32:
512
+ L_ENTRY:
513
+ start = call @sa_time_instant_ns()
514
+ backoff_slot = stack_alloc 8
515
+ store backoff_slot+0, 1 as u64
516
+ jmp L_TO_TRY
517
+ L_TO_TRY:
518
+ ok = call @__mpsc_try_recv(&chan, &out_value_slot)
519
+ br ok -> L_TO_OK, L_TO_CHECK
520
+ L_TO_OK:
521
+ !start
522
+ !timeout_ns
523
+ return 1
524
+ L_TO_CHECK:
525
+ now = call @sa_time_instant_ns()
526
+ elapsed = sub now, start
527
+ timed_out = uge elapsed, timeout_ns
528
+ !now
529
+ !elapsed
530
+ br timed_out -> L_TO_TIMEOUT, L_TO_BACKOFF
531
+ L_TO_BACKOFF:
532
+ backoff_ns = load backoff_slot+0 as u64
533
+ call @sa_time_sleep_ns(backoff_ns)
534
+ at_limit = uge backoff_ns, 1024
535
+ br at_limit -> L_TO_KEEP, L_TO_GROW
536
+ L_TO_GROW:
537
+ next = shl backoff_ns, 1
538
+ store backoff_slot+0, next as u64
539
+ !next
540
+ !at_limit
541
+ !backoff_ns
542
+ !timed_out
543
+ !ok
544
+ jmp L_TO_TRY
545
+ L_TO_KEEP:
546
+ !at_limit
547
+ !backoff_ns
548
+ !timed_out
549
+ !ok
550
+ jmp L_TO_TRY
551
+ L_TO_TIMEOUT:
552
+ !timed_out
553
+ !ok
554
+ !start
555
+ !timeout_ns
556
+ return 0
557
+
558
+ [MACRO] MPSC_TRY_RECV_TIMEOUT_ERROR %out_ok, %out_error, %out_value, %chan, %timeout_ns
559
+ __mpsc_recv_timeout_error_disconnected_%out_ok = eq %chan, 0
560
+ br __mpsc_recv_timeout_error_disconnected_%out_ok -> L_MPSC_RECV_TIMEOUT_ERROR_DISCONNECTED_%out_ok, L_MPSC_RECV_TIMEOUT_ERROR_CALL_%out_ok
561
+ L_MPSC_RECV_TIMEOUT_ERROR_CALL_%out_ok:
562
+ EXPAND MPSC_TRY_RECV_TIMEOUT_NS %out_ok, %out_value, %chan, %timeout_ns
563
+ br %out_ok -> L_MPSC_RECV_TIMEOUT_ERROR_OK_%out_ok, L_MPSC_RECV_TIMEOUT_ERROR_TIMEOUT_%out_ok
564
+ L_MPSC_RECV_TIMEOUT_ERROR_OK_%out_ok:
565
+ %out_error = add 0, 0
566
+ jmp L_MPSC_RECV_TIMEOUT_ERROR_DONE_%out_ok
567
+ L_MPSC_RECV_TIMEOUT_ERROR_TIMEOUT_%out_ok:
568
+ EXPAND MPSC_RECV_TIMEOUT_ERROR_NEW %out_error, RECV_TIMEOUT_ERROR_TIMEOUT
569
+ jmp L_MPSC_RECV_TIMEOUT_ERROR_DONE_%out_ok
570
+ L_MPSC_RECV_TIMEOUT_ERROR_DISCONNECTED_%out_ok:
571
+ %out_ok = add 0, 0
572
+ %out_value = add 0, 0
573
+ EXPAND MPSC_RECV_TIMEOUT_ERROR_NEW %out_error, RECV_TIMEOUT_ERROR_DISCONNECTED
574
+ L_MPSC_RECV_TIMEOUT_ERROR_DONE_%out_ok:
575
+ !__mpsc_recv_timeout_error_disconnected_%out_ok
576
+ [END_MACRO]
577
+
578
+ [MACRO] MPSC_RX_TRY_RECV_TIMEOUT_ERROR %out_ok, %out_error, %out_value, %rx, %timeout_ns
579
+ __mpsc_rx_timeout_error_chan_%out_ok = load %rx+MpscReceiver_chan as ptr
580
+ EXPAND MPSC_TRY_RECV_TIMEOUT_ERROR %out_ok, %out_error, %out_value, __mpsc_rx_timeout_error_chan_%out_ok, %timeout_ns
581
+ !__mpsc_rx_timeout_error_chan_%out_ok
582
+ [END_MACRO]
583
+ [MACRO] MPSC_TRY_RECV_TIMEOUT_NS %out_ok, %out_value, %chan, %timeout_ns
584
+ __mpsc_to_slot_%out_ok = stack_alloc 8
585
+ store __mpsc_to_slot_%out_ok+0, 0 as u64
586
+ %out_ok = call @__mpsc_try_recv_timeout_ns(&%chan, &__mpsc_to_slot_%out_ok, %timeout_ns)
587
+ %out_value = load __mpsc_to_slot_%out_ok+0 as u64
588
+ [END_MACRO]
589
+
590
+ [MACRO] MPSC_RX_TRY_RECV_TIMEOUT_NS %out_ok, %out_value, %rx, %timeout_ns
591
+ __mpsc_rx_to_chan_%out_ok = load %rx+MpscReceiver_chan as ptr
592
+ __mpsc_rx_to_disconnected_%out_ok = eq __mpsc_rx_to_chan_%out_ok, 0
593
+ br __mpsc_rx_to_disconnected_%out_ok -> L_MPSC_RX_TIMEOUT_EMPTY_%out_ok, L_MPSC_RX_TIMEOUT_CALL_%out_ok
594
+ L_MPSC_RX_TIMEOUT_CALL_%out_ok:
595
+ EXPAND MPSC_TRY_RECV_TIMEOUT_NS %out_ok, %out_value, __mpsc_rx_to_chan_%out_ok, %timeout_ns
596
+ jmp L_MPSC_RX_TIMEOUT_DONE_%out_ok
597
+ L_MPSC_RX_TIMEOUT_EMPTY_%out_ok:
598
+ %out_ok = add 0, 0
599
+ %out_value = add 0, 0
600
+ L_MPSC_RX_TIMEOUT_DONE_%out_ok:
601
+ !__mpsc_rx_to_disconnected_%out_ok
602
+ !__mpsc_rx_to_chan_%out_ok
603
+ [END_MACRO]
604
+
605
+ [MACRO] MPSC_TRY_RECV_TIMEOUT_MS %out_ok, %out_value, %chan, %timeout_ms
606
+ EXPAND NUM_U64_CHECKED_MUL __mpsc_recv_timeout_mul_ok_%out_ok, __mpsc_recv_timeout_ns_%out_ok, %timeout_ms, 1000000
607
+ br __mpsc_recv_timeout_mul_ok_%out_ok -> L_MPSC_RECV_TIMEOUT_MS_OK_%out_ok, L_MPSC_RECV_TIMEOUT_MS_FAIL_%out_ok
608
+ L_MPSC_RECV_TIMEOUT_MS_OK_%out_ok:
609
+ EXPAND MPSC_TRY_RECV_TIMEOUT_NS %out_ok, %out_value, %chan, __mpsc_recv_timeout_ns_%out_ok
610
+ !__mpsc_recv_timeout_ns_%out_ok
611
+ !__mpsc_recv_timeout_mul_ok_%out_ok
612
+ jmp L_MPSC_RECV_TIMEOUT_MS_DONE_%out_ok
613
+ L_MPSC_RECV_TIMEOUT_MS_FAIL_%out_ok:
614
+ %out_ok = add 0, 0
615
+ %out_value = add 0, 0
616
+ !__mpsc_recv_timeout_ns_%out_ok
617
+ !__mpsc_recv_timeout_mul_ok_%out_ok
618
+ L_MPSC_RECV_TIMEOUT_MS_DONE_%out_ok:
619
+ [END_MACRO]
620
+
621
+ [MACRO] MPSC_TRY_RECV_TIMEOUT_ERROR_MS %out_ok, %out_error, %out_value, %chan, %timeout_ms
622
+ EXPAND NUM_U64_CHECKED_MUL __mpsc_recv_error_timeout_mul_ok_%out_ok, __mpsc_recv_error_timeout_ns_%out_ok, %timeout_ms, 1000000
623
+ br __mpsc_recv_error_timeout_mul_ok_%out_ok -> L_MPSC_RECV_ERROR_TIMEOUT_MS_OK_%out_ok, L_MPSC_RECV_ERROR_TIMEOUT_MS_FAIL_%out_ok
624
+ L_MPSC_RECV_ERROR_TIMEOUT_MS_OK_%out_ok:
625
+ EXPAND MPSC_TRY_RECV_TIMEOUT_ERROR %out_ok, %out_error, %out_value, %chan, __mpsc_recv_error_timeout_ns_%out_ok
626
+ !__mpsc_recv_error_timeout_ns_%out_ok
627
+ !__mpsc_recv_error_timeout_mul_ok_%out_ok
628
+ jmp L_MPSC_RECV_ERROR_TIMEOUT_MS_DONE_%out_ok
629
+ L_MPSC_RECV_ERROR_TIMEOUT_MS_FAIL_%out_ok:
630
+ %out_ok = add 0, 0
631
+ %out_value = add 0, 0
632
+ EXPAND MPSC_RECV_TIMEOUT_ERROR_NEW %out_error, RECV_TIMEOUT_ERROR_TIMEOUT
633
+ !__mpsc_recv_error_timeout_ns_%out_ok
634
+ !__mpsc_recv_error_timeout_mul_ok_%out_ok
635
+ L_MPSC_RECV_ERROR_TIMEOUT_MS_DONE_%out_ok:
636
+ [END_MACRO]
637
+
638
+ [MACRO] MPSC_RX_TRY_RECV_TIMEOUT_ERROR_MS %out_ok, %out_error, %out_value, %rx, %timeout_ms
639
+ __mpsc_rx_error_timeout_chan_%out_ok = load %rx+MpscReceiver_chan as ptr
640
+ EXPAND MPSC_TRY_RECV_TIMEOUT_ERROR_MS %out_ok, %out_error, %out_value, __mpsc_rx_error_timeout_chan_%out_ok, %timeout_ms
641
+ !__mpsc_rx_error_timeout_chan_%out_ok
642
+ [END_MACRO]
643
+ [MACRO] MPSC_RX_TRY_RECV_TIMEOUT_MS %out_ok, %out_value, %rx, %timeout_ms
644
+ EXPAND NUM_U64_CHECKED_MUL __mpsc_rx_timeout_mul_ok_%out_ok, __mpsc_rx_timeout_ns_%out_ok, %timeout_ms, 1000000
645
+ br __mpsc_rx_timeout_mul_ok_%out_ok -> L_MPSC_RX_TIMEOUT_MS_OK_%out_ok, L_MPSC_RX_TIMEOUT_MS_FAIL_%out_ok
646
+ L_MPSC_RX_TIMEOUT_MS_OK_%out_ok:
647
+ EXPAND MPSC_RX_TRY_RECV_TIMEOUT_NS %out_ok, %out_value, %rx, __mpsc_rx_timeout_ns_%out_ok
648
+ !__mpsc_rx_timeout_ns_%out_ok
649
+ !__mpsc_rx_timeout_mul_ok_%out_ok
650
+ jmp L_MPSC_RX_TIMEOUT_MS_DONE_%out_ok
651
+ L_MPSC_RX_TIMEOUT_MS_FAIL_%out_ok:
652
+ %out_ok = add 0, 0
653
+ %out_value = add 0, 0
654
+ !__mpsc_rx_timeout_ns_%out_ok
655
+ !__mpsc_rx_timeout_mul_ok_%out_ok
656
+ L_MPSC_RX_TIMEOUT_MS_DONE_%out_ok:
657
+ [END_MACRO]
658
+
659
+ @__mpsc_try_send_timeout_ns(&chan: ptr, &value_slot: ptr, timeout_ns: u64) -> i32:
660
+ L_ENTRY:
661
+ start = call @sa_time_instant_ns()
662
+ backoff_slot = stack_alloc 8
663
+ store backoff_slot+0, 1 as u64
664
+ jmp L_ST_TRY
665
+ L_ST_TRY:
666
+ ok = call @__mpsc_try_send(&chan, &value_slot)
667
+ br ok -> L_ST_OK, L_ST_CHECK
668
+ L_ST_OK:
669
+ !chan
670
+ !value_slot
671
+ !start
672
+ !timeout_ns
673
+ return 1
674
+ L_ST_CHECK:
675
+ now = call @sa_time_instant_ns()
676
+ elapsed = sub now, start
677
+ timed_out = uge elapsed, timeout_ns
678
+ !now
679
+ !elapsed
680
+ br timed_out -> L_ST_TIMEOUT, L_ST_BACKOFF
681
+ L_ST_BACKOFF:
682
+ backoff_ns = load backoff_slot+0 as u64
683
+ call @sa_time_sleep_ns(backoff_ns)
684
+ at_limit = uge backoff_ns, 1024
685
+ br at_limit -> L_ST_KEEP, L_ST_GROW
686
+ L_ST_GROW:
687
+ next = shl backoff_ns, 1
688
+ store backoff_slot+0, next as u64
689
+ !next
690
+ !at_limit
691
+ !backoff_ns
692
+ !timed_out
693
+ !ok
694
+ jmp L_ST_TRY
695
+ L_ST_KEEP:
696
+ !at_limit
697
+ !backoff_ns
698
+ !timed_out
699
+ !ok
700
+ jmp L_ST_TRY
701
+ L_ST_TIMEOUT:
702
+ !chan
703
+ !value_slot
704
+ !timed_out
705
+ !ok
706
+ !start
707
+ !timeout_ns
708
+ return 0
709
+
710
+ [MACRO] MPSC_TRY_SEND_TIMEOUT_NS %out_ok, %chan, %value, %timeout_ns
711
+ __mpsc_st_slot_%out_ok = stack_alloc 8
712
+ store __mpsc_st_slot_%out_ok+0, %value as u64
713
+ %out_ok = call @__mpsc_try_send_timeout_ns(&%chan, &__mpsc_st_slot_%out_ok, %timeout_ns)
714
+ [END_MACRO]
715
+
716
+ [MACRO] MPSC_TX_TRY_SEND_TIMEOUT_NS %out_ok, %tx, %value, %timeout_ns
717
+ __mpsc_tx_st_chan_%out_ok = load %tx+MpscSender_chan as ptr
718
+ __mpsc_tx_st_disconnected_%out_ok = eq __mpsc_tx_st_chan_%out_ok, 0
719
+ br __mpsc_tx_st_disconnected_%out_ok -> L_MPSC_TX_TIMEOUT_FAIL_%out_ok, L_MPSC_TX_TIMEOUT_CALL_%out_ok
720
+ L_MPSC_TX_TIMEOUT_CALL_%out_ok:
721
+ EXPAND MPSC_TRY_SEND_TIMEOUT_NS %out_ok, __mpsc_tx_st_chan_%out_ok, %value, %timeout_ns
722
+ jmp L_MPSC_TX_TIMEOUT_DONE_%out_ok
723
+ L_MPSC_TX_TIMEOUT_FAIL_%out_ok:
724
+ %out_ok = add 0, 0
725
+ L_MPSC_TX_TIMEOUT_DONE_%out_ok:
726
+ !__mpsc_tx_st_disconnected_%out_ok
727
+ !__mpsc_tx_st_chan_%out_ok
728
+ [END_MACRO]
729
+
730
+ [MACRO] MPSC_TRY_SEND_TIMEOUT_MS %out_ok, %chan, %value, %timeout_ms
731
+ EXPAND NUM_U64_CHECKED_MUL __mpsc_send_timeout_mul_ok_%out_ok, __mpsc_send_timeout_ns_%out_ok, %timeout_ms, 1000000
732
+ br __mpsc_send_timeout_mul_ok_%out_ok -> L_MPSC_SEND_TIMEOUT_MS_OK_%out_ok, L_MPSC_SEND_TIMEOUT_MS_FAIL_%out_ok
733
+ L_MPSC_SEND_TIMEOUT_MS_OK_%out_ok:
734
+ EXPAND MPSC_TRY_SEND_TIMEOUT_NS %out_ok, %chan, %value, __mpsc_send_timeout_ns_%out_ok
735
+ !__mpsc_send_timeout_ns_%out_ok
736
+ !__mpsc_send_timeout_mul_ok_%out_ok
737
+ jmp L_MPSC_SEND_TIMEOUT_MS_DONE_%out_ok
738
+ L_MPSC_SEND_TIMEOUT_MS_FAIL_%out_ok:
739
+ %out_ok = add 0, 0
740
+ !__mpsc_send_timeout_ns_%out_ok
741
+ !__mpsc_send_timeout_mul_ok_%out_ok
742
+ L_MPSC_SEND_TIMEOUT_MS_DONE_%out_ok:
743
+ [END_MACRO]
744
+
745
+ [MACRO] MPSC_TX_TRY_SEND_TIMEOUT_MS %out_ok, %tx, %value, %timeout_ms
746
+ EXPAND NUM_U64_CHECKED_MUL __mpsc_tx_timeout_mul_ok_%out_ok, __mpsc_tx_timeout_ns_%out_ok, %timeout_ms, 1000000
747
+ br __mpsc_tx_timeout_mul_ok_%out_ok -> L_MPSC_TX_TIMEOUT_MS_OK_%out_ok, L_MPSC_TX_TIMEOUT_MS_FAIL_%out_ok
748
+ L_MPSC_TX_TIMEOUT_MS_OK_%out_ok:
749
+ EXPAND MPSC_TX_TRY_SEND_TIMEOUT_NS %out_ok, %tx, %value, __mpsc_tx_timeout_ns_%out_ok
750
+ !__mpsc_tx_timeout_ns_%out_ok
751
+ !__mpsc_tx_timeout_mul_ok_%out_ok
752
+ jmp L_MPSC_TX_TIMEOUT_MS_DONE_%out_ok
753
+ L_MPSC_TX_TIMEOUT_MS_FAIL_%out_ok:
754
+ %out_ok = add 0, 0
755
+ !__mpsc_tx_timeout_ns_%out_ok
756
+ !__mpsc_tx_timeout_mul_ok_%out_ok
757
+ L_MPSC_TX_TIMEOUT_MS_DONE_%out_ok:
758
+ [END_MACRO]