Skip to content
This repository was archived by the owner on Jun 8, 2021. It is now read-only.

Commit c54924e

Browse files
committed
Add init/clear function for boxed types
These allow allocated them on our side and releasing all memory of them again. It is needed for functions that take an out parameter and require us to allocate the underlying object. Fixes #469
1 parent 34b8df4 commit c54924e

File tree

2 files changed

+167
-68
lines changed

2 files changed

+167
-68
lines changed

src/boxed.rs

Lines changed: 135 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -17,69 +17,38 @@ use translate::*;
1717
#[macro_export]
1818
macro_rules! glib_boxed_wrapper {
1919
([$($attr:meta)*] $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr,
20-
@free $free_arg:ident $free_expr:expr,
20+
@free $free_arg:ident $free_expr:expr, @init $init_arg:ident $init_expr:expr, @clear $clear_arg:ident $clear_expr:expr,
2121
@get_type $get_type_expr:expr) => {
22-
glib_boxed_wrapper!([$($attr)*] $name, $ffi_name, @copy $copy_arg $copy_expr,
23-
@free $free_arg $free_expr);
24-
25-
impl $crate::types::StaticType for $name {
26-
fn static_type() -> $crate::types::Type {
27-
#[allow(unused_unsafe)]
28-
unsafe { $crate::translate::from_glib($get_type_expr) }
29-
}
30-
}
31-
32-
#[doc(hidden)]
33-
impl<'a> $crate::value::FromValueOptional<'a> for $name {
34-
unsafe fn from_value_optional(value: &$crate::Value) -> Option<Self> {
35-
$crate::translate::from_glib_full($crate::gobject_sys::g_value_dup_boxed($crate::translate::ToGlibPtr::to_glib_none(value).0) as *mut $ffi_name)
36-
}
37-
}
38-
39-
#[doc(hidden)]
40-
impl $crate::value::SetValue for $name {
41-
unsafe fn set_value(value: &mut $crate::Value, this: &Self) {
42-
$crate::gobject_sys::g_value_set_boxed($crate::translate::ToGlibPtrMut::to_glib_none_mut(value).0, $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(this).0 as $crate::glib_sys::gpointer)
43-
}
44-
}
22+
glib_boxed_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name);
23+
glib_boxed_wrapper!(@memory_manager_impl $name, $ffi_name, @copy $copy_arg $copy_expr, @free $free_arg $free_expr,
24+
@init $init_arg $init_expr, @clear $clear_arg $clear_expr);
25+
glib_boxed_wrapper!(@value_impl $name, $ffi_name, @get_type $get_type_expr);
26+
};
4527

46-
#[doc(hidden)]
47-
impl $crate::value::SetValueOptional for $name {
48-
unsafe fn set_value_optional(value: &mut $crate::Value, this: Option<&Self>) {
49-
$crate::gobject_sys::g_value_set_boxed($crate::translate::ToGlibPtrMut::to_glib_none_mut(value).0, $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(&this).0 as $crate::glib_sys::gpointer)
50-
}
51-
}
28+
([$($attr:meta)*] $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr,
29+
@free $free_arg:ident $free_expr:expr, @init $init_arg:ident $init_expr:expr, @clear $clear_arg:ident $clear_expr:expr) => {
30+
glib_boxed_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name);
31+
glib_boxed_wrapper!(@memory_manager_impl $name, $ffi_name, @copy $copy_arg $copy_expr, @free $free_arg $free_expr,
32+
@init $init_arg $init_expr, @clear $clear_arg $clear_expr);
5233
};
5334

5435
([$($attr:meta)*] $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr,
5536
@free $free_arg:ident $free_expr:expr) => {
37+
glib_boxed_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name);
38+
glib_boxed_wrapper!(@memory_manager_impl $name, $ffi_name, @copy $copy_arg $copy_expr, @free $free_arg $free_expr);
39+
};
40+
41+
([$($attr:meta)*] $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr,
42+
@free $free_arg:ident $free_expr:expr, @get_type $get_type_expr:expr) => {
43+
glib_boxed_wrapper!(@generic_impl [$($attr)*] $name, $ffi_name);
44+
glib_boxed_wrapper!(@memory_manager_impl $name, $ffi_name, @copy $copy_arg $copy_expr, @free $free_arg $free_expr);
45+
glib_boxed_wrapper!(@value_impl $name, $ffi_name, @get_type $get_type_expr);
46+
};
47+
48+
(@generic_impl [$($attr:meta)*] $name:ident, $ffi_name:path) => {
5649
$(#[$attr])*
5750
#[derive(Clone)]
5851
pub struct $name($crate::boxed::Boxed<$ffi_name, MemoryManager>);
59-
60-
#[doc(hidden)]
61-
pub struct MemoryManager;
62-
63-
impl $crate::boxed::BoxedMemoryManager<$ffi_name> for MemoryManager {
64-
#[inline]
65-
unsafe fn copy($copy_arg: *const $ffi_name) -> *mut $ffi_name {
66-
$copy_expr
67-
}
68-
69-
#[inline]
70-
unsafe fn free($free_arg: *mut $ffi_name) {
71-
$free_expr
72-
}
73-
}
74-
75-
#[doc(hidden)]
76-
impl $crate::translate::Uninitialized for $name {
77-
#[inline]
78-
unsafe fn uninitialized() -> Self {
79-
$name($crate::boxed::Boxed::uninitialized())
80-
}
81-
}
82-
8352
#[doc(hidden)]
8453
impl $crate::translate::GlibPtrDefault for $name {
8554
type GlibType = *mut $ffi_name;
@@ -261,7 +230,100 @@ macro_rules! glib_boxed_wrapper {
261230
$crate::translate::FromGlibContainerAsVec::from_glib_full_num_as_vec(ptr, $crate::translate::c_ptr_array_len(ptr))
262231
}
263232
}
264-
}
233+
};
234+
235+
(@value_impl $name:ident, $ffi_name:path, @get_type $get_type_expr:expr) => {
236+
impl $crate::types::StaticType for $name {
237+
fn static_type() -> $crate::types::Type {
238+
#[allow(unused_unsafe)]
239+
unsafe { $crate::translate::from_glib($get_type_expr) }
240+
}
241+
}
242+
243+
#[doc(hidden)]
244+
impl<'a> $crate::value::FromValueOptional<'a> for $name {
245+
unsafe fn from_value_optional(value: &$crate::Value) -> Option<Self> {
246+
$crate::translate::from_glib_full($crate::gobject_sys::g_value_dup_boxed($crate::translate::ToGlibPtr::to_glib_none(value).0) as *mut $ffi_name)
247+
}
248+
}
249+
250+
#[doc(hidden)]
251+
impl $crate::value::SetValue for $name {
252+
unsafe fn set_value(value: &mut $crate::Value, this: &Self) {
253+
$crate::gobject_sys::g_value_set_boxed($crate::translate::ToGlibPtrMut::to_glib_none_mut(value).0, $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(this).0 as $crate::glib_sys::gpointer)
254+
}
255+
}
256+
257+
#[doc(hidden)]
258+
impl $crate::value::SetValueOptional for $name {
259+
unsafe fn set_value_optional(value: &mut $crate::Value, this: Option<&Self>) {
260+
$crate::gobject_sys::g_value_set_boxed($crate::translate::ToGlibPtrMut::to_glib_none_mut(value).0, $crate::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(&this).0 as $crate::glib_sys::gpointer)
261+
}
262+
}
263+
};
264+
265+
(@memory_manager_impl $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr, @free $free_arg:ident $free_expr:expr) => {
266+
#[doc(hidden)]
267+
pub struct MemoryManager;
268+
269+
impl $crate::boxed::BoxedMemoryManager<$ffi_name> for MemoryManager {
270+
#[inline]
271+
unsafe fn copy($copy_arg: *const $ffi_name) -> *mut $ffi_name {
272+
$copy_expr
273+
}
274+
275+
#[inline]
276+
unsafe fn free($free_arg: *mut $ffi_name) {
277+
$free_expr
278+
}
279+
280+
#[inline]
281+
unsafe fn init(_: *mut $ffi_name) {
282+
unimplemented!()
283+
}
284+
285+
#[inline]
286+
unsafe fn clear(_: *mut $ffi_name) {
287+
unimplemented!()
288+
}
289+
}
290+
};
291+
292+
(@memory_manager_impl $name:ident, $ffi_name:path, @copy $copy_arg:ident $copy_expr:expr, @free $free_arg:ident $free_expr:expr,
293+
@init $init_arg:ident $init_expr:expr, @clear $clear_arg:ident $clear_expr:expr) => {
294+
#[doc(hidden)]
295+
pub struct MemoryManager;
296+
297+
impl $crate::boxed::BoxedMemoryManager<$ffi_name> for MemoryManager {
298+
#[inline]
299+
unsafe fn copy($copy_arg: *const $ffi_name) -> *mut $ffi_name {
300+
$copy_expr
301+
}
302+
303+
#[inline]
304+
unsafe fn free($free_arg: *mut $ffi_name) {
305+
$free_expr
306+
}
307+
308+
#[inline]
309+
unsafe fn init($init_arg: *mut $ffi_name) {
310+
$init_expr
311+
}
312+
313+
#[inline]
314+
unsafe fn clear($clear_arg: *mut $ffi_name) {
315+
$clear_expr
316+
}
317+
}
318+
319+
#[doc(hidden)]
320+
impl $crate::translate::Uninitialized for $name {
321+
#[inline]
322+
unsafe fn uninitialized() -> Self {
323+
$name($crate::boxed::Boxed::uninitialized())
324+
}
325+
}
326+
};
265327
}
266328

267329
enum AnyBox<T> {
@@ -293,6 +355,10 @@ pub trait BoxedMemoryManager<T>: 'static {
293355
unsafe fn copy(ptr: *const T) -> *mut T;
294356
/// Frees the object.
295357
unsafe fn free(ptr: *mut T);
358+
/// Initializes an already allocated object.
359+
unsafe fn init(ptr: *mut T);
360+
/// Clears and frees all memory of the object, but not the object itself.
361+
unsafe fn clear(ptr: *mut T);
296362
}
297363

298364
/// Encapsulates memory management logic for boxed types.
@@ -301,21 +367,16 @@ pub struct Boxed<T: 'static, MM: BoxedMemoryManager<T>> {
301367
_dummy: PhantomData<MM>,
302368
}
303369

304-
impl<T: 'static, MM: BoxedMemoryManager<T>> Boxed<T, MM> {
305-
#[inline]
306-
pub unsafe fn uninitialized() -> Self {
307-
Boxed {
308-
inner: AnyBox::Native(Box::new(mem::uninitialized())),
309-
_dummy: PhantomData,
310-
}
311-
}
312-
}
313-
314370
impl<T: 'static, MM: BoxedMemoryManager<T>> Uninitialized for Boxed<T, MM> {
315371
#[inline]
316372
unsafe fn uninitialized() -> Self {
317373
Boxed {
318-
inner: AnyBox::Native(Box::new(mem::uninitialized())),
374+
inner: {
375+
let mut inner = Box::<T>::new(mem::zeroed());
376+
MM::init(&mut *inner);
377+
378+
AnyBox::Native(inner)
379+
},
319380
_dummy: PhantomData,
320381
}
321382
}
@@ -403,8 +464,14 @@ impl<T: 'static, MM: BoxedMemoryManager<T>> Drop for Boxed<T, MM> {
403464
#[inline]
404465
fn drop(&mut self) {
405466
unsafe {
406-
if let AnyBox::ForeignOwned(ptr) = self.inner {
407-
MM::free(ptr.as_ptr());
467+
match self.inner {
468+
AnyBox::ForeignOwned(ptr) => {
469+
MM::free(ptr.as_ptr());
470+
}
471+
AnyBox::Native(ref mut box_) => {
472+
MM::clear(&mut **box_);
473+
}
474+
_ => (),
408475
}
409476
}
410477
}

src/wrapper.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,38 @@ macro_rules! glib_wrapper {
265265
@free $free_arg $free_expr, @get_type $get_type_expr);
266266
};
267267

268+
(
269+
$(#[$attr:meta])*
270+
pub struct $name:ident(Boxed<$ffi_name:path>);
271+
272+
match fn {
273+
copy => |$copy_arg:ident| $copy_expr:expr,
274+
free => |$free_arg:ident| $free_expr:expr,
275+
init => |$init_arg:ident| $init_expr:expr,
276+
clear => |$clear_arg:ident| $clear_expr:expr,
277+
}
278+
) => {
279+
glib_boxed_wrapper!([$($attr)*] $name, $ffi_name, @copy $copy_arg $copy_expr,
280+
@free $free_arg $free_expr, @init $init_arg $init_expr, @clear $clear_arg $clear_expr);
281+
};
282+
283+
(
284+
$(#[$attr:meta])*
285+
pub struct $name:ident(Boxed<$ffi_name:path>);
286+
287+
match fn {
288+
copy => |$copy_arg:ident| $copy_expr:expr,
289+
free => |$free_arg:ident| $free_expr:expr,
290+
init => |$init_arg:ident| $init_expr:expr,
291+
clear => |$clear_arg:ident| $clear_expr:expr,
292+
get_type => || $get_type_expr:expr,
293+
}
294+
) => {
295+
glib_boxed_wrapper!([$($attr)*] $name, $ffi_name, @copy $copy_arg $copy_expr,
296+
@free $free_arg $free_expr, @init $init_arg $init_expr, @clear $clear_arg $clear_expr,
297+
@get_type $get_type_expr);
298+
};
299+
268300
// Shared
269301

270302
(

0 commit comments

Comments
 (0)