我有一个简单的POD数据类,例如
struct hash{
char buffer[16];
};
我需要一个包含许多实例的向量,它将完全不适合ram(20 PB)。从概念上讲,它分为向量(树)。我希望有一种方法可以使指针像东西一样隐藏RAM,文件系统,冷存储器,并具有简单的数组\指针像接口(使fs,初始化后的操作不可见,但允许在多个位置放置数据-RAM,快速SSD,SSD,HDD,磁带,云驱动器位置)
如何在C ++中做到这一点?
答案 0 :(得分:1)
在语言级别上对此不支持。
一种解决方案是使用内存映射文件,例如:
Creating a File Mapping Using Large Pages
如果您需要更独立于平台的解决方案,那么可以使用boost库中也支持内存映射文件的boost-filesystem。
除了您之外,您还可以始终创建一个 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
类。
此外,如果要被多个线程使用,则应锁定,并且我假设您不会两次访问同一元素。
或者您也可以像他们告诉您的那样使用内存映射文件访问。