Hi,
Learning Rust and getting caught up in details, but I always want to know the whys of things, and the minor differences.
Lets start of with, is there a difference between the const value vs const reference?
// Given this little struct of mine, a Page with information about an endpoint
#[derive(Clone)]
pub struct Page<'a> {
pub title: &'a str,
pub endpoint: &'a str,
}
// Value
const ROOT_PAGE: Page = Page::new("Home", "/home");
// Reference
const ROOT_PAGE: &'static Page = &Page::new("Home", "/home");
-
Since my functions always take a reference, is there any advantage to any of them. References are read-only, but since it's const it probably doesn't matter. What is prefered?
-
I know String does allocations, while &str is a string slice or something which may be on the stack. Do I not end up making any allocations in this case since stucts are on the stack by default, and only hold the pointers to a string "slice". Especially given how they are made in this case.
-
Is structs with references like this okay, this Page is constant but I'm going to make many "Pages" later based on the pages my blog has, as well as some other endpoints of course.
-
If the struct is cloned, is the entire string as well, or just the pointer to the string slice? I assume it does copy the entire string, since to the best of my knowledge a &str does not do any reference counting, so deleting a &str means deleting it's content, not just the reference. Since that is the case, a clone will also copy the string.
-
I am contemplating adding a "body" string to my Page struct. These string will of course be large and vary depending on the page. Naturally, I do not want to end up copying the entire body string every time the Page is cloned. What is the best course here, it kind of depends on the previous question, but is an Arc the solution here? There is only reading to be done from them, so I do not need to worry about any owner holding it.
Sorry, but a long and slightly complicated question, for a hypotetical case.
I wanted to serve pages in my blog. The blog doesn't actually exist yet (but works locally, need to find out how I can safely host it later...), but lets assume it becomes viral, and by viral i mean the entire internet has decided to use it. And they are all crazy picky about loading times....
I haven't figued out the structure of the Page objects yet, but for the question they can be like the last question:
I wanted to create a HashMap that held all my pages, and when I updated a source file, the a thread would replace that page in the mapping. It's rather trivial of a problem really. I didnt find out if I could update a mapping from a thread, so I decided to make each value something that could hould a page and have the page object replaced on demand. It made somewhat sense since I don't need to delete a page.
There is a trivial solution. And it's just to have each HashMap value be a RwLock with an Arc holding my large string. No lagre string copies, Arc make it shared, and RwLock is fine since any number of readers can exist. Only when writing is the readers locked. Good enough really.
But I heard about DoubleBuffers, and though, why can't I have a AtomicPointer to my data that always exist? Some work later and I had something holding an AtomicPointer with a reference to an Arc with my Page type. But it didn't work. It actually failed rather confusingly. It crashed as I was trying to read the title on my Page object after getting it from the Arc. It wasn't even any thread stuff going on, reading once works, the next time it crashed.
This has undefined behavior, which isn't too surprising since I don't understand pointers that much... and I'm actually calling unsafe code. I have heard it can produce unexpected error outside it's block. I'm just surprised it works a little. This code sometimes fails the second assert with an empty string, crashes with access violation, or one time it gave me a comparison where some of it was lots of question marks! My best understanding is that my Page or it's content is moved or deallocated, but odd that my Arc seems perfectly fine. I just don't see the connection between the pointer and Arcs content causing a crash.
I may just be doing the entire thing wrong, so sticking with RwLock is much better and safer since there is no unsafe code. But I seek to know why this is so bad in the first place. What is wrong here, and is there a remedy? Or is it just fundamentally wrong?