|
|
//+--------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1992.
//
// File: dfbasis.cxx
//
// Contents: Docfile basis implementation
//
// History: 28-Jul-92 DrewB Created
//
//---------------------------------------------------------------
#include <dfhead.cxx>
#pragma hdrstop
#include <sstream.hxx>
#include <ole.hxx>
#include <entry.hxx>
#include <smalloc.hxx>
#include <lock.hxx>
size_t CDFBasis::_aReserveSize[CDFB_CLASSCOUNT] = { sizeof(CDocFile), sizeof(CDirectStream), sizeof(CWrappedDocFile), sizeof(CTransactedStream) };
//+--------------------------------------------------------------
//
// Member: CDFBasis::Release, public
//
// Synopsis: Decrease reference count and free memory
//
// History: 02-Mar-92 DrewB Created
// 24-Jul-95 SusiA Take mutex prior to delete
//
//---------------------------------------------------------------
#ifdef CODESEGMENTS
#pragma code_seg(SEG_CDFBasis_vRelease)
#endif
void CDFBasis::vRelease(void) { LONG lRet; olDebugOut((DEB_ITRACE, "In CDFBasis::Release()\n")); olAssert(_cReferences > 0); lRet = InterlockedDecrement(&_cReferences); if (lRet == 0) { #if !defined(MULTIHEAP)
//take the mutex here instead of in the allocator.
g_smAllocator.GetMutex()->Take(DFM_TIMEOUT); #endif
delete this; #if !defined(MULTIHEAP)
g_smAllocator.GetMutex()->Release(); #endif
} olDebugOut((DEB_ITRACE, "Out CDFBasis::Release()\n")); }
#ifdef DIRECTWRITERLOCK
//+--------------------------------------------------------------
//
// Member: CDFBasis::TryReadLocks, public
//
// Synopsis: attempts to obtain read locks
//
// Arguments: [ulOpenLock] - lock index for this open docfile
// [ulMask] - range lock mask
//
// History: 30-Apr-96 HenryLee Created
//
// Notes: tree mutex and update lock must be taken
//
//---------------------------------------------------------------
HRESULT CDFBasis::TryReadLocks (CGlobalContext *pgc, ULONG ulMask) { HRESULT sc = S_OK; ULARGE_INTEGER cbLength = {0,0}; ULARGE_INTEGER ulOffset = {0,0}; ILockBytes *plst = GetBase();
olAssert (pgc != NULL);
ULISetLow(cbLength, COPENLOCKS); ULISetLow(ulOffset, ODIRECTWRITERLOCK & ulMask); olChk(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE)); olVerSucc(plst->UnlockRegion(ulOffset,cbLength,LOCK_ONLYONCE));
EH_Err: return sc; }
//+--------------------------------------------------------------
//
// Member: CDFBasis::WaitForWriteAccess, public
//
// Synopsis: attempts to obtain write access
//
// Arguments: [dwTimeout] - in milliseconds
// [ulOpenLock] - lock index for this open docfile
//
// History: 30-Apr-96 HenryLee Created
//
// Notes: tree mutex must be taken
//
//---------------------------------------------------------------
HRESULT CDFBasis::WaitForWriteAccess (DWORD dwTimeout, CGlobalContext *pgc) { olDebugOut((DEB_ITRACE,"In CDFBasis::WaitForWriteAccess(%d)\n",dwTimeout));
HRESULT sc = S_OK; BOOL fUpdateLocked = FALSE; BOOL fDenyLocked = FALSE; ULARGE_INTEGER cbLength = {0,0}; ULARGE_INTEGER ulOffset = {0,0}; ILockBytes *plst = GetBase(); const ULONG ulMask = 0xFFFFFFFF;
// lock out other opens
ULISetLow(ulOffset, OUPDATE & ulMask); ULISetLow(cbLength, 1); olChk(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE)); fUpdateLocked = TRUE;
// lock out future readers
ULISetLow(ulOffset, OOPENDENYREADLOCK & ulMask); ULISetLow(cbLength, COPENLOCKS); olChk(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE)); fDenyLocked = TRUE;
// try to identify current readers
sc = TryReadLocks (pgc, ulMask);
if (sc == STG_E_LOCKVIOLATION && dwTimeout != 0) { const DWORD dwWaitInitial = 100; DWORD dwWait = dwWaitInitial, dwWaitTotal = 0; for (;;) { sc = TryReadLocks (pgc, ulMask); if (sc != STG_E_LOCKVIOLATION || dwWaitTotal >= dwTimeout) { break; } Sleep(dwWait); dwWaitTotal += dwWait; dwWait *= 2; } }
EH_Err: if (fDenyLocked && !SUCCEEDED(sc))
{ ULISetLow(ulOffset, OOPENDENYREADLOCK & ulMask); ULISetLow(cbLength, COPENLOCKS); olVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE)); }
if (fUpdateLocked) { ULISetLow(ulOffset, OUPDATE & ulMask); ULISetLow(cbLength, 1); olVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE)); }
if (sc == STG_E_LOCKVIOLATION) sc = STG_E_INUSE; if (SUCCEEDED(sc)) _fWriteLocked = TRUE;
olDebugOut((DEB_ITRACE,"Out CDFBasis::WaitForWriteAccess(%x)\n", sc)); return sc; };
//+--------------------------------------------------------------
//
// Member: CDFBasis::ReleaseWriteAccess, public
//
// Synopsis: relinquishes write access
// releases all locks except for ulOpenLock
//
// History: 30-Apr-96 HenryLee Created
//
// Notes: tree mutex must be taken
//
//---------------------------------------------------------------
HRESULT CDFBasis::ReleaseWriteAccess () { olDebugOut((DEB_ITRACE,"In CDFBasis::ReleaseWriteAccess()\n"));
HRESULT sc = S_OK; BOOL fUpdateLocked = FALSE; ULARGE_INTEGER cbLength = {0,0}; ULARGE_INTEGER ulOffset = {0,0}; const ULONG ulMask = 0xFFFFFFFF; ILockBytes *plst = GetBase();
// lock out other opens
ULISetLow(ulOffset, OUPDATE & ulMask); ULISetLow(cbLength, 1); olChk(plst->LockRegion(ulOffset, cbLength, LOCK_ONLYONCE)); fUpdateLocked = TRUE;
// undo WaitForWriteAccess
ULISetLow(ulOffset, OOPENDENYREADLOCK & ulMask); ULISetLow(cbLength, COPENLOCKS); olChk(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE));
EH_Err: if (fUpdateLocked) { ULISetLow(ulOffset, OUPDATE & ulMask); ULISetLow(cbLength, 1); olVerSucc(plst->UnlockRegion(ulOffset, cbLength, LOCK_ONLYONCE)); }
if (SUCCEEDED(sc)) _fWriteLocked = FALSE;
olDebugOut((DEB_ITRACE,"Out CDFBasis::ReleaseWriteAccess(%x)\n", sc)); return sc; }; #endif
|