core/src/command_wrappers.cpp
changeset 36 99de8c43cede
parent 0 7f656887cf89
child 76 b9edfff731fb
--- a/core/src/command_wrappers.cpp	Tue Jul 13 09:10:33 2010 +0100
+++ b/core/src/command_wrappers.cpp	Sun Jul 18 18:57:41 2010 +0100
@@ -11,20 +11,14 @@
 //
 
 #include "command_wrappers.h"
-
-
-//
-// Constants.
-//
-
-const TInt KMaxHeapSize = KMinHeapSize * 1024;
-
+#include "worker_thread.h"
 
 //
 // CCommandWrapperBase.
 //
 
 CCommandWrapperBase::CCommandWrapperBase()
+	: CActive(CActive::EPriorityStandard)
 	{
 	}
 
@@ -96,14 +90,23 @@
 	delete this;
 	}
 
+void CCommandWrapperBase::RunL()
+	{
+	// Optionally for use by subclasses
+	}
+
+void CCommandWrapperBase::DoCancel()
+	{
+	// Optionally for use by subclasses
+	}
 
 //
 // CThreadCommand.
 //
 
-CThreadCommand* CThreadCommand::NewL(const TDesC& aName, TCommandConstructor aCommandConstructor, TUint aFlags)
+CThreadCommand* CThreadCommand::NewL(const TDesC& aName, TCommandConstructor aCommandConstructor, TUint aFlags, MTaskRunner* aTaskRunner)
 	{
-	CThreadCommand* self = new(ELeave) CThreadCommand(aCommandConstructor, aFlags);
+	CThreadCommand* self = new(ELeave) CThreadCommand(aCommandConstructor, aFlags, aTaskRunner);
 	CleanupStack::PushL(self);
 	self->ConstructL(aName);
 	CleanupStack::Pop(self);
@@ -112,14 +115,15 @@
 
 CThreadCommand::~CThreadCommand()
 	{
-	delete iWatcher;
-	delete iArgs;
+	Cancel();
+	delete iCommandLine;
 	iThread.Close();
 	}
 
-CThreadCommand::CThreadCommand(TCommandConstructor aCommandConstructor, TUint aFlags)
-	: iFlags(aFlags), iCommandConstructor(aCommandConstructor)
+CThreadCommand::CThreadCommand(TCommandConstructor aCommandConstructor, TUint aFlags, MTaskRunner* aTaskRunner)
+	: iFlags(aFlags), iCommandConstructor(aCommandConstructor), iTaskRunner(aTaskRunner)
 	{
+	CActiveScheduler::Add(this);
 	iThread.SetHandle(0); // By default RThread refers to the current thread. This results in fshell's thread exiting if this object gets killed before it has managed to open a real thread handle.
 	if (iFlags & EUpdateEnvironment) iFlags |= ESharedHeap; // Update environment implies a shared heap, ever since we did away with the explict SwitchAllocator
 	}
@@ -127,66 +131,31 @@
 void CThreadCommand::ConstructL(const TDesC& aName)
 	{
 	BaseConstructL(aName);
-	iWatcher = CThreadWatcher::NewL();
 	}
 
-void CommandThreadStartL(CThreadCommand::TArgs& aArgs)
+void CThreadCommand::DoCommandThreadStartL(TAny* aSelf)
 	{
-	if (aArgs.iFlags & CThreadCommand::ESharedHeap)
-		{
-		// If we're sharing the main fshell heap, we have to play by the rules and not crash
-		User::SetCritical(User::EProcessCritical);
-		}
-
-	CActiveScheduler* scheduler = new(ELeave) CActiveScheduler;
-	CleanupStack::PushL(scheduler);
-	CActiveScheduler::Install(scheduler);
-
-	HBufC* commandLine = aArgs.iCommandLine.AllocLC();
+	CThreadCommand* self = static_cast<CThreadCommand*>(aSelf);
 
 	IoUtils::CEnvironment* env;
-	if (aArgs.iFlags & CThreadCommand::EUpdateEnvironment)
+	if (self->iFlags & CThreadCommand::EUpdateEnvironment)
 		{
-		env = aArgs.iEnv.CreateSharedEnvironmentL();
+		env = self->iSuppliedEnv->CreateSharedEnvironmentL();
 		}
 	else
 		{
 		// A straight-forward copy
-		env = IoUtils::CEnvironment::NewL(aArgs.iEnv);
+		env = IoUtils::CEnvironment::NewL(*self->iSuppliedEnv);
 		}
 	CleanupStack::PushL(env);
 
-	CCommandBase* command = (*aArgs.iCommandConstructor)();
-	RThread parentThread;
-	User::LeaveIfError(parentThread.Open(aArgs.iParentThreadId));
-	parentThread.RequestComplete(aArgs.iParentStatus, KErrNone);
-	parentThread.Close();
-
-	command->RunCommandL(commandLine, env);
-	CleanupStack::PopAndDestroy(4, scheduler); // env, command, commandline, scheduler
+	CCommandBase* command = (*self->iCommandConstructor)();
+	//RDebug::Print(_L("5. DoCommandThreadStartL rendezvousing for %S %S"), &self->CmndName(), self->iCommandLine);
+	RThread::Rendezvous(KErrNone);
+	command->RunCommandL(self->iCommandLine, env);
+	CleanupStack::PopAndDestroy(2, env); // command, env
 	}
 
-TInt CommandThreadStart(TAny* aPtr)
-	{
-	CThreadCommand::TArgs args = *(CThreadCommand::TArgs*)aPtr;
-	TBool sharedHeap = (args.iFlags & CThreadCommand::ESharedHeap);
-	if (!sharedHeap)
-		{
-		__UHEAP_MARK;
-		}
-	TInt err = KErrNoMemory;
-	CTrapCleanup* cleanup = CTrapCleanup::New();
-	if (cleanup)
-		{
-		TRAP(err, CommandThreadStartL(args));
-		delete cleanup;
-		}
-	if (!sharedHeap)
-		{
-		__UHEAP_MARKEND;
-		}
-	return err;
-	}
 
 void SetHandleOwnersL(TThreadId aThreadId, RIoReadHandle& aStdin, RIoWriteHandle& aStdout, RIoWriteHandle& aStderr)
 	{
@@ -199,64 +168,36 @@
 	{
 	ASSERT(iObserver == NULL);
 
-	TRequestStatus status(KRequestPending);
-	iArgs = new TArgs(iFlags, aEnv, iCommandConstructor, aCommandLine, status);
-	if (iArgs == NULL)
+	MThreadedTask* thread = NULL;
+	TRAPD(err, thread = iTaskRunner->NewTaskInSeparateThreadL(CmndName(), iFlags & ESharedHeap, &DoCommandThreadStartL, this));
+	if (err) return err;
+
+	TRAP(err, SetHandleOwnersL(thread->GetThreadId(), CmndStdin(), CmndStdout(), CmndStderr()));
+
+	if (!err)
 		{
-		return KErrNoMemory;
+		iCommandLine = aCommandLine.Alloc();
+		if (!iCommandLine) err = KErrNoMemory;
 		}
 
-	TInt i = 0;
-	TName threadName;
-	TInt err = KErrNone;
-	do
+	if (!err)
 		{
-		const TDesC& name = CmndName();
-		threadName.Format(_L("%S_%02d"), &name, i++);
-		if (iFlags & ESharedHeap)
-			{
-			err = iThread.Create(threadName, CommandThreadStart, KDefaultStackSize, NULL, iArgs);
-			}
-		else
-			{
-			err = iThread.Create(threadName, CommandThreadStart, KDefaultStackSize, KMinHeapSize, KMaxHeapSize, iArgs);
-			}
-		}
-		while (err == KErrAlreadyExists);
-
-	if (err)
-		{
-		return err;
+		err = iThread.Open(thread->GetThreadId());
 		}
 
-	err = iWatcher->Logon(*this, iThread, aObserver);
-	if (err)
+	if (!err)
 		{
-		iThread.Kill(0);
-		iThread.Close();
-		return err;
+		iSuppliedEnv = &aEnv;
+		iObserver = &aObserver;
+		thread->ExecuteTask(iStatus);
+		SetActive();
+		}
+	else
+		{
+		thread->AbortTask();
 		}
 
-	TThreadId threadId = iThread.Id();
-	TRAP(err, SetHandleOwnersL(threadId, CmndStdin(), CmndStdout(), CmndStderr()));
-	if (err)
-		{
-		iThread.Kill(0);
-		iThread.Close();
-		return err;
-		}
-
-	iThread.Resume();
-	User::WaitForRequest(status, iWatcher->iStatus);
-	if (status == KRequestPending)
-		{
-		iThread.Close();
-		return iWatcher->iStatus.Int();
-		}
-
-	iWatcher->SetActive();
-	iObserver = &aObserver;
-	return KErrNone;
+	return err;
 	}
 
 void CThreadCommand::CmndForeground()
@@ -300,71 +241,14 @@
 	return iThread.ExitCategory();
 	}
 
-
-//
-// CThreadCommand::TArgs.
-//
-
-CThreadCommand::TArgs::TArgs(TUint aFlags, IoUtils::CEnvironment& aEnv, TCommandConstructor aCommandConstructor, const TDesC& aCommandLine, TRequestStatus& aParentStatus)
-	: iFlags(aFlags), iEnv(aEnv), iCommandConstructor(aCommandConstructor), iCommandLine(aCommandLine), iParentStatus(&aParentStatus), iParentThreadId(RThread().Id())
+void CThreadCommand::RunL()
 	{
-	}
-
-
-//
-// CThreadCommand::CThreadWatcher.
-//
-
-CThreadCommand::CThreadWatcher* CThreadCommand::CThreadWatcher::NewL()
-	{
-	return new(ELeave) CThreadWatcher();
-	}
-
-CThreadCommand::CThreadWatcher::~CThreadWatcher()
-	{
-	Cancel();
-	}
-
-CThreadCommand::CThreadWatcher::CThreadWatcher()
-	: CActive(CActive::EPriorityStandard)
-	{
-	CActiveScheduler::Add(this);
+	iObserver->HandleCommandComplete(*this, iStatus.Int());
 	}
 
-TInt CThreadCommand::CThreadWatcher::Logon(CThreadCommand& aCommand, RThread& aThread, MCommandObserver& aObserver)
+void CThreadCommand::DoCancel()
 	{
-	TInt ret = KErrNone;
-	aThread.Logon(iStatus);
-	if (iStatus != KRequestPending)
-		{
-		User::WaitForRequest(iStatus);
-		ret = iStatus.Int();
-		}
-	else
-		{
-		iCommand = &aCommand;
-		iThread = &aThread;
-		iObserver = &aObserver;
-		}
-	return ret;
-	}
-
-void CThreadCommand::CThreadWatcher::SetActive()
-	{
-	CActive::SetActive();
-	}
-
-void CThreadCommand::CThreadWatcher::RunL()
-	{
-	iObserver->HandleCommandComplete(*iCommand, iStatus.Int());
-	}
-
-void CThreadCommand::CThreadWatcher::DoCancel()
-	{
-	if (iThread)
-		{
-		iThread->LogonCancel(iStatus);
-		}
+	CmndKill(); // This is a bit drastic, but effective...
 	}