reifydb_core/value/column/pool/
guard.rs1use std::{
11 fmt,
12 fmt::{Debug, Formatter},
13 ops::{Deref, DerefMut},
14 rc::{Rc, Weak},
15};
16
17use reifydb_type::value::{
18 container::{
19 blob::BlobContainer, bool::BoolContainer, number::NumberContainer, row::RowNumberContainer,
20 temporal::TemporalContainer, utf8::Utf8Container, uuid::UuidContainer,
21 },
22 date::Date,
23 datetime::DateTime,
24 duration::Duration,
25 time::Time,
26 uuid::{Uuid4, Uuid7},
27};
28
29use super::{Pools, PoolsInner, allocator::PoolAllocator};
30
31pub trait Releasable: Clone + Debug {
33 fn release_to_pool(self, pools: &Pools);
34}
35
36impl Releasable for BoolContainer {
38 fn release_to_pool(self, pools: &Pools) {
39 pools.bool_pool().release(self);
40 }
41}
42
43impl Releasable for Utf8Container {
44 fn release_to_pool(self, pools: &Pools) {
45 pools.string_pool().release(self);
46 }
47}
48
49impl Releasable for BlobContainer {
50 fn release_to_pool(self, pools: &Pools) {
51 pools.blob_pool().release(self);
52 }
53}
54
55impl Releasable for RowNumberContainer {
56 fn release_to_pool(self, pools: &Pools) {
57 pools.row_number_pool().release(self);
58 }
59}
60
61impl Releasable for NumberContainer<i32> {
62 fn release_to_pool(self, pools: &Pools) {
63 pools.i32_pool().release(self);
64 }
65}
66
67impl Releasable for NumberContainer<i64> {
68 fn release_to_pool(self, pools: &Pools) {
69 pools.i64_pool().release(self);
70 }
71}
72
73impl Releasable for NumberContainer<f32> {
74 fn release_to_pool(self, pools: &Pools) {
75 pools.f32_pool().release(self);
76 }
77}
78
79impl Releasable for NumberContainer<f64> {
80 fn release_to_pool(self, pools: &Pools) {
81 pools.f64_pool().release(self);
82 }
83}
84
85impl Releasable for NumberContainer<i8> {
86 fn release_to_pool(self, pools: &Pools) {
87 pools.i8_pool().release(self);
88 }
89}
90
91impl Releasable for NumberContainer<i16> {
92 fn release_to_pool(self, pools: &Pools) {
93 pools.i16_pool().release(self);
94 }
95}
96
97impl Releasable for NumberContainer<i128> {
98 fn release_to_pool(self, pools: &Pools) {
99 pools.i128_pool().release(self);
100 }
101}
102
103impl Releasable for NumberContainer<u8> {
104 fn release_to_pool(self, pools: &Pools) {
105 pools.u8_pool().release(self);
106 }
107}
108
109impl Releasable for NumberContainer<u16> {
110 fn release_to_pool(self, pools: &Pools) {
111 pools.u16_pool().release(self);
112 }
113}
114
115impl Releasable for NumberContainer<u32> {
116 fn release_to_pool(self, pools: &Pools) {
117 pools.u32_pool().release(self);
118 }
119}
120
121impl Releasable for NumberContainer<u64> {
122 fn release_to_pool(self, pools: &Pools) {
123 pools.u64_pool().release(self);
124 }
125}
126
127impl Releasable for NumberContainer<u128> {
128 fn release_to_pool(self, pools: &Pools) {
129 pools.u128_pool().release(self);
130 }
131}
132
133impl Releasable for TemporalContainer<Date> {
134 fn release_to_pool(self, pools: &Pools) {
135 pools.date_pool().release(self);
136 }
137}
138
139impl Releasable for TemporalContainer<DateTime> {
140 fn release_to_pool(self, pools: &Pools) {
141 pools.datetime_pool().release(self);
142 }
143}
144
145impl Releasable for TemporalContainer<Time> {
146 fn release_to_pool(self, pools: &Pools) {
147 pools.time_pool().release(self);
148 }
149}
150
151impl Releasable for TemporalContainer<Duration> {
152 fn release_to_pool(self, pools: &Pools) {
153 pools.duration_pool().release(self);
154 }
155}
156
157impl Releasable for UuidContainer<Uuid4> {
158 fn release_to_pool(self, pools: &Pools) {
159 pools.uuid4_pool().release(self);
160 }
161}
162
163impl Releasable for UuidContainer<Uuid7> {
164 fn release_to_pool(self, pools: &Pools) {
165 pools.uuid7_pool().release(self);
166 }
167}
168
169pub struct PooledGuard<T: Releasable> {
175 container: Option<T>,
176 pools: Weak<PoolsInner>,
177}
178
179impl<T: Releasable> Debug for PooledGuard<T> {
180 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
181 Debug::fmt(&self.container, f)
182 }
183}
184
185impl<T: Releasable> PooledGuard<T> {
186 fn new(container: T, pools: Pools) -> Self {
189 Self {
190 container: Some(container),
191 pools: Rc::downgrade(&pools.0),
192 }
193 }
194
195 pub fn to_owned(mut self) -> T {
200 let container = self.container.take().expect("Container already taken");
201 let cloned_container = container.clone();
202
203 if let Some(pools_inner) = self.pools.upgrade() {
205 container.release_to_pool(&Pools(pools_inner));
206 }
207
208 cloned_container
209 }
210
211 pub fn is_empty(&self) -> bool {
213 self.container.is_none()
214 }
215}
216
217impl PooledGuard<BoolContainer> {
219 pub fn new_bool(pools: Pools, capacity: usize) -> Self {
221 let container = pools.bool_pool().acquire(capacity);
222 Self::new(container, pools)
223 }
224}
225
226impl PooledGuard<Utf8Container> {
227 pub fn new_string(pools: Pools, capacity: usize) -> Self {
229 let container = pools.string_pool().acquire(capacity);
230 Self::new(container, pools)
231 }
232}
233
234impl PooledGuard<BlobContainer> {
235 pub fn new_blob(pools: Pools, capacity: usize) -> Self {
237 let container = pools.blob_pool().acquire(capacity);
238 Self::new(container, pools)
239 }
240}
241
242impl PooledGuard<RowNumberContainer> {
243 pub fn new_row_number(pools: Pools, capacity: usize) -> Self {
245 let container = pools.row_number_pool().acquire(capacity);
246 Self::new(container, pools)
247 }
248}
249
250impl PooledGuard<NumberContainer<i32>> {
252 pub fn new_i32(pools: Pools, capacity: usize) -> Self {
254 let container = pools.i32_pool().acquire(capacity);
255 Self::new(container, pools)
256 }
257}
258
259impl PooledGuard<NumberContainer<i64>> {
260 pub fn new_i64(pools: Pools, capacity: usize) -> Self {
262 let container = pools.i64_pool().acquire(capacity);
263 Self::new(container, pools)
264 }
265}
266
267impl PooledGuard<NumberContainer<f32>> {
268 pub fn new_f32(pools: Pools, capacity: usize) -> Self {
270 let container = pools.f32_pool().acquire(capacity);
271 Self::new(container, pools)
272 }
273}
274
275impl PooledGuard<NumberContainer<f64>> {
276 pub fn new_f64(pools: Pools, capacity: usize) -> Self {
278 let container = pools.f64_pool().acquire(capacity);
279 Self::new(container, pools)
280 }
281}
282
283impl PooledGuard<NumberContainer<i8>> {
284 pub fn new_i8(pools: Pools, capacity: usize) -> Self {
286 let container = pools.i8_pool().acquire(capacity);
287 Self::new(container, pools)
288 }
289}
290
291impl PooledGuard<NumberContainer<i16>> {
292 pub fn new_i16(pools: Pools, capacity: usize) -> Self {
294 let container = pools.i16_pool().acquire(capacity);
295 Self::new(container, pools)
296 }
297}
298
299impl PooledGuard<NumberContainer<i128>> {
300 pub fn new_i128(pools: Pools, capacity: usize) -> Self {
303 let container = pools.i128_pool().acquire(capacity);
304 Self::new(container, pools)
305 }
306}
307
308impl PooledGuard<NumberContainer<u8>> {
309 pub fn new_u8(pools: Pools, capacity: usize) -> Self {
311 let container = pools.u8_pool().acquire(capacity);
312 Self::new(container, pools)
313 }
314}
315
316impl PooledGuard<NumberContainer<u16>> {
317 pub fn new_u16(pools: Pools, capacity: usize) -> Self {
319 let container = pools.u16_pool().acquire(capacity);
320 Self::new(container, pools)
321 }
322}
323
324impl PooledGuard<NumberContainer<u32>> {
325 pub fn new_u32(pools: Pools, capacity: usize) -> Self {
327 let container = pools.u32_pool().acquire(capacity);
328 Self::new(container, pools)
329 }
330}
331
332impl PooledGuard<NumberContainer<u64>> {
333 pub fn new_u64(pools: Pools, capacity: usize) -> Self {
335 let container = pools.u64_pool().acquire(capacity);
336 Self::new(container, pools)
337 }
338}
339
340impl PooledGuard<NumberContainer<u128>> {
341 pub fn new_u128(pools: Pools, capacity: usize) -> Self {
344 let container = pools.u128_pool().acquire(capacity);
345 Self::new(container, pools)
346 }
347}
348
349impl PooledGuard<TemporalContainer<Date>> {
351 pub fn new_date(pools: Pools, capacity: usize) -> Self {
354 let container = pools.date_pool().acquire(capacity);
355 Self::new(container, pools)
356 }
357}
358
359impl PooledGuard<TemporalContainer<DateTime>> {
360 pub fn new_datetime(pools: Pools, capacity: usize) -> Self {
363 let container = pools.datetime_pool().acquire(capacity);
364 Self::new(container, pools)
365 }
366}
367
368impl PooledGuard<TemporalContainer<Time>> {
369 pub fn new_time(pools: Pools, capacity: usize) -> Self {
372 let container = pools.time_pool().acquire(capacity);
373 Self::new(container, pools)
374 }
375}
376
377impl PooledGuard<TemporalContainer<Duration>> {
378 pub fn new_duration(pools: Pools, capacity: usize) -> Self {
381 let container = pools.duration_pool().acquire(capacity);
382 Self::new(container, pools)
383 }
384}
385
386impl PooledGuard<UuidContainer<Uuid4>> {
388 pub fn new_uuid4(pools: Pools, capacity: usize) -> Self {
390 let container = pools.uuid4_pool().acquire(capacity);
391 Self::new(container, pools)
392 }
393}
394
395impl PooledGuard<UuidContainer<Uuid7>> {
396 pub fn new_uuid7(pools: Pools, capacity: usize) -> Self {
398 let container = pools.uuid7_pool().acquire(capacity);
399 Self::new(container, pools)
400 }
401}
402
403impl<T: Releasable> Drop for PooledGuard<T> {
405 fn drop(&mut self) {
406 if let (Some(container), Some(pools_inner)) = (self.container.take(), self.pools.upgrade()) {
407 container.release_to_pool(&Pools(pools_inner));
408 }
409 }
410}
411
412impl<T: Releasable> Deref for PooledGuard<T> {
414 type Target = T;
415
416 fn deref(&self) -> &Self::Target {
417 self.container.as_ref().expect("Container has been taken")
418 }
419}
420
421impl<T: Releasable> DerefMut for PooledGuard<T> {
423 fn deref_mut(&mut self) -> &mut Self::Target {
424 self.container.as_mut().expect("Container has been taken")
425 }
426}
427
428#[cfg(test)]
429pub mod tests {
430 use super::*;
431
432 #[test]
433 fn test_bool_container_guard() {
434 let pools = Pools::default();
435
436 let initial_stats = pools.bool_pool().stats();
438 assert_eq!(initial_stats.available, 0);
439
440 {
441 let guard = PooledGuard::new_bool(pools.clone(), 10);
442 assert!(guard.capacity() >= 10);
443 assert_eq!(guard.len(), 0);
444
445 let stats = pools.bool_pool().stats();
447 assert_eq!(stats.total_acquired, 1);
448 assert_eq!(stats.available, 0);
449 } let final_stats = pools.bool_pool().stats();
453 assert_eq!(final_stats.total_acquired, 1);
454 assert_eq!(final_stats.total_released, 1);
455 assert_eq!(final_stats.available, 1);
456 }
457
458 #[test]
459 fn test_number_container_guard() {
460 let pools = Pools::default();
461
462 {
463 let mut guard = PooledGuard::new_i32(pools.clone(), 20);
464 assert!(guard.capacity() >= 20);
465
466 guard.push(42);
468 guard.push(100);
469 assert_eq!(guard.len(), 2);
470 assert_eq!(guard.get(0), Some(&42));
471 assert_eq!(guard.get(1), Some(&100));
472 }
473
474 let stats = pools.i32_pool().stats();
476 assert_eq!(stats.available, 1);
477 }
478
479 #[test]
480 fn test_string_container_guard() {
481 let pools = Pools::default();
482
483 {
484 let mut guard = PooledGuard::new_string(pools.clone(), 5);
485 guard.push("hello".to_string());
486 guard.push("world".to_string());
487 assert_eq!(guard.len(), 2);
488 }
489
490 let stats = pools.string_pool().stats();
491 assert_eq!(stats.available, 1);
492 }
493
494 #[test]
495 fn test_guard_to_owned() {
496 let pools = Pools::default();
497
498 let guard = PooledGuard::new_bool(pools.clone(), 10);
499 let container = guard.to_owned(); assert!(container.capacity() >= 10);
502
503 let stats = pools.bool_pool().stats();
505 assert_eq!(stats.available, 1);
506 assert_eq!(stats.total_released, 1);
507
508 assert!(container.capacity() >= 10);
510 }
511
512 #[test]
513 fn test_multiple_guards_same_pool() {
514 let pools = Pools::default();
515
516 {
517 let _guard1 = PooledGuard::new_f32(pools.clone(), 100);
518 let _guard2 = PooledGuard::new_f32(pools.clone(), 200);
519 let _guard3 = PooledGuard::new_f32(pools.clone(), 50);
520
521 let stats = pools.f32_pool().stats();
522 assert_eq!(stats.total_acquired, 3);
523 assert_eq!(stats.available, 0);
524 }
525
526 let final_stats = pools.f32_pool().stats();
528 assert_eq!(final_stats.total_released, 3);
529 assert_eq!(final_stats.available, 3);
530 }
531
532 #[test]
533 fn test_guard_reuse() {
534 let pools = Pools::default();
535
536 {
538 let mut guard = PooledGuard::new_i64(pools.clone(), 50);
539 guard.push(123);
540 assert_eq!(guard.len(), 1);
541 }
542
543 {
545 let guard = PooledGuard::new_i64(pools.clone(), 50);
546 assert_eq!(guard.len(), 0);
548 assert!(guard.capacity() >= 50);
549 }
550
551 let stats = pools.i64_pool().stats();
552 assert_eq!(stats.total_acquired, 2);
553 assert_eq!(stats.total_released, 2);
554 assert_eq!(stats.available, 1);
555 }
556
557 #[test]
558 fn test_temporal_containers() {
559 let pools = Pools::default();
560
561 {
562 let _date_guard = PooledGuard::new_date(pools.clone(), 10);
563 let _datetime_guard = PooledGuard::new_datetime(pools.clone(), 20);
564 let _time_guard = PooledGuard::new_time(pools.clone(), 30);
565 let _duration_guard = PooledGuard::new_duration(pools.clone(), 40);
566 }
567
568 let all_stats = pools.all_stats();
569 assert_eq!(all_stats["date"].available, 1);
570 assert_eq!(all_stats["datetime"].available, 1);
571 assert_eq!(all_stats["time"].available, 1);
572 assert_eq!(all_stats["duration"].available, 1);
573 }
574
575 #[test]
576 fn test_uuid_containers() {
577 let pools = Pools::default();
578
579 {
580 let _uuid4_guard = PooledGuard::new_uuid4(pools.clone(), 15);
581 let _uuid7_guard = PooledGuard::new_uuid7(pools.clone(), 25);
582 }
583
584 let all_stats = pools.all_stats();
585 assert_eq!(all_stats["uuid4"].available, 1);
586 assert_eq!(all_stats["uuid7"].available, 1);
587 }
588}