【发布时间】:2021-11-17 01:43:05
【问题描述】:
我的应用程序启动了几个类似的进程。第一个创建了一个“全局”临时文件,它们都是红色/写入的。当最后一个进程被销毁时,这个文件需要被删除。 稍后可能会启动更多进程,并且应该重新创建此文件。 从各种示例中,我想出了一个管理器类,它使用自定义删除器(删除文件)创建 shared_ptr,并将 week_ptr 保存到这些对象中,以便能够根据请求分发它们。这可行,但我想知道是否有更好的方法,或者在我的代码中可以发现任何陷阱。
#include <iostream>
#include <memory>
#include <string>
#include <set>
bool ptr_less(std::weak_ptr<std::string> lhs, std::weak_ptr<std::string> rhs) {
auto left = lhs.lock();
auto right= rhs.lock();
if (!left || !right)
return left < right;
return *left < *right;
}
struct Manager {
std::shared_ptr<std::string> get(const std::string& filename) {
auto result = resources.find( std::weak_ptr<std::string>(std::make_shared<std::string>(filename)) );
if (result != resources.end()) {
std::cout << "Exists: " << filename << std::endl;
if (auto sp = result->lock())
return sp;
resources.erase(result);
}
// Create new object to manage, auto deleting
std::shared_ptr<std::string> ptr(new std::string(filename),
[](std::string* str) { std::cout << "remove: " << *str << std::endl; delete str; });
resources.emplace(std::weak_ptr<std::string>(ptr));
//cleanup null pointers
for (auto iter=resources.begin(); iter != resources.end(); ) {
if (!iter->lock())
iter = resources.erase(iter);
else
++iter;
}
return ptr;
}
//Keep track of files to share. std::set comparing values not pointers
std::set<std::weak_ptr<std::string>, decltype(ptr_less)*> resources{ptr_less};
};
static Manager custodian;
struct User {
User(std::string name) : mName(std::move(name)) {
std::cout << "New user: " << mName << std::endl;
mGlob = custodian.get("global.json");
mSet = custodian.get("settings-" + mName + ".json");
mVal = custodian.get("values-" + mName + ".json");
}
~User() {
std::cout << "~User(): " << mName << std::endl;
}
std::shared_ptr<std::string> mGlob;
std::shared_ptr<std::string> mSet;
std::shared_ptr<std::string> mVal;
std::string mName;
};
int main()
{
using namespace std;
User* ps3 { nullptr };
{
User ps1("ps1");
User ps2("ps2");
ps3 = new User("ps3");
}
delete ps3;
cout << "Resources size: " << custodian.resources.size() << endl;
User ps1("ps1");
cout << "Resources size: " << custodian.resources.size() << endl;
return 0;
}
【问题讨论】:
-
看起来你只在
resources集合中保留弱指针。这不会使对象保持活动状态。 -
@RichardCritten
resources有意保留周指针,所以我不会让分配的对象超过它们的用处。如果result->lock()失败,我打算通过}创建一个新对象。 -
进程与线程完全不同(顺便说一句,您在示例中没有使用任何线程),您甚至不能使用
weak_ptr跨进程边界。它如何工作? -
这里提供的实现没有多大意义;如果经理没有给定的资源,它会实例化一个并返回它,同时持有
weak_ptr给它。如果有其他东西来请求相同的资源,它会将shared_ptr交还给它,然后停止持有weak_ptr,这意味着如果有对该资源的第三个请求,它将实例化另一个新的一个资源的对象,实际上可能已经在使用中。 -
这里的另一个问题是您必须进行整个临时堆分配才能进行查找。这可以通过使用透明比较器来避免。
标签: c++ c++11 shared-ptr temporary-files stdset