从类返回自动解锁的锁定资源
Return locked resource from class with automatic unlocking
我想有一个类成员函数返回一个指向资源的指针。资源应该自动锁定和解锁。我想创建一个不可复制的对象来处理锁。
你认为以下是一个好的解决方案吗?是线程安全的吗?STL中已经有这个用例的工具了吗?
template<typename T, typename M>
struct LockedResource
{
private:
T* data_;
std::unique_lock<std::mutex> lock_;
public:
LockedRessource(T* data, M& mtx) : data_{data}, lock_{mtx} {}
T* data() const { return data_; }
};
用例示例:
#include <iostream>
#include <mutex>
#include <thread>
#include <vector>
class Foo {
private:
std::vector<int> data_;
std::mutex mtx_;
public:
LockedResource<std::vector<int>,std::mutex> data()
{ return LockedResource<std::vector<int>,std::mutex>{&data_, mtx_}; }
};
Foo foo;
void worker(int worker, int iterations, int dt) {
for(int i=0; i<iterations; i++) {
std::this_thread::sleep_for(std::chrono::milliseconds(dt));
auto res = foo.data();
// we now have a unique_lock until the end of the scope
std::cout << "Worker " << worker << " adding " << i << std::endl;
res.data()->push_back(i);
}
}
int main() {
std::thread t1{worker, 1, 10, 173};
std::thread t2{worker, 2, 20, 87};
t1.join();
t2.join();
}
这个想法——提供一个句柄来封装对同步对象的访问和必要的锁定——并不是新的:参见使用同步值强制正确使用互斥锁。
我喜欢Rook使用带有自定义删除器的unique_ptr
作为句柄的想法,所以我想出了一个:
template <typename BasicLockable>
class unlock_deleter {
std::unique_lock<BasicLockable> lock_;
public:
unlock_deleter(BasicLockable& mtx) : lock_{mtx} {}
unlock_deleter(BasicLockable& mtx, std::adopt_lock_t a) noexcept : lock_{mtx, a} {}
template <typename T>
void operator () (T*) const noexcept {
// no-op
}
};
template <typename T, typename M = std::mutex>
using locked_ptr = std::unique_ptr<T, unlock_deleter<M>>;
,用于实现包装对象和互斥锁的模板类synchronized
:
template <typename T, typename M = std::mutex>
class synchronized {
T item_;
mutable M mtx_;
// Implement Copy/Move construction
template <typename Other, typename N>
synchronized(Other&& other, const std::lock_guard<N>&) :
item_{std::forward<Other>(other).item_} {}
// Implement Copy/Move assignment
template <typename Other>
void assign(Other&& other) {
std::lock(mtx_, other.mtx_);
std::lock_guard<M> _{mtx_, std::adopt_lock};
std::lock_guard<decltype(other.mtx_)> _o{other.mtx_, std::adopt_lock};
item_ = std::forward<Other>(other).item_;
}
public:
synchronized() = default;
synchronized(const synchronized& other) :
synchronized(other, std::lock_guard<M>(other.mtx_)) {}
template <typename N>
synchronized(const synchronized<T, N>& other) :
synchronized(other, std::lock_guard<N>(other.mtx_)) {}
synchronized(synchronized&& other) :
synchronized(std::move(other), std::lock_guard<M>(other.mtx_)) {}
template <typename N>
synchronized(synchronized<T, N>&& other) :
synchronized(std::move(other), std::lock_guard<N>(other.mtx_)) {}
synchronized& operator = (const synchronized& other) & {
if (&other != this) {
assign(other);
}
return *this;
}
template <typename N>
synchronized& operator = (const synchronized<T, N>& other) & {
assign(other);
return *this;
}
synchronized& operator = (synchronized&& other) & {
if (&other != this) {
assign(std::move(other));
}
return *this;
}
template <typename N>
synchronized& operator = (synchronized<T, N>&& other) & {
assign(std::move(other));
return *this;
}
template <typename N>
void swap(synchronized<T, N>& other) {
if (static_cast<void*>(&other) != static_cast<void*>(this)) {
std::lock(mtx_, other.mtx_);
std::lock_guard<M> _{mtx_, std::adopt_lock};
std::lock_guard<N> _o{other.mtx_, std::adopt_lock};
using std::swap;
swap(item_, other.item_);
}
}
locked_ptr<T, M> data() & {
return locked_ptr<T, M>{&item_, mtx_};
}
locked_ptr<const T, M> data() const& {
return locked_ptr<const T, M>{&item_, mtx_};
}
};
template <typename T, typename M, typename N>
void swap(synchronized<T, M>& a, synchronized<T, N>& b) {
a.swap(b);
}
注意正确同步拷贝/移动/交换。以下是Coliru的示例程序。
相关文章:
- 具有瞬态资源的RAII类
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 如何找到锁定Linux futex的C++行
- G锁定铸造到基础上会释放模拟行为
- 允许从 std::map 的密钥窃取资源?
- 参考资源文件VC++中的$(SolutionDir)
- 如何检查线程是否锁定
- 如何维护资源管理器项目视图中当前可见的项目列表
- 如何在C++中找到active directory中禁用和锁定的窗口帐户
- 我应该在锁定TBitmap画布后解锁它吗
- 将 std::allocate_shared 与多态资源分配器一起使用
- 使用RAII在给定次数的迭代后重新分配资源
- 资源管理设计模式
- 如何跨平台将二进制资源构建到程序中?
- SetDlgItemInt 不会更改嵌入资源的编辑框
- Klocwork Inside的资源泄漏
- 从存储为 Windows 资源 (c++) 的 png 中获取 png 文件数据
- 可以通话到STD ::锁定通过通话线程已经锁定的资源
- 锁定构造函数和析构函数中的共享资源
- 从类返回自动解锁的锁定资源