Skip to content

Commit 47bc6dd

Browse files
committed
force TLS access to go through mutex
1 parent 98c7770 commit 47bc6dd

File tree

4 files changed

+248
-217
lines changed

4 files changed

+248
-217
lines changed

crates/bevy_app/src/app.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use bevy_ecs::{
44
prelude::*,
55
schedule::{IntoSystemConfigs, IntoSystemSetConfigs, ScheduleLabel},
66
storage::{
7-
ThreadLocalAccessor, ThreadLocalTask, ThreadLocalTaskSendError, ThreadLocalTaskSender,
8-
ThreadLocals,
7+
ThreadLocalAccessor, ThreadLocalStorage, ThreadLocalTask, ThreadLocalTaskSendError,
8+
ThreadLocalTaskSender,
99
},
1010
};
1111
use bevy_utils::HashMap;
@@ -99,7 +99,7 @@ fn run_once(mut app: App) {
9999
/// ```
100100
pub struct App {
101101
sub_apps: SubApps,
102-
tls: ThreadLocals,
102+
tls: ThreadLocalStorage,
103103
/// The function that will manage the app's lifecycle.
104104
///
105105
/// Bevy provides the [`WinitPlugin`] and [`HeadlessPlugin`] for windowed and headless
@@ -155,12 +155,12 @@ impl App {
155155
main: SubApp::new(),
156156
sub_apps: HashMap::new(),
157157
},
158-
tls: ThreadLocals::new(),
158+
tls: ThreadLocalStorage::new(),
159159
runner: Some(Box::new(run_once)),
160160
}
161161
}
162162

163-
pub fn into_parts(self) -> (SubApps, ThreadLocals, Option<RunnerFn>) {
163+
pub fn into_parts(self) -> (SubApps, ThreadLocalStorage, Option<RunnerFn>) {
164164
let App {
165165
sub_apps,
166166
tls,
@@ -170,7 +170,11 @@ impl App {
170170
(sub_apps, tls, runner)
171171
}
172172

173-
pub fn from_parts(sub_apps: SubApps, tls: ThreadLocals, runner: Option<RunnerFn>) -> Self {
173+
pub fn from_parts(
174+
sub_apps: SubApps,
175+
tls: ThreadLocalStorage,
176+
runner: Option<RunnerFn>,
177+
) -> Self {
174178
App {
175179
sub_apps,
176180
tls,
@@ -182,16 +186,15 @@ impl App {
182186
///
183187
/// See [`insert_sub_app`](Self::insert_sub_app) for more details.
184188
pub fn update(&mut self) {
185-
let (mut sub_apps, mut tls, runner) = std::mem::take(self).into_parts();
189+
let (mut sub_apps, tls, runner) = std::mem::take(self).into_parts();
186190

187191
// create event loop channel
188192
let (send, recv) = std::sync::mpsc::channel();
189193

190194
// insert TLS accessor
191195
sub_apps.for_each(|sub_app| {
192-
// SAFETY: `tls` is not moved or dropped until `access` has been dropped.
193-
let access =
194-
unsafe { ThreadLocalAccessor::new(std::ptr::addr_of_mut!(tls), send.clone()) };
196+
// SAFETY: `tls` will not be dropped until `access` has been dropped.
197+
let access = unsafe { tls.make_accessor(send.clone()) };
195198
sub_app.world.insert_resource(access);
196199
});
197200

@@ -208,7 +211,7 @@ impl App {
208211
let event = recv.recv().unwrap();
209212
match event {
210213
AppThreadEvent::RunTask(f) => {
211-
f(&mut tls);
214+
f(&mut *tls.lock());
212215
}
213216
AppThreadEvent::Exit(sub_apps) => {
214217
handle.join();
@@ -475,7 +478,7 @@ impl App {
475478
/// .insert_non_send_resource(MyCounter { counter: 0 });
476479
/// ```
477480
pub fn insert_non_send_resource<R: ThreadLocalResource>(&mut self, resource: R) -> &mut Self {
478-
self.tls.insert_resource(resource);
481+
self.tls.lock().insert_resource(resource);
479482
self
480483
}
481484

@@ -485,7 +488,7 @@ impl App {
485488
/// If the [`Default`] trait is implemented, the [`FromWorld`] trait will use
486489
/// the [`Default::default`] method to initialize the [`Resource`].
487490
pub fn init_non_send_resource<R: 'static + FromWorld>(&mut self) -> &mut Self {
488-
self.tls.init_resource::<R>();
491+
self.tls.lock().init_resource::<R>();
489492
self
490493
}
491494

crates/bevy_app/src/schedule_runner.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,17 +102,15 @@ impl Plugin for ScheduleRunnerPlugin {
102102
Ok(Duration::ZERO)
103103
};
104104

105-
let (mut sub_apps, mut tls, _) = app.into_parts();
105+
let (mut sub_apps, tls, _) = app.into_parts();
106106

107107
// create event loop channel
108108
let (send, recv) = std::sync::mpsc::channel();
109109

110110
// insert TLS accessor
111111
sub_apps.for_each(|sub_app| {
112-
// SAFETY: `tls` is not moved or dropped until `access` has been dropped.
113-
let access = unsafe {
114-
ThreadLocalAccessor::new(std::ptr::addr_of_mut!(tls), send.clone())
115-
};
112+
// SAFETY: `tls` will not be dropped until `access` has been dropped.
113+
let access = unsafe { tls.make_accessor(send.clone()) };
116114
sub_app.world.insert_resource(access);
117115
});
118116

@@ -133,7 +131,7 @@ impl Plugin for ScheduleRunnerPlugin {
133131
let event = recv.recv().unwrap();
134132
match event {
135133
AppThreadEvent::RunTask(f) => {
136-
f(&mut tls);
134+
f(&mut *tls.lock());
137135
}
138136
AppThreadEvent::Exit(sub_apps) => {
139137
handle.join();

0 commit comments

Comments
 (0)