Skip to content

Instantly share code, notes, and snippets.

@matthewjberger
Last active August 12, 2024 19:32
Show Gist options
  • Save matthewjberger/2c95d97a6984de1f9452ccef2a4bf0a4 to your computer and use it in GitHub Desktop.
Save matthewjberger/2c95d97a6984de1f9452ccef2a4bf0a4 to your computer and use it in GitHub Desktop.
Alternatives to drain to preventable multiple mutable refs to self
use std::collections::VecDeque;
#[derive(Debug, Clone)]
struct Event(u32);
struct Context {
queued_events: VecDeque<Event>,
}
impl Context {
fn new() -> Self {
let mut queued_events = VecDeque::new();
queued_events.push_back(Event(1));
queued_events.push_back(Event(2));
queued_events.push_back(Event(3));
Context { queued_events }
}
fn process_event(&mut self, event: &Event) {
println!(" Processing event: Event({})", event.0);
self.some_other_method();
}
fn some_other_method(&mut self) {
println!(" Called some_other_method");
}
fn process_events_drain(&mut self) {
println!("1. Using drain() - This will not compile:");
// Uncommenting the next line will cause a compilation error
// self.queued_events.drain(..).for_each(|event| self.process_event(&event));
// Error: cannot borrow `self` as mutable more than once at a time
println!(" (Compilation error if uncommented)");
}
fn process_events_clone(&mut self) {
println!("\n2. Using clone (works but maybe inefficient):");
let events = self.queued_events.clone();
for event in &events {
self.process_event(event);
}
self.queued_events.clear();
println!(" Queue size: {}", self.queued_events.len());
}
fn process_events_pop_front(&mut self) {
println!("\n3. Using while let with pop_front():");
while let Some(event) = self.queued_events.pop_front() {
self.process_event(&event);
}
println!(" Queue size: {}", self.queued_events.len());
}
fn process_events_take(&mut self) {
println!("\n4. Using std::mem::take():");
let events = std::mem::take(&mut self.queued_events);
for event in &events {
self.process_event(event);
}
println!(" Queue size: {}", self.queued_events.len());
}
fn process_events_replace(&mut self) {
println!("\n5. Using std::mem::replace() with new():");
let events = std::mem::replace(&mut self.queued_events, VecDeque::new());
for event in &events {
self.process_event(event);
}
println!(
" Queue size after processing: {}",
self.queued_events.len()
);
}
}
fn main() {
let mut context = Context::new();
context.process_events_drain();
context = Context::new();
context.process_events_clone();
context = Context::new();
context.process_events_pop_front();
context = Context::new();
context.process_events_take();
context = Context::new();
context.process_events_replace();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment