rust
40 lines · 7 steps
A round-robin worker pool in Rust
Spawns a fixed set of worker threads, each with its own channel, and spreads tasks across them with an atomic counter.
Explained by
highlit
1use std::sync::atomic::{AtomicUsize, Ordering};
2use std::sync::Arc;
3use std::thread;
4
5pub struct RoundRobin<T> {
6 workers: Vec<crossbeam_channel::Sender<T>>,
7 next: AtomicUsize,
8}
9
10impl<T: Send + 'static> RoundRobin<T> {
11 pub fn new<F>(count: usize, handler: F) -> Arc<Self>
12 where
13 F: Fn(usize, T) + Send + Sync + Clone + 'static,
14 {
15 let mut workers = Vec::with_capacity(count);
16
17 for id in 0..count {
18 let (tx, rx) = crossbeam_channel::unbounded::<T>();
19 let handler = handler.clone();
20 thread::spawn(move || {
21 for task in rx {
22 handler(id, task);
23 }
24 });
25 workers.push(tx);
26 }
27
28 Arc::new(Self {
29 workers,
30 next: AtomicUsize::new(0),
31 })
32 }
33
34 pub fn dispatch(&self, task: T) {
35 let idx = self.next.fetch_add(1, Ordering::Relaxed) % self.workers.len();
36 if self.workers[idx].send(task).is_err() {
37 eprintln!("worker {idx} channel closed, dropping task");
38 }
39 }
40}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Giving each worker its own channel avoids contention on a single shared queue.
- 2An atomic counter with modulo arithmetic distributes work evenly without a lock.
- 3Handling a closed channel on send keeps the dispatcher from panicking when a worker dies.
Related explainers
ruby
class Debouncer def initialize(delay:) @delay = delay @mutex = Mutex.new
A thread-safe debouncer in Ruby
concurrency
debouncing
mutex
Advanced
5 steps
ruby
require "net/http" require "json" class UrlFetcher
A thread-pool URL fetcher in Ruby
concurrency
thread-pool
queues
Intermediate
8 steps
ruby
class SyncContactsJob < ApplicationJob queue_as :external_api MAX_CONCURRENCY = 5
Rate-limited CRM sync in a Rails job
background-jobs
rate-limiting
redis
Advanced
9 steps
rust
use std::fs::File; use std::io::{self, Read}; use std::path::Path;
Streaming a SHA-256 hash of a file in Rust
hashing
buffered-io
streaming
Intermediate
5 steps
python
import threading from functools import wraps
A thread-safe debounce decorator in Python
decorators
debounce
threading
Advanced
6 steps
rust
use axum::{ extract::State, http::StatusCode, Json,
Idempotent webhook handling in Axum
deduplication
idempotency
shared-state
Intermediate
8 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/a-round-robin-worker-pool-in-rust-explained-rust-1f8b/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.