torsh_tensor/
lockfree_cache.rs1use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
15use std::sync::Arc;
16
17pub struct LockFreeSPSCQueue<T> {
22 buffer: Vec<Option<T>>,
23 capacity: usize,
24 head: AtomicUsize, tail: AtomicUsize, _padding: [u8; 64], }
28
29impl<T> LockFreeSPSCQueue<T> {
30 pub fn new(capacity: usize) -> Self {
32 let actual_capacity = capacity.next_power_of_two();
33 let mut buffer = Vec::with_capacity(actual_capacity);
34 for _ in 0..actual_capacity {
35 buffer.push(None);
36 }
37
38 Self {
39 buffer,
40 capacity: actual_capacity,
41 head: AtomicUsize::new(0),
42 tail: AtomicUsize::new(0),
43 _padding: [0; 64],
44 }
45 }
46
47 pub fn try_push(&mut self, item: T) -> bool {
49 let tail = self.tail.load(Ordering::Relaxed);
50 let next_tail = (tail + 1) & (self.capacity - 1);
51 let head = self.head.load(Ordering::Acquire);
52
53 if next_tail == head {
54 return false; }
56
57 self.buffer[tail] = Some(item);
59 self.tail.store(next_tail, Ordering::Release);
60 true
61 }
62
63 pub fn try_pop(&mut self) -> Option<T> {
65 let head = self.head.load(Ordering::Relaxed);
66 let tail = self.tail.load(Ordering::Acquire);
67
68 if head == tail {
69 return None; }
71
72 let item = self.buffer[head].take();
73 let next_head = (head + 1) & (self.capacity - 1);
74 self.head.store(next_head, Ordering::Release);
75
76 item
77 }
78
79 pub fn is_empty(&self) -> bool {
81 let head = self.head.load(Ordering::Acquire);
82 let tail = self.tail.load(Ordering::Acquire);
83 head == tail
84 }
85
86 pub fn len(&self) -> usize {
88 let head = self.head.load(Ordering::Acquire);
89 let tail = self.tail.load(Ordering::Acquire);
90
91 if tail >= head {
92 tail - head
93 } else {
94 self.capacity - head + tail
95 }
96 }
97
98 pub fn capacity(&self) -> usize {
100 self.capacity
101 }
102}
103
104#[derive(Clone)]
106pub struct LockFreeCacheEntry<T: Clone> {
107 data: Arc<T>,
108 access_count: Arc<AtomicUsize>,
109 last_access: Arc<AtomicUsize>, valid: Arc<AtomicBool>,
111}
112
113impl<T: Clone> LockFreeCacheEntry<T> {
114 pub fn new(data: T) -> Self {
116 Self {
117 data: Arc::new(data),
118 access_count: Arc::new(AtomicUsize::new(0)),
119 last_access: Arc::new(AtomicUsize::new(Self::current_timestamp())),
120 valid: Arc::new(AtomicBool::new(true)),
121 }
122 }
123
124 pub fn get(&self) -> Option<Arc<T>> {
126 if self.valid.load(Ordering::Acquire) {
127 self.access_count.fetch_add(1, Ordering::Relaxed);
128 self.last_access
129 .store(Self::current_timestamp(), Ordering::Release);
130 Some(Arc::clone(&self.data))
131 } else {
132 None
133 }
134 }
135
136 pub fn invalidate(&self) {
138 self.valid.store(false, Ordering::Release);
139 }
140
141 pub fn is_valid(&self) -> bool {
143 self.valid.load(Ordering::Acquire)
144 }
145
146 pub fn access_count(&self) -> usize {
148 self.access_count.load(Ordering::Relaxed)
149 }
150
151 pub fn last_access(&self) -> usize {
153 self.last_access.load(Ordering::Relaxed)
154 }
155
156 fn current_timestamp() -> usize {
158 use std::sync::atomic::AtomicUsize as GlobalCounter;
159 static COUNTER: GlobalCounter = GlobalCounter::new(0);
160 COUNTER.fetch_add(1, Ordering::Relaxed)
161 }
162}
163
164pub struct LockFreeCache<K: Eq + std::hash::Hash + Clone, V: Clone> {
169 entries: Vec<Option<(K, LockFreeCacheEntry<V>)>>,
170 size: AtomicUsize,
171 capacity: usize,
172}
173
174impl<K: Eq + std::hash::Hash + Clone, V: Clone> LockFreeCache<K, V> {
175 pub fn new(capacity: usize) -> Self {
177 let mut entries = Vec::with_capacity(capacity);
178 for _ in 0..capacity {
179 entries.push(None);
180 }
181
182 Self {
183 entries,
184 size: AtomicUsize::new(0),
185 capacity,
186 }
187 }
188
189 pub fn capacity(&self) -> usize {
191 self.capacity
192 }
193
194 pub fn len(&self) -> usize {
196 self.size.load(Ordering::Relaxed)
197 }
198
199 pub fn is_empty(&self) -> bool {
201 self.len() == 0
202 }
203
204 fn hash(&self, key: &K) -> usize {
206 use std::collections::hash_map::DefaultHasher;
207 use std::hash::Hasher;
208
209 let mut hasher = DefaultHasher::new();
210 key.hash(&mut hasher);
211 (hasher.finish() as usize) % self.capacity
212 }
213
214 pub fn get(&self, key: &K) -> Option<Arc<V>> {
216 let index = self.hash(key);
217 let mut probe = 0;
218
219 while probe < self.capacity {
220 let current_index = (index + probe) % self.capacity;
221
222 if let Some((ref k, ref entry)) = unsafe { &*self.entries.as_ptr().add(current_index) }
224 {
225 if k == key {
226 return entry.get();
227 }
228 } else {
229 return None;
231 }
232
233 probe += 1;
234 }
235
236 None
237 }
238
239 pub fn contains_key(&self, key: &K) -> bool {
241 self.get(key).is_some()
242 }
243}
244
245#[derive(Debug, Default)]
247pub struct LockFreeStats {
248 pub successes: AtomicUsize,
250 pub failures: AtomicUsize,
252 pub retries: AtomicUsize,
254}
255
256impl LockFreeStats {
257 pub fn new() -> Self {
259 Self::default()
260 }
261
262 pub fn record_success(&self) {
264 self.successes.fetch_add(1, Ordering::Relaxed);
265 }
266
267 pub fn record_failure(&self) {
269 self.failures.fetch_add(1, Ordering::Relaxed);
270 }
271
272 pub fn record_retry(&self) {
274 self.retries.fetch_add(1, Ordering::Relaxed);
275 }
276
277 pub fn successes(&self) -> usize {
279 self.successes.load(Ordering::Relaxed)
280 }
281
282 pub fn failures(&self) -> usize {
284 self.failures.load(Ordering::Relaxed)
285 }
286
287 pub fn retries(&self) -> usize {
289 self.retries.load(Ordering::Relaxed)
290 }
291
292 pub fn success_rate(&self) -> f64 {
294 let total = self.successes() + self.failures();
295 if total == 0 {
296 0.0
297 } else {
298 self.successes() as f64 / total as f64
299 }
300 }
301
302 pub fn reset(&self) {
304 self.successes.store(0, Ordering::Relaxed);
305 self.failures.store(0, Ordering::Relaxed);
306 self.retries.store(0, Ordering::Relaxed);
307 }
308}
309
310#[cfg(test)]
311mod tests {
312 use super::*;
313
314 #[test]
315 fn test_spsc_queue_basic() {
316 let mut queue = LockFreeSPSCQueue::new(4);
317
318 assert!(queue.is_empty());
319 assert_eq!(queue.len(), 0);
320
321 assert!(queue.try_push(1));
322 assert!(queue.try_push(2));
323 assert!(queue.try_push(3));
324
325 assert_eq!(queue.len(), 3);
326 assert!(!queue.is_empty());
327
328 assert_eq!(queue.try_pop(), Some(1));
329 assert_eq!(queue.try_pop(), Some(2));
330 assert_eq!(queue.len(), 1);
331
332 assert_eq!(queue.try_pop(), Some(3));
333 assert!(queue.is_empty());
334 assert_eq!(queue.try_pop(), None);
335 }
336
337 #[test]
338 fn test_spsc_queue_full() {
339 let mut queue = LockFreeSPSCQueue::new(2);
340
341 assert!(queue.try_push(1));
343
344 assert!(!queue.try_push(2));
346
347 assert_eq!(queue.try_pop(), Some(1));
349
350 assert!(queue.try_push(3));
352 }
353
354 #[test]
355 fn test_spsc_queue_wraparound() {
356 let mut queue = LockFreeSPSCQueue::new(4);
357
358 assert!(queue.try_push(1));
360 assert!(queue.try_push(2));
361
362 assert_eq!(queue.try_pop(), Some(1));
364
365 assert!(queue.try_push(3));
367 assert!(queue.try_push(4));
368
369 assert_eq!(queue.try_pop(), Some(2));
371 assert_eq!(queue.try_pop(), Some(3));
372 assert_eq!(queue.try_pop(), Some(4));
373 assert_eq!(queue.try_pop(), None);
374 }
375
376 #[test]
377 fn test_cache_entry_basic() {
378 let entry = LockFreeCacheEntry::new(42);
379
380 assert!(entry.is_valid());
381 assert_eq!(*entry.get().expect("get should succeed"), 42);
382 assert_eq!(entry.access_count(), 1);
383
384 entry.invalidate();
385 assert!(!entry.is_valid());
386 assert!(entry.get().is_none());
387 }
388
389 #[test]
390 fn test_cache_entry_access_count() {
391 let entry = LockFreeCacheEntry::new("test");
392
393 assert_eq!(entry.access_count(), 0);
394
395 entry.get();
396 assert_eq!(entry.access_count(), 1);
397
398 entry.get();
399 entry.get();
400 assert_eq!(entry.access_count(), 3);
401 }
402
403 #[test]
404 fn test_lock_free_cache_basic() {
405 let cache: LockFreeCache<String, i32> = LockFreeCache::new(10);
406
407 assert_eq!(cache.capacity(), 10);
408 assert_eq!(cache.len(), 0);
409 assert!(cache.is_empty());
410 }
411
412 #[test]
413 fn test_lock_free_cache_contains() {
414 let cache = LockFreeCache::<String, i32>::new(10);
415
416 assert!(!cache.contains_key(&"test".to_string()));
417 }
418
419 #[test]
420 fn test_lockfree_stats() {
421 let stats = LockFreeStats::new();
422
423 assert_eq!(stats.successes(), 0);
424 assert_eq!(stats.failures(), 0);
425 assert_eq!(stats.retries(), 0);
426
427 stats.record_success();
428 stats.record_success();
429 stats.record_failure();
430
431 assert_eq!(stats.successes(), 2);
432 assert_eq!(stats.failures(), 1);
433
434 let rate = stats.success_rate();
435 assert!((rate - 0.666).abs() < 0.01);
436
437 stats.reset();
438 assert_eq!(stats.successes(), 0);
439 assert_eq!(stats.failures(), 0);
440 }
441
442 #[test]
443 fn test_spsc_queue_capacity() {
444 let queue = LockFreeSPSCQueue::<i32>::new(7);
445 assert_eq!(queue.capacity(), 8);
447 }
448
449 #[test]
450 fn test_cache_entry_timestamp() {
451 let entry1 = LockFreeCacheEntry::new(1);
452 let entry2 = LockFreeCacheEntry::new(2);
453
454 let ts1 = entry1.last_access();
455 let ts2 = entry2.last_access();
456
457 assert!(ts2 > ts1);
459 }
460}