【问题标题】:Shared temp file management共享临时文件管理
【发布时间】: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;
}

Demo here

【问题讨论】:

  • 看起来你只在 resources 集合中保留弱指针。这不会使对象保持活动状态。
  • @RichardCritten resources 有意保留周指针,所以我不会让分配的对象超过它们的用处。如果result-&gt;lock() 失败,我打算通过} 创建一个新对象。
  • 进程与线程完全不同(顺便说一句,您在示例中没有使用任何线程),您甚至不能使用weak_ptr 跨进程边界。它如何工作
  • 这里提供的实现没有多大意义;如果经理没有给定的资源,它会实例化一个并返回它,同时持有weak_ptr 给它。如果有其他东西来请求相同的资源,它会将shared_ptr 交还给它,然后停止持有weak_ptr,这意味着如果有对该资源的第三个请求,它将实例化另一个新的一个资源的对象,实际上可能已经在使用中。
  • 这里的另一个问题是您必须进行整个临时堆分配才能进行查找。这可以通过使用透明比较器来避免。

标签: c++ c++11 shared-ptr temporary-files stdset


【解决方案1】:

weak_ptr 可能是这里工作的错误工具。

考虑这一行:

 auto result = resources.find( std::weak_ptr<std::string>(std::make_shared<std::string>(filename)) );
    

这里发生的是您在堆上创建filename 的副本并通过新创建的shared_ptr 对其进行管理。然后构造一个weak_ptr,之后shared_ptr 超出范围,留下一个空的weak_ptr。因此,您可能一开始就使用空的weak_ptr

如 cmets 中所述,shared_ptr 不是一种进程间通信技术。如果您想跨多个进程同步资源(您似乎想要这样做),您将需要适当的 IPC 机制。 C++ 标准库不提供这些,因此您必须为此目的查看其他库。

另请注意,您的 ptr_less 函数没有做有效的事情。在 C++ 中,你是 only allowed to compare certain related values 使用 operator &lt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-13
    • 1970-01-01
    • 2022-01-17
    • 2021-08-11
    • 2012-10-31
    • 1970-01-01
    • 1970-01-01
    • 2012-03-07
    相关资源
    最近更新 更多