examples/PIPS/LibpThreadExample/src/libpthreadexample.cpp

00001 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
00002 // All rights reserved.
00003 // License: "Symbian Foundation License v1.0" to Symbian Foundation
00004 // members and "Symbian Foundation End User License Agreement v1.0"
00005 // to non-members at the URL
00006 // "http://www.symbianfoundation.org/legal/licencesv10.html".
00007 //
00008 // Initial Contributors:
00009 // Nokia Corporation - initial contribution.
00010 //
00011 // Contributors:
00012 //
00013 // Description:
00014 // Include Files  
00015 //
00016 
00017 #include "libpthreadexample.h"
00018 #include <e32base.h>
00019 #include <e32std.h>
00020 #include <e32cons.h>    // Console
00021 #include <pthread.h>    //Used for all the functions with prefix pthread_
00022 #include <f32file.h>
00023 #include "unistd.h"             //USed for sleep()
00024 
00025 //  Constants
00026 _LIT(KTestFile,"c:\\newfile.txt");  //Text file as the shared resource
00027 
00028 //  Global Variables
00029 LOCAL_D CConsoleBase* console; // Write all messages to this
00030 pthread_mutex_t  mutex;  //mutex 
00031 
00032 /*
00033  * This function is the routine for threadOne. It writes "one" in the text file. 
00034  * A mutex is used to avoid race condition amongst the threads  
00035  */
00036 void *TestFunction1L(void*)
00037         {
00038         // Start a file server session
00039         RFs aFs;
00040         User::LeaveIfError(aFs.Connect());
00041         
00042         RFile file;
00043         pthread_mutex_lock(&mutex);    //Lock the mutex for threadone. 
00044         TInt pos = 0;      
00045         for(int i=0; i<5; i++)                  
00046                 {
00047                         //Push the file object on the cleanup stack before doing any file operation which could leave. 
00048                         CleanupClosePushL(file); 
00049                         file.Open(aFs,KTestFile,EFileRead|EFileWrite);
00050         
00051                         _LIT8(KWriteBuf,"One, \n");
00052                         file.Seek(ESeekEnd, pos );
00053                         file.Write(pos ,KWriteBuf);
00054                         CleanupStack::PopAndDestroy(&file);
00055                         file.Close();
00056                         User::After(1000000);                   //Wait for 0.1 s to ensure a visible interthreading mechanism
00057                 }
00058                 aFs.Close();
00059                 pthread_mutex_unlock(&mutex);   //Release the mutex . 
00060                 return NULL;
00061         }
00062         
00063 /*
00064  * This function is the routine for threadTwo. It writes "two" in the text file. 
00065  * A mutex is used to avoid race condition amongst the threads  
00066  */
00067 void *TestFunction2L(void*)
00068         {
00069         // Start a file server session
00070         RFs aFs;        
00071         User::LeaveIfError(aFs.Connect());
00072         
00073         RFile file;             
00074         pthread_mutex_lock(&mutex); //Lock the mutex for threadone. 
00075         TInt pos = 0;
00076         for(int i=0; i<5; i++)
00077                 {
00078                         //Push the file object on the cleanup stack before doing any file operation which could leave. 
00079                         CleanupClosePushL(file); 
00080                         file.Open(aFs, KTestFile, EFileRead|EFileWrite);
00081                         
00082                         _LIT8(KWriteBuf, "Two, \n");
00083                         file.Seek(ESeekEnd, pos );
00084                         file.Write(pos, KWriteBuf);
00085                         CleanupStack::PopAndDestroy(&file);
00086                         file.Close();
00087                         User::After(1000000); //Wait for 0.1 s to ensure a visible interthreading mechanism
00088                 }       
00089         aFs.Close();
00090         pthread_mutex_unlock(&mutex);
00091         return NULL;
00092         }
00093         
00094 /*
00095  * This function is the routine for threadThree. It writes "three" in the text file. 
00096  * A mutex is used to avoid race condition amongst the threads  
00097  */
00098 void *TestFunction3L(void*)
00099         {
00100         // Start a file server session
00101         RFs aFs;
00102         User::LeaveIfError(aFs.Connect());
00103         
00104         RFile file;
00105         pthread_mutex_lock(&mutex);
00106         TInt pos = 0;
00107         for(int i=0; i<5;i++ )
00108                 {
00109                         //Push the file object on the cleanup stack before doing any file operation which could leave. 
00110                         CleanupClosePushL(file); 
00111                         file.Open(aFs,KTestFile,EFileRead|EFileWrite);
00112                         
00113                         _LIT8(KWriteBuf,"Three ,\n");
00114                         file.Seek(ESeekEnd , pos );
00115                         file.Write(pos ,KWriteBuf);
00116                         CleanupStack::PopAndDestroy(&file);
00117                         file.Close();
00118                         User::After(1000000); //Wait for 0.1 s to ensure a visible interthreading mechanism 
00119                 }
00120         aFs.Close();
00121         pthread_mutex_unlock(&mutex);
00122         return NULL;
00123         }
00124         
00125 /*
00126 * The following function creates three threads which starts executing as soon as it is created
00127 * it creates a text file which is used as a shared resource . The main thread will wait till 
00128 * child threads completes its execution . 
00129 */
00130 int CreateThreadL()
00131         {       
00132         //Three threads declared.
00133         pthread_t threadOne;
00134         pthread_t threadTwo;
00135         pthread_t threadThree;
00136         
00137         _LIT(KMain ,"in main\n" ); 
00138         console->Write(KMain);
00139         //Start a file server session 
00140         RFs aFs;        
00141         User::LeaveIfError(aFs.Connect());
00142         
00143         //Create a text file which can be used as a shared resource. 
00144         RFile file;
00145         CleanupClosePushL(file); 
00146         file.Create(aFs ,KTestFile,EFileRead|EFileWrite);
00147         CleanupStack::PopAndDestroy(&file);
00148         file.Close(); 
00149         aFs.Close();
00150         //Create and initialize mutex for synchronization       
00151         if((pthread_mutex_init(&mutex,NULL)) != 0)
00152                 {
00153                         return -1;
00154                 }         
00155         
00156         //Create threadOne.. thread is in running state. 
00157         TInt err1 = pthread_create(&threadOne,NULL,TestFunction1L, NULL);
00158         User::LeaveIfError(err1);
00159         _LIT(KThreadOneCreated , "ThreadOne created\n");
00160         console->Write(KThreadOneCreated);
00161         
00162         //Create threadTwo.. thread is in running state.
00163         TInt err2 = pthread_create(&threadTwo,NULL,TestFunction2L, NULL);
00164         User::LeaveIfError(err2);
00165         _LIT(KThreadTwoCreated , "ThreadTwo created\n");
00166         console->Write(KThreadTwoCreated);
00167         
00168         //Create threadThree.. thread is in running state.
00169         TInt err3 = pthread_create(&threadThree,NULL,TestFunction3L, NULL);
00170         User::LeaveIfError(err3);
00171         _LIT(KThreadThreeCreated , "ThreadThree created\n");
00172         console->Write(KThreadThreeCreated);
00173         
00174         
00175         //------Main thread waits for other threads to complete ---- 
00176         _LIT(KWait , "Waiting for child threads to complete execution\n");
00177         console->Write(KWait);
00178         
00179         _LIT(KJoinError , "Error in pthread_join()");
00180         //Main thread waits for threadOne to complete execution
00181         if(pthread_join(threadOne, NULL) != 0)
00182                 {
00183                         console->Write(KJoinError);      
00184                 }
00185         else
00186                 {
00187                         _LIT(KRetThreadOne ,"Returned from threadone\n"); 
00188                         console->Write(KRetThreadOne); //Control comes to main thread once threadOne completes execution.
00189                 }
00190 
00191         //Main thread waits for threadTwo to complete execution
00192         if(pthread_join(threadTwo, NULL) != 0)
00193                 {
00194                         console->Write(KJoinError);
00195                 }
00196         else
00197                 {
00198                         _LIT(KRetThreadTwo ,"Returned from threadtwo\n"); 
00199                         console->Write(KRetThreadTwo); //Control comes to main thread once threadTwo completes execution.
00200                 }
00201                 
00202         //Main thread waits for threadThree to complete execution
00203         if(pthread_join(threadThree, NULL) != 0)
00204                 {
00205                         console->Write(KJoinError);      
00206                 }
00207         else 
00208                 {
00209                         _LIT(KRetThreadThree ,"Returned from threadthree\n"); 
00210                         console->Write(KRetThreadThree); //Control comes to main thread once threadTwo completes execution.
00211                 }
00212         //Clean up
00213         pthread_mutex_destroy(&mutex);
00214         return -1; 
00215         }
00216         
00217         //  Local Functions
00218 
00219 LOCAL_C void MainL()
00220         {
00221         _LIT(KHello , "Welcome to the LibpThread example, we will create three threads and use them to print data to \\epoc32\\winscw\\c\\newfile.txt\n\n");
00222         console->Write(KHello);
00223         CreateThreadL();
00224         }
00225 
00226 LOCAL_C void DoStartL()
00227         {
00228         MainL();
00229         }
00230 
00231         //  Global Functions
00232 
00233 GLDEF_C TInt E32Main()
00234         {
00235         // Create cleanup stack
00236         __UHEAP_MARK;
00237         CTrapCleanup* cleanup = CTrapCleanup::New();
00238                 // Create output console
00239         _LIT(KTextConsoleTitle, "Console");
00240         TRAPD(createError, console = Console::NewL(KTextConsoleTitle, TSize(KConsFullScreen,KConsFullScreen)));
00241         if (createError)
00242         return createError;
00243                 // Run application code inside TRAP harness, wait keypress when terminated
00244         TRAPD(mainError, DoStartL());
00245         _LIT(KTextFailed, " failed, leave code = %d");
00246         if (mainError)
00247         console->Printf(KTextFailed, mainError);
00248         _LIT(KTextPressAnyKey, " [press any key]\n");
00249         console->Printf(KTextPressAnyKey);
00250         console->Getch();
00251         delete console;
00252         delete cleanup;
00253         __UHEAP_MARKEND;
00254         return KErrNone;
00255         }
00256         

Generated by  doxygen 1.6.2