Commit 76a634c
authored
refactor(nns): Switch NNS Governance global state from static to thread_local (#2844)
# Why `governance()` and `governance_mut()` are bad
Representing the canister global state with `thread_local!` avoids using
unsafe blocks to access it. When using unsafe blocks to access it, one
can easily write code with undefined behavior by retaining references
across await boundary (more precisely, after an inter-canister call).
# Why this PR
The NNS Governance heavily depends on the accessing the global state as
`static`, and there will be a lot of refactoring needed in order to get
away with the current pattern. This PR is the first step towards getting
rid of those bad access patterns - with this change, we can gradually
migrate from using `governance()`/`governance_mut()` to using
`GOVERNANCE.with()`. When all the usage of
`governance()`/`governance_mut()` are replaced, we can delete them and
declare victory.
# What
Define the global state with `thread_local!`
(`LocalKey<RefCell<Governance>>`) while returning the raw pointer for
the existing access pattern.
# Why it is safe
The `LocalKey<RefCell<T>>` is set once and only once during
`post_upgrade` or `init`, so the pointer should remain constant, given
that the canister code is single threaded. When accessing through
`governance()` or `governance_mut()` one can still write code with
undefined behavior, but it is the same danger as what we have now.
# Why `Governance::new_uninitialized`
This is needed in order for the `thread_local!` state to be `Governance`
instead of `Option<Governance>`. We know the "uninitialized" version
won't be used except for the code in the init/post_upgrade before the
"initialized" state is set. However, there doesn't seem to be a good way
to express that understanding. An alternative is to still use
`Option<Governance>` and `unwrap()` every time, but it seems more
cumbersome.1 parent d19a1b4 commit 76a634c
2 files changed
+35
-17
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
81 | 81 | | |
82 | 82 | | |
83 | 83 | | |
84 | | - | |
85 | | - | |
86 | | - | |
87 | | - | |
88 | | - | |
89 | | - | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
90 | 91 | | |
91 | 92 | | |
92 | 93 | | |
| |||
135 | 136 | | |
136 | 137 | | |
137 | 138 | | |
138 | | - | |
| 139 | + | |
139 | 140 | | |
140 | 141 | | |
141 | 142 | | |
142 | 143 | | |
143 | 144 | | |
144 | 145 | | |
145 | 146 | | |
146 | | - | |
| 147 | + | |
147 | 148 | | |
148 | 149 | | |
149 | 150 | | |
150 | 151 | | |
151 | | - | |
152 | | - | |
153 | | - | |
154 | | - | |
155 | | - | |
156 | | - | |
157 | | - | |
158 | | - | |
| 152 | + | |
159 | 153 | | |
160 | 154 | | |
161 | 155 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
117 | 117 | | |
118 | 118 | | |
119 | 119 | | |
120 | | - | |
| 120 | + | |
121 | 121 | | |
122 | 122 | | |
123 | 123 | | |
| |||
1935 | 1935 | | |
1936 | 1936 | | |
1937 | 1937 | | |
| 1938 | + | |
| 1939 | + | |
| 1940 | + | |
| 1941 | + | |
| 1942 | + | |
| 1943 | + | |
| 1944 | + | |
| 1945 | + | |
| 1946 | + | |
| 1947 | + | |
| 1948 | + | |
| 1949 | + | |
| 1950 | + | |
| 1951 | + | |
| 1952 | + | |
| 1953 | + | |
| 1954 | + | |
| 1955 | + | |
| 1956 | + | |
| 1957 | + | |
| 1958 | + | |
| 1959 | + | |
| 1960 | + | |
| 1961 | + | |
1938 | 1962 | | |
1939 | 1963 | | |
1940 | 1964 | | |
| |||
0 commit comments