c++虚拟内存
可以通过调用vmemalloc类型对象的括号运算符(len, name)分配大小为len,文件名为name的虚拟内存。
返回首地址的迭代器。
无需delete,程序结束后会自动清空文件,但是保留文件名
模板 vmemalloc 可以对特定类型分配空间,但是要求类型为POD,当类型不为POD时结果未定义
#warning Unsafe content. Deprecated.
/**
* -O1
* (SSD DRIVE, LEAST)
* 1s for 5e5 random access.
* 1s for 1.3e8 cont access.
* 1s for 6e4 stable_sort
* 1s for 2.5e4 sort
* 1s for 8e3 insection_sort
*/
#include<bits/stdc++.h>
using namespace std;
namespace virtual_memory{
/**
* small functions to be called by filename.
*/
void file_reset(const string& fname, size_t siz){
ofstream f(fname.c_str(), ios::binary| ios::out | ios::trunc);
int i = 0;
// cerr << 1.0 * clock() / CLOCKS_PER_SEC << endl;
static char buf1[32768 + 10] = {};
for(; i + 32768 < siz; i += 32768){
f.write(buf1, 32768);
}
static char buf2[128] = {};
for(; i + 128 < siz; i += 128){
f.write(buf2, 128);
}
char val = 0;
for(; i < siz; ++i) f.write(&val, 1);
f.close();
}
void file_clear(const string& fname){
file_reset(fname, 0);
}
/**
* proxy of a file.
* fixed file size.
* if a file was opened, the name won't be change.
* only opened by a file.
* safe write/read
*/
struct proxy_file{
string fname;
fstream f;
long long fsize;
using pos_type = fstream :: pos_type;
using off_type = fstream :: off_type;
using seekdir = fstream :: seekdir;
proxy_file(){
fsize = 0;
}
proxy_file(const string& str, size_t siz) : proxy_file(){
open(str, siz);
}
~proxy_file(){
file_clear(fname);
}
void open(const string& str, size_t siz){
assert(fname.empty() || str == fname);
fname = str;
fsize = siz;
file_reset(str, siz);
f.open(fname, ios :: binary | ios::out | ios::in);
assert(f.good());
}
void write_at(const char* str, size_t siz, off_type pos){
assert(0 <= pos && pos + siz <= fsize);
// cerr << "bef = " << f.tellp() << endl;
f.seekp(pos, ios :: beg);
// cerr << "fat = " << f.tellp() << endl;
f.write(str, siz);
}
void read_at(char * str, size_t siz, off_type pos){
assert(0 <= pos && pos + siz <= fsize);
f.seekg(pos, ios :: beg);
f.read(str, siz);
}
};
/**
* a pointer with a full information to read/write the file.
* with operator +, -, and so on.
* only check whether in the same file. uncheck the range.
*/
struct file_pointer{
proxy_file* file;
proxy_file :: off_type pos;
file_pointer() {
file = nullptr;
pos = 0;
}
file_pointer(proxy_file* file_, proxy_file :: off_type pos_) : file(file_), pos(pos_){}
friend int operator - (const file_pointer& x, const file_pointer& y){
assert(x.file == y.file);
return int(x.pos - y.pos);
}
friend file_pointer operator + (file_pointer x, ptrdiff_t len){
x.pos += len;
return x;
}
friend file_pointer operator - (file_pointer x, ptrdiff_t len){
x.pos -= len;
return x;
}
friend bool operator == (const file_pointer& x, const file_pointer& y){
return x.file == y.file && x.pos == y.pos;
}
friend bool operator < (const file_pointer& x, const file_pointer& y){
assert(x.file == y.file);
return x.pos < y.pos;
}
};
/**
* a proxy to the proxy_file
* because random access is very slow, we have to accelerate it by buffer
* safe read/write
* safe bounds
* FBUF_SIZE MUST BE EVEN.
*/
const int FBUF_SIZE = 1e8 * 2;
struct file_buf{
char buf[FBUF_SIZE];
file_pointer first; ptrdiff_t len;
file_buf(){
len = 0;
memset(buf,0, sizeof(buf));
}
~file_buf(){
write_through();
}
bool check_in(const file_pointer& p){
assert(p.file != nullptr);
return first.file == p.file && first.pos <= p.pos && p.pos < first.pos + len;
}
void write_through(){
if(first.file == nullptr) return;
first.file->write_at(buf, len, first.pos);
}
void read_through(){
if(first.file == nullptr) return;
first.file->read_at(buf, len, first.pos);
}
void init_buf(const file_pointer& p){
if(check_in(p)) return;
write_through();
assert(0 <= p.pos && p.pos < (p.file->fsize));
first.file = p.file;
first.pos = p.pos - FBUF_SIZE / 2 < 0 ? 0 : p.pos - FBUF_SIZE / 2;
len = min(FBUF_SIZE, int(p.file->fsize - first.pos));
read_through();
}
size_t get_pos(const file_pointer& p){
init_buf(p);
return p.pos - first.pos;
}
void read(const file_pointer& p, char& val){
size_t pos = get_pos(p);
val = buf[pos];
}
void write(const file_pointer& p, char val){
size_t pos = get_pos(p);
buf[pos] = val;
}
};
struct file_view{
file_buf * buf;
file_pointer pos;
file_view(){
buf = nullptr;
}
file_view(file_buf * buf_, file_pointer pos_) : buf(buf_), pos(pos_) {};
file_view(const file_view& rhs){
buf = rhs.buf;
pos = rhs.pos;
}
void read(char &val){
assert(buf != nullptr);
buf->read(pos, val);
}
void write(char val){
assert(buf != nullptr);
buf->write(pos, val);
}
friend auto operator - (const file_view& x, const file_view& y){
assert(x.buf == y.buf);
return x.pos - y.pos;
}
friend file_view operator + (file_view x, ptrdiff_t len){
x.pos = x.pos + len;
return x;
}
friend file_view operator - (file_view x, ptrdiff_t len){
x.pos = x.pos - len;
return x;
}
friend bool operator == (const file_view& x, const file_view& y){
return x.buf == y.buf && x.pos == y.pos;
}
friend bool operator < (const file_view& x, const file_view& y){
return x.pos < y.pos;
}
};
struct proxy_char{
file_view f;
proxy_char(file_view f_) : f(f_){}
proxy_char& operator = (char val){
f.write(val);
return *this;
}
operator char(){
char val;
f.read(val);
return val;
}
};
struct file_iterator{
file_view f;
file_iterator(file_view f_) : f(f_){}
file_iterator(file_buf * buf_, file_pointer pos_) : file_iterator(file_view(buf_, pos_)) {
}
file_iterator(const file_iterator& it_){
f = it_.f;
}
using iterator_category = random_access_iterator_tag;
using difference_type = ptrdiff_t;
using value_type = char;
using pointer = proxy_char*;
using reference = proxy_char;
friend auto operator - (const file_iterator& x, const file_iterator& y){
return x.f - y.f;
}
friend file_iterator operator + (file_iterator x, ptrdiff_t len) {
x.f = x.f + len;
return x;
}
friend file_iterator operator - (file_iterator x, ptrdiff_t len) {
x.f = x.f- len;
return x;
}
file_iterator& operator += (ptrdiff_t len){
*this = *this + len;
return *this;
}
file_iterator& operator -= (ptrdiff_t len){
*this = *this - len;
return *this;
}
bool friend operator ==(const file_iterator& x, const file_iterator& y){
return x.f == y.f;
}
void operator ++(){
*this = *this + 1;
}
void operator --(){
*this = *this - 1;
}
proxy_char operator *(){
return proxy_char(f);
}
friend bool operator < (const file_iterator& x, const file_iterator& y){
return x.f < y.f;
}
};
struct proxy_file_pool{
map<string, proxy_file> data;
~proxy_file_pool(){
data = decltype(data)();
}
proxy_file* get_file(string name){
assert(data.count(name));
return &data[name];
}
void create_file(string name, size_t siz){
assert(data.count(name) == false);
data[name].open(name, siz);
}
bool check_file(string name){
return data.count(name);
}
void erase_file(string name){
data.erase(name);
}
};
struct vmemalloc_base{
proxy_file_pool pool;
file_buf buf;
~vmemalloc_base(){
buf.~file_buf();
pool.~proxy_file_pool();
}
file_iterator operator ()(size_t len,const string& name){
pool.create_file(name, len);
return file_iterator(&buf, file_pointer(pool.get_file(name), 0));
}
};
template<typename T>
struct proxy_type{
virtual_memory :: file_iterator it;
proxy_type(file_iterator it_) : it(it_){}
operator T()const{
static char buf[sizeof(T)];
for(int i = 0; i < sizeof(T); ++i) buf[i] = *(it + i);
return *((T*)(buf));
}
proxy_type& operator = (T val){
const char* buf = (const char*)(&val);
for(int i = 0; i < sizeof(T); ++i) *(it + i) = buf[i];
return *this;
}
friend void swap(proxy_type lhs, proxy_type rhs){
T tmp = lhs;
lhs = T(rhs);
rhs = tmp;
}
};
template<typename T>
struct type_iterator{
file_iterator it;
type_iterator(const type_iterator<T>& ano) : it(ano.it) {}
type_iterator(file_iterator it_) : it(it_){}
type_iterator(file_buf * buf_, file_pointer pos_) : type_iterator(file_iterator(buf_, pos_)) {
}
using iterator_category = random_access_iterator_tag;
using difference_type = ptrdiff_t;
using value_type = T;
using pointer = proxy_type<T>*;
using reference = proxy_type<T>;
friend int operator - (const type_iterator& x, const type_iterator& y){
// cout << typeid(x.it - y.it).name() << endl;
return (x.it - y.it) / sizeof(T);
}
friend type_iterator operator + (type_iterator x, ptrdiff_t len) {
x.it = x.it + len * sizeof(T);
return x;
}
friend type_iterator operator - (type_iterator x, ptrdiff_t len) {
x.it = x.it - len * sizeof(T);
return x;
}
type_iterator& operator += (ptrdiff_t len){
*this = *this + len;
return *this;
}
type_iterator& operator -= (ptrdiff_t len){
*this = *this - len;
return *this;
}
friend bool operator ==(const type_iterator&x, const type_iterator& y){
return x.it == y.it;
}
friend bool operator !=(const type_iterator&x, const type_iterator& y){
return !(x == y);
}
type_iterator& operator ++(){
*this = *this + 1;
return *this;
}
type_iterator& operator --(){
*this = *this - 1;
return *this;
}
proxy_type<T> operator *()const{
return proxy_type<T>(it);
}
proxy_type<T> operator [](int x)const{
return *(*this + x);
}
friend bool operator < (const type_iterator& x, const type_iterator& y){
return x.it < y.it;
}
};
template<typename T>
struct vmemalloc : vmemalloc_base{
type_iterator<T> operator ()(size_t count,const string& name){
pool.create_file(name, count * sizeof(T));
return type_iterator<T>(file_iterator(&buf, file_pointer(pool.get_file(name), 0)));
}
};
}
int main(){
}