appfw/viewserver/server/VWSQUEUE.CPP
changeset 0 2e3d3ce01487
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/appfw/viewserver/server/VWSQUEUE.CPP	Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,284 @@
+// Copyright (c) 1999-2009 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:
+//
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "vwsinternal.h"
+#include "vwsdefpartner.h"
+#endif //SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "VWSQUEUE.H"
+
+
+//
+// CVwsEventQueue.
+//
+
+CVwsEventQueue::CVwsEventQueue() 
+	{
+	}
+
+#ifdef __DO_LOGGING__
+CVwsEventQueue::CVwsEventQueue(const TDesC& aName) : iQueueName(aName)
+	{
+	}
+
+void CVwsEventQueue::SetName(const TDesC& aName)
+	{
+	iQueueName=aName;
+	}
+#endif
+
+CVwsEventQueue::~CVwsEventQueue()
+	{
+	do
+		{
+		delete Head();
+		}
+	while (RemoveHead() == KErrNone);
+	}
+
+void CVwsEventQueue::ProcessEventL(CVwsEvent* aEvent)
+	{
+	TInt err=AddToTail(aEvent);
+	if(err!=KErrNone)
+		{
+		if(aEvent!=NULL)
+			{
+			delete aEvent;
+			aEvent=NULL;
+			}
+		User::Leave(err);
+		}
+
+	if (aEvent)
+		{
+		switch (iState)
+			{
+			case EEmpty:
+				{
+				iState=EProcessing;
+				TRAPD(err,aEvent->ProcessEventL());
+				if (err)
+					{
+					DeleteHead();
+					iState=EEmpty;
+					}
+				User::LeaveIfError(err);
+				}
+				break;
+			case EProcessing:
+				// Wait until current event has finished being processed.
+				break;
+			default:
+				ASSERT(EFalse);
+			}
+		}
+	}
+
+void CVwsEventQueue::HandleEventProcessed()
+	{
+	if (iQueueSize==1)
+		{
+		Head()->HandleLastOnQueue();
+		DeleteHead();
+		LOG3(CVwsLog::ELoud,_L("Completed event at head of %S, queue empty"),&iQueueName);
+		iState=EEmpty;
+		}
+	else if (iQueueSize>0)
+		{
+		DeleteHead();
+		LOG4(CVwsLog::ELoud,_L("Completed event at head of %S, processing next [queue size %d]"),&iQueueName,iQueueSize);
+		// Start processing next event in the queue.
+		TInt err=KErrGeneral;
+		while (iQueueSize>0 && err)
+				{
+				TRAP(err, Head()->ProcessEventL());
+				if (err)
+					{
+					DeleteHead();
+					if (0==iQueueSize)
+						{
+						iState=EEmpty;
+						}
+					}
+				}
+		}
+	}
+
+CVwsEvent* CVwsEventQueue::Head() const
+	{
+	if (iQueueSize==0)
+		return NULL;
+
+	return iQueue[iQueueStart];
+	}
+
+CVwsEvent* CVwsEventQueue::Tail() const
+	{
+	if (iQueueSize==0)
+		return NULL;
+
+	return iQueue[(iQueueEnd+KQueueSize-1)%KQueueSize];
+	}
+
+TInt CVwsEventQueue::Count() const
+	{
+	return iQueueSize;
+	}
+
+void CVwsEventQueue::DeleteHead()
+	{
+	delete Head();
+	RemoveHead();
+	}
+
+void CVwsEventQueue::HandleSessionRemoval(const TThreadId& aClientThreadId)
+	{
+	if (iQueueSize>0)
+		{
+		LOG4(CVwsLog::ELoud,_L("Session removed - handling removal in head event of %S [queue size %d]"),&iQueueName,iQueueSize);
+		Head()->HandleSessionRemoval(aClientThreadId);
+		}
+	}
+
+TInt CVwsEventQueue::AddToTail(CVwsEvent*& aEvent)
+	{
+	switch (aEvent->Type())
+		{
+		case CVwsEvent::ENormal:
+			return DoAddToTail(aEvent);
+		case CVwsEvent::ERejectPairs:
+			return AddToTailIfNotPair(aEvent);
+		default:
+			ASSERT(EFalse);
+			return KErrGeneral;
+		}
+	}
+
+TInt CVwsEventQueue::RemoveHead()
+	{
+	if (iQueueSize>0)
+		{
+		iQueue[iQueueStart]=NULL;
+		iQueueStart=(iQueueStart+1)%KQueueSize;
+		iQueueSize--;
+		return KErrNone;
+		}
+
+	return KErrUnderflow;
+	}
+
+TInt CVwsEventQueue::DoAddToTail(CVwsEvent* aEvent)
+	{
+	if (iQueueSize<KQueueSize)
+		{
+		iQueue[iQueueEnd]=aEvent;
+		iQueueEnd=(iQueueEnd+1)%KQueueSize;
+		iQueueSize++;
+		aEvent->HandleAddedToQueue();
+		LOG4(CVwsLog::ELoud,_L("Added event to tail of %S [queue size %d]"),&iQueueName,iQueueSize);
+		return KErrNone;
+		}
+
+	return KErrOverflow;
+	}
+
+TInt CVwsEventQueue::AddToTailIfNotPair(CVwsEvent*& aEvent)
+	{
+	if (iQueueSize==0)
+		{
+		// Nothing in queue, so safe to add.
+		return DoAddToTail(aEvent);
+		}
+
+	// Check for type match in queue.
+	if (iQueueSize>2)
+		{
+		if ((Tail()->Type()==aEvent->Type()) && (At(iQueueSize-2)->Type()==aEvent->Type()) && (At(iQueueSize-3)->Type()==aEvent->Type()))
+			{
+			LOG3(CVwsLog::ENormal,_L("Discarded event - one already in %S"),&iQueueName);
+			delete aEvent;
+			aEvent=NULL;
+			return KErrNone;
+			}
+		}
+
+	// No match, do add to tail.
+	return DoAddToTail(aEvent);
+	}
+
+CVwsEvent* CVwsEventQueue::At(TInt aIndex)
+	{
+	CVwsEvent* event=NULL;
+
+	if (aIndex<iQueueSize)
+		{
+		event=iQueue[(iQueueStart+aIndex)%KQueueSize];
+		}
+
+	return event;
+	}
+
+void CVwsEventQueue::KickStart()
+	{
+	//Attempt to restart stalled q
+	DeleteHead();
+	iState=EEmpty;
+	TInt err = KErrGeneral;
+	while(iQueueSize>0 && err)
+		{
+		iState=EProcessing;
+		TRAP(err, Head()->ProcessEventL());
+		if (err)
+			{
+			DeleteHead();
+			iState=EEmpty;
+			}
+		}
+	}
+
+//
+// CVwsEvent.
+//
+
+CVwsEvent::CVwsEvent(TType aType,CVwsEventQueue& aQueue)
+	:iType(aType),iQueue(aQueue)
+	{
+	}
+
+CVwsEvent::~CVwsEvent()
+	{
+	}
+
+CVwsEvent::TType CVwsEvent::Type()
+	{
+	return iType;
+	}
+
+void CVwsEvent::ReportEventProcessed()
+	{
+	iQueue.HandleEventProcessed();
+	}
+
+void CVwsEvent::HandleAddedToQueue()
+	{
+	}
+
+void CVwsEvent::HandleLastOnQueue()
+	{
+	}
+
+void CVwsEvent::HandleSessionRemoval(const TThreadId& /*aClientThreadId*/)
+	{
+	}