diff -r 000000000000 -r 96e5fb8b040d userlibandfileserver/fileserver/smassstorage/inc/rwdrivethread.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/userlibandfileserver/fileserver/smassstorage/inc/rwdrivethread.h Thu Dec 17 09:24:54 2009 +0200 @@ -0,0 +1,283 @@ +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// Thread for reading and writing to a drive. +// +// + +/** + @file + @internalTechnology +*/ + +#ifndef __RWDRIVETHREAD_H__ +#define __RWDRIVETHREAD_H__ + +#ifdef MSDC_MULTITHREADED + +typedef void (*ProcessWriteCompleteFunc)(TUint8* aAddress, TAny* aPtr); + + +/** +Class contains buffer for data with associated drive offset and length in bytes. +*/ + +class TBlockDesc +{ +public: + + TBlockDesc(); + void SetPtr(TPtr8& aDes); + + TPtr8 GetReadBuffer(); + TPtr8 GetReadBuffer(TUint aLength, const TInt64& aOffset); + +public: + TInt64 iByteOffset; + TUint iLength; + TPtr8 iBuf; +}; + + +/** +Class contains two buffers. Whilst one buffer is being read the +other buffer can be written to. The buffers should be accessed +by the buffer pointers iDescReadPtr and iDescWritePtr. +*/ + +class TBlockDescBuffer +{ +public: + TBlockDescBuffer(); + + void SwapDesc(); + TInt MaxLength() const {return iDesc2.iBuf.MaxLength();} + TInt GetBufferNumber(const TPtr8* aBufferPtr) const; + void SetUpReadBuf(TPtr8& aDes1, TPtr8& aDes2); + +public: + /** Points to block descriptor containing buffer to read from */ + TBlockDesc* iDescReadPtr; + /** Points to block descriptor containing buffer to write to */ + TBlockDesc* iDescWritePtr; + +private: + /** Block descriptor for read/write operations */ + TBlockDesc iDesc1; + /** Block descriptor for read/write operations */ + TBlockDesc iDesc2; +}; + + +/** +Provides the common thread context used by CReadDriveThread and CWriteDriveThread +classes. +*/ +class CThreadContext : public CBase +{ +public: + static CThreadContext* NewL(const TDesC& aName, + TThreadFunction aThreadFunction, + TAny* aOwner); + ~CThreadContext(); + +private: + CThreadContext(); + void ConstructL(const TDesC& aName, TThreadFunction aThreadFunction, TAny* aOwner); + + +public: + void Resume() {iThread.Resume();} + + TInt MaxBufferLength() const {return iBuffer.MaxLength();} + TPtr8 GetReadBuffer(); + TPtr8 GetReadBuffer(TInt aLength); + + TPtrC8 WriteBuf(); + +public: + /** Used to tell thread which drive to use */ + CMassStorageDrive* iDrive; + /** Used by the thread to return error code */ + TInt iError; + /** CS to regulate read/write buffer access */ + RCriticalSection iCritSect; + + /** buffer for reading and writing */ + TBlockDescBuffer iBuffer; + +public: + RThread iThread; +}; + + +/** +Separate disk writer thread, used to implement OUT transfer double-buffering. +*/ +class CWriteDriveThread : public CBase + { +public: + static CWriteDriveThread* NewL(); + ~CWriteDriveThread(); + +private: + CWriteDriveThread(); + void ConstructL(); + +public: + TBlockDesc* GetReadDesc(); + + TInt WriteDriveData(CMassStorageDrive* aDrive, const TInt64& aOffset, TPtrC8& aDes, ProcessWriteCompleteFunc aFunc, TAny* aPtr); + + TUint WriteBufferLength() const {return iThreadContext->iBuffer.iDescWritePtr->iBuf.Length();} + TUint ReadBufferLength() const {return iThreadContext->iBuffer.iDescReadPtr->iBuf.Length();} + + TInt DeferredError() const {return iThreadContext->iError;} + void ClearDeferredError() {iThreadContext->iError = KErrNone;} + void WaitForWriteEmpty(); + + TBool IsRecentlyWritten(TInt64 aOffset, TInt aLength); + inline void SetCommandWrite10(TBool aIsWriteCommand) {iIsCommandWrite10 = aIsWriteCommand;}; + +private: + static TInt ThreadFunction(TAny* aSelf); + TInt WriteToDrive(); + +public: + /** Thread context */ + CThreadContext* iThreadContext; + + TInt iWriteCounter; +private: + /** Semaphore for reading USB */ + RSemaphore iProducerSem; + /** Semaphore for writing to drive */ + RSemaphore iConsumerSem; + /* Call back to tell transport that 'transfer' was written and the corresponding buffer can be overwriiten (mainly for SC LDD) */ + ProcessWriteCompleteFunc iCallback; + TAny* iCallbackParameter; + /* Flag set to true if the command is Write10. Used in Read10 to ignore pre-read if the previous command was Write10 */ + TBool iIsCommandWrite10; + }; + + +/** +Separate disk reader thread, used to implement IN transfer double-buffering. +*/ +class CReadDriveThread : public CBase + { +public: + static CReadDriveThread* NewL(); + ~CReadDriveThread(); + +private: + CReadDriveThread(); + void ConstructL(); + +public: + TBool ReadDriveData(CMassStorageDrive* aDrive, const TInt64& aOffset, TUint32 aLength, TBool aIgnoreCache); + void DiscardRead(); + +private: + static TInt ThreadFunction(TAny* aSelf); + TInt ReadFromDrive(); + +public: + /** Thread context */ + CThreadContext* iThreadContext; + TBool iCompleted; + +private: + TBool iThreadRunning; + }; + + +//----------------------------------------------- + +/** +Swap the buffer which the read and write buffer pointers are pointing to. +*/ +inline void TBlockDescBuffer::SwapDesc() +{ + TBlockDesc* const tmp = iDescReadPtr; + iDescReadPtr = iDescWritePtr; + iDescWritePtr = tmp; +} + +inline TPtr8 TBlockDesc::GetReadBuffer() +{ + return iBuf.LeftTPtr(iBuf.Length()); +} + + +inline TPtr8 TBlockDesc::GetReadBuffer(TUint aLength, const TInt64& aOffset) +{ + iByteOffset = aOffset; + iLength = aLength; + iBuf.SetLength(aLength); + + return GetReadBuffer(); +} + +//----------------------------------------------- + +/** +Returns the id of the buffer + +@param bufferPtr pointer to the buffer. +@return returns the buffer ID or -1 if the buffer is not found. +*/ +inline TInt TBlockDescBuffer::GetBufferNumber(const TPtr8* aBufferPtr) const +{ + TInt no = -1; + if (aBufferPtr == &iDesc1.iBuf) + no = 1; + else if (aBufferPtr == &iDesc2.iBuf) + no = 2; + return no; +} + + +//----------------------------------------------- + +inline TPtr8 CThreadContext::GetReadBuffer() +{ + TInt len = iBuffer.iDescReadPtr->iBuf.Length(); + return iBuffer.iDescReadPtr->iBuf.LeftTPtr(len); +} + + +inline TPtr8 CThreadContext::GetReadBuffer(TInt aLength) +{ + iBuffer.iDescReadPtr->iBuf.SetLength(aLength); + return GetReadBuffer(); +} + + +inline TPtrC8 CThreadContext::WriteBuf() +{ + return iBuffer.iDescWritePtr->iBuf; +} + +//----------------------------------------------- + +inline TBlockDesc* CWriteDriveThread::GetReadDesc() +{ + return iThreadContext->iBuffer.iDescReadPtr; +} + +//----------------------------------------------- + +#endif // MSDC_MULTITHREADED + +#endif // __RWDRIVETHREAD_H__