Re:Sayonara, C++, and Hello to Rust
by lenkite on Friday December 10, 2021 @10:41AM
(#29511169)
Note that in `good` below, one can have many such lock guards: lk1, lk2, etc without any explicit lock release expression in the body of the function.
[ Parent
| on HN ]
Re:Sayonara, C++, and Hello to Rust
by AndyKelley on Friday December 10, 2021 @06:16PM
(#29516648)
var m: std.Thread.Mutex = .{};
fn good() !void {
m.lock();
defer m.unlock();
try f();
if (!everything_ok()) return;
}
It's still the RAII pattern. The explicit call to deinitialization does not disqualify it. I can overcomplicate it with a LockGuard class too: const LockGuard = struct {
mutex: *std.Thread.Mutex,
fn init(mutex: *std.Thread.Mutex) !LockGuard {
mutex.lock();
return .{
.mutex = mutex,
};
}
fn deinit(lg: *LockGuard) void {
lg.mutex.unlock();
}
};
fn good() !void {
var lk = try LockGuard.init(&m);
defer lk.deinit();
try f();
if (!everything_ok()) return;
}
In this case it demonstrates an improvement over C++, which is what happens if an error happens during a constructor. In C++ throwing an exception in a constructor is essentially UB; in zig it's a regular function call just like anything else.Thanks for the informative snippet, but explicit expressions involving defer is not what RAII means. In RAII resource is automatically tied to object lifetime.
https://en.wikipedia.org/wiki/Resource_acquisition_is_initia...
Regarding errors in a C++ constructor: https://isocpp.org/wiki/faq/exceptions#ctors-can-throw