kerneltest/e32test/thread/t_threadedserver.cpp
changeset 0 a41df078684a
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32test\thread\t_threadedserver.cpp
       
    15 // Tests the multi-threaded server/session support in CServer2/CSession2
       
    16 // Overview:
       
    17 // Tests the CServer2::SetMaster and CSession2:SetServer functions
       
    18 // API Information:
       
    19 // CServer2, CSession2
       
    20 // Details:
       
    21 // - Test creating multiple sessions with a single-threaded server
       
    22 // - Test creating multiple sessions with a multi-threaded server
       
    23 // - Verify that requests to a multi-threaded server can run in parallel and complete out-of-order
       
    24 // Platforms/Drives/Compatibility:
       
    25 // All.
       
    26 // Assumptions/Requirement/Pre-requisites:
       
    27 // Failures and causes:
       
    28 // Base Port information:
       
    29 //
       
    30 
       
    31 
       
    32 
       
    33 #define __E32TEST_EXTENSION__
       
    34 #include <e32test.h>
       
    35 #include <e32panic.h>
       
    36 #include <e32debug.h>
       
    37 
       
    38 _LIT(KMyName, "T_THREADEDSERVER");
       
    39 _LIT(KServerName,"MyServer");
       
    40 const TInt KHeapSize = 4096;
       
    41 
       
    42 LOCAL_D RTest test(KMyName);
       
    43 
       
    44 class CMySession : public CSession2
       
    45 	{
       
    46 public:
       
    47 	enum TMyRequests { EFinish, EDelay5, EPing };
       
    48 	CMySession(TInt aId);
       
    49 	virtual void ServiceL(const RMessage2& aMessage);
       
    50 private:
       
    51 	const TInt iD;
       
    52 	};
       
    53 
       
    54 CMySession::CMySession(TInt aId) :
       
    55 	iD(aId)
       
    56 	{
       
    57 	}
       
    58 
       
    59 void CMySession::ServiceL(const RMessage2& aMessage)
       
    60 	{
       
    61 	TInt err = KErrNotSupported;
       
    62 
       
    63 	RDebug::Printf("Session %d: received message %d", iD, aMessage.Function());
       
    64 	switch (aMessage.Function())
       
    65 		{
       
    66 		case EFinish:
       
    67 			CActiveScheduler::Stop();
       
    68 			err = KErrNone;
       
    69 			break;
       
    70 
       
    71 		case EDelay5:
       
    72 			User::After(5000000);
       
    73 			err = KErrNone;
       
    74 			break;
       
    75 
       
    76 		case EPing:
       
    77 			User::After(1000000);
       
    78 			err = KErrNone;
       
    79 			break;
       
    80 
       
    81 		default:
       
    82 			break;
       
    83 		}
       
    84 
       
    85 	RDebug::Printf("Session %d: completing message %d, err %d", iD, aMessage.Function(), err);
       
    86 	if (err == KErrNone)
       
    87 		aMessage.Complete(err);
       
    88 	else
       
    89 		aMessage.Panic(KServerName, err);
       
    90 	}
       
    91 
       
    92 
       
    93 class CMyServer : public CServer2
       
    94 	{
       
    95 public:
       
    96 	CMyServer();
       
    97 	virtual CSession2* NewSessionL(const TVersion& aVersion, const RMessage2& aMessage) const;
       
    98 private:
       
    99 	mutable TInt iCount;
       
   100 	};
       
   101 
       
   102 static CMyServer* TheMaster = NULL;
       
   103 static CMyServer* TheSlave = NULL;
       
   104 
       
   105 CMyServer::CMyServer() :
       
   106 	CServer2(0),
       
   107 	iCount(0)
       
   108 	{
       
   109 	}
       
   110 
       
   111 CSession2* CMyServer::NewSessionL(const TVersion&, const RMessage2&) const
       
   112 	{
       
   113 	RDebug::Printf("Server: creating session, slave is $%x", TheSlave);
       
   114 	iCount += 1;
       
   115 	CSession2* mySession = new (ELeave) CMySession(iCount);
       
   116 	if (iCount > 1 && TheSlave != NULL)
       
   117 		mySession->SetServer(TheSlave);
       
   118 	RDebug::Printf("Server: created session %d", iCount);
       
   119 	return mySession;
       
   120 	}
       
   121 
       
   122 TInt RunServerCode(TAny* aFlag)
       
   123 	{
       
   124 	TInt mode = (TInt)aFlag;
       
   125 	TInt r = KErrNoMemory;
       
   126 	RDebug::Printf("Server: start, mode %d", mode);
       
   127 
       
   128 	CTrapCleanup* cleanup = CTrapCleanup::New();
       
   129 	if (cleanup == NULL)
       
   130 		return r;
       
   131 
       
   132 	CActiveScheduler* pR = new CActiveScheduler;
       
   133 	if (pR == NULL)
       
   134 		return r;
       
   135 
       
   136 	CActiveScheduler::Install(pR);
       
   137 	CMyServer* pS = new CMyServer();
       
   138 	if (pS == NULL)
       
   139 		return r;
       
   140 
       
   141 	switch (mode)
       
   142 		{
       
   143 		case 0:
       
   144 			r = pS->Start(KServerName);
       
   145 			break;
       
   146 		case 1:
       
   147 			TheMaster = pS;
       
   148 			pS->SetMaster(TheMaster);
       
   149 			r = pS->Start(KServerName);
       
   150 			break;
       
   151 		case 2:
       
   152 			TheSlave = pS;
       
   153 			pS->SetMaster(TheMaster);
       
   154 			r = pS->Start(KNullDesC);
       
   155 			break;
       
   156 		}
       
   157 	if (r != KErrNone)
       
   158 		return r;
       
   159 
       
   160 	RThread::Rendezvous(KErrNone);
       
   161 	TRAP(r, CActiveScheduler::Start());
       
   162 	if (r != KErrNone)
       
   163 		return r;
       
   164 
       
   165 	delete pS;
       
   166 	delete pR;
       
   167 	delete cleanup;
       
   168 
       
   169 	RDebug::Printf("Server: exit");
       
   170 	return KErrNone;
       
   171 	}
       
   172 
       
   173 
       
   174 class RSession : public RSessionBase
       
   175 	{
       
   176 public:
       
   177 	TInt Create();
       
   178 	void Request(TInt aRequest, TRequestStatus& aStatus);
       
   179 	void Request(TInt aRequest);
       
   180 	};
       
   181 
       
   182 TInt RSession::Create()
       
   183 	{
       
   184 	return CreateSession(KServerName, TVersion());
       
   185 	}
       
   186 
       
   187 void RSession::Request(TInt aRequest, TRequestStatus& aStatus)
       
   188 	{
       
   189 	SendReceive(aRequest, TIpcArgs(), aStatus);
       
   190 	}
       
   191 
       
   192 void RSession::Request(TInt aRequest)
       
   193 	{
       
   194 	SendReceive(aRequest, TIpcArgs());
       
   195 	}
       
   196 
       
   197 TInt RunClientCode(TAny* aFlag)
       
   198 	{
       
   199 	TInt mode = (TInt)aFlag;
       
   200 	RDebug::Printf("Client: open sessions");
       
   201 	RSession session1, session2;
       
   202 	session1.Create();
       
   203 	session2.Create();
       
   204 
       
   205 	TBool ooc = EFalse;
       
   206 	TRequestStatus status1 (KRequestPending), status2 (KRequestPending);
       
   207 	RDebug::Printf("Client: send request 1");
       
   208 	session1.Request(CMySession::EDelay5, status1);
       
   209 	User::After(1000000);
       
   210 	RDebug::Printf("Client: send request 2");
       
   211 	session2.Request(CMySession::EPing, status2);
       
   212 
       
   213 	User::WaitForRequest(status1, status2);
       
   214 	if (status1 == KRequestPending)
       
   215 		{
       
   216 		// request2 finished first ...
       
   217 		ooc = ETrue;
       
   218 		RDebug::Printf("Client: request 2 completed %d", status2.Int());
       
   219 		User::WaitForRequest(status1);
       
   220 		}
       
   221 	else
       
   222 		{
       
   223 		RDebug::Printf("Client: request 1 completed %d", status1.Int());
       
   224 		User::WaitForRequest(status2);
       
   225 		}
       
   226 	RDebug::Printf("Client: status1 %d status2 %d OOC %d", status1.Int(), status2.Int(), ooc);
       
   227 	test_KErrNone(status1.Int());
       
   228 	test_KErrNone(status2.Int());
       
   229 	test_Equal(ooc, mode > 0);
       
   230 
       
   231 	if (mode)
       
   232 		session2.Request(CMySession::EFinish);
       
   233 	session1.Request(CMySession::EFinish);
       
   234 	RDebug::Printf("Client: exit");
       
   235 	return KErrNone;
       
   236 	}
       
   237 
       
   238 
       
   239 void TestSequential()
       
   240 	{
       
   241 	TRequestStatus status;
       
   242 
       
   243 	RDebug::Printf("Main: start server");
       
   244 	RThread serverThread;
       
   245 	test_KErrNone(serverThread.Create(_L("server"), RunServerCode, KHeapSize, NULL, (TAny*)0));
       
   246 	serverThread.Rendezvous(status);
       
   247 	serverThread.Resume();
       
   248 	User::WaitForRequest(status);
       
   249 	test_KErrNone(status.Int());
       
   250 
       
   251 	RDebug::Printf("Main: start client");
       
   252 	RThread clientThread;
       
   253 	test_KErrNone(clientThread.Create(_L("client"), RunClientCode, KHeapSize, NULL, (TAny*)0));
       
   254 	clientThread.Logon(status);
       
   255 	clientThread.Resume();
       
   256 	User::WaitForRequest(status);
       
   257 	test_KErrNone(clientThread.ExitReason());
       
   258 	test_Equal(EExitKill, clientThread.ExitType());
       
   259 
       
   260 	serverThread.Logon(status);
       
   261 	User::WaitForRequest(status);
       
   262 	test_KErrNone(serverThread.ExitReason());
       
   263 	test_Equal(EExitKill, serverThread.ExitType());
       
   264 
       
   265 	User::After(1000);
       
   266 	RDebug::Printf("Main: exit");
       
   267 	}
       
   268 
       
   269 void TestParallel()
       
   270 	{
       
   271 	TRequestStatus status;
       
   272 
       
   273 	RDebug::Printf("Main: start master server");
       
   274 	RThread masterThread;
       
   275 	test_KErrNone(masterThread.Create(_L("master"), RunServerCode, KHeapSize, NULL, (TAny*)1));
       
   276 	masterThread.Rendezvous(status);
       
   277 	masterThread.Resume();
       
   278 	User::WaitForRequest(status);
       
   279 	test_KErrNone(status.Int());
       
   280 
       
   281 	RDebug::Printf("Main: start slave server");
       
   282 	RThread slaveThread;
       
   283 	test_KErrNone(slaveThread.Create(_L("slave"), RunServerCode, KHeapSize, NULL, (TAny*)2));
       
   284 	slaveThread.Rendezvous(status);
       
   285 	slaveThread.Resume();
       
   286 	User::WaitForRequest(status);
       
   287 	test_KErrNone(status.Int());
       
   288 
       
   289 	RDebug::Printf("Main: start client");
       
   290 	RThread clientThread;
       
   291 	test_KErrNone(clientThread.Create(_L("client2"), RunClientCode, KHeapSize, NULL, (TAny*)3));
       
   292 	clientThread.Logon(status);
       
   293 	clientThread.Resume();
       
   294 	User::WaitForRequest(status);
       
   295 	test_KErrNone(clientThread.ExitReason());
       
   296 	test_Equal(EExitKill, clientThread.ExitType());
       
   297 
       
   298 	slaveThread.Logon(status);
       
   299 	User::WaitForRequest(status);
       
   300 	test_KErrNone(slaveThread.ExitReason());
       
   301 	test_Equal(EExitKill, slaveThread.ExitType());
       
   302 
       
   303 	masterThread.Logon(status);
       
   304 	User::WaitForRequest(status);
       
   305 	test_KErrNone(masterThread.ExitReason());
       
   306 	test_Equal(EExitKill, masterThread.ExitType());
       
   307 
       
   308 	User::After(1000);
       
   309 	RDebug::Printf("Main: exit");
       
   310 	}
       
   311 
       
   312 
       
   313 GLDEF_C TInt E32Main()
       
   314 //
       
   315 // Main
       
   316 //
       
   317 	{	
       
   318 	test.Title();
       
   319 	__UHEAP_MARK;
       
   320 
       
   321 	test.Start(_L("Test threaded server support"));
       
   322 	test.Next(_L("Test two sessions to the same server (single-threaded)"));
       
   323 	TestSequential();
       
   324 	test.Next(_L("Test two sessions to the same server (multi-threaded)"));
       
   325 	TestParallel();
       
   326 	test.End();
       
   327 
       
   328 	__UHEAP_MARKEND;
       
   329 	return(KErrNone);
       
   330 	}