diff -r 000000000000 -r 4e1aa6a622a0 sensorservices/sensorserver/inc/server/sensrvchannelbuffer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/sensorservices/sensorserver/inc/server/sensrvchannelbuffer.h Tue Feb 02 00:53:00 2010 +0200 @@ -0,0 +1,365 @@ +/* +* Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: Sensor server channel listener implemetation +* +*/ + + +#ifndef SENSRVCHANNELBUFFER_H +#define SENSRVCHANNELBUFFER_H + +#include +#include "sensrvtransaction.h" +#include "senserverchannellistener.h" + + +class CSensrvChannel; + +/** +* Indicates recently added tail when there was outstanding request +* for data block. Index will be replaced +* on next invalidation to point to head index. +*/ +const TInt KSensrvChannelBufferUninitializedTail(KMaxTInt); + +/** +* Indicates this tail is not being used at all. +*/ +const TInt KSensrvChannelBufferUnusedTail(KMinTInt); + +/** +* Listener tail index item. Also stores data lost count for +* that listener. +* +* @since S60 5.0 +*/ +class TSensrvTailIndexItem + { + public: + TSensrvTailIndexItem(CSensrvChannelListener* aListener) + : iListener(aListener), + iDataTailIndex(KSensrvChannelBufferUnusedTail), + iConditionTailIndex(KSensrvChannelBufferUnusedTail), + iDataLostCount(0), + iDataAvailable(0), + iConditionDataAvailable(0) + { + } + + /** + * Listener for which this index is. + * Not own. + */ + CSensrvChannelListener* iListener; + + /** + * Tail index to buffer, indicating the next valid data + * for data listening. + * If tail index is same as buffer head index, then there + * is no valid data. + */ + TInt iDataTailIndex; + + /** + * Tail index to buffer, indicating the next valid data + * for condition listening. + * If tail index is same as buffer head index, then there + * is no valid data. + */ + TInt iConditionTailIndex; + + /** + * Number of data items lost to buffer overwrite + * since last time data was read by this listener. + */ + TInt iDataLostCount; + + /** + * Indicates if listener has unread data. + * Needed to separate between no data and data starting + * from head index, as in both cases tail will be at + * head index. + */ + TBool iDataAvailable; + + /** + * Indicates if listener has unevaluated data. + * Needed to separate between no data and data starting + * from head index, as in both cases tail will be at + * head index. + */ + TBool iConditionDataAvailable; + }; + + +/** +* Implements channel buffer related handling. +* +* Channel buffer is a ring buffer with a couple of special twists: +* - There can be multiple tail pointers (one for each client that is +* listening to the channel). +* - New data is written by SSY or sensor driver directly to buffer, +* so any pointer given for writing must have at enough continuous +* space to fit n items (specified when new pointer is requested). +* -> This leads to situations where end of the buffer contains no +* valid data, so there is an end index to indicate end of valid data. +* +* @since S60 5.0 +*/ +class CSensrvChannelBuffer : public CBase + { + public: + + /** + * Two phase constructor + * + * @since S60 5.0 + * @param aItemSize Size of single buffered item in bytes + * @param aBufferLength Number of items that need to be buffered. + * @return New CSensrvChannelBuffer instance + * @exception KErrNoMemory Out of memory + */ + static CSensrvChannelBuffer* NewL( TInt aItemSize, + TInt aBufferLength); + + /** + * Destructor. + */ + virtual ~CSensrvChannelBuffer(); + + /** + * Gets buffer length + * Called from server thread + * + * @since S60 5.0 + * @return Buffer length + */ + inline TInt Length() const { return iBufferLength; }; + + /** + * Gets pointer to next free block of n items. + * Adjusts indexes accordingly. + * Called by SSY thread. + * + * @since S60 5.0 + * @param aCount Number of items to get free block for. + */ + TUint8* GetFreeBlock(TInt aCount); + + /** + * Validates block of n items starting from the head index. + * Adjusts indexes accordingly. + * Called by SSY thread. + * + * @since S60 5.0 + * @param aCount Number of items that were written. + */ + void WroteBlock(TInt aCount); + + /** + * Cancels any outstanding free block request + * Called by SSY thread. + * + * @since S60 5.0 + */ + void CancelFreeBlock(); + + + /** + * Add new listener tail index. Index is initialized to + * KSensrvChannelBufferUninitializedTail, if there is an + * outstanding request for data block, or iHeadIndex if not. + * This is done so that first write of data will be ignored, + * as it was generated before listening started for this + * listener. + * + * Called by server thread. + * + * @since S60 5.0 + * @param aListener Pointer to the listener. + * @param aTailItem Returns pointer to tail item that can be + * supplied to other methods. + * @param aState channel listener state. + * @return Symbian error code + */ + TInt AddListener(CSensrvChannelListener* aListener, + TSensrvTailIndexItem*& aTailItem, + CSensrvChannelListener::TSensrvChannelListenerState aState); + + /** + * Removes a listener tail index. + * Called by server thread. + * + * @since S60 5.0 + * @param aListener Pointer to the listener. + */ + void RemoveListener(CSensrvChannelListener* aListener); + + /** + * Gets data for transaction and adjusts listener tail + * accordingly. Data written can be less than the specified + * count, if there is less data available. + * Called by server thread. + * + * @since S60 5.0 + * @param aTailItem Pointer to the tail item. + * @param aMessageData Reference to message data that is filled. + * Note that the data is only guaranteed valid as long as proxy's mutex + * is not signaled. + * @param aCount Maximum number of data items to write. + */ + void GetMessageData(TSensrvTailIndexItem* aTailItem, + CSensrvChannelListener::TChannelDataMessage& aMessageData, + TInt aCount); + + /** + * Gets data for condition evaluation and resets condition tail + * to head index. + * + * @since S60 5.0 + * @param aTailItem Pointer to the tail item. + * @param aDataParts Reference to dataparts object is filled. + * Note that the data is only guaranteed valid as long as proxy's mutex + * is not signaled. + */ + void GetConditionData(TSensrvTailIndexItem* aTailItem, + CSensrvChannelListener::TChannelDataParts& aDataParts); + + /** + * Gets the initial data item that can be sent to new listerers + * if there is no data available by GetMessageData(). + * Called by server thread. + * + * @since S60 5.0 + * @param aMessageData Reference to message data that is filled. + * Note that the data is only guaranteed valid as long as proxy's mutex + * is not signaled. + */ + void GetInitialMessageData( CSensrvChannelListener::TChannelDataMessage& aMessageData ); + + private: + + /** + * C++ constructor + * + * @since S60 5.0 + * @param aItemSize Size of single buffered item in bytes + * @param aBufferLength Number of items that need to be buffered. + */ + CSensrvChannelBuffer(TInt aItemSize, + TInt aBufferLength); + + /** + * 2nd phase of construction + * + * @since S60 5.0 + */ + void ConstructL(); + + /** + * Invalidates range of items starting from head index. + * Adjusts valid and tail indexes accordingly. + * + * @since S60 5.0 + * @param aCount Number of items to invalidate. + */ + void InvalidateRange(TInt aCount); + + /** + * Checks how much new data is available for listener. + * If there is no data amount change, no update is needed. + * + * @since S60 5.0 + * @param aTailItem Reference to the tail item. + * @param aMoreData If ETrue, indicates that update is + * potentially increasing the amount of data. + * If false, the update is potentially decreasing the + * amount of data. + * @return Amount of new data available. + */ + void UpdateDataAvailable(TSensrvTailIndexItem& aTailItem, + TBool aMoreData); + + /** + * Gets tail index for listener. + * + * @since S60 5.0 + * @param aListener Pointer to the listener. + * @return Index for listener in iTailIndexArray or + * KErrNotFound if not found. + */ + TInt GetTailIndex(CSensrvChannelListener* aListener); + + +#ifdef BUFFER_TRACE_DEBUG + /** + * Prints out the buffer contents with RDebug + * + * @since S60 5.0 + */ + void DebugPrintBuffer(); +#endif // BUFFER_TRACE_DEBUG + + private: // Member variables + + /** + * Single buffered data item size + */ + TInt iItemSize; + + /** + * Number of items buffer can hold. + */ + TInt iBufferLength; + + /** + * Actual buffer. + * Own. + */ + HBufC8* iBuffer; + + /** + * Indicates cell where SSY will be writing next. + */ + TInt iHeadIndex; + + /** + * Indicates first invalid data cell after continuous valid cells. + * If iHeadIndex == iValidEndIndex, valid buffer space is continuous. + * If iHeadIndex < iValidEndIndex, buffer has wrapped around. + */ + TInt iValidEndIndex; + + /** + * Array of listener tail indexes + */ + RPointerArray iTailIndexArray; + + /** + * Indicates the length of free block that has been requested. + */ + TInt iRequestedFreeBlockLength; + + /** + * Index of the latest written data item or KErrNotFound. + * The item located at this index can be sent to new listeners as initial data if + * there is nothing else to sent. + */ + TInt iLatestWrittenItemIndex; + + }; + + + +#endif // SENSRVCHANNELBUFFER_H