Lifetimes and reference usage in thread

I have a struct TableDefinition (that I cannot change) which holds a reference to a string slice, and another struct A which contains an Arc<String>. My goal is to create an instance of B which contains TableDefinition initialized with a string slice from A's Arc<String>. This setup works fine until I attempt to pass B to a new thread, at which point I encounter a lifetime issue.

The error I'm getting is as follows:

error[E0597]: `a.table_name` does not live long enough
  --> src/test_share_thread.rs:38:41
   |
33 |         let a = A {
   |             - binding `a` declared here
...
38 |             table: TableDefinition::new(a.table_name.as_str()),
   |                    ---------------------^^^^^^^^^^^^----------
   |                    |                    |
   |                    |                    borrowed value does not live long enough
   |                    argument requires that `a.table_name` is borrowed for `'static`
...
45 |     }
   |     - `a.table_name` dropped here while still borrowed

I understand that the error is related to the lifetime of a.table_name, but I'm not sure how to properly extend its lifetime or restructure my code to satisfy Rust's borrowing rules, especially while working with threads.

Here's the relevant portion of my code for context (Rust Playground):

use std::sync::Arc;
use std::thread;

pub struct TableDefinition<'a> {
    name: &'a str,
}
// ... [TableDefinition implementation]

struct A {
    pub table_name: Arc<String>,
}

struct B<'a> {
    pub table: TableDefinition<'a>
}

#[test]
fn simple() {
    let a = A {
        table_name: Arc::new("my_table".to_string()),
    };

    let b = B {
        table: TableDefinition::new(a.table_name.as_str()),
    };

    let handle = thread::spawn(move || {
        b.table
    });
}

Perrhaps there's a way to redesign the structs or a different method to handle lifetimes in this scenario?

Note: I can not change the definition of TableDefinition.

Here are two potential options:

  1. Since you're borrowing across threads, use std::thread::scope

  2. Don't borrow across threads. Clone the arc string then get the reference to it in your destination thread.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.