examples/Base/SemaphoreExample/src/SemaphoreExample.cpp

00001 /*
00002 Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
00003 
00004 Redistribution and use in source and binary forms, with or without
00005 modification, are permitted provided that the following conditions are met:
00006 
00007 * Redistributions of source code must retain the above copyright notice, this
00008 � list of conditions and the following disclaimer.
00009 * Redistributions in binary form must reproduce the above copyright notice,
00010 � this list of conditions and the following disclaimer in the documentation
00011 � and/or other materials provided with the distribution.
00012 * Neither the name of Nokia Corporation nor the names of its contributors
00013 � may be used to endorse or promote products derived from this software
00014 � without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00017 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00018 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00020 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00021 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00022 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00023 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00024 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00025 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 
00027 Description:�
00028 Contains the E32Main() function, which executes the example. The macro USE_SEMAPHORE is used at various
00029 places to show synchronization mechanism using semaphores. 
00030 */
00031 
00032 
00033  
00034 #include "SemaphoreExample.h"
00035 
00039 CSemaphoreExample::~CSemaphoreExample()
00040     {
00041     iReadThread.Close();//Reader thread closed. 
00042     iWriteThread.Close();//Writer thread closed. 
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     //Create a reader thread to read the database.
00065     _LIT(KReader,"ReaderThread");
00066     User::LeaveIfError(iReadThread.Create(KReader,ReadThreadFuncL,KDefaultStackSize,KMinHeapSize,256*KMinHeapSize,this,EOwnerProcess));   
00067 
00068     //Create a writer thread to write into the database. 
00069     _LIT(KWriter,"WriterThread");
00070     User::LeaveIfError(iWriteThread.Create(KWriter,WriteThreadFuncL,KDefaultStackSize,KMinHeapSize,256*KMinHeapSize,this,EOwnerProcess));           
00071 
00072     //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
00073     //should be using semaphores. If USE_SEMAPHORE is used, create a global semaphore. 
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     //Request a notification for iReadThread to terminate. 
00094     iReadThread.Logon(status2);
00095     iReadThread.Resume();
00096     
00097     //Request a notification for iWriteThread to terminate. 
00098     iWriteThread.Logon(status1);   
00099     iWriteThread.Resume();
00100     
00101     //Control returns to the main thread when the two threads terminate. 
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     //Start reading the database. 
00167     db->ReadfromDatabaseL();
00168     
00169     CleanupStack::PopAndDestroy(db);
00170     CleanupStack::PopAndDestroy(scheduler);
00171     }
00172 
00177 TInt CSemaphoreExample::ReadThreadFuncL(TAny* /*aPtr*/)
00178     {
00179     __UHEAP_MARK;
00180     //Create cleanup stack.
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     //Create a database.
00211     db->CreateDatabaseL();
00212     
00213     //Write into the database. 
00214     db->WritetoDatabaseL();
00215     
00216     CleanupStack::PopAndDestroy(db);
00217     CleanupStack::PopAndDestroy(scheduler);
00218     }
00219 
00224 TInt CSemaphoreExample::WriteThreadFuncL(TAny* /*aPtr*/)
00225     {
00226     __UHEAP_MARK;
00227     //Create cleanup stack.
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     //Create cleanup stack.
00263     __UHEAP_MARK;
00264     CTrapCleanup* cleanup = CTrapCleanup::New();
00265     if(!cleanup)
00266         {
00267         return KErrNoMemory;
00268         }
00269     //Run application code inside a TRAP harness.
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     }

Generated by  doxygen 1.6.2