windowing/windowserver/nonnga/SERVER/WsMemMgr.cpp
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nonnga/SERVER/WsMemMgr.cpp	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,198 @@
+// Copyright (c) 2007-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:
+//
+
+#include "WsMemMgr.h"
+#include "inifile.h"
+#include "panics.h"
+#include "wstop.h"
+
+CWsMemoryManager * CWsMemoryManager::iStatic = NULL;
+
+CWsMemoryManager * CWsMemoryManager::Static()
+	{
+	return iStatic;
+	}
+
+CWsMemoryManager * CWsMemoryManager::NewLC()
+	{
+	CWsMemoryManager * self = new (ELeave) CWsMemoryManager;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	iStatic = self;
+	return iStatic;
+	}
+
+CWsMemoryManager::CWsMemoryManager()
+	{
+	iImpl = User::SwitchAllocator(this);
+	}
+	
+CWsMemoryManager::~CWsMemoryManager()
+	{
+	WS_ASSERT_ALWAYS(this == User::SwitchAllocator(iImpl),EWsPanicMemoryManager);
+	iStatic = 0;
+	if (iReserve!=NULL)
+		{
+		Free(iReserve);
+		iReserve = NULL;
+		}	
+	}
+
+void CWsMemoryManager::ConstructL()
+	{
+	_LIT(KMemMgrReserve, "MEMORYRESERVE");
+	const TInt KDefaultMemMgrReserve = 1024;
+	
+	if (!WsIniFile->FindVar(KMemMgrReserve, iReserveSize))
+		iReserveSize = KDefaultMemMgrReserve;
+
+	if (iReserveSize > 0)
+		iReserve = Alloc(iReserveSize);
+	}
+
+/**
+Implementing RAllocator
+*/
+
+/**
+Alloc and ReAlloc attempt to obtain memory through CWsTop::ReleaseMemory when they run low.
+ReleaseMemory looks for blocks of memory that the window server doesn't need urgently and frees
+them.
+*/
+TAny* CWsMemoryManager::Alloc(TInt aSize)
+	{
+	TBool keepTrying = ETrue;
+	do
+		{
+		if(iReleasing)
+			return iImpl->Alloc(aSize); //fallback on RAllocator
+		
+		if(TAny* ret = iImpl->Alloc(aSize)) //normal case
+			return ret;
+		
+		if(iReserveEnabled && iReserve && (aSize < iReserveSize))
+			{
+			Free(iReserve);
+			iReserve = NULL;
+			}
+		else
+			{
+			iReleasing = ETrue;
+			keepTrying = CWsTop::ReleaseMemory();
+			if(keepTrying)
+ 				{
+ 				const TInt reclaimed = Compress(); //Try to give back to the OS
+ 				}			
+			iReleasing = EFalse;
+			}
+		
+		} while(keepTrying);
+
+	return NULL;
+	}
+
+TAny* CWsMemoryManager::ReAlloc(TAny* aPtr, TInt aSize, TInt aMode)
+	{
+	TBool keepTrying = ETrue;
+	do
+		{
+		if(iReleasing)
+			return iImpl->ReAlloc(aPtr, aSize, aMode); //fallback on RAllocator
+		
+		if(TAny* ret = iImpl->ReAlloc(aPtr, aSize, aMode)) //normal case
+			return ret;
+		
+		if(iReserveEnabled && iReserve && (aSize < iReserveSize))
+			{
+			Free(iReserve);
+			iReserve = NULL;
+			}
+		else
+			{
+			iReleasing = ETrue;
+			keepTrying = CWsTop::ReleaseMemory();
+			if(keepTrying)
+ 				{
+ 				const TInt reclaimed = Compress(); //Try to give back to the OS
+ 				}	
+			iReleasing = EFalse;
+			}
+
+		} while(keepTrying);
+
+	return NULL;
+	}
+
+/**
+The rest of these functions just call the default implementation
+*/
+void CWsMemoryManager::Free(TAny* aPtr)
+	{
+	return iImpl->Free(aPtr);
+	}
+
+TInt CWsMemoryManager::AllocLen(const TAny* aCell) const
+	{
+	return iImpl->AllocLen(aCell);
+	}
+
+TInt CWsMemoryManager::Compress()
+	{
+	return iImpl->Compress();
+	}
+
+void CWsMemoryManager::Reset()
+	{
+	iImpl->Reset();
+	}
+
+TInt CWsMemoryManager::AllocSize(TInt& aTotalAllocSize) const
+	{
+	return iImpl->AllocSize(aTotalAllocSize);
+	}
+
+TInt CWsMemoryManager::Available(TInt& aBiggestBlock) const
+	{
+	return iImpl->Available(aBiggestBlock);
+	}
+
+TInt CWsMemoryManager::DebugFunction(TInt aFunc, TAny* a1, TAny* a2)
+	{
+	return iImpl->DebugFunction(aFunc,a1,a2);
+	}
+
+TInt CWsMemoryManager::Count() const
+	{
+	return iImpl->Count();
+	}
+/** This is a fairly dumb way to enable and disable the reserve, but we normally
+get away with it because wserv is high priority.  A better approach would be to
+use placement new into the reserve memory and manage it directly.  This would also
+allow us to track misbehaving code which allocated during OOM drawing and didn't
+free at the end.
+*/
+void CWsMemoryManager::EnableReserve()
+	{
+	WS_ASSERT_DEBUG(!iReserveEnabled, EWsPanicMemoryManager);
+	iReserveEnabled = ETrue;
+	}
+
+void CWsMemoryManager::DisableReserve()
+	{
+	WS_ASSERT_DEBUG(iReserveEnabled, EWsPanicMemoryManager);
+	iReserveEnabled = EFalse;
+	if((!iReserve) && (iReserveSize > 0))
+		iReserve = Alloc(iReserveSize);
+	}