Idiomatic Way to Implement Buffer Pool
⚓ Rust 📅 2025-10-06 👤 surdeus 👁️ 6Hi, I'm implementing a buffer pool manager. A long time ago I did this in C and now that I am trying it in Rust I am hitting some snags. Note that I'm just working on a single-threaded version for now and will tackle thread safety later.
- A buffer pool manager usually allocates a large contiguous buffer of memory upon startup and re-uses that buffer. How do I allocate a contiguous block of memory in Rust? I would assume Vec<Vec<u8>>won't be contiguous because the size of the inner vec can't be known at the time of memory allocation. So I think it must be a slice
type Pool<const NUM_FRAMES: usize, const PAGE_SIZE: usize> = [[u8; PAGE_SIZE]; NUM_FRAMES];
Is this idiomatic? It feels annoying carrying these consts around everywhere.
- I believe callers of this API should be borrowing not owning the page so it can be re-used.
pub fn get_page(&'static mut self,  page_id: u64) -> PageRef<NUM_FRAMES, PAGE_SIZE>  {
...
struct PageRef<const NUM_FRAMES: usize, const PAGE_SIZE: usize> {
    pool: &'static mut BufferPool<NUM_FRAMES, PAGE_SIZE>,
    page: &'static [u8],
    page_id: u64,
}
This starts to introduce a lot of lifetimes. I think the BufferPool and all of its pages should be static because they will exist for as long as the process is running but in PageRef I'm determining the lifetime of the borrows of those values, not the values themselves. So what should they be? And if the borrows of pool and page are static, what happens when PageRef is dropped?
- The buffer pool has some metadata it updates upon a caller finishing with a page. It seems most idiomatic to implement this in the dropfunction
impl<'a, const NUM_FRAMES: usize, const PAGE_SIZE: usize> Drop for PageRef<'a, NUM_FRAMES, PAGE_SIZE> {
    fn drop(&mut self) {
        let metadata = self.pool.page_table.get_mut(&self.page_id).expect("page_id not in pool");
        metadata.pins -= 1;
        
        if metadata.pins == 0 {
            self.pool.free_frames.push_back(metadata.frame_index);
            self.pool.page_table.remove(&self.page_id);
        }
    }
}
so I have to return a mutable reference in PageRef but now I have a immutable borrow and a mutable borrow. Is it even possible to return a mutable reference to self? I'm a bit stuck
error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
  --> src/main.rs:40:80
   |
40 |         return PageRef{ page: &self.pool[metadata.frame_index], page_id, pool: self }; 
   |                               --------------------------------                 ^^^^ mutable borrow occurs here
   |                               |
   |                               immutable borrow occurs here
   |                               this usage requires that `self.pool[_]` is borrowed for `'static`
Any help would be appreciated. Thank you
3 posts - 3 participants
🏷️ Rust_feed