In C++ a mutex can wrap the object being protected.
In C++ a mutex can wrap the object being protected.
One reason not to provide the owning mutex in C++ is that it isn't able to deliver similar guarantees to Rust because its type system isn't strong enough. Rust won't let you accidentally keep a reference to the protected object after unlocking, C++ will for example.
#include <iostream>
#include <mutex>
#include <thread>
class SharedResource {
private:
int value;
std::mutex mtx;
public:
SharedResource() : value(0) {}
void setValue(int newValue) {
std::lock_guard<std::mutex> guard(mtx);
value = newValue;
}
int getValue() {
std::lock_guard<std::mutex> guard(mtx);
return value;
}
};
void threadFunction(SharedResource& resource) {
resource.setValue(42);
std::cout << "Value: " << resource.getValue() << std::endl;
}
int main() {
SharedResource resource;
std::thread t1(threadFunction, std::ref(resource));
std::thread t2(threadFunction, std::ref(resource));
t1.join();
t2.join();
return 0;
}In C++, a class like std::lock_guard also provides "Automatic unlock". AFAICT, the article argues that only Rust's API provides that.
{
const std::lock_guard<std::mutex> lock(mtx);
account.balance -= amount;
account.transaction_count++;
} // Automatically unlocked.The issue isn't automatic unlocking. From the article:
> The problem? Nothing stops you from accessing account without locking the mutex first. The compiler won’t catch this bug.
i.e., a C++ compiler will happily compile code that modifies `account` without taking the lock first. Your lock_guard example suffers from this same issue.
Nothing in the C++ stdlib provides an API that makes it impossible to access `account` without first taking the lock, and while you can write C++ classes that approximate the Rust API you can't quite reach the same level of robustness without external help.
The article wrote:
> Automatic unlock: When you lock, you receive a guard. When the guard goes out of scope, it automatically unlocks. No manual cleanup needed.
And presented Rust as being different from C++ regarding that, and the C++ example was not idiomatic, since it did not use something like std::lock_guard.
I have not addressed the rest of your comment, since it is a different topic, sorry.
As for the automatic cleanup bit, perhaps the article is trying to focus purely on the mutex types themselves? Or maybe they included the "when you lock" bit to emphasize that you can't forget to unlock the mutex (i.e., no reliance on unenforced idioms). Hard to say given the brevity/nature of the section, and in the end I think it's not that much of a problem given the general topic of the blogpost.
From my reading, the section (and the article in general, really) is specifically focusing on mutexes, so the observations the article makes are indeed accurate in that respect (i.e., C++'s std::mutex indeed does not have automatic unlocking; you need to use an external construct for that functionality). Now, if the article were talking about locking patterns more generally, I think your criticism would hold more weight, but I think the article is more narrowly focused than that.
For a bit of a more speculative read, I think it's not unreasonable to take the C++ code as a general demonstration of the mutex API "languages other than Rust" use rather than trying to be a more specific comparison of locking patterns in Rust and C++. Consider the preceding paragraph:
> In languages other than Rust, you typically declare a mutex separately from your data, then manually lock it before entering the critical section and unlock it afterward. Here’s how it looks in C++:
I don't think it's unreasonable to read the "it" in the final sentence as "that pattern"; i.e., "Here's what that pattern looks like when written in C++". The example code would be perfectly correct in that case - it shows a mutex declared separately from the data, and it shows that mutex being manually locked before entering the critical section and unlocked after.
Edit: Downvoting comments that you know are good, is even further against good debate practice. You are doing worse and worse, and you are well aware of it. Have some shame.