如何在c ++中使用多个缓存层(RAM,HDD,冷)

时间:2019-04-23 23:40:41

标签: c++ file pointers filesystems

我有一个简单的POD数据类,例如

struct hash{
    char buffer[16];
};

我需要一个包含许多实例的向量,它将完全不适合ram(20 PB)。从概念上讲,它分为向量(树)。我希望有一种方法可以使指针像东西一样隐藏RAM,文件系统,冷存储器,并具有简单的数组\指针像接口(使fs,初始化后的操作不可见,但允许在多个位置放置数据-RAM,快速SSD,SSD,HDD,磁带,云驱动器位置)

如何在C ++中做到这一点?

2 个答案:

答案 0 :(得分:1)

在语言级别上对此不支持。

一种解决方案是使用内存映射文件,例如:

Creating a File Mapping Using Large Pages

如果您需要更独立于平台的解决方案,那么可以使用库中也支持内存映射文件的

除了您之外,您还可以始终创建一个 like 对象外观来管理基础逻辑(阿拉智能指针)。

template<class T>
struct MyMappedPointerType {
  T& operator* MyPointerType();//derefence - may throw..
  //implement rest of semantics
};

答案 1 :(得分:0)

我认为通常会使用一些手柄。然后,当您要访问该对象时,可以将句柄传递给一个函数,该函数将加载内存并提供地址,然后关闭该句柄。在C ++中,您将使用RAII。

#include <string>
#include <cstdio>

template <class T>
class Access
{
private:
    FILE* f= nullptr;
public:
    Access(const std::string& filename)
    {
        f= fopen(filename.data(), "rw");
    }

    ~Access()
    {
        fclose(f);
    }

    class WriteAccess
    {
        T buffer{};
        bool dirty= false;
        FILE* f;
        int64_t elementNumber;
    public:
        WriteAccess(FILE* f, int64_t elementNumber)
        : f(f)
        , elementNumber(elementNumber)
        {
            if (f) {
                fseek(f, elementNumber*sizeof(buffer), SEEK_SET);
                fread(&buffer, sizeof(buffer), 1, f);
            }
        }

        T& get() { dirty= true; return buffer; }
        const T& get() const { return buffer; }

        ~WriteAccess()
        {
            if (dirty && f) {
                fseek(f, elementNumber*sizeof(buffer), SEEK_SET);
                fwrite(&buffer, sizeof(buffer), 1, f);
            }
        }
    };

    WriteAccess operator[] (int64_t elementNumber)
    {
        return WriteAccess(f, elementNumber);
    }
};

struct SomeData
{
    int a= 0;
    int b= 0;
    int c= 0;
};

int main()
{
    Access<SomeData> myfile("thedata.bin");

    myfile[0].get().a= 1;
    auto pos1= myfile[1];

    pos1.get().a= 10;
    pos1.get().b= 10;
}

当然,您将提供读取访问权限和写访问权限,可能不使用fopen而是使用新的c ++文件,您应检查错误,也许可以摆脱get()函数转换为T的形式。

您还应该注意,您可以使用一些引用计数,在我的简单示例中,Access类的寿命应该超过WriteAccess类。

此外,如果要被多个线程使用,则应锁定,并且我假设您不会两次访问同一元素。

或者您也可以像他们告诉您的那样使用内存映射文件访问。