⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pagetext.cpp

📁 内存受限系统软件开发一书的代码。(虽不及Gang of Four的模式掷地有声
💻 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 + -