00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <d32dbms.h>
00015 #include "SmpExample.h"
00016 _LIT(KDatabase1, "C:\\DBforSMP1.db");
00017 _LIT(KDatabase2, "C:\\DBforSMP2.db");
00018
00022 CSmpExample::~CSmpExample()
00023 {
00024 iReadThread.Close();
00025 iWriteThread1.Close();
00026 iWriteThread2.Close();
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
00054 _LIT(KReader, "ReaderThread");
00055 User::LeaveIfError(iReadThread.Create(KReader, ReadThreadFuncL, KDefaultStackSize, KMinHeapSize, 256*KMinHeapSize, this, EOwnerProcess));
00056
00057
00058 _LIT(KWriter1, "WriterThread1");
00059 User::LeaveIfError(iWriteThread1.Create(KWriter1, WriteThread1FuncL, KDefaultStackSize, KMinHeapSize, 256*KMinHeapSize, this, EOwnerProcess));
00060
00061
00062 _LIT(KWriter2, "WriterThread2");
00063 User::LeaveIfError(iWriteThread2.Create(KWriter2, WriteThread2FuncL, KDefaultStackSize, KMinHeapSize, 256*KMinHeapSize, this, EOwnerProcess));
00064
00065
00066
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
00086 iReadThread.Logon(readerThreadStatus);
00087 iReadThread.Resume();
00088
00089
00090 iWriteThread1.Logon(writerThread1Status);
00091 iWriteThread1.Resume();
00092
00093
00094 iWriteThread2.Logon(writerThread2Status);
00095 iWriteThread2.Resume();
00096
00097
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
00134 RFs fsSession;
00135 CleanupClosePushL(fsSession);
00136 fsSession.Connect();
00137
00138
00139 RDbs dbs;
00140 CleanupClosePushL(dbs);
00141 dbs.Connect();
00142
00143
00144 RDbNamedDatabase database;
00145 CleanupClosePushL(database);
00146 User::LeaveIfError(database.Open(dbs, aDbName));
00147
00148
00149 database.Begin();
00150
00151 _LIT(KSQLStatement, "Select Number1, Number2, Number3 from Numbers order by Number1, Number2, Number3");
00152
00153
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
00164 TBool isDbEmpty= EFalse;
00165
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
00173 _LIT(KRowFormatter, "Reading %d \t%d\t%d\n");
00174
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
00206 ReadDatabaseL(KDatabase1, *console);
00207
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* )
00221 {
00222 __UHEAP_MARK;
00223
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
00248 RFs fsSession;
00249 CleanupClosePushL(fsSession);
00250 fsSession.Connect();
00251
00252
00253
00254 RDbs dbs;
00255 CleanupClosePushL(dbs);
00256 dbs.Connect();
00257
00258
00259 RDbNamedDatabase database;
00260 CleanupClosePushL(database);
00261 User::LeaveIfError(database.Open(dbs, aDbName));
00262
00263
00264 database.Begin();
00265
00266
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
00276 view.InsertL();
00277
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
00286 database.Commit();
00287 CleanupStack::PopAndDestroy(&database);
00288 CleanupStack::PopAndDestroy(&dbs);
00289 CleanupStack::PopAndDestroy(&fsSession);
00290 }
00291
00292
00297 TInt CSmpExample::WriteThread2FuncL(TAny* )
00298 {
00299 __UHEAP_MARK;
00300
00301 CTrapCleanup* cleanup = CTrapCleanup::New();
00302 if(!cleanup)
00303 {
00304 return KErrNoMemory;
00305 }
00306
00307
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* )
00325 {
00326 __UHEAP_MARK;
00327
00328 CTrapCleanup* cleanup = CTrapCleanup::New();
00329 if(!cleanup)
00330 {
00331 return KErrNoMemory;
00332 }
00333
00334
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
00354 RFs fsSession;
00355 CleanupClosePushL(fsSession);
00356 fsSession.Connect();
00357
00358
00359 RDbs dbs;
00360 CleanupClosePushL(dbs);
00361 dbs.Connect();
00362
00363
00364
00365 RDbNamedDatabase database;
00366 CleanupClosePushL(database);
00367 User::LeaveIfError(database.Replace(fsSession, aDbName));
00368 database.Close();
00369
00370
00371 User::LeaveIfError(database.Open(dbs, aDbName));
00372
00373 CDbColSet* columns=CDbColSet::NewLC();
00374
00375
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
00385 _LIT(KTable, "Numbers");
00386 User::LeaveIfError(database.CreateTable(KTable, *columns));
00387
00388 CDbKey* key=CDbKey::NewLC();
00389
00390
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
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
00426 __UHEAP_MARK;
00427 CTrapCleanup* cleanup = CTrapCleanup::New();
00428 if(!cleanup)
00429 {
00430 return KErrNoMemory;
00431 }
00432
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