717 lines
18 KiB
C++
717 lines
18 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1992.
|
|
//
|
|
// File: page.hxx
|
|
//
|
|
// Contents: Paging classes for MSF
|
|
//
|
|
// Classes: CMSFPage
|
|
// CMSFPageTable
|
|
//
|
|
// Functions:
|
|
//
|
|
// History: 28-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#ifndef __PAGE_HXX__
|
|
#define __PAGE_HXX__
|
|
|
|
class CPagedVector;
|
|
|
|
#define STG_S_NEWPAGE \
|
|
MAKE_SCODE(SEVERITY_SUCCESS, FACILITY_STORAGE, 0x2FF)
|
|
|
|
#define FB_NONE 0x00000000
|
|
#define FB_DIRTY 0x00000001
|
|
#define FB_NEW 0x00000002
|
|
#define FB_TOUCHED 0x10000000
|
|
|
|
class CMSFPageTable;
|
|
class CMSFPage;
|
|
|
|
SAFE_DFBASED_PTR(CBasedPagedVectorPtr, CPagedVector);
|
|
SAFE_DFBASED_PTR(CBasedMSFPageTablePtr, CMSFPageTable);
|
|
SAFE_DFBASED_PTR(CBasedMSFPagePtr, CMSFPage);
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CMSFPage (mp)
|
|
//
|
|
// Purpose: Contain MSF data in a form that is swappable to disk
|
|
//
|
|
// Interface: See below.
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#if _MSC_VER == 700
|
|
#pragma warning(disable:4001)
|
|
#elif _MSC_VER >= 800
|
|
#pragma warning(disable:4200)
|
|
#endif
|
|
|
|
class CMSFPage : public CMallocBased
|
|
{
|
|
public:
|
|
void * operator new(size_t size, IMalloc * const pMalloc,
|
|
size_t sizeData);
|
|
|
|
#if DBG == 1
|
|
CMSFPage(CMSFPage *pmpNext, CMSFPageTable *pmpt);
|
|
#else
|
|
CMSFPage(CMSFPage *pmpNext);
|
|
#endif
|
|
|
|
inline ~CMSFPage();
|
|
|
|
inline void AddRef(void);
|
|
inline void Release(void);
|
|
|
|
inline CMSFPage *GetNext(void) const;
|
|
inline CMSFPage *GetPrev(void) const;
|
|
inline SID GetSid(void) const;
|
|
inline ULONG GetOffset(void) const;
|
|
inline SECT GetSect(void) const;
|
|
inline void *GetData(void) const;
|
|
inline DWORD GetFlags(void) const;
|
|
inline CPagedVector * GetVector(void) const;
|
|
|
|
inline void Remove(void);
|
|
|
|
inline void SetChain(CMSFPage *const pmpPrev,
|
|
CMSFPage *const pmpNext);
|
|
inline void SetPrev(CMSFPage *const pmpPrev);
|
|
inline void SetNext(CMSFPage *const pmpNext);
|
|
|
|
inline void SetSid(const SID sid);
|
|
inline void SetOffset(const ULONG ulOffset);
|
|
#ifndef SORTPAGETABLE
|
|
inline void SetSect(const SECT sect);
|
|
#endif
|
|
inline void SetFlags(const DWORD dwFlags);
|
|
inline void SetVector(CPagedVector *ppv);
|
|
|
|
inline void SetDirty(void);
|
|
inline void ResetDirty(void);
|
|
inline BOOL IsDirty(void) const;
|
|
|
|
inline BOOL IsInUse(void) const;
|
|
inline BOOL IsFlushable(void) const;
|
|
private:
|
|
#ifdef SORTPAGETABLE
|
|
friend CMSFPageTable;
|
|
inline void SetSect(const SECT sect);
|
|
#endif
|
|
|
|
CBasedMSFPagePtr _pmpNext;
|
|
CBasedMSFPagePtr _pmpPrev;
|
|
|
|
#if DBG == 1
|
|
CBasedMSFPageTablePtr _pmpt;
|
|
#endif
|
|
|
|
SID _sid;
|
|
ULONG _ulOffset;
|
|
CBasedPagedVectorPtr _ppv;
|
|
SECT _sect;
|
|
DWORD _dwFlags;
|
|
LONG _cReferences;
|
|
#if DBG == 1 || defined(_WIN64)
|
|
ULONGLONG ulPadding; // alignment for unbuffered I/O and IA64
|
|
#endif
|
|
BYTE _ab[];
|
|
};
|
|
SAFE_DFBASED_PTR(CBasedMSFPagePtrPtr, CBasedMSFPagePtr);
|
|
|
|
#if _MSC_VER == 700
|
|
#pragma warning(default:4001)
|
|
#elif _MSC_VER >= 800
|
|
#pragma warning(default:4200)
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::~CMSFPage, public
|
|
//
|
|
// Synopsis: Destructor
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline CMSFPage::~CMSFPage()
|
|
{
|
|
msfAssert(_cReferences == 0);
|
|
|
|
Remove();
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::Remove, public
|
|
//
|
|
// Synopsis: Remove page from list
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CMSFPage::Remove(void)
|
|
{
|
|
//Avoid using SetNext and SetPrev so we don't need to unbase and
|
|
// then rebase everything.
|
|
|
|
_pmpPrev->_pmpNext = _pmpNext;
|
|
_pmpNext->_pmpPrev = _pmpPrev;
|
|
|
|
_pmpNext = _pmpPrev = NULL;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::operator new, public
|
|
//
|
|
// Synopsis: Overloaded new operator for CMSFPage.
|
|
//
|
|
// Arguments: [size] -- Default size field
|
|
// [pMalloc] -- Allocator
|
|
// [sizeData] -- Size of byte array to allocate.
|
|
//
|
|
// Returns: Pointer to new CMSFPage object
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
// 21-May-93 AlexT Added allocator
|
|
//
|
|
// Notes: *Finish This*
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void * CMSFPage::operator new(size_t size, IMalloc * const pMalloc,
|
|
size_t sizeData)
|
|
{
|
|
msfAssert(size == sizeof(CMSFPage));
|
|
|
|
return(CMallocBased::operator new(sizeData + sizeof(CMSFPage), pMalloc));
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::GetNext, public
|
|
//
|
|
// Synopsis: Returns the next page in the list
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline CMSFPage * CMSFPage::GetNext(void) const
|
|
{
|
|
return BP_TO_P(CMSFPage *, _pmpNext);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::GetPrev, public
|
|
//
|
|
// Synopsis: Returns the next page in the list
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline CMSFPage * CMSFPage::GetPrev(void) const
|
|
{
|
|
return BP_TO_P(CMSFPage *, _pmpPrev);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::GetSid, public
|
|
//
|
|
// Synopsis: Returns the SID for this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline SID CMSFPage::GetSid(void) const
|
|
{
|
|
return _sid;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::GetOffset, public
|
|
//
|
|
// Synopsis: Returns the array offset for this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline ULONG CMSFPage::GetOffset(void) const
|
|
{
|
|
return _ulOffset;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::GetSect, public
|
|
//
|
|
// Synopsis: Returns the SECT for this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline SECT CMSFPage::GetSect(void) const
|
|
{
|
|
return _sect;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::GetFlags, public
|
|
//
|
|
// Synopsis: Returns the flags for this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline DWORD CMSFPage::GetFlags(void) const
|
|
{
|
|
return _dwFlags;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::GetData, public
|
|
//
|
|
// Synopsis: Returns a pointer to the page storage for this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void * CMSFPage::GetData(void) const
|
|
{
|
|
return (void *) _ab;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::GetVector, public
|
|
//
|
|
// Synopsis: Returns a pointer to the vector holding this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline CPagedVector * CMSFPage::GetVector(void) const
|
|
{
|
|
return BP_TO_P(CPagedVector *, _ppv);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::SetChain, public
|
|
//
|
|
// Synopsis: Sets the chain pointers for this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CMSFPage::SetChain(
|
|
CMSFPage *const pmpPrev,
|
|
CMSFPage *const pmpNext)
|
|
{
|
|
_pmpPrev = P_TO_BP(CBasedMSFPagePtr, pmpPrev);
|
|
_pmpNext = P_TO_BP(CBasedMSFPagePtr, pmpNext);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::SetPrev, public
|
|
//
|
|
// Synopsis: Sets the prev pointer for this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CMSFPage::SetPrev(CMSFPage *const pmpPrev)
|
|
{
|
|
_pmpPrev = P_TO_BP(CBasedMSFPagePtr, pmpPrev);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::SetNext, public
|
|
//
|
|
// Synopsis: Sets the next pointer for this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CMSFPage::SetNext(CMSFPage *const pmpNext)
|
|
{
|
|
_pmpNext = P_TO_BP(CBasedMSFPagePtr, pmpNext);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::SetSid, public
|
|
//
|
|
// Synopsis: Sets the SID for this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CMSFPage::SetSid(const SID sid)
|
|
{
|
|
_sid = sid;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::SetOffset, public
|
|
//
|
|
// Synopsis: Sets the offset for this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CMSFPage::SetOffset(const ULONG ulOffset)
|
|
{
|
|
_ulOffset = ulOffset;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::SetSect, public
|
|
//
|
|
// Synopsis: Sets the SECT for this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#ifndef SORTPAGETABLE
|
|
inline void CMSFPage::SetSect(const SECT sect)
|
|
{
|
|
_sect = sect;
|
|
}
|
|
#endif
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::SetFlags, public
|
|
//
|
|
// Synopsis: Sets the flags for this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CMSFPage::SetFlags(const DWORD dwFlags)
|
|
{
|
|
_dwFlags = dwFlags;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::SetVector, public
|
|
//
|
|
// Synopsis: Sets the pointer to the vector holding this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CMSFPage::SetVector(CPagedVector *ppv)
|
|
{
|
|
_ppv = P_TO_BP(CBasedPagedVectorPtr, ppv);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::SetDirty, public
|
|
//
|
|
// Synopsis: Sets the dirty bit for this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CMSFPage::SetDirty(void)
|
|
{
|
|
_dwFlags = _dwFlags | FB_DIRTY;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::ResetDirty, public
|
|
//
|
|
// Synopsis: Resets the dirty bit for this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CMSFPage::ResetDirty(void)
|
|
{
|
|
_dwFlags = _dwFlags & ~FB_DIRTY;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::IsDirty, public
|
|
//
|
|
// Synopsis: Returns TRUE if the dirty bit is set on this page
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline BOOL CMSFPage::IsDirty(void) const
|
|
{
|
|
return (_dwFlags & FB_DIRTY) != 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::IsInUse, public
|
|
//
|
|
// Synopsis: Returns TRUE if the page is currently in use
|
|
//
|
|
// History: 05-Nov-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline BOOL CMSFPage::IsInUse(void) const
|
|
{
|
|
return (_cReferences != 0);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::IsFlushable, public
|
|
//
|
|
// Synopsis: Returns TRUE if the page can be flushed to disk
|
|
//
|
|
// History: 05-Nov-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline BOOL CMSFPage::IsFlushable(void) const
|
|
{
|
|
return (IsDirty() && !IsInUse());
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Class: CMSFPageTable
|
|
//
|
|
// Purpose: Page allocator and handler for MSF
|
|
//
|
|
// Interface: See below
|
|
//
|
|
// History: 20-Oct-92 PhilipLa Created
|
|
//
|
|
// Notes:
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
class CMSFPageTable : public CMallocBased
|
|
{
|
|
public:
|
|
CMSFPageTable(
|
|
CMStream *const pmsParent,
|
|
const ULONG _cMinPages,
|
|
const ULONG _cMaxPages);
|
|
~CMSFPageTable();
|
|
|
|
inline void AddRef();
|
|
inline void Release();
|
|
|
|
SCODE Init(void);
|
|
SCODE GetPage(
|
|
CPagedVector *ppv,
|
|
SID sid,
|
|
ULONG ulOffset,
|
|
SECT sectKnown,
|
|
CMSFPage **ppmp);
|
|
|
|
SCODE CopyPage(
|
|
CPagedVector *ppv,
|
|
CMSFPage *pmpOld,
|
|
CBasedMSFPagePtr *ppmp);
|
|
|
|
SCODE FindPage(
|
|
CPagedVector *ppv,
|
|
SID sid,
|
|
ULONG ulOffset,
|
|
CMSFPage **ppmp);
|
|
|
|
SCODE GetFreePage(CMSFPage **ppmp);
|
|
|
|
void ReleasePage(CPagedVector *ppv, SID sid, ULONG ulOffset);
|
|
|
|
void FreePages(CPagedVector *ppv);
|
|
|
|
#ifdef SORTPAGETABLE
|
|
void SetSect(CMSFPage *pmp, SECT sect);
|
|
#endif
|
|
|
|
SCODE Flush(void);
|
|
SCODE FlushPage(CMSFPage *pmp);
|
|
|
|
inline void SetParent(CMStream *pms);
|
|
|
|
#if DBG == 1
|
|
void AddPageRef(void);
|
|
void ReleasePageRef(void);
|
|
#endif
|
|
|
|
private:
|
|
inline CMSFPage * GetNewPage(void);
|
|
CMSFPage * FindSwapPage(void);
|
|
|
|
CBasedMStreamPtr _pmsParent;
|
|
const ULONG _cbSector;
|
|
const ULONG _cMinPages;
|
|
const ULONG _cMaxPages;
|
|
|
|
ULONG _cActivePages;
|
|
ULONG _cPages;
|
|
CBasedMSFPagePtr _pmpCurrent;
|
|
#ifdef SORTPAGETABLE
|
|
CBasedMSFPagePtr _pmpStart;
|
|
inline BOOL IsSorted(CMSFPage *pmp);
|
|
#endif
|
|
|
|
LONG _cReferences;
|
|
|
|
#if DBG == 1
|
|
ULONG _cCurrentPageRef;
|
|
ULONG _cMaxPageRef;
|
|
#endif
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::AddRef, public
|
|
//
|
|
// Synopsis: Increment the reference count
|
|
//
|
|
// History: 28-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CMSFPage::AddRef(void)
|
|
{
|
|
msfAssert(_cReferences >= 0);
|
|
#if DBG == 1
|
|
if (_cReferences == 0)
|
|
{
|
|
_pmpt->AddPageRef();
|
|
}
|
|
#endif
|
|
AtomicInc(&_cReferences);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPage::Release, public
|
|
//
|
|
// Synopsis: Decrement the reference count
|
|
//
|
|
// History: 28-Oct-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CMSFPage::Release(void)
|
|
{
|
|
LONG lRet;
|
|
|
|
msfAssert(_cReferences > 0);
|
|
lRet = AtomicDec(&_cReferences);
|
|
#if DBG == 1
|
|
if (lRet == 0)
|
|
{
|
|
_pmpt->ReleasePageRef();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPageTable::AddRef, public
|
|
//
|
|
// Synopsis: Increment the ref coutn
|
|
//
|
|
// History: 05-Nov-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CMSFPageTable::AddRef(void)
|
|
{
|
|
AtomicInc(&_cReferences);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPageTable::Release, public
|
|
//
|
|
// Synopsis: Decrement the ref count, delete if necessary
|
|
//
|
|
// History: 05-Nov-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CMSFPageTable::Release(void)
|
|
{
|
|
LONG lRet;
|
|
|
|
msfAssert(_cReferences > 0);
|
|
lRet = AtomicDec(&_cReferences);
|
|
if (lRet == 0)
|
|
{
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CMSFPageTable::SetParent, public
|
|
//
|
|
// Synopsis: Set the parent of this page table
|
|
//
|
|
// Arguments: [pms] -- Pointer to new parent
|
|
//
|
|
// History: 05-Nov-92 PhilipLa Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
inline void CMSFPageTable::SetParent(CMStream *pms)
|
|
{
|
|
_pmsParent = P_TO_BP(CBasedMStreamPtr, pms);
|
|
}
|
|
|
|
|
|
#endif // #ifndef __PAGE_HXX__
|