lean_sys/types/mod.rs
1/*!
2Adapted from a file automatically generated by rust-bindgen 0.60.1 from `lean.h`.
3Comments adapted from `lean.h`.
4*/
5
6mod incomplete_array;
7use core::ffi::{c_char, c_int, c_uint, c_void};
8
9pub use incomplete_array::*;
10
11/**
12Lean object header.
13
14The reference counter `m_rc` field also encodes whether the object is single threaded (> 0), multi threaded (< 0), or
15reference counting is not needed (== 0). We don't use reference counting for objects stored in compact regions, or
16marked as persistent.
17
18For "small" objects stored in compact regions, the field `m_cs_sz` contains the object size. For "small" objects not
19stored in compact regions, we use the page information to retrieve its size.
20
21During deallocation and 64-bit machines, the fields `m_rc` and `m_cs_sz` store the next object in the deletion TODO list.
22These two fields together have 48-bits, and this is enough for modern computers.
23In 32-bit machines, the field `m_rc` is sufficient.
24
25The field `m_other` is used to store the number of fields in a constructor object and the element size in a scalar array.
26*/
27#[repr(C)]
28#[derive(Debug, Copy, Clone)]
29pub struct lean_object {
30 pub m_rc: c_int,
31 pub m_cs_sz: u16,
32 pub m_other: u8,
33 pub m_tag: u8,
34}
35
36/// Standard object argument
37pub type lean_obj_arg = *mut lean_object;
38/// Borrowed object argument
39pub type b_lean_obj_arg = *mut lean_object;
40/// Unique (aka non shared) object argument
41pub type u_lean_obj_arg = *mut lean_object;
42/// Standard object result
43pub type lean_obj_res = *mut lean_object;
44/// Borrowed object result
45pub type b_lean_obj_res = *mut lean_object;
46
47#[repr(C)]
48#[derive(Debug)]
49pub struct lean_ctor_object {
50 pub m_header: lean_object,
51 pub m_objs: IncompleteArrayField<*mut lean_object>,
52}
53
54/// Array arrays
55#[repr(C)]
56#[derive(Debug)]
57pub struct lean_array_object {
58 pub m_header: lean_object,
59 pub m_size: usize,
60 pub m_capacity: usize,
61 pub m_data: IncompleteArrayField<*mut lean_object>,
62}
63
64/// Scalar arrays
65#[repr(C)]
66#[derive(Debug)]
67pub struct lean_sarray_object {
68 pub m_header: lean_object,
69 pub m_size: usize,
70 pub m_capacity: usize,
71 pub m_data: IncompleteArrayField<u8>,
72}
73
74#[repr(C)]
75#[derive(Debug)]
76pub struct lean_string_object {
77 pub m_header: lean_object,
78 /// Byte length including `\0` terminator
79 pub m_size: usize,
80 pub m_capacity: usize,
81 /// UTF-8 length
82 pub m_length: usize,
83 pub m_data: IncompleteArrayField<c_char>,
84}
85
86#[repr(C)]
87#[derive(Debug)]
88pub struct lean_closure_object {
89 pub m_header: lean_object,
90 pub m_fun: *mut c_void,
91 /// Number of arguments expected by `m_fun`
92 pub m_arity: u16,
93 //TODO: already been fixed?
94 /// Number of arguments that have been already fixed
95 pub m_num_fixed: u16,
96 pub m_objs: IncompleteArrayField<*mut lean_object>,
97}
98
99#[repr(C)]
100#[derive(Debug, Copy, Clone)]
101pub struct lean_ref_object {
102 pub m_header: lean_object,
103 pub m_value: *mut lean_object,
104}
105
106#[repr(C)]
107#[derive(Debug, Copy, Clone)]
108pub struct lean_thunk_object {
109 pub m_header: lean_object,
110 pub m_value: u64,
111 pub m_closure: u64,
112}
113
114/** Data required for executing a Lean task. It is released as soon as
115the task terminates even if the task object itself is still referenced. */
116#[repr(C)]
117#[derive(Debug, Copy, Clone)]
118pub struct lean_task_imp {
119 pub m_closure: *mut lean_object,
120 pub m_head_dep: *mut lean_task_object,
121 pub m_next_dep: *mut lean_task_object,
122 pub m_prio: c_uint,
123 pub m_canceled: u8,
124 /// If true, task will not be freed until finished
125 pub m_keep_alive: u8,
126 pub m_deleted: u8,
127}
128
129/** Object of type `Task _`. The lifetime of a `lean_task` object can be represented as a state machine with atomic
130state transitions.
131
132In the following, `condition` describes a predicate uniquely identifying a state.
133
134creation:
135* Task.spawn ==> Queued
136* Task.map/bind ==> Waiting
137* Task.pure ==> Finished
138* Promise.new ==> Promised
139
140states:
141* Queued
142 * condition: in `task_manager::m_queues && m_imp != nullptr && !m_imp->m_deleted`
143 * invariant: `m_value == nullptr`
144 * transition: RC becomes 0 ==> Deactivated (`deactivate_task` lock)
145 * transition: dequeued by worker thread ==> Running (`spawn_worker` lock)
146* Waiting
147 * condition: reachable from task via `m_head_dep->m_next_dep->... && !m_imp->m_deleted`
148 * invariant: `m_imp != nullptr && m_value == nullptr`
149 * invariant: task dependency is Queued/Waiting/Running
150 * It cannot become Deactivated because this task should be holding an owned reference to it
151 * transition: RC becomes 0 ==> Deactivated (`deactivate_task` lock)
152 * transition: task dependency Finished ==> Queued (`handle_finished` under `spawn_worker` lock)
153* Promised
154 * condition: obtained as result from promise
155 * invariant: `m_imp != nullptr && m_value == nullptr`
156 * transition: promise resolved ==> Finished (`resolve_core` under `spawn_worker` lock)
157 * transition: RC becomes 0 ==> Deactivated (`deactivate_task` lock)
158* Running
159 * condition: `m_imp != nullptr && m_imp->m_closure == nullptr`
160 * The worker takes ownership of the closure when running it
161 * invariant: `m_value == nullptr`
162 * transition: RC becomes 0 ==> Deactivated (`deactivate_task` lock)
163 * transition: finished execution ==> Finished (`spawn_worker` lock)
164* Deactivated
165 * condition: `m_imp != nullptr && m_imp->m_deleted`
166 * invariant: `RC == 0`
167 * invariant: `m_imp->m_closure == nullptr && m_imp->m_head_dep == nullptr` (both freed by `deactivate_task_core`)
168 * Note that all dependent tasks must have already been Deactivated by the converse of the second Waiting invariant
169 * invariant: `m_value == nullptr`
170 * transition: dequeued by worker thread ==> freed
171 * transition: finished execution ==> freed
172 * transition: task dependency Finished ==> freed
173 * We must keep the task object alive until one of these transitions because in either case, we have live
174 (internal, unowned) references to the task up to that point
175 * transition: task dependency Deactivated ==> freed
176* Finished
177 * condition: `m_value != nullptr`
178 * invariant: `m_imp == nullptr`
179 * transition: RC becomes 0 ==> freed (`deactivate_task` lock)
180*/
181#[repr(C)]
182#[derive(Debug, Copy, Clone)]
183pub struct lean_task_object {
184 pub m_header: lean_object,
185 pub m_value: u64,
186 pub m_imp: *mut lean_task_imp,
187}
188
189#[repr(C)]
190#[derive(Debug, Copy, Clone)]
191pub struct lean_promise_object {
192 pub m_header: lean_object,
193 pub m_result: *mut lean_task_object,
194}
195
196pub type lean_external_finalize_proc = Option<unsafe extern "C" fn(arg1: *mut c_void)>;
197pub type lean_external_foreach_proc =
198 Option<unsafe extern "C" fn(arg1: *mut c_void, arg2: b_lean_obj_arg)>;
199
200/* Object for wrapping external data. */
201#[repr(C)]
202#[derive(Debug, Copy, Clone)]
203pub struct lean_external_class {
204 pub m_finalize: lean_external_finalize_proc,
205 pub m_foreach: lean_external_foreach_proc,
206}
207
208#[repr(C)]
209#[derive(Debug, Copy, Clone)]
210pub struct lean_external_object {
211 pub m_header: lean_object,
212 pub m_class: *mut lean_external_class,
213 pub m_data: *mut c_void,
214}