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 // Description: 00014 // Contains the E32Main() function, which executes the example. The macro USE_SEMAPHORE is used at various 00015 // places to show synchronization mechanism using semaphores. 00016 00017 00018 #include "SemaphoreExample.h" 00019 00023 CSemaphoreExample::~CSemaphoreExample() 00024 { 00025 iReadThread.Close();//Reader thread closed. 00026 iWriteThread.Close();//Writer thread closed. 00027 delete iConsole; 00028 } 00029 00033 CSemaphoreExample* CSemaphoreExample::NewL() 00034 { 00035 CSemaphoreExample* self=new(ELeave)CSemaphoreExample(); 00036 CleanupStack::PushL(self); 00037 self->ConstructL(); 00038 CleanupStack::Pop(self); 00039 return self; 00040 } 00041 00046 void CSemaphoreExample::ConstructL() 00047 { 00048 //Create a reader thread to read the database. 00049 _LIT(KReader,"ReaderThread"); 00050 User::LeaveIfError(iReadThread.Create(KReader,ReadThreadFuncL,KDefaultStackSize,KMinHeapSize,256*KMinHeapSize,this,EOwnerProcess)); 00051 00052 //Create a writer thread to write into the database. 00053 _LIT(KWriter,"WriterThread"); 00054 User::LeaveIfError(iWriteThread.Create(KWriter,WriteThreadFuncL,KDefaultStackSize,KMinHeapSize,256*KMinHeapSize,this,EOwnerProcess)); 00055 00056 //Sets the priorities of the threads when not using a semaphore, but this is not a good practice to achieve serialized execution; the preferred way 00057 //should be using semaphores. If USE_SEMAPHORE is used, create a global semaphore. 00058 #ifndef USE_SEMAPHORE 00059 iWriteThread.SetPriority(EPriorityMore); 00060 iReadThread.SetPriority(EPriorityLess); 00061 #else 00062 _LIT(KSemaphoreWrite, "WriteSemaphore"); 00063 User::LeaveIfError(iSem.CreateGlobal(KSemaphoreWrite, 0, EOwnerProcess)); 00064 #endif 00065 } 00066 00070 void CSemaphoreExample::StartThreads() 00071 { 00072 TRequestStatus status1, status2; 00073 00074 _LIT(KPressKey, "\nPress any key to start writing to and reading from the database.\n"); 00075 iConsole->Printf(KPressKey); 00076 iConsole->Getch(); 00077 //Request a notification for iReadThread to terminate. 00078 iReadThread.Logon(status2); 00079 iReadThread.Resume(); 00080 00081 //Request a notification for iWriteThread to terminate. 00082 iWriteThread.Logon(status1); 00083 iWriteThread.Resume(); 00084 00085 //Control returns to the main thread when the two threads terminate. 00086 User::WaitForRequest(status1); 00087 User::WaitForRequest(status2); 00088 } 00089 00090 void CSemaphoreExample::PrintMessage() 00091 { 00092 _LIT(KTextConsoleTitle, "SemaphoreExample"); 00093 iConsole = Console::NewL(KTextConsoleTitle, TSize(KConsFullScreen,KConsFullScreen)); 00094 _LIT(KWelcome, "Welcome to the SemaphoreExample.\n"); 00095 00096 iConsole->Printf(KWelcome); 00097 #ifdef USE_SEMAPHORE 00098 _LIT(KSemDefined, "The USE_SEMAPHORE macro is defined.\n"); 00099 iConsole->Printf(KSemDefined); 00100 #else 00101 _LIT(KSemUnDefined, "The USE_SEMAPHORE macro is undefined.\n"); 00102 iConsole->Printf(KSemUnDefined); 00103 #endif 00104 00105 _LIT(KPurposel1, "There are two threads running in the example: WriterThread calls a periodic function\n"); 00106 _LIT(KPurposel2, "which adds rows of integers to a database at an interval of 1 second.\n"); 00107 00108 iConsole->Printf(KPurposel1); 00109 iConsole->Printf(KPurposel2); 00110 00111 00112 #ifdef USE_SEMAPHORE 00113 00114 _LIT(KPurposel4, "ReaderThread waits for the WriterThread to complete inserting one row of integers\n"); 00115 _LIT(KPurposel5, "and then reads the data just written.\n"); 00116 00117 iConsole->Printf(KPurposel4); 00118 iConsole->Printf(KPurposel5); 00119 #else 00120 _LIT(KPurposel31, "ReaderThread also calls a periodic function to read each row of integers\n"); 00121 _LIT(KPurposel32, "and displays them in the console.\n"); 00122 iConsole->Printf(KPurposel31); 00123 iConsole->Printf(KPurposel32); 00124 #endif 00125 00126 #ifdef USE_SEMAPHORE 00127 _LIT(KSemaphoreNote, "RSemaphore is used to synchronize the two threads.\n"); 00128 iConsole->Printf(KSemaphoreNote); 00129 #else 00130 _LIT(KNoSemaphoreNotel, "This implementation does not use Semaphores, instead it uses thread priorities and doesn't\n"); 00131 _LIT(KNoSemaphoreNote2, "guarantee correct thread synchronization.\n"); 00132 iConsole->Printf(KNoSemaphoreNotel); 00133 iConsole->Printf(KNoSemaphoreNote2); 00134 #endif 00135 } 00136 00141 static void ReadDbFuncL() 00142 { 00143 CActiveScheduler* scheduler = new (ELeave) CActiveScheduler(); 00144 CleanupStack::PushL(scheduler); 00145 CActiveScheduler::Install(scheduler); 00146 00147 CDatabase* db = CDatabase::NewL(); 00148 CleanupStack::PushL(db); 00149 00150 //Start reading the database. 00151 db->ReadfromDatabaseL(); 00152 00153 CleanupStack::PopAndDestroy(db); 00154 CleanupStack::PopAndDestroy(scheduler); 00155 } 00156 00161 TInt CSemaphoreExample::ReadThreadFuncL(TAny* /*aPtr*/) 00162 { 00163 __UHEAP_MARK; 00164 //Create cleanup stack. 00165 CTrapCleanup* cleanup = CTrapCleanup::New(); 00166 if(!cleanup) 00167 { 00168 return KErrNoMemory; 00169 } 00170 00171 TRAPD(error, ReadDbFuncL()); 00172 if(error != KErrNone) 00173 { 00174 _LIT(KUserPanic,"Failed"); 00175 User::Panic(KUserPanic, error); 00176 } 00177 delete cleanup; 00178 __UHEAP_MARKEND; 00179 return KErrNone; 00180 } 00181 00186 static void WriteDbFuncL() 00187 { 00188 CActiveScheduler* scheduler = new (ELeave) CActiveScheduler(); 00189 CleanupStack::PushL(scheduler); 00190 CActiveScheduler::Install(scheduler); 00191 00192 CDatabase* db = CDatabase::NewL(); 00193 CleanupStack::PushL(db); 00194 //Create a database. 00195 db->CreateDatabaseL(); 00196 00197 //Write into the database. 00198 db->WritetoDatabaseL(); 00199 00200 CleanupStack::PopAndDestroy(db); 00201 CleanupStack::PopAndDestroy(scheduler); 00202 } 00203 00208 TInt CSemaphoreExample::WriteThreadFuncL(TAny* /*aPtr*/) 00209 { 00210 __UHEAP_MARK; 00211 //Create cleanup stack. 00212 CTrapCleanup* cleanup = CTrapCleanup::New(); 00213 if(!cleanup) 00214 { 00215 return KErrNoMemory; 00216 } 00217 00218 TRAPD(err, WriteDbFuncL()); 00219 if(err != KErrNone) 00220 { 00221 _LIT(KUserPanic,"Failed"); 00222 User::Panic(KUserPanic, err); 00223 } 00224 delete cleanup; 00225 __UHEAP_MARKEND; 00226 return KErrNone; 00227 } 00228 00232 static void MainL() 00233 { 00234 CSemaphoreExample* semExample = CSemaphoreExample::NewL(); 00235 CleanupStack::PushL(semExample); 00236 semExample->PrintMessage(); 00237 semExample->StartThreads(); 00238 CleanupStack::PopAndDestroy(semExample); 00239 } 00240 00244 extern TInt E32Main() 00245 { 00246 //Create cleanup stack. 00247 __UHEAP_MARK; 00248 CTrapCleanup* cleanup = CTrapCleanup::New(); 00249 if(!cleanup) 00250 { 00251 return KErrNoMemory; 00252 } 00253 //Run application code inside a TRAP harness. 00254 TRAPD(mainError, MainL()); 00255 if(mainError != KErrNone) 00256 { 00257 _LIT(KUserPanic,"Failed"); 00258 User::Panic(KUserPanic, mainError); 00259 } 00260 delete cleanup; 00261 __UHEAP_MARKEND; 00262 return KErrNone; 00263 }
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.