multithreadingrustr2d2

Why is the Connection pool cloned here?


In this code example, from the Github page of r2d2:

fn main() {
    let manager = r2d2_foodb::FooConnectionManager::new("localhost:1234");
    let pool = r2d2::Pool::builder()
        .max_size(15)
        .build(manager)
        .unwrap();

    for _ in 0..20 {
        let pool = pool.clone();
        thread::spawn(move || {
            let conn = pool.get().unwrap();
        })
    }
}

Why is the Pool struct being cloned in the loop?


Solution

  • This is because the threads spawned inside the loop need to take ownership of pool, as each thread could run for longer than main. Referencing pool owned by main from inside a thread could lead to referencing a value that has already been destroyed if main exits while the threads are still running.

    Taking ownership of pool requires you to clone it each time the loop executes, so each thread has its own copy.

    Internally, a Pool is an std::sync::Arc and the Clone implementation simply clones the Arc. That is, each clone of Pool is just an incremented reference count. As the threads are created, the reference count is increased. When the threads finish, they decrement the reference count by dropping their Pool, destroying the underlying connection when the reference count reaches zero.