Skip to content

Commit 9e7db4b

Browse files
Merge pull request #877 from sdroege/collections-list-copy-types
glib: Minor optimization for `List`/`SList` with `Copy` types
2 parents 21c5579 + 3db22a7 commit 9e7db4b

File tree

2 files changed

+66
-45
lines changed

2 files changed

+66
-45
lines changed

glib/src/collections/list.rs

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,22 @@ impl<T: TransparentPtrType> List<T> {
2323
#[inline]
2424
pub unsafe fn from_glib_none(list: *const ffi::GList) -> List<T> {
2525
// Need to copy the whole list
26-
unsafe extern "C" fn copy_item<T: TransparentPtrType>(
27-
ptr: ffi::gconstpointer,
28-
_user_data: ffi::gpointer,
29-
) -> ffi::gpointer {
30-
let mut item =
31-
mem::ManuallyDrop::new((*(&ptr as *const ffi::gconstpointer as *const T)).clone());
32-
33-
*(&mut *item as *mut T as *mut *mut T::GlibType) as ffi::gpointer
34-
}
26+
let list = if mem::needs_drop::<T>() {
27+
unsafe extern "C" fn copy_item<T: TransparentPtrType>(
28+
ptr: ffi::gconstpointer,
29+
_user_data: ffi::gpointer,
30+
) -> ffi::gpointer {
31+
let mut item = mem::ManuallyDrop::new(
32+
(*(&ptr as *const ffi::gconstpointer as *const T)).clone(),
33+
);
34+
35+
*(&mut *item as *mut T as *mut *mut T::GlibType) as ffi::gpointer
36+
}
3537

36-
let list = ffi::g_list_copy_deep(mut_override(list), Some(copy_item::<T>), ptr::null_mut());
38+
ffi::g_list_copy_deep(mut_override(list), Some(copy_item::<T>), ptr::null_mut())
39+
} else {
40+
ffi::g_list_copy(mut_override(list))
41+
};
3742

3843
List {
3944
ptr: ptr::NonNull::new(list),
@@ -46,15 +51,17 @@ impl<T: TransparentPtrType> List<T> {
4651
#[inline]
4752
pub unsafe fn from_glib_container(list: *mut ffi::GList) -> List<T> {
4853
// Need to copy all items as we only own the container
49-
unsafe extern "C" fn copy_item<T: TransparentPtrType>(
50-
ptr: ffi::gpointer,
51-
_user_data: ffi::gpointer,
52-
) {
53-
let item = (*(&ptr as *const ffi::gpointer as *const T)).clone();
54-
ptr::write(ptr as *mut T, item);
55-
}
54+
if mem::needs_drop::<T>() {
55+
unsafe extern "C" fn copy_item<T: TransparentPtrType>(
56+
ptr: ffi::gpointer,
57+
_user_data: ffi::gpointer,
58+
) {
59+
let item = (*(&ptr as *const ffi::gpointer as *const T)).clone();
60+
ptr::write(ptr as *mut T, item);
61+
}
5662

57-
ffi::g_list_foreach(list, Some(copy_item::<T>), ptr::null_mut());
63+
ffi::g_list_foreach(list, Some(copy_item::<T>), ptr::null_mut());
64+
}
5865

5966
List {
6067
ptr: ptr::NonNull::new(list),
@@ -392,11 +399,15 @@ impl<T: TransparentPtrType> Drop for List<T> {
392399
fn drop(&mut self) {
393400
if let Some(ptr) = self.ptr {
394401
unsafe {
395-
unsafe extern "C" fn drop_item<T: TransparentPtrType>(mut ptr: ffi::gpointer) {
396-
ptr::drop_in_place(&mut ptr as *mut ffi::gpointer as *mut T);
397-
}
402+
if mem::needs_drop::<T>() {
403+
unsafe extern "C" fn drop_item<T: TransparentPtrType>(mut ptr: ffi::gpointer) {
404+
ptr::drop_in_place(&mut ptr as *mut ffi::gpointer as *mut T);
405+
}
398406

399-
ffi::g_list_free_full(ptr.as_ptr(), Some(drop_item::<T>));
407+
ffi::g_list_free_full(ptr.as_ptr(), Some(drop_item::<T>));
408+
} else {
409+
ffi::g_list_free(ptr.as_ptr());
410+
}
400411
}
401412
}
402413
}

glib/src/collections/slist.rs

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,22 @@ impl<T: TransparentPtrType> SList<T> {
2323
#[inline]
2424
pub unsafe fn from_glib_none(list: *const ffi::GSList) -> SList<T> {
2525
// Need to copy the whole list
26-
unsafe extern "C" fn copy_item<T: TransparentPtrType>(
27-
ptr: ffi::gconstpointer,
28-
_user_data: ffi::gpointer,
29-
) -> ffi::gpointer {
30-
let mut item =
31-
mem::ManuallyDrop::new((*(&ptr as *const ffi::gconstpointer as *const T)).clone());
32-
33-
*(&mut *item as *mut T as *mut *mut T::GlibType) as ffi::gpointer
34-
}
26+
let list = if mem::needs_drop::<T>() {
27+
unsafe extern "C" fn copy_item<T: TransparentPtrType>(
28+
ptr: ffi::gconstpointer,
29+
_user_data: ffi::gpointer,
30+
) -> ffi::gpointer {
31+
let mut item = mem::ManuallyDrop::new(
32+
(*(&ptr as *const ffi::gconstpointer as *const T)).clone(),
33+
);
34+
35+
*(&mut *item as *mut T as *mut *mut T::GlibType) as ffi::gpointer
36+
}
3537

36-
let list =
37-
ffi::g_slist_copy_deep(mut_override(list), Some(copy_item::<T>), ptr::null_mut());
38+
ffi::g_slist_copy_deep(mut_override(list), Some(copy_item::<T>), ptr::null_mut())
39+
} else {
40+
ffi::g_slist_copy(mut_override(list))
41+
};
3842

3943
SList {
4044
ptr: ptr::NonNull::new(list),
@@ -47,15 +51,17 @@ impl<T: TransparentPtrType> SList<T> {
4751
#[inline]
4852
pub unsafe fn from_glib_container(list: *mut ffi::GSList) -> SList<T> {
4953
// Need to copy all items as we only own the container
50-
unsafe extern "C" fn copy_item<T: TransparentPtrType>(
51-
ptr: ffi::gpointer,
52-
_user_data: ffi::gpointer,
53-
) {
54-
let item = (*(&ptr as *const ffi::gpointer as *const T)).clone();
55-
ptr::write(ptr as *mut T, item);
56-
}
54+
if mem::needs_drop::<T>() {
55+
unsafe extern "C" fn copy_item<T: TransparentPtrType>(
56+
ptr: ffi::gpointer,
57+
_user_data: ffi::gpointer,
58+
) {
59+
let item = (*(&ptr as *const ffi::gpointer as *const T)).clone();
60+
ptr::write(ptr as *mut T, item);
61+
}
5762

58-
ffi::g_slist_foreach(list, Some(copy_item::<T>), ptr::null_mut());
63+
ffi::g_slist_foreach(list, Some(copy_item::<T>), ptr::null_mut());
64+
}
5965

6066
SList {
6167
ptr: ptr::NonNull::new(list),
@@ -388,11 +394,15 @@ impl<T: TransparentPtrType> Drop for SList<T> {
388394
fn drop(&mut self) {
389395
if let Some(ptr) = self.ptr {
390396
unsafe {
391-
unsafe extern "C" fn drop_item<T: TransparentPtrType>(mut ptr: ffi::gpointer) {
392-
ptr::drop_in_place(&mut ptr as *mut ffi::gpointer as *mut T);
393-
}
397+
if mem::needs_drop::<T>() {
398+
unsafe extern "C" fn drop_item<T: TransparentPtrType>(mut ptr: ffi::gpointer) {
399+
ptr::drop_in_place(&mut ptr as *mut ffi::gpointer as *mut T);
400+
}
394401

395-
ffi::g_slist_free_full(ptr.as_ptr(), Some(drop_item::<T>));
402+
ffi::g_slist_free_full(ptr.as_ptr(), Some(drop_item::<T>));
403+
} else {
404+
ffi::g_slist_free(ptr.as_ptr());
405+
}
396406
}
397407
}
398408
}

0 commit comments

Comments
 (0)