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

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

Generated by  doxygen 1.6.2