You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: ARCHITECTURE.md
+19-3Lines changed: 19 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -19,7 +19,16 @@ Ideally this would all be self-documenting and fool-proof, but for now it relies
19
19
20
20
## Four patterns for memory ownership
21
21
22
-
So, at the risk of producing documentation that is very prone to becoming out-of-date as things get refactored, these are the four patterns of memory ownership as manifested in the four different varieties of scanner.
22
+
So, at the risk of producing documentation that is very prone to becoming out-of-date as things get refactored, these are the four patterns of memory ownership as manifested in the four different varieties of scanner. In summary:
23
+
24
+
| Scanner pattern | Has `candidates`? |`candidates` owner | Has `buffer`? |`buffer` owner |`str_t` are slab-allocated? |
@@ -36,6 +45,8 @@ This is the most common form of scanning in Command-T, used by anything that wra
36
45
-`finders.command()` passes the `scanner` into `lib.matcher_new()`, and returns a `finder` object that exposes a `run()` function (calling `lib.matcher_run()`); the `finder` object has a reference to the `scanner`, which keeps it alive until the `finder` itself falls out of scope.
37
46
- The returned `finder` is passed into `ui.show()`, which stores a reference in the module-local `current_finder` variable, keeping the `finder` alive until the next time `ui.show()` is called and a different `finder` is passed in.
38
47
48
+
The overall ownership chain, then, is: the `finder` owns the `scanner`, the `scanner` owns its `candidates` slab and `buffer` slab, and the `str_t` structs in the `candidates` slab do not own their individual `contents` because those are all slab-allocated.
49
+
39
50
### `scanner_new()` as used by the built-in `:CommandT` finder
40
51
41
52
- The main controller (defined in `init.lua`) calls `finders.file()` to obtain a `finder`:
@@ -54,6 +65,8 @@ This is the most common form of scanning in Command-T, used by anything that wra
54
65
-`finders.file()` passes the `scanner` into `lib.matcher_new()`, and returns a `finder` object that exposes a `run()` function (calling `lib.matcher_run()`); the `finder` object has a reference to the `scanner`, which keeps it alive until the `finder` itself falls out of scope.
55
66
- The returned `finder` is passed into `ui.show()`, which stores a reference in the module-local `current_finder` variable, keeping the `finder` alive until the next time `ui.show()` is called and a different `finder` is passed in.
56
67
68
+
The overall ownership chain, then, is: the `finder` owns the `scanner`, the `scanner` assumes ownership of the `candidates` and `buffer` slabs passed into it, and the `str_t` structs in `candidates` do not own their individual `contents` because those are all slab-allocated.
69
+
57
70
### `scanner_new_copy()` as used to create "list" scanners
58
71
59
72
- The main controller (defined in `init.lua`) calls `finders.list()` to obtain a `finder`:
@@ -63,11 +76,14 @@ This is the most common form of scanning in Command-T, used by anything that wra
63
76
-`commandt_scanner_new_copy()` uses `xmap()` to create `candidates` storage (for `str_t` structs).
64
77
- It uses `str_init_copy()` to create `str_t` objects in the slab which themselves reference storage obtained via `xmalloc()` and populated with `memcpy()`. This is why, as mentioned above, "list" scanners are only suitable for smaller sets of candidates.
65
78
-`lib.scanner_new_copy()` uses `ffi.gc()` to mark the returned `scanner` such that when it is garbage-collected, the `commandt_scanner_free()` function will be called:
66
-
-`commandt_scanner_free()` will free its `candidates` (with `xmunmap()`).
67
-
- It will also free (with `xmunmap()`) its `buffer` (string storage) and the `scanner_t` struct itself.
79
+
-`commandt_scanner_free()` will free its `candidates` (with `xmunmap()`) after calling `free()` on the `contents` storage of each `str_t` in the `candidates` slab.
80
+
- It will not free its `buffer` because it does not use one.
81
+
- It will free the `scanner_t` struct itself.
68
82
-`finders.list()` passes the `scanner` into `lib.matcher_new()`, and returns a `finder` object that exposes a `run()` function (calling `lib.matcher_run()`); the `finder` object has a reference to the `scanner`, which keeps it alive until the `finder` itself falls out of scope.
69
83
- The returned `finder` is passed into `ui.show()`, which stores a reference in the module-local `current_finder` variable, keeping the `finder` alive until the next time `ui.show()` is called and a different `finder` is passed in.
70
84
85
+
The overall ownership chain, then, is: the `finder` owns the `scanner`, the `scanner` owns its `candidates` slab (but has no `buffer` slab), and the `str_t` structs in the `candidates` slab own individual `contents` allocations.
86
+
71
87
### `scanner_new_str()` as used by `:CommandTWatchman`
72
88
73
89
- The main controller (defined in `init.lua`) calls `finders.watchman()` to obtain a `finder`:
0 commit comments