vortex_array/arrays/shared/
array.rs1use std::fmt::Display;
5use std::fmt::Formatter;
6use std::future::Future;
7use std::sync::Arc;
8use std::sync::OnceLock;
9
10use async_lock::Mutex as AsyncMutex;
11use vortex_error::SharedVortexResult;
12use vortex_error::VortexResult;
13
14use crate::ArrayRef;
15use crate::Canonical;
16use crate::IntoArray;
17use crate::array::Array;
18use crate::array::ArrayParts;
19use crate::array::TypedArrayRef;
20use crate::array_slots;
21use crate::arrays::Shared;
22
23#[array_slots(Shared)]
24pub struct SharedSlots {
25 #[slot(0)]
27 pub source: ArrayRef,
28}
29
30#[derive(Debug, Clone)]
35pub struct SharedData {
36 cached: Arc<OnceLock<SharedVortexResult<ArrayRef>>>,
37 async_compute_lock: Arc<AsyncMutex<()>>,
38}
39
40impl Display for SharedData {
41 fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result {
42 Ok(())
43 }
44}
45
46#[expect(async_fn_in_trait)]
47pub trait SharedArrayExt: TypedArrayRef<Shared> + SharedArraySlotsExt {
48 fn current_array_ref(&self) -> &ArrayRef {
49 match self.cached.get() {
50 Some(Ok(arr)) => arr,
51 _ => self.source(),
52 }
53 }
54
55 fn get_or_compute(
56 &self,
57 f: impl FnOnce(&ArrayRef) -> VortexResult<Canonical>,
58 ) -> VortexResult<ArrayRef> {
59 let result = self
60 .cached
61 .get_or_init(|| f(self.source()).map(|c| c.into_array()).map_err(Arc::new));
62 result.clone().map_err(Into::into)
63 }
64
65 async fn get_or_compute_async<F, Fut>(&self, f: F) -> VortexResult<ArrayRef>
66 where
67 F: FnOnce(ArrayRef) -> Fut,
68 Fut: Future<Output = VortexResult<Canonical>>,
69 {
70 if let Some(result) = self.cached.get() {
71 return result.clone().map_err(Into::into);
72 }
73
74 let _guard = self.async_compute_lock.lock().await;
75
76 if let Some(result) = self.cached.get() {
77 return result.clone().map_err(Into::into);
78 }
79
80 let computed = f(self.source().clone())
81 .await
82 .map(|c| c.into_array())
83 .map_err(Arc::new);
84
85 let result = self.cached.get_or_init(|| computed);
86 result.clone().map_err(Into::into)
87 }
88}
89impl<T: TypedArrayRef<Shared>> SharedArrayExt for T {}
90
91impl SharedData {
92 pub fn new() -> Self {
93 Self {
94 cached: Arc::new(OnceLock::new()),
95 async_compute_lock: Arc::new(AsyncMutex::new(())),
96 }
97 }
98}
99
100impl Default for SharedData {
101 fn default() -> Self {
102 Self::new()
103 }
104}
105
106impl Array<Shared> {
107 pub fn new(source: ArrayRef) -> Self {
109 let dtype = source.dtype().clone();
110 let len = source.len();
111 unsafe {
112 Array::from_parts_unchecked(
113 ArrayParts::new(Shared, dtype, len, SharedData::new())
114 .with_slots(SharedSlots { source }.into_slots()),
115 )
116 }
117 }
118}