1#![doc(html_favicon_url = "https://raw.githubusercontent.com/zng-ui/zng/main/examples/image/res/zng-logo-icon.png")]
2#![doc(html_logo_url = "https://raw.githubusercontent.com/zng-ui/zng/main/examples/image/res/zng-logo.png")]
3#![doc = include_str!(concat!("../", std::env!("CARGO_PKG_README")))]
8#![warn(unused_extern_crates)]
9#![warn(missing_docs)]
10
11use std::{any::Any, cell::RefCell, fmt, mem, ops, sync::Arc, thread::LocalKey, time::Duration};
12
13use parking_lot::*;
14use zng_txt::Txt;
15use zng_unique_id::unique_id_32;
16
17#[doc(hidden)]
18pub use zng_unique_id::{hot_static, hot_static_ref};
19
20unique_id_32! {
21 pub struct AppId;
23}
24zng_unique_id::impl_unique_id_name!(AppId);
25zng_unique_id::impl_unique_id_fmt!(AppId);
26zng_unique_id::impl_unique_id_bytemuck!(AppId);
27
28impl serde::Serialize for AppId {
29 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
30 where
31 S: serde::Serializer,
32 {
33 let name = self.name();
34 if name.is_empty() {
35 use serde::ser::Error;
36 return Err(S::Error::custom("cannot serialize unnamed `AppId`"));
37 }
38 name.serialize(serializer)
39 }
40}
41impl<'de> serde::Deserialize<'de> for AppId {
42 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
43 where
44 D: serde::Deserializer<'de>,
45 {
46 let name = Txt::deserialize(deserializer)?;
47 Ok(AppId::named(name))
48 }
49}
50
51#[derive(Clone, Copy)]
52enum LocalValueKind {
53 Local,
54 Var,
55 App,
56}
57impl LocalValueKind {
58 fn include_local(self) -> bool {
60 !matches!(self, Self::Var)
61 }
62
63 fn include_var(self) -> bool {
65 !matches!(self, Self::Local)
66 }
67}
68
69type LocalValue = (Arc<dyn Any + Send + Sync>, LocalValueKind);
71type LocalData = std::collections::HashMap<AppLocalId, LocalValue, BuildFxHasher>;
73#[derive(Clone, Default)]
74struct BuildFxHasher;
75impl std::hash::BuildHasher for BuildFxHasher {
76 type Hasher = rustc_hash::FxHasher;
77
78 fn build_hasher(&self) -> Self::Hasher {
79 rustc_hash::FxHasher::default()
80 }
81}
82const fn new_local_data() -> LocalData {
83 LocalData::with_hasher(BuildFxHasher)
84}
85
86type LocalSet = std::collections::HashSet<AppLocalId, BuildFxHasher>;
87const fn new_local_set() -> LocalSet {
88 LocalSet::with_hasher(BuildFxHasher)
89}
90
91#[must_use = "ends the app scope on drop"]
95pub struct AppScope {
96 id: AppId,
97 _same_thread: std::rc::Rc<()>,
98}
99impl Drop for AppScope {
100 fn drop(&mut self) {
101 LocalContext::end_app(self.id);
102 }
103}
104
105impl AppId {
106 fn local_id() -> AppLocalId {
107 hot_static! {
108 static ID: u8 = 0;
109 }
110 AppLocalId(hot_static_ref!(ID) as *const u8 as *const () as _)
111 }
112}
113fn cleanup_list_id() -> AppLocalId {
114 hot_static! {
115 static ID: u8 = 0;
116 }
117 AppLocalId(hot_static_ref!(ID) as *const u8 as *const () as _)
118}
119
120#[derive(Clone)]
124pub struct LocalContext {
125 data: LocalData,
126 tracing: Option<tracing::dispatcher::Dispatch>,
127}
128impl fmt::Debug for LocalContext {
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 let app = self
131 .data
132 .get(&AppId::local_id())
133 .map(|(v, _)| v.downcast_ref::<AppId>().unwrap())
134 .copied();
135
136 f.debug_struct("LocalContext")
137 .field("<app>", &app)
138 .field("<entries>", &(self.data.len() - 1))
139 .finish()
140 }
141}
142impl Default for LocalContext {
143 fn default() -> Self {
144 Self::new()
145 }
146}
147impl LocalContext {
148 pub const fn new() -> Self {
150 Self {
151 data: new_local_data(),
152 tracing: None,
153 }
154 }
155
156 pub fn start_app(id: AppId) -> AppScope {
158 let valid = LOCAL.with_borrow_mut_dyn(|c| match c.entry(AppId::local_id()) {
159 std::collections::hash_map::Entry::Occupied(_) => false,
160 std::collections::hash_map::Entry::Vacant(e) => {
161 e.insert((Arc::new(id), LocalValueKind::App));
162 true
163 }
164 });
165 assert!(valid, "cannot start app, another app is already in the thread context");
166
167 AppScope {
168 id,
169 _same_thread: std::rc::Rc::new(()),
170 }
171 }
172 fn end_app(id: AppId) {
173 let valid = LOCAL.with_borrow_mut_dyn(|c| {
174 if c.get(&AppId::local_id())
175 .map(|(v, _)| v.downcast_ref::<AppId>() == Some(&id))
176 .unwrap_or(false)
177 {
178 Some(mem::take(&mut *c))
179 } else {
180 None
181 }
182 });
183
184 if let Some(data) = valid {
185 let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(move || {
187 drop(data); }));
189 if let Err(p) = r {
190 tracing::error!("panic on app drop. {}", panic_str(&p));
191 eprintln!("panic on app drop. {}", panic_str(&p));
192 zng_env::exit(i32::from_le_bytes(*b"appa"));
193 }
194 } else {
195 tracing::error!("can only drop app in one of its threads");
196 eprintln!("can only drop app in one of its threads");
197 zng_env::exit(i32::from_le_bytes(*b"appa"));
198 }
199 }
200
201 pub fn current_app() -> Option<AppId> {
203 LOCAL.with_borrow_dyn(|c| c.get(&AppId::local_id()).map(|(v, _)| v.downcast_ref::<AppId>().unwrap()).copied())
204 }
205
206 pub fn register_cleanup(cleanup: impl FnOnce(AppId) + Send + 'static) {
208 let id = Self::current_app().expect("no app in context");
209 Self::register_cleanup_dyn(Box::new(move || cleanup(id)));
210 }
211 fn register_cleanup_dyn(cleanup: Box<dyn FnOnce() + Send>) {
212 let cleanup = RunOnDrop::new(cleanup);
213
214 type CleanupList = Vec<RunOnDrop<Box<dyn FnOnce() + Send>>>;
215 LOCAL.with_borrow_mut_dyn(|c| {
216 let c = c
217 .entry(cleanup_list_id())
218 .or_insert_with(|| (Arc::new(Mutex::new(CleanupList::new())), LocalValueKind::App));
219 c.0.downcast_ref::<Mutex<CleanupList>>().unwrap().lock().push(cleanup);
220 });
221 }
222
223 pub fn capture() -> Self {
230 Self {
231 data: LOCAL.with_borrow_dyn(|c| c.clone()),
232 tracing: Some(tracing::dispatcher::get_default(|d| d.clone())),
233 }
234 }
235
236 pub fn capture_filtered(filter: CaptureFilter) -> Self {
238 match filter {
239 CaptureFilter::None => Self::new(),
240 CaptureFilter::All => Self::capture(),
241 CaptureFilter::ContextVars { exclude } => {
242 let mut data = new_local_data();
243 LOCAL.with_borrow_dyn(|c| {
244 for (k, (v, kind)) in c.iter() {
245 if kind.include_var() && !exclude.0.contains(k) {
246 data.insert(*k, (v.clone(), *kind));
247 }
248 }
249 });
250 Self { data, tracing: None }
251 }
252 CaptureFilter::ContextLocals { exclude } => {
253 let mut data = new_local_data();
254 LOCAL.with_borrow_dyn(|c| {
255 for (k, (v, kind)) in c.iter() {
256 if kind.include_local() && !exclude.0.contains(k) {
257 data.insert(*k, (v.clone(), *kind));
258 }
259 }
260 });
261 Self {
262 data,
263 tracing: Some(tracing::dispatcher::get_default(|d| d.clone())),
264 }
265 }
266 CaptureFilter::Include(set) => {
267 let mut data = new_local_data();
268 LOCAL.with_borrow_dyn(|c| {
269 for (k, v) in c.iter() {
270 if set.0.contains(k) {
271 data.insert(*k, v.clone());
272 }
273 }
274 });
275 Self {
276 data,
277 tracing: if set.contains(&TracingDispatcherContext) {
278 Some(tracing::dispatcher::get_default(|d| d.clone()))
279 } else {
280 None
281 },
282 }
283 }
284 CaptureFilter::Exclude(set) => {
285 let mut data = new_local_data();
286 LOCAL.with_borrow_dyn(|c| {
287 for (k, v) in c.iter() {
288 if !set.0.contains(k) {
289 data.insert(*k, v.clone());
290 }
291 }
292 });
293 Self {
294 data,
295 tracing: if !set.contains(&TracingDispatcherContext) {
296 Some(tracing::dispatcher::get_default(|d| d.clone()))
297 } else {
298 None
299 },
300 }
301 }
302 }
303 }
304
305 pub fn value_set(&self) -> ContextValueSet {
307 let mut set = ContextValueSet::new();
308 LOCAL.with_borrow_dyn(|c| {
309 for k in c.keys() {
310 set.0.insert(*k);
311 }
312 });
313 set
314 }
315
316 pub fn with_context<R>(&mut self, f: impl FnOnce() -> R) -> R {
323 let data = mem::take(&mut self.data);
324 let prev = LOCAL.with_borrow_mut_dyn(|c| mem::replace(c, data));
325 let _tracing_restore = self.tracing.as_ref().map(tracing::dispatcher::set_default);
326 let _restore = RunOnDrop::new(|| {
327 self.data = LOCAL.with_borrow_mut_dyn(|c| mem::replace(c, prev));
328 });
329 f()
330 }
331
332 pub fn with_context_blend<R>(&mut self, over: bool, f: impl FnOnce() -> R) -> R {
342 if self.data.is_empty() {
343 f()
344 } else {
345 let prev = LOCAL.with_borrow_mut_dyn(|c| {
346 let (mut base, over) = if over { (c.clone(), &self.data) } else { (self.data.clone(), &*c) };
347 for (k, v) in over {
348 base.insert(*k, v.clone());
349 }
350
351 mem::replace(c, base)
352 });
353 let _restore = RunOnDrop::new(|| {
354 LOCAL.with_borrow_mut_dyn(|c| {
355 *c = prev;
356 });
357 });
358 f()
359 }
360 }
361
362 pub fn extend(&mut self, ctx: Self) {
364 self.data.extend(ctx.data);
365 }
366
367 fn contains(key: AppLocalId) -> bool {
368 LOCAL.with_borrow_dyn(|c| c.contains_key(&key))
369 }
370
371 fn get(key: AppLocalId) -> Option<LocalValue> {
372 LOCAL.with_borrow_dyn(|c| c.get(&key).cloned())
373 }
374
375 fn set(key: AppLocalId, value: LocalValue) -> Option<LocalValue> {
376 LOCAL.with_borrow_mut_dyn(|c| c.insert(key, value))
377 }
378 fn remove(key: AppLocalId) -> Option<LocalValue> {
379 LOCAL.with_borrow_mut_dyn(|c| c.remove(&key))
380 }
381
382 fn with_value_ctx<T: Send + Sync + 'static>(
383 key: &'static ContextLocal<T>,
384 kind: LocalValueKind,
385 value: &mut Option<Arc<T>>,
386 f: impl FnOnce(),
387 ) {
388 let key = key.id();
389 let prev = Self::set(key, (value.take().expect("no `value` to set"), kind));
390 let _restore = RunOnDrop::new(move || {
391 let back = if let Some(prev) = prev {
392 Self::set(key, prev)
393 } else {
394 Self::remove(key)
395 }
396 .unwrap();
397 *value = Some(Arc::downcast(back.0).unwrap());
398 });
399
400 f();
401 }
402
403 fn with_default_ctx<T: Send + Sync + 'static>(key: &'static ContextLocal<T>, f: impl FnOnce()) {
404 let key = key.id();
405 let prev = Self::remove(key);
406 let _restore = RunOnDrop::new(move || {
407 if let Some(prev) = prev {
408 Self::set(key, prev);
409 }
410 });
411
412 f()
413 }
414}
415thread_local! {
416 static LOCAL: RefCell<LocalData> = const { RefCell::new(new_local_data()) };
417}
418
419trait LocalKeyDyn {
420 fn with_borrow_dyn<R>(&'static self, f: impl FnOnce(&LocalData) -> R) -> R;
421 fn with_borrow_mut_dyn<R>(&'static self, f: impl FnOnce(&mut LocalData) -> R) -> R;
422}
423impl LocalKeyDyn for LocalKey<RefCell<LocalData>> {
424 fn with_borrow_dyn<R>(&'static self, f: impl FnOnce(&LocalData) -> R) -> R {
425 let mut r = None;
426 let f = |l: &LocalData| r = Some(f(l));
427
428 #[cfg(feature = "dyn_closure")]
429 let f: Box<dyn FnOnce(&LocalData)> = Box::new(f);
430
431 self.with_borrow(f);
432
433 r.unwrap()
434 }
435
436 fn with_borrow_mut_dyn<R>(&'static self, f: impl FnOnce(&mut LocalData) -> R) -> R {
437 let mut r = None;
438 let f = |l: &mut LocalData| r = Some(f(l));
439
440 #[cfg(feature = "dyn_closure")]
441 let f: Box<dyn FnOnce(&mut LocalData)> = Box::new(f);
442
443 self.with_borrow_mut(f);
444
445 r.unwrap()
446 }
447}
448
449#[doc(hidden)]
454pub struct AppLocalConst<T: Send + Sync + 'static> {
455 value: RwLock<T>,
456}
457impl<T: Send + Sync + 'static> AppLocalConst<T> {
458 pub const fn new(init: T) -> Self {
459 Self { value: RwLock::new(init) }
460 }
461}
462#[doc(hidden)]
463pub struct AppLocalOption<T: Send + Sync + 'static> {
464 value: RwLock<Option<T>>,
465 init: fn() -> T,
466}
467impl<T: Send + Sync + 'static> AppLocalOption<T> {
468 pub const fn new(init: fn() -> T) -> Self {
469 Self {
470 value: RwLock::new(None),
471 init,
472 }
473 }
474
475 fn read_impl(&'static self, read: RwLockReadGuard<'static, Option<T>>) -> MappedRwLockReadGuard<'static, T> {
476 if read.is_some() {
477 return RwLockReadGuard::map(read, |v| v.as_ref().unwrap());
478 }
479 drop(read);
480
481 let mut write = self.value.write();
482 if write.is_some() {
483 drop(write);
484 return self.read();
485 }
486
487 let value = (self.init)();
488 *write = Some(value);
489
490 let read = RwLockWriteGuard::downgrade(write);
491
492 RwLockReadGuard::map(read, |v| v.as_ref().unwrap())
493 }
494
495 fn write_impl(&'static self, mut write: RwLockWriteGuard<'static, Option<T>>) -> MappedRwLockWriteGuard<'static, T> {
496 if write.is_some() {
497 return RwLockWriteGuard::map(write, |v| v.as_mut().unwrap());
498 }
499
500 let value = (self.init)();
501 *write = Some(value);
502
503 RwLockWriteGuard::map(write, |v| v.as_mut().unwrap())
504 }
505}
506
507#[doc(hidden)]
508pub struct AppLocalVec<T: Send + Sync + 'static> {
509 value: RwLock<Vec<(AppId, T)>>,
510 init: fn() -> T,
511}
512impl<T: Send + Sync + 'static> AppLocalVec<T> {
513 pub const fn new(init: fn() -> T) -> Self {
514 Self {
515 value: RwLock::new(vec![]),
516 init,
517 }
518 }
519
520 fn cleanup(&'static self, id: AppId) {
521 self.try_cleanup(id, 0);
522 }
523 fn try_cleanup(&'static self, id: AppId, tries: u8) {
524 if let Some(mut w) = self.value.try_write_for(if tries == 0 {
525 Duration::from_millis(50)
526 } else {
527 Duration::from_millis(500)
528 }) {
529 if let Some(i) = w.iter().position(|(s, _)| *s == id) {
530 w.swap_remove(i);
531 }
532 } else if tries > 5 {
533 tracing::error!("failed to cleanup `app_local` for {id:?}, was locked after app drop");
534 } else {
535 std::thread::spawn(move || {
536 self.try_cleanup(id, tries + 1);
537 });
538 }
539 }
540
541 fn read_impl(&'static self, read: RwLockReadGuard<'static, Vec<(AppId, T)>>) -> MappedRwLockReadGuard<'static, T> {
542 let id = LocalContext::current_app().expect("no app running, `app_local` can only be accessed inside apps");
543
544 if let Some(i) = read.iter().position(|(s, _)| *s == id) {
545 return RwLockReadGuard::map(read, |v| &v[i].1);
546 }
547 drop(read);
548
549 let mut write = self.value.write();
550 if write.iter().any(|(s, _)| *s == id) {
551 drop(write);
552 return self.read();
553 }
554
555 let value = (self.init)();
556 let i = write.len();
557 write.push((id, value));
558
559 LocalContext::register_cleanup(Box::new(move |id| self.cleanup(id)));
560
561 let read = RwLockWriteGuard::downgrade(write);
562
563 RwLockReadGuard::map(read, |v| &v[i].1)
564 }
565
566 fn write_impl(&'static self, mut write: RwLockWriteGuard<'static, Vec<(AppId, T)>>) -> MappedRwLockWriteGuard<'static, T> {
567 let id = LocalContext::current_app().expect("no app running, `app_local` can only be accessed inside apps");
568
569 if let Some(i) = write.iter().position(|(s, _)| *s == id) {
570 return RwLockWriteGuard::map(write, |v| &mut v[i].1);
571 }
572
573 let value = (self.init)();
574 let i = write.len();
575 write.push((id, value));
576
577 LocalContext::register_cleanup(move |id| self.cleanup(id));
578
579 RwLockWriteGuard::map(write, |v| &mut v[i].1)
580 }
581}
582#[doc(hidden)]
583pub trait AppLocalImpl<T: Send + Sync + 'static>: Send + Sync + 'static {
584 fn read(&'static self) -> MappedRwLockReadGuard<'static, T>;
585 fn try_read(&'static self) -> Option<MappedRwLockReadGuard<'static, T>>;
586 fn write(&'static self) -> MappedRwLockWriteGuard<'static, T>;
587 fn try_write(&'static self) -> Option<MappedRwLockWriteGuard<'static, T>>;
588}
589
590impl<T: Send + Sync + 'static> AppLocalImpl<T> for AppLocalVec<T> {
591 fn read(&'static self) -> MappedRwLockReadGuard<'static, T> {
592 self.read_impl(self.value.read_recursive())
593 }
594
595 fn try_read(&'static self) -> Option<MappedRwLockReadGuard<'static, T>> {
596 Some(self.read_impl(self.value.try_read_recursive()?))
597 }
598
599 fn write(&'static self) -> MappedRwLockWriteGuard<'static, T> {
600 self.write_impl(self.value.write())
601 }
602
603 fn try_write(&'static self) -> Option<MappedRwLockWriteGuard<'static, T>> {
604 Some(self.write_impl(self.value.try_write()?))
605 }
606}
607impl<T: Send + Sync + 'static> AppLocalImpl<T> for AppLocalOption<T> {
608 fn read(&'static self) -> MappedRwLockReadGuard<'static, T> {
609 self.read_impl(self.value.read_recursive())
610 }
611
612 fn try_read(&'static self) -> Option<MappedRwLockReadGuard<'static, T>> {
613 Some(self.read_impl(self.value.try_read_recursive()?))
614 }
615
616 fn write(&'static self) -> MappedRwLockWriteGuard<'static, T> {
617 self.write_impl(self.value.write())
618 }
619
620 fn try_write(&'static self) -> Option<MappedRwLockWriteGuard<'static, T>> {
621 Some(self.write_impl(self.value.try_write()?))
622 }
623}
624impl<T: Send + Sync + 'static> AppLocalImpl<T> for AppLocalConst<T> {
625 fn read(&'static self) -> MappedRwLockReadGuard<'static, T> {
626 RwLockReadGuard::map(self.value.read(), |l| l)
627 }
628
629 fn try_read(&'static self) -> Option<MappedRwLockReadGuard<'static, T>> {
630 Some(RwLockReadGuard::map(self.value.try_read()?, |l| l))
631 }
632
633 fn write(&'static self) -> MappedRwLockWriteGuard<'static, T> {
634 RwLockWriteGuard::map(self.value.write(), |l| l)
635 }
636
637 fn try_write(&'static self) -> Option<MappedRwLockWriteGuard<'static, T>> {
638 Some(RwLockWriteGuard::map(self.value.try_write()?, |l| l))
639 }
640}
641
642pub struct AppLocal<T: Send + Sync + 'static> {
651 inner: fn() -> &'static dyn AppLocalImpl<T>,
652}
653impl<T: Send + Sync + 'static> AppLocal<T> {
654 #[doc(hidden)]
655 pub const fn new(inner: fn() -> &'static dyn AppLocalImpl<T>) -> Self {
656 AppLocal { inner }
657 }
658
659 #[inline]
667 pub fn read(&'static self) -> MappedRwLockReadGuard<'static, T> {
668 (self.inner)().read()
669 }
670
671 #[inline]
681 pub fn try_read(&'static self) -> Option<MappedRwLockReadGuard<'static, T>> {
682 (self.inner)().try_read()
683 }
684
685 #[inline]
693 pub fn write(&'static self) -> MappedRwLockWriteGuard<'static, T> {
694 (self.inner)().write()
695 }
696
697 pub fn try_write(&'static self) -> Option<MappedRwLockWriteGuard<'static, T>> {
707 (self.inner)().try_write()
708 }
709
710 #[inline]
712 pub fn get(&'static self) -> T
713 where
714 T: Clone,
715 {
716 self.read().clone()
717 }
718
719 #[inline]
721 pub fn set(&'static self, value: T) {
722 *self.write() = value;
723 }
724
725 #[inline]
729 pub fn try_get(&'static self) -> Option<T>
730 where
731 T: Clone,
732 {
733 self.try_read().map(|l| l.clone())
734 }
735
736 #[inline]
740 pub fn try_set(&'static self, value: T) -> Result<(), T> {
741 match self.try_write() {
742 Some(mut l) => {
743 *l = value;
744 Ok(())
745 }
746 None => Err(value),
747 }
748 }
749
750 #[inline]
752 pub fn read_map<O>(&'static self, map: impl FnOnce(&T) -> &O) -> MappedRwLockReadGuard<'static, O> {
753 MappedRwLockReadGuard::map(self.read(), map)
754 }
755
756 #[inline]
758 pub fn try_read_map<O>(&'static self, map: impl FnOnce(&T) -> &O) -> Option<MappedRwLockReadGuard<'static, O>> {
759 let lock = self.try_read()?;
760 Some(MappedRwLockReadGuard::map(lock, map))
761 }
762
763 #[inline]
765 pub fn write_map<O>(&'static self, map: impl FnOnce(&mut T) -> &mut O) -> MappedRwLockWriteGuard<'static, O> {
766 MappedRwLockWriteGuard::map(self.write(), map)
767 }
768
769 #[inline]
771 pub fn try_write_map<O>(&'static self, map: impl FnOnce(&mut T) -> &mut O) -> Option<MappedRwLockWriteGuard<'static, O>> {
772 let lock = self.try_write()?;
773 Some(MappedRwLockWriteGuard::map(lock, map))
774 }
775
776 pub fn id(&'static self) -> AppLocalId {
781 AppLocalId((self.inner)() as *const dyn AppLocalImpl<T> as *const () as _)
782 }
783}
784impl<T: Send + Sync + 'static> PartialEq for AppLocal<T> {
785 fn eq(&self, other: &Self) -> bool {
786 let a = AppLocalId((self.inner)() as *const dyn AppLocalImpl<T> as *const () as _);
787 let b = AppLocalId((other.inner)() as *const dyn AppLocalImpl<T> as *const () as _);
788 a == b
789 }
790}
791impl<T: Send + Sync + 'static> Eq for AppLocal<T> {}
792impl<T: Send + Sync + 'static> std::hash::Hash for AppLocal<T> {
793 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
794 let a = AppLocalId((self.inner)() as *const dyn AppLocalImpl<T> as *const () as _);
795 std::hash::Hash::hash(&a, state)
796 }
797}
798
799#[derive(PartialEq, Eq, Hash, Clone, Copy)]
805pub struct AppLocalId(usize);
806impl AppLocalId {
807 pub fn get(self) -> usize {
809 self.0 as _
811 }
812}
813impl fmt::Debug for AppLocalId {
814 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
815 write!(f, "AppLocalId({:#x})", self.0)
816 }
817}
818
819#[macro_export]
871macro_rules! app_local {
872 ($(
873 $(#[$meta:meta])*
874 $vis:vis static $IDENT:ident : $T:ty = $(const { $init_const:expr })? $($init:expr_2021)?;
875 )+) => {$(
876 $crate::app_local_impl! {
877 $(#[$meta])*
878 $vis static $IDENT: $T = $(const { $init_const })? $($init)?;
879 }
880 )+};
881}
882
883#[doc(hidden)]
884#[macro_export]
885macro_rules! app_local_impl_single {
886 (
887 $(#[$meta:meta])*
888 $vis:vis static $IDENT:ident : $T:ty = const { $init:expr };
889 ) => {
890 $(#[$meta])*
891 $vis static $IDENT: $crate::AppLocal<$T> = {
892 fn s() -> &'static dyn $crate::AppLocalImpl<$T> {
893 $crate::hot_static! {
894 static IMPL: $crate::AppLocalConst<$T> = $crate::AppLocalConst::new($init);
895 }
896 $crate::hot_static_ref!(IMPL)
897 }
898 $crate::AppLocal::new(s)
899 };
900 };
901 (
902 $(#[$meta:meta])*
903 $vis:vis static $IDENT:ident : $T:ty = $init:expr_2021;
904 ) => {
905 $(#[$meta])*
906 $vis static $IDENT: $crate::AppLocal<$T> = {
907 fn s() -> &'static dyn $crate::AppLocalImpl<$T> {
908 fn init() -> $T {
909 std::convert::Into::into($init)
910 }
911 $crate::hot_static! {
912 static IMPL: $crate::AppLocalOption<$T> = $crate::AppLocalOption::new(init);
913 }
914 $crate::hot_static_ref!(IMPL)
915 }
916 $crate::AppLocal::new(s)
917 };
918 };
919 (
920 $(#[$meta:meta])*
921 $vis:vis static $IDENT:ident : $T:ty = ($tt:tt)*
922 ) => {
923 std::compile_error!("expected `const { $expr };` or `$expr;`")
924 };
925}
926
927#[doc(hidden)]
928#[macro_export]
929macro_rules! app_local_impl_multi {
930 (
931 $(#[$meta:meta])*
932 $vis:vis static $IDENT:ident : $T:ty = const { $init:expr };
933 ) => {
934 $(#[$meta])*
935 $vis static $IDENT: $crate::AppLocal<$T> = {
936 fn s() -> &'static dyn $crate::AppLocalImpl<$T> {
937 const fn init() -> $T {
938 $init
939 }
940 $crate::hot_static! {
941 static IMPL: $crate::AppLocalVec<$T> = $crate::AppLocalVec::new(init);
942 }
943 $crate::hot_static_ref!(IMPL)
944 }
945 $crate::AppLocal::new(s)
946 };
947 };
948 (
949 $(#[$meta:meta])*
950 $vis:vis static $IDENT:ident : $T:ty = $init:expr_2021;
951 ) => {
952 $(#[$meta])*
953 $vis static $IDENT: $crate::AppLocal<$T> = {
954 fn s() -> &'static dyn $crate::AppLocalImpl<$T> {
955 fn init() -> $T {
956 std::convert::Into::into($init)
957 }
958 $crate::hot_static! {
959 static IMPL: $crate::AppLocalVec<$T> = $crate::AppLocalVec::new(init);
960 }
961 $crate::hot_static_ref!(IMPL)
962 }
963 $crate::AppLocal::new(s)
964 };
965 };
966 (
967 $(#[$meta:meta])*
968 $vis:vis static $IDENT:ident : $T:ty = ($tt:tt)*
969 ) => {
970 std::compile_error!("expected `const { $expr };` or `$expr;`")
971 };
972}
973
974#[cfg(feature = "multi_app")]
975#[doc(hidden)]
976pub use app_local_impl_multi as app_local_impl;
977#[cfg(not(feature = "multi_app"))]
978#[doc(hidden)]
979pub use app_local_impl_single as app_local_impl;
980
981#[doc(hidden)]
986pub struct ContextLocalData<T: Send + Sync + 'static> {
987 default_init: fn() -> T,
988 default_value: Option<Arc<T>>,
989}
990impl<T: Send + Sync + 'static> ContextLocalData<T> {
991 #[doc(hidden)]
992 pub const fn new(default_init: fn() -> T) -> Self {
993 Self {
994 default_init,
995 default_value: None,
996 }
997 }
998}
999
1000pub struct ContextLocal<T: Send + Sync + 'static> {
1006 data: AppLocal<ContextLocalData<T>>,
1007}
1008impl<T: Send + Sync + 'static> ContextLocal<T> {
1009 #[doc(hidden)]
1010 pub const fn new(storage: fn() -> &'static dyn AppLocalImpl<ContextLocalData<T>>) -> Self {
1011 Self {
1012 data: AppLocal::new(storage),
1013 }
1014 }
1015
1016 pub fn id(&'static self) -> AppLocalId {
1021 self.data.id()
1022 }
1023
1024 pub fn with_context<R>(&'static self, value: &mut Option<Arc<T>>, f: impl FnOnce() -> R) -> R {
1032 let mut r = None;
1033 let f = || r = Some(f());
1034 #[cfg(feature = "dyn_closure")]
1035 let f: Box<dyn FnOnce()> = Box::new(f);
1036
1037 LocalContext::with_value_ctx(self, LocalValueKind::Local, value, f);
1038
1039 r.unwrap()
1040 }
1041
1042 pub fn with_context_var<R>(&'static self, value: &mut Option<Arc<T>>, f: impl FnOnce() -> R) -> R {
1048 let mut r = None;
1049 let f = || r = Some(f());
1050
1051 #[cfg(feature = "dyn_closure")]
1052 let f: Box<dyn FnOnce()> = Box::new(f);
1053
1054 LocalContext::with_value_ctx(self, LocalValueKind::Var, value, f);
1055
1056 r.unwrap()
1057 }
1058
1059 pub fn with_default<R>(&'static self, f: impl FnOnce() -> R) -> R {
1061 let mut r = None;
1062 let f = || r = Some(f());
1063
1064 #[cfg(feature = "dyn_closure")]
1065 let f: Box<dyn FnOnce()> = Box::new(f);
1066 LocalContext::with_default_ctx(self, f);
1067
1068 r.unwrap()
1069 }
1070
1071 pub fn is_default(&'static self) -> bool {
1073 !LocalContext::contains(self.id())
1074 }
1075
1076 pub fn get(&'static self) -> Arc<T> {
1078 let cl = self.data.read();
1079 match LocalContext::get(self.id()) {
1080 Some(c) => Arc::downcast(c.0).unwrap(),
1081 None => match &cl.default_value {
1082 Some(d) => d.clone(),
1083 None => {
1084 drop(cl);
1085 let mut cl = self.data.write();
1086 match &cl.default_value {
1087 None => {
1088 let d = Arc::new((cl.default_init)());
1089 cl.default_value = Some(d.clone());
1090 d
1091 }
1092 Some(d) => d.clone(),
1093 }
1094 }
1095 },
1096 }
1097 }
1098
1099 pub fn get_clone(&'static self) -> T
1101 where
1102 T: Clone,
1103 {
1104 let cl = self.data.read();
1105 match LocalContext::get(self.id()) {
1106 Some(c) => c.0.downcast_ref::<T>().unwrap().clone(),
1107 None => match &cl.default_value {
1108 Some(d) => d.as_ref().clone(),
1109 None => {
1110 drop(cl);
1111 let mut cl = self.data.write();
1112 match &cl.default_value {
1113 None => {
1114 let val = (cl.default_init)();
1115 let r = val.clone();
1116 cl.default_value = Some(Arc::new(val));
1117 r
1118 }
1119 Some(d) => d.as_ref().clone(),
1120 }
1121 }
1122 },
1123 }
1124 }
1125}
1126
1127impl<T: Send + Sync + 'static> ContextLocal<RwLock<T>> {
1128 pub fn read_only(&'static self) -> ReadOnlyRwLock<T> {
1130 ReadOnlyRwLock::new(self.get())
1131 }
1132
1133 pub fn read(&'static self) -> RwLockReadGuardOwned<T> {
1137 RwLockReadGuardOwned::lock(self.get())
1138 }
1139
1140 pub fn read_recursive(&'static self) -> RwLockReadGuardOwned<T> {
1147 RwLockReadGuardOwned::lock_recursive(self.get())
1148 }
1149
1150 pub fn write(&'static self) -> RwLockWriteGuardOwned<T> {
1155 RwLockWriteGuardOwned::lock(self.get())
1156 }
1157
1158 pub fn try_read(&'static self) -> Option<RwLockReadGuardOwned<T>> {
1162 RwLockReadGuardOwned::try_lock(self.get())
1163 }
1164
1165 pub fn try_read_recursive(&'static self) -> Option<RwLockReadGuardOwned<T>> {
1169 RwLockReadGuardOwned::try_lock_recursive(self.get())
1170 }
1171
1172 pub fn try_write(&'static self) -> Option<RwLockWriteGuardOwned<T>> {
1177 RwLockWriteGuardOwned::try_lock(self.get())
1178 }
1179}
1180
1181pub struct RwLockReadGuardOwned<T: 'static> {
1183 lock: parking_lot::RwLockReadGuard<'static, T>,
1184 _owned: Arc<RwLock<T>>,
1185}
1186impl<T> RwLockReadGuardOwned<T> {
1187 pub fn lock(own: Arc<RwLock<T>>) -> Self {
1191 Self {
1192 lock: unsafe { mem::transmute::<parking_lot::RwLockReadGuard<'_, T>, parking_lot::RwLockReadGuard<'static, T>>(own.read()) },
1194 _owned: own,
1195 }
1196 }
1197
1198 pub fn lock_recursive(own: Arc<RwLock<T>>) -> Self {
1202 Self {
1203 lock: unsafe {
1205 mem::transmute::<parking_lot::RwLockReadGuard<'_, T>, parking_lot::RwLockReadGuard<'static, T>>(own.read_recursive())
1206 },
1207 _owned: own,
1208 }
1209 }
1210
1211 pub fn try_lock(own: Arc<RwLock<T>>) -> Option<Self> {
1215 let lock = own.try_read()?;
1216 Some(Self {
1217 lock: unsafe { mem::transmute::<parking_lot::RwLockReadGuard<'_, T>, parking_lot::RwLockReadGuard<'static, T>>(lock) },
1219 _owned: own,
1220 })
1221 }
1222
1223 pub fn try_lock_recursive(own: Arc<RwLock<T>>) -> Option<Self> {
1227 let lock = own.try_read_recursive()?;
1228 Some(Self {
1229 lock: unsafe { mem::transmute::<parking_lot::RwLockReadGuard<'_, T>, parking_lot::RwLockReadGuard<'static, T>>(lock) },
1231 _owned: own,
1232 })
1233 }
1234
1235 pub fn map<O>(guard: Self, map: impl FnOnce(&T) -> &O) -> MappedRwLockReadGuardOwned<T, O> {
1241 MappedRwLockReadGuardOwned {
1242 lock: parking_lot::RwLockReadGuard::map(guard.lock, map),
1243 _owned: guard._owned,
1244 }
1245 }
1246}
1247impl<T> ops::Deref for RwLockReadGuardOwned<T> {
1248 type Target = T;
1249
1250 fn deref(&self) -> &Self::Target {
1251 self.lock.deref()
1252 }
1253}
1254
1255pub struct MappedRwLockReadGuardOwned<T: 'static, O: 'static> {
1257 lock: parking_lot::MappedRwLockReadGuard<'static, O>,
1258 _owned: Arc<RwLock<T>>,
1259}
1260impl<T, O> MappedRwLockReadGuardOwned<T, O> {
1261 pub fn map<O2>(guard: Self, map: impl FnOnce(&O) -> &O2) -> MappedRwLockReadGuardOwned<T, O2> {
1267 MappedRwLockReadGuardOwned {
1268 lock: parking_lot::MappedRwLockReadGuard::map(guard.lock, map),
1269 _owned: guard._owned,
1270 }
1271 }
1272}
1273impl<T, O> ops::Deref for MappedRwLockReadGuardOwned<T, O> {
1274 type Target = O;
1275
1276 fn deref(&self) -> &Self::Target {
1277 self.lock.deref()
1278 }
1279}
1280
1281pub struct RwLockWriteGuardOwned<T: 'static> {
1283 lock: parking_lot::RwLockWriteGuard<'static, T>,
1284 _owned: Arc<RwLock<T>>,
1285}
1286impl<T> RwLockWriteGuardOwned<T> {
1287 pub fn lock(own: Arc<RwLock<T>>) -> Self {
1291 Self {
1292 lock: unsafe { mem::transmute::<parking_lot::RwLockWriteGuard<'_, T>, parking_lot::RwLockWriteGuard<'static, T>>(own.write()) },
1294 _owned: own,
1295 }
1296 }
1297
1298 pub fn try_lock(own: Arc<RwLock<T>>) -> Option<Self> {
1302 let lock = own.try_write()?;
1303 Some(Self {
1304 lock: unsafe { mem::transmute::<parking_lot::RwLockWriteGuard<'_, T>, parking_lot::RwLockWriteGuard<'static, T>>(lock) },
1306 _owned: own,
1307 })
1308 }
1309
1310 pub fn map<O>(guard: Self, map: impl FnOnce(&mut T) -> &mut O) -> MappedRwLockWriteGuardOwned<T, O> {
1316 MappedRwLockWriteGuardOwned {
1317 lock: parking_lot::RwLockWriteGuard::map(guard.lock, map),
1318 _owned: guard._owned,
1319 }
1320 }
1321}
1322impl<T> ops::Deref for RwLockWriteGuardOwned<T> {
1323 type Target = T;
1324
1325 fn deref(&self) -> &Self::Target {
1326 self.lock.deref()
1327 }
1328}
1329impl<T> ops::DerefMut for RwLockWriteGuardOwned<T> {
1330 fn deref_mut(&mut self) -> &mut Self::Target {
1331 self.lock.deref_mut()
1332 }
1333}
1334
1335pub struct MappedRwLockWriteGuardOwned<T: 'static, O: 'static> {
1337 lock: parking_lot::MappedRwLockWriteGuard<'static, O>,
1338 _owned: Arc<RwLock<T>>,
1339}
1340impl<T, O> MappedRwLockWriteGuardOwned<T, O> {
1341 pub fn map<O2>(guard: Self, map: impl FnOnce(&mut O) -> &mut O2) -> MappedRwLockWriteGuardOwned<T, O2> {
1347 MappedRwLockWriteGuardOwned {
1348 lock: parking_lot::MappedRwLockWriteGuard::map(guard.lock, map),
1349 _owned: guard._owned,
1350 }
1351 }
1352}
1353impl<T, O> ops::Deref for MappedRwLockWriteGuardOwned<T, O> {
1354 type Target = O;
1355
1356 fn deref(&self) -> &Self::Target {
1357 self.lock.deref()
1358 }
1359}
1360impl<T, O> ops::DerefMut for MappedRwLockWriteGuardOwned<T, O> {
1361 fn deref_mut(&mut self) -> &mut Self::Target {
1362 self.lock.deref_mut()
1363 }
1364}
1365
1366pub struct ReadOnlyRwLock<T>(Arc<RwLock<T>>);
1368impl<T> Clone for ReadOnlyRwLock<T> {
1369 fn clone(&self) -> Self {
1370 Self(self.0.clone())
1371 }
1372}
1373impl<T> ReadOnlyRwLock<T> {
1374 pub fn new(l: Arc<RwLock<T>>) -> Self {
1376 Self(l)
1377 }
1378
1379 pub fn read(&self) -> parking_lot::RwLockReadGuard<T> {
1383 self.0.read()
1384 }
1385
1386 pub fn read_recursive(&self) -> parking_lot::RwLockReadGuard<T> {
1393 self.0.read_recursive()
1394 }
1395
1396 pub fn try_read(&self) -> Option<parking_lot::RwLockReadGuard<T>> {
1400 self.0.try_read()
1401 }
1402
1403 pub fn try_read_recursive(&self) -> Option<parking_lot::RwLockReadGuard<T>> {
1407 self.0.try_read_recursive()
1408 }
1409
1410 pub fn ptr_eq(&self, other: &Self) -> bool {
1412 Arc::ptr_eq(&self.0, &other.0)
1413 }
1414}
1415
1416#[macro_export]
1471macro_rules! context_local {
1472 ($(
1473 $(#[$meta:meta])*
1474 $vis:vis static $IDENT:ident : $T:ty = $init:expr;
1475 )+) => {$(
1476 $crate::context_local_impl! {
1477 $(#[$meta])*
1478 $vis static $IDENT: $T = $init;
1479 }
1480 )+};
1481}
1482
1483#[doc(hidden)]
1484#[macro_export]
1485macro_rules! context_local_impl_single {
1486 ($(
1487 $(#[$meta:meta])*
1488 $vis:vis static $IDENT:ident : $T:ty = $init:expr;
1489 )+) => {$(
1490 $(#[$meta])*
1491 $vis static $IDENT: $crate::ContextLocal<$T> = {
1492 fn s() -> &'static dyn $crate::AppLocalImpl<$crate::ContextLocalData<$T>> {
1493 fn init() -> $T {
1494 std::convert::Into::into($init)
1495 }
1496 $crate::hot_static! {
1497 static IMPL: $crate::AppLocalConst<$crate::ContextLocalData<$T>> =
1498 $crate::AppLocalConst::new(
1499 $crate::ContextLocalData::new(init)
1500 );
1501 }
1502 $crate::hot_static_ref!(IMPL)
1503 }
1504 $crate::ContextLocal::new(s)
1505 };
1506 )+};
1507}
1508
1509#[doc(hidden)]
1510#[macro_export]
1511macro_rules! context_local_impl_multi {
1512 ($(
1513 $(#[$meta:meta])*
1514 $vis:vis static $IDENT:ident : $T:ty = $init:expr;
1515 )+) => {$(
1516 $(#[$meta])*
1517 $vis static $IDENT: $crate::ContextLocal<$T> = {
1518 fn s() -> &'static dyn $crate::AppLocalImpl<$crate::ContextLocalData<$T>> {
1519 fn init() -> $T {
1520 std::convert::Into::into($init)
1521 }
1522 $crate::hot_static! {
1523 static IMPL: $crate::AppLocalVec<$crate::ContextLocalData<$T>> =
1524 $crate::AppLocalVec::new(
1525 || $crate::ContextLocalData::new(init)
1526 );
1527 }
1528 $crate::hot_static_ref!(IMPL)
1529 }
1530 $crate::ContextLocal::new(s)
1531 };
1532 )+};
1533}
1534
1535#[cfg(feature = "multi_app")]
1536#[doc(hidden)]
1537pub use context_local_impl_multi as context_local_impl;
1538
1539#[cfg(not(feature = "multi_app"))]
1540#[doc(hidden)]
1541pub use context_local_impl_single as context_local_impl;
1542
1543#[derive(Debug, Clone, PartialEq, Eq)]
1545pub enum CaptureFilter {
1546 None,
1548
1549 All,
1551 ContextVars {
1553 exclude: ContextValueSet,
1555 },
1556 ContextLocals {
1558 exclude: ContextValueSet,
1560 },
1561
1562 Include(ContextValueSet),
1564
1565 Exclude(ContextValueSet),
1567}
1568impl CaptureFilter {
1569 pub const fn context_vars() -> Self {
1571 Self::ContextVars {
1572 exclude: ContextValueSet::new(),
1573 }
1574 }
1575
1576 pub const fn context_locals() -> Self {
1578 Self::ContextLocals {
1579 exclude: ContextValueSet::new(),
1580 }
1581 }
1582
1583 pub fn app_only() -> Self {
1585 let mut set = ContextValueSet::new();
1586 set.insert_app();
1587 Self::Include(set)
1588 }
1589}
1590
1591pub trait ContextLocalKeyProvider {
1595 fn context_local_key(&'static self) -> AppLocalId;
1597}
1598impl<T: Send + Sync + 'static> ContextLocalKeyProvider for ContextLocal<T> {
1599 fn context_local_key(&'static self) -> AppLocalId {
1600 self.id()
1601 }
1602}
1603
1604pub struct TracingDispatcherContext;
1608
1609impl ContextLocalKeyProvider for TracingDispatcherContext {
1610 fn context_local_key(&'static self) -> AppLocalId {
1611 static ID: bool = true;
1612 AppLocalId(&ID as *const bool as *const () as usize)
1613 }
1614}
1615
1616#[derive(Default, Clone, PartialEq, Eq)]
1618pub struct ContextValueSet(LocalSet);
1619impl ContextValueSet {
1620 pub const fn new() -> Self {
1622 Self(new_local_set())
1623 }
1624
1625 pub fn insert(&mut self, value: &'static impl ContextLocalKeyProvider) -> bool {
1627 self.0.insert(value.context_local_key())
1628 }
1629
1630 pub fn remove(&mut self, value: &'static impl ContextLocalKeyProvider) -> bool {
1632 self.0.remove(&value.context_local_key())
1633 }
1634
1635 pub fn contains(&self, value: &'static impl ContextLocalKeyProvider) -> bool {
1637 self.0.contains(&value.context_local_key())
1638 }
1639
1640 pub fn len(&self) -> usize {
1642 self.0.len()
1643 }
1644
1645 pub fn is_empty(&self) -> bool {
1647 self.0.is_empty()
1648 }
1649
1650 pub fn insert_all(&mut self, other: &Self) {
1652 self.0.extend(other.0.iter().copied());
1653 }
1654
1655 pub fn remove_all(&mut self, other: &Self) {
1657 for o in other.0.iter() {
1658 self.0.remove(o);
1659 }
1660 }
1661
1662 pub fn insert_app(&mut self) -> bool {
1664 let inserted_app = self.0.insert(AppId::local_id());
1665 static TRACING: TracingDispatcherContext = TracingDispatcherContext;
1666 self.insert(&TRACING) || inserted_app
1667 }
1668}
1669impl fmt::Debug for ContextValueSet {
1670 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1671 f.debug_struct("ContextValueSet").field("len()", &self.len()).finish()
1672 }
1673}
1674
1675pub struct RunOnDrop<F: FnOnce()>(Option<F>);
1677impl<F: FnOnce()> RunOnDrop<F> {
1678 pub fn new(clean: F) -> Self {
1680 RunOnDrop(Some(clean))
1681 }
1682}
1683impl<F: FnOnce()> Drop for RunOnDrop<F> {
1684 fn drop(&mut self) {
1685 if let Some(clean) = self.0.take() {
1686 clean();
1687 }
1688 }
1689}
1690
1691fn panic_str<'s>(payload: &'s Box<dyn std::any::Any + Send + 'static>) -> &'s str {
1692 if let Some(s) = payload.downcast_ref::<&str>() {
1693 s
1694 } else if let Some(s) = payload.downcast_ref::<String>() {
1695 s
1696 } else {
1697 "<unknown-panic-message-type>"
1698 }
1699}