1
1
// Copyright 2021-Present Datadog, Inc. https://www.datadoghq.com/
2
2
// SPDX-License-Identifier: Apache-2.0
3
3
4
+ use crate :: Error ;
4
5
use anyhow:: Context ;
5
- use ddcommon_ffi:: Error ;
6
6
use std:: ffi:: c_void;
7
7
8
8
#[ repr( C ) ]
9
+ // A simple wrapper around crossbeam_queue::ArrayQueue<*mut c_void>, which is a lock free
10
+ // bounded multi-producer and multi-consumer (MPMC) queue.
9
11
pub struct ArrayQueue {
12
+ // The actual type here should be *mut crossbeam_queue::ArrayQueue<*mut c_void>.
13
+ // However, cbindgen does not use the module name crossbeam_queue to generate the C header.
14
+ // So we use *mut c_void here and cast it to the correct type in the FFI functions.
10
15
inner : * mut c_void ,
16
+ item_delete_fn : unsafe extern "C" fn ( * mut c_void ) -> c_void ,
11
17
}
12
18
13
19
impl ArrayQueue {
14
- pub fn new ( inner : * mut c_void ) -> Self {
15
- Self { inner }
20
+ pub fn new (
21
+ inner : * mut c_void ,
22
+ item_delete_fn : unsafe extern "C" fn ( * mut c_void ) -> c_void ,
23
+ ) -> Self {
24
+ Self {
25
+ inner,
26
+ item_delete_fn,
27
+ }
28
+ }
29
+ }
30
+
31
+ impl Drop for ArrayQueue {
32
+ fn drop ( & mut self ) {
33
+ unsafe {
34
+ let queue = self . inner as * mut crossbeam_queue:: ArrayQueue < * mut c_void > ;
35
+ while let Some ( item) = ( * queue) . pop ( ) {
36
+ ( self . item_delete_fn ) ( item) ;
37
+ }
38
+ drop ( Box :: from_raw ( queue) ) ;
39
+ }
16
40
}
17
41
}
18
42
@@ -23,15 +47,23 @@ pub enum ArrayQueueNewResult {
23
47
Err ( Error ) ,
24
48
}
25
49
50
+ /// Creates a new ArrayQueue with the given capacity and item_delete_fn.
51
+ /// The item_delete_fn is called when an item is dropped from the queue.
26
52
#[ no_mangle]
27
- pub unsafe extern "C" fn array_queue_new ( capacity : usize ) -> ArrayQueueNewResult {
53
+ pub extern "C" fn array_queue_new (
54
+ capacity : usize ,
55
+ item_delete_fn : unsafe extern "C" fn ( * mut c_void ) -> c_void ,
56
+ ) -> ArrayQueueNewResult {
28
57
let internal_queue: crossbeam_queue:: ArrayQueue < * mut c_void > =
29
58
crossbeam_queue:: ArrayQueue :: new ( capacity) ;
30
59
let internal_queue_ptr = Box :: into_raw ( Box :: new ( internal_queue) ) ;
31
- let ffi_queue = ArrayQueue :: new ( internal_queue_ptr as * mut c_void ) ;
60
+ let ffi_queue = ArrayQueue :: new ( internal_queue_ptr as * mut c_void , item_delete_fn ) ;
32
61
ArrayQueueNewResult :: Ok ( ffi_queue)
33
62
}
34
63
64
+ /// Converts a *mut ArrayQueue to a &mut crossbeam_queue::ArrayQueue<*mut c_void>.
65
+ /// # Safety
66
+ /// The pointer is null or points to a valid memory location allocated by array_queue_new.
35
67
unsafe fn array_queue_ptr_to_inner < ' a > (
36
68
queue_ptr : * mut ArrayQueue ,
37
69
) -> anyhow:: Result < & ' a mut crossbeam_queue:: ArrayQueue < * mut c_void > > {
@@ -46,6 +78,16 @@ unsafe fn array_queue_ptr_to_inner<'a>(
46
78
}
47
79
}
48
80
81
+ /// Drops the ArrayQueue.
82
+ /// # Safety
83
+ /// The pointer is null or points to a valid memory location allocated by array_queue_new.
84
+ #[ no_mangle]
85
+ pub unsafe extern "C" fn array_queue_drop ( queue_ptr : * mut ArrayQueue ) {
86
+ if !queue_ptr. is_null ( ) {
87
+ drop ( Box :: from_raw ( queue_ptr) ) ;
88
+ }
89
+ }
90
+
49
91
#[ allow( unused) ]
50
92
#[ repr( C ) ]
51
93
pub enum ArrayQueuePushResult {
@@ -62,6 +104,10 @@ impl From<Result<(), anyhow::Error>> for ArrayQueuePushResult {
62
104
}
63
105
}
64
106
107
+ /// Pushes an item into the ArrayQueue.
108
+ /// # Safety
109
+ /// The pointer is null or points to a valid memory location allocated by array_queue_new. The value
110
+ /// is null or points to a valid memory location that can be deallocated by the item_delete_fn.
65
111
#[ no_mangle]
66
112
pub unsafe extern "C" fn array_queue_push (
67
113
queue_ptr : * mut ArrayQueue ,
@@ -93,6 +139,9 @@ impl From<anyhow::Result<*mut c_void>> for ArrayQueuePopResult {
93
139
}
94
140
}
95
141
142
+ /// Pops an item from the ArrayQueue.
143
+ /// # Safety
144
+ /// The pointer is null or points to a valid memory location allocated by array_queue_new.
96
145
#[ no_mangle]
97
146
pub unsafe extern "C" fn array_queue_pop ( queue_ptr : * mut ArrayQueue ) -> ArrayQueuePopResult {
98
147
( || {
@@ -121,6 +170,9 @@ impl From<anyhow::Result<bool>> for ArrayQueueIsEmptyResult {
121
170
}
122
171
}
123
172
173
+ /// Checks if the ArrayQueue is empty.
174
+ /// # Safety
175
+ /// The pointer is null or points to a valid memory location allocated by array_queue_new.
124
176
#[ no_mangle]
125
177
pub unsafe extern "C" fn array_queue_is_empty (
126
178
queue_ptr : * mut ArrayQueue ,
@@ -149,6 +201,9 @@ impl From<anyhow::Result<usize>> for ArrayQueueLenResult {
149
201
}
150
202
}
151
203
204
+ /// Returns the length of the ArrayQueue.
205
+ /// # Safety
206
+ /// The pointer is null or points to a valid memory location allocated by array_queue_new.
152
207
#[ no_mangle]
153
208
pub unsafe extern "C" fn array_queue_len ( queue_ptr : * mut ArrayQueue ) -> ArrayQueueLenResult {
154
209
( || {
0 commit comments