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