examples/Base/SemaphoreExample/src/SemaphoreExample.cpp

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     }

Generated by  doxygen 1.6.2