00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "SemaphoreExample.h"
00019
00023 CSemaphoreExample::~CSemaphoreExample()
00024 {
00025 iReadThread.Close();
00026 iWriteThread.Close();
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
00049 _LIT(KReader,"ReaderThread");
00050 User::LeaveIfError(iReadThread.Create(KReader,ReadThreadFuncL,KDefaultStackSize,KMinHeapSize,256*KMinHeapSize,this,EOwnerProcess));
00051
00052
00053 _LIT(KWriter,"WriterThread");
00054 User::LeaveIfError(iWriteThread.Create(KWriter,WriteThreadFuncL,KDefaultStackSize,KMinHeapSize,256*KMinHeapSize,this,EOwnerProcess));
00055
00056
00057
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
00078 iReadThread.Logon(status2);
00079 iReadThread.Resume();
00080
00081
00082 iWriteThread.Logon(status1);
00083 iWriteThread.Resume();
00084
00085
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
00151 db->ReadfromDatabaseL();
00152
00153 CleanupStack::PopAndDestroy(db);
00154 CleanupStack::PopAndDestroy(scheduler);
00155 }
00156
00161 TInt CSemaphoreExample::ReadThreadFuncL(TAny* )
00162 {
00163 __UHEAP_MARK;
00164
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
00195 db->CreateDatabaseL();
00196
00197
00198 db->WritetoDatabaseL();
00199
00200 CleanupStack::PopAndDestroy(db);
00201 CleanupStack::PopAndDestroy(scheduler);
00202 }
00203
00208 TInt CSemaphoreExample::WriteThreadFuncL(TAny* )
00209 {
00210 __UHEAP_MARK;
00211
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
00247 __UHEAP_MARK;
00248 CTrapCleanup* cleanup = CTrapCleanup::New();
00249 if(!cleanup)
00250 {
00251 return KErrNoMemory;
00252 }
00253
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 }