1use std::{fmt::Debug, marker::PhantomData, sync::Arc};
16
17use foyer_common::code::{Key, Value};
18
19use crate::{record::Record, Eviction};
20
21pub struct Piece<K, V> {
25 record: *const (),
26 key: *const K,
27 value: *const V,
28 hash: u64,
29 drop_fn: fn(*const ()),
30}
31
32impl<K, V> Debug for Piece<K, V> {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 f.debug_struct("Piece")
35 .field("record", &self.record)
36 .field("hash", &self.hash)
37 .finish()
38 }
39}
40
41unsafe impl<K, V> Send for Piece<K, V> {}
42unsafe impl<K, V> Sync for Piece<K, V> {}
43
44impl<K, V> Drop for Piece<K, V> {
45 fn drop(&mut self) {
46 (self.drop_fn)(self.record);
47 }
48}
49
50impl<K, V> Piece<K, V> {
51 pub fn new<E>(record: Arc<Record<E>>) -> Self
53 where
54 E: Eviction<Key = K, Value = V>,
55 {
56 let raw = Arc::into_raw(record);
57 let record = raw as *const ();
58 let key = unsafe { (*raw).key() } as *const _;
59 let value = unsafe { (*raw).value() } as *const _;
60 let hash = unsafe { (*raw).hash() };
61 let drop_fn = |ptr| unsafe {
62 let _ = Arc::from_raw(ptr as *const Record<E>);
63 };
64 Self {
65 record,
66 key,
67 value,
68 hash,
69 drop_fn,
70 }
71 }
72
73 pub fn key(&self) -> &K {
75 unsafe { &*self.key }
76 }
77
78 pub fn value(&self) -> &V {
80 unsafe { &*self.value }
81 }
82
83 pub fn hash(&self) -> u64 {
85 self.hash
86 }
87}
88
89pub trait Pipe: Send + Sync + 'static {
91 type Key;
93 type Value;
95
96 fn is_enabled(&self) -> bool;
98
99 fn send(&self, piece: Piece<Self::Key, Self::Value>);
101}
102
103#[derive(Debug)]
105pub struct NoopPipe<K, V>(PhantomData<(K, V)>);
106
107impl<K, V> Default for NoopPipe<K, V> {
108 fn default() -> Self {
109 Self(PhantomData)
110 }
111}
112
113impl<K, V> Pipe for NoopPipe<K, V>
114where
115 K: Key,
116 V: Value,
117{
118 type Key = K;
119 type Value = V;
120
121 fn is_enabled(&self) -> bool {
122 false
123 }
124
125 fn send(&self, _: Piece<Self::Key, Self::Value>) {}
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131 use crate::{
132 eviction::fifo::{Fifo, FifoHint},
133 record::Data,
134 };
135
136 #[test]
137 fn test_piece() {
138 let r1 = Arc::new(Record::new(Data::<Fifo<Arc<Vec<u8>>, Arc<Vec<u8>>>> {
139 key: Arc::new(vec![b'k'; 4096]),
140 value: Arc::new(vec![b'k'; 16384]),
141 hint: FifoHint,
142 hash: 1,
143 weight: 1,
144 }));
145
146 let p1 = Piece::new(r1.clone());
147 let k1 = p1.key().clone();
148 let r2 = r1.clone();
149 let p2 = Piece::new(r1.clone());
150
151 drop(p1);
152 drop(r2);
153 drop(p2);
154 drop(r1);
155 drop(k1);
156 }
157}