@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,42 @@
1
+ #def Mpsc_SIZE = 32
2
+ #def Mpsc_cap = +0
3
+ #def Mpsc_head = +8
4
+ #def Mpsc_tail = +16
5
+ #def Mpsc_data = +32
6
+
7
+ #def Mpsc_SLOT_SIZE = 16
8
+ #def Mpsc_SLOT_value = +0
9
+ #def Mpsc_SLOT_ready = +8
10
+ #def Mpsc_SLOT_EMPTY = 0
11
+ #def Mpsc_SLOT_READY = 1
12
+
13
+ #def SendErrorU64_SIZE = 8
14
+ #def SendErrorU64_ALIGN = 8
15
+ #def SendErrorU64_value = +0
16
+
17
+ #def RecvError_SIZE = 0
18
+ #def RecvError_ALIGN = 1
19
+
20
+ #def TryRecvError_SIZE = 8
21
+ #def TryRecvError_ALIGN = 8
22
+ #def TryRecvError_kind = +0
23
+ #def TRY_RECV_ERROR_EMPTY = 0
24
+ #def TRY_RECV_ERROR_DISCONNECTED = 1
25
+
26
+ #def RecvTimeoutError_SIZE = 8
27
+ #def RecvTimeoutError_ALIGN = 8
28
+ #def RecvTimeoutError_kind = +0
29
+ #def RECV_TIMEOUT_ERROR_TIMEOUT = 0
30
+ #def RECV_TIMEOUT_ERROR_DISCONNECTED = 1
31
+
32
+ #def TrySendErrorU64_SIZE = 16
33
+ #def TrySendErrorU64_ALIGN = 8
34
+ #def TrySendErrorU64_kind = +0
35
+ #def TrySendErrorU64_value = +8
36
+ #def TRY_SEND_ERROR_FULL = 0
37
+ #def TRY_SEND_ERROR_DISCONNECTED = 1
38
+
39
+ #def MpscSender_SIZE = 8
40
+ #def MpscSender_chan = +0
41
+ #def MpscReceiver_SIZE = 8
42
+ #def MpscReceiver_chan = +0
@@ -0,0 +1,255 @@
1
+ // Unbounded channel backed by LinkedList + Mutex (single-producer multi not optimized).
2
+ // Models supportable unbounded mpsc semantics without growable ring complexity.
3
+ @import "mpsc_list.sal"
4
+ @import "mutex.sa"
5
+ @import "../collections/linked_list.sa"
6
+ @import "mpsc.sal"
7
+ @import "../time.sai"
8
+
9
+ @sa_mpsc_list_new() -> ^ptr:
10
+ L_ENTRY:
11
+ chan = alloc MpscList_SIZE
12
+ EXPAND MUTEX_NEW mtx
13
+ EXPAND LINKED_LIST_NEW list
14
+ store chan+MpscList_mutex, mtx as ptr
15
+ store chan+MpscList_list, list as ptr
16
+ return chan
17
+
18
+ @sa_mpsc_list_send(&chan: ptr, value: u64) -> void:
19
+ L_ENTRY:
20
+ mtx = load chan+MpscList_mutex as ptr
21
+ list = load chan+MpscList_list as ptr
22
+ null_ptr = 0 as ptr
23
+ disconnected = eq mtx, null_ptr
24
+ br disconnected -> L_SEND_DISCONNECTED, L_SEND_LOCK
25
+ L_SEND_LOCK:
26
+ EXPAND MUTEX_LOCK mtx
27
+ EXPAND LINKED_LIST_PUSH_BACK list, value
28
+ EXPAND MUTEX_UNLOCK mtx
29
+ !disconnected
30
+ !null_ptr
31
+ !list
32
+ !mtx
33
+ !value
34
+ return
35
+ L_SEND_DISCONNECTED:
36
+ !disconnected
37
+ !null_ptr
38
+ !list
39
+ !mtx
40
+ !value
41
+ return
42
+
43
+ @sa_mpsc_list_try_recv(&chan: ptr, &out_value: ptr) -> i32:
44
+ L_ENTRY:
45
+ mtx = load chan+MpscList_mutex as ptr
46
+ list = load chan+MpscList_list as ptr
47
+ null_ptr = 0 as ptr
48
+ disconnected = eq mtx, null_ptr
49
+ br disconnected -> L_RECV_DISCONNECTED, L_RECV_LOCK
50
+ L_RECV_LOCK:
51
+ EXPAND MUTEX_LOCK mtx
52
+ ok = call @sa_linked_list_try_pop_front(&list, &out_value)
53
+ EXPAND MUTEX_UNLOCK mtx
54
+ !disconnected
55
+ !null_ptr
56
+ !list
57
+ !mtx
58
+ !chan
59
+ !out_value
60
+ return ok
61
+ L_RECV_DISCONNECTED:
62
+ store out_value+0, 0 as u64
63
+ !disconnected
64
+ !null_ptr
65
+ !list
66
+ !mtx
67
+ !chan
68
+ !out_value
69
+ return 0
70
+
71
+ @sa_mpsc_list_free(&chan: ptr) -> void:
72
+ L_ENTRY:
73
+ list = load chan+MpscList_list as ptr
74
+ mtx = load chan+MpscList_mutex as ptr
75
+ null_ptr = 0 as ptr
76
+ closed = eq mtx, null_ptr
77
+ br closed -> L_FREE_ALREADY, L_FREE_CLOSE
78
+ L_FREE_ALREADY:
79
+ !mtx
80
+ !closed
81
+ !null_ptr
82
+ jmp L_FREE_DONE
83
+ L_FREE_CLOSE:
84
+ EXPAND LINKED_LIST_FREE list
85
+ EXPAND MUTEX_FREE mtx
86
+ store chan+MpscList_list, null_ptr as ptr
87
+ store chan+MpscList_mutex, null_ptr as ptr
88
+ !closed
89
+ !null_ptr
90
+ jmp L_FREE_DONE
91
+ L_FREE_DONE:
92
+ !chan
93
+ return
94
+ @sa_mpsc_list_try_recv_timeout(&chan: ptr, &out_value: ptr, timeout_ns: u64) -> i32:
95
+ L_ENTRY:
96
+ start = call @sa_time_instant_ns()
97
+ backoff_slot = stack_alloc 8
98
+ store backoff_slot+0, 1 as u64
99
+ L_TRY:
100
+ ok = call @sa_mpsc_list_try_recv(&chan, &out_value)
101
+ br ok -> L_OK, L_CHECK
102
+ L_OK:
103
+ !ok
104
+ !start
105
+ !timeout_ns
106
+ !chan
107
+ !out_value
108
+ return 1
109
+ L_CHECK:
110
+ now = call @sa_time_instant_ns()
111
+ elapsed = sub now, start
112
+ timed_out = uge elapsed, timeout_ns
113
+ br timed_out -> L_TIMEOUT, L_BACKOFF
114
+ L_BACKOFF:
115
+ backoff_ns = load backoff_slot+0 as u64
116
+ call @sa_time_sleep_ns(backoff_ns)
117
+ at_limit = uge backoff_ns, 1024
118
+ br at_limit -> L_KEEP, L_GROW
119
+ L_GROW:
120
+ next_backoff = shl backoff_ns, 1
121
+ store backoff_slot+0, next_backoff as u64
122
+ !next_backoff
123
+ !at_limit
124
+ !backoff_ns
125
+ !timed_out
126
+ !elapsed
127
+ !now
128
+ !ok
129
+ jmp L_TRY
130
+ L_KEEP:
131
+ !at_limit
132
+ !backoff_ns
133
+ !timed_out
134
+ !elapsed
135
+ !now
136
+ !ok
137
+ jmp L_TRY
138
+ L_TIMEOUT:
139
+ !timed_out
140
+ !elapsed
141
+ !now
142
+ !ok
143
+ !start
144
+ !timeout_ns
145
+ !chan
146
+ !out_value
147
+ return 0
148
+
149
+ [MACRO] MPSC_LIST_NEW %out_chan
150
+ %out_chan = call @sa_mpsc_list_new()
151
+ [END_MACRO]
152
+
153
+ [MACRO] MPSC_LIST_SEND %chan, %value
154
+ call @sa_mpsc_list_send(&%chan, %value)
155
+ [END_MACRO]
156
+
157
+ [MACRO] MPSC_LIST_TRY_RECV %out_ok, %out_value, %chan
158
+ __mpl_slot_%out_ok = stack_alloc 8
159
+ store __mpl_slot_%out_ok+0, 0 as u64
160
+ %out_ok = call @sa_mpsc_list_try_recv(&%chan, &__mpl_slot_%out_ok)
161
+ %out_value = load __mpl_slot_%out_ok+0 as u64
162
+ [END_MACRO]
163
+
164
+ [MACRO] MPSC_LIST_TRY_RECV_TIMEOUT_NS %out_ok, %out_value, %chan, %timeout_ns
165
+ __mpl_timeout_slot_%out_ok = stack_alloc 8
166
+ store __mpl_timeout_slot_%out_ok+0, 0 as u64
167
+ %out_ok = call @sa_mpsc_list_try_recv_timeout(&%chan, &__mpl_timeout_slot_%out_ok, %timeout_ns)
168
+ %out_value = load __mpl_timeout_slot_%out_ok+0 as u64
169
+ [END_MACRO]
170
+
171
+ [MACRO] MPSC_LIST_TRY_RECV_TIMEOUT_MS %out_ok, %out_value, %chan, %timeout_ms
172
+ EXPAND NUM_U64_CHECKED_MUL __mpl_timeout_mul_ok_%out_ok, __mpl_timeout_ns_%out_ok, %timeout_ms, 1000000
173
+ br __mpl_timeout_mul_ok_%out_ok -> L_MPSC_LIST_TIMEOUT_MS_OK_%out_ok, L_MPSC_LIST_TIMEOUT_MS_FAIL_%out_ok
174
+ L_MPSC_LIST_TIMEOUT_MS_OK_%out_ok:
175
+ EXPAND MPSC_LIST_TRY_RECV_TIMEOUT_NS %out_ok, %out_value, %chan, __mpl_timeout_ns_%out_ok
176
+ !__mpl_timeout_ns_%out_ok
177
+ !__mpl_timeout_mul_ok_%out_ok
178
+ jmp L_MPSC_LIST_TIMEOUT_MS_DONE_%out_ok
179
+ L_MPSC_LIST_TIMEOUT_MS_FAIL_%out_ok:
180
+ %out_ok = add 0, 0
181
+ %out_value = add 0, 0
182
+ !__mpl_timeout_ns_%out_ok
183
+ !__mpl_timeout_mul_ok_%out_ok
184
+ L_MPSC_LIST_TIMEOUT_MS_DONE_%out_ok:
185
+ [END_MACRO]
186
+
187
+ [MACRO] MPSC_LIST_FREE %chan
188
+ call @sa_mpsc_list_free(&%chan)
189
+ [END_MACRO]
190
+
191
+ [MACRO] MPSC_LIST_DROP %chan
192
+ EXPAND MPSC_LIST_FREE %chan
193
+ [END_MACRO]
194
+
195
+ [MACRO] MPSC_LIST_IS_DISCONNECTED %out_bool, %chan
196
+ __mpl_disc_mtx_%out_bool = load %chan+MpscList_mutex as ptr
197
+ __mpl_disc_list_%out_bool = load %chan+MpscList_list as ptr
198
+ __mpl_disc_null_%out_bool = 0 as ptr
199
+ __mpl_disc_mtx_zero_%out_bool = eq __mpl_disc_mtx_%out_bool, __mpl_disc_null_%out_bool
200
+ __mpl_disc_list_zero_%out_bool = eq __mpl_disc_list_%out_bool, __mpl_disc_null_%out_bool
201
+ %out_bool = and __mpl_disc_mtx_zero_%out_bool, __mpl_disc_list_zero_%out_bool
202
+ !__mpl_disc_list_zero_%out_bool
203
+ !__mpl_disc_mtx_zero_%out_bool
204
+ !__mpl_disc_null_%out_bool
205
+ !__mpl_disc_list_%out_bool
206
+ !__mpl_disc_mtx_%out_bool
207
+ [END_MACRO]
208
+
209
+ [MACRO] MPSC_LIST_LEN %out_len, %chan
210
+ __mpl_len_mtx_%out_len = load %chan+MpscList_mutex as ptr
211
+ __mpl_list_%out_len = load %chan+MpscList_list as ptr
212
+ __mpl_len_null_%out_len = 0 as ptr
213
+ __mpl_len_disconnected_%out_len = eq __mpl_len_mtx_%out_len, __mpl_len_null_%out_len
214
+ br __mpl_len_disconnected_%out_len -> L_MPSC_LIST_LEN_DISCONNECTED_%out_len, L_MPSC_LIST_LEN_LOCK_%out_len
215
+ L_MPSC_LIST_LEN_LOCK_%out_len:
216
+ EXPAND MUTEX_LOCK __mpl_len_mtx_%out_len
217
+ EXPAND LINKED_LIST_LEN %out_len, __mpl_list_%out_len
218
+ EXPAND MUTEX_UNLOCK __mpl_len_mtx_%out_len
219
+ !__mpl_len_disconnected_%out_len
220
+ !__mpl_len_null_%out_len
221
+ !__mpl_list_%out_len
222
+ !__mpl_len_mtx_%out_len
223
+ jmp L_MPSC_LIST_LEN_DONE_%out_len
224
+ L_MPSC_LIST_LEN_DISCONNECTED_%out_len:
225
+ %out_len = add 0, 0
226
+ !__mpl_len_disconnected_%out_len
227
+ !__mpl_len_null_%out_len
228
+ !__mpl_list_%out_len
229
+ !__mpl_len_mtx_%out_len
230
+ L_MPSC_LIST_LEN_DONE_%out_len:
231
+ [END_MACRO]
232
+
233
+ [MACRO] MPSC_LIST_IS_EMPTY %out_bool, %chan
234
+ __mpl_empty_mtx_%out_bool = load %chan+MpscList_mutex as ptr
235
+ __mpl_list_e_%out_bool = load %chan+MpscList_list as ptr
236
+ __mpl_empty_null_%out_bool = 0 as ptr
237
+ __mpl_empty_disconnected_%out_bool = eq __mpl_empty_mtx_%out_bool, __mpl_empty_null_%out_bool
238
+ br __mpl_empty_disconnected_%out_bool -> L_MPSC_LIST_EMPTY_DISCONNECTED_%out_bool, L_MPSC_LIST_EMPTY_LOCK_%out_bool
239
+ L_MPSC_LIST_EMPTY_LOCK_%out_bool:
240
+ EXPAND MUTEX_LOCK __mpl_empty_mtx_%out_bool
241
+ EXPAND LINKED_LIST_IS_EMPTY %out_bool, __mpl_list_e_%out_bool
242
+ EXPAND MUTEX_UNLOCK __mpl_empty_mtx_%out_bool
243
+ !__mpl_empty_disconnected_%out_bool
244
+ !__mpl_empty_null_%out_bool
245
+ !__mpl_list_e_%out_bool
246
+ !__mpl_empty_mtx_%out_bool
247
+ jmp L_MPSC_LIST_EMPTY_DONE_%out_bool
248
+ L_MPSC_LIST_EMPTY_DISCONNECTED_%out_bool:
249
+ %out_bool = add 0, 1
250
+ !__mpl_empty_disconnected_%out_bool
251
+ !__mpl_empty_null_%out_bool
252
+ !__mpl_list_e_%out_bool
253
+ !__mpl_empty_mtx_%out_bool
254
+ L_MPSC_LIST_EMPTY_DONE_%out_bool:
255
+ [END_MACRO]
@@ -0,0 +1,3 @@
1
+ #def MpscList_SIZE = 16
2
+ #def MpscList_mutex = +0
3
+ #def MpscList_list = +8
@@ -0,0 +1,182 @@
1
+ // Concrete mutex/spinlock macros built on atomic xchg and release unlock.
2
+ @import "mutex.sal"
3
+ @import "../time.sa"
4
+ @import "../time.sai"
5
+
6
+ @__mutex_lock_spin(lock: ptr) -> void:
7
+ L_MUTEX_LOCK_INIT:
8
+ backoff_slot = stack_alloc 8
9
+ store backoff_slot+0, 1 as u64
10
+
11
+ L_MUTEX_LOCK_TRY:
12
+ prev = atomic_rmw_xchg lock+Mutex_lock, 1 as u64 acq_rel
13
+ free = eq prev, 0
14
+ br free -> L_MUTEX_LOCK_DONE, L_MUTEX_LOCK_WAIT
15
+
16
+ L_MUTEX_LOCK_WAIT:
17
+ backoff_ns = load backoff_slot+0 as u64
18
+ call @sa_time_sleep_ns(backoff_ns)
19
+ backoff_at_limit = uge backoff_ns, 1024
20
+ br backoff_at_limit -> L_MUTEX_LOCK_KEEP_BACKOFF, L_MUTEX_LOCK_GROW_BACKOFF
21
+
22
+ L_MUTEX_LOCK_GROW_BACKOFF:
23
+ next_backoff = shl backoff_ns, 1
24
+ store backoff_slot+0, next_backoff as u64
25
+ !next_backoff
26
+ !backoff_at_limit
27
+ !backoff_ns
28
+ !free
29
+ !prev
30
+ jmp L_MUTEX_LOCK_TRY
31
+
32
+ L_MUTEX_LOCK_KEEP_BACKOFF:
33
+ !backoff_at_limit
34
+ !backoff_ns
35
+ !free
36
+ !prev
37
+ jmp L_MUTEX_LOCK_TRY
38
+
39
+ L_MUTEX_LOCK_DONE:
40
+ !free
41
+ !prev
42
+ return
43
+
44
+ [MACRO] MUTEX_NEW %out_mutex
45
+ %out_mutex = alloc Mutex_SIZE
46
+ store %out_mutex+Mutex_lock, 0 as u64
47
+ [END_MACRO]
48
+
49
+ [MACRO] MUTEX_NEW_I32 %out_mutex, %value
50
+ %out_mutex = alloc 16
51
+ store %out_mutex+Mutex_lock, 0 as u64
52
+ store %out_mutex+Mutex_data, %value as i32
53
+ [END_MACRO]
54
+
55
+ [MACRO] MUTEX_LOCK %lock_ptr
56
+ call @__mutex_lock_spin(%lock_ptr)
57
+ [END_MACRO]
58
+
59
+ [MACRO] MUTEX_TRY_LOCK %out_ok, %lock_ptr
60
+ __mutex_try_prev_%out_ok = atomic_rmw_xchg %lock_ptr+Mutex_lock, 1 as u64 acq_rel
61
+ %out_ok = eq __mutex_try_prev_%out_ok, 0
62
+ !__mutex_try_prev_%out_ok
63
+ [END_MACRO]
64
+
65
+ [MACRO] MUTEX_IS_LOCKED %out_bool, %lock_ptr
66
+ __mutex_state_%out_bool = atomic_load %lock_ptr+Mutex_lock as u64 acquire
67
+ %out_bool = ne __mutex_state_%out_bool, 0
68
+ !__mutex_state_%out_bool
69
+ [END_MACRO]
70
+
71
+ [MACRO] MUTEX_UNLOCK %lock_ptr
72
+ atomic_store %lock_ptr+Mutex_lock, 0 as u64 release
73
+ [END_MACRO]
74
+
75
+ [MACRO] MUTEX_TRY_UNLOCK %out_ok, %lock_ptr
76
+ __mutex_unlock_state_%out_ok, %out_ok = cmpxchg %lock_ptr+Mutex_lock, 1, 0 as u64 acq_rel acquire
77
+ !__mutex_unlock_state_%out_ok
78
+ [END_MACRO]
79
+
80
+ [MACRO] MUTEX_FORCE_UNLOCKED %lock_ptr
81
+ atomic_store %lock_ptr+Mutex_lock, 0 as u64 release
82
+ [END_MACRO]
83
+
84
+ [MACRO] MUTEX_FREE %lock_ptr
85
+ !%lock_ptr
86
+ [END_MACRO]
87
+
88
+ [MACRO] MUTEX_DEFAULT %out_mutex
89
+ EXPAND MUTEX_NEW %out_mutex
90
+ [END_MACRO]
91
+
92
+ // Rust-style into_inner for MUTEX_NEW_I32 layout: returns stored i32 and releases lock word.
93
+ [MACRO] MUTEX_INTO_INNER_I32 %out_value, %mutex_reg
94
+ %out_value = load %mutex_reg+Mutex_data as i32
95
+ atomic_store %mutex_reg+Mutex_lock, 0 as u64 release
96
+ [END_MACRO]
97
+
98
+ // Guard layout helper: store mutex ptr in guard for unlock symmetry.
99
+ [MACRO] MUTEX_GUARD_NEW %out_guard, %mutex_reg
100
+ %out_guard = alloc MutexGuard_SIZE
101
+ store %out_guard+MutexGuard_mutex, %mutex_reg as ptr
102
+ [END_MACRO]
103
+
104
+ [MACRO] MUTEX_GUARD_UNLOCK %guard_reg
105
+ __mutex_guard_ptr_%guard_reg = load %guard_reg+MutexGuard_mutex as ptr
106
+ EXPAND MUTEX_UNLOCK __mutex_guard_ptr_%guard_reg
107
+ !__mutex_guard_ptr_%guard_reg
108
+ [END_MACRO]
109
+
110
+
111
+ [MACRO] MUTEX_GET_MUT_I32 %out_ptr, %mutex_reg
112
+ %out_ptr = ptr_add %mutex_reg, Mutex_data
113
+ [END_MACRO]
114
+
115
+ @__mutex_try_lock_timeout_ns(lock: ptr, timeout_ns: u64) -> i32:
116
+ L_ENTRY:
117
+ start = call @sa_time_instant_ns()
118
+ backoff_slot = stack_alloc 8
119
+ store backoff_slot+0, 1 as u64
120
+ jmp L_MT_TRY
121
+ L_MT_TRY:
122
+ prev = atomic_rmw_xchg lock+Mutex_lock, 1 as u64 acq_rel
123
+ free = eq prev, 0
124
+ !prev
125
+ br free -> L_MT_OK, L_MT_CHECK
126
+ L_MT_OK:
127
+ !lock
128
+ !free
129
+ !start
130
+ !timeout_ns
131
+ return 1
132
+ L_MT_CHECK:
133
+ !free
134
+ now = call @sa_time_instant_ns()
135
+ elapsed = sub now, start
136
+ timed_out = uge elapsed, timeout_ns
137
+ !now
138
+ !elapsed
139
+ br timed_out -> L_MT_TIMEOUT, L_MT_BACKOFF
140
+ L_MT_BACKOFF:
141
+ backoff_ns = load backoff_slot+0 as u64
142
+ call @sa_time_sleep_ns(backoff_ns)
143
+ at_limit = uge backoff_ns, 1024
144
+ br at_limit -> L_MT_KEEP, L_MT_GROW
145
+ L_MT_GROW:
146
+ next = shl backoff_ns, 1
147
+ store backoff_slot+0, next as u64
148
+ !next
149
+ !at_limit
150
+ !backoff_ns
151
+ !timed_out
152
+ jmp L_MT_TRY
153
+ L_MT_KEEP:
154
+ !at_limit
155
+ !backoff_ns
156
+ !timed_out
157
+ jmp L_MT_TRY
158
+ L_MT_TIMEOUT:
159
+ !lock
160
+ !timed_out
161
+ !start
162
+ !timeout_ns
163
+ return 0
164
+
165
+ [MACRO] MUTEX_TRY_LOCK_TIMEOUT_NS %out_ok, %lock_ptr, %timeout_ns
166
+ %out_ok = call @__mutex_try_lock_timeout_ns(%lock_ptr, %timeout_ns)
167
+ [END_MACRO]
168
+
169
+ [MACRO] MUTEX_TRY_LOCK_TIMEOUT_MS %out_ok, %lock_ptr, %timeout_ms
170
+ EXPAND TIME_CHECKED_MUL_NS __mutex_timeout_ms_ok_%out_ok, __mutex_timeout_ns_%out_ok, %timeout_ms, Time_NS_PER_MS
171
+ br __mutex_timeout_ms_ok_%out_ok -> L_MUTEX_TIMEOUT_MS_OK_%out_ok, L_MUTEX_TIMEOUT_MS_FAIL_%out_ok
172
+ L_MUTEX_TIMEOUT_MS_OK_%out_ok:
173
+ EXPAND MUTEX_TRY_LOCK_TIMEOUT_NS %out_ok, %lock_ptr, __mutex_timeout_ns_%out_ok
174
+ !__mutex_timeout_ms_ok_%out_ok
175
+ !__mutex_timeout_ns_%out_ok
176
+ jmp L_MUTEX_TIMEOUT_MS_DONE_%out_ok
177
+ L_MUTEX_TIMEOUT_MS_FAIL_%out_ok:
178
+ %out_ok = add 0, 0
179
+ !__mutex_timeout_ms_ok_%out_ok
180
+ !__mutex_timeout_ns_%out_ok
181
+ L_MUTEX_TIMEOUT_MS_DONE_%out_ok:
182
+ [END_MACRO]
@@ -0,0 +1,7 @@
1
+ #def Mutex_SIZE = 8
2
+ #def Mutex_lock = +0
3
+ #def Mutex_data = +8
4
+
5
+ #def MutexGuard_SIZE = 8
6
+ #def MutexGuard_mutex = +0
7
+ #def MutexGuard_data = +8