Update contrib.
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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
16 #include <mmf/server/mmfsubthreadbase.h>
17 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
18 #include <mmf/server/mmfsubthreadbaseimpl.h>
22 EXPORT_C void RMMFSubThreadBase::ReceiveEvents(TMMFEventPckg& aEventPckg, TRequestStatus& aStatus)
24 SendReceiveResult(EMMFSubThreadReceiveEvents, aEventPckg, aStatus);
27 EXPORT_C TInt RMMFSubThreadBase::CancelReceiveEvents()
29 return SendReceive(EMMFSubThreadCancelReceiveEvents);
32 EXPORT_C void RMMFSubThreadBase::Shutdown()
34 if (iSubThread.Handle() != KNullHandle)
36 // check that the subthread has yet to terminate
37 if (iLogonStatus == KRequestPending)
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)
44 iSubThread.LogonCancel(iLogonStatus);
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
53 TRequestStatus timeout;
54 timer.After(timeout, iShutdownTimeout);
55 User::WaitForRequest(iLogonStatus, timeout);
56 if (iLogonStatus == KRequestPending)
58 //we have timed out. Panic the thread in debug mode, kill it in release mode.
59 iSubThread.LogonCancel(iLogonStatus);
60 User::WaitForRequest(iLogonStatus);
62 Panic(EMMFSubThreadPanicTimedOut);
64 iSubThread.Kill(KErrDied);
69 //subthread has exited. Cancel the timer.
71 User::WaitForRequest(timeout);
76 //we have no timer so we'll just have to risk the deadlock
77 User::WaitForRequest(iLogonStatus);
82 //close the handle to the subthread
89 void RMMFSubThreadBase::Panic(TMMFSubThreadPanicCode aPanicCode)
91 _LIT(KMMFSubThreadPanicCategory, "MMFSubThread");
92 iSubThread.Panic(KMMFSubThreadPanicCategory, aPanicCode);
95 TInt RMMFSubThreadBase::DoCreateSubThread(const TDesC& aName, TThreadFunction aFunction, TBool aUseNewHeap)
97 TInt error = KErrNone;
101 error = iSubThread.Create(aName, aFunction,
102 KDefaultStackSize, KMinHeapSize, KMMFSubThreadMaxHeapSize,
107 error = iSubThread.Create(aName, aFunction,
108 KDefaultStackSize, &User::Heap(),
117 TRequestStatus rendezvous;
118 iSubThread.Rendezvous(rendezvous);
120 if (rendezvous != KRequestPending)
126 iLogonStatus = KRequestPending;
127 iSubThread.Logon(iLogonStatus);
128 if (iLogonStatus != KRequestPending)
131 iSubThread.RendezvousCancel(rendezvous);
132 User::WaitForRequest(rendezvous);
135 return iLogonStatus.Int();
142 User::WaitForRequest(rendezvous); // wait for start or death
144 if (rendezvous != KErrNone)
146 iSubThread.LogonCancel(iLogonStatus);
147 User::WaitForRequest(iLogonStatus);
149 return rendezvous.Int();
155 CMMFSubThreadShutdown* CMMFSubThreadShutdown::NewL()
157 CMMFSubThreadShutdown* s = new(ELeave) CMMFSubThreadShutdown();
158 CleanupStack::PushL(s);
164 CMMFSubThreadShutdown::CMMFSubThreadShutdown() :
167 CActiveScheduler::Add(this);
170 void CMMFSubThreadShutdown::ConstructL()
172 CTimer::ConstructL();
175 void CMMFSubThreadShutdown::Start()
177 After(EMMFSubThreadShutdownDelay);
180 void CMMFSubThreadShutdown::RunL()
185 void CMMFSubThreadShutdown::ShutdownNow()
187 CActiveScheduler::Stop();
193 CMMFSubThreadServer::CMMFSubThreadServer(TInt aPriority) :
194 CMmfIpcServer(aPriority)
198 void CMMFSubThreadServer::ConstructL()
200 StartL(RThread().Name());
201 iShutdownTimer = CMMFSubThreadShutdown::NewL();
202 iShutdownTimer->Start();
205 CMMFSubThreadServer::~CMMFSubThreadServer()
207 delete iShutdownTimer;
210 void CMMFSubThreadServer::SessionCreated()
212 //stop the shutdown timer
213 iShutdownTimer->Cancel();
216 void CMMFSubThreadServer::ShutdownNow()
218 iShutdownTimer->ShutdownNow();
221 TInt CMMFSubThreadServer::RunError(TInt aError)
224 Message().Complete(aError);
233 CMMFSubThreadEventReceiver* CMMFSubThreadEventReceiver::NewL(const RMmfIpcMessage& aMessage)
235 return new(ELeave) CMMFSubThreadEventReceiver(aMessage);
238 CMMFSubThreadEventReceiver::~CMMFSubThreadEventReceiver()
240 if (iNeedToCompleteMessage)
241 iMessage.Complete(KErrDied);
244 void CMMFSubThreadEventReceiver::SendEvent(const TMMFEvent& aEvent)
246 TMMFEventPckg eventpckg(aEvent);
247 TRAPD(err, MmfMessageUtil::WriteL(iMessage, 0, eventpckg));
248 iMessage.Complete(err);
249 iNeedToCompleteMessage = EFalse;
252 CMMFSubThreadEventReceiver::CMMFSubThreadEventReceiver(const RMmfIpcMessage& aMessage) :
255 iNeedToCompleteMessage = ETrue;
263 void CMMFSubThreadSession::CreateL(const CMmfIpcServer& aServer)
265 CMmfIpcSession::CreateL(aServer);
266 iServer = STATIC_CAST(CMMFSubThreadServer*, (CONST_CAST(CMmfIpcServer*, &aServer)));
267 iServer->SessionCreated();
271 CMMFSubThreadSession::~CMMFSubThreadSession()
273 delete iEventReceiver;
278 TBool CMMFSubThreadSession::ReceiveEventsL(const RMmfIpcMessage& aMessage)
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)
286 TMMFEvent& event = iEvents[0];
287 iEventReceiver->SendEvent(event);
288 delete iEventReceiver;
295 TBool CMMFSubThreadSession::CancelReceiveEvents()
297 delete iEventReceiver;
298 iEventReceiver = NULL;
302 TBool CMMFSubThreadSession::ShutDown()
304 iServer->ShutdownNow();
308 TInt CMMFSubThreadSession::SendEventToClient(const TMMFEvent& aEvent)
310 TInt error = KErrNone;
313 //send event to client now
314 iEventReceiver->SendEvent(aEvent);
315 delete iEventReceiver;
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)
326 error = iEvents.Append(event);