diff -r 89d6a7a84779 -r 25a17d01db0c Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_smp_example_8cpp-source.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/Examples/guid-6013a680-57f9-415b-8851-c4fa63356636/_smp_example_8cpp-source.html Fri Jan 22 18:26:19 2010 +0000 @@ -0,0 +1,407 @@ + +
+00001 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). +00002 // All rights reserved. +00003 // This component and the accompanying materials are made available +00004 // under the terms of "Eclipse Public License v1.0" +00005 // which accompanies this distribution, and is available +00006 // at the URL "http://www.eclipse.org/legal/epl-v10.html". +00007 // +00008 // Initial Contributors: +00009 // Nokia Corporation - initial contribution. +00010 // +00011 // Contributors: +00012 // +00013 +00014 #include <d32dbms.h> //Used for RDbDatabase class. +00015 #include "SmpExample.h" +00016 _LIT(KDatabase1, "C:\\DBforSMP1.db"); +00017 _LIT(KDatabase2, "C:\\DBforSMP2.db"); +00018 +00022 CSmpExample::~CSmpExample() +00023 { +00024 iReadThread.Close(); //Reader thread closed. +00025 iWriteThread1.Close(); //Writer thread closed. +00026 iWriteThread2.Close(); //Writer thread closed. +00027 delete iConsole; +00028 } +00029 +00033 CSmpExample* CSmpExample::NewL() +00034 { +00035 CSmpExample* self = new(ELeave)CSmpExample(); +00036 CleanupStack::PushL(self); +00037 self->ConstructL(); +00038 CleanupStack::Pop(self); +00039 return self; +00040 } +00041 +00045 void CSmpExample::ConstructL() +00046 { +00047 CreateDatabaseL(KDatabase1); +00048 CreateDatabaseL(KDatabase2); +00049 +00050 _LIT(KTextConsoleTitle, "SmpExample"); +00051 iConsole = Console::NewL(KTextConsoleTitle, TSize(KConsFullScreen, KConsFullScreen)); +00052 +00053 //Creates a reader thread to read the databases. +00054 _LIT(KReader, "ReaderThread"); +00055 User::LeaveIfError(iReadThread.Create(KReader, ReadThreadFuncL, KDefaultStackSize, KMinHeapSize, 256*KMinHeapSize, this, EOwnerProcess)); +00056 +00057 //Creates a writer thread to write to the DBforSMP1.db database. +00058 _LIT(KWriter1, "WriterThread1"); +00059 User::LeaveIfError(iWriteThread1.Create(KWriter1, WriteThread1FuncL, KDefaultStackSize, KMinHeapSize, 256*KMinHeapSize, this, EOwnerProcess)); +00060 +00061 //Creates a writer thread to write to the DBforSMP2.db database. +00062 _LIT(KWriter2, "WriterThread2"); +00063 User::LeaveIfError(iWriteThread2.Create(KWriter2, WriteThread2FuncL, KDefaultStackSize, KMinHeapSize, 256*KMinHeapSize, this, EOwnerProcess)); +00064 +00065 +00066 //Sets priority to the threads. +00067 iWriteThread1.SetPriority(EPriorityMuchLess); +00068 iWriteThread2.SetPriority(EPriorityMore); +00069 iReadThread.SetPriority(EPriorityNormal); +00070 } +00071 +00075 void CSmpExample::StartThreads() +00076 { +00077 TRequestStatus writerThread1Status; +00078 TRequestStatus readerThreadStatus; +00079 TRequestStatus writerThread2Status; +00080 +00081 _LIT(KTextPressKey, "\nPress any key to start writing to and reading from the database\n"); +00082 iConsole->Printf(KTextPressKey); +00083 iConsole->Getch(); +00084 +00085 //Requests a notification for the ReaderThread to terminate. +00086 iReadThread.Logon(readerThreadStatus); +00087 iReadThread.Resume(); +00088 +00089 //Requests a notification for the WriterThread1 to terminate. +00090 iWriteThread1.Logon(writerThread1Status); +00091 iWriteThread1.Resume(); +00092 +00093 //Requests a notification for the WriterThread2 to terminate. +00094 iWriteThread2.Logon(writerThread2Status); +00095 iWriteThread2.Resume(); +00096 +00097 //Control returns to the main thread when the all the threads terminate. +00098 User::WaitForRequest(writerThread1Status); +00099 User::WaitForRequest(readerThreadStatus); +00100 User::WaitForRequest(writerThread2Status); +00101 } +00102 +00106 void CSmpExample::PrintMessage() +00107 { +00108 _LIT(KTextWelcome, "Welcome to the SmpExample.\n"); +00109 _LIT(KTextPurposel1, "There are three threads running in the example: WriterThread1 has the lowest priority,\n"); +00110 _LIT(KTextPurposel2, "ReaderThread has normal priority and WriterThread2 has maximum priority.\n"); +00111 _LIT(KTextPurposel3, "The two WriterThreads open two different databases and write some integers to them.\n"); +00112 _LIT(KTextPurposel4, "ReaderThread reads the two databases and prints the output to the console.\n"); +00113 +00114 _LIT(KTextPurposel5, "In a unicore environment, WriterThread1 will be scheduled to run last and would not have\n"); +00115 _LIT(KTextPurposel6, "written to the database when ReaderThread starts reading the databases.\n"); +00116 _LIT(KTextPurposel7, "But in an SMP environment, both the WriterThreads write to their respective databases simultaneously.\n"); +00117 +00118 iConsole->Printf(KTextWelcome); +00119 iConsole->Printf(KTextPurposel1); +00120 iConsole->Printf(KTextPurposel2); +00121 iConsole->Printf(KTextPurposel3); +00122 iConsole->Printf(KTextPurposel4); +00123 iConsole->Printf(KTextPurposel5); +00124 iConsole->Printf(KTextPurposel6); +00125 iConsole->Printf(KTextPurposel7); +00126 } +00127 +00131 void CSmpExample::ReadDatabaseL(const TDesC& aDbName, CConsoleBase& console) +00132 { +00133 //Creates a file server session object before any file system manipulation. +00134 RFs fsSession; +00135 CleanupClosePushL(fsSession); +00136 fsSession.Connect(); +00137 +00138 //Creates Rdbs object +00139 RDbs dbs; +00140 CleanupClosePushL(dbs); +00141 dbs.Connect(); +00142 +00143 //Opens the named database using the RDbs object +00144 RDbNamedDatabase database; +00145 CleanupClosePushL(database); +00146 User::LeaveIfError(database.Open(dbs, aDbName)); +00147 +00148 //Locks the database. +00149 database.Begin(); +00150 //Prepare an SQL query to read one row of numbers from the database. +00151 _LIT(KSQLStatement, "Select Number1, Number2, Number3 from Numbers order by Number1, Number2, Number3"); +00152 +00153 //Creates a view on the database to read it. +00154 RDbView view; +00155 CleanupClosePushL(view); +00156 +00157 User::LeaveIfError(view.Prepare(database, TDbQuery(KSQLStatement, EDbCompareNormal))); +00158 User::LeaveIfError(view.EvaluateAll()); +00159 +00160 _LIT(KTextReading, "Reading the database\t %S.\n"); +00161 console.Printf(KTextReading, &aDbName); +00162 +00163 //Boolean variable to check whether the database is empty. +00164 TBool isDbEmpty= EFalse; +00165 //Iterates through the database till the last row is read. +00166 for (view.FirstL(); view.AtRow(); view.NextL()) +00167 { +00168 view.GetL(); +00169 TInt number1 = view.ColInt(1); +00170 TInt number2 = view.ColInt(2); +00171 TInt number3 = view.ColInt(3); +00172 //Prepare a row formatter to print numbers in the console. +00173 _LIT(KRowFormatter, "Reading %d \t%d\t%d\n"); +00174 //Reads the integers from the view and display them in the console. +00175 console.Printf(KRowFormatter, number1, number2, number3); +00176 isDbEmpty= ETrue; +00177 } +00178 +00179 if(isDbEmpty== EFalse) +00180 { +00181 _LIT(KTextDbEmpty, "Database is empty.\n\n"); +00182 console.Printf(KTextDbEmpty); +00183 } +00184 else +00185 { +00186 _LIT(KTextAllRead, "All the numbers in the database have been read.\n\n"); +00187 console.Printf(KTextAllRead); +00188 } +00189 +00190 CleanupStack::PopAndDestroy(&view); +00191 CleanupStack::PopAndDestroy(&database); +00192 CleanupStack::PopAndDestroy(&dbs); +00193 CleanupStack::PopAndDestroy(&fsSession); +00194 } +00195 +00199 void CSmpExample::ReadBothDatabasesL() +00200 { +00201 _LIT(KTextConsoleTitle, "ReaderThread"); +00202 CConsoleBase* console= Console::NewL(KTextConsoleTitle, TSize(KConsFullScreen, KConsFullScreen)); +00203 CleanupStack::PushL(console); +00204 +00205 //Reads DBforSMP1.db and prints the output to the console. +00206 ReadDatabaseL(KDatabase1, *console); +00207 //Reads DBforSMP2.db and prints the output to the console. +00208 ReadDatabaseL(KDatabase2, *console); +00209 +00210 _LIT(KExit, "Press any key to exit\n"); +00211 console->Printf(KExit); +00212 console->Getch(); +00213 CleanupStack::PopAndDestroy(console); +00214 } +00215 +00220 TInt CSmpExample::ReadThreadFuncL(TAny* /*aPtr*/) +00221 { +00222 __UHEAP_MARK; +00223 //Creates cleanup stack. +00224 CTrapCleanup* cleanup = CTrapCleanup::New(); +00225 if(!cleanup) +00226 { +00227 return KErrNoMemory; +00228 } +00229 +00230 TRAPD(error, ReadBothDatabasesL()); +00231 if(error != KErrNone) +00232 { +00233 _LIT(KUserPanic, "DB Read Failed"); +00234 User::Panic(KUserPanic, error); +00235 } +00236 delete cleanup; +00237 __UHEAP_MARKEND; +00238 return KErrNone; +00239 } +00240 +00245 void CSmpExample::WriteDbFuncL(const TDesC& aDbName, TInt aNum) +00246 { +00247 //Creates a file server session object before any file system manipulation. +00248 RFs fsSession; +00249 CleanupClosePushL(fsSession); +00250 fsSession.Connect(); +00251 +00252 +00253 //Creates Rdbs object +00254 RDbs dbs; +00255 CleanupClosePushL(dbs); +00256 dbs.Connect(); +00257 +00258 //Opens the database using the RDbs object +00259 RDbNamedDatabase database; +00260 CleanupClosePushL(database); +00261 User::LeaveIfError(database.Open(dbs, aDbName)); +00262 +00263 //Locks the database. +00264 database.Begin(); +00265 +00266 //Creates a view on the database. +00267 RDbView view; +00268 CleanupClosePushL(view); +00269 _LIT(KSQLStatement, "Select Number1, Number2, Number3 from Numbers order by Number1, Number2, Number3"); +00270 User::LeaveIfError(view.Prepare(database, TDbQuery(KSQLStatement, EDbCompareNormal))); +00271 User::LeaveIfError(view.EvaluateAll()); +00272 +00273 for(int i=0; i<5; i++) +00274 { +00275 //Inserts a new row at the end of the database. +00276 view.InsertL(); +00277 //Fills three columns with numbers. +00278 view.SetColL(1, aNum++); +00279 view.SetColL(2, aNum++); +00280 view.SetColL(3, aNum++); +00281 view.PutL(); +00282 } +00283 +00284 CleanupStack::PopAndDestroy(&view); +00285 //Commits the database and unlocks it. +00286 database.Commit(); +00287 CleanupStack::PopAndDestroy(&database); +00288 CleanupStack::PopAndDestroy(&dbs); +00289 CleanupStack::PopAndDestroy(&fsSession); +00290 } +00291 +00292 +00297 TInt CSmpExample::WriteThread2FuncL(TAny* /*aPtr*/) +00298 { +00299 __UHEAP_MARK; +00300 //Creates cleanup stack. +00301 CTrapCleanup* cleanup = CTrapCleanup::New(); +00302 if(!cleanup) +00303 { +00304 return KErrNoMemory; +00305 } +00306 +00307 //First number to be written to the database. +00308 const int KFirstNumforDb2 = 500; +00309 TRAPD(err, WriteDbFuncL(KDatabase2, KFirstNumforDb2)); +00310 if(err != KErrNone) +00311 { +00312 _LIT(KUserPanic, "DB Write Failed"); +00313 User::Panic(KUserPanic, err); +00314 } +00315 delete cleanup; +00316 __UHEAP_MARKEND; +00317 return KErrNone; +00318 } +00319 +00324 TInt CSmpExample::WriteThread1FuncL(TAny* /*aPtr*/) +00325 { +00326 __UHEAP_MARK; +00327 //Creates cleanup stack. +00328 CTrapCleanup* cleanup = CTrapCleanup::New(); +00329 if(!cleanup) +00330 { +00331 return KErrNoMemory; +00332 } +00333 +00334 //First number to be written to the database. +00335 const int KFirstNumforDb1 = 0; +00336 TRAPD(err, WriteDbFuncL(KDatabase1, KFirstNumforDb1)); +00337 if(err != KErrNone) +00338 { +00339 _LIT(KUserPanic, "DB Write Failed"); +00340 User::Panic(KUserPanic, err); +00341 } +00342 delete cleanup; +00343 __UHEAP_MARKEND; +00344 return KErrNone; +00345 } +00346 +00351 void CSmpExample::CreateDatabaseL(const TDesC& aDbName) +00352 { +00353 //Creates a file server session object before any file system manipulation. +00354 RFs fsSession; +00355 CleanupClosePushL(fsSession); +00356 fsSession.Connect(); +00357 +00358 //Creates Rdbs object +00359 RDbs dbs; +00360 CleanupClosePushL(dbs); +00361 dbs.Connect(); +00362 +00363 //Creates a new database with the name specified in the parameter aDbName, +00364 //if database with same name is present, it will be replaced. +00365 RDbNamedDatabase database; +00366 CleanupClosePushL(database); +00367 User::LeaveIfError(database.Replace(fsSession, aDbName)); +00368 database.Close(); +00369 +00370 //Opens the database using the RDbs object +00371 User::LeaveIfError(database.Open(dbs, aDbName)); +00372 //Creates a table definition. +00373 CDbColSet* columns=CDbColSet::NewLC(); +00374 +00375 //Adds three columns each containing Int32 values. +00376 _LIT(KCol1, "Number1"); +00377 _LIT(KCol2, "Number2"); +00378 _LIT(KCol3, "Number3"); +00379 columns->AddL(TDbCol(KCol1, EDbColInt32)); +00380 columns->AddL(TDbCol(KCol2, EDbColInt32)); +00381 columns->AddL(TDbCol(KCol3, EDbColInt32)); +00382 +00383 +00384 //Creates the table, table name is "Numbers" and add the columns to it. +00385 _LIT(KTable, "Numbers"); +00386 User::LeaveIfError(database.CreateTable(KTable, *columns)); +00387 +00388 CDbKey* key=CDbKey::NewLC(); +00389 +00390 //Add the key columns. +00391 TDbKeyCol number1(KCol1); +00392 key->AddL(number1); +00393 TDbKeyCol number2(KCol2); +00394 key->AddL(number2); +00395 TDbKeyCol number3(KCol3); +00396 key->AddL(number3); +00397 User::LeaveIfError(database.CreateIndex(KTable, KTable, *key)); +00398 +00399 //Cleans up the column set. +00400 CleanupStack::PopAndDestroy(key); +00401 CleanupStack::PopAndDestroy(columns); +00402 CleanupStack::PopAndDestroy(&database); +00403 CleanupStack::PopAndDestroy(&dbs); +00404 CleanupStack::PopAndDestroy(&fsSession); +00405 } +00406 +00411 static void MainL() +00412 { +00413 CSmpExample* smpExample = CSmpExample::NewL(); +00414 CleanupStack::PushL(smpExample); +00415 smpExample->PrintMessage(); +00416 smpExample->StartThreads(); +00417 CleanupStack::PopAndDestroy(smpExample); +00418 } +00419 +00423 extern TInt E32Main() +00424 { +00425 //Creates cleanup stack. +00426 __UHEAP_MARK; +00427 CTrapCleanup* cleanup = CTrapCleanup::New(); +00428 if(!cleanup) +00429 { +00430 return KErrNoMemory; +00431 } +00432 //Run application code inside a TRAP harness. +00433 TRAPD(mainError, MainL()); +00434 if(mainError != KErrNone) +00435 { +00436 _LIT(KUserPanic, "Main Failed"); +00437 User::Panic(KUserPanic, mainError); +00438 } +00439 delete cleanup; +00440 __UHEAP_MARKEND; +00441 return KErrNone; +00442 } +00443 +