diff -r 741dcdf88ba9 -r c4d65d91ad0c kerneltest/e32test/misc/test_thread.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/misc/test_thread.h Sun Mar 14 13:15:32 2010 +0000 @@ -0,0 +1,240 @@ +// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "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. +// +// Description: Some helper classes to assist with writing multi-threaded tests + +#ifndef TEST_THREAD_H +#define TEST_THREAD_H + +#define __E32TEST_EXTENSION__ +#include +#include +#include +#include +#include +#include +#include +#include + + +_LIT(KPciPanicCat, "test_thread.h"); + +static const TInt KPciHeapSize=0x2000; + +enum TPciPanicCode + { + EThreadCreateFailed + }; + +/** +A utility class for running functions in other threads/processes +*/ +class TTestRemote + { +public: + virtual TInt WaitForExitL() = 0; + virtual ~TTestRemote() + {} + + virtual void Rendezvous(TRequestStatus& aStatus) = 0; + +protected: + TTestRemote() + {} + + static TInt RunFunctor(TAny* aFunctor) + { + TFunctor& functor = *(TFunctor*)aFunctor; + functor(); + return KErrNone; + } + + TRequestStatus iLogonStatus; + static TInt iCount; + }; +TInt TTestRemote::iCount=0; + +class TTestThread : public TTestRemote + { +public: + TTestThread(const TDesC& aName, TThreadFunction aFn, TAny* aData, TBool aAutoResume=ETrue) + { + Init(aName, aFn, aData, aAutoResume); + } + + /** + Run aFunctor in another thread + */ + TTestThread(const TDesC& aName, TFunctor& aFunctor, TBool aAutoResume=ETrue) + { + Init(aName, RunFunctor, &aFunctor, aAutoResume); + } + + ~TTestThread() + { + //RTest::CloseHandleAndWaitForDestruction(iThread); + iThread.Close(); + } + + void Resume() + { + iThread.Resume(); + } + + /** + If thread exited normally, return its return code + Otherwise, leave with exit reason + */ + virtual TInt WaitForExitL() + { + User::WaitForRequest(iLogonStatus); + const TInt exitType = iThread.ExitType(); + const TInt exitReason = iThread.ExitReason(); + + __ASSERT_ALWAYS(exitType != EExitPending, User::Panic(_L("TTestThread"),0)); + + if(exitType != EExitKill) + User::Leave(exitReason); + + return exitReason; + } + + virtual void Rendezvous(TRequestStatus& aStatus) + { + iThread.Rendezvous(aStatus); + } + +private: + void Init(const TDesC& aName, TThreadFunction aFn, TAny* aData, TBool aAutoResume) + { + TKName name(aName); + name.AppendFormat(_L("-%d"), iCount++); + TInt r=iThread.Create(name, aFn, KDefaultStackSize, KPciHeapSize, KPciHeapSize, aData); + if(r!=KErrNone) + { + RDebug::Printf("RThread::Create failed, code=%d", r); + User::Panic(KPciPanicCat, EThreadCreateFailed); + } + + iThread.Logon(iLogonStatus); + __ASSERT_ALWAYS(iLogonStatus == KRequestPending, User::Panic(_L("TTestThread"),0)); + + if(aAutoResume) + iThread.Resume(); + } + + RThread iThread; + }; + +class CTest : public CBase, public TFunctor + { +public: + ~CTest() + { + iName.Close(); + } + + virtual void operator()() + { + RTest test(iName); + test.Start(iName); + for(TInt i=0; i testArray; + RPointerArray threadArray; + + for(TInt i=0; iWaitForExitL()); + if(leaveCode != KErrNone) + { + test.Printf(_L("Thread %d: Panic code:%d\n"), j, leaveCode); + test_KErrNone(leaveCode); + } + + if(r!=KErrNone) + { + test.Printf(_L("Thread Number %d\n"), j); + test_KErrNone(r); + } + } + + threadArray.ResetAndDestroy(); + threadArray.Close(); + + testArray.ResetAndDestroy(); + testArray.Close(); + } + +#endif //TEST_THREAD_H +