3 ms·
About the threading stuff, I think I wasn't clear initially. Maybe a rephrasing/simplification of my question will help: Does C++ have a compile-time way of ens
by davidatbu 4y ago
About the threading stuff, I think I wasn't clear initially. Maybe a rephrasing/simplification of my question will help: Does C++ have a compile-time way of ensuring, say, that mutex-protected data isn't accessed without acquiring a lock on the mutex?
> You can prevent dangling pointers using strong/weak pointers
I presume you're talking about unique_ptr/shared_ptr/weak_ptr right? If one avoids raw pointers and uses those, I think you cannot have a shared reference without ref counting right? (because shared_ptr uses ref-counting). Not that this invalidates your point, just thought it was useful to point out.
> how would a rust program handle a handle to the currently playing audio device being unplugged and invalidating your handle?
I've never had to deal with that situation, but I presume some mechanism similar to how the mutex in the stdlib has a .lock() method that returns an Option<MutexGuard<_>> (which forces the user to acknowledge/handle the case of a poisoned mutex).
> Constexpr primatives/functions have compile time guarantees and can't be changed.
Consider the c++ code here:
int a = 4;
const int &b = a;
a += 1;
Such a thing would be disallowed in Rust, which (though hard to see from this example) is the exact mechanism that prevents a Vec being modified while it is being iterated on. Does C++ have primitives that provide such guarantees?
- fizzynut 4y agoLike I said, use constexpr. constexpr int a = 4; auto& b = a; a+= 1; // compile error b+= 1; // compile error Trying to make b constexpr with "a" as an int is also a compile error.
- davidatbu 4y agoThat would unnecessarily constraint `a` to be known at compile time though? I imagine that would be incredibly limiting. E.g., if you're implementing an iterator that takes a reference to the length of the container being iterated, and you require that that reference is constexpr, that means the container will have a fixed, compile-time-known, size. Since you didn't reply to the other parts of the comment, I'll presume that C++ doesn't have the mutex I'm talking about (apart from this attempt[0], which I just learnt about and commented on in a different reply), and that it's not possible to have non-ref-counted shared references while statically avoiding dangling pointers. [0] https://clang.llvm.org/docs/ThreadSafetyAnalysis.html https://clang.llvm.org/docs/ThreadSafetyAnalysis.html
- fizzynut 4y agoA lot of constants are known at compile time and constexpr solves a lot of problems. However, you do not need constexpr to solve your example- this is still a compile error: void iter(std::vector<int>& vec) { auto& vec_size = vec.size(); vec_size += 10; //compile error } There are many ways of forcing compile errors for mutexes that people have built, but they all come with their own trade-offs. I've not encountered a problem where I specifically needed "non-ref-counted shared references while statically avoiding dangling pointers", so I'm not an expert on it.
- davidatbu 4y agoWhat I'm referring to with regards containers is: preventing containers being modified while they are being iterated on (which is usually bad, because you will probably invalidate the iterator when modifying the container). That is what is prevented by Rust's references rules, and to my knowledge, isn't possible to protect against in C++ (statically). Thanks for the replies about the other stuff!
- nyanpasu64 4y agoPractically all valid Rust can be rewritten as valid C++. To make C++ reject most invalid thread-based code that Rust rejects, you can mark cross-thread-shared references as const&, atomic fields as mutable, and write a Mutex<T> class which wraps a mutable T, and only allows accessing a T& through a Mutex const& by locking the mutex. So implementing Rust-style threading in C++ is viable, but extra work to write a Mutex<T>, and the compiler lacks borrow checking to prevent you from making lifetime and overlapping &/&mut mistakes and committing data races. (http://www.drdobbs.com/cpp/volatile-the-multithreaded-programmers-b/184403766 http://www.drdobbs.com/cpp/volatile-the-multithreaded-progra... proposes using volatile& for this purpose, but many regard this as actually a bad idea.) Though in practice most C++ codebases sprinkle mutexes ad-hoc, relying on at best comments describing what data is protected by what mutex, with predictably disastrous results. I feel Rust is a better language than C++ at implementing correct multithreaded code, but is so constraining that it makes correct single-threaded code hard to implement when it doesn't fit neatly into tree-shaped ownership (eg. graphs, GUI trees, and extending existing program architectures).
- davidatbu 4y agoLearnt a lot from this. Thanks!