genericopenlibs/posixrealtimeextensions/src/timerhandler.cpp
changeset 0 e4d67989cc36
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/genericopenlibs/posixrealtimeextensions/src/timerhandler.cpp	Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,246 @@
+// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Name        : timerhandler.cpp
+// Part of     : librt-timer specific cpp file
+// This is a project specific source file for building the 
+// timer related functions as part of librt library.
+// 
+//
+
+
+#include "sysif.h"
+#include "timerhandler.h"
+#include "timerclient.h"
+#include "timerserver.h"
+#include "timermessage.h"
+#include "timer.h"
+#include <pthread.h>
+
+#ifdef __WINSCW__ 
+#include <pls.h> // For emulator WSD API 
+const TUid KLibrtUid3 = {0x2001E553}; 
+#elif defined __X86GCC__
+CTimerReqHandler gTimerHandler;
+#endif
+
+
+CTimerReqHandler* getTimerHandler()
+	{
+#ifdef __WINSCW__	
+	// Access the PLS of this process
+	CTimerReqHandler* lTimerHandlerPtr = Pls<CTimerReqHandler>(KLibrtUid3); 
+	return lTimerHandlerPtr;  
+#elif defined __X86GCC__
+	return &gTimerHandler;
+#else
+	static CTimerReqHandler sgTimerHandler;
+	return &sgTimerHandler;
+#endif
+	}
+
+
+ CTimerReqHandler::CTimerReqHandler() : iTimers(CTimerReqHandler::KTimersGran)
+	{
+	iTimersLock.CreateLocal();
+	iServConnectLock.CreateLocal();
+	iTimerSemaphore.CreateLocal(0);
+	}
+
+
+ CTimerReqHandler::~CTimerReqHandler()
+	{
+	iTimersLock.Close();
+	iTimers.ResetAndDestroy();
+	iTimerSemaphore.Close();
+	iServ.Close();
+	iServConnectLock.Close();
+	}
+
+//method to create a timer
+TInt CTimerReqHandler::CreateTimer(TInt& aTimerId, struct sigevent *aSig)
+	{
+	TInt lRet = KErrNone;
+	if(iTimers.Count() >= MAXTIMERLIMIT)
+		{
+		lRet = KErrWouldBlock;
+		}
+		
+	if(lRet == KErrNone)
+		{
+		if(aSig != NULL)
+			{
+			switch(aSig->sigev_notify)	
+				{
+				case SIGEV_SIGNAL:
+#if (!defined SYMBIAN_OE_POSIX_SIGNALS || !defined SYMBIAN_OE_LIBRT)
+					{
+					aTimerId = -1;
+					lRet = KErrNotSupported;
+					break;	
+					}
+#else			
+				
+				if(aSig->sigev_signo < 1 || aSig->sigev_signo > SIGRTMAX)
+					{
+					aTimerId = -1;
+					lRet = KErrArgument;						
+					}
+#endif	
+					
+				case SIGEV_NONE:					
+				case SIGEV_THREAD:
+					break;
+				default:
+					aTimerId = -1;	
+					lRet = KErrArgument;
+					break;
+				}
+			}
+			
+		if(lRet == KErrNone)	
+			{
+			RHeap* oldHeap = User::SwitchHeap(Backend()->Heap());
+			CRtTimer *lTimer = CRtTimer::New(aSig);
+			if(NULL == lTimer)
+				{
+				aTimerId = -1;	
+				lRet = KErrNoMemory;
+				User::SwitchHeap(oldHeap);
+				}
+			else
+				{
+				aTimerId = lTimer->iTimerId;				
+				iTimersLock.Wait();	
+				TRAP(lRet, iTimers.AppendL(lTimer));				
+				User::SwitchHeap(oldHeap);
+				iTimersLock.Signal();			
+				}	
+			}
+		}
+		
+	return lRet;	
+	}
+
+//method to delete a timer
+TInt CTimerReqHandler::RemoveTimer(const TInt& aTimerId)
+	{
+	if(FindTimer(aTimerId)== NULL)
+		{
+		return KErrArgument;
+		}
+	TInt lRet = Connect();
+	if(lRet == KErrNone)
+		{
+		session.OnDemandConnect(iServer);
+		lRet = session.DeleteTimer(aTimerId);
+		}	
+	return lRet;		
+	}
+
+//method to set a new timeout value for a timer
+TInt CTimerReqHandler::SetTime(const TInt& aTimerId, TInt aFlag, const struct itimerspec *aIpTime,
+			 struct itimerspec *aOpTime) 
+	{
+	TInt lRet = Connect();
+	if(lRet == KErrNone)
+		{
+		CRtTimer* lTimer = FindTimer(aTimerId);	
+		if(lTimer != NULL)
+			lRet = lTimer->SetTime(aFlag, aIpTime, aOpTime);	
+		else
+			lRet = KErrArgument;	
+		}
+		
+	return lRet;	
+	}
+
+//method to makesure that the timer server is started only once on demand.
+TInt CTimerReqHandler::Connect()
+	{
+	TInt lRet = KErrNone;
+	
+	iServConnectLock.Wait();
+	if(!iIsServStarted)
+		{
+		lRet = StartTimerServer();
+		if(lRet == KErrNone)
+			iIsServStarted = ETrue;
+		}
+	iServConnectLock.Signal();
+	return lRet;		
+	}
+
+//start up function for the timer server.
+static TInt sTimerServer(TAny*)
+	{
+	RHeap *oldHeap = User::SwitchHeap(Backend()->Heap());
+	CTrapCleanup* cleanup = CTrapCleanup::New();
+	TRAPD(ret, CTimerServer::NewTimerServerL());
+	delete cleanup;
+	User::SwitchHeap(oldHeap);
+	return ret;
+	}
+
+//method to start the timer server
+TInt CTimerReqHandler::StartTimerServer()
+	{
+	TRequestStatus status;
+	TInt lRet = iServ.Create(KNullDesC, sTimerServer, 
+			KDefaultStackSize, NULL, (TAny*)NULL);
+	if(lRet == KErrNone)							
+		{
+		iServ.SetPriority(EPriorityAbsoluteHigh);// match the signal server priority.
+		iServ.Rendezvous(status);
+		iServ.Resume(); //get this ready
+		User::WaitForRequest(status);
+		}
+	return lRet;
+	}
+
+//method to get the "time to expiration" of a timer
+TInt CTimerReqHandler::Time(const TInt& aTimerId, struct itimerspec *aTime)
+	{
+ 	CRtTimer* lTimer = FindTimer(aTimerId);
+	if(lTimer == NULL)
+		return KErrArgument;	
+	return lTimer->Time(aTime);
+	}
+
+//method to get the overruns for a timer
+TInt CTimerReqHandler::OverrunCount(const TInt& aTimerId, TInt& aOverrunCount)
+	{
+	CRtTimer* lTimer = FindTimer(aTimerId);
+	if(lTimer == NULL)
+		return KErrArgument;		
+	return lTimer->OverrunCount(aOverrunCount);
+	}
+
+//find the timer with the given timer id
+CRtTimer* CTimerReqHandler::FindTimer(const TInt& aTimerId)
+	{
+	CRtTimer* lRtTimerP = NULL;
+	iTimersLock.Wait();	
+	TInt lTimerCount = iTimers.Count();	
+	for(TInt lIdx =0; lIdx < lTimerCount; lIdx++)
+		{
+		if(iTimers[lIdx]->iTimerId == aTimerId)
+			{
+			lRtTimerP = (iTimers[lIdx]);
+			break;	
+			}
+		}
+	iTimersLock.Signal();
+	return lRtTimerP;	
+	}
+