1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/windowing/windowserver/nga/SERVER/EVQUEUE.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,1173 @@
1.4 +// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// Window server event queue handling
1.18 +//
1.19 +//
1.20 +
1.21 +#include "EVQUEUE.H"
1.22 +
1.23 +#include "server.h"
1.24 +#include "wstop.h"
1.25 +#include "panics.h"
1.26 +#include "pointer.h"
1.27 +#include "advancedpointereventhelper.h"
1.28 +#include "debughelper.h"
1.29 +
1.30 +GLREF_D CDebugLogBase* wsDebugLog;
1.31 +
1.32 +#if defined(_DEBUG)
1.33 +#define __CHECK_QUEUE() CheckQueue()
1.34 +#define __ZAP_EVENTS(pointer,len) ZapEvents(pointer,len)
1.35 +#define __ZAP_EVENT(pointer) ZapEvent(pointer)
1.36 +#else
1.37 +#define __CHECK_QUEUE()
1.38 +#define __ZAP_EVENTS(pointer,len)
1.39 +#define __ZAP_EVENT(pointer)
1.40 +#endif
1.41 +
1.42 +const TInt ECopyBufSize=4;
1.43 +
1.44 +TDblQue<CEventQueue> CEventQueue::iQueueList(_FOFF(CEventQueue,iLink));
1.45 +TWsEvent* CEventQueue::iGlobalEventQueue=NULL;
1.46 +TInt CEventQueue::iGlobalEventQueueSize=0;
1.47 +TInt CEventQueue::iNumConnections=0;
1.48 +RMutex CEventQueue::iMutex;
1.49 +TWsEvent CEventQueue::iNullEvent;
1.50 +
1.51 +// CEventBase
1.52 +
1.53 +CEventBase::~CEventBase()
1.54 + {
1.55 + if (!iEventMsg.IsNull() && CWsTop::ShuttingDown())
1.56 + {
1.57 + iEventMsg.Complete(KErrServerTerminated);
1.58 + }
1.59 + }
1.60 +
1.61 +CEventBase::CEventBase(CWsClient* aOwner) : iWsOwner(aOwner)
1.62 + {
1.63 + }
1.64 +
1.65 +void CEventBase::SignalEvent(TInt aCode)
1.66 + {
1.67 + if (wsDebugLog)
1.68 + wsDebugLog->SignalEvent(iWsOwner->ConnectionHandle());
1.69 + iEventMsg.Complete(aCode);
1.70 + iEventSignalledState|=EEventFlagSignalled;
1.71 + }
1.72 +
1.73 +inline TBool CEventBase::IsEventCancelled()
1.74 + {
1.75 + return (iEventSignalledState & EEventFlagCancelled);
1.76 + }
1.77 +
1.78 +/**
1.79 +If there is an outstanding read cancel it.
1.80 +*/
1.81 +void CEventBase::CancelRead()
1.82 + {
1.83 + if (!iEventMsg.IsNull())
1.84 + {
1.85 + iEventMsg.Complete(KErrCancel);
1.86 + }
1.87 + iEventSignalledState|=EEventFlagCancelled;
1.88 + }
1.89 +
1.90 +void CEventBase::GetData(TAny* aData, TInt aLen)
1.91 + {
1.92 + if (!(iEventSignalledState&EEventFlagSignalled))
1.93 + {
1.94 + iWsOwner->PPanic(EWservPanicUnsignalledEventData);
1.95 + }
1.96 + iEventSignalledState&=~EEventFlagSignalled;
1.97 + CWsClient::ReplyBuf(aData,aLen);
1.98 + }
1.99 +
1.100 +/**
1.101 +Queue a read of an event notification
1.102 +*/
1.103 +void CEventBase::EventReadyCheck()
1.104 + {
1.105 + if ((iEventSignalledState&EEventFlagSignalled && !(iEventSignalledState&EEventFlagCancelled)) || !iEventMsg.IsNull())
1.106 + {
1.107 +#ifdef LOG_WSERV_EVENTS
1.108 + RDebug::Printf("_WSEVENT: CEventBase::EventReadyCheck, Event is not ready");
1.109 +#endif
1.110 + iWsOwner->PPanic(EWservPanicReadOutstanding);
1.111 + }
1.112 + }
1.113 +
1.114 +void CEventBase::EventReady(const RMessagePtr2& aEventMsg)
1.115 + {
1.116 + EventReadyCheck();
1.117 + iEventMsg=aEventMsg;
1.118 + }
1.119 +
1.120 +// CEventQueue - Queue organisation functions
1.121 +
1.122 +#if defined(_DEBUG)
1.123 +void CEventQueue::CheckQueue()
1.124 + {
1.125 + TDblQueIter<CEventQueue> iter(iQueueList);
1.126 + CEventQueue* qptr;
1.127 + iter.SetToFirst();
1.128 + while((qptr=iter++)!=NULL)
1.129 + {
1.130 + WS_ASSERT_DEBUG(qptr->iQueueSize>=0 && qptr->iQueueSize<=iGlobalEventQueueSize, EWsPanicCheckEventQueue);
1.131 + WS_ASSERT_DEBUG(qptr->iQueueSize==0 || qptr->iHead<qptr->iQueueSize, EWsPanicCheckEventQueue);
1.132 + WS_ASSERT_DEBUG(qptr->iCount<=qptr->iQueueSize, EWsPanicCheckEventQueue);
1.133 + WS_ASSERT_DEBUG(qptr->iEventPtr>=iGlobalEventQueue && qptr->iEventPtr<=(iGlobalEventQueue+iGlobalEventQueueSize), EWsPanicCheckEventQueue);
1.134 + }
1.135 + for(TInt index=0;index<iCount;index++)
1.136 + {
1.137 + TWsEvent* ev=EventPtr(index);
1.138 + WS_ASSERT_DEBUG(ev->Type()!=EEventMarkInvalid, EWsPanicCheckEventQueue);
1.139 + }
1.140 + }
1.141 +
1.142 +void CEventQueue::ZapEvent(TWsEvent* aTarget)
1.143 + {
1.144 + aTarget->SetType(EEventMarkInvalid);
1.145 + aTarget->SetHandle(555);
1.146 + }
1.147 +
1.148 +void CEventQueue::ZapEvents(TWsEvent* aTarget, TInt aLen)
1.149 + {
1.150 + for(TInt index=0;index<aLen;index++)
1.151 + ZapEvent(aTarget+index);
1.152 + }
1.153 +
1.154 +#endif
1.155 +
1.156 +void CEventQueue::EventCopy(TWsEvent* aTarget, TWsEvent* aSource, TInt aNumEvents)
1.157 + {
1.158 + WS_ASSERT_DEBUG(aTarget>=iGlobalEventQueue, EWsPanicEventQueueCopy);
1.159 + WS_ASSERT_DEBUG((aTarget+aNumEvents)<=(iGlobalEventQueue+iGlobalEventQueueSize), EWsPanicEventQueueCopy);
1.160 + Mem::Copy(aTarget,aSource,aNumEvents*sizeof(TWsEvent));
1.161 + }
1.162 +
1.163 +TInt CEventQueue::RequiredQueueSize(TInt aNumConnections)
1.164 + {
1.165 + return(aNumConnections*EMinQueueSize+EMaxQueueSize+EExtraQueueSize);
1.166 + }
1.167 +
1.168 +/**
1.169 +Adjust the Global Queue Size.
1.170 +@param aNewSize the size for event queue.
1.171 +*/
1.172 +void CEventQueue::AdjustQueueSizeL(TInt aNewSize)
1.173 + {
1.174 + TWsEvent* oldQ=iGlobalEventQueue;
1.175 + if (aNewSize < iGlobalEventQueueSize)
1.176 + {
1.177 + // Re-alloc wont move the cell down to a lower address, this means once this cell is
1.178 + // high up in memory it may never move down again, thus wasting loads of global heap space.
1.179 + const CEventQueue* last=iQueueList.Last();
1.180 + if ((last->iEventPtr + last->iQueueSize) >= (iGlobalEventQueue + aNewSize))
1.181 + {
1.182 + return;
1.183 + }
1.184 + TInt allocSize = aNewSize * sizeof(TWsEvent);
1.185 + iGlobalEventQueue=static_cast<TWsEvent*>(User::AllocL(allocSize));
1.186 + Mem::Copy(iGlobalEventQueue,oldQ,allocSize);
1.187 + User::Free(oldQ);
1.188 + }
1.189 + else
1.190 + {
1.191 + iGlobalEventQueue = static_cast<TWsEvent*>(User::ReAllocL(iGlobalEventQueue, aNewSize * sizeof(TWsEvent)));
1.192 + }
1.193 + __ZAP_EVENTS(iGlobalEventQueue + iGlobalEventQueueSize, aNewSize - iGlobalEventQueueSize);
1.194 + iGlobalEventQueueSize = aNewSize;
1.195 + // coverity[use_after_free]
1.196 + TInt diff=(reinterpret_cast<TInt8*>(iGlobalEventQueue)-reinterpret_cast<TInt8*>(oldQ));
1.197 + if (diff)
1.198 + {
1.199 + TDblQueIter<CEventQueue> iter(iQueueList);
1.200 + CEventQueue* qptr;
1.201 + while((qptr=iter++)!=NULL)
1.202 + {
1.203 + qptr->iEventPtr=reinterpret_cast<TWsEvent*>(reinterpret_cast<TInt8*>(qptr->iEventPtr)+diff);
1.204 + }
1.205 + }
1.206 + }
1.207 +
1.208 +void CEventQueue::AddQueueL()
1.209 + {
1.210 + Wait();
1.211 + if ((iNumConnections%EQueueGranularity)==0)
1.212 + {
1.213 + const TInt newSize = RequiredQueueSize(iNumConnections + EQueueGranularity);
1.214 + TRAPD(err,AdjustQueueSizeL(newSize));
1.215 + if (err!=KErrNone)
1.216 + {
1.217 + __CHECK_QUEUE();
1.218 + Signal();
1.219 + User::Leave(err);
1.220 + }
1.221 + }
1.222 + iNumConnections++;
1.223 + if (iQueueList.IsEmpty())
1.224 + iEventPtr=iGlobalEventQueue;
1.225 + else
1.226 + {
1.227 + CEventQueue* qptr=iQueueList.Last();
1.228 + iEventPtr=qptr->iEventPtr+qptr->iQueueSize;
1.229 + }
1.230 + iQueueList.AddLast(*this);
1.231 +
1.232 + //Initialize the queue size to at least EMinQueueSize
1.233 + //Check the queue by doing standard queue compression.
1.234 + TBool isExpanded = ETrue;
1.235 + do {isExpanded = Expand(EEventPriorityLow);} while ((iQueueSize < EMinQueueSize) && isExpanded);
1.236 + while (iQueueSize < EMinQueueSize)
1.237 + {
1.238 + //Cannot get enough spaces by doing standard queue compression,
1.239 + //try to grow the global queue.
1.240 + TInt sizeRequired = EMinQueueSize - iQueueSize;
1.241 + const TInt newSize = iGlobalEventQueueSize + sizeRequired;
1.242 + TRAPD(err, AdjustQueueSizeL(newSize));
1.243 + if (err != KErrNone)
1.244 + {
1.245 + //Cannot get enough spaces by growing global queue.
1.246 + //try to purge the oldest events from inactive clients.
1.247 + TInt numEventCleared = PurgeInactiveEvents(sizeRequired);
1.248 + if (numEventCleared == 0)
1.249 + {
1.250 + __CHECK_QUEUE();
1.251 + Signal();
1.252 + User::Leave(err);
1.253 + }
1.254 + }
1.255 + while (doExpand(ECompressNoPurge)) {};
1.256 + }
1.257 + __CHECK_QUEUE();
1.258 + Signal();
1.259 + }
1.260 +
1.261 +void CEventQueue::RemoveQueue()
1.262 + {
1.263 + Wait();
1.264 + if (iEventPtr) // If this is still NULL this class hasn't been linked into the Q list
1.265 + {
1.266 + __ZAP_EVENTS(iEventPtr, iQueueSize);
1.267 + iLink.Deque();
1.268 + if (--iNumConnections==0)
1.269 + {
1.270 + User::Free(iGlobalEventQueue);
1.271 + iGlobalEventQueue=NULL;
1.272 + iGlobalEventQueueSize=0;
1.273 + }
1.274 + else if ((iNumConnections%EQueueGranularity)==0)
1.275 + {
1.276 + TDblQueIter<CEventQueue> iter(iQueueList);
1.277 + CEventQueue* qptr=iter++;
1.278 + qptr->Compress(ECompressNoPurge);
1.279 + while((qptr=iter++)!=NULL)
1.280 + {
1.281 + qptr->SqueezeDown();
1.282 + }
1.283 + const TInt newSize = RequiredQueueSize(iNumConnections);
1.284 + TRAP_IGNORE(AdjustQueueSizeL(newSize));
1.285 + // Can easily leave as we need to allocate the new smaller queue before freeing
1.286 + // the old queue. But if it does it doesn't matter as we'll simply be left with
1.287 + // a larger than necessary buffer until the next realloc
1.288 + }
1.289 + iCount=0;
1.290 + }
1.291 + __CHECK_QUEUE();
1.292 + Signal();
1.293 + }
1.294 +
1.295 +void CEventQueue::IncreaseQueueSize(TInt aNumSpaces)
1.296 + {
1.297 + if ((iQueueSize+aNumSpaces)>EMaxQueueSize)
1.298 + aNumSpaces=EMaxQueueSize-iQueueSize;
1.299 + EventCopy(iEventPtr+iHead+aNumSpaces, iEventPtr+iHead, iQueueSize-iHead);
1.300 + __ZAP_EVENTS(iEventPtr+iHead, aNumSpaces);
1.301 + iQueueSize+=aNumSpaces;
1.302 + iHead=(iHead+aNumSpaces)%iQueueSize;
1.303 + }
1.304 +
1.305 +TBool CEventQueue::Expand(TWservEventPriorities aPriority)
1.306 + {
1.307 + if (iQueueSize==EMaxQueueSize)
1.308 + {
1.309 + if (aPriority==EEventPriorityHigh)
1.310 + {
1.311 + Purge();
1.312 + if (iCount<iQueueSize)
1.313 + return(ETrue); // Success!
1.314 + }
1.315 + }
1.316 + else if (doExpand(ECompressNoPurge) ||
1.317 + doExpand(ECompressPurge1) ||
1.318 + (aPriority==EEventPriorityHigh && doExpand(ECompressPurge2)))
1.319 + return(ETrue);
1.320 + return(EFalse); // Failure
1.321 + }
1.322 +
1.323 +TBool CEventQueue::doExpand(TCompressMode aCompressMode)
1.324 + {
1.325 + TDblQueIter<CEventQueue> iter(iQueueList);
1.326 + iter.SetToLast();
1.327 + CEventQueue* qptr=NULL;
1.328 + TInt spare=0;
1.329 +
1.330 + // while loop from last queue till current queue, moving all queues up
1.331 + // to get all the space from between them
1.332 + while((qptr=iter)!=this)
1.333 + {
1.334 + spare=qptr->SqueezeUp();
1.335 + if (spare==0)
1.336 + qptr->Compress(aCompressMode);
1.337 + iter--;
1.338 + }
1.339 +
1.340 + // current queue, if we have space then expand the same and return
1.341 + spare=FollowingGap();
1.342 + if (spare>0)
1.343 + {
1.344 + IncreaseQueueSize(spare);
1.345 + __CHECK_QUEUE();
1.346 + return(ETrue);
1.347 + }
1.348 +
1.349 + // while loop from current queue till first queue, looking for a gap
1.350 + // between queues and using the first one it finds
1.351 + iter--;
1.352 + TInt expanded=0;
1.353 + while((qptr=iter)!=NULL)
1.354 + {
1.355 + expanded=qptr->SqueezeUp();
1.356 + if (expanded>0)
1.357 + {
1.358 + return MoveDownAndExpand(iter, expanded);
1.359 + }
1.360 + else
1.361 + qptr->Compress(aCompressMode);
1.362 + iter--;
1.363 + }
1.364 +
1.365 + // Even by doing all the above if we did not find space then check if first
1.366 + // queue has some space before it. If so then make use of it and movedown all the
1.367 + // queue till the current queue and then use the space for expansion
1.368 + iter.SetToFirst();
1.369 + qptr=iter;
1.370 + if (qptr->iEventPtr>iGlobalEventQueue)
1.371 + {
1.372 + return MoveDownAndExpand(iter, qptr->iEventPtr-iGlobalEventQueue);
1.373 + }
1.374 +
1.375 + __CHECK_QUEUE();
1.376 + return(EFalse); // Failed to expand enough room
1.377 + }
1.378 +
1.379 +// This function moves the queue down by given amount and repeats this until
1.380 +// the current queue and then expand the same
1.381 +TBool CEventQueue::MoveDownAndExpand(TDblQueIter<CEventQueue> &aIter, TInt aExpand)
1.382 + {
1.383 + CEventQueue* qptr=NULL;
1.384 + FOREVER
1.385 + {
1.386 + qptr=aIter++;
1.387 + qptr->MoveDown(aExpand);
1.388 + if (qptr==this)
1.389 + {
1.390 + IncreaseQueueSize(aExpand);
1.391 + __CHECK_QUEUE();
1.392 + break;
1.393 + }
1.394 + }
1.395 + return ETrue;
1.396 + }
1.397 +
1.398 +void CEventQueue::MoveDown(TInt aMove)
1.399 + {
1.400 + if (!aMove)
1.401 + {
1.402 + return;
1.403 + }
1.404 + EventCopy(iEventPtr-aMove,iEventPtr,iQueueSize);
1.405 + iEventPtr-=aMove;
1.406 + }
1.407 +
1.408 +/*void CEventQueue::LogUpDownEvents(TChar aChar)
1.409 + {
1.410 + TWsEvent *event;
1.411 + TBuf<128> buf;
1.412 + buf.Zero();
1.413 + buf.Append(aChar);
1.414 + buf.Append('#');
1.415 + buf.Append('#');
1.416 + TBool some=EFalse;
1.417 + TInt index;
1.418 +
1.419 + for (index=0;index<iCount;index++)
1.420 + {
1.421 + event=EventPtr(index);
1.422 + if (event->Type()==EEventPointer)
1.423 + {
1.424 + if (event->Pointer()->iType==TPointerEvent::EButton1Down
1.425 + || event->Pointer()->iType==TPointerEvent::EButton1Up)
1.426 + {
1.427 + some=ETrue;
1.428 + if (event->Pointer()->iType==TPointerEvent::EButton1Down)
1.429 + buf.Append('D');
1.430 + else
1.431 + buf.Append('U');
1.432 + buf.AppendNum(index);
1.433 + }
1.434 + }
1.435 + }
1.436 + if (wsDebugLog)
1.437 + wsDebugLog->MiscMessage(ELogImportant,buf);
1.438 + }*/
1.439 +
1.440 +inline void CEventQueue::IncEventPointer(TWsEvent*& aEventPtr)
1.441 + {
1.442 + // iEventPtr[iQueueSize] is the element beyond the array, used for efficient bounds checking of the circular buffer only, do not access!!
1.443 + if(++aEventPtr==&iEventPtr[iQueueSize])
1.444 + {
1.445 + aEventPtr=iEventPtr;
1.446 + }
1.447 + }
1.448 +
1.449 +inline void CEventQueue::DecEventPointer(TWsEvent*& aEventPtr)
1.450 + {
1.451 + if(aEventPtr--==iEventPtr)
1.452 + {
1.453 + aEventPtr=&iEventPtr[iQueueSize - 1];
1.454 + }
1.455 + }
1.456 +
1.457 +/*
1.458 +Starting from aEventToPurge searches the queue for matching event by iterating towards end of queue.
1.459 +Matching event will be a pointer event with the same window handle and pointer number
1.460 +as aEventToPurge, but will have type aMatchingType. If matching event is found, it will
1.461 +be removed from the queue and search will finish.
1.462 +
1.463 +Search will be stopped if an event of type aSearchTerminator is found with the same pointer number
1.464 +as aEventToPurge.
1.465 +
1.466 +If search is not stopped by aSearchTerminator and matching event is not found, TWsPointer
1.467 +class is notified that matching event has not been removed, so if it arrives in the future,
1.468 +TWsPointer class will be able to ignore it.
1.469 +*/
1.470 +void CEventQueue::PurgeEventPairs(TWsEvent* aEventToPurge, TPointerEvent::TType aMatchingType, TPointerEvent::TType aSearchTerminator)
1.471 + {
1.472 + TWsEvent* eventToMatch = aEventToPurge;
1.473 + TWsEvent* lastEvent = EventPtr(iCount);
1.474 + for(IncEventPointer(eventToMatch);eventToMatch!=lastEvent;IncEventPointer(eventToMatch))
1.475 + {
1.476 + if ( (eventToMatch->Type()==EEventPointer) // Must be checked first to ensure it is pointer data checked later
1.477 + && (TAdvancedPointerEventHelper::PointerNumber(*eventToMatch) == TAdvancedPointerEventHelper::PointerNumber(*aEventToPurge))) // same pointer
1.478 + {
1.479 + if ((eventToMatch->Pointer()->iType==aMatchingType) // correct event type
1.480 + && (eventToMatch->Handle()==aEventToPurge->Handle())) // same window
1.481 + {
1.482 + *eventToMatch=iNullEvent;
1.483 + return;
1.484 + }
1.485 + else if (eventToMatch->Pointer()->iType==aSearchTerminator) // stop searching for mathing type
1.486 + {
1.487 + return;
1.488 + }
1.489 + }
1.490 + };
1.491 + TWsPointer::UnmatchedEventPurged(aMatchingType, aEventToPurge);
1.492 + }
1.493 +
1.494 +/**
1.495 +Starting from pointer event aBasePointerEvent searches the queue for next pointer event for
1.496 +the same pointer by iterating towards end of queue.
1.497 +
1.498 +@param aBasePointerEvent must be of type EEventPointer
1.499 +@return Next pointer event in the queue for the same pointer as aBasePointerEvent
1.500 + if it has the same handle as aBasePointerEvent or NULL if it has different handle.
1.501 + NULL if there is no next pointer event for the same pointer in the queue.
1.502 +*/
1.503 +TWsEvent* CEventQueue::NextPointerEvent(TWsEvent* aBasePointerEvent)
1.504 + {
1.505 + WS_ASSERT_DEBUG(aBasePointerEvent->Type() == EEventPointer, EWsPanicCheckEventQueue);
1.506 + TWsEvent* currentEvent = aBasePointerEvent;
1.507 + TWsEvent* lastEvent = EventPtr(iCount);
1.508 + TUint8 pointerNumber = TAdvancedPointerEventHelper::PointerNumber(*aBasePointerEvent);
1.509 + TUint handle = aBasePointerEvent->Handle();
1.510 + for(IncEventPointer(currentEvent);currentEvent!=lastEvent;IncEventPointer(currentEvent))
1.511 + {
1.512 + if ((currentEvent->Type() == EEventPointer) &&
1.513 + (TAdvancedPointerEventHelper::PointerNumber(*currentEvent) == pointerNumber))
1.514 + {
1.515 + if (currentEvent->Handle() == handle)
1.516 + {
1.517 + return currentEvent;
1.518 + }
1.519 + else
1.520 + {
1.521 + return NULL;
1.522 + }
1.523 + }
1.524 + };
1.525 + return NULL;
1.526 + }
1.527 +
1.528 +/**
1.529 +Checks if aEventToPurge should be purged. If it can be purged, then events that should
1.530 +be purged together with aEventToPurge (matching events) are overwritten with iNullEvent.
1.531 +
1.532 +@return ETrue if aEventToPurge should be purged, EFalse otherwise.
1.533 +*/
1.534 +TBool CEventQueue::CheckPurgePointerEvent(TWsEvent* aEventToPurge)
1.535 + {
1.536 + switch(aEventToPurge->Pointer()->iType)
1.537 + {
1.538 + case TPointerEvent::EDrag:
1.539 + case TPointerEvent::EMove:
1.540 + case TPointerEvent::EButtonRepeat:
1.541 + case TPointerEvent::ESwitchOn:
1.542 + return ETrue;
1.543 + case TPointerEvent::EButton1Down:
1.544 + PurgeEventPairs(aEventToPurge,TPointerEvent::EButton1Up, TPointerEvent::ENullType);
1.545 + return ETrue;
1.546 + case TPointerEvent::EButton2Down:
1.547 + PurgeEventPairs(aEventToPurge,TPointerEvent::EButton2Up, TPointerEvent::ENullType);
1.548 + return ETrue;
1.549 + case TPointerEvent::EButton3Down:
1.550 + PurgeEventPairs(aEventToPurge,TPointerEvent::EButton3Up, TPointerEvent::ENullType);
1.551 + return ETrue;
1.552 + case TPointerEvent::EEnterHighPressure:
1.553 + PurgeEventPairs(aEventToPurge,TPointerEvent::EExitHighPressure, TPointerEvent::EButton1Up);
1.554 + return ETrue;
1.555 + case TPointerEvent::EEnterCloseProximity:
1.556 + {
1.557 + TWsEvent* nextEvent = NextPointerEvent(aEventToPurge);
1.558 + if (nextEvent != NULL)
1.559 + {
1.560 + switch(nextEvent->Pointer()->iType)
1.561 + {
1.562 + case TPointerEvent::EExitCloseProximity:
1.563 + *nextEvent = iNullEvent;
1.564 + case TPointerEvent::EOutOfRange:
1.565 + return ETrue;
1.566 + }
1.567 + }
1.568 + break;
1.569 + }
1.570 + case TPointerEvent::EExitCloseProximity:
1.571 + {
1.572 + TWsEvent* nextEvent = NextPointerEvent(aEventToPurge);
1.573 + if (nextEvent != NULL)
1.574 + {
1.575 + switch(nextEvent->Pointer()->iType)
1.576 + {
1.577 + case TPointerEvent::EEnterCloseProximity:
1.578 + *nextEvent = iNullEvent;
1.579 + case TPointerEvent::EOutOfRange:
1.580 + return ETrue;
1.581 + }
1.582 + }
1.583 + break;
1.584 + }
1.585 + case TPointerEvent::EOutOfRange:
1.586 + {
1.587 + TWsEvent* nextEvent = NextPointerEvent(aEventToPurge);
1.588 + if ((nextEvent != NULL) &&
1.589 + (nextEvent->Pointer()->iType == TPointerEvent::EOutOfRange))
1.590 + {
1.591 + return ETrue;
1.592 + }
1.593 + break;
1.594 + }
1.595 + case TPointerEvent::EExitHighPressure:
1.596 + {
1.597 + TWsEvent* nextEvent = NextPointerEvent(aEventToPurge);
1.598 + if ((nextEvent != NULL) &&
1.599 + (nextEvent->Pointer()->iType == TPointerEvent::EButton1Up))
1.600 + {
1.601 + return ETrue;
1.602 + }
1.603 + break;
1.604 + }
1.605 + case TPointerEvent::EButton1Up:
1.606 + case TPointerEvent::EButton2Up:
1.607 + case TPointerEvent::EButton3Up:
1.608 + break;
1.609 + }
1.610 + return EFalse;
1.611 + }
1.612 +
1.613 +/** Purgable events are:
1.614 + Pointer Up/Down pairs belonging to the same pointer, button and window
1.615 + Pointer moves & drags
1.616 + Key messages
1.617 + Key Up/Down pairs
1.618 + Key Ups if not foreground connection
1.619 + Focus lost/gained pairs
1.620 + EEnterHighPressure/EExitHighPressure pairs belonging to the same pointer
1.621 + EEnterCloseProximity/EExitCloseProximity pairs belonging to the same pointer
1.622 + Lone EEnterHighPressure, EExitHighPressure if followed by Up for the same pointer
1.623 + Lone EEnterCloseProximity, EExitCloseProximity if followed by EOutOfRange for the same pointer
1.624 + EOutOfRange if followed by another EOutOfRange for the same pointer
1.625 +
1.626 + Events that must not be purged:
1.627 + Key ups for foreground connections queue
1.628 + Lone pointer ups, must be delivered to match preceeding pointer down
1.629 + Lone EExitHighPressure if not followed by Up, must be delivered to match preceeding EEnterHighPressure
1.630 + Lone EEnterCloseProximity, EExitCloseProximity not followed by EOutOfRange for the same pointer
1.631 + Lone focus lost/gained messages
1.632 +*/
1.633 +void CEventQueue::Purge()
1.634 + {
1.635 + TWsEvent* eventToPurge;
1.636 + TWsEvent* eventToMatch;
1.637 + TInt indexToMatch;
1.638 + TInt indexToPurge=iCount;
1.639 + while(indexToPurge>0)
1.640 + {
1.641 + eventToPurge=EventPtr(--indexToPurge);
1.642 + switch(eventToPurge->Type())
1.643 + {
1.644 + case EEventPassword:
1.645 + break;
1.646 + case EEventMarkInvalid:
1.647 +#if defined(_DEBUG)
1.648 + WS_PANIC_DEBUG(EWsPanicCheckEventQueue);
1.649 +#endif
1.650 + case EEventNull:
1.651 + case EEventKey:
1.652 + case EEventPointerEnter:
1.653 + case EEventPointerExit:
1.654 + case EEventDragDrop:
1.655 +breakLoopAndRemoveEvent:
1.656 +#ifdef LOG_WSERV_EVENTS
1.657 + RDebug::Print(_L("_WSEVENT: CEventQueue::Purge(), The event to be purged is %S"), &WsEventName(*eventToPurge));
1.658 +#endif
1.659 + RemoveEvent(indexToPurge);
1.660 + return;
1.661 + case EEventKeyUp:
1.662 + if (iQueueList.First()!=this)
1.663 + goto breakLoopAndRemoveEvent;
1.664 + break;
1.665 + case EEventKeyDown:
1.666 + if (iQueueList.First()!=this)
1.667 + goto breakLoopAndRemoveEvent;
1.668 + for (indexToMatch=indexToPurge+1;indexToMatch<iCount;indexToMatch++)
1.669 + {
1.670 + eventToMatch=EventPtr(indexToMatch);
1.671 + if (eventToMatch->Type()==EEventKeyUp && eventToMatch->Key()->iScanCode==eventToPurge->Key()->iScanCode)
1.672 + {
1.673 + *eventToMatch=iNullEvent;
1.674 + goto breakLoopAndRemoveEvent;
1.675 + }
1.676 + }
1.677 + break;
1.678 + case EEventModifiersChanged:
1.679 + for (indexToMatch=indexToPurge;indexToMatch>0;)
1.680 + {
1.681 + eventToMatch=EventPtr(--indexToMatch);
1.682 + if (eventToMatch->Type()==EEventModifiersChanged)
1.683 + {
1.684 + eventToPurge->ModifiersChanged()->iChangedModifiers|=eventToMatch->ModifiersChanged()->iChangedModifiers;
1.685 + indexToPurge=indexToMatch;
1.686 + goto breakLoopAndRemoveEvent;
1.687 + }
1.688 + }
1.689 + break;
1.690 + case EEventPointerBufferReady:
1.691 + CWsPointerBuffer::DiscardPointerMoveBuffer(eventToPurge->Handle());
1.692 + goto breakLoopAndRemoveEvent;
1.693 + case EEventFocusLost:
1.694 + case EEventFocusGained:
1.695 + if ((indexToPurge+1)<iCount)
1.696 + {
1.697 + eventToMatch=EventPtr(indexToPurge+1);
1.698 + if (eventToMatch->Type()==EEventFocusLost || eventToMatch->Type()==EEventFocusGained)
1.699 + {
1.700 + *eventToMatch=iNullEvent;
1.701 + goto breakLoopAndRemoveEvent;
1.702 + }
1.703 + }
1.704 + break;
1.705 + case EEventSwitchOn:
1.706 + if ((indexToPurge+1)<iCount && EventPtr(indexToPurge+1)->Type()==EEventSwitchOn)
1.707 + goto breakLoopAndRemoveEvent;
1.708 + break;
1.709 + case EEventPointer:
1.710 + if (CheckPurgePointerEvent(eventToPurge))
1.711 + {
1.712 + goto breakLoopAndRemoveEvent;
1.713 + }
1.714 + break;
1.715 + }
1.716 + }
1.717 + }
1.718 +
1.719 +void CEventQueue::PurgePointerEvents()
1.720 + {
1.721 + TWsEvent* eventToPurge;
1.722 + TInt indexToPurge=iCount;
1.723 + while(indexToPurge>0)
1.724 + {
1.725 + eventToPurge=EventPtr(--indexToPurge);
1.726 + switch(eventToPurge->Type())
1.727 + {
1.728 + case EEventPointerBufferReady:
1.729 + CWsPointerBuffer::DiscardPointerMoveBuffer(eventToPurge->Handle());
1.730 + RemoveEvent(indexToPurge);
1.731 + break;
1.732 + case EEventPointer:
1.733 + if (CheckPurgePointerEvent(eventToPurge))
1.734 + {
1.735 + RemoveEvent(indexToPurge);
1.736 + }
1.737 + break;
1.738 + }
1.739 + }
1.740 + }
1.741 +
1.742 +/**
1.743 +Purge requested number of oldest events from inactive event queue.
1.744 +@param aSizeRequired the total events required to be cleared.
1.745 +@return The number of events cleared.
1.746 +*/
1.747 +TInt CEventQueue::PurgeInactiveEvents(const TInt& aSizeRequired)
1.748 + {
1.749 + TInt numEventsCleared = 0;
1.750 + CEventQueue* qptr;
1.751 + TBool isRemoved;
1.752 + do {
1.753 + TDblQueIter<CEventQueue> iter(iQueueList);
1.754 + isRemoved = EFalse;
1.755 + while ((qptr = iter++) != NULL && (aSizeRequired > numEventsCleared))
1.756 + {
1.757 + if ((qptr->IsEventCancelled() || (qptr->iEventMsg.IsNull() && !qptr->iEventSignalledState)) &&
1.758 + (qptr->iQueueSize > EMinQueueSize))
1.759 + {
1.760 + // we have a client that is not listening with a size larger than min queue size.
1.761 + // so lets remove it's oldest event until the number of removed events meet the requirement.
1.762 + qptr->RemoveEvent(0);
1.763 + numEventsCleared++;
1.764 + isRemoved = ETrue;
1.765 + }
1.766 + }
1.767 + } while ((aSizeRequired > numEventsCleared) && isRemoved);
1.768 + return numEventsCleared;
1.769 + }
1.770 +
1.771 +void CEventQueue::Compress(TCompressMode aCompressMode)
1.772 + {
1.773 +//
1.774 +// The different purge modes are
1.775 +//
1.776 +// ECompressNoPurge, // Don't purge anything
1.777 +// ECompressPurge1, // Don't purge foreground queue
1.778 +// ECompressPurge2, // Purge all queues
1.779 +//
1.780 + if (aCompressMode==ECompressPurge2 ||
1.781 + (this!=iQueueList.First() && aCompressMode==ECompressPurge1))
1.782 + Purge();
1.783 + TInt compress=iQueueSize-(iCount>EMinQueueSize?iCount:EMinQueueSize);
1.784 + if (compress>0)
1.785 + {
1.786 + compress=(compress+1)/2; // Compress half the free space in the queue
1.787 + TWsEvent* head=EventPtr(0);
1.788 + TWsEvent* tail=EventPtr(iCount);
1.789 + if (head>tail)
1.790 + {
1.791 + EventCopy(iEventPtr+compress,iEventPtr,tail-iEventPtr);
1.792 + iHead-=compress;
1.793 + }
1.794 + else
1.795 + {
1.796 + EventCopy(iEventPtr+compress,head,iCount);
1.797 + iHead=0;
1.798 + }
1.799 + iEventPtr+=compress;
1.800 + iQueueSize-=compress;
1.801 + }
1.802 + }
1.803 +
1.804 +void CEventQueue::MoveUp(TInt aNumEvents)
1.805 + {
1.806 + if (!aNumEvents)
1.807 + {
1.808 + return;
1.809 + }
1.810 + EventCopy(iEventPtr+aNumEvents,iEventPtr,iQueueSize);
1.811 + iEventPtr+=aNumEvents;
1.812 + }
1.813 +
1.814 +TInt CEventQueue::FollowingGap() const
1.815 + {
1.816 + TDblQueIter<CEventQueue> iter(iQueueList);
1.817 + CEventQueue* qptr;
1.818 + iter.Set(*(CEventQueue *)this);
1.819 + iter++;
1.820 + TWsEvent* end;
1.821 + if ((qptr=iter)!=NULL)
1.822 + end=qptr->iEventPtr;
1.823 + else
1.824 + end=iGlobalEventQueue+iGlobalEventQueueSize;
1.825 + return(end-(iEventPtr+iQueueSize));
1.826 + }
1.827 +
1.828 +TInt CEventQueue::SqueezeUp()
1.829 + {
1.830 + TInt gap=FollowingGap();
1.831 + MoveUp(gap);
1.832 + return(gap);
1.833 + }
1.834 +
1.835 +void CEventQueue::SqueezeDown()
1.836 + {
1.837 + TDblQueIter<CEventQueue> iter(iQueueList);
1.838 + iter.Set(*this);
1.839 + iter--;
1.840 + CEventQueue* qptr=iter;
1.841 + if (qptr!=NULL)
1.842 + {
1.843 + Compress(ECompressNoPurge);
1.844 + TInt gap=qptr->FollowingGap();
1.845 + MoveDown(gap);
1.846 + }
1.847 + }
1.848 +
1.849 +void CEventQueue::MoveToFront()
1.850 + {
1.851 + if (this==iQueueList.First())
1.852 + return;
1.853 + Wait();
1.854 + CEventQueue* qptr;
1.855 + TInt gap=0;
1.856 + TDblQueIter<CEventQueue> iter(iQueueList);
1.857 + iter.SetToLast();
1.858 + while((qptr=iter--)!=NULL)
1.859 + {
1.860 + if (gap<iQueueSize)
1.861 + qptr->Compress(ECompressNoPurge);
1.862 + gap=qptr->SqueezeUp();
1.863 + }
1.864 + if (gap>=iQueueSize)
1.865 + EventCopy(iGlobalEventQueue,iEventPtr,iQueueSize);
1.866 + else
1.867 + {
1.868 + EventCopy(iGlobalEventQueue,iEventPtr,gap);
1.869 + iEventPtr+=gap;
1.870 + TWsEvent copyBuf[ECopyBufSize]; // temp buffer, can copy upto ECopyBufSize events at a time
1.871 + TInt eventsToGo=iQueueSize-gap;
1.872 + iQueueSize=gap;
1.873 + do
1.874 + {
1.875 + TInt copy=Min(eventsToGo,ECopyBufSize);
1.876 + Mem::Copy(©Buf[0],iEventPtr,copy*sizeof(TWsEvent));
1.877 + iter.Set(*this);
1.878 + iter--;
1.879 + while((qptr=iter--)!=NULL)
1.880 + qptr->MoveUp(copy);
1.881 + EventCopy(iGlobalEventQueue+iQueueSize,©Buf[0],copy);
1.882 + iQueueSize+=copy;
1.883 + eventsToGo-=copy;
1.884 + iEventPtr+=copy;
1.885 + } while(eventsToGo>0);
1.886 + }
1.887 + iEventPtr=iGlobalEventQueue;
1.888 + this->iLink.Deque();
1.889 + iQueueList.AddFirst(*this);
1.890 + __CHECK_QUEUE();
1.891 + Signal();
1.892 + }
1.893 +
1.894 +// CEventQueue
1.895 +
1.896 +CEventQueue::CEventQueue(CWsClient* aOwner) : CEventBase(aOwner)
1.897 + {
1.898 + __DECLARE_NAME(_S("CEventQueue"));
1.899 + }
1.900 +
1.901 +CEventQueue::~CEventQueue()
1.902 + {
1.903 + RemoveQueue();
1.904 + }
1.905 +
1.906 +void CEventQueue::InitStaticsL()
1.907 + {
1.908 + User::LeaveIfError(iMutex.CreateLocal());
1.909 + }
1.910 +
1.911 +void CEventQueue::DeleteStaticsL()
1.912 + {
1.913 + iMutex.Close();
1.914 + }
1.915 +
1.916 +void CEventQueue::ConstructL()
1.917 + {
1.918 + AddQueueL();
1.919 + Mem::FillZ(&iNullEvent,sizeof(iNullEvent));
1.920 + }
1.921 +
1.922 +TWsEvent* CEventQueue::EventPtr(TInt index)
1.923 + {
1.924 + return(iEventPtr+((iHead+index)%iQueueSize));
1.925 + }
1.926 +
1.927 +TBool CEventQueue::QueueEvent(const TWsEvent &event)
1.928 + {
1.929 + TWservEventPriorities priority=EEventPriorityLow;
1.930 +#ifdef SYMBIAN_PROCESS_MONITORING_AND_STARTUP
1.931 + if (event.Type()==EEventPassword || event.Type()==EEventSwitchOff ||
1.932 + event.Type()==EEventKeySwitchOff || event.Type()==EEventRestartSystem)
1.933 +#else
1.934 + if (event.Type()==EEventPassword || event.Type()==EEventSwitchOff || event.Type()==EEventKeySwitchOff)
1.935 +#endif
1.936 + {
1.937 + priority=EEventPriorityHigh;
1.938 + }
1.939 + return(QueueEvent(event,priority));
1.940 + }
1.941 +
1.942 +TBool CEventQueue::CheckRoom()
1.943 +//
1.944 +// If the queue is full and room is created return ETrue
1.945 +//
1.946 + {
1.947 + TBool ret=EFalse;
1.948 + Wait();
1.949 + if (iCount==iQueueSize && Expand(EEventPriorityHigh))
1.950 + ret=ETrue;
1.951 + Signal();
1.952 + return(ret);
1.953 + }
1.954 +
1.955 +TBool CEventQueue::QueueEvent(const TWsEvent &event, TWservEventPriorities aPriority)
1.956 +//
1.957 +// Queue an event, returns ETrue if queued or delivered, EFalse if the queue was full.
1.958 +//
1.959 + {
1.960 + TBool ret=ETrue;
1.961 + Wait();
1.962 + if (iCount==iQueueSize && !Expand(aPriority))
1.963 + {
1.964 + ret=EFalse;
1.965 +#ifdef LOG_WSERV_EVENTS
1.966 + RDebug::Printf("WSEVENT: CEventQueue::QueueEvent(): 0x%X: Queue Full!!!!!, iCount = %d, iQueueSize = %d", this, iCount, iQueueSize);
1.967 + RDebug::Print(_L("WSEVENT: CEventQueue::QueueEvent(): 0x%X: Queue Full!!!!! TWsEvent.Type() = %S"), this, &WsEventName(event));
1.968 +#endif
1.969 + }
1.970 + else
1.971 + {
1.972 + if (!iEventMsg.IsNull())
1.973 + {
1.974 + SignalEvent();
1.975 + }
1.976 +#ifdef LOG_WSERV_EVENTS
1.977 + RDebug::Printf("_WSEVENT: CEventQueue::QueueEvent, Right before adding the event");
1.978 +#endif
1.979 + *EventPtr(iCount++)=event;
1.980 +#ifdef LOG_WSERV_EVENTS
1.981 + RDebug::Print(_L("_WSEVENT: CEventQueue::QueueEvent, Event %S successfully queued"), &WsEventName(event));
1.982 +#endif
1.983 + }
1.984 + Signal();
1.985 + return(ret);
1.986 + }
1.987 +
1.988 +TBool CEventQueue::QueueEvent(TUint32 aTarget, TInt aEvent, TInt aIntVal)
1.989 + {
1.990 + TWsEvent event;
1.991 + event.SetType(aEvent);
1.992 + event.SetHandle(aTarget);
1.993 + event.SetTimeNow();
1.994 + *(event.Int()) = aIntVal;
1.995 + return(QueueEvent(event));
1.996 + }
1.997 +
1.998 +void CEventQueue::UpdateLastEvent(const TWsEvent &event)
1.999 + {
1.1000 + WS_ASSERT_DEBUG(iCount>0, EWsPanicQueueUpdateCount);
1.1001 + Mem::Copy(EventPtr(iCount-1)->EventData(),event.EventData(),TWsEvent::EWsEventDataSize);
1.1002 + }
1.1003 +
1.1004 +/*
1.1005 +Replaces last pointer event related to particular pointer with new one.
1.1006 +
1.1007 +While searching for event to replace this method considers all events on the
1.1008 +queue except EMove and EDrag pointer events from pointers different than aEvent.
1.1009 +If the last of these events under consideration:
1.1010 +(1) is a pointer event,
1.1011 +(2) has the same type as aEvent,
1.1012 +(3) its type is either EMove or EDrag and
1.1013 +(4) has the same window handle as aEvent,
1.1014 +then it is removed from the queue and aEvent is put at the end of the queue.
1.1015 +
1.1016 +@return ETrue if event on the queue has been replaced with aEvent, EFalse otherwise.
1.1017 +*/
1.1018 +TBool CEventQueue::UpdateLastPointerEvent(const TWsEvent &aEvent)
1.1019 + {
1.1020 + if (aEvent.Pointer()->iType == TPointerEvent::EMove || aEvent.Pointer()->iType == TPointerEvent::EDrag)
1.1021 + {
1.1022 + Wait();
1.1023 +
1.1024 + if (iCount == 0)
1.1025 + {
1.1026 + Signal();
1.1027 + return EFalse;
1.1028 + }
1.1029 +
1.1030 + // loop through all events on the queue starting from the last one
1.1031 + TWsEvent* evToUpdate = EventPtr(iCount);
1.1032 + TWsEvent* evOnHead = &iEventPtr[iHead];
1.1033 + while (evToUpdate != evOnHead)
1.1034 + {
1.1035 + DecEventPointer(evToUpdate);
1.1036 +
1.1037 + // conditions that stop searching
1.1038 + if ( (evToUpdate->Type() != EEventPointer) // found non-pointer event
1.1039 + || (evToUpdate->Pointer()->iType != TPointerEvent::EMove && evToUpdate->Pointer()->iType != TPointerEvent::EDrag) // pointer event but wrong type
1.1040 + || ( (TAdvancedPointerEventHelper::PointerNumber(*evToUpdate) == TAdvancedPointerEventHelper::PointerNumber(aEvent))
1.1041 + && ( (evToUpdate->Handle() != aEvent.Handle()) // good number & bad handle
1.1042 + || (evToUpdate->Pointer()->iType != aEvent.Pointer()->iType)))) // good number & bad type
1.1043 + {
1.1044 + Signal();
1.1045 + return EFalse;
1.1046 + }
1.1047 + else if (TAdvancedPointerEventHelper::PointerNumber(*evToUpdate) == TAdvancedPointerEventHelper::PointerNumber(aEvent))
1.1048 + {
1.1049 + // we found event to update: evToUpdate is pointer event with right type, pointer number
1.1050 + // and window handle
1.1051 +
1.1052 + if (evToUpdate == EventPtr(iCount - 1))
1.1053 + {
1.1054 + UpdateLastEvent(aEvent);
1.1055 + }
1.1056 + else
1.1057 + {
1.1058 + RemoveEvent(evToUpdate);
1.1059 + *EventPtr(iCount++) = aEvent;
1.1060 + }
1.1061 + Signal();
1.1062 + return ETrue;
1.1063 + }
1.1064 +
1.1065 + // evToUpdate is EMove or EDrag pointer event with different pointer id,
1.1066 + // continue to loop through the queue
1.1067 + }
1.1068 + Signal();
1.1069 + }
1.1070 + return EFalse;
1.1071 + }
1.1072 +
1.1073 +void CEventQueue::GetData()
1.1074 +//
1.1075 +// If there is an outstanding event in the queue, reply with it's data and remove it from the Q
1.1076 +//
1.1077 + {
1.1078 + if (iCount>0)
1.1079 + {
1.1080 + WS_ASSERT_DEBUG((iEventPtr+iHead)->Type()!=EEventMarkInvalid, EWsPanicCheckEventQueue);
1.1081 + CEventBase::GetData(iEventPtr+iHead,sizeof(*iEventPtr));
1.1082 +#ifdef LOG_WSERV_EVENTS
1.1083 + RDebug::Printf("_WSEVENT: CEventQueue::GetData(), TWsEvent.Type() = %d", (iEventPtr+iHead)->Type());
1.1084 +#endif
1.1085 + __ZAP_EVENT(iEventPtr+iHead);
1.1086 + iHead=(iHead+1)%iQueueSize;
1.1087 + iCount--;
1.1088 + }
1.1089 + else
1.1090 + CEventBase::GetData(&iNullEvent,sizeof(iNullEvent));
1.1091 + }
1.1092 +
1.1093 +void CEventQueue::EventReady(const RMessagePtr2& aEventMsg)
1.1094 +//
1.1095 +// Queue a read of an event notification
1.1096 +//
1.1097 + {
1.1098 + EventReadyCheck();
1.1099 + Wait();
1.1100 + iEventMsg=aEventMsg;
1.1101 + if (iCount>0)
1.1102 + SignalEvent();
1.1103 + Signal();
1.1104 + }
1.1105 +
1.1106 +void CEventQueue::RemoveEvent(TInt index)
1.1107 +//
1.1108 +// Remove event 'index' in the queue, this event MUST exist in the queue
1.1109 +//
1.1110 + {
1.1111 +#ifdef LOG_WSERV_EVENTS
1.1112 + RDebug::Printf("_WSEVENT: CEventQueue::RemoveEvent(index), Remove event index %d in the queue", index);
1.1113 +#endif
1.1114 + WS_ASSERT_DEBUG(index < iCount, EWsPanicCheckEventQueue);
1.1115 + RemoveEvent(EventPtr(index));
1.1116 + }
1.1117 +
1.1118 +void CEventQueue::RemoveEvent(TWsEvent* aEvToRemove)
1.1119 +//
1.1120 +// Remove event in the queue, this event MUST exist in the queue
1.1121 +//
1.1122 + {
1.1123 +#ifdef LOG_WSERV_EVENTS
1.1124 + RDebug::Print(_L("_WSEVENT: CEventQueue::RemoveEvent(aEvToRemove), Remove event %S in the queue"), &WsEventName(*aEvToRemove));
1.1125 +#endif
1.1126 + iCount--;
1.1127 + TWsEvent* last = EventPtr(iCount);
1.1128 + TWsEvent* prev;
1.1129 + while(aEvToRemove!=last)
1.1130 + {
1.1131 + prev = aEvToRemove;
1.1132 + IncEventPointer(aEvToRemove);
1.1133 + *prev = *aEvToRemove;
1.1134 + }
1.1135 + __ZAP_EVENT(last);
1.1136 + }
1.1137 +
1.1138 +const TWsEvent* CEventQueue::PeekLastEvent()
1.1139 +//
1.1140 +// Return a read only pointer to the last event in the queue (or NULL if no event)
1.1141 +//
1.1142 + {
1.1143 + if (iCount==0)
1.1144 + return(NULL);
1.1145 + return(EventPtr(iCount-1));
1.1146 + }
1.1147 +
1.1148 +void CEventQueue::Wait()
1.1149 + {
1.1150 + iMutex.Wait();
1.1151 + }
1.1152 +
1.1153 +void CEventQueue::Signal()
1.1154 + {
1.1155 + iMutex.Signal();
1.1156 + }
1.1157 +
1.1158 +void CEventQueue::WalkEventQueue(EventQueueWalk aFunc, TAny* aFuncParam)
1.1159 + {
1.1160 + Wait();
1.1161 +restart:
1.1162 + for (TInt index=0;index<iCount;index++)
1.1163 + {
1.1164 + TWsEvent* event=EventPtr(index);
1.1165 + switch((aFunc)(aFuncParam,event))
1.1166 + {
1.1167 + case EEventQueueWalkDeleteEvent:
1.1168 + RemoveEvent(index--);
1.1169 + case EEventQueueWalkOk:
1.1170 + break;
1.1171 + case EEventQueueWalkRestart:
1.1172 + goto restart;
1.1173 + }
1.1174 + }
1.1175 + Signal();
1.1176 + }