mmlibs/mmfw/src/server/BaseClasses/mmfsubthreadbase.cpp
changeset 0 40261b775718
equal deleted inserted replaced
-1:000000000000 0:40261b775718
       
     1 // Copyright (c) 2002-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 "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 //
       
    15 
       
    16 #include <mmf/server/mmfsubthreadbase.h>
       
    17 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    18 #include <mmf/server/mmfsubthreadbaseimpl.h>
       
    19 #endif
       
    20 
       
    21 
       
    22 EXPORT_C void RMMFSubThreadBase::ReceiveEvents(TMMFEventPckg& aEventPckg, TRequestStatus& aStatus)
       
    23 	{
       
    24 	SendReceiveResult(EMMFSubThreadReceiveEvents, aEventPckg, aStatus);
       
    25 	}
       
    26 
       
    27 EXPORT_C TInt RMMFSubThreadBase::CancelReceiveEvents()
       
    28 	{
       
    29 	return SendReceive(EMMFSubThreadCancelReceiveEvents);
       
    30 	}
       
    31 
       
    32 EXPORT_C void RMMFSubThreadBase::Shutdown()
       
    33 	{
       
    34 	if (iSubThread.Handle() != KNullHandle)
       
    35 		{
       
    36 		// check that the subthread has yet to terminate
       
    37 		if (iLogonStatus == KRequestPending)
       
    38 			{	
       
    39 			//close the subthread and wait for its exit.
       
    40 			//signal to the subthread to close down.			
       
    41 			TInt shutdownError = SendReceive(EMMFSubThreadShutdown);
       
    42 			if (shutdownError != KErrNone)
       
    43 				{
       
    44 				iSubThread.LogonCancel(iLogonStatus);
       
    45 				}
       
    46 			else
       
    47 				{
       
    48 				RTimer timer;
       
    49 				TInt err = timer.CreateLocal();
       
    50 				//if we managed to create the timer, wait for both the death and the timeout to minimise the risk of deadlock
       
    51 				if (!err)
       
    52 					{
       
    53 					TRequestStatus timeout;
       
    54 					timer.After(timeout, iShutdownTimeout);
       
    55 					User::WaitForRequest(iLogonStatus, timeout);
       
    56 					if (iLogonStatus == KRequestPending)
       
    57 						{
       
    58 						//we have timed out.  Panic the thread in debug mode, kill it in release mode.
       
    59 						iSubThread.LogonCancel(iLogonStatus);
       
    60 						User::WaitForRequest(iLogonStatus);
       
    61 					#ifdef _DEBUG	
       
    62 						Panic(EMMFSubThreadPanicTimedOut);
       
    63 					#else
       
    64 						iSubThread.Kill(KErrDied);
       
    65 					#endif
       
    66 						}
       
    67 					else
       
    68 						{
       
    69 						//subthread has exited. Cancel the timer.
       
    70 						timer.Cancel();
       
    71 						User::WaitForRequest(timeout);
       
    72 						}
       
    73 					}
       
    74 				else
       
    75 					{
       
    76 					//we have no timer so we'll just have to risk the deadlock
       
    77 					User::WaitForRequest(iLogonStatus);
       
    78 					}
       
    79 				timer.Close();
       
    80 				}
       
    81 			}
       
    82 		//close the handle to the subthread
       
    83 		iSubThread.Close();
       
    84 		}
       
    85 	// close our parent
       
    86 	RHandleBase::Close(); 
       
    87 	}
       
    88 	
       
    89 void RMMFSubThreadBase::Panic(TMMFSubThreadPanicCode aPanicCode)
       
    90 	{
       
    91 	_LIT(KMMFSubThreadPanicCategory, "MMFSubThread");
       
    92 	iSubThread.Panic(KMMFSubThreadPanicCategory, aPanicCode);
       
    93 	}
       
    94 
       
    95 TInt RMMFSubThreadBase::DoCreateSubThread(const TDesC& aName, TThreadFunction aFunction, TBool aUseNewHeap)
       
    96 	{
       
    97 	TInt error = KErrNone;
       
    98 
       
    99 	if (aUseNewHeap)
       
   100 		{
       
   101 		error = iSubThread.Create(aName, aFunction,
       
   102 			KDefaultStackSize, KMinHeapSize, KMMFSubThreadMaxHeapSize, 
       
   103 			NULL, EOwnerThread);
       
   104 		}
       
   105 	else
       
   106 		{
       
   107 		error = iSubThread.Create(aName, aFunction,
       
   108 			KDefaultStackSize, &User::Heap(), 
       
   109 			NULL, EOwnerThread);
       
   110 		}
       
   111 
       
   112 	if (error)
       
   113 		{
       
   114 		return error;
       
   115 		}
       
   116 	
       
   117 	TRequestStatus rendezvous;
       
   118 	iSubThread.Rendezvous(rendezvous);
       
   119 	
       
   120 	if (rendezvous != KRequestPending)
       
   121 		{
       
   122 		iSubThread.Kill(0);
       
   123 		}
       
   124 	else
       
   125 		{
       
   126 		iLogonStatus = KRequestPending;
       
   127 		iSubThread.Logon(iLogonStatus);
       
   128 		if (iLogonStatus != KRequestPending)
       
   129 			{
       
   130 			// Failed to log on
       
   131 			iSubThread.RendezvousCancel(rendezvous);
       
   132 			User::WaitForRequest(rendezvous);
       
   133 			iSubThread.Kill(0);
       
   134 			iSubThread.Close();
       
   135 			return iLogonStatus.Int();
       
   136 			}
       
   137 		else
       
   138 			{
       
   139 			iSubThread.Resume();		
       
   140 			}
       
   141 		}
       
   142 	User::WaitForRequest(rendezvous); // wait for start or death
       
   143 	
       
   144 	if (rendezvous != KErrNone)
       
   145 		{
       
   146 		iSubThread.LogonCancel(iLogonStatus);
       
   147 		User::WaitForRequest(iLogonStatus);
       
   148 		iSubThread.Close();
       
   149 		return rendezvous.Int();
       
   150 		}
       
   151 		
       
   152 	return KErrNone;	
       
   153 	}
       
   154 
       
   155 CMMFSubThreadShutdown* CMMFSubThreadShutdown::NewL() 
       
   156 	{
       
   157 	CMMFSubThreadShutdown* s = new(ELeave) CMMFSubThreadShutdown();
       
   158 	CleanupStack::PushL(s);
       
   159 	s->ConstructL();
       
   160 	CleanupStack::Pop();
       
   161 	return s;
       
   162 	}
       
   163 
       
   164 CMMFSubThreadShutdown::CMMFSubThreadShutdown() : 
       
   165 	CTimer(EPriorityLow)
       
   166 	{
       
   167 	CActiveScheduler::Add(this);
       
   168 	}
       
   169 
       
   170 void CMMFSubThreadShutdown::ConstructL()
       
   171 	{
       
   172 	CTimer::ConstructL();
       
   173 	}
       
   174 
       
   175 void CMMFSubThreadShutdown::Start()
       
   176 	{
       
   177 	After(EMMFSubThreadShutdownDelay);
       
   178 	}
       
   179 
       
   180 void CMMFSubThreadShutdown::RunL()
       
   181 	{
       
   182 	ShutdownNow();
       
   183 	}
       
   184 
       
   185 void CMMFSubThreadShutdown::ShutdownNow()
       
   186 	{
       
   187 	CActiveScheduler::Stop();
       
   188 	}
       
   189 
       
   190 
       
   191 
       
   192 
       
   193 CMMFSubThreadServer::CMMFSubThreadServer(TInt aPriority) :
       
   194 	CMmfIpcServer(aPriority)
       
   195 	{
       
   196 	}
       
   197 
       
   198 void CMMFSubThreadServer::ConstructL()
       
   199 	{
       
   200 	StartL(RThread().Name());
       
   201 	iShutdownTimer = CMMFSubThreadShutdown::NewL();
       
   202 	iShutdownTimer->Start();
       
   203 	}
       
   204 
       
   205 CMMFSubThreadServer::~CMMFSubThreadServer()
       
   206 	{
       
   207 	delete iShutdownTimer;
       
   208 	}
       
   209 
       
   210 void CMMFSubThreadServer::SessionCreated()
       
   211 	{
       
   212 	//stop the shutdown timer
       
   213 	iShutdownTimer->Cancel();
       
   214 	}
       
   215 
       
   216 void CMMFSubThreadServer::ShutdownNow()
       
   217 	{
       
   218 	iShutdownTimer->ShutdownNow();
       
   219 	}
       
   220 
       
   221 TInt CMMFSubThreadServer::RunError(TInt aError)
       
   222 	{
       
   223 	//signal the client
       
   224 	Message().Complete(aError);
       
   225 	ReStart();
       
   226 	return KErrNone;
       
   227 	}
       
   228 
       
   229 
       
   230 
       
   231 
       
   232 
       
   233 CMMFSubThreadEventReceiver* CMMFSubThreadEventReceiver::NewL(const RMmfIpcMessage& aMessage)
       
   234 	{
       
   235 	return new(ELeave) CMMFSubThreadEventReceiver(aMessage);
       
   236 	}
       
   237 
       
   238 CMMFSubThreadEventReceiver::~CMMFSubThreadEventReceiver()
       
   239 	{
       
   240 	if (iNeedToCompleteMessage)
       
   241 		iMessage.Complete(KErrDied);
       
   242 	}
       
   243 
       
   244 void CMMFSubThreadEventReceiver::SendEvent(const TMMFEvent& aEvent)
       
   245 	{
       
   246 	TMMFEventPckg eventpckg(aEvent);
       
   247 	TRAPD(err, MmfMessageUtil::WriteL(iMessage, 0, eventpckg));
       
   248 	iMessage.Complete(err);
       
   249 	iNeedToCompleteMessage = EFalse;
       
   250 	}
       
   251 
       
   252 CMMFSubThreadEventReceiver::CMMFSubThreadEventReceiver(const RMmfIpcMessage& aMessage) : 
       
   253 	iMessage(aMessage)
       
   254 	{
       
   255 	iNeedToCompleteMessage = ETrue;
       
   256 	}
       
   257 
       
   258 
       
   259 
       
   260 
       
   261 
       
   262 
       
   263 void CMMFSubThreadSession::CreateL(const CMmfIpcServer& aServer)
       
   264 	{
       
   265 	CMmfIpcSession::CreateL(aServer);
       
   266 	iServer = STATIC_CAST(CMMFSubThreadServer*, (CONST_CAST(CMmfIpcServer*, &aServer)));
       
   267 	iServer->SessionCreated();
       
   268 	}
       
   269 
       
   270 
       
   271 CMMFSubThreadSession::~CMMFSubThreadSession()
       
   272 	{
       
   273 	delete iEventReceiver;
       
   274 	iEvents.Close();
       
   275 	}
       
   276 
       
   277 
       
   278 TBool CMMFSubThreadSession::ReceiveEventsL(const RMmfIpcMessage& aMessage)
       
   279 	{
       
   280 	if (iEventReceiver)
       
   281 		User::Leave(KErrAlreadyExists);
       
   282 	iEventReceiver = CMMFSubThreadEventReceiver::NewL(aMessage);
       
   283 	//send the next cached event (if any) to the client
       
   284 	if (iEvents.Count() > 0)
       
   285 		{
       
   286 		TMMFEvent& event = iEvents[0];
       
   287 		iEventReceiver->SendEvent(event);
       
   288 		delete iEventReceiver;
       
   289 		iEventReceiver=NULL;
       
   290 		iEvents.Remove(0);
       
   291 		}
       
   292 	return EFalse;
       
   293 	}
       
   294 
       
   295 TBool CMMFSubThreadSession::CancelReceiveEvents()
       
   296 	{
       
   297 	delete iEventReceiver;
       
   298 	iEventReceiver = NULL;
       
   299 	return ETrue;
       
   300 	}
       
   301 
       
   302 TBool CMMFSubThreadSession::ShutDown()
       
   303 	{
       
   304 	iServer->ShutdownNow();
       
   305 	return ETrue;
       
   306 	}
       
   307 
       
   308 TInt CMMFSubThreadSession::SendEventToClient(const TMMFEvent& aEvent)
       
   309 	{
       
   310 	TInt error = KErrNone;
       
   311 	if (iEventReceiver)
       
   312 		{
       
   313 		//send event to client now
       
   314 		iEventReceiver->SendEvent(aEvent);
       
   315 		delete iEventReceiver;
       
   316 		iEventReceiver=NULL;
       
   317 		error = KErrNone;
       
   318 		}
       
   319 	else
       
   320 		{
       
   321 		//queue the request for later
       
   322 		TMMFEvent event(aEvent);
       
   323 		//if we've exceeded the max number of cached messages, delete the first and append this one to the end
       
   324 		if (iEvents.Count() >= KMMFSubThreadMaxCachedMessages)
       
   325 			iEvents.Remove(0);
       
   326 		error = iEvents.Append(event);
       
   327 		}
       
   328 	return error;
       
   329 	}
       
   330 
       
   331