Skip to content

Commit 84b3f20

Browse files
committed
Merge branch 'cleanup-redis-allocator-usage'
2 parents 1428bea + b736250 commit 84b3f20

File tree

8 files changed

+40
-42
lines changed

8 files changed

+40
-42
lines changed

.circleci/config.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,4 @@ jobs:
5656

5757
- run:
5858
name: Run all tests
59-
command: cargo test --features experimental-api --all
59+
command: cargo test --features test,experimental-api --all-targets

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,7 @@ cc = "1.0"
3636
default = []
3737
experimental-api = []
3838

39+
# Workaround to allow cfg(feature = "test") in dependencies:
40+
# https://github.com/rust-lang/rust/issues/59168#issuecomment-472653680
41+
# This requires running the tests with `--features test`
42+
test = []

build.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env sh
2+
cargo build --features experimental-api --all --all-targets
3+

src/alloc.rs

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,17 @@
1-
use std::alloc::{GlobalAlloc, Layout, System};
1+
use std::alloc::{GlobalAlloc, Layout};
22
use std::os::raw::c_void;
3-
use std::sync::atomic::{AtomicBool, Ordering::SeqCst};
43

54
use crate::raw;
65

76
pub struct RedisAlloc;
87

9-
static USE_REDIS_ALLOC: AtomicBool = AtomicBool::new(false);
10-
118
unsafe impl GlobalAlloc for RedisAlloc {
129
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
13-
let use_redis = USE_REDIS_ALLOC.load(SeqCst);
14-
if use_redis {
15-
// complete the requested size to be aligned with the requested layout.align()
16-
let size = (layout.size() + layout.align() - 1) & (!(layout.align() - 1));
17-
return raw::RedisModule_Alloc.unwrap()(size) as *mut u8;
18-
}
19-
System.alloc(layout)
10+
let size = (layout.size() + layout.align() - 1) & (!(layout.align() - 1));
11+
return raw::RedisModule_Alloc.unwrap()(size) as *mut u8;
2012
}
2113

22-
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
23-
let use_redis = USE_REDIS_ALLOC.load(SeqCst);
24-
if use_redis {
25-
return raw::RedisModule_Free.unwrap()(ptr as *mut c_void);
26-
}
27-
System.dealloc(ptr, layout);
14+
unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
15+
return raw::RedisModule_Free.unwrap()(ptr as *mut c_void);
2816
}
2917
}
30-
31-
pub fn use_redis_alloc() {
32-
USE_REDIS_ALLOC.store(true, SeqCst);
33-
eprintln!("Now using Redis allocator");
34-
}

src/context.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ impl Context {
5757
}
5858

5959
pub fn is_keys_position_request(&self) -> bool {
60-
// HACK: Used for tests, where the context is null
61-
if self.ctx.is_null() {
60+
// We want this to be available in tests where we don't have an actual Redis to call
61+
if cfg!(feature = "test") {
6262
return false;
6363
}
6464

src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ mod key;
2828
pub use crate::context::Context;
2929
pub use crate::redismodule::*;
3030

31+
/// Ideally this would be `#[cfg(not(test))]`, but that doesn't work:
32+
/// https://github.com/rust-lang/rust/issues/59168#issuecomment-472653680
33+
/// The workaround is to use the `test` feature instead.
34+
#[cfg(not(feature = "test"))]
3135
#[global_allocator]
3236
static ALLOC: crate::alloc::RedisAlloc = crate::alloc::RedisAlloc;
3337

src/macros.rs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ macro_rules! redis_module {
7373
]),* $(,)*
7474
] $(,)*
7575
) => {
76-
use std::os::raw::c_int;
76+
use std::os::raw::{c_int, c_char};
7777
use std::ffi::CString;
7878
use std::slice;
7979

@@ -87,25 +87,27 @@ macro_rules! redis_module {
8787
_argv: *mut *mut raw::RedisModuleString,
8888
_argc: c_int,
8989
) -> c_int {
90-
{
91-
// We use an explicit block here to make sure all memory allocated before we
92-
// switch to the Redis allocator will be out of scope and thus deallocated.
93-
let module_name = CString::new($module_name).unwrap();
94-
let module_version = $module_version as c_int;
9590

96-
if unsafe { raw::Export_RedisModule_Init(
97-
ctx,
98-
module_name.as_ptr(),
99-
module_version,
100-
raw::REDISMODULE_APIVER_1 as c_int,
101-
) } == raw::Status::Err as c_int { return raw::Status::Err as c_int; }
91+
// We use a statically sized buffer to avoid allocating.
92+
// This is needed since we use a custom allocator that relies on the Redis allocator,
93+
// which isn't yet ready at this point.
94+
let mut name_buffer = [0; 64];
95+
unsafe {
96+
std::ptr::copy(
97+
$module_name.as_ptr(),
98+
name_buffer.as_mut_ptr(),
99+
$module_name.len(),
100+
);
102101
}
103102

104-
if true {
105-
redis_module::alloc::use_redis_alloc();
106-
} else {
107-
eprintln!("*** NOT USING Redis allocator ***");
108-
}
103+
let module_version = $module_version as c_int;
104+
105+
if unsafe { raw::Export_RedisModule_Init(
106+
ctx,
107+
name_buffer.as_ptr() as *const c_char,
108+
module_version,
109+
raw::REDISMODULE_APIVER_1 as c_int,
110+
) } == raw::Status::Err as c_int { return raw::Status::Err as c_int; }
109111

110112
$(
111113
if $init_func(ctx) == raw::Status::Err as c_int {

test.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#!/usr/bin/env sh
2+
cargo test --all-targets --features test,experimental-api

0 commit comments

Comments
 (0)