a3s_boot/provider/
context_id.rs1use super::cache::ProviderCache;
2use crate::{BootError, BootRequest, Result};
3use std::fmt;
4use std::hash::{Hash, Hasher};
5use std::sync::atomic::{AtomicU64, Ordering};
6use std::sync::{Arc, Weak};
7
8static NEXT_CONTEXT_ID: AtomicU64 = AtomicU64::new(1);
9
10#[derive(Clone)]
12pub struct ContextId {
13 id: u64,
14 state: ContextIdStateRef,
15}
16
17#[derive(Clone)]
18enum ContextIdStateRef {
19 Strong(Arc<ContextIdState>),
20 Weak(Weak<ContextIdState>),
21}
22
23struct ContextIdState {
24 cache: ProviderCache,
25}
26
27impl ContextId {
28 fn new(id: u64) -> Self {
29 Self {
30 id,
31 state: ContextIdStateRef::Strong(Arc::new(ContextIdState {
32 cache: ProviderCache::new(),
33 })),
34 }
35 }
36
37 pub fn id(&self) -> u64 {
39 self.id
40 }
41
42 pub(crate) fn cache(&self) -> Result<ProviderCache> {
43 let state = match &self.state {
44 ContextIdStateRef::Strong(state) => Arc::clone(state),
45 ContextIdStateRef::Weak(state) => state.upgrade().ok_or_else(|| {
46 BootError::Internal(format!(
47 "dependency-injection context {} is no longer active",
48 self.id
49 ))
50 })?,
51 };
52 Ok(state.cache.clone())
53 }
54
55 pub(crate) fn downgrade(&self) -> Self {
56 let state = match &self.state {
57 ContextIdStateRef::Strong(state) => ContextIdStateRef::Weak(Arc::downgrade(state)),
58 ContextIdStateRef::Weak(state) => ContextIdStateRef::Weak(Weak::clone(state)),
59 };
60 Self { id: self.id, state }
61 }
62}
63
64impl fmt::Debug for ContextId {
65 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
66 formatter
67 .debug_struct("ContextId")
68 .field("id", &self.id())
69 .finish_non_exhaustive()
70 }
71}
72
73impl PartialEq for ContextId {
74 fn eq(&self, other: &Self) -> bool {
75 self.id() == other.id()
76 }
77}
78
79impl Eq for ContextId {}
80
81impl PartialOrd for ContextId {
82 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
83 Some(self.cmp(other))
84 }
85}
86
87impl Ord for ContextId {
88 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
89 self.id().cmp(&other.id())
90 }
91}
92
93impl Hash for ContextId {
94 fn hash<H>(&self, state: &mut H)
95 where
96 H: Hasher,
97 {
98 self.id().hash(state);
99 }
100}
101
102#[derive(Debug, Clone, Copy, Default)]
104pub struct ContextIdFactory;
105
106impl ContextIdFactory {
107 pub fn create() -> ContextId {
109 ContextId::new(NEXT_CONTEXT_ID.fetch_add(1, Ordering::Relaxed))
110 }
111
112 pub fn get_by_request(request: &BootRequest) -> ContextId {
114 request.context_id().cloned().unwrap_or_else(Self::create)
115 }
116}