kernel/eka/euser/cbase/ub_act.cpp
changeset 0 a41df078684a
child 1 cb3e90eb7d89
child 6 0173bcd7697c
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\euser\cbase\ub_act.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "ub_std.h"
       
    19 #include "us_data.h"
       
    20 
       
    21 #ifdef __SMP__
       
    22 #include <e32atomics.h>
       
    23 #endif
       
    24 
       
    25 
       
    26 
       
    27 #pragma warning( disable : 4705 )	// statement has no effect
       
    28 EXPORT_C CActive::CActive(TInt aPriority)
       
    29 /**
       
    30 Constructs the active object with the specified priority.
       
    31 
       
    32 Derived classes must define and implement a constructor through which the
       
    33 priority can be specified. A typical implementation calls this active object
       
    34 constructor through a constructor initialization list.
       
    35 
       
    36 @param aPriority An integer specifying the priority of this active object.
       
    37                  CActive::TPriority defines a standard set of priorities.
       
    38 */
       
    39 	{
       
    40 	iLink.iPriority=aPriority;
       
    41 	}
       
    42 #pragma warning( default : 4705 )
       
    43 
       
    44 
       
    45 
       
    46 
       
    47 EXPORT_C CActive::~CActive()
       
    48 /**
       
    49 Frees resources prior to destruction.
       
    50 
       
    51 Specifically, it removes this active object from the active scheduler's
       
    52 list of active objects.
       
    53 
       
    54 Typically, a derived class calls Cancel() in its destructor.
       
    55 
       
    56 @panic E32USER-CBase 40 if the active object has an outstanding request when
       
    57        the destructor is called,
       
    58 
       
    59 @see CActive::Cancel
       
    60 */
       
    61 	{
       
    62 	__ASSERT_ALWAYS(!(iStatus.iFlags&TRequestStatus::EActive),Panic(EReqStillActiveOnDestruct));
       
    63 	if (IsAdded())
       
    64 		iLink.Deque();
       
    65 	}
       
    66 
       
    67 
       
    68 
       
    69 
       
    70 EXPORT_C void CActive::Cancel()
       
    71 /**
       
    72 Cancels the wait for completion of an outstanding request.
       
    73 
       
    74 If there is no request outstanding, then the function does nothing.
       
    75 
       
    76 If there is an outstanding request, the function:
       
    77 
       
    78 1. calls the active object's DoCancel() function, provided by
       
    79    the derived class to implement cancellation of the request.
       
    80 
       
    81 2. waits for the cancelled request to complete; this must complete as fast as
       
    82    possible.
       
    83 
       
    84 3. marks the active object's request as complete (i.e. the request is no longer
       
    85    outstanding).
       
    86 
       
    87 @see CActive::DoCancel
       
    88 @see CActive::IsActive
       
    89 @see CActive::~CActive
       
    90 @see User::WaitForRequest
       
    91 */
       
    92 	{
       
    93 	if (iStatus.iFlags&TRequestStatus::EActive)
       
    94 		{
       
    95 		DoCancel();
       
    96 		User::WaitForRequest(iStatus);
       
    97     	iStatus.iFlags&=~(TRequestStatus::EActive | TRequestStatus::ERequestPending); //iActive=EFalse;
       
    98 		}
       
    99 	}
       
   100 
       
   101 
       
   102 
       
   103 
       
   104 EXPORT_C void CActive::Deque()
       
   105 /**
       
   106 Removes the active object from the active scheduler's list of active objects.
       
   107 
       
   108 Before being removed from the active scheduler's list, the function cancels
       
   109 any outstanding request.
       
   110 
       
   111 @see CActive::Cancel
       
   112 */
       
   113 	{
       
   114 	__ASSERT_ALWAYS(IsAdded(),Panic(EActiveNotAdded));
       
   115 	Cancel();
       
   116 	iLink.Deque();
       
   117 	iLink.iNext=NULL; // Must do this or object cannot be re-queued
       
   118 	}
       
   119 
       
   120 
       
   121 
       
   122 
       
   123 EXPORT_C void CActive::SetActive()
       
   124 /**
       
   125 Indicates that the active object has issued a request and that
       
   126 it is now outstanding.
       
   127 
       
   128 Derived classes must call this function after issuing a request.
       
   129 
       
   130 A request is automatically marked as complete (i.e. it is no longer
       
   131 outstanding) by:
       
   132 
       
   133 1. the active scheduler, immediately before it calls the active object's RunL()
       
   134    function.
       
   135 
       
   136 or
       
   137 
       
   138 2. the active object within the implementation of the Cancel() function.
       
   139 
       
   140 @see CActive::IsActive
       
   141 @see CActive::RunL
       
   142 @see CActive::Cancel
       
   143 */
       
   144 	{
       
   145 	__ASSERT_ALWAYS(!(iStatus.iFlags&TRequestStatus::EActive),Panic(EReqAlreadyActive));
       
   146 	__ASSERT_ALWAYS(IsAdded(),Panic(EActiveNotAdded));
       
   147 	iStatus.iFlags|=TRequestStatus::EActive;
       
   148 	}
       
   149 
       
   150 
       
   151 
       
   152 
       
   153 EXPORT_C void CActive::SetPriority(TInt aPriority)
       
   154 /**
       
   155 Sets the priority of the active object.
       
   156 
       
   157 @param aPriority An integer specifying the new priority of this active object.
       
   158                  CActive::TPriority defines a standard set of priorities.
       
   159 
       
   160 @panic E32USER-CBase 50 if this function is called while a request
       
   161        is outstanding.
       
   162 */
       
   163 	{
       
   164 	__ASSERT_ALWAYS(!(iStatus.iFlags&TRequestStatus::EActive),Panic(ESetPriorityActive));
       
   165 	iLink.iPriority=aPriority;
       
   166 	if (IsAdded())
       
   167 		{
       
   168 		Deque();
       
   169 		iLink.iNext=NULL; // Make this not added
       
   170 		CActiveScheduler::Add(this);
       
   171 		}
       
   172 	}
       
   173 
       
   174 
       
   175 
       
   176 
       
   177 EXPORT_C TInt CActive::RunError(TInt aError)
       
   178 /**
       
   179 Handles a leave occurring in the request completion event handler RunL().
       
   180 
       
   181 The active scheduler calls this function if this active object's RunL()
       
   182 function leaves. This gives this active object the opportunity to perform
       
   183 any necessary cleanup.
       
   184 
       
   185 A derived class implementation should handle the leave and return KErrNone.
       
   186 Returning any other value results in the active scheduler function
       
   187 CActiveScheduler::Error() being called.
       
   188 
       
   189 The default implementation simply returns the leave code.
       
   190 
       
   191 Note that if the active scheduler is to handle the error, a suitably derived
       
   192 CActiveScheduler::Error() function must be supplied.
       
   193 
       
   194 @param aError The leave code
       
   195 
       
   196 @return The default implementation returns aError. A derived class
       
   197         implementation should return KErrNone, if it handles the leave;
       
   198         otherwise it should return any suitable value to cause the handling
       
   199         of the error to be propagated back to the active scheduler.
       
   200 
       
   201 @see CActiveScheduler::Error
       
   202 */
       
   203 	{
       
   204 	return aError;
       
   205 	}
       
   206 
       
   207 
       
   208 
       
   209 
       
   210 /**
       
   211 Extension function
       
   212 
       
   213 
       
   214 */
       
   215 EXPORT_C TInt CActive::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
       
   216 	{
       
   217 	return CBase::Extension_(aExtensionId, a0, a1);
       
   218 	}
       
   219 
       
   220 
       
   221 
       
   222 
       
   223 EXPORT_C CIdle* CIdle::New(TInt aPriority)
       
   224 /**
       
   225 Allocates and initialises an Idle time active object and adds it to the active
       
   226 scheduler.
       
   227 
       
   228 @param aPriority An integer specifying the priority of this active object.
       
   229                  It must be lower than that of all other active objects on
       
   230                  the active scheduler.
       
   231                  The value CActive::TPriority::EPriorityIdle is recommended.
       
   232 
       
   233 @return Pointer to the new Idle time active object, or NULL if the object could
       
   234         not be created.
       
   235 */
       
   236 	{
       
   237 	CIdle *pI=new CIdle(aPriority);
       
   238 	if (pI!=NULL)
       
   239 		CActiveScheduler::Add(pI);
       
   240 	return(pI);
       
   241 	}
       
   242 
       
   243 
       
   244 
       
   245 
       
   246 EXPORT_C CIdle* CIdle::NewL(TInt aPriority)
       
   247 /**
       
   248 Allocates and initialises an Idle time active object, adds it to the active
       
   249 scheduler, but leaves on failure.
       
   250 
       
   251 @param aPriority An integer specifying the priority of this active object.
       
   252                  It must be lower than that of all other active objects on
       
   253                  the active scheduler.
       
   254                  The value CActive::TPriority::EPriorityIdle is recommended.
       
   255 
       
   256 @return Pointer to the new Idle time active object.
       
   257 */
       
   258 	{
       
   259 	CIdle *pI=new(ELeave) CIdle(aPriority);
       
   260 	CActiveScheduler::Add(pI);
       
   261 	return(pI);
       
   262 	}
       
   263 
       
   264 
       
   265 
       
   266 
       
   267 
       
   268 EXPORT_C CIdle::CIdle(TInt aPriority)
       
   269 	: CActive(aPriority)
       
   270 /**
       
   271 Protected constructor taking a priority value.
       
   272 
       
   273 Sets this active object's priority value.
       
   274 
       
   275 @param aPriority The active object priority value.
       
   276 */
       
   277 	{}
       
   278 
       
   279 
       
   280 
       
   281 
       
   282 EXPORT_C CIdle::~CIdle()
       
   283 /**
       
   284 Frees resources prior to destruction.
       
   285 
       
   286 Specifically, it cancels any outstanding request.
       
   287 */
       
   288 	{
       
   289 	Cancel();
       
   290 	}
       
   291 
       
   292 
       
   293 
       
   294 
       
   295 EXPORT_C void CIdle::Start(TCallBack aCallBack)
       
   296 /**
       
   297 Starts the background task.
       
   298 
       
   299 The background task is encapsulated in the callback. The function represented
       
   300 by this callback is called every time this Idle time active object is scheduled
       
   301 to run.
       
   302 
       
   303 The callback function should be structured to perform a background task in
       
   304 many increments, i.e. it should voluntarily relinquish control (i.e. return)
       
   305 after a suitable time interval to allow other, higher priority events to be
       
   306 handled.
       
   307 
       
   308 If the callback function has further work to do, it should return a true value.
       
   309 This ensures that the active object is scheduled to run again later.
       
   310 
       
   311 Once the callback function has finally completed its work, it should return
       
   312 a false value. The active object is then no longer scheduled to run.
       
   313 
       
   314 @param aCallBack A callback object encapsulating a function which is called
       
   315                  when no higher priority active object is ready to run.
       
   316 */
       
   317 	{
       
   318 	iCallBack=aCallBack;
       
   319 	iStatus=KRequestPending;
       
   320 	TRequestStatus *pS=(&iStatus);
       
   321 	User::RequestComplete(pS,0);
       
   322 	SetActive();
       
   323 	}
       
   324 
       
   325 
       
   326 
       
   327 
       
   328 EXPORT_C void CIdle::RunL()
       
   329 /**
       
   330 Handles this idle active object's request completion event.
       
   331 
       
   332 It is called when nothing of a higher priority can be scheduled.
       
   333 
       
   334 @see CActive::RunL
       
   335 */
       
   336 	{
       
   337 	if (iCallBack.CallBack())
       
   338 		Start(iCallBack);
       
   339 	}
       
   340 
       
   341 
       
   342 
       
   343 
       
   344 EXPORT_C void CIdle::DoCancel()
       
   345 /**
       
   346 Implements the cancellation of an outstanding request.
       
   347 
       
   348 This function is called by the active object's Cancel() function.
       
   349 
       
   350 @see CActive::DoCancel
       
   351 */
       
   352 	{
       
   353 	}
       
   354 
       
   355 
       
   356 
       
   357 
       
   358 EXPORT_C void CAsyncOneShot::Call()
       
   359 /**
       
   360 Queues this active object to be run once.
       
   361 
       
   362 @panic E32USER-CBase 2 In debug builds only, if this active object has not
       
   363        already been added to the active scheduler.
       
   364 */
       
   365 	{
       
   366 	__ASSERT_DEBUG(IsAdded(),Panic(ECAsyncOneShotNotAdded));
       
   367 	TRequestStatus *pS=(&iStatus);
       
   368 	iStatus = KRequestPending;
       
   369 	SetActive();
       
   370 	iThread.RequestComplete(pS,0);
       
   371 	}
       
   372 
       
   373 
       
   374 
       
   375 
       
   376 EXPORT_C void CAsyncOneShot::DoCancel()
       
   377 /**
       
   378 Implements cancellation of an outstanding request.
       
   379 
       
   380 The class provides an empty implementation.
       
   381 
       
   382 This is called by the destructor.
       
   383 */
       
   384 	{
       
   385 	// Empty
       
   386 	}
       
   387 
       
   388 
       
   389 
       
   390 
       
   391 EXPORT_C CAsyncOneShot::CAsyncOneShot(TInt aPriority)
       
   392 	:CActive(aPriority)
       
   393 /**
       
   394 Constructor taking a priority value.
       
   395 
       
   396 Specifically, the constructor:
       
   397 
       
   398 1. sets this active object's priority value
       
   399 
       
   400 2. opens a handle to the current thread to ensure that the thread cannot be
       
   401    closed until this CAsyncOneShot object is destroyed
       
   402 
       
   403 3. adds this active object to the current active scheduler.
       
   404 
       
   405 @param aPriority The active object priority value. CActive::TPriority defines
       
   406                  a standard set of priorities.
       
   407 
       
   408 @panic E32USER-CBase 93 if the attempt to open a handle to the current thread
       
   409        fails.
       
   410 */
       
   411 	{
       
   412 	Setup();
       
   413 	}
       
   414 
       
   415 
       
   416 
       
   417 
       
   418 void CAsyncOneShot::Setup()
       
   419 //
       
   420 // ensures that we are added to the Scheduler.
       
   421 //
       
   422 	{
       
   423 	// No error checking was done initially.  As this function is called from
       
   424 	// the c'tor, there is no way to fix it properly without breaking BC.  So
       
   425 	// we panic if something goes wrong (should only happen in extreme
       
   426 	// circumstances if the kernel heap is exhausted or heavily fragmented).
       
   427 	__ASSERT_ALWAYS(iThread.Duplicate(RThread()) == KErrNone, Panic(EAsyncOneShotSetupFailed));
       
   428 
       
   429 	// Add ourself to the current active scheduler
       
   430 	// This is because we might be being used as an inter thread call
       
   431 	// we need to make sure that we're on the correct scheduler for
       
   432 	// the RThread were going to duplicate.
       
   433 	CActiveScheduler::Add(this);
       
   434 	}
       
   435 
       
   436 
       
   437 
       
   438 
       
   439 EXPORT_C CAsyncOneShot::~CAsyncOneShot()
       
   440 /**
       
   441 Frees resources prior to destruction.
       
   442 
       
   443 Specifically, it closes the handle to the current thread.
       
   444 
       
   445 @see CActive::~CActive
       
   446 */
       
   447 	{
       
   448 	Cancel();
       
   449 	iThread.Close();
       
   450 	}
       
   451 
       
   452 
       
   453 
       
   454 
       
   455 EXPORT_C CAsyncCallBack::CAsyncCallBack(TInt aPriority)
       
   456 	: CAsyncOneShot(aPriority), iCallBack(NULL)
       
   457 /**
       
   458 Constructor taking a priority value.
       
   459 
       
   460 Specifically, the constructor sets this active object's priority value through
       
   461 a call to the base class constructor in its ctor list.
       
   462 
       
   463 No call back is set, which means that it must be set subsequently through
       
   464 a call to the Set() function.
       
   465 
       
   466 @param aPriority The active object priority value. CActive::TPriority defines
       
   467                  a standard set of priorities.
       
   468 
       
   469 @see CAsyncCallBack::Set
       
   470 */
       
   471 	{
       
   472 	}
       
   473 
       
   474 
       
   475 
       
   476 
       
   477 EXPORT_C CAsyncCallBack::CAsyncCallBack(const TCallBack& aCallBack, TInt aPriority)
       
   478 	: CAsyncOneShot(aPriority), iCallBack(aCallBack)
       
   479 /**
       
   480 Constructor taking a priority value and a callback.
       
   481 
       
   482 Specifically, the constructor:
       
   483 
       
   484 1. sets this active object's priority value through a call to the base class
       
   485    constructor in its ctor list
       
   486 
       
   487 2. sets the callback; the function encapsulated by the callback is called when
       
   488    this active object is scheduled to run.
       
   489 
       
   490 @param aCallBack A reference to a callback object encapsulating a function
       
   491                  which is called when this active object is ready to run.
       
   492                  The constructor takes a copy of this callback object, which
       
   493                  means that it can be safely discarded after construction.
       
   494 @param aPriority The active object priority value.
       
   495 */
       
   496 	{
       
   497 	}
       
   498 
       
   499 
       
   500 
       
   501 
       
   502 EXPORT_C CAsyncCallBack::~CAsyncCallBack()
       
   503 /**
       
   504 Destructor.
       
   505 */
       
   506 	{
       
   507 	}
       
   508 
       
   509 
       
   510 
       
   511 
       
   512 EXPORT_C void CAsyncCallBack::CallBack()
       
   513 /**
       
   514 Queues this active object to be run, if it is not already queued.
       
   515 */
       
   516 	{
       
   517 	if (!IsActive())
       
   518 		Call();
       
   519 	}
       
   520 
       
   521 
       
   522 
       
   523 
       
   524 EXPORT_C void CAsyncCallBack::Set(const TCallBack& aCallBack)
       
   525 /**
       
   526 Sets the call back.
       
   527 
       
   528 @param aCallBack A reference to a callback object encapsulating a function
       
   529                  which is called when this active object is ready to run.
       
   530 
       
   531 @panic E32USER-CBase 1 if the active object is currently active.
       
   532 */
       
   533 	{
       
   534 	__ASSERT_ALWAYS(!IsActive(), Panic(ECAsyncCBIsActive));
       
   535 	iCallBack = aCallBack;
       
   536 	}
       
   537 
       
   538 
       
   539 
       
   540 
       
   541 void CAsyncCallBack::RunL()
       
   542 /**
       
   543 Calls the callback function.
       
   544 
       
   545 @see TCallBack::CallBack
       
   546 */
       
   547 	{
       
   548 	iCallBack.CallBack();
       
   549 	}
       
   550 
       
   551 
       
   552 
       
   553 
       
   554 struct CActiveScheduler::TLoop
       
   555 	{
       
   556 	TLoop* iNext;
       
   557 	CActiveScheduler::TLoopOwner* iOwner;
       
   558 	TCallBack iCallback;
       
   559 	TInt iExitCode;
       
   560 	};
       
   561 
       
   562 CActiveScheduler::TLoopOwner* const KLoopNoOwner=reinterpret_cast<CActiveScheduler::TLoopOwner*>(1);
       
   563 CActiveScheduler::TLoopOwner* const KLoopInactive=0;
       
   564 
       
   565 
       
   566 
       
   567 
       
   568 EXPORT_C CActiveSchedulerWait::CActiveSchedulerWait()
       
   569 /**
       
   570 Default constructor.
       
   571 */
       
   572 	{}
       
   573 
       
   574 
       
   575 
       
   576 
       
   577 
       
   578 EXPORT_C CActiveSchedulerWait::~CActiveSchedulerWait()
       
   579 /**
       
   580 Ensures that the attached scheduler loop, and all nested loops, are stopped
       
   581 prior to destruction.
       
   582 
       
   583 @see AsyncStop()
       
   584 */
       
   585 	{
       
   586 	if (IsStarted())
       
   587 		AsyncStop();
       
   588 	}
       
   589 
       
   590 
       
   591 
       
   592 
       
   593 EXPORT_C void CActiveSchedulerWait::Start()
       
   594 /**
       
   595 Starts a new wait loop under the control of the current active scheduler.
       
   596 
       
   597 Compared with CActiveScheduler::Start(), this object owns control of
       
   598 the scheduling loop that is started, and that loop can only be stopped
       
   599 by using this objects AsyncStop() function or the CActiveScheduler::Halt()
       
   600 function. Start() only returns when either of thos has occurred.
       
   601 
       
   602 This is the preferred way to start a nested wait loop. Typically, a nested
       
   603 wait loop is used when the handling of a completed event in an active object
       
   604 requires processing further events from the other active objects before it
       
   605 can complete. This is a form of modal processing.
       
   606 
       
   607 @panic E32USER-CBase 44 if the thread does not have an active scheduler installed.
       
   608 @panic E32USER-CBase 91 if this object has already been started.
       
   609 
       
   610 @see CActiveSchedulerWait::AsyncStop
       
   611 @see CActiveSchedulerWait::IsStarted
       
   612 @see CActiveScheduler::Start
       
   613 @see CActiveScheduler::Halt
       
   614 */
       
   615 	{
       
   616 	__ASSERT_ALWAYS(!IsStarted(), Panic(EActiveSchedulerWaitAlreadyStarted));		// can only start a CActiveSchedulerWait if it isn't already started
       
   617 	CActiveScheduler::Start(&iLoop);
       
   618 	}
       
   619 
       
   620 
       
   621 
       
   622 
       
   623 EXPORT_C void CActiveSchedulerWait::AsyncStop()
       
   624 /**
       
   625 Stops the scheduling loop owned by this object.
       
   626 
       
   627 Note that the corresponding call to Start() only returns once all nested
       
   628 scheduler loops have stopped.
       
   629 
       
   630 @panic E32USER-CBase 92 if the wait object has not been started.
       
   631 */
       
   632 	{
       
   633 	AsyncStop(TCallBack());
       
   634 	}
       
   635 
       
   636 
       
   637 
       
   638 
       
   639 EXPORT_C void CActiveSchedulerWait::AsyncStop(const TCallBack& aCallMeWhenStopped)
       
   640 /**
       
   641 Stops the scheduling loop owned by this object, specifying a callback.
       
   642 
       
   643 This version of AsyncStop() provides a callback which is invoked immediately
       
   644 after the scheduler loop actually stops before the corresponding call
       
   645 to Start() returns.
       
   646 
       
   647 Note that the corresponding call to Start() only returns once all nested
       
   648 scheduler loops have stopped.
       
   649 
       
   650 @param aCallMeWhenStopped The callback to invoke when the scheduler loop exits.
       
   651 
       
   652 @panic E32USER-CBase 92 if the wait object has not been started.
       
   653  */
       
   654 	{
       
   655 	CActiveScheduler::TLoopOwner loop=iLoop;
       
   656 	__ASSERT_ALWAYS(loop, Panic(EActiveSchedulerWaitNotStarted));		// can only stop a CActiveSchedulerWait if it's started
       
   657 	__ASSERT_DEBUG(loop->iOwner==&iLoop, User::Invariant());
       
   658 
       
   659 	loop->iCallback = aCallMeWhenStopped;
       
   660 	loop->iOwner = KLoopInactive;			// disconnect from owner
       
   661 	iLoop = 0;
       
   662 	}
       
   663 
       
   664 
       
   665 
       
   666 
       
   667 EXPORT_C TBool CActiveSchedulerWait::CanStopNow() const
       
   668 /**
       
   669 Reports whether stopping will have immediate effect.
       
   670 
       
   671 This returns an indication of whether a call to AsyncStop() would be
       
   672 expected to stop the scheduler loop immediately, or whether it will
       
   673 have to wait until nested scheduler loops have stopped. This may alter
       
   674 which version of AsyncStop() you would want to call.
       
   675 
       
   676 @return Boolean indicating if the scheduling loop would stop immediately.
       
   677 
       
   678 @panic E32USER-CBase 92 if the wait object has not been started.
       
   679 
       
   680 @see CActiveSchedulerWait::Start
       
   681 @see CActiveSchedulerWait::AsyncStop
       
   682 */
       
   683  	{
       
   684 	__ASSERT_ALWAYS(IsStarted(), Panic(EActiveSchedulerWaitNotStarted));		// Scheduler must be running
       
   685 	for (CActiveScheduler::TLoop* loop=GetActiveScheduler()->iStack; loop; loop=loop->iNext)
       
   686 		{
       
   687 		if (loop==iLoop)
       
   688 			return ETrue;
       
   689 		if (loop->iOwner != KLoopInactive)
       
   690 			break;
       
   691 		}
       
   692 	return EFalse;
       
   693 	}
       
   694 
       
   695 
       
   696 
       
   697 EXPORT_C CActiveScheduler::CActiveScheduler()
       
   698 	: iActiveQ(_FOFF(CActive,iLink))
       
   699 /**
       
   700 Constructs an active scheduler.
       
   701 
       
   702 After construction, the scheduler should be installed.
       
   703 
       
   704 @see CActiveScheduler::Install
       
   705 */
       
   706 	{}
       
   707 
       
   708 
       
   709 
       
   710 
       
   711 EXPORT_C CActiveScheduler::~CActiveScheduler()
       
   712 /**
       
   713 Frees resources prior to destruction.
       
   714 
       
   715 Specifically, it removes all active objects from the active scheduler's list
       
   716 of active objects.
       
   717 
       
   718 An active scheduler should only be destroyed when the top-level call to Start()
       
   719 has returned.
       
   720 
       
   721 @see CActiveScheduler::Start
       
   722 @see CActiveScheduler::Stop
       
   723 */
       
   724 	{
       
   725 	while (!iActiveQ.IsEmpty())
       
   726 		iActiveQ.First()->Deque();
       
   727 	if (GetActiveScheduler()==this)
       
   728 		SetActiveScheduler(NULL);
       
   729 	}
       
   730 
       
   731 
       
   732 
       
   733 
       
   734 EXPORT_C void CActiveScheduler::Install(CActiveScheduler *aManager)
       
   735 /**
       
   736 Installs the specified active scheduler as the current active scheduler.
       
   737 
       
   738 The installed active scheduler now handles events for this thread.
       
   739 
       
   740 The current active scheduler can be uninstalled by passing a NULL pointer.
       
   741 
       
   742 @param aManager A pointer to the active scheduler to be installed.
       
   743                 If this is NULL, the current active scheduler is uninstalled.
       
   744 
       
   745 @panic E32USER-CBase 43 if If there is already an installed active scheduler.
       
   746 */
       
   747 	{
       
   748 	if (aManager!=NULL)
       
   749 		__ASSERT_ALWAYS(GetActiveScheduler()==NULL,Panic(EReqManagerAlreadyExists));
       
   750 	SetActiveScheduler(aManager);
       
   751 	}
       
   752 
       
   753 
       
   754 
       
   755 
       
   756 EXPORT_C void CActiveScheduler::Add(CActive *aRequest)
       
   757 /**
       
   758 Adds the specified active object to the current active scheduler.
       
   759 
       
   760 An active object can be removed from an active scheduler either by
       
   761 destroying the active object or by using its Deque() member function.
       
   762 
       
   763 @param aRequest Pointer to the active object to be added.
       
   764 
       
   765 @panic E32USER-CBase 41 if the active object aRequest has already been added
       
   766        to the current active scheduler.
       
   767 @panic E32USER-CBase 48 if aRequest is NULL.
       
   768 @panic E32USER-CBase 44 if the thread does not have an installed
       
   769        active scheduler.
       
   770 
       
   771 @see CActive::Deque
       
   772 */
       
   773 	{
       
   774 	CActiveScheduler *pS=GetActiveScheduler();
       
   775 	__ASSERT_ALWAYS(pS!=NULL,Panic(EReqManagerDoesNotExist));
       
   776 	__ASSERT_ALWAYS(aRequest,Panic(EReqNull));
       
   777 	__ASSERT_ALWAYS(!aRequest->IsAdded(),Panic(EReqAlreadyAdded));
       
   778 	pS->iActiveQ.Add(*aRequest);
       
   779 	}
       
   780 
       
   781 
       
   782 
       
   783 
       
   784 EXPORT_C void CActiveScheduler::WaitForAnyRequest()
       
   785 /**
       
   786 Wait for an asynchronous request to complete.
       
   787 
       
   788 The default implementation just calls User::WaitForAnyRequest().
       
   789 
       
   790 Derived classes can replace this. Typically, this would be done to implement
       
   791 code for maintaining an outstanding request; this would be followed by a call
       
   792 to User::WaitForAnyRequest().
       
   793 
       
   794 @see User::WaitForAnyRequest
       
   795 */
       
   796 	{
       
   797 	User::WaitForAnyRequest();
       
   798 	}
       
   799 
       
   800 
       
   801 
       
   802 
       
   803 EXPORT_C void CActiveScheduler::Start()
       
   804 /**
       
   805 Starts a new wait loop under the control of the current active scheduler.
       
   806 
       
   807 At least one active object, with an outstanding request, must be added
       
   808 to the scheduler before the wait loop is started, otherwise no events
       
   809 will occur and the thread will hang, or any events that do occur will be
       
   810 counted as stray signals, raising a panic.
       
   811 
       
   812 While Start() is executing, user code runs only:
       
   813 
       
   814 1. in the RunL() function of active objects known to the current active scheduler
       
   815 
       
   816 2. in the RunError() function of an active object that leaves from its RunL()
       
   817 
       
   818 3. in the current active scheduler’s Error() function, if an active object’s
       
   819    RunError() returns an error code.
       
   820 
       
   821 Start() returns only when a corresponding Stop() or Halt() is issued.
       
   822 
       
   823 Although this can be used to start a nested wait loop, this API is deprecated
       
   824 for that specific functionality, and a CActiveSchedulerWait object should be
       
   825 used instead.
       
   826 
       
   827 (Note that a nested wait loop is used when the handling of a completed event
       
   828  in an active object requires the processing of further events from the other
       
   829  active objects before it can complete. This is a form of modal processing.)
       
   830 
       
   831 @panic E32USER-CBase 44 if the thread does not have an active
       
   832        scheduler installed.
       
   833 
       
   834 @see CActiveScheduler::Stop
       
   835 @see CActiveScheduler::Halt
       
   836 @see CActive::RunL
       
   837 @see CActive::RunError
       
   838 @see CActiveScheduler::Error
       
   839 @see CActiveSchedulerWait
       
   840 */
       
   841 	{
       
   842 	Start(KLoopNoOwner);
       
   843 	}
       
   844 
       
   845 
       
   846 
       
   847 
       
   848 void CActiveScheduler::Start(TLoopOwner* aOwner)
       
   849 /**
       
   850 @internalComponent
       
   851 
       
   852 Start a new nesting level
       
   853 */
       
   854 	{
       
   855 	CActiveScheduler* pS=GetActiveScheduler();
       
   856 	__ASSERT_ALWAYS(pS!=NULL, Panic(EReqManagerDoesNotExist));
       
   857 
       
   858 	// Instantiate the local loop control
       
   859 	TLoop loop;
       
   860 	loop.iOwner=aOwner;
       
   861 	if (aOwner != KLoopNoOwner)
       
   862 		*aOwner=&loop;
       
   863 	loop.iNext=pS->iStack;
       
   864 	pS->iStack=&loop;
       
   865 	loop.iExitCode=0;
       
   866 
       
   867 	// Run the scheduler loop
       
   868 #if 1
       
   869 	// FIXME!!! Will support old-style leave-from-Error() transiently
       
   870 	// in order to avoid simultaneous integration requirement.
       
   871 	// This should be reverted to the conditionally excluded code once
       
   872 	// fixes have been made elsewhere
       
   873 	TRAPD(r,pS->Run(loop.iOwner));
       
   874 	if (r!=KErrNone)
       
   875 		{
       
   876 		loop.iExitCode = r;
       
   877 		TLoopOwner* owner=loop.iOwner;
       
   878 		if (TUint(owner) > TUint(KLoopNoOwner))
       
   879 			*owner = NULL;
       
   880 		}
       
   881 #else	// fixme
       
   882 #ifdef _DEBUG
       
   883 	// catch old-style bad behaviour - leaving from Error()
       
   884 	TRAPD(r,pS->Run(loop.iOwner));
       
   885 	__ASSERT_DEBUG(r==KErrNone,User::Invariant());
       
   886 #else
       
   887 	pS->Run(loop.iOwner);
       
   888 #endif
       
   889 #endif
       
   890 
       
   891 	pS->iStack=loop.iNext;
       
   892 	loop.iCallback.CallBack();
       
   893 	// propagate the exit-code via a leave (yuck, but blame BAFL & co.)
       
   894 	if (loop.iExitCode)
       
   895 		User::Leave(loop.iExitCode);
       
   896 	}
       
   897 
       
   898 /*
       
   899 @internalComponent
       
   900 
       
   901 Dummy Function. This is used as a dummy object to put onto the cleanupstack in order
       
   902 to check for imbalance in the CActiveScheduler::DoRunL.
       
   903  */
       
   904 void DummyFunc(TAny* /*aPtr*/)
       
   905 	{}
       
   906 
       
   907 
       
   908 #ifdef __LEAVE_EQUALS_THROW__
       
   909 /**
       
   910 @internalComponent
       
   911 
       
   912 Start dispatching request completions.
       
   913 
       
   914 Stop when aLoop becomes 'Inactive'
       
   915 
       
   916 This version uses the implementation of TRAP/Leave in terms of C++ exceptions.
       
   917 We have to make sure here that we don't call Active Object's RunError() or Active Scheduler's Error()
       
   918 while we are still in exception (within 'catch' brackets), as it can lead to nested-exceptions scenario.
       
   919 It is not fatal by default, but if two nested exceptions are due to OOM condition, RVCT implementation
       
   920 of exception will run out of emergency buffers and terminate the thread.
       
   921 */
       
   922 void CActiveScheduler::Run(TLoopOwner* const volatile& aLoop)
       
   923 	{
       
   924 	CActive * volatile curr_obj = 0;
       
   925 	TBool leaveException = EFalse;
       
   926 	TInt exceptionReason = 0;
       
   927 	do
       
   928 		{
       
   929 		try	{
       
   930 			__WIN32SEHTRAP
       
   931 			TTrapHandler* t = User::MarkCleanupStack();
       
   932 			
       
   933 #ifdef _DEBUG
       
   934 			//We cache the cleanupstack here do avoid repeated exec calls in DoRunL
       
   935 			TCleanupTrapHandler *pH=(TCleanupTrapHandler *)GetTrapHandler();
       
   936 			CCleanup* cleanupPtr=NULL;
       
   937 			TCleanupBundle cleanupBundle;
       
   938 
       
   939 			if(pH!=NULL) // test whether there's a CleanupTrapHandler installed
       
   940 				{
       
   941 				CCleanup& ccleanup =pH->Cleanup();
       
   942 				//Store pointer as need the scope of ccleanup increased
       
   943 				cleanupPtr = &ccleanup; 
       
   944 				cleanupBundle.iCleanupPtr = cleanupPtr;
       
   945 				
       
   946 				//Push a dummy item onto the stack - we check it after the AO's RunL has returned
       
   947 				//and we check to make sure its still at the top.
       
   948 				ccleanup.PushL(TCleanupItem(DummyFunc, &(cleanupBundle.iDummyInt)));
       
   949 				
       
   950 				DoRunL(aLoop, curr_obj, &cleanupBundle);
       
   951 
       
   952 				//Dummy Int must (will) be at the top
       
   953 				//Cleanup our stack
       
   954 				cleanupPtr->Pop(1);
       
   955 				} 
       
   956 			else // no cleanup stack installed
       
   957 				{
       
   958 				DoRunL(aLoop, curr_obj, NULL);
       
   959 				}
       
   960 			
       
   961 #else
       
   962 			DoRunL(aLoop, curr_obj, NULL);
       
   963 #endif
       
   964 			
       
   965 			User::UnMarkCleanupStack(t);
       
   966 			__WIN32SEHUNTRAP
       
   967 			return;
       
   968 			}
       
   969 		catch (XLeaveException& l)
       
   970 			{
       
   971 			Exec::LeaveEnd();
       
   972 			leaveException = ETrue;
       
   973 			exceptionReason = l.Reason();
       
   974 			}
       
   975 		catch (...)
       
   976 			{
       
   977 			User::Invariant();
       
   978 			}
       
   979 
       
   980 		if (leaveException)
       
   981 			{
       
   982 			if (exceptionReason != KErrNone)
       
   983 				{
       
   984 				TInt r = curr_obj->RunError(exceptionReason);
       
   985 				if (r != KErrNone)
       
   986 					Error(r);
       
   987 				}
       
   988 			leaveException = EFalse;
       
   989 			}
       
   990 
       
   991 		} while (aLoop != KLoopInactive);
       
   992 	}
       
   993 
       
   994 #else
       
   995 
       
   996 /**
       
   997 @internalComponent
       
   998 
       
   999 Start dispatching request completions.
       
  1000 
       
  1001 Stop when aLoop becomes 'Inactive'
       
  1002 
       
  1003 This version uses the original implementation of TRAP/Leave.
       
  1004 */
       
  1005 void CActiveScheduler::Run(TLoopOwner* const volatile& aLoop)
       
  1006 	{
       
  1007 	CActive * volatile curr_obj = 0;
       
  1008 	do
       
  1009 		{
       
  1010 		// explicitly expand the TRAPD macro here to enable single-step debugging
       
  1011 		// of the scheduler loop
       
  1012 		TInt r;
       
  1013 		TTrap trap;
       
  1014 		if (trap.Trap(r)==0)
       
  1015 			{
       
  1016 #ifdef _DEBUG
       
  1017 			//We cache the cleanupstack here do avoid repeated exec calls in DoRunL
       
  1018 			TCleanupTrapHandler *pH=(TCleanupTrapHandler *)GetTrapHandler();
       
  1019 			CCleanup* cleanupPtr=NULL;
       
  1020 			TCleanupBundle cleanupBundle;
       
  1021 
       
  1022 			if(pH!=NULL) // test whether there's a CleanupTrapHandler installed
       
  1023 				{
       
  1024 				CCleanup& ccleanup =pH->Cleanup();
       
  1025 				//Store pointer as need the scope of ccleanup increased
       
  1026 				cleanupPtr = &ccleanup; 
       
  1027 				cleanupBundle.iCleanupPtr = cleanupPtr;
       
  1028 				
       
  1029 				//Push a dummy item onto the stack - we check it after the AO's RunL has returned
       
  1030 				//and we check to make sure its still at the top.
       
  1031 				ccleanup.PushL(TCleanupItem(DummyFunc, &(cleanupBundle.iDummyInt)));
       
  1032 				
       
  1033 				DoRunL(aLoop, curr_obj, &cleanupBundle);
       
  1034 
       
  1035 				//Dummy Int must (will) be at the top
       
  1036 				//Cleanup our stack
       
  1037 				cleanupPtr->Pop(1);
       
  1038 				} 
       
  1039 			else // no cleanup stack installed
       
  1040 				{
       
  1041 				DoRunL(aLoop, curr_obj, NULL);
       
  1042 				}
       
  1043 #else
       
  1044 			DoRunL(aLoop, curr_obj, NULL);
       
  1045 #endif
       
  1046 			
       
  1047 			TTrap::UnTrap();
       
  1048 			return;		// exit level
       
  1049 			}
       
  1050 		if (r != KErrNone)
       
  1051 			{
       
  1052 			r = curr_obj->RunError(r);
       
  1053 			if (r != KErrNone)
       
  1054 				Error(r);
       
  1055 			}
       
  1056 		} while (aLoop != KLoopInactive);
       
  1057 	}
       
  1058 #endif
       
  1059 
       
  1060 #ifndef __CACTIVESCHEDULER_MACHINE_CODED__
       
  1061 /**
       
  1062 @internalComponent
       
  1063 
       
  1064 The inner active scheduler loop. This repeatedly waits for a signal and then
       
  1065 dispatches the highest priority ready active object. The loop terminates either
       
  1066 if one of the RunLs stops the current active scheduler level or leaves.
       
  1067 
       
  1068 Stop when aLoop becomes 'Inactive'
       
  1069 @panic EClnCheckFailed 90 This will panic when the RunL has left the cleanup stack in an unbalanced state.
       
  1070 */
       
  1071 #ifdef _DEBUG
       
  1072 void CActiveScheduler::DoRunL(TLoopOwner* const volatile& aLoop, CActive* volatile & aCurrentObj, TCleanupBundle* aCleanupBundlePtr)
       
  1073 #else
       
  1074 void CActiveScheduler::DoRunL(TLoopOwner* const volatile& aLoop, CActive* volatile & aCurrentObj, TCleanupBundle* /*aCleanupBundlePtr*/)
       
  1075 #endif
       
  1076 	{
       
  1077 	TDblQueIter<CActive> q(iActiveQ);
       
  1078 	do
       
  1079 		{
       
  1080 		WaitForAnyRequest();
       
  1081 		q.SetToFirst();
       
  1082 		CActive* pR;
       
  1083 		do
       
  1084 			{
       
  1085 			pR=q++;
       
  1086 			__ASSERT_ALWAYS(pR!=NULL,Panic(EReqStrayEvent));
       
  1087 			//if the line below panics it's either because you made a request but you haven't
       
  1088 			//SetActive the object (pR->iStatus.iFlags&TRequestStatus::EActive==0) or you didn't set the iStatus
       
  1089 			//to KRequestPending (pR->iStatus.iFlags&TRequestStatus::ERequestPending==0)
       
  1090 			__ASSERT_DEBUG(!(pR->iStatus.iFlags&TRequestStatus::EActive)==!(pR->iStatus.iFlags&TRequestStatus::ERequestPending),Panic(EReqStrayEvent));
       
  1091 			} while (!pR->IsActive() || pR->iStatus==KRequestPending);
       
  1092 #ifdef __SMP__
       
  1093 		__e32_memory_barrier();
       
  1094 #endif
       
  1095 		pR->iStatus.iFlags&=~(TRequestStatus::EActive | TRequestStatus::ERequestPending); //pR->iActive=EFalse;
       
  1096 		aCurrentObj = pR;
       
  1097 		pR->RunL();
       
  1098 
       
  1099 #ifdef _DEBUG
       
  1100 		if(aCleanupBundlePtr!=NULL)
       
  1101 			{
       
  1102 			//If the following line panics, the RunL left the
       
  1103 			//cleanup stack in an umbalanced state.
       
  1104 			TInt* dummyInt = &(aCleanupBundlePtr->iDummyInt);
       
  1105 			aCleanupBundlePtr->iCleanupPtr->Check(dummyInt);
       
  1106 			}
       
  1107 #endif
       
  1108 
       
  1109 		} while (aLoop != KLoopInactive);
       
  1110 	return;		// exit level
       
  1111 	}
       
  1112 
       
  1113 #else
       
  1114 
       
  1115 extern "C" void PanicStrayEvent()
       
  1116 	{
       
  1117 	Panic(EReqStrayEvent);
       
  1118 	}
       
  1119 #endif
       
  1120 
       
  1121 
       
  1122 
       
  1123 
       
  1124 EXPORT_C void CActiveScheduler::Stop()
       
  1125 /**
       
  1126 Stops the wait loop started by the most recent call to Start().
       
  1127 
       
  1128 Typically, this is called by the RunL() of one of the scheduler’s active
       
  1129 objects. When this RunL() finishes, the scheduler’s wait loop terminates,
       
  1130 i.e. it does not wait for the completion of the next request.
       
  1131 
       
  1132 It will not stop a wait loop started by a call
       
  1133 to CActiveSchedulerWait::Start().
       
  1134 
       
  1135 Stop() may also be called from Error().
       
  1136 
       
  1137 Note that stopping a nested wait loop is deprecated using this functionality,
       
  1138 use a CActiveSchedulerWait object instead.
       
  1139 
       
  1140 @see CActiveSchedulerWait::Start
       
  1141 @see CActive::RunL
       
  1142 @see CActiveSchedulerWait::Error
       
  1143 @see CActiveSchedulerWait::AsyncStop
       
  1144 */
       
  1145 	{
       
  1146 	CActiveScheduler *pS=GetActiveScheduler();
       
  1147 	__ASSERT_ALWAYS(pS!=NULL,Panic(EReqManagerDoesNotExist));
       
  1148 
       
  1149 	for (CActiveScheduler::TLoop* loop=pS->iStack; loop; loop=loop->iNext)
       
  1150 		{
       
  1151 		if (loop->iOwner == KLoopNoOwner)
       
  1152 			{
       
  1153 			loop->iOwner=KLoopInactive;
       
  1154 			return;
       
  1155 			}
       
  1156 		}
       
  1157 	Panic(EReqTooManyStops);
       
  1158 	}
       
  1159 
       
  1160 
       
  1161 
       
  1162 
       
  1163 EXPORT_C void CActiveScheduler::Halt(TInt aExitCode) const
       
  1164 /**
       
  1165 Unilaterally terminates the current scheduler loop.
       
  1166 
       
  1167 This causes the current scheduler loop to stop, whether it was started
       
  1168 using CActiveSchedulerWait::Start() or CActiveScheduler::Start(). It can
       
  1169 also trigger a leave from Start() if an exit code is provided. If the
       
  1170 current level has already been stopped, then this still records the exit code.
       
  1171 
       
  1172 @param aExitCode If non-zero, the reason code reported by Start().
       
  1173 */
       
  1174 	{
       
  1175 	CActiveScheduler::TLoop* loop=iStack;
       
  1176 	__ASSERT_ALWAYS(loop!=NULL,Panic(EReqTooManyStops));
       
  1177 	TLoopOwner* owner=loop->iOwner;
       
  1178 	if (TUint(owner) > TUint(KLoopNoOwner))
       
  1179 		*owner = NULL;
       
  1180 	loop->iOwner = KLoopInactive;			// disconnect from owner
       
  1181 	loop->iExitCode = aExitCode;
       
  1182 	}
       
  1183 
       
  1184 
       
  1185 
       
  1186 
       
  1187 EXPORT_C TInt CActiveScheduler::StackDepth() const
       
  1188 /**
       
  1189 Gets the current number of nested wait loops.
       
  1190 
       
  1191 @return The number of nested calls to Start().
       
  1192 */
       
  1193 	{
       
  1194 	TInt depth=0;
       
  1195 	for (CActiveScheduler::TLoop* loop=iStack; loop; loop=loop->iNext)
       
  1196 		++depth;
       
  1197 	return depth;
       
  1198 	}
       
  1199 
       
  1200 
       
  1201 
       
  1202 
       
  1203 EXPORT_C CActiveScheduler* CActiveScheduler::Current()
       
  1204 /**
       
  1205 Gets a pointer to the currently installed active scheduler.
       
  1206 
       
  1207 @return A pointer to the active scheduler which is currently installed.
       
  1208 */
       
  1209 	{
       
  1210 	return GetActiveScheduler();
       
  1211 	}
       
  1212 
       
  1213 
       
  1214 
       
  1215 
       
  1216 EXPORT_C void CActiveScheduler::Error(TInt /*aError*/) const
       
  1217 /**
       
  1218 Handles the result of a leave occurring in an active object’s RunL()
       
  1219 function.
       
  1220 
       
  1221 An active scheduler always invokes an active object’s RunL()
       
  1222 function under a trap harness.
       
  1223 
       
  1224 The default implementation must be replaced.
       
  1225 
       
  1226 Any cleanup relevant to the possible causes of leaving should
       
  1227 be performed. If Stop() or Halt() is called from within this function, the
       
  1228 current wait loop terminates. This may be an appropriate response to
       
  1229 catastrophic error conditions.
       
  1230 
       
  1231 @param aError The leave code propagated from the active object’s RunL() function
       
  1232 
       
  1233 @panic E32USER-CBase 47 if the default implementation is invoked.
       
  1234 
       
  1235 @see CActive::RunL
       
  1236 @see CActiveScheduler::Stop
       
  1237 @see CActiveScheduler::Halt
       
  1238 */
       
  1239 	{
       
  1240 	Panic(EReqActiveObjectLeave);
       
  1241 	}
       
  1242 
       
  1243 
       
  1244 
       
  1245 
       
  1246 EXPORT_C TBool CActiveScheduler::RunIfReady(TInt& aError, TInt aMinimumPriority)
       
  1247 /**
       
  1248 @deprecated
       
  1249 
       
  1250 Causes the RunL() function of at most one pending active object of priority
       
  1251 aMinimumPriority or greater to be run.
       
  1252 
       
  1253 @param aError Error returned by called active object.
       
  1254 @param aMinimumPriority Minimum priority of active object to run.
       
  1255 
       
  1256 @return EFalse if no active object's RunL() function was run, i.e. if there
       
  1257         were no active objects of priority aMinimumPriority or greater pending.
       
  1258 */
       
  1259 	{
       
  1260 	aError=KErrNone;
       
  1261 	CActiveScheduler* pS=GetActiveScheduler();
       
  1262 	if (pS!=NULL)
       
  1263 		{
       
  1264 		TDblQueIter<CActive> iterator(pS->iActiveQ);
       
  1265 		for (CActive* active=iterator++; (active!=NULL) && (active->Priority()>=aMinimumPriority); active=iterator++)
       
  1266 			{
       
  1267 			if (active->IsActive() && (active->iStatus!=KRequestPending))
       
  1268 				{
       
  1269 				active->iStatus.iFlags&=~(TRequestStatus::EActive | TRequestStatus::ERequestPending); //pR->iActive=EFalse;
       
  1270 				TRAP(aError, active->RunL());
       
  1271 				if (aError!=KErrNone)
       
  1272 					aError=active->RunError(aError);
       
  1273 				return ETrue;
       
  1274 				}
       
  1275 			}
       
  1276 		}
       
  1277 	return EFalse;
       
  1278 	}
       
  1279 
       
  1280 
       
  1281 
       
  1282 
       
  1283 EXPORT_C CActiveScheduler* CActiveScheduler::Replace(CActiveScheduler* aNewActiveScheduler)
       
  1284 /**
       
  1285 Allows the current active scheduler to be replaced, while retaining its active
       
  1286 objects.
       
  1287 
       
  1288 @param aNewActiveScheduler The new active scheduler.
       
  1289 
       
  1290 @return Previous active scheduler.
       
  1291 */
       
  1292 	{
       
  1293 	__ASSERT_ALWAYS(aNewActiveScheduler!=NULL, Panic(EReqManagerDoesNotExist));
       
  1294 	CActiveScheduler* oldActiveScheduler=GetActiveScheduler();
       
  1295 	__ASSERT_ALWAYS(aNewActiveScheduler!=oldActiveScheduler, Panic(EActiveSchedulerReplacingSelf));
       
  1296 	if (oldActiveScheduler!=NULL)
       
  1297 		{
       
  1298 		// steal all the CActive objects from oldActiveScheduler (without canceling any of them)
       
  1299 		TPriQue<CActive>& oldActiveQ=oldActiveScheduler->iActiveQ;
       
  1300 		TPriQue<CActive>& newActiveQ=aNewActiveScheduler->iActiveQ;
       
  1301 		while (!oldActiveQ.IsEmpty())
       
  1302 			{
       
  1303 			CActive& active=*oldActiveQ.First();
       
  1304 			// call the lower-level function active.iLink.Deque() rather than active.Deque()
       
  1305 			// as the latter would also call active.Cancel() (which we don't want)
       
  1306 			active.iLink.Deque();
       
  1307 			newActiveQ.Add(active);
       
  1308 			}
       
  1309 		}
       
  1310 	SetActiveScheduler(aNewActiveScheduler);
       
  1311 	return oldActiveScheduler;
       
  1312 	}
       
  1313 
       
  1314 
       
  1315 
       
  1316 
       
  1317 EXPORT_C void CActiveScheduler::OnStarting()
       
  1318 /**
       
  1319 @removed
       
  1320 
       
  1321 Dummy EXPORT for Binary Compatibility reasons.
       
  1322 This method is never called.
       
  1323 */
       
  1324 	{
       
  1325 	}
       
  1326 
       
  1327 
       
  1328 
       
  1329 
       
  1330 EXPORT_C void CActiveScheduler::OnStopping()
       
  1331 /**
       
  1332 @removed
       
  1333 
       
  1334 Dummy EXPORT for Binary Compatibility reasons.
       
  1335 This method is never called.
       
  1336 */
       
  1337 	{
       
  1338 	}
       
  1339 
       
  1340 
       
  1341 
       
  1342 EXPORT_C void CActiveScheduler::Reserved_1()
       
  1343 /**
       
  1344 @internalComponent
       
  1345 
       
  1346 Dummy EXPORT for Binary Compatibility reasons.
       
  1347 */
       
  1348 	{
       
  1349 	}
       
  1350 
       
  1351 
       
  1352 
       
  1353 EXPORT_C void CActiveScheduler::Reserved_2()
       
  1354 /**
       
  1355 @internalComponent
       
  1356 
       
  1357 Dummy EXPORT for Binary Compatibility reasons.
       
  1358 */
       
  1359 	{
       
  1360 	}
       
  1361 
       
  1362 
       
  1363 /**
       
  1364 Extension function
       
  1365 
       
  1366 
       
  1367 */
       
  1368 EXPORT_C TInt CActiveScheduler::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
       
  1369 	{
       
  1370 	return CBase::Extension_(aExtensionId, a0, a1);
       
  1371 	}