If I understand your question correctly, you want a global mutable variable of type Connection
and you are wondering if it will be reinitialized every time the variable is imported from a different crate/thread.
In this case, you do not need the default trait. Default
is not a special trait. It is only in the standard library because it is very common. To define a global variable, you must initialize the value directly. You must first define the type Connection
:
pub struct Connection {
pub id: i32,
pub speed: i32,
}
And then create the global variable. There are many ways to create a global mutable variable as explained in this answer. Assuming that Connection
stores things other than integers you will probably need to wrap the global in an Arc
for thread-safety, and a Mutex
if you require mutability across threads. You can use lazy_static
to initialize the variable at runtime which allows you to make the necessary method calls to create the Connection
:
lazy_static! {
pub static ref conn: Arc<Connection> = Arc::new(Connection {
id: open_connection(),
speed: get_speed_at_init(),
});
}
Now to answer your question.
No, spawning a new thread or importing a variable from a crate will not re-initialize the static variable. A static
variable represents a precise memory location in the program. All references to the static refer to the same memory location, whether they live in the same module, crate, or thread. We can test this by generating a random id
in open_connection
and placing the global conn
in a seperate module:
pub mod connection {
lazy_static! {
pub static ref conn: Arc<Connection> = Arc::new(Connection {
id: open_connection(),
speed: get_speed_at_init(),
});
}
fn open_connection() -> i32 {
let mut rng = rand::thread_rng();
rng.gen()
}
}
You can access the conn
from multiple modules or crates:
mod a {
use crate::connection::conn;
pub fn do_stuff() {
println!("id from a: {}", conn.id);
}
}
// a different crate
mod b {
use crate::connection::conn;
pub fn do_stuff() {
println!("id from b: {}", conn.id);
}
}
And multiple threads:
mod c {
use crate::connection::conn;
pub fn do_stuff() {
for i in 0..5 {
std::thread::spawn(move || {
println!("id from thread #{}: {}", i, conn.id);
})
.join()
.unwrap();
}
}
}
But the id
will always refer to the id
that was generated when the global variable was initially declared:
fn main() {
a::do_stuff();
different_crate::b::do_stuff();
c::do_stuff();
}
// id from a: 1037769551
// id from b: 1037769551
// id from thread #0: 1037769551
// id from thread #1: 1037769551
// id from thread #2: 1037769551
// id from thread #3: 1037769551
// id from thread #4: 1037769551
Playground link: Unfortunately you cannot have multiple crates on the playground, so modules were the best I could do. If you are still unsure, you could always test it out locally.