|
From: Paul S. <psn...@us...> - 2004-03-28 22:25:13
|
Update of /cvsroot/whisper2/Whisper/Source/BackEnd/Files/Source/Files/Mac In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv19418/Source/BackEnd/Files/Source/Files/Mac Modified Files: MMemoryMappedFile.cpp Log Message: Minor code fixes to build on both Mac and Win32 again; fixes to project files to not cache like mad order things so precompiled headers work again. Index: MMemoryMappedFile.cpp =================================================================== RCS file: /cvsroot/whisper2/Whisper/Source/BackEnd/Files/Source/Files/Mac/MMemoryMappedFile.cpp,v retrieving revision 1.7 retrieving revision 1.8 diff -C2 -d -r1.7 -r1.8 *** MMemoryMappedFile.cpp 15 Aug 2003 09:53:49 -0000 1.7 --- MMemoryMappedFile.cpp 28 Mar 2004 22:13:16 -0000 1.8 *************** *** 1,547 **** ! /* ! * File: MMemoryMappedFile.cpp ! * Summary: A class that allows a file to be efficiently treated as a bag'o'bits. ! * Written by: Jesse Jones ! * ! * Copyright © 1999-2001 Jesse Jones. ! * This code is distributed under the zlib/libpng license (see License.txt for details). ! * ! * Change History (most recent first): ! * ! * $Log$ ! * Revision 1.7 2003/08/15 09:53:49 meeroh ! * Macro changes: ! * MAC -> TARGET_OS_MAC ! * WIN -> TARGET_OS_WIN32 ! * TARGET_CARBON -> TARGET_API_MAC_CARBON ! * BIG_ENDIAN -> TARGET_RT_BIG_ENDIAN ! * !BIG_ENDIAN -> TARGET_RT_LITTLE_ENDIAN ! * CODE_WARRIOR -> TARGET_CC_METROWERKS ! * __MWERKS__ -> TARGET_CC_METROWERKS ! * MSVC -> TARGET_CC_MICROSOFT ! * _MSC_VER -> TARGET_CC_MICROSOFT ! * #pragma mark ~ -> #pragma mark - ! * Added #ifdef PRAGMA_MARK ! * ! * Revision 1.6 2003/08/14 06:00:21 meeroh ! * Replaced FSSpecs with CFURLs/FSRefs ! * ! * Revision 1.5 2001/04/21 03:26:52 jesjones ! * Updated for the new debug macros. ! * ! * Revision 1.4 2001/04/17 01:41:09 jesjones ! * Got rid of XInvariantMixin. ! * ! * Revision 1.3 2000/12/10 04:04:14 jesjones ! * Replaced int16_cast, uint32_cast, etc with numeric_cast. ! * ! * Revision 1.2 2000/11/09 09:15:45 jesjones ! * 1) Removed double CRs introduced during the initial checkin. 2) Changed the header comments to make it clearer that Whisper is using the zlib license agreement. 3) Added the Log keyword. ! */ ! ! #include <XWhisperHeader.h> ! #include <XMemoryMappedFile.h> ! ! #include <XError.h> ! #include <XExceptions.h> ! #include <XIntConversions.h> ! #include <XLocker.h> ! #include <XNumbers.h> ! #include <XStringUtils.h> ! ! namespace Whisper { ! ! ! //----------------------------------- ! // Constants ! // ! #if DEBUG ! const uint32 kTail = 'Tail'; ! const uint32 kTailSize = sizeof(kTail); ! #else ! const uint32 kTailSize = 0; ! #endif ! ! ! // =================================================================================== ! // Internal Functions ! // =================================================================================== ! ! //--------------------------------------------------------------- ! // ! // ThrowFileErr ! // ! //--------------------------------------------------------------- ! static void ThrowFileErr(const XFileSpec& spec, OSStatus err) ! { ! switch (err) { ! case dirFulErr: ! case dskFulErr: ! case nsvErr: ! case ioErr: ! case fnOpnErr: ! case eofErr: ! case posErr: ! case mFulErr: ! case tmfoErr: ! case fnfErr: ! case wPrErr: ! case fLckdErr: ! ! case vLckdErr: ! case fBsyErr: ! case dupFNErr: ! case opWrErr: ! case rfNumErr: ! case gfpErr: ! case volOffLinErr: ! case permErr: ! case volOnLinErr: ! case nsDrvErr: ! case noMacDskErr: ! case wrPermErr: ! case dirNFErr: ! case tmwdoErr: ! case volGoneErr: ! { ! #if DEBUG ! std::wstring mesg = XError::Instance()->GetText(err) + L" with file " + spec.GetName(); ! #else ! std::wstring mesg = LoadWhisperString(L"File error ##1 (with file '#2')", Int32ToStr(err), spec.GetName()); ! #endif ! throw std::runtime_error(ToUTF8Str(mesg)); ! } ! break; ! ! default: ! ThrowErr(err); ! } ! } ! ! ! //--------------------------------------------------------------- ! // ! // ThrowIfFileErr ! // ! //--------------------------------------------------------------- ! inline void ThrowIfFileErr(const XFileSpec& spec, OSStatus err) ! { ! if (err != noErr) ! ThrowFileErr(spec, err); ! } ! ! #pragma mark - ! ! // =================================================================================== ! // class XMemoryMappedFile ! // =================================================================================== ! ! //--------------------------------------------------------------- ! // ! // XMemoryMappedFile::~XMemoryMappedFile ! // ! //--------------------------------------------------------------- ! XMemoryMappedFile::~XMemoryMappedFile() ! { ! PRECONDITION(!this->IsOpened()); // in the normal course of events you should explicitly close the file ! CALL_INVARIANT; ! ! if (this->IsOpened()) { // but if an exception was thrown the file may still be open ! try { ! if (mWriting && mData != nil) ! this->Flush(); ! ! mFile.Close(); // if so, we need to close the file (and attempt to save any changes) ! ! } catch (...) { ! // can't throw from dtor ! } ! } ! ! if (mData != nil) ! DisposeHandle(mData); ! } ! ! ! //--------------------------------------------------------------- ! // ! // XMemoryMappedFile::XMemoryMappedFile (XFileSpec) ! // ! //--------------------------------------------------------------- ! XMemoryMappedFile::XMemoryMappedFile(const XFileSpec& file) : mFile(file) ! { ! // mRefNum = kNoFileRefNum; ! ! mReading = false; ! mWriting = false; ! ! mData = nil; ! mMaxBytes = 0; ! mPurgable = true; ! ! CALL_INVARIANT; ! } ! ! ! //--------------------------------------------------------------- ! // ! // XMemoryMappedFile::XMemoryMappedFile (XFolderSpec, wstring) ! // ! //--------------------------------------------------------------- ! XMemoryMappedFile::XMemoryMappedFile(const XFolderSpec& folder, const std::wstring& name) : mFile(folder, name) ! { ! // mRefNum = kNoFileRefNum; ! ! mReading = false; ! mWriting = false; ! ! mData = nil; ! mMaxBytes = 0; ! mPurgable = true; ! ! CALL_INVARIANT; ! } ! ! ! //--------------------------------------------------------------- ! // ! // XMemoryMappedFile::Open (EFilePermission, uint32) ! // ! //--------------------------------------------------------------- ! void XMemoryMappedFile::Open(EFilePermission perm, uint32 maxBytes) ! { ! PRECONDITION(!this->IsOpened()); ! PRECONDITION(mData == nil); ! CHECK_INVARIANT; ! ! int16 tempRef = kNoFileRefNum; ! mMaxBytes = maxBytes; ! ! // Open the file ! mFile.Open(perm); ! // OSErr err = ::FSOpenFork(&mSpec.GetFSRef(), 0, nil, perm, &tempRef); ! // ThrowIfFileErr(mSpec, err); ! ! // Initialize maxBytes if the user hasn't specified a value ! if (mMaxBytes == 0) { ! // int64 bytes; ! // err = ::FSGetForkSize(tempRef, &bytes); ! // ThrowIfFileErr(mSpec, err); ! ! // mMaxBytes = numeric_cast<uint32>(bytes); ! mMaxBytes = mFile.GetLength(); ! } ! ! // Set some member variables ! // mRefNum = tempRef; ! mReading = perm == kReadPermission || perm == kReadWritePermission; ! mWriting = perm == kWritePermission || perm == kReadWritePermission; ! ! POSTCONDITION(this->IsOpened()); ! } ! ! ! //--------------------------------------------------------------- ! // ! // XMemoryMappedFile::Open (OSType, OSType, EFilePermission, uint32) ! // ! //--------------------------------------------------------------- ! void XMemoryMappedFile::Open(OSType creator, OSType fileType, EFilePermission perm, uint32 maxBytes) ! { ! PRECONDITION(!this->IsOpened()); ! PRECONDITION(mData == nil); ! CHECK_INVARIANT; ! ! int16 tempRef = kNoFileRefNum; ! mMaxBytes = maxBytes; ! ! // Open the file ! mFile.Open(creator, fileType, perm); ! ! // Initialize maxBytes if the user hasn't specified a value ! if (mMaxBytes == 0) { ! // int64 bytes; ! // err = ::FSGetForkSize(tempRef, &bytes); ! // ThrowIfFileErr(mSpec, err); ! ! // mMaxBytes = numeric_cast<uint32>(bytes); ! mMaxBytes = mFile.GetLength(); ! } ! ! // Set some member variables ! // mRefNum = tempRef; ! mReading = perm == kReadPermission || perm == kReadWritePermission; ! mWriting = perm == kWritePermission || perm == kReadWritePermission; ! ! POSTCONDITION(this->IsOpened()); ! } ! ! ! //--------------------------------------------------------------- ! // ! // XMemoryMappedFile::Close () ! // ! //--------------------------------------------------------------- ! void XMemoryMappedFile::Close() ! { ! PRECONDITION(this->IsOpened()); ! CHECK_INVARIANT; ! ! try { ! if (mWriting && mData != nil) ! this->Flush(); ! ! mFile.Close(); // File Manager buffers data and flushes on close so an error is quite possible ! // OSErr err = FSClose(mRefNum); ! // ThrowIfFileErr(mSpec, err); // File Manager buffers data and flushes on close so an error is quite possible ! ! if (mData != nil) { ! DisposeHandle(mData); ! mData = nil; ! } ! ! // mRefNum = kNoFileRefNum; ! mReading = false; ! mWriting = false; ! ! } catch (...) { ! if (mData != nil) { ! DisposeHandle(mData); ! mData = nil; ! } ! ! // mRefNum = kNoFileRefNum; ! ! throw; ! } ! ! POSTCONDITION(!this->IsOpened()); ! } ! ! ! //--------------------------------------------------------------- ! // ! // XMemoryMappedFile::Close (uint32) ! // ! //--------------------------------------------------------------- ! void XMemoryMappedFile::Close(uint32 newSize) ! { ! PRECONDITION(mWriting); ! CHECK_INVARIANT; ! ! if (mData != nil && newSize != mMaxBytes) { // mData will only be nil if the file was never locked ! ASSERT(*mData != nil); ! ASSERT(newSize <= GetHandleSize(mData) - kTailSize); ! ! SetHandleSize(mData, newSize + kTailSize); ! ThrowIfMemError(); ! ! mMaxBytes = newSize; ! ! #if DEBUG ! uint32* tail = reinterpret_cast<uint32*>(*mData + mMaxBytes); ! *tail = kTail; ! #endif ! } ! ! this->Close(); ! ! POSTCONDITION(!this->IsOpened()); ! } ! ! ! //--------------------------------------------------------------- ! // ! // XMemoryMappedFile::IsOpened ! // ! //--------------------------------------------------------------- ! bool XMemoryMappedFile::IsOpened() const ! { ! return mFile.IsOpened(); ! // bool open = mRefNum != kNoFileRefNum; ! ! // return open; ! } ! ! ! //--------------------------------------------------------------- ! // ! // XMemoryMappedFile::GetBuffer ! // ! //--------------------------------------------------------------- ! uint8* XMemoryMappedFile::GetBuffer() ! { ! PRECONDITION(this->IsLocked()); ! PRECONDITION(mData != nil); ! PRECONDITION(*mData != nil); ! ! return (uint8*) *mData; ! } ! ! ! //--------------------------------------------------------------- ! // ! // XMemoryMappedFile::GetBufferSize ! // ! //--------------------------------------------------------------- ! uint32 XMemoryMappedFile::GetBufferSize() const ! { ! PRECONDITION(this->IsOpened()); // mMaxBytes is set via Open ! ! return mMaxBytes; ! } ! ! ! //--------------------------------------------------------------- ! // ! // XMemoryMappedFile::Flush ! // ! //--------------------------------------------------------------- ! void XMemoryMappedFile::Flush() ! { ! PRECONDITION(mWriting); ! PRECONDITION(this->IsOpened()); ! CHECK_INVARIANT; ! ! if (mData != nil) { // will only be nil if the file hasn't been locked yet ! ASSERT(*mData != nil); // writable files aren't purgeable ! ! mFile.Seek(kSeekFromStart, 0); ! // OSErr err = SetFPos(mRefNum, fsFromStart, 0); ! // ThrowIfFileErr(mSpec, err); ! ! uint32 bytes = GetHandleSize(mData) - kTailSize; ! ! { ! XLocker lock(this); ! mFile.Write(*mData,bytes); ! // err = FSWrite(mRefNum, &bytes, *mData); ! // ThrowIfFileErr(mSpec, err); ! } ! ! mFile.Trim(); ! // err = SetEOF(mRefNum, bytes); ! // ThrowIfFileErr(mSpec, err); ! } ! } ! ! ! //--------------------------------------------------------------- ! // ! // XMemoryMappedFile::EnablePurging ! // ! //--------------------------------------------------------------- ! void XMemoryMappedFile::EnablePurging(bool enable) ! { ! ASSERT_IF(enable, !mWriting); ! CHECK_INVARIANT; ! ! if (enable != mPurgable) { ! mPurgable = enable; ! ! if (mData != nil && *mData != nil) { ! if (mPurgable) ! HPurge(mData); // this will have no effect while the handle is locked ! else ! HNoPurge(mData); ! ThrowIfMemError(); ! } ! } ! ! POSTCONDITION(true); ! } ! ! #if PRAGMA_MARK ! #pragma mark Ê ! #endif ! ! //--------------------------------------------------------------- ! // ! // XMemoryMappedFile::Invariant ! // ! //--------------------------------------------------------------- ! void XMemoryMappedFile::Invariant() const ! { ! } ! ! ! //--------------------------------------------------------------- ! // ! // XMemoryMappedFile::OnLock ! // ! //--------------------------------------------------------------- ! void XMemoryMappedFile::OnLock(bool moveHigh) ! { ! PRECONDITION(this->IsOpened()); ! ! bool dirty = false; ! OSErr err = noErr; ! ! // Allocate (or re-allocate) the handle ! if (mData == nil) { ! mData = TempNewHandle(numeric_cast<int32>(mMaxBytes + kTailSize), &err); ! if (mData == nil) ! mData = NewHandle(mMaxBytes + kTailSize); ! ThrowIfMemFail(mData); ! ! dirty = true; ! ! } else if (*mData == nil) { ! ReallocateHandle(mData, numeric_cast<int32>(mMaxBytes + kTailSize)); ! ThrowIfMemError(); ! ! HNoPurge(mData); ! ThrowIfMemError(); ! ! dirty = true; ! } ! ! // Lock it ! if (moveHigh) ! HLockHi(mData); ! else ! HLock(mData); ! ThrowIfMemError(); ! ! // And read in the file as necessary ! if (dirty && mReading) { ! #if DEBUG ! uint32* tail = reinterpret_cast<uint32*>(*mData + mMaxBytes); ! *tail = kTail; ! #endif ! ! uint32 bytes = mFile.GetLength(); ! ! bytes = Min(bytes, mMaxBytes); ! ! mFile.Read(*mData, bytes); ! } ! } ! ! ! //--------------------------------------------------------------- ! // ! // XMemoryMappedFile::OnUnlock ! // ! //--------------------------------------------------------------- ! void XMemoryMappedFile::OnUnlock() ! { ! PRECONDITION(mData != nil); ! PRECONDITION(*mData != nil); ! ! #if DEBUG ! uint32* tail = reinterpret_cast<uint32*>(*mData + mMaxBytes); ! ASSERT(*tail == kTail); ! #endif ! ! HUnlock(mData); ! ThrowIfMemError(); ! ! if (mReading && !mWriting && mPurgable) { ! HPurge(mData); ! ThrowIfMemError(); ! } ! } ! ! ! } // namespace Whisper --- 1,4 ---- ! /* * File: MMemoryMappedFile.cpp * Summary: A class that allows a file to be efficiently treated as a bag'o'bits. * Written by: Jesse Jones * * Copyright © 1999-2001 Jesse Jones. * This code is distributed under the zlib/libpng license (see License.txt for details). * * Change History (most recent first): * * $Log$ ! /* * File: MMemoryMappedFile.cpp * Summary: A class that allows a file to be efficiently treated as a bag'o'bits. * Written by: Jesse Jones * * Copyright © 1999-2001 Jesse Jones. * This code is distributed under the zlib/libpng license (see License.txt for details). * * Change History (most recent first): * * Revision 1.8 2004/03/28 22:13:16 psnively ! /* * File: MMemoryMappedFile.cpp * Summary: A class that allows a file to be efficiently treated as a bag'o'bits. * Written by: Jesse Jones * * Copyright © 1999-2001 Jesse Jones. * This code is distributed under the zlib/libpng license (see License.txt for details). * * Change History (most recent first): * * Minor code fixes to build on both Mac and Win32 again; fixes to project files to not cache like mad order things so precompiled headers work again. ! /* * File: MMemoryMappedFile.cpp * Summary: A class that allows a file to be efficiently treated as a bag'o'bits. * Written by: Jesse Jones * * Copyright © 1999-2001 Jesse Jones. * This code is distributed under the zlib/libpng license (see License.txt for details). * * Change History (most recent first): * * * Revision 1.7 2003/08/15 09:53:49 meeroh * Macro changes: * MAC -> TARGET_OS_MAC * WIN -> TARGET_OS_WIN32 * TARGET_CARBON -> TARGET_API_MAC_CARBON * BIG_ENDIAN -> TARGET_RT_BIG_ENDIAN * !BIG_ENDIAN -> TARGET_RT_LITTLE_ENDIAN * CODE_WARRIOR -> TARGET_CC_METROWERKS * __MWERKS__ -> TARGET_CC_METROWERKS * MSVC -> TARGET_CC_MICROSOFT * _MSC_VER -> TARGET_CC_MICROSOFT * #pragma mark ~ -> #pragma mark - * Added #ifdef PRAGMA_MARK * * Revision 1.6 2003/08/14 06:00:21 meeroh * Replaced FSSpecs with CFURLs/FSRefs * * Revision 1.5 2001/04/21 03:26:52 jesjones * Updated for the new debug macros. * * Revision 1.4 2001/04/17 01:41:09 jesjones * Got rid of XInvariantMixin. * * Revision 1.3 2000/12/10 04:04:14 jesjones * Replaced int16_cast, uint32_cast, etc with numeric_cast. * * Revision 1.2 2000/11/09 09:15:45 jesjones * 1) Removed double CRs introduced during the initial checkin. 2) Changed the header comments to make it clearer that Whisper is using the zlib license agreement. 3) Added the Log keyword. */ #include <XWhisperHeader.h> #include <XMemoryMappedFile.h> #include <XError.h> #include <XExceptions.h> #include <XIntConversions.h> #include <XLocker.h> #include <XNumbers.h> #include <XStringUtils.h> namespace Whisper { //----------------------------------- // Constants // #if DEBUG const uint32 kTail = 'Tail'; const uint32 kTailSize = sizeof(kTail); #else const uint32 kTailSize = 0; #endif // =================================================================================== // Internal Functions // =================================================================================== //--------------------------------------------------------------- // // ThrowFileErr // //--------------------------------------------------------------- static void ThrowFileErr(const XFileSpec& spec, OSStatus err) { switch (err) { case dirFulErr: case dskFulErr: case nsvErr: case ioErr: case fnOpnErr: case eofErr: case posErr: case mFulErr: case tmfoErr: case fnfErr: case wPrErr: case fLckdErr: case vLckdErr: case fBsyErr: case dupFNErr: case opWrErr: case rfNumErr: case gfpErr: case volOffLinErr: case permErr: case volOnLinErr: case nsDrvErr: case noMacDskErr: case wrPermErr: case dirNFErr: case tmwdoErr: case volGoneErr: { #if DEBUG std::wstring mesg = XError::Instance()->GetText(err) + L" with file " + spec.GetName(); #else std::wstring mesg = LoadWhisperString(L"File error ##1 (with file '#2')", Int32ToStr(err), spec.GetName()); #endif throw std::runtime_error(ToUTF8Str(mesg)); } break; default: ThrowErr(err); } } //--------------------------------------------------------------- // // ThrowIfFileErr // //--------------------------------------------------------------- inline void ThrowIfFileErr(const XFileSpec& spec, OSStatus err) { if (err != noErr) ThrowFileErr(spec, err); } #pragma mark - // =================================================================================== // class XMemoryMappedFile // =================================================================================== //--------------------------------------------------------------- // // XMemoryMappedFile::~XMemoryMappedFile // //--------------------------------------------------------------- XMemoryMappedFile::~XMemoryMappedFile() { PRECONDITION(!this->IsOpened()); // in the normal course of events you should explicitly close the file CALL_INVARIANT; if (this->IsOpened()) { // but if an exception was thrown the file may still be open try { if (mWriting && mData != nil) this->Flush(); mFile.Close(); // if so, we need to close the file (and attempt to save any changes) } catch (...) { // can't throw from dtor } } if (mData != nil) DisposeHandle(mData); } //--------------------------------------------------------------- // // XMemoryMappedFile::XMemoryMappedFile (XFileSpec) // //--------------------------------------------------------------- XMemoryMappedFile::XMemoryMappedFile(const XFileSpec& file) : mFile(file) { // mRefNum = kNoFileRefNum; mReading = false; mWriting = false; mData = nil; mMaxBytes = 0; mPurgable = true; CALL_INVARIANT; } //--------------------------------------------------------------- // // XMemoryMappedFile::XMemoryMappedFile (XFolderSpec, wstring) // //--------------------------------------------------------------- XMemoryMappedFile::XMemoryMappedFile(const XFolderSpec& folder, const std::wstring& name) : mFile(folder, name) { // mRefNum = kNoFileRefNum; mReading = false; mWriting = false; mData = nil; mMaxBytes = 0; mPurgable = true; CALL_INVARIANT; } //--------------------------------------------------------------- // // XMemoryMappedFile::Open (EFilePermission, uint32) // //--------------------------------------------------------------- void XMemoryMappedFile::Open(EFilePermission perm, uint32 maxBytes) { PRECONDITION(!this->IsOpened()); PRECONDITION(mData == nil); CHECK_INVARIANT; int16 tempRef = kNoFileRefNum; mMaxBytes = maxBytes; // Open the file mFile.Open(perm); // OSErr err = ::FSOpenFork(&mFile.GetFSRef(), 0, nil, perm, &tempRef); // ThrowIfFileErr(mFile, err); // Initialize maxBytes if the user hasn't specified a value if (mMaxBytes == 0) { // int64 bytes; // err = ::FSGetForkSize(tempRef, &bytes); // ThrowIfFileErr(mFile, err); // mMaxBytes = numeric_cast<uint32>(bytes); mMaxBytes = mFile.GetLength(); } // Set some member variables // mRefNum = tempRef; mReading = perm == kReadPermission || perm == kReadWritePermission; mWriting = perm == kWritePermission || perm == kReadWritePermission; POSTCONDITION(this->IsOpened()); } //--------------------------------------------------------------- // // XMemoryMappedFile::Open (OSType, OSType, EFilePermission, uint32) // //--------------------------------------------------------------- void XMemoryMappedFile::Open(OSType creator, OSType fileType, EFilePermission perm, uint32 maxBytes) { PRECONDITION(!this->IsOpened()); PRECONDITION(mData == nil); CHECK_INVARIANT; int16 tempRef = kNoFileRefNum; mMaxBytes = maxBytes; // Open the file mFile.Open(creator, fileType, perm); // Initialize maxBytes if the user hasn't specified a value if (mMaxBytes == 0) { // int64 bytes; // err = ::FSGetForkSize(tempRef, &bytes); // ThrowIfFileErr(mFile, err); // mMaxBytes = numeric_cast<uint32>(bytes); mMaxBytes = mFile.GetLength(); } // Set some member variables // mRefNum = tempRef; mReading = perm == kReadPermission || perm == kReadWritePermission; mWriting = perm == kWritePermission || perm == kReadWritePermission; POSTCONDITION(this->IsOpened()); } //--------------------------------------------------------------- // // XMemoryMappedFile::Close () // //--------------------------------------------------------------- void XMemoryMappedFile::Close() { PRECONDITION(this->IsOpened()); CHECK_INVARIANT; try { if (mWriting && mData != nil) this->Flush(); mFile.Close(); // File Manager buffers data and flushes on close so an error is quite possible // OSErr err = FSClose(mRefNum); // ThrowIfFileErr(mFile, err); // File Manager buffers data and flushes on close so an error is quite possible if (mData != nil) { DisposeHandle(mData); mData = nil; } // mRefNum = kNoFileRefNum; mReading = false; mWriting = false; } catch (...) { if (mData != nil) { DisposeHandle(mData); mData = nil; } // mRefNum = kNoFileRefNum; throw; } POSTCONDITION(!this->IsOpened()); } //--------------------------------------------------------------- // // XMemoryMappedFile::Close (uint32) // //--------------------------------------------------------------- void XMemoryMappedFile::Close(uint32 newSize) { PRECONDITION(mWriting); CHECK_INVARIANT; if (mData != nil && newSize != mMaxBytes) { // mData will only be nil if the file was never locked ASSERT(*mData != nil); ASSERT(newSize <= GetHandleSize(mData) - kTailSize); SetHandleSize(mData, newSize + kTailSize); ThrowIfMemError(); mMaxBytes = newSize; #if DEBUG uint32* tail = reinterpret_cast<uint32*>(*mData + mMaxBytes); *tail = kTail; #endif } this->Close(); POSTCONDITION(!this->IsOpened()); } //--------------------------------------------------------------- // // XMemoryMappedFile::IsOpened // //--------------------------------------------------------------- bool XMemoryMappedFile::IsOpened() const { return mFile.IsOpened(); // bool open = mRefNum != kNoFileRefNum; // return open; } //--------------------------------------------------------------- // // XMemoryMappedFile::GetBuffer // //--------------------------------------------------------------- uint8* XMemoryMappedFile::GetBuffer() { PRECONDITION(this->IsLocked()); PRECONDITION(mData != nil); PRECONDITION(*mData != nil); return (uint8*) *mData; } //--------------------------------------------------------------- // // XMemoryMappedFile::GetBufferSize // //--------------------------------------------------------------- uint32 XMemoryMappedFile::GetBufferSize() const { PRECONDITION(this->IsOpened()); // mMaxBytes is set via Open return mMaxBytes; } //--------------------------------------------------------------- // // XMemoryMappedFile::Flush // //--------------------------------------------------------------- void XMemoryMappedFile::Flush() { PRECONDITION(mWriting); PRECONDITION(this->IsOpened()); CHECK_INVARIANT; if (mData != nil) { // will only be nil if the file hasn't been locked yet ASSERT(*mData != nil); // writable files aren't purgeable mFile.Seek(kSeekFromStart, 0); // OSErr err = SetFPos(mRefNum, fsFromStart, 0); // ThrowIfFileErr(mFile, err); uint32 bytes = GetHandleSize(mData) - kTailSize; { XLocker lock(this); mFile.Write(*mData,bytes); // err = FSWrite(mRefNum, &bytes, *mData); // ThrowIfFileErr(mFile, err); } mFile.Trim(); // err = SetEOF(mRefNum, bytes); // ThrowIfFileErr(mFile, err); } } //--------------------------------------------------------------- // // XMemoryMappedFile::EnablePurging // //--------------------------------------------------------------- void XMemoryMappedFile::EnablePurging(bool enable) { ASSERT_IF(enable, !mWriting); CHECK_INVARIANT; if (enable != mPurgable) { mPurgable = enable; if (mData != nil && *mData != nil) { if (mPurgable) HPurge(mData); // this will have no effect while the handle is locked else HNoPurge(mData); ThrowIfMemError(); } } POSTCONDITION(true); } #if PRAGMA_MARK #pragma mark Ê #endif //--------------------------------------------------------------- // // XMemoryMappedFile::Invariant // //--------------------------------------------------------------- void XMemoryMappedFile::Invariant() const { } //--------------------------------------------------------------- // // XMemoryMappedFile::OnLock // //--------------------------------------------------------------- void XMemoryMappedFile::OnLock(bool moveHigh) { PRECONDITION(this->IsOpened()); bool dirty = false; OSErr err = noErr; // Allocate (or re-allocate) the handle if (mData == nil) { mData = TempNewHandle(numeric_cast<int32>(mMaxBytes + kTailSize), &err); if (mData == nil) mData = NewHandle(mMaxBytes + kTailSize); ThrowIfMemFail(mData); dirty = true; } else if (*mData == nil) { ReallocateHandle(mData, numeric_cast<int32>(mMaxBytes + kTailSize)); ThrowIfMemError(); HNoPurge(mData); ThrowIfMemError(); dirty = true; } // Lock it if (moveHigh) HLockHi(mData); else HLock(mData); ThrowIfMemError(); // And read in the file as necessary if (dirty && mReading) { #if DEBUG uint32* tail = reinterpret_cast<uint32*>(*mData + mMaxBytes); *tail = kTail; #endif uint32 bytes = mFile.GetLength(); bytes = Min(bytes, mMaxBytes); mFile.Read(*mData, bytes); } } //--------------------------------------------------------------- // // XMemoryMappedFile::OnUnlock // //--------------------------------------------------------------- void XMemoryMappedFile::OnUnlock() { PRECONDITION(mData != nil); PRECONDITION(*mData != nil); #if DEBUG uint32* tail = reinterpret_cast<uint32*>(*mData + mMaxBytes); ASSERT(*tail == kTail); #endif HUnlock(mData); ThrowIfMemError(); if (mReading && !mWriting && mPurgable) { HPurge(mData); ThrowIfMemError(); } } } // namespace Whisper \ No newline at end of file |