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
00031
00032
00033
00034 #include "SemaphoreExample.h"
00035
00039 CSemaphoreExample::~CSemaphoreExample()
00040 {
00041 iReadThread.Close();
00042 iWriteThread.Close();
00043 delete iConsole;
00044 }
00045
00049 CSemaphoreExample* CSemaphoreExample::NewL()
00050 {
00051 CSemaphoreExample* self=new(ELeave)CSemaphoreExample();
00052 CleanupStack::PushL(self);
00053 self->ConstructL();
00054 CleanupStack::Pop(self);
00055 return self;
00056 }
00057
00062 void CSemaphoreExample::ConstructL()
00063 {
00064
00065 _LIT(KReader,"ReaderThread");
00066 User::LeaveIfError(iReadThread.Create(KReader,ReadThreadFuncL,KDefaultStackSize,KMinHeapSize,256*KMinHeapSize,this,EOwnerProcess));
00067
00068
00069 _LIT(KWriter,"WriterThread");
00070 User::LeaveIfError(iWriteThread.Create(KWriter,WriteThreadFuncL,KDefaultStackSize,KMinHeapSize,256*KMinHeapSize,this,EOwnerProcess));
00071
00072
00073
00074 #ifndef USE_SEMAPHORE
00075 iWriteThread.SetPriority(EPriorityMore);
00076 iReadThread.SetPriority(EPriorityLess);
00077 #else
00078 _LIT(KSemaphoreWrite, "WriteSemaphore");
00079 User::LeaveIfError(iSem.CreateGlobal(KSemaphoreWrite, 0, EOwnerProcess));
00080 #endif
00081 }
00082
00086 void CSemaphoreExample::StartThreads()
00087 {
00088 TRequestStatus status1, status2;
00089
00090 _LIT(KPressKey, "\nPress any key to start writing to and reading from the database.\n");
00091 iConsole->Printf(KPressKey);
00092 iConsole->Getch();
00093
00094 iReadThread.Logon(status2);
00095 iReadThread.Resume();
00096
00097
00098 iWriteThread.Logon(status1);
00099 iWriteThread.Resume();
00100
00101
00102 User::WaitForRequest(status1);
00103 User::WaitForRequest(status2);
00104 }
00105
00106 void CSemaphoreExample::PrintMessage()
00107 {
00108 _LIT(KTextConsoleTitle, "SemaphoreExample");
00109 iConsole = Console::NewL(KTextConsoleTitle, TSize(KConsFullScreen,KConsFullScreen));
00110 _LIT(KWelcome, "Welcome to the SemaphoreExample.\n");
00111
00112 iConsole->Printf(KWelcome);
00113 #ifdef USE_SEMAPHORE
00114 _LIT(KSemDefined, "The USE_SEMAPHORE macro is defined.\n");
00115 iConsole->Printf(KSemDefined);
00116 #else
00117 _LIT(KSemUnDefined, "The USE_SEMAPHORE macro is undefined.\n");
00118 iConsole->Printf(KSemUnDefined);
00119 #endif
00120
00121 _LIT(KPurposel1, "There are two threads running in the example: WriterThread calls a periodic function\n");
00122 _LIT(KPurposel2, "which adds rows of integers to a database at an interval of 1 second.\n");
00123
00124 iConsole->Printf(KPurposel1);
00125 iConsole->Printf(KPurposel2);
00126
00127
00128 #ifdef USE_SEMAPHORE
00129
00130 _LIT(KPurposel4, "ReaderThread waits for the WriterThread to complete inserting one row of integers\n");
00131 _LIT(KPurposel5, "and then reads the data just written.\n");
00132
00133 iConsole->Printf(KPurposel4);
00134 iConsole->Printf(KPurposel5);
00135 #else
00136 _LIT(KPurposel31, "ReaderThread also calls a periodic function to read each row of integers\n");
00137 _LIT(KPurposel32, "and displays them in the console.\n");
00138 iConsole->Printf(KPurposel31);
00139 iConsole->Printf(KPurposel32);
00140 #endif
00141
00142 #ifdef USE_SEMAPHORE
00143 _LIT(KSemaphoreNote, "RSemaphore is used to synchronize the two threads.\n");
00144 iConsole->Printf(KSemaphoreNote);
00145 #else
00146 _LIT(KNoSemaphoreNotel, "This implementation does not use Semaphores, instead it uses thread priorities and doesn't\n");
00147 _LIT(KNoSemaphoreNote2, "guarantee correct thread synchronization.\n");
00148 iConsole->Printf(KNoSemaphoreNotel);
00149 iConsole->Printf(KNoSemaphoreNote2);
00150 #endif
00151 }
00152
00157 static void ReadDbFuncL()
00158 {
00159 CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
00160 CleanupStack::PushL(scheduler);
00161 CActiveScheduler::Install(scheduler);
00162
00163 CDatabase* db = CDatabase::NewL();
00164 CleanupStack::PushL(db);
00165
00166
00167 db->ReadfromDatabaseL();
00168
00169 CleanupStack::PopAndDestroy(db);
00170 CleanupStack::PopAndDestroy(scheduler);
00171 }
00172
00177 TInt CSemaphoreExample::ReadThreadFuncL(TAny* )
00178 {
00179 __UHEAP_MARK;
00180
00181 CTrapCleanup* cleanup = CTrapCleanup::New();
00182 if(!cleanup)
00183 {
00184 return KErrNoMemory;
00185 }
00186
00187 TRAPD(error, ReadDbFuncL());
00188 if(error != KErrNone)
00189 {
00190 _LIT(KUserPanic,"Failed");
00191 User::Panic(KUserPanic, error);
00192 }
00193 delete cleanup;
00194 __UHEAP_MARKEND;
00195 return KErrNone;
00196 }
00197
00202 static void WriteDbFuncL()
00203 {
00204 CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
00205 CleanupStack::PushL(scheduler);
00206 CActiveScheduler::Install(scheduler);
00207
00208 CDatabase* db = CDatabase::NewL();
00209 CleanupStack::PushL(db);
00210
00211 db->CreateDatabaseL();
00212
00213
00214 db->WritetoDatabaseL();
00215
00216 CleanupStack::PopAndDestroy(db);
00217 CleanupStack::PopAndDestroy(scheduler);
00218 }
00219
00224 TInt CSemaphoreExample::WriteThreadFuncL(TAny* )
00225 {
00226 __UHEAP_MARK;
00227
00228 CTrapCleanup* cleanup = CTrapCleanup::New();
00229 if(!cleanup)
00230 {
00231 return KErrNoMemory;
00232 }
00233
00234 TRAPD(err, WriteDbFuncL());
00235 if(err != KErrNone)
00236 {
00237 _LIT(KUserPanic,"Failed");
00238 User::Panic(KUserPanic, err);
00239 }
00240 delete cleanup;
00241 __UHEAP_MARKEND;
00242 return KErrNone;
00243 }
00244
00248 static void MainL()
00249 {
00250 CSemaphoreExample* semExample = CSemaphoreExample::NewL();
00251 CleanupStack::PushL(semExample);
00252 semExample->PrintMessage();
00253 semExample->StartThreads();
00254 CleanupStack::PopAndDestroy(semExample);
00255 }
00256
00260 extern TInt E32Main()
00261 {
00262
00263 __UHEAP_MARK;
00264 CTrapCleanup* cleanup = CTrapCleanup::New();
00265 if(!cleanup)
00266 {
00267 return KErrNoMemory;
00268 }
00269
00270 TRAPD(mainError, MainL());
00271 if(mainError != KErrNone)
00272 {
00273 _LIT(KUserPanic,"Failed");
00274 User::Panic(KUserPanic, mainError);
00275 }
00276 delete cleanup;
00277 __UHEAP_MARKEND;
00278 return KErrNone;
00279 }