--- /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 <e32test.h>
+#include <e32panic.h>
+#include <e32debug.h>
+
+_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);
+ }