📄 pagetext.cpp
字号:
template <class T> class POPointer {
public:
POPointer( T* obj=0 ) : offset( obj ? obj->GetOffset() : -1 ) {}
const POPointer<T>& operator=( const POPointer<T>&b ) const
{ offset = b.offset; return *this;}
operator bool() const { return offset != -1; }
const T* operator ->() const { return GetConst(); }
T* operator ->() { return Get(); }
void Delete() const
{ if(*this) delete const_cast<POPointer<T>& >(*this).Get(); }
private:
const T* GetConst() const {
return (const T*)PagedObject::File.GetConstObject( offset );
}
T* Get() {
return (T*)PagedObject::File.GetObject( offset );
}
mutable int offset;
};
class PagedObject {
public:
int GetOffset() { return offset; }
private:
void SetOffset( int i ) { offset=i; }
int offset;
public:
static PageFile& File;
};
void* PagedObject::operator new( unsigned int size )
{
ASSERT( size <= File.PageSize() );
return File.NewPage()->GetObject();
}
void PagedObject::operator delete( void* item )
{
PageFrame* pf = File.FindPageFor(((PagedObject*)item)->GetOffset());
File.DeletePage( pf );
}
class PageFrame
A single page of 'real memory', representing the page of virtual memory starting at StartOffset()
{
public:
const PagedObject* GetConstObject() {
return m_Object;
}
PagedObject* GetObject() {
m_Dirty = true;
return const_cast<PagedObject*> (GetConstObject());
}
int StartOffset() { return m_Offset; }
private:
bool m_Dirty; // Set if the page has been written
int m_Offset; // Equal to m_Object->GetOffset() only
// when page is loaded
PagedObject* m_Object;
};
class PageFile
A buffer which holds only a fixed portion of itself in RAM, and pages
the remainder to and from a temporary file on secondary storage.
{
public:
int PageSize() { return m_PageSize; }
const PagedObject* GetConstObject(int offset)
{ return FindPageFor( offset )->GetConstObject(); }
PagedObject* GetObject(int offset)
{ return FindPageFor( offset )->GetObject(); }
private:
// Utility functions to read and write bytes to file:
void Read( char* buffer, int offset, int nBytes );
void Write( char* buffer, int offset, int nBytes );
vector<PageFrame*> m_PageTable;
// Entry for each virtual memory page, Null if not loaded, indexed
// by (fileOffset/PageSize)
list<PageFrame*> m_PageFrames;
// Entry for each 'real memory' page; max m_PageCacheSize entries.
int m_PageSize;
int m_PageCacheSize;
fstream m_File;
list<int> m_FreeList; // List of file offsets
};
PageFrame* PageFile::NewPage() {
Create a new object, either from the free queue or by adding a new entry to page table
PageFrame* pf;
if (!m_FreeList.empty())
{
int offset=m_FreeList.front();
m_FreeList.pop_front();
pf=FindPageFor( offset );
}
else
{
pf = MakeFrameAvailable();
pf->m_Offset = m_PageTable.size() * m_PageSize;
pf->m_Object->SetOffset( pf->m_Offset );
m_PageTable.insert( m_PageTable.end(), pf );
pf->Save( *this ); // Need to ensure the file is big enough for random access
}
pf->m_Dirty = true;
return pf;
}
void PageFile::DeletePage( PageFrame* pf )
{
m_FreeList.push_front( pf->StartOffset() );
}
PageFrame* PageFile::FindPageFor( int offset )
Finds a real memory page corresponding to the given virtual offset. If it's already cached, returns it, otherwise co-opts the LRU and loads the page from disk.
{
int pageNumber = offset / m_PageSize;
PageFrame* frame = m_PageTable[pageNumber];
if (frame == 0)
{
frame = MakeFrameAvailable();
frame->Load( *this, offset );
m_PageTable[pageNumber] = frame;
}
else
FrameUsed( frame );
return frame;
}
void PageFile::FrameUsed( PageFrame* pf )
{
m_PageFrames.remove( pf );
m_PageFrames.push_back( pf );
}
PageFrame* PageFile::MakeFrameAvailable()
{
PageFrame* pf;
if (m_PageFrames.size() < m_PageCacheSize)
{
pf = new PageFrame( m_PageSize );
m_PageFrames.push_back( pf );
}
else
{
pf = m_PageFrames.front();
FrameUsed( pf );
pf->Save( *this );
m_PageTable[pf->StartOffset()/m_PageSize] = 0;
}
return pf;
}
PageFrame::PageFrame( int pageSize )
: m_Object( (PagedObject*)(new char[pageSize]) ),
m_Dirty( false )
{}
void PageFrame::Load( PageFile& file, int fileOffset )
// Make me be the virtual memory page corresponding to fileOffset
{
(void)file.Read( (char*)m_Object, fileOffset,
file.PageSize() );
m_Offset = fileOffset;
}
void PageFrame::Save( PageFile& file )
{
if (m_Dirty)
file.Write( (char*)m_Object, m_Object->GetOffset(), file.PageSize() );
m_Dirty = false;
}
class MyObject : public PagedObject {
public:
typedef POPointer<MyObject> Ptr;
MyObject( Ptr p );
: next( p ) {}
~MyObject()
{
const Ptr self = this;
self->next.Delete();
}
Ptr next;
};
PageFile& PagedObject::File = *new PageFile( sizeof( MyObject ), 4 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -