Что такое Mutex<T>
2025-03-02 19:37![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Продолжаем изучать примитивы языка Rust. В этом деле Грок неплохой помощник. Как выясняется, тип Mutex<T> представляет собой удобную комбинацию классов std::mutex и std::unique_lock из Си++.
Question: Please show me a possible implementation of type Mutex<T> in C++.
I'll provide an implementation of a Mutex<T> type in C++ that mimics Rust's Mutex. Rust's Mutex provides mutual exclusion with a lock guard pattern, so we'll create a similar construct in C++ using the standard library's threading primitives.
Here's a possible implementation: mutex.cpp.
Question: Please show me a possible implementation of type Mutex<T> in C++.
I'll provide an implementation of a Mutex<T> type in C++ that mimics Rust's Mutex. Rust's Mutex provides mutual exclusion with a lock guard pattern, so we'll create a similar construct in C++ using the standard library's threading primitives.
Here's a possible implementation: mutex.cpp.
#include <mutex>
#include <memory>
template<typename T>
class Mutex {
private:
T data;
std::mutex mtx;
public:
// Constructor
explicit Mutex(T value) : data(std::move(value)) {}
// Lock guard class (similar to Rust's MutexGuard)
class LockGuard {
private:
T& data_ref;
std::unique_lock<std::mutex> lock;
public:
LockGuard(T& d, std::mutex& m)
: data_ref(d), lock(m) {}
// Access the underlying data
T& operator*() { return data_ref; }
T* operator->() { return &data_ref; }
};
// Lock method that returns the guard
LockGuard lock() {
return LockGuard(data, mtx);
}
// Prevent copying
Mutex(const Mutex&) = delete;
Mutex& operator=(const Mutex&) = delete;
// Allow move construction
Mutex(Mutex&&) = default;
Mutex& operator=(Mutex&&) = default;
};
Let's break down the key components:
1. Mutex<T> Class:
1. Mutex<T> Class:
- Stores the actual data (T data)
- Contains a std::mutex for synchronization
- Takes an initial value in constructor
- Similar to Rust's MutexGuard
- Holds a reference to the data and a std::unique_lock
- Provides access to the underlying data via operators * and ->
- Automatically unlocks when it goes out of scope (RAII)
- lock() method returns a LockGuard object
- Copy prevention to avoid race conditions
- Move semantics supported
- Thread-safe access to the contained data
- C++ doesn't have Rust's ownership system, so we rely on RAII
- No poisoning mechanism (Rust's Mutex can poison on panic)
- Manual lock() call instead of Rust's Option/Result pattern
- The LockGuard provides safe access to the data while holding the lock
- The lock is automatically released when the guard goes out of scope
- Multiple threads can safely access the mutex-protected data
- Adding try_lock() functionality
- Adding timeout-based locking
- Adding condition variable support
- Implementing poisoning for exception safety
#include <iostream>
#include <thread>
void example() {
Mutex<int> counter(0);
auto worker = [&counter](int id) {
for (int i = 0; i < 100; ++i) {
auto guard = counter.lock();
*guard += 1;
std::cout << "Thread " << id << " incremented to " << *guard << "\n";
}
};
std::thread t1(worker, 1);
std::thread t2(worker, 2);
t1.join();
t2.join();
auto final = counter.lock();
std::cout << "Final value: " << *final << "\n";
}
int main() {
example();
return 0;
}
no subject
Date: 2025-03-03 10:08 (UTC)