Support both Rc and Arc in a library

Rather than symlinks, you can use the following "trick" that uses only Rust-specific constructs, and is thus OS-agnostic (any platform will be able to clone the repo and make it work):

tree

foo
├── Cargo.toml
└── src
    ├── common
    │   ├── mod.rs
    │   └── some_submodule.rs
    └── lib.rs

src/lib.rs

pub
mod multi_threaded {
    use ::std::sync::{
        Arc, Weak,
        RwLock,
    };

    include!("common/mod.rs");
    /* or:
    #[path = "../common/mod.rs"]
    mod common;
    pub use common::*;
    // but it requires that there be a `src/multi_threaded` dir */
}

pub
mod single_threaded {
    mod private {
        use ::core::cell::{RefCell, Ref, RefMut};

        pub
        struct RwLock<T> (
            RefCell<T>,
        );

        // Mimic `RwLock`'s API
        impl<T> RwLock<T> {
            pub
            fn new (value: T)
              -> Self
            {
                Self(RefCell::new(value))
            }

            pub
            fn read (self: &'_ Self)
              -> Result<Ref<'_, T>, ::core::convert::Infallible>
            {
                Ok(self.0.borrow())
            }

            pub
            fn write (self: &'_ Self)
              -> Result<RefMut<'_, T>, ::core::convert::Infallible>
            {
                Ok(self.0.borrow_mut())
            }

            // etc.
        }
    }
    use ::std::rc::{Rc as Arc, Weak};
    use private::RwLock;

    include!("common/mod.rs");
}

src/common/mod.rs

// magically `Arc`, `Weak` and `RwLock` are in scope here

/* If using the `mod common;` technique, then you have to:
use super::{Arc, Weak, RwLock};
// so that it is explicit that such items are in scope */

pub
struct MyShared<T> (
    Arc<RwLock<T>>,
);

mod some_submodule; // etc.

4 Likes