使用拥有自定义删除器的非所有权std::unique_ptr
来安排关键部分的以下方法的弊端或错误是什么?
#include <memory>
#include <shared_mutex>
#include <optional>
#include <variant>
#include <cassert>
struct Data
{
std::optional<int> i;
};
struct DataLocker
{
std::variant<std::unique_lock<std::shared_mutex>,std::shared_lock<std::shared_mutex>> lock;
void operator () (const Data *)
{
std::visit([] (auto & lock) { if (lock) lock.unlock(); },lock);
}
};
struct DataHolder
{
std::unique_ptr<Data,DataLocker> getLockedData()
{
return {&data,{std::unique_lock<std::shared_mutex>{m}}};
}
std::unique_ptr<const Data,DataLocker> getLockedData() const
{
return {&data,{std::shared_lock<std::shared_mutex>{m}}};
}
private :
mutable std::shared_mutex m;
Data data;
};
#include <iostream>
#include <thread>
int main()
{
DataHolder d;
auto producer = [&d]
{
d.getLockedData()->i = 123;
};
auto consumer = [&d = std::as_const(d)]
{
for (;;) {
if (const auto i = d.getLockedData()->i) {
std::cout << *i << std::endl;
return;
}
}
};
std::thread p(producer);
std::thread c(consumer);
p.join();
c.join();
}
一个极端的情况是,当编写者reset()
指向一个指针并且永不破坏std::unique_ptr
本身时,可以通过在删除者的unlock
上添加operator ()
来解决。