diff -r 000000000000 -r a41df078684a kerneltest/e32test/thread/t_threadedserver.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kerneltest/e32test/thread/t_threadedserver.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,330 @@ +// Copyright (c) 1998-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. +// +// Contributors: +// +// Description: +// e32test\thread\t_threadedserver.cpp +// Tests the multi-threaded server/session support in CServer2/CSession2 +// Overview: +// Tests the CServer2::SetMaster and CSession2:SetServer functions +// API Information: +// CServer2, CSession2 +// Details: +// - Test creating multiple sessions with a single-threaded server +// - Test creating multiple sessions with a multi-threaded server +// - Verify that requests to a multi-threaded server can run in parallel and complete out-of-order +// Platforms/Drives/Compatibility: +// All. +// Assumptions/Requirement/Pre-requisites: +// Failures and causes: +// Base Port information: +// + + + +#define __E32TEST_EXTENSION__ +#include +#include +#include + +_LIT(KMyName, "T_THREADEDSERVER"); +_LIT(KServerName,"MyServer"); +const TInt KHeapSize = 4096; + +LOCAL_D RTest test(KMyName); + +class CMySession : public CSession2 + { +public: + enum TMyRequests { EFinish, EDelay5, EPing }; + CMySession(TInt aId); + virtual void ServiceL(const RMessage2& aMessage); +private: + const TInt iD; + }; + +CMySession::CMySession(TInt aId) : + iD(aId) + { + } + +void CMySession::ServiceL(const RMessage2& aMessage) + { + TInt err = KErrNotSupported; + + RDebug::Printf("Session %d: received message %d", iD, aMessage.Function()); + switch (aMessage.Function()) + { + case EFinish: + CActiveScheduler::Stop(); + err = KErrNone; + break; + + case EDelay5: + User::After(5000000); + err = KErrNone; + break; + + case EPing: + User::After(1000000); + err = KErrNone; + break; + + default: + break; + } + + RDebug::Printf("Session %d: completing message %d, err %d", iD, aMessage.Function(), err); + if (err == KErrNone) + aMessage.Complete(err); + else + aMessage.Panic(KServerName, err); + } + + +class CMyServer : public CServer2 + { +public: + CMyServer(); + virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const; +private: + mutable TInt iCount; + }; + +static CMyServer* TheMaster = NULL; +static CMyServer* TheSlave = NULL; + +CMyServer::CMyServer() : + CServer2(0), + iCount(0) + { + } + +CSession2* CMyServer::NewSessionL(const TVersion&, const RMessage2&) const + { + RDebug::Printf("Server: creating session, slave is $%x", TheSlave); + iCount += 1; + CSession2* mySession = new (ELeave) CMySession(iCount); + if (iCount > 1 && TheSlave != NULL) + mySession->SetServer(TheSlave); + RDebug::Printf("Server: created session %d", iCount); + return mySession; + } + +TInt RunServerCode(TAny* aFlag) + { + TInt mode = (TInt)aFlag; + TInt r = KErrNoMemory; + RDebug::Printf("Server: start, mode %d", mode); + + CTrapCleanup* cleanup = CTrapCleanup::New(); + if (cleanup == NULL) + return r; + + CActiveScheduler* pR = new CActiveScheduler; + if (pR == NULL) + return r; + + CActiveScheduler::Install(pR); + CMyServer* pS = new CMyServer(); + if (pS == NULL) + return r; + + switch (mode) + { + case 0: + r = pS->Start(KServerName); + break; + case 1: + TheMaster = pS; + pS->SetMaster(TheMaster); + r = pS->Start(KServerName); + break; + case 2: + TheSlave = pS; + pS->SetMaster(TheMaster); + r = pS->Start(KNullDesC); + break; + } + if (r != KErrNone) + return r; + + RThread::Rendezvous(KErrNone); + TRAP(r, CActiveScheduler::Start()); + if (r != KErrNone) + return r; + + delete pS; + delete pR; + delete cleanup; + + RDebug::Printf("Server: exit"); + return KErrNone; + } + + +class RSession : public RSessionBase + { +public: + TInt Create(); + void Request(TInt aRequest, TRequestStatus& aStatus); + void Request(TInt aRequest); + }; + +TInt RSession::Create() + { + return CreateSession(KServerName, TVersion()); + } + +void RSession::Request(TInt aRequest, TRequestStatus& aStatus) + { + SendReceive(aRequest, TIpcArgs(), aStatus); + } + +void RSession::Request(TInt aRequest) + { + SendReceive(aRequest, TIpcArgs()); + } + +TInt RunClientCode(TAny* aFlag) + { + TInt mode = (TInt)aFlag; + RDebug::Printf("Client: open sessions"); + RSession session1, session2; + session1.Create(); + session2.Create(); + + TBool ooc = EFalse; + TRequestStatus status1 (KRequestPending), status2 (KRequestPending); + RDebug::Printf("Client: send request 1"); + session1.Request(CMySession::EDelay5, status1); + User::After(1000000); + RDebug::Printf("Client: send request 2"); + session2.Request(CMySession::EPing, status2); + + User::WaitForRequest(status1, status2); + if (status1 == KRequestPending) + { + // request2 finished first ... + ooc = ETrue; + RDebug::Printf("Client: request 2 completed %d", status2.Int()); + User::WaitForRequest(status1); + } + else + { + RDebug::Printf("Client: request 1 completed %d", status1.Int()); + User::WaitForRequest(status2); + } + RDebug::Printf("Client: status1 %d status2 %d OOC %d", status1.Int(), status2.Int(), ooc); + test_KErrNone(status1.Int()); + test_KErrNone(status2.Int()); + test_Equal(ooc, mode > 0); + + if (mode) + session2.Request(CMySession::EFinish); + session1.Request(CMySession::EFinish); + RDebug::Printf("Client: exit"); + return KErrNone; + } + + +void TestSequential() + { + TRequestStatus status; + + RDebug::Printf("Main: start server"); + RThread serverThread; + test_KErrNone(serverThread.Create(_L("server"), RunServerCode, KHeapSize, NULL, (TAny*)0)); + serverThread.Rendezvous(status); + serverThread.Resume(); + User::WaitForRequest(status); + test_KErrNone(status.Int()); + + RDebug::Printf("Main: start client"); + RThread clientThread; + test_KErrNone(clientThread.Create(_L("client"), RunClientCode, KHeapSize, NULL, (TAny*)0)); + clientThread.Logon(status); + clientThread.Resume(); + User::WaitForRequest(status); + test_KErrNone(clientThread.ExitReason()); + test_Equal(EExitKill, clientThread.ExitType()); + + serverThread.Logon(status); + User::WaitForRequest(status); + test_KErrNone(serverThread.ExitReason()); + test_Equal(EExitKill, serverThread.ExitType()); + + User::After(1000); + RDebug::Printf("Main: exit"); + } + +void TestParallel() + { + TRequestStatus status; + + RDebug::Printf("Main: start master server"); + RThread masterThread; + test_KErrNone(masterThread.Create(_L("master"), RunServerCode, KHeapSize, NULL, (TAny*)1)); + masterThread.Rendezvous(status); + masterThread.Resume(); + User::WaitForRequest(status); + test_KErrNone(status.Int()); + + RDebug::Printf("Main: start slave server"); + RThread slaveThread; + test_KErrNone(slaveThread.Create(_L("slave"), RunServerCode, KHeapSize, NULL, (TAny*)2)); + slaveThread.Rendezvous(status); + slaveThread.Resume(); + User::WaitForRequest(status); + test_KErrNone(status.Int()); + + RDebug::Printf("Main: start client"); + RThread clientThread; + test_KErrNone(clientThread.Create(_L("client2"), RunClientCode, KHeapSize, NULL, (TAny*)3)); + clientThread.Logon(status); + clientThread.Resume(); + User::WaitForRequest(status); + test_KErrNone(clientThread.ExitReason()); + test_Equal(EExitKill, clientThread.ExitType()); + + slaveThread.Logon(status); + User::WaitForRequest(status); + test_KErrNone(slaveThread.ExitReason()); + test_Equal(EExitKill, slaveThread.ExitType()); + + masterThread.Logon(status); + User::WaitForRequest(status); + test_KErrNone(masterThread.ExitReason()); + test_Equal(EExitKill, masterThread.ExitType()); + + User::After(1000); + RDebug::Printf("Main: exit"); + } + + +GLDEF_C TInt E32Main() +// +// Main +// + { + test.Title(); + __UHEAP_MARK; + + test.Start(_L("Test threaded server support")); + test.Next(_L("Test two sessions to the same server (single-threaded)")); + TestSequential(); + test.Next(_L("Test two sessions to the same server (multi-threaded)")); + TestParallel(); + test.End(); + + __UHEAP_MARKEND; + return(KErrNone); + }