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