Skip to content

Commit 8257850

Browse files
committed
Add blanket impl Allocator for &mut A where A: Allocator
1 parent fb230d4 commit 8257850

File tree

2 files changed

+30
-16
lines changed

2 files changed

+30
-16
lines changed

benchmark/benchmark.rs

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,8 @@ fn pass_by_object<S, T>(testcase: T, mut reuse: S, iters: u64) -> ::capnp::Resul
148148
let mut rng = common::FastRand::new();
149149
let (mut allocator_req, mut allocator_res) = reuse.get_allocators();
150150
for _ in 0..iters {
151-
let mut message_req = message::Builder::new(allocator_req);
152-
let mut message_res = message::Builder::new(allocator_res);
151+
let mut message_req = message::Builder::new(&mut allocator_req);
152+
let mut message_res = message::Builder::new(&mut allocator_res);
153153

154154
let expected = testcase.setup_request(
155155
&mut rng,
@@ -162,9 +162,6 @@ fn pass_by_object<S, T>(testcase: T, mut reuse: S, iters: u64) -> ::capnp::Resul
162162
testcase.check_response(
163163
message_res.get_root_as_reader()?,
164164
expected)?;
165-
166-
allocator_req = message_req.into_allocator();
167-
allocator_res = message_res.into_allocator();
168165
}
169166
Ok(())
170167
}
@@ -177,8 +174,8 @@ fn pass_by_bytes<C, S, T>(testcase: T, mut reuse: S, compression: C, iters: u64)
177174
let mut rng = common::FastRand::new();
178175
let (mut allocator_req, mut allocator_res) = reuse.get_allocators();
179176
for _ in 0..iters {
180-
let mut message_req = message::Builder::new(allocator_req);
181-
let mut message_res = message::Builder::new(allocator_res);
177+
let mut message_req = message::Builder::new(&mut allocator_req);
178+
let mut message_res = message::Builder::new(&mut allocator_res);
182179

183180
let expected = {
184181
let request = message_req.init_root();
@@ -214,8 +211,6 @@ fn pass_by_bytes<C, S, T>(testcase: T, mut reuse: S, compression: C, iters: u64)
214211

215212
let response_reader = message_reader.get_root()?;
216213
testcase.check_response(response_reader, expected)?;
217-
allocator_req = message_req.into_allocator();
218-
allocator_res = message_res.into_allocator();
219214
}
220215
Ok(())
221216
}
@@ -229,7 +224,7 @@ fn server<C, S, T, R, W>(testcase: T, mut reuse: S, compression: C, iters: u64,
229224
let (mut allocator_res, _) = reuse.get_allocators();
230225
for _ in 0..iters {
231226
use std::io::Write;
232-
let mut message_res = message::Builder::new(allocator_res);
227+
let mut message_res = message::Builder::new(&mut allocator_res);
233228

234229
{
235230
let response = message_res.init_root();
@@ -242,7 +237,6 @@ fn server<C, S, T, R, W>(testcase: T, mut reuse: S, compression: C, iters: u64,
242237

243238
compression.write_message(&mut out_buffered, &mut message_res)?;
244239
out_buffered.flush()?;
245-
allocator_res = message_res.into_allocator();
246240
}
247241
Ok(())
248242
}
@@ -259,7 +253,7 @@ fn sync_client<C, S, T>(testcase: T, mut reuse: S, compression: C, iters: u64)
259253
let (mut allocator_req, _) = reuse.get_allocators();
260254
for _ in 0..iters {
261255
use std::io::Write;
262-
let mut message_req = message::Builder::new(allocator_req);
256+
let mut message_req = message::Builder::new(&mut allocator_req);
263257

264258
let expected = {
265259
let request = message_req.init_root();
@@ -273,7 +267,6 @@ fn sync_client<C, S, T>(testcase: T, mut reuse: S, compression: C, iters: u64)
273267
Default::default())?;
274268
let response_reader = message_reader.get_root()?;
275269
testcase.check_response(response_reader, expected)?;
276-
allocator_req = message_req.into_allocator();
277270
}
278271
Ok(())
279272
}

capnp/src/message.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ pub unsafe trait Allocator {
287287
fn allocate_segment(&mut self, minimum_size: u32) -> (*mut u8, u32);
288288

289289
/// Indicates that a segment, previously allocated via allocate_segment(), is no longer in use.
290+
/// `word_size` is the length of the segment in words, as returned from `allocate_segment()`.
290291
fn deallocate_segment(&mut self, ptr: *mut u8, word_size: u32, words_used: u32);
291292
}
292293

@@ -469,6 +470,15 @@ impl Builder<HeapAllocator> {
469470
}
470471

471472
/// An Allocator whose first segment is a backed by a user-provided buffer.
473+
///
474+
/// Recall that an `Allocator` implementation must ensure that allocated segments are
475+
/// initially *zeroed*. `ScratchSpaceHeapAllocator` ensures that is the case by zeroing
476+
/// the entire buffer upon initial construction, and then zeroing any *potentially used*
477+
/// part of the buffer upon `deallocate_segment()`.
478+
///
479+
/// You can reuse a `ScratchSpaceHeapAllocator` by calling `message::Builder::into_allocator()`,
480+
/// or by initally passing it to `message::Builder::new()` as a `&mut ScratchSpaceHeapAllocator`.
481+
/// Such reuse can save significant amounts of zeroing.
472482
pub struct ScratchSpaceHeapAllocator<'a> {
473483
scratch_space: &'a mut [u8],
474484
scratch_space_allocated: bool,
@@ -478,9 +488,9 @@ pub struct ScratchSpaceHeapAllocator<'a> {
478488
impl <'a> ScratchSpaceHeapAllocator<'a> {
479489
/// Writes zeroes into the entire buffer and constructs a new allocator from it.
480490
///
481-
/// If you want to reuse the same buffer and to minimize the cost of zeroing for each message,
482-
/// you can call `message::Builder::into_allocator()` to recover the allocator from
483-
/// the previous message and then pass it into the new message.
491+
/// If the buffer is large, this operation could be relatively expensive. If you want to reuse
492+
/// the same scratch space in a later message, you should reuse the entire
493+
/// `ScratchSpaceHeapAllocator`, to avoid paying this full cost again.
484494
pub fn new(scratch_space: &'a mut [u8]) -> ScratchSpaceHeapAllocator<'a> {
485495
#[cfg(not(feature = "unaligned"))]
486496
{
@@ -535,3 +545,14 @@ unsafe impl <'a> Allocator for ScratchSpaceHeapAllocator<'a> {
535545
}
536546
}
537547
}
548+
549+
unsafe impl <'a, A> Allocator for &'a mut A where A: Allocator {
550+
fn allocate_segment(&mut self, minimum_size: u32) -> (*mut u8, u32) {
551+
(*self).allocate_segment(minimum_size)
552+
}
553+
554+
fn deallocate_segment(&mut self, ptr: *mut u8, word_size: u32, words_used: u32) {
555+
(*self).deallocate_segment(ptr, word_size, words_used)
556+
}
557+
}
558+

0 commit comments

Comments
 (0)