共享临时文件管理

Posted

技术标签:

【中文标题】共享临时文件管理【英文标题】: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)*> resourcesptr_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,这意味着如果有对该资源的第三个请求,它将实例化另一个新的一个资源的对象,实际上可能已经在使用中。 这里的另一个问题是您必须进行整个临时堆分配才能进行查找。这可以通过使用透明比较器来避免。 【参考方案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;

【讨论】:

以上是关于共享临时文件管理的主要内容,如果未能解决你的问题,请参考以下文章

MySQL Innodb--共享临时表空间和临时文件

MySQL 存储引擎

samba文件共享服务配置(multiuser机制)二 (共两节)

Kubernetes 共享临时存储来异步上传文件

各个目录说明

linux根目录tmp文件夹