1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/mmlibs/mmfw/src/server/BaseClasses/mmfsubthreadbase.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,331 @@
1.4 +// Copyright (c) 2002-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 +//
1.18 +
1.19 +#include <mmf/server/mmfsubthreadbase.h>
1.20 +#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
1.21 +#include <mmf/server/mmfsubthreadbaseimpl.h>
1.22 +#endif
1.23 +
1.24 +
1.25 +EXPORT_C void RMMFSubThreadBase::ReceiveEvents(TMMFEventPckg& aEventPckg, TRequestStatus& aStatus)
1.26 + {
1.27 + SendReceiveResult(EMMFSubThreadReceiveEvents, aEventPckg, aStatus);
1.28 + }
1.29 +
1.30 +EXPORT_C TInt RMMFSubThreadBase::CancelReceiveEvents()
1.31 + {
1.32 + return SendReceive(EMMFSubThreadCancelReceiveEvents);
1.33 + }
1.34 +
1.35 +EXPORT_C void RMMFSubThreadBase::Shutdown()
1.36 + {
1.37 + if (iSubThread.Handle() != KNullHandle)
1.38 + {
1.39 + // check that the subthread has yet to terminate
1.40 + if (iLogonStatus == KRequestPending)
1.41 + {
1.42 + //close the subthread and wait for its exit.
1.43 + //signal to the subthread to close down.
1.44 + TInt shutdownError = SendReceive(EMMFSubThreadShutdown);
1.45 + if (shutdownError != KErrNone)
1.46 + {
1.47 + iSubThread.LogonCancel(iLogonStatus);
1.48 + }
1.49 + else
1.50 + {
1.51 + RTimer timer;
1.52 + TInt err = timer.CreateLocal();
1.53 + //if we managed to create the timer, wait for both the death and the timeout to minimise the risk of deadlock
1.54 + if (!err)
1.55 + {
1.56 + TRequestStatus timeout;
1.57 + timer.After(timeout, iShutdownTimeout);
1.58 + User::WaitForRequest(iLogonStatus, timeout);
1.59 + if (iLogonStatus == KRequestPending)
1.60 + {
1.61 + //we have timed out. Panic the thread in debug mode, kill it in release mode.
1.62 + iSubThread.LogonCancel(iLogonStatus);
1.63 + User::WaitForRequest(iLogonStatus);
1.64 + #ifdef _DEBUG
1.65 + Panic(EMMFSubThreadPanicTimedOut);
1.66 + #else
1.67 + iSubThread.Kill(KErrDied);
1.68 + #endif
1.69 + }
1.70 + else
1.71 + {
1.72 + //subthread has exited. Cancel the timer.
1.73 + timer.Cancel();
1.74 + User::WaitForRequest(timeout);
1.75 + }
1.76 + }
1.77 + else
1.78 + {
1.79 + //we have no timer so we'll just have to risk the deadlock
1.80 + User::WaitForRequest(iLogonStatus);
1.81 + }
1.82 + timer.Close();
1.83 + }
1.84 + }
1.85 + //close the handle to the subthread
1.86 + iSubThread.Close();
1.87 + }
1.88 + // close our parent
1.89 + RHandleBase::Close();
1.90 + }
1.91 +
1.92 +void RMMFSubThreadBase::Panic(TMMFSubThreadPanicCode aPanicCode)
1.93 + {
1.94 + _LIT(KMMFSubThreadPanicCategory, "MMFSubThread");
1.95 + iSubThread.Panic(KMMFSubThreadPanicCategory, aPanicCode);
1.96 + }
1.97 +
1.98 +TInt RMMFSubThreadBase::DoCreateSubThread(const TDesC& aName, TThreadFunction aFunction, TBool aUseNewHeap)
1.99 + {
1.100 + TInt error = KErrNone;
1.101 +
1.102 + if (aUseNewHeap)
1.103 + {
1.104 + error = iSubThread.Create(aName, aFunction,
1.105 + KDefaultStackSize, KMinHeapSize, KMMFSubThreadMaxHeapSize,
1.106 + NULL, EOwnerThread);
1.107 + }
1.108 + else
1.109 + {
1.110 + error = iSubThread.Create(aName, aFunction,
1.111 + KDefaultStackSize, &User::Heap(),
1.112 + NULL, EOwnerThread);
1.113 + }
1.114 +
1.115 + if (error)
1.116 + {
1.117 + return error;
1.118 + }
1.119 +
1.120 + TRequestStatus rendezvous;
1.121 + iSubThread.Rendezvous(rendezvous);
1.122 +
1.123 + if (rendezvous != KRequestPending)
1.124 + {
1.125 + iSubThread.Kill(0);
1.126 + }
1.127 + else
1.128 + {
1.129 + iLogonStatus = KRequestPending;
1.130 + iSubThread.Logon(iLogonStatus);
1.131 + if (iLogonStatus != KRequestPending)
1.132 + {
1.133 + // Failed to log on
1.134 + iSubThread.RendezvousCancel(rendezvous);
1.135 + User::WaitForRequest(rendezvous);
1.136 + iSubThread.Kill(0);
1.137 + iSubThread.Close();
1.138 + return iLogonStatus.Int();
1.139 + }
1.140 + else
1.141 + {
1.142 + iSubThread.Resume();
1.143 + }
1.144 + }
1.145 + User::WaitForRequest(rendezvous); // wait for start or death
1.146 +
1.147 + if (rendezvous != KErrNone)
1.148 + {
1.149 + iSubThread.LogonCancel(iLogonStatus);
1.150 + User::WaitForRequest(iLogonStatus);
1.151 + iSubThread.Close();
1.152 + return rendezvous.Int();
1.153 + }
1.154 +
1.155 + return KErrNone;
1.156 + }
1.157 +
1.158 +CMMFSubThreadShutdown* CMMFSubThreadShutdown::NewL()
1.159 + {
1.160 + CMMFSubThreadShutdown* s = new(ELeave) CMMFSubThreadShutdown();
1.161 + CleanupStack::PushL(s);
1.162 + s->ConstructL();
1.163 + CleanupStack::Pop();
1.164 + return s;
1.165 + }
1.166 +
1.167 +CMMFSubThreadShutdown::CMMFSubThreadShutdown() :
1.168 + CTimer(EPriorityLow)
1.169 + {
1.170 + CActiveScheduler::Add(this);
1.171 + }
1.172 +
1.173 +void CMMFSubThreadShutdown::ConstructL()
1.174 + {
1.175 + CTimer::ConstructL();
1.176 + }
1.177 +
1.178 +void CMMFSubThreadShutdown::Start()
1.179 + {
1.180 + After(EMMFSubThreadShutdownDelay);
1.181 + }
1.182 +
1.183 +void CMMFSubThreadShutdown::RunL()
1.184 + {
1.185 + ShutdownNow();
1.186 + }
1.187 +
1.188 +void CMMFSubThreadShutdown::ShutdownNow()
1.189 + {
1.190 + CActiveScheduler::Stop();
1.191 + }
1.192 +
1.193 +
1.194 +
1.195 +
1.196 +CMMFSubThreadServer::CMMFSubThreadServer(TInt aPriority) :
1.197 + CMmfIpcServer(aPriority)
1.198 + {
1.199 + }
1.200 +
1.201 +void CMMFSubThreadServer::ConstructL()
1.202 + {
1.203 + StartL(RThread().Name());
1.204 + iShutdownTimer = CMMFSubThreadShutdown::NewL();
1.205 + iShutdownTimer->Start();
1.206 + }
1.207 +
1.208 +CMMFSubThreadServer::~CMMFSubThreadServer()
1.209 + {
1.210 + delete iShutdownTimer;
1.211 + }
1.212 +
1.213 +void CMMFSubThreadServer::SessionCreated()
1.214 + {
1.215 + //stop the shutdown timer
1.216 + iShutdownTimer->Cancel();
1.217 + }
1.218 +
1.219 +void CMMFSubThreadServer::ShutdownNow()
1.220 + {
1.221 + iShutdownTimer->ShutdownNow();
1.222 + }
1.223 +
1.224 +TInt CMMFSubThreadServer::RunError(TInt aError)
1.225 + {
1.226 + //signal the client
1.227 + Message().Complete(aError);
1.228 + ReStart();
1.229 + return KErrNone;
1.230 + }
1.231 +
1.232 +
1.233 +
1.234 +
1.235 +
1.236 +CMMFSubThreadEventReceiver* CMMFSubThreadEventReceiver::NewL(const RMmfIpcMessage& aMessage)
1.237 + {
1.238 + return new(ELeave) CMMFSubThreadEventReceiver(aMessage);
1.239 + }
1.240 +
1.241 +CMMFSubThreadEventReceiver::~CMMFSubThreadEventReceiver()
1.242 + {
1.243 + if (iNeedToCompleteMessage)
1.244 + iMessage.Complete(KErrDied);
1.245 + }
1.246 +
1.247 +void CMMFSubThreadEventReceiver::SendEvent(const TMMFEvent& aEvent)
1.248 + {
1.249 + TMMFEventPckg eventpckg(aEvent);
1.250 + TRAPD(err, MmfMessageUtil::WriteL(iMessage, 0, eventpckg));
1.251 + iMessage.Complete(err);
1.252 + iNeedToCompleteMessage = EFalse;
1.253 + }
1.254 +
1.255 +CMMFSubThreadEventReceiver::CMMFSubThreadEventReceiver(const RMmfIpcMessage& aMessage) :
1.256 + iMessage(aMessage)
1.257 + {
1.258 + iNeedToCompleteMessage = ETrue;
1.259 + }
1.260 +
1.261 +
1.262 +
1.263 +
1.264 +
1.265 +
1.266 +void CMMFSubThreadSession::CreateL(const CMmfIpcServer& aServer)
1.267 + {
1.268 + CMmfIpcSession::CreateL(aServer);
1.269 + iServer = STATIC_CAST(CMMFSubThreadServer*, (CONST_CAST(CMmfIpcServer*, &aServer)));
1.270 + iServer->SessionCreated();
1.271 + }
1.272 +
1.273 +
1.274 +CMMFSubThreadSession::~CMMFSubThreadSession()
1.275 + {
1.276 + delete iEventReceiver;
1.277 + iEvents.Close();
1.278 + }
1.279 +
1.280 +
1.281 +TBool CMMFSubThreadSession::ReceiveEventsL(const RMmfIpcMessage& aMessage)
1.282 + {
1.283 + if (iEventReceiver)
1.284 + User::Leave(KErrAlreadyExists);
1.285 + iEventReceiver = CMMFSubThreadEventReceiver::NewL(aMessage);
1.286 + //send the next cached event (if any) to the client
1.287 + if (iEvents.Count() > 0)
1.288 + {
1.289 + TMMFEvent& event = iEvents[0];
1.290 + iEventReceiver->SendEvent(event);
1.291 + delete iEventReceiver;
1.292 + iEventReceiver=NULL;
1.293 + iEvents.Remove(0);
1.294 + }
1.295 + return EFalse;
1.296 + }
1.297 +
1.298 +TBool CMMFSubThreadSession::CancelReceiveEvents()
1.299 + {
1.300 + delete iEventReceiver;
1.301 + iEventReceiver = NULL;
1.302 + return ETrue;
1.303 + }
1.304 +
1.305 +TBool CMMFSubThreadSession::ShutDown()
1.306 + {
1.307 + iServer->ShutdownNow();
1.308 + return ETrue;
1.309 + }
1.310 +
1.311 +TInt CMMFSubThreadSession::SendEventToClient(const TMMFEvent& aEvent)
1.312 + {
1.313 + TInt error = KErrNone;
1.314 + if (iEventReceiver)
1.315 + {
1.316 + //send event to client now
1.317 + iEventReceiver->SendEvent(aEvent);
1.318 + delete iEventReceiver;
1.319 + iEventReceiver=NULL;
1.320 + error = KErrNone;
1.321 + }
1.322 + else
1.323 + {
1.324 + //queue the request for later
1.325 + TMMFEvent event(aEvent);
1.326 + //if we've exceeded the max number of cached messages, delete the first and append this one to the end
1.327 + if (iEvents.Count() >= KMMFSubThreadMaxCachedMessages)
1.328 + iEvents.Remove(0);
1.329 + error = iEvents.Append(event);
1.330 + }
1.331 + return error;
1.332 + }
1.333 +
1.334 +