Skip to content

Commit 710a0cf

Browse files
committed
docs: add table and more clarifying details
1 parent 5cffb0d commit 710a0cf

File tree

1 file changed

+19
-3
lines changed

1 file changed

+19
-3
lines changed

ARCHITECTURE.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,16 @@ Ideally this would all be self-documenting and fool-proof, but for now it relies
1919

2020
## Four patterns for memory ownership
2121

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? |
25+
| ----------------------- | ----------------- | ---------------------------- | ------------- | -------------------------------- | --------------------------- |
26+
| `scanner_new_command()` | Yes | `scanner_t` (created) | Yes | `scanner_t` (created) | Yes |
27+
| `scanner_new()` | Yes | `scanner_t` (assigned) | Yes | `scanner_t` (assigned) | Yes |
28+
| `scanner_new_copy()` | Yes | `scanner_t` (created) | No | n/a | No |
29+
| `scanner_new_str()` | Yes | `watchman_query_t` (`files`) | Yes | `wathcman_reponse_t` (`payload`) | Yes |
30+
31+
Details follow.
2332

2433
### `scanner_new_command()`
2534

@@ -36,6 +45,8 @@ This is the most common form of scanning in Command-T, used by anything that wra
3645
- `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.
3746
- 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.
3847

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+
3950
### `scanner_new()` as used by the built-in `:CommandT` finder
4051

4152
- 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
5465
- `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.
5566
- 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.
5667

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+
5770
### `scanner_new_copy()` as used to create "list" scanners
5871

5972
- 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
6376
- `commandt_scanner_new_copy()` uses `xmap()` to create `candidates` storage (for `str_t` structs).
6477
- 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.
6578
- `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.
6882
- `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.
6983
- 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.
7084

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+
7187
### `scanner_new_str()` as used by `:CommandTWatchman`
7288

7389
- The main controller (defined in `init.lua`) calls `finders.watchman()` to obtain a `finder`:

0 commit comments

Comments
 (0)