00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <d32dbms.h>
00031 #include "SmpExample.h"
00032 _LIT(KDatabase1, "C:\\DBforSMP1.db");
00033 _LIT(KDatabase2, "C:\\DBforSMP2.db");
00034
00038 CSmpExample::~CSmpExample()
00039 {
00040 iReadThread.Close();
00041 iWriteThread1.Close();
00042 iWriteThread2.Close();
00043 delete iConsole;
00044 }
00045
00049 CSmpExample* CSmpExample::NewL()
00050 {
00051 CSmpExample* self = new(ELeave)CSmpExample();
00052 CleanupStack::PushL(self);
00053 self->ConstructL();
00054 CleanupStack::Pop(self);
00055 return self;
00056 }
00057
00061 void CSmpExample::ConstructL()
00062 {
00063 CreateDatabaseL(KDatabase1);
00064 CreateDatabaseL(KDatabase2);
00065
00066 _LIT(KTextConsoleTitle, "SmpExample");
00067 iConsole = Console::NewL(KTextConsoleTitle, TSize(KConsFullScreen, KConsFullScreen));
00068
00069
00070 _LIT(KReader, "ReaderThread");
00071 User::LeaveIfError(iReadThread.Create(KReader, ReadThreadFuncL, KDefaultStackSize, KMinHeapSize, 256*KMinHeapSize, this, EOwnerProcess));
00072
00073
00074 _LIT(KWriter1, "WriterThread1");
00075 User::LeaveIfError(iWriteThread1.Create(KWriter1, WriteThread1FuncL, KDefaultStackSize, KMinHeapSize, 256*KMinHeapSize, this, EOwnerProcess));
00076
00077
00078 _LIT(KWriter2, "WriterThread2");
00079 User::LeaveIfError(iWriteThread2.Create(KWriter2, WriteThread2FuncL, KDefaultStackSize, KMinHeapSize, 256*KMinHeapSize, this, EOwnerProcess));
00080
00081
00082
00083 iWriteThread1.SetPriority(EPriorityMuchLess);
00084 iWriteThread2.SetPriority(EPriorityMore);
00085 iReadThread.SetPriority(EPriorityNormal);
00086 }
00087
00091 void CSmpExample::StartThreads()
00092 {
00093 TRequestStatus writerThread1Status;
00094 TRequestStatus readerThreadStatus;
00095 TRequestStatus writerThread2Status;
00096
00097 _LIT(KTextPressKey, "\nPress any key to start writing to and reading from the database\n");
00098 iConsole->Printf(KTextPressKey);
00099 iConsole->Getch();
00100
00101
00102 iReadThread.Logon(readerThreadStatus);
00103 iReadThread.Resume();
00104
00105
00106 iWriteThread1.Logon(writerThread1Status);
00107 iWriteThread1.Resume();
00108
00109
00110 iWriteThread2.Logon(writerThread2Status);
00111 iWriteThread2.Resume();
00112
00113
00114 User::WaitForRequest(writerThread1Status);
00115 User::WaitForRequest(readerThreadStatus);
00116 User::WaitForRequest(writerThread2Status);
00117 }
00118
00122 void CSmpExample::PrintMessage()
00123 {
00124 _LIT(KTextWelcome, "Welcome to the SmpExample.\n");
00125 _LIT(KTextPurposel1, "There are three threads running in the example: WriterThread1 has the lowest priority,\n");
00126 _LIT(KTextPurposel2, "ReaderThread has normal priority and WriterThread2 has maximum priority.\n");
00127 _LIT(KTextPurposel3, "The two WriterThreads open two different databases and write some integers to them.\n");
00128 _LIT(KTextPurposel4, "ReaderThread reads the two databases and prints the output to the console.\n");
00129
00130 _LIT(KTextPurposel5, "In a unicore environment, WriterThread1 will be scheduled to run last and would not have\n");
00131 _LIT(KTextPurposel6, "written to the database when ReaderThread starts reading the databases.\n");
00132 _LIT(KTextPurposel7, "But in an SMP environment, both the WriterThreads write to their respective databases simultaneously.\n");
00133
00134 iConsole->Printf(KTextWelcome);
00135 iConsole->Printf(KTextPurposel1);
00136 iConsole->Printf(KTextPurposel2);
00137 iConsole->Printf(KTextPurposel3);
00138 iConsole->Printf(KTextPurposel4);
00139 iConsole->Printf(KTextPurposel5);
00140 iConsole->Printf(KTextPurposel6);
00141 iConsole->Printf(KTextPurposel7);
00142 }
00143
00147 void CSmpExample::ReadDatabaseL(const TDesC& aDbName, CConsoleBase& console)
00148 {
00149
00150 RFs fsSession;
00151 CleanupClosePushL(fsSession);
00152 fsSession.Connect();
00153
00154
00155 RDbs dbs;
00156 CleanupClosePushL(dbs);
00157 dbs.Connect();
00158
00159
00160 RDbNamedDatabase database;
00161 CleanupClosePushL(database);
00162 User::LeaveIfError(database.Open(dbs, aDbName));
00163
00164
00165 database.Begin();
00166
00167 _LIT(KSQLStatement, "Select Number1, Number2, Number3 from Numbers order by Number1, Number2, Number3");
00168
00169
00170 RDbView view;
00171 CleanupClosePushL(view);
00172
00173 User::LeaveIfError(view.Prepare(database, TDbQuery(KSQLStatement, EDbCompareNormal)));
00174 User::LeaveIfError(view.EvaluateAll());
00175
00176 _LIT(KTextReading, "Reading the database\t %S.\n");
00177 console.Printf(KTextReading, &aDbName);
00178
00179
00180 TBool isDbEmpty= EFalse;
00181
00182 for (view.FirstL(); view.AtRow(); view.NextL())
00183 {
00184 view.GetL();
00185 TInt number1 = view.ColInt(1);
00186 TInt number2 = view.ColInt(2);
00187 TInt number3 = view.ColInt(3);
00188
00189 _LIT(KRowFormatter, "Reading %d \t%d\t%d\n");
00190
00191 console.Printf(KRowFormatter, number1, number2, number3);
00192 isDbEmpty= ETrue;
00193 }
00194
00195 if(isDbEmpty== EFalse)
00196 {
00197 _LIT(KTextDbEmpty, "Database is empty.\n\n");
00198 console.Printf(KTextDbEmpty);
00199 }
00200 else
00201 {
00202 _LIT(KTextAllRead, "All the numbers in the database have been read.\n\n");
00203 console.Printf(KTextAllRead);
00204 }
00205
00206 CleanupStack::PopAndDestroy(&view);
00207 CleanupStack::PopAndDestroy(&database);
00208 CleanupStack::PopAndDestroy(&dbs);
00209 CleanupStack::PopAndDestroy(&fsSession);
00210 }
00211
00215 void CSmpExample::ReadBothDatabasesL()
00216 {
00217 _LIT(KTextConsoleTitle, "ReaderThread");
00218 CConsoleBase* console= Console::NewL(KTextConsoleTitle, TSize(KConsFullScreen, KConsFullScreen));
00219 CleanupStack::PushL(console);
00220
00221
00222 ReadDatabaseL(KDatabase1, *console);
00223
00224 ReadDatabaseL(KDatabase2, *console);
00225
00226 _LIT(KExit, "Press any key to exit\n");
00227 console->Printf(KExit);
00228 console->Getch();
00229 CleanupStack::PopAndDestroy(console);
00230 }
00231
00236 TInt CSmpExample::ReadThreadFuncL(TAny* )
00237 {
00238 __UHEAP_MARK;
00239
00240 CTrapCleanup* cleanup = CTrapCleanup::New();
00241 if(!cleanup)
00242 {
00243 return KErrNoMemory;
00244 }
00245
00246 TRAPD(error, ReadBothDatabasesL());
00247 if(error != KErrNone)
00248 {
00249 _LIT(KUserPanic, "DB Read Failed");
00250 User::Panic(KUserPanic, error);
00251 }
00252 delete cleanup;
00253 __UHEAP_MARKEND;
00254 return KErrNone;
00255 }
00256
00261 void CSmpExample::WriteDbFuncL(const TDesC& aDbName, TInt aNum)
00262 {
00263
00264 RFs fsSession;
00265 CleanupClosePushL(fsSession);
00266 fsSession.Connect();
00267
00268
00269
00270 RDbs dbs;
00271 CleanupClosePushL(dbs);
00272 dbs.Connect();
00273
00274
00275 RDbNamedDatabase database;
00276 CleanupClosePushL(database);
00277 User::LeaveIfError(database.Open(dbs, aDbName));
00278
00279
00280 database.Begin();
00281
00282
00283 RDbView view;
00284 CleanupClosePushL(view);
00285 _LIT(KSQLStatement, "Select Number1, Number2, Number3 from Numbers order by Number1, Number2, Number3");
00286 User::LeaveIfError(view.Prepare(database, TDbQuery(KSQLStatement, EDbCompareNormal)));
00287 User::LeaveIfError(view.EvaluateAll());
00288
00289 for(int i=0; i<5; i++)
00290 {
00291
00292 view.InsertL();
00293
00294 view.SetColL(1, aNum++);
00295 view.SetColL(2, aNum++);
00296 view.SetColL(3, aNum++);
00297 view.PutL();
00298 }
00299
00300 CleanupStack::PopAndDestroy(&view);
00301
00302 database.Commit();
00303 CleanupStack::PopAndDestroy(&database);
00304 CleanupStack::PopAndDestroy(&dbs);
00305 CleanupStack::PopAndDestroy(&fsSession);
00306 }
00307
00308
00313 TInt CSmpExample::WriteThread2FuncL(TAny* )
00314 {
00315 __UHEAP_MARK;
00316
00317 CTrapCleanup* cleanup = CTrapCleanup::New();
00318 if(!cleanup)
00319 {
00320 return KErrNoMemory;
00321 }
00322
00323
00324 const int KFirstNumforDb2 = 500;
00325 TRAPD(err, WriteDbFuncL(KDatabase2, KFirstNumforDb2));
00326 if(err != KErrNone)
00327 {
00328 _LIT(KUserPanic, "DB Write Failed");
00329 User::Panic(KUserPanic, err);
00330 }
00331 delete cleanup;
00332 __UHEAP_MARKEND;
00333 return KErrNone;
00334 }
00335
00340 TInt CSmpExample::WriteThread1FuncL(TAny* )
00341 {
00342 __UHEAP_MARK;
00343
00344 CTrapCleanup* cleanup = CTrapCleanup::New();
00345 if(!cleanup)
00346 {
00347 return KErrNoMemory;
00348 }
00349
00350
00351 const int KFirstNumforDb1 = 0;
00352 TRAPD(err, WriteDbFuncL(KDatabase1, KFirstNumforDb1));
00353 if(err != KErrNone)
00354 {
00355 _LIT(KUserPanic, "DB Write Failed");
00356 User::Panic(KUserPanic, err);
00357 }
00358 delete cleanup;
00359 __UHEAP_MARKEND;
00360 return KErrNone;
00361 }
00362
00367 void CSmpExample::CreateDatabaseL(const TDesC& aDbName)
00368 {
00369
00370 RFs fsSession;
00371 CleanupClosePushL(fsSession);
00372 fsSession.Connect();
00373
00374
00375 RDbs dbs;
00376 CleanupClosePushL(dbs);
00377 dbs.Connect();
00378
00379
00380
00381 RDbNamedDatabase database;
00382 CleanupClosePushL(database);
00383 User::LeaveIfError(database.Replace(fsSession, aDbName));
00384 database.Close();
00385
00386
00387 User::LeaveIfError(database.Open(dbs, aDbName));
00388
00389 CDbColSet* columns=CDbColSet::NewLC();
00390
00391
00392 _LIT(KCol1, "Number1");
00393 _LIT(KCol2, "Number2");
00394 _LIT(KCol3, "Number3");
00395 columns->AddL(TDbCol(KCol1, EDbColInt32));
00396 columns->AddL(TDbCol(KCol2, EDbColInt32));
00397 columns->AddL(TDbCol(KCol3, EDbColInt32));
00398
00399
00400
00401 _LIT(KTable, "Numbers");
00402 User::LeaveIfError(database.CreateTable(KTable, *columns));
00403
00404 CDbKey* key=CDbKey::NewLC();
00405
00406
00407 TDbKeyCol number1(KCol1);
00408 key->AddL(number1);
00409 TDbKeyCol number2(KCol2);
00410 key->AddL(number2);
00411 TDbKeyCol number3(KCol3);
00412 key->AddL(number3);
00413 User::LeaveIfError(database.CreateIndex(KTable, KTable, *key));
00414
00415
00416 CleanupStack::PopAndDestroy(key);
00417 CleanupStack::PopAndDestroy(columns);
00418 CleanupStack::PopAndDestroy(&database);
00419 CleanupStack::PopAndDestroy(&dbs);
00420 CleanupStack::PopAndDestroy(&fsSession);
00421 }
00422
00427 static void MainL()
00428 {
00429 CSmpExample* smpExample = CSmpExample::NewL();
00430 CleanupStack::PushL(smpExample);
00431 smpExample->PrintMessage();
00432 smpExample->StartThreads();
00433 CleanupStack::PopAndDestroy(smpExample);
00434 }
00435
00439 extern TInt E32Main()
00440 {
00441
00442 __UHEAP_MARK;
00443 CTrapCleanup* cleanup = CTrapCleanup::New();
00444 if(!cleanup)
00445 {
00446 return KErrNoMemory;
00447 }
00448
00449 TRAPD(mainError, MainL());
00450 if(mainError != KErrNone)
00451 {
00452 _LIT(KUserPanic, "Main Failed");
00453 User::Panic(KUserPanic, mainError);
00454 }
00455 delete cleanup;
00456 __UHEAP_MARKEND;
00457 return KErrNone;
00458 }
00459