Skip to content

Commit 21f1511

Browse files
committed
Add support for custom allocator
1 parent a2e05da commit 21f1511

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

libgit2-sys/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,13 @@ pub struct git_writestream {
925925
pub free: Option<extern "C" fn(*mut git_writestream)>,
926926
}
927927

928+
#[repr(C)]
929+
pub struct git_allocator {
930+
pub gmalloc: *const extern "C" fn(size_t, *const c_char, c_int) -> *mut c_void,
931+
pub grealloc: *const extern "C" fn(*mut c_void, size_t, *const c_char, c_int) -> *mut c_void,
932+
pub gfree: *const extern "C" fn(*mut c_void),
933+
}
934+
928935
git_enum! {
929936
pub enum git_attr_value_t {
930937
GIT_ATTR_VALUE_UNSPECIFIED = 0,

src/opts.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,29 @@ where
3333
Ok(())
3434
}
3535

36+
/// Set the memory allocator to a different memory allocator.
37+
///
38+
/// This allocator will then be used to make all memory allocations for
39+
/// libgit2 operations. If the given `allocator` is None, then the
40+
/// system default will be restored.
41+
pub unsafe fn set_allocator(
42+
gmalloc: *const extern "C" fn(libc::size_t, *const core::ffi::c_char, core::ffi::c_int) -> *mut core::ffi::c_void,
43+
grealloc: *const extern "C" fn(*mut core::ffi::c_void, libc::size_t, *const core::ffi::c_char, core::ffi::c_int) -> *mut core::ffi::c_void,
44+
gfree: *const extern "C" fn(*mut core::ffi::c_void),
45+
) -> Result<(), Error> {
46+
crate::init();
47+
let allocator = raw::git_allocator{
48+
gmalloc: gmalloc,
49+
gfree: gfree,
50+
grealloc: grealloc,
51+
};
52+
try_call!(raw::git_libgit2_opts(
53+
raw::GIT_OPT_SET_ALLOCATOR as libc::c_int,
54+
&allocator as *const raw::git_allocator
55+
));
56+
Ok(())
57+
}
58+
3659
/// Reset the search path for a given level of config data to the default
3760
/// (generally based on environment variables).
3861
///
@@ -416,6 +439,8 @@ pub unsafe fn set_server_timeout_in_milliseconds(timeout: libc::c_int) -> Result
416439

417440
#[cfg(test)]
418441
mod test {
442+
use crate::test::repo_init;
443+
419444
use super::*;
420445

421446
#[test]
@@ -447,6 +472,40 @@ mod test {
447472
}
448473
}
449474

475+
static mut ALLOC_CALLED: bool = false;
476+
static mut FREE_CALLED: bool = false;
477+
478+
#[test]
479+
fn custom_allocator() {
480+
unsafe {
481+
extern "C" fn gmalloc(size: libc::size_t, _: *const core::ffi::c_char, _: core::ffi::c_int) -> *mut core::ffi::c_void {
482+
unsafe {
483+
ALLOC_CALLED = true;
484+
libc::malloc(size)
485+
}
486+
}
487+
extern "C" fn grealloc(ptr: *mut core::ffi::c_void, size: libc::size_t, _: *const core::ffi::c_char, _: core::ffi::c_int) -> *mut core::ffi::c_void {
488+
unsafe {
489+
ALLOC_CALLED = true;
490+
libc::realloc(ptr, size)
491+
}
492+
}
493+
extern "C" fn gfree(ptr: *mut core::ffi::c_void) {
494+
unsafe {
495+
FREE_CALLED = true;
496+
libc::free(ptr)
497+
}
498+
}
499+
assert!(set_allocator(
500+
gmalloc as *const extern "C" fn(libc::size_t, *const core::ffi::c_char, core::ffi::c_int) -> *mut core::ffi::c_void,
501+
grealloc as *const extern "C" fn(*mut core::ffi::c_void, libc::size_t, *const core::ffi::c_char, core::ffi::c_int) -> *mut core::ffi::c_void,
502+
gfree as *const extern "C" fn(*mut core::ffi::c_void),
503+
).is_ok());
504+
repo_init();
505+
assert!(ALLOC_CALLED);
506+
assert!(FREE_CALLED);}
507+
}
508+
450509
#[test]
451510
fn server_connect_timeout() {
452511
unsafe {

0 commit comments

Comments
 (0)