81 lines
1.8 KiB
C++
81 lines
1.8 KiB
C++
#ifndef _PAGECACHE_HH_
|
|
#define _PAGECACHE_HH_
|
|
|
|
#include <map>
|
|
#include <list>
|
|
|
|
#include "interfaces.hh"
|
|
#include "mtprim.hh"
|
|
|
|
class PageCache {
|
|
private:
|
|
struct _allocInfo;
|
|
|
|
public:
|
|
class Handle {
|
|
public:
|
|
Handle() : alloc_(nullptr) {
|
|
}
|
|
Handle(Handle const& copy);
|
|
~Handle();
|
|
|
|
Handle& operator=(Handle const& copy);
|
|
|
|
char *data() {
|
|
return alloc_->virtMem + ofs_*4096;
|
|
}
|
|
|
|
void setDirty();
|
|
void flush();
|
|
|
|
private:
|
|
Handle(_allocInfo* alloc, int ofs);
|
|
|
|
_allocInfo *alloc_;
|
|
int ofs_;
|
|
|
|
friend class PageCache;
|
|
};
|
|
|
|
PageCache(int maxPages = -1);
|
|
~PageCache();
|
|
|
|
// Allocate memory in the cache and fill it with data from dev
|
|
// If the data already exists in the cache a Handle to that entry may be returned
|
|
Handle readAllocate(IBlockDevice& dev, unsigned pos, unsigned count);
|
|
|
|
// Allocate memory in the cache without reading from device
|
|
// This prevents useless reads if you're going to overwrite the entire range anyways
|
|
// If the data already exists in the cache a Handle to that entry may be returned
|
|
Handle writeAllocate(IBlockDevice& dev, unsigned pos, unsigned count);
|
|
|
|
// Flush all dirty cached pages to their block devices
|
|
void sync();
|
|
|
|
// Eject pages from cache. If lengthHint is > 0, try to free at least that many pages
|
|
void eject(int lengthHint);
|
|
|
|
private:
|
|
int maxPages_, curPages_;
|
|
Mutex mutex_;
|
|
|
|
struct _allocInfo {
|
|
IBlockDevice *dev;
|
|
unsigned start;
|
|
unsigned len;
|
|
uintptr_t physMem;
|
|
char *virtMem;
|
|
bool dirty;
|
|
int refs;
|
|
};
|
|
|
|
std::map<IBlockDevice*, std::list<_allocInfo> > allocs_;
|
|
|
|
void freeAlloc(_allocInfo& alloc);
|
|
void buildAlloc(_allocInfo& alloc, unsigned len);
|
|
_allocInfo* searchAlloc(IBlockDevice* dev, unsigned start, unsigned len);
|
|
void _eject(int lengthHint);
|
|
};
|
|
|
|
#endif
|