1

I'm trying to understand how to pass an Arc<Mutex<T>> to another function. Here is my code, I removed part of it for clarity:

pub struct Pool {
    inner: Arc<Mutex<PostgresDb>>,
}

fn main() {
    let postgres: Arc<Mutex<PostgresDb>>; //removed creation of the instance

    setup(&postgres)
}

fn setup(postgres: &Arc<Mutex<PostgresDb>>) -> () {
    let pool = Arc::new(Pool::new(*postgres));
}

I'm getting the error:

cannot move out of `*postgres` which is behind a shared reference
let pool = Arc::new(Pool::new(*postgres));
move occurs because `*postgres` has type `Arc<Mutex<PostgresDb>>`, which does not implement the `Copy` trait

How do I correctly pass postgres?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
sergeda
  • 2,061
  • 3
  • 20
  • 43

1 Answers1

6

Arcs are made to be cloned, and not made to be moved out of. If you want an Arc to put in your Pool, then just clone it and move it in:

pub struct Pool {
    inner: Arc<Mutex<PostgresDb>>,
}

impl Pool {
    pub fn new(postgres: Arc<Mutex<PostgresDb>>) -> Self {
        Self { inner: postgres }
    }
}

fn main() {
    let postgres: Arc<Mutex<PostgresDb>> = foo();
    setup(Arc::clone(&postgres));
}

fn setup(postgres: Arc<Mutex<PostgresDb>>) {
    let pool: Pool = Pool::new(postgres);
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Aplet123
  • 33,825
  • 1
  • 29
  • 55
  • 1
    Note: although you can certainly move the Arc itself (that avoids updating refcounts), or lend references to either the Arc or its contents (depending on the constraints). These capabilities help avoid some of the inefficiencies of Arc (namely having to update refcounts atomically). – Masklinn Nov 10 '20 at 12:56
  • 1
    *not made to be moved out of* — this is true most of the time, but not always: [How to take ownership of T from Arc>?](https://stackoverflow.com/q/29177449/155423) – Shepmaster Nov 10 '20 at 14:03