1use core::{cell::UnsafeCell, marker::PhantomData, mem};
2
3use crate::{
4 bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_QUEUE},
5 helpers::{bpf_map_pop_elem, bpf_map_push_elem},
6 maps::PinningType,
7};
8
9#[repr(transparent)]
10pub struct Queue<T> {
11 def: UnsafeCell<bpf_map_def>,
12 _t: PhantomData<T>,
13}
14
15unsafe impl<T: Sync> Sync for Queue<T> {}
16
17impl<T> Queue<T> {
18 pub const fn with_max_entries(max_entries: u32, flags: u32) -> Queue<T> {
19 Queue {
20 def: UnsafeCell::new(bpf_map_def {
21 type_: BPF_MAP_TYPE_QUEUE,
22 key_size: 0,
23 value_size: mem::size_of::<T>() as u32,
24 max_entries,
25 map_flags: flags,
26 id: 0,
27 pinning: PinningType::None as u32,
28 }),
29 _t: PhantomData,
30 }
31 }
32
33 pub const fn pinned(max_entries: u32, flags: u32) -> Queue<T> {
34 Queue {
35 def: UnsafeCell::new(bpf_map_def {
36 type_: BPF_MAP_TYPE_QUEUE,
37 key_size: 0,
38 value_size: mem::size_of::<T>() as u32,
39 max_entries,
40 map_flags: flags,
41 id: 0,
42 pinning: PinningType::ByName as u32,
43 }),
44 _t: PhantomData,
45 }
46 }
47
48 pub fn push(&self, value: &T, flags: u64) -> Result<(), i64> {
49 let ret = unsafe {
50 bpf_map_push_elem(
51 self.def.get() as *mut _,
52 value as *const _ as *const _,
53 flags,
54 )
55 };
56 (ret == 0).then_some(()).ok_or(ret)
57 }
58
59 pub fn pop(&self) -> Option<T> {
60 unsafe {
61 let mut value = mem::MaybeUninit::uninit();
62 let ret = bpf_map_pop_elem(self.def.get() as *mut _, value.as_mut_ptr() as *mut _);
63 (ret == 0).then_some(value.assume_init())
64 }
65 }
66}