examples/Base/IPC/condvar/condvarglobal/src/adder.cpp

Go to the documentation of this file.
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 // Implements the write operation on a shared memory block.
00015 //
00016 
00017 
00018 
00022 #include "sharedmem.h"
00023 #include "adder.h"
00024 
00030 CAdder* CAdder::NewL(CConsoleBase* aConsole)
00031         {
00032         CAdder* self = new (ELeave) CAdder;
00033         CleanupStack::PushL(self);
00034         self->ConstructL(aConsole);
00035         CleanupStack::Pop(self);
00036         return self;
00037         }
00038 
00043 void CAdder::RunL()
00044         {
00045         // Get the key code.
00046         TUint8 option = iConsole->KeyCode();
00047         // Print the selected option.
00048         _LIT(KTextFormat,"%c\n");
00049         iConsole->Printf(KTextFormat,option);
00050         // Stop the timer and the active scheduler.
00051         StopTimer();
00052         CActiveScheduler::Stop();
00053         }
00054 
00058 void CAdder::DoCancel()
00059         {
00060         if(IsActive())
00061                 {
00062                 // Cancel any outstanding read requests.
00063                 iConsole->ReadCancel();
00064                 }
00065         }
00066 
00070 CAdder::~CAdder()
00071         {
00072         // Cancel all outstanding requests.
00073         DoCancel();
00074 
00075         // Delete the timer object.
00076         iPeriodic->Cancel();
00077         delete iPeriodic;
00078 
00079         // Close all resource handles.
00080         iChunk.Close();
00081         iMutex.Close();
00082         iCondVar.Close();
00083         }
00084 
00088 CAdder::CAdder():CActive(EPriorityUserInput)
00089         {
00090         }
00091 
00101 void CAdder::ConstructL(CConsoleBase* aConsole)
00102         {
00103         // Create the global condition variable.
00104         User::LeaveIfError(iCondVar.CreateGlobal(KCondVarName));
00105         // Create the global chunk.
00106         User::LeaveIfError(iChunk.CreateGlobal(KChunkName,KChunkSize,KChunkSize));
00107         // Create the global mutex variable.
00108         User::LeaveIfError(iMutex.CreateGlobal(KMutexName));
00109 
00110         // Create the CPeriodic object.
00111         iPeriodic = CPeriodic::NewL(CActive::EPriorityUserInput);
00112         iConsole = aConsole;
00113 
00114         // Get the address of the chunk.
00115         TUint8 *ptr = iChunk.Base();
00116         // Initialise the value of the chunk to 0.
00117         *ptr = 0;
00118 
00119         // Add the object to the active scheduler.
00120         CActiveScheduler::Add(this);
00121         }
00122 
00126 void CAdder::ReadFunction()
00127         {
00128         _LIT(KTextMessage,"Press a key to exit...\n");
00129         iConsole->Printf(KTextMessage);
00130         // Wait for a key press event.
00131         iConsole->Read(iStatus);
00132         SetActive();
00133         }
00134 
00139 void CAdder::StartTimer()
00140         {
00141         // Start generating periodic events.
00142         iPeriodic->Start(0,3000000,TCallBack(AddFunction,this));
00143         }
00144 
00148 void CAdder::StopTimer()
00149         {
00150         // Cancel the  outstanding request.
00151         iPeriodic->Cancel();
00152         }
00153 
00159 TInt CAdder::AddFunction(TAny* aPtr)
00160         {
00161         CAdder* ptr = static_cast<CAdder*> (aPtr);
00162         _LIT(KTxtPanic,"Pointer is NULL");
00163         __ASSERT_ALWAYS(ptr,User::Panic(KTxtPanic,-1));
00164         // Invoke the Add() function.
00165         ptr->Add();
00166         return KErrNone;
00167         }
00168 
00172 void CAdder::Add()
00173         {
00174         // Acquire the mutex.
00175         iMutex.Wait();
00176 
00177         // Get a random number.
00178         TInt randVal = Math::Random() % 10;
00179 
00180         // Get the address of the chunk.
00181         TUint8 *ptr = iChunk.Base();
00182 
00183         // Print the value of the chunk before addition.
00184         iConsole->Printf(_L("Value read from the shared memory: %d\n"),*ptr);
00185 
00186         // Add the random value to the shared memory variable.
00187         *ptr += randVal;
00188 
00189         while(*ptr > KUpperThreshold)
00190                 {
00191                 // Wait on the condition variable if the result is greater than 100.
00192                 _LIT(KBlockMessage,"Adder blocked by condVar until Subtractor signals that value has been decreased.\nIntermediate value of the chunk = %d\n");
00193                 iConsole->Printf(KBlockMessage,*ptr);
00194                 iCondVar.Wait(iMutex);
00195                 }
00196         // Print the updated value of the chunk.
00197         iConsole->Printf(_L("Value of the shared memory increased to : %d\n"),*ptr);
00198 
00199         // Signal the mutex and the condition variable.
00200         if(*ptr > KLowerThreshold)
00201                 {
00202                 // Signal that the level is safe for subtraction to (re)start.
00203                 iCondVar.Signal();
00204                 }
00205         iMutex.Signal();
00206         }
00207 
00208 LOCAL_D CConsoleBase* console;
00209 LOCAL_C void DoExampleL();
00210 LOCAL_C void callExampleL();
00211 
00212 LOCAL_C void DoExampleL()
00213         {
00214         // Create and install the active scheduler.
00215         CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
00216         CleanupStack::PushL(scheduler);
00217         CActiveScheduler::Install(scheduler);
00218 
00219         // Create the CAdder object.
00220         CAdder* adder = CAdder::NewL(console);
00221         CleanupStack::PushL(adder);
00222 
00223         // Start the timer of the CAdder object.
00224         adder->StartTimer();
00225         // Issue an asynchronous read request.
00226         adder->ReadFunction();
00227         // Start the active scheduler.
00228         CActiveScheduler::Start();
00229 
00230         CleanupStack::PopAndDestroy(2,scheduler);
00231         }
00232 
00233 GLDEF_C TInt E32Main() // main function called by E32
00234     {
00235         __UHEAP_MARK;
00236         CTrapCleanup* cleanup=CTrapCleanup::New(); // get clean-up stack
00237         TRAPD(error,callExampleL()); // more initializations, then do example
00238         delete cleanup; // destroy clean-up stack
00239         __ASSERT_ALWAYS(!error,User::Panic(KTxtEPOC32EX,error));
00240         __UHEAP_MARKEND;
00241         return 0; // and return
00242     }
00243 
00244 LOCAL_C void callExampleL() // initialise and call example code under cleanup stack
00245     {
00246         console=Console::NewL(KTxtExampleCode,TSize(KConsFullScreen,KConsFullScreen));
00247         CleanupStack::PushL(console);
00248         TRAPD(error,DoExampleL()); // perform example function
00249         if (error)
00250                 console->Printf(KFormatFailed, error);
00251         else
00252                 console->Printf(KTxtOK);
00253         console->Printf(KTxtPressAnyKey);
00254         console->Getch(); // get and ignore character
00255         CleanupStack::PopAndDestroy(); // close console
00256     }

Generated by  doxygen 1.6.2