--- /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 <e32base.h>
+#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<TSensrvTailIndexItem> 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