Update contrib.
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 * This component and the accompanying materials are made available
5 * under the terms of "Eclipse Public License v1.0"
6 * which accompanies this distribution, and is available
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
20 #include "timerserver.h"
21 #include "timerhandler.h"
24 /* Implementation of the CShutDown class
28 // -------------------------------------------------------------------------------
29 // CShutdown::ConstructL
30 // -------------------------------------------------------------------------------
31 void CShutdown::ConstructL()
36 // -------------------------------------------------------------------------------
38 // Starts the timer for the specified time given
39 // -------------------------------------------------------------------------------
40 void CShutdown::Start()
42 CActiveScheduler::Add(this);
43 After(KTimerServerShutdownDelay);
46 // -------------------------------------------------------------------------------
48 // Initiate server exit when timer expires
49 // -------------------------------------------------------------------------------
50 void CShutdown::RunL()
52 getTimerHandler()->ResetClientFlag();
53 getTimerHandler()->ResetServerFlag();
54 CActiveScheduler::Stop();
57 // -------------------------------------------------------------------------------
58 // CTimerServerSession::CreateL
59 // 2nd phase construction for sessions. Invoked by the CServer2 framework
60 // -------------------------------------------------------------------------------
61 void CTimerServerSession::CreateL()
63 Server().AddSession();
66 //---------------------------------------------------------------------
67 //CTimerServerSession::~CTimerServerSession
68 //Destructor of the server side session
69 //---------------------------------------------------------------------
70 CTimerServerSession::~CTimerServerSession()
72 Server().DropSession();
75 //---------------------------------------------------------------------
76 // Handle a client request.
77 // Leaving is handled by CMyServer::ServiceError() which reports
78 // the error code to the client
79 //---------------------------------------------------------------------
80 void CTimerServerSession::ServiceL(const RMessage2& aMessage)
82 switch (aMessage.Function())
86 TInt timerid = aMessage.Int0();
87 TInt ret = Server().RemoveInternal(timerid);
88 aMessage.Complete(ret);
93 TInt timerid = aMessage.Int0();
94 TInt ret = Server().SetTimer(timerid);
95 aMessage.Complete(ret);
99 PanicClient(aMessage,EPanicIllegalFunction);
104 CTimerServer& CTimerServerSession::Server()
106 return *static_cast<CTimerServer*>(const_cast<CServer2*>(CSession2::Server()));
109 //------------------------------------------------------------------------------
110 // Handle an error from CTimerServerSession::ServiceL()
111 // A bad descriptor error implies a badly programmed client, so panic it;
112 // otherwise use the default handling (report the error to the client)
113 //------------------------------------------------------------------------------
115 void CTimerServerSession::ServiceError(const RMessage2& aMessage,TInt aError)
117 PanicClient(aMessage,EPanicIllegalFunction);
118 CSession2::ServiceError(aMessage,aError);
121 //-----------------------------------------------------------------------------------------
122 // Implementation for CTimerServer class
123 // Implements the functionalities of the timer server
124 //------------------------------------------------------------------------------------------
125 CTimerServer* CTimerServer::NewLC()
127 CTimerServer* self=new(ELeave) CTimerServer;
128 CleanupStack::PushL(self);
133 // -------------------------------------------------------------------------------
134 // CTimerServer::ConstructL
135 // Second phase construction. Create the shutdown timer object and the semaphore
136 // -------------------------------------------------------------------------------
137 void CTimerServer::ConstructL()
139 CShutdown* shutdown = new(ELeave) CShutdown;
140 CleanupStack::PushL(shutdown);
141 shutdown->ConstructL();
143 iShutdown = shutdown;
147 // -------------------------------------------------------------------------------
148 // CTimerServer::AddToScheduler
149 // Add both the server and the shutdown timer objects to the active scheduler
150 // -------------------------------------------------------------------------------
151 TInt CTimerServer::AddToScheduler()
154 return CServer2::Start(KNullDesC);
157 // -------------------------------------------------------------------------------
158 // CFileDesTransferServer::RemoveFromScheduler
159 // Remove both the server and the shutdown timer objects from the active scheduler
160 // -------------------------------------------------------------------------------
161 void CTimerServer::RemoveFromScheduler()
163 if (iShutdown->IsAdded())
170 // -------------------------------------------------------------------------------
171 // CFileDesTransferServer::NewSessionL
172 // Create a new client session.
173 // -------------------------------------------------------------------------------
174 CSession2* CTimerServer::NewSessionL(const TVersion&, const RMessage2&) const
176 return new(ELeave) CTimerServerSession;
179 // -------------------------------------------------------------------------------
180 // CFileDesTransferServer::AddSession
181 // A new session is created. Cancel the shutdown timer if it was running.
182 // -------------------------------------------------------------------------------
183 inline void CTimerServer::AddSession()
185 if (iShutdown->IsAdded())
193 // -------------------------------------------------------------------------------
194 // CTimerServer::DropSession
195 // The session is destroyed. Stop the ActiveScheduler
196 // -------------------------------------------------------------------------------
197 void CTimerServer::DropSession()
199 if (--iSessionCount==0)
201 CTimerReqHandler* handler = getTimerHandler();
202 handler->ResetClientFlag();
203 if ((handler->iTimers.Count()) == 0 )
205 getTimerHandler()->ResetServerFlag();
206 CActiveScheduler::Stop();
211 //-------------------------------------------------------------------------
212 // CTimerServer::NewTimerServerL
213 // creates an active scheduler and installs it.
214 //-------------------------------------------------------------------------
215 TInt CTimerServer::NewTimerServerL()
217 CActiveScheduler* pScheduler = new(ELeave) CActiveScheduler;
218 CleanupStack::PushL(pScheduler);
220 CTimerServer* pServer = CTimerServer::NewLC();
222 CActiveScheduler::Install(pScheduler);
224 TInt err = pServer->AddToScheduler();
227 pServer->RemoveFromScheduler();
228 CActiveScheduler::Install(NULL);
231 getTimerHandler()->SetServerHandle(pServer->Server());
232 // pop both pScheduler and pServer from the cleanup stack
233 // Start the scheduler
234 RThread().Rendezvous(KErrNone);
235 CActiveScheduler::Start();
236 CActiveScheduler::Install(NULL);
238 CleanupStack::PopAndDestroy(2);
241 // -------------------------------------------------------------------------------
242 // CFileDesTransferServer::~CFileDesTransferServer
243 // -------------------------------------------------------------------------------
244 CTimerServer::~CTimerServer()
253 //---------------------------------------------------------------------------------
254 // CTimerServer:: RemoveInternal
255 // Removing the timer object from the list
256 //---------------------------------------------------------------------------------
257 TInt CTimerServer:: RemoveInternal(const TInt aTimerId)
260 TInt lRet = KErrArgument;
261 TBool lSigReq = EFalse;
262 CTimerReqHandler* handler = getTimerHandler();
263 handler->iTimersLock.Wait();
264 int lTimerCnt = handler->iTimers.Count();
266 for(lTimerIdx = 0; lTimerIdx != lTimerCnt; lTimerIdx++)
268 if(handler->iTimers[lTimerIdx]->iTimerId == aTimerId)
270 if (handler->iTimers[lTimerIdx]->iSigEvent.sigev_notify == SIGEV_SIGNAL)
272 RHeap* oldHeap = User::SwitchHeap(Backend()->Heap());
273 delete handler->iTimers[lTimerIdx];
274 handler->iTimers.Delete(lTimerIdx);
275 User::SwitchHeap(oldHeap);
280 if(lRet == KErrNone && lSigReq)
282 RHeap* oldHeap = User::SwitchHeap(Backend()->Heap());
283 handler->iTimers.Compress();
284 User::SwitchHeap(oldHeap);
285 #if (defined SYMBIAN_OE_POSIX_SIGNALS && defined SYMBIAN_OE_LIBRT)
286 Backend()->DeleteTimer(aTimerId);
289 handler->iTimersLock.Signal();
290 if(handler->iTimers.Count() == 0)
297 //thread startup function for SIGEV_THREAD
298 static TAny* sThreadFunc(TAny* aArgPtr)
300 struct sigevent* lTimerP = reinterpret_cast<struct sigevent *> (aArgPtr);
301 lTimerP->sigev_notify_function(lTimerP->sigev_value);
305 //---------------------------------------------------------------------------------
306 // CTimerServer:: SetTimer
307 // Server sets a new value for the timeout.
308 //---------------------------------------------------------------------------------
309 TInt CTimerServer:: SetTimer(const TInt aTimerId)
311 CRtTimer* lTimer = getTimerHandler()->FindTimer(aTimerId);
314 TTime lSetTime(MAKE_TINT64 (0x00dcddb3 ,0x0f2f8000));
315 if (lTimer->iIsArmed)
317 lTimer->iTimer.Cancel();
318 if(lTimer->iIsTimerReset)
320 lTimer->iTimer.Deque();
321 lTimer->iIsArmed = EFalse;
326 lTimer->iTimer.ConstructL();
328 lSetTime+=(TTimeIntervalSeconds) lTimer->iEndTime.tv_sec;
329 lSetTime+=(TTimeIntervalMicroSeconds)(lTimer->iEndTime.tv_nsec/1000);
331 lTimer->iTimer.AddToAS();
332 lTimer->iTimer.At(lSetTime); //Before requesting a timer event, add this active object to AS.
333 lTimer->iIsArmed = ETrue;
338 void CLibRtTimer::AddToAS()
341 CActiveScheduler::Add(this);
345 void CLibRtTimer::RunL()
347 CLocalSystemInterface* lClsiPtr = Backend();
349 unsigned long lPeriodicTimeout = (1000000 * GetRtPtr()->iStartTime.it_interval.tv_sec) +
350 (GetRtPtr()->iStartTime.it_interval.tv_nsec/1000);
354 this->HighRes(lPeriodicTimeout);
358 GetRtPtr()->iIsArmed = EFalse;
360 int val = GetRtPtr()->iSigEvent.sigev_notify;
361 //run the handler here
362 switch(GetRtPtr()->iSigEvent.sigev_notify)
364 #if (defined SYMBIAN_OE_POSIX_SIGNALS && defined SYMBIAN_OE_LIBRT)
367 lClsiPtr->AddTimer(GetRtPtr()->iTimerId);
369 if(lClsiPtr->IncrementOverrun(GetRtPtr()->iTimerId) == 1)
371 lClsiPtr->RaiseTimerSignal(GetRtPtr()->iSigEvent.sigev_signo,\
372 GetRtPtr()->iTimerId);
379 pthread_t lthread = 0;
380 pthread_create( <hread,
381 (pthread_attr_t*)GetRtPtr()->iSigEvent.sigev_notify_attributes,
383 &GetRtPtr()->iSigEvent );
393 // ---------------------------------------------------------------------------
394 // RMessage::Panic() also completes the message. This is:
395 // (a) important for efficient cleanup within the kernel
396 // (b) a problem if the message is completed a second time
397 // ---------------------------------------------------------------------------
398 void PanicClient(const RMessagePtr2& aMessage,TMyPanic aPanic)
400 _LIT(KPanic,"TimerServer");
401 aMessage.Panic(KPanic,aPanic);