I’ve been trying to use OneCell, but I keep having errors trying to set it up to handle a mutable vector that I can push to.

I know there’s going to be some answers telling me maybe not to use a singleton, but the alternative of passing a vector all around throughout my code is not ergonmic at all.

I’ve tried lots of things, but this is where I’m at right now. Specifically I’m just having trouble initializing it.

`/**

  • LOG_CELL
  • Stores a vec of Strings that is added to throughout the algorithm with information to report
  • To the end user and developer */ pub static LOG_CELL: OnceLock<&mut Vec> = OnceLock::new();

pub fn set_log() { LOG_CELL.set(Vec::new()); }

pub fn push_log(message: String) { if let Some(vec_of_messages) = LOG_CELL.get() { let something = *vec_of_messages; something.push(message); } } `

  • pranaless@beehaw.org
    link
    fedilink
    arrow-up
    3
    ·
    1 year ago

    OnceLock is the wrong primitive for this. Use a Mutex or an RwLock instead? You can initialize either of them with an empty array at declaration, so you don’t need the set_log function. In push_log, do a .lock().unwrap() for a mutex or .write().unwrap() for an rwlock to get mutable access to the vector.

  • frankfurt_schoolgirl [she/her]@hexbear.net
    link
    fedilink
    English
    arrow-up
    2
    ·
    1 year ago

    Is the Singleton accessed by one thread or many?

    If it’s one thread, couldn’t you just wrap the Vec in an Rc and then clone your singleton every time you need it in a new scope?

    If it’s many, you should use channels and a dedicated logging thread imo.

  • ActuallyRuben@actuallyruben.nl
    link
    fedilink
    arrow-up
    2
    ·
    1 year ago

    Can’t you just use the get_or_init method instead of get inside the push_log method? This would initialize the cell on first use. You’d still need a Mutex inside of it to acquire a mutable reference to the vector.

  • Barbacamanitu@lemmy.world
    link
    fedilink
    arrow-up
    1
    ·
    1 year ago

    Maybe lazy_static? Personally I’d just pass a borrow to the vec around. It’s very common for programs to have some global state that they pass around to different parts.

      • Barbacamanitu@lemmy.world
        link
        fedilink
        arrow-up
        1
        ·
        edit-2
        1 year ago

        Ah I didn’t realize most people have moved onto OnceCell. The issue with both lazy static and oncecell is that they can only be assigned to once. You need a global mutable state, so neither OnceCell or lazy_static are the right choice.

        You’re going to be fighting the borrow checker if you try to have global mutable state. It will bite you eventually. You can potentially use an interior mutablity pattern along with a mutex. Have you looked into interior mutability?