-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TinyTemplate object not thread safe? How to synchronize? #30
Comments
Hello! Thanks for the suggestion. The honest answer is it never really occurred to me that anyone would want to do that. Unfortunately, now I've painted myself into a corner and can't fix this without a breaking change. The issue is that the formatter functions aren't required to implement Send or Sync - someone could configure a formatter that uses mutable state behind the scenes, if they wanted - and now Rust can't prove that it's safe to send those formatter functions (and therefore, the TinyTemplate object that contains them) between threads, so you can't. It's very unlikely that anyone is doing that, of course, but it's technically allowed and disallowing it would be a breaking change. In the meantime until I fix it, yeah, you'll basically have to clone it for each thread. |
Thanks for the detailed explanations! I didn't even know that Send or Sync are defined at the function level or that functions are allowed to change internal state when called from a non mutable reference, I will read those chapters of the Rust book. a few hours later I have now read about Send and Sync and that mutability is inherited but now I am more confused than before. Apparently, mutability is inherited in Rust and thus if I have a non mutable reference to something, I can't call methods that change the internal state. I guess that is a general problem I have with understanding Rust and I need to read more about it. |
Send and Sync are sort of strange. They're magical traits that are automatically derived by the compiler if it's safe to do so. They are, so far as I know, the only two such automatic traits. They aren't really a function-level thing, they're more a property of a type. The details aren't precisely relevant to this case, but the short version is that because I didn't specify Send or Sync on the bounds for the generic function type, the type-checker has to assume that they won't implement Send or Sync. Therefore, because it contains things that don't implement Send or Sync, the compiler can't automatically derive those traits for the TinyTemplate type. |
It's kinda ugly, but to avoid the breaking change on the API it's also possible to export a separate TinyTemplate type that is Send+Sync. I tried this out in a fork: master...johnbartholomew:TinyTemplate:sync It adds a module |
I want to use TinyTemplate for an Actix Web application, but I run into problems making my TinyTemplate object lazy_static because it does not have the Sync trait. Is it possible to add that or is there a technical reason for that? I could understand that a mutable TinyTemplate object could add a template while another thread calls the render function but why can't two threads use the render function at the same time when they have non-mut reference? Is it recommended to just recreate a new TinyTemplate object every time
render()
is used or is it faster to reuse the same object and add some synchronization code? Or should I clone the object once for each CPU core and use some kind of pool? Is it possible to share a pointer to just the render() function and use that in a thread safe manner?Sorry if those are basic questions, I'm still new to Rust, but TinyTemplate works very well for my use case but right now I recreate the TinyTemplate every time I need it and wonder if I'm doing it wrong.
The text was updated successfully, but these errors were encountered: