19
19
//! into the event cache for the actual storage. By default this brings an
20
20
//! in-memory store.
21
21
22
- use std::{str::Utf8Error, sync::Arc};
22
+ use std::{fmt, ops::Deref, str::Utf8Error, sync::Arc};
23
23
24
24
#[cfg(any(test, feature = "testing"))]
25
25
#[macro_use]
26
26
pub mod integration_tests;
27
27
mod memory_store;
28
28
mod traits;
29
29
30
- use matrix_sdk_common::store_locks::BackingStore;
30
+ use matrix_sdk_common::store_locks::{
31
+ BackingStore, CrossProcessStoreLock, CrossProcessStoreLockGuard, LockStoreError,
32
+ };
31
33
pub use matrix_sdk_store_encryption::Error as StoreEncryptionError;
32
34
33
35
#[cfg(any(test, feature = "testing"))]
@@ -37,6 +39,75 @@ pub use self::{
37
39
traits::{DynEventCacheStore, EventCacheStore, IntoEventCacheStore},
38
40
};
39
41
42
+ /// The high-level public type to represent an `EventCacheStore` lock.
43
+ pub struct EventCacheStoreLock {
44
+ /// The inner cross process lock that is used to lock the `EventCacheStore`.
45
+ cross_process_lock: CrossProcessStoreLock<LockableEventCacheStore>,
46
+
47
+ /// The store itself.
48
+ ///
49
+ /// That's the only place where the store exists.
50
+ store: Arc<DynEventCacheStore>,
51
+ }
52
+
53
+ impl fmt::Debug for EventCacheStoreLock {
54
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
55
+ formatter.debug_struct("EventCacheStoreLock").finish_non_exhaustive()
56
+ }
57
+ }
58
+
59
+ impl EventCacheStoreLock {
60
+ /// Create a new lock around the [`EventCacheStore`].
61
+ pub fn new<S>(store: S, key: String, holder: String) -> Self
62
+ where
63
+ S: IntoEventCacheStore,
64
+ {
65
+ let store = store.into_event_cache_store();
66
+
67
+ Self {
68
+ cross_process_lock: CrossProcessStoreLock::new(
69
+ LockableEventCacheStore(store.clone()),
70
+ key,
71
+ holder,
72
+ ),
73
+ store,
74
+ }
75
+ }
76
+
77
+ /// Acquire a spin lock (see [`CrossProcessStoreLock::spin_lock`]).
78
+ pub async fn lock(&self) -> Result<EventCacheStoreLockGuard<'_>, LockStoreError> {
79
+ let cross_process_lock_guard = self.cross_process_lock.spin_lock(None).await?;
80
+
81
+ Ok(EventCacheStoreLockGuard { cross_process_lock_guard, store: self.store.deref() })
82
+ }
83
+ }
84
+
85
+ /// An RAII implementation of a “scoped lock” of an [`EventCacheStoreLock`].
86
+ /// When this structure is dropped (falls out of scope), the lock will be
87
+ /// unlocked.
88
+ pub struct EventCacheStoreLockGuard<'a> {
89
+ /// The cross process lock guard.
90
+ #[allow(unused)]
91
+ cross_process_lock_guard: CrossProcessStoreLockGuard,
92
+
93
+ /// A reference to the store.
94
+ store: &'a DynEventCacheStore,
95
+ }
96
+
97
+ impl<'a> fmt::Debug for EventCacheStoreLockGuard<'a> {
98
+ fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
99
+ formatter.debug_struct("EventCacheStoreLockGuard").finish_non_exhaustive()
100
+ }
101
+ }
102
+
103
+ impl<'a> Deref for EventCacheStoreLockGuard<'a> {
104
+ type Target = DynEventCacheStore;
105
+
106
+ fn deref(&self) -> &Self::Target {
107
+ self.store
108
+ }
109
+ }
110
+
40
111
/// Event cache store specific error type.
41
112
#[derive(Debug, thiserror::Error)]
42
113
pub enum EventCacheStoreError {
0 commit comments