Hello,
I'm still pretty new to Rust. Coming from C++ I assumed a good beginner problem to learn would be to write my own shared pointer implementation. Also I wanted to build something more similar to C++'s boost::intrusive_ptr.
I started off with the example given in the nomicon but ran into problems as soon as I wanted to use trait objects. The following line does not work with the implementation given there.
let x: Arc<dyn MyTrait> = Arc::new(MyStruct { x: 0 });
It's possible in nightly, but not on stable. The std lib uses lots of nightly features internally. In many cases it's for performance, but also to provide things like unsized coercions. So providng a fully featured implementation may require nightly. (As it does in this case)
So I can experiment on nightly which is sufficient for what I want to do right now.
(But as soon as I want to use it in any public "production crate" I'd have to reevaluate the situation and look for other solutions...?)
Then, I have loosened the <T> generics present in that code to <T : ?Sized>: Playground;
Finally, unless you have nightly, you will need to use helper crates that use a bit of unsafe to feature the coercions in stable Rust. So here is one which is being released as we speak:
Right now supporting arbitrary custom traits is a bit unergonomic in that first you need to write a dummy function pointer fattener: fn fatten_ptr<'lt> (p: *const (impl 'lt + Trait)) -> *const (dyn 'lt + Trait) { p } and then use a bit of unsafe to assert that this function you provide is indeed as dummy as it looks.
I'll soon make a PR to offer a non-unsafe (macro-based) interface for ease of use
But as soon as I want to use it in any public "production crate" I'd have to reevaluate the situation and look for other solutions
Not necessarily. You can release a crate which only compiles on nightly, but that will mean that it can only be consumed by crates or users which are also on nightly. That may reduce your audience, but it's not necessarily a deal-breaker; rocket is a very popular crate, probably the most popular web framework, which targets nightly.
Keep in mind though that if you enable a feature gate (which requires nightly), then that feature may be unstable, and is subject to backwards-incompatible changes. This is in contrast to the rest of the standard library and language which maintains backwards-compatibility. So this may mean that a future rust update may break your code, and require you to update your code to compile again.
In this code, because the fetch_sub is Relaxed it is allowed to be ordered before previous uses of the Arc, which can cause use after frees if another thread comes along and frees the Arc just after you fetch_sub. The only place a Release fence could go in that code is before the fetch_sub, to show to the compiler that the fetch_sub must occur after you finish using the Arc:
You're completely right, I applied the load-acquire to store-release symmetry incorrectly, good catch! Thanks! Now I have an actual example to remember to avoid making this mistake in the future (I'll edit my playground link to fix it).