examples/Base/IPC/Async/AcceptInput1/AcceptInput1.cpp

00001 /*
00002 Copyright (c) 2000-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 Asynchronous keyboard processing with messenger program.
00029 A single CKeyMessengerProcessor active object (derived from
00030 class CActiveConsole) which accepts input from keyboard, but does not
00031 print it.
00032 This object contains a CMessageTimer object which it activates if the
00033 user inputs the character "m" and cancelled if the user inputs "c".
00034 */
00035 
00036 
00037 #include "CommonFramework.h"
00038 
00039 //
00040 // Common literal text
00041 //
00042 _LIT(KTextEsc,"\n");
00043 
00044 // panics
00045 enum
00046         {
00047         EPanicAlreadyActive=1000,
00048         };
00049 
00050 
00052 //
00053 // -----> CTimedMessenger (definition)
00054 //
00056 class CTimedMessenger : public CTimer
00057         {
00058 public:
00059           // Construction
00060         CTimedMessenger();
00061       // Destruction
00062         ~CTimedMessenger();
00063 
00064 public:
00065           // Static construction
00066         static CTimedMessenger* NewLC(const TDesC& aGreeting,
00067                                           TInt aTicksRequested,
00068                                                                   TInt aTicksInterval
00069                                                                  );
00070         static CTimedMessenger* NewL(const TDesC& aGreeting,
00071                                          TInt aTicksRequested,
00072                                                                  TInt aTicksInterval
00073                                                                 );
00074 
00075 public:
00076           // Second phase construction
00077         void ConstructL(const TDesC& aGreeting,
00078                             TInt aTicksRequested,
00079                                         TInt aTicksInterval
00080                                    );
00081 
00082           // issue request
00083         void IssueRequest(); 
00084 
00085           // Cancel request
00086           // Defined as pure virtual by CActive;
00087           // implementation provided by this class.
00088         void DoCancel();
00089 
00090           // service completed request.
00091           // Defined as pure virtual by CActive;
00092           // implementation provided by this class.
00093         void RunL();
00094 
00095 public:
00096           // data members defined by this class
00097         TBufC<20> iGreeting;   // Text of the greeting.
00098         TInt iTicksRequested;  // Total number of greetings CTimedMessenger
00099                                // will emit.
00100         TInt iTicksInterval;   // Number of seconds between each greeting.
00101         TInt iTicksDone;       // Number of greetings issued so far.
00102         };
00103 
00104 
00106 //
00107 // -----> CExampleScheduler (definition)
00108 //
00110 class CExampleScheduler : public CActiveScheduler
00111         {
00112 public:
00113         void Error (TInt aError) const;
00114         };
00115 
00116 
00118 //
00119 // -----> CActiveConsole (definition)
00120 //
00121 // An abstract class which provides the facility to issue key requests. 
00122 //
00124 class CActiveConsole : public CActive
00125         {
00126 public:
00127           // Construction
00128         CActiveConsole(CConsoleBase* aConsole);
00129         void ConstructL();
00130 
00131           // Destruction
00132         ~CActiveConsole();
00133 
00134           // Issue request
00135         void RequestCharacter();
00136         
00137           // Cancel request.
00138           // Defined as pure virtual by CActive;
00139           // implementation provided by this class.
00140         void DoCancel();
00141 
00142           // Service completed request.
00143           // Defined as pure virtual by CActive;
00144           // implementation provided by this class,
00145         void RunL();
00146 
00147           // Called from RunL() - an implementation must be provided
00148           // by derived classes to handle the completed request
00149         virtual void ProcessKeyPress(TChar aChar) = 0; 
00150           
00151 protected:
00152           // Data members defined by this class
00153         CConsoleBase* iConsole; // A console for reading from
00154         };
00155 
00156 
00158 //
00159 // -----> CWriteKeyProcessor (definition)
00160 //
00161 // This class is derived from CActiveConsole. 
00162 // Request handling: accepts input from the keyboard and outputs it 
00163 // to the console.
00164 //
00166 class CWriteKeyProcessor : public CActiveConsole
00167         {
00168 public:
00169           // Construction
00170         CWriteKeyProcessor(CConsoleBase* aConsole);
00171 
00172 public:
00173           // Static constuction
00174         static CWriteKeyProcessor *NewLC (CConsoleBase* aConsole);
00175         static CWriteKeyProcessor *NewL(CConsoleBase* aConsole);
00176 
00177           // Service request
00178         void ProcessKeyPress(TChar aChar);
00179         };
00180 
00181 
00183 //
00184 // -----> CTimedMessenger (implementation)
00185 //
00187 CTimedMessenger::CTimedMessenger()
00188         : CTimer(CActive::EPriorityStandard)
00189           // Construct  zero-priority active object
00190         {};
00191 
00192 CTimedMessenger* CTimedMessenger::NewLC(const TDesC& aGreeting,
00193                                                                                 TInt aTicksRequested,
00194                                                                                 TInt aTicksInterval
00195                                                                            )
00196         {
00197         CTimedMessenger* self=new (ELeave) CTimedMessenger;
00198         CleanupStack::PushL(self);
00199         self->ConstructL(aGreeting,aTicksRequested,aTicksInterval);
00200         return self;
00201         }
00202 
00203 CTimedMessenger* CTimedMessenger::NewL(const TDesC& aGreeting,
00204                                                                    TInt aTicksRequested,
00205                                                                            TInt aTicksInterval
00206                                                                           )
00207         {
00208         CTimedMessenger* self = NewLC(aGreeting,aTicksRequested,aTicksInterval);
00209         CleanupStack::Pop();
00210         return self;
00211         }
00212 
00213 void CTimedMessenger::ConstructL(const TDesC& aGreeting,
00214                                                                  TInt aTicksRequested,
00215                                                                  TInt aTicksInterval
00216                                                                 )
00217         {
00218           // Base class second-phase construction.
00219         CTimer::ConstructL();
00220           // Set members from arguments
00221         iGreeting       = aGreeting;       // Set greeting text.
00222         iTicksRequested = aTicksRequested; // Ticks requested
00223         iTicksInterval  = aTicksInterval;  // Interval between ticks
00224           // Add active object to active scheduler
00225         CActiveScheduler::Add(this); 
00226         }
00227 
00228 
00229 CTimedMessenger::~CTimedMessenger()
00230         {
00231           // Make sure we're cancelled
00232         Cancel();
00233         }
00234 
00235 void CTimedMessenger::DoCancel()
00236         {
00237           // Base class
00238         CTimer::DoCancel(); 
00239           // Reset this variable - needed if the object is re-activated later
00240         iTicksDone = 0;
00241           // Tell user
00242         _LIT(KMsgCancelled,"Outstanding Messenger request cancelled\n");
00243         console->Printf(KMsgCancelled); 
00244         }
00245 
00246 void CTimedMessenger::IssueRequest()
00247         {
00248           // There should never be an outstanding request at this point.
00249         _LIT(KMsgAlreadyActive,"Is already Active");
00250         __ASSERT_ALWAYS(!IsActive(),User::Panic(KMsgAlreadyActive,EPanicAlreadyActive));
00251           // Request another wait
00252         CTimer::After( iTicksInterval*1000000);
00253         }
00254 
00255 void CTimedMessenger::RunL()
00256         {
00257           // Handle request completion
00258           // One more tick done
00259         iTicksDone++;
00260           // Print greeting
00261         _LIT(KFormatString1,"%S \n");
00262         console->Printf(KFormatString1,&iGreeting);
00263           // Issue new request, or stop if we have reached the limit
00264         if (iTicksDone  < iTicksRequested)
00265                 {
00266                 IssueRequest();
00267                 }
00268         else
00269                 {
00270                 _LIT(KMsgFinished,"Messenger finished \n");
00271                 console->Printf(KMsgFinished);
00272                   // Reset this variable - needed if the object is re-activated later
00273                 iTicksDone=0;
00274                   // Can now stop the active scheduler
00275                 CActiveScheduler::Stop();
00276                 }
00277         }
00278 
00279 
00281 //
00282 // -----> CExampleScheduler (implementation)
00283 //
00285 void CExampleScheduler::Error(TInt aError) const
00286         {
00287         _LIT(KMsgSchedErr,"CExampleScheduler-error");
00288         User::Panic(KMsgSchedErr,aError);
00289         }
00290 
00291 
00293 //
00294 // -----> CActiveConsole (implementation)
00295 //
00297 CActiveConsole::CActiveConsole( CConsoleBase* aConsole) 
00298         : CActive(CActive::EPriorityUserInput)
00299           // Construct high-priority active object
00300         {
00301         iConsole = aConsole;
00302         }
00303 
00304 void CActiveConsole::ConstructL()
00305         {
00306           // Add to active scheduler
00307         CActiveScheduler::Add(this);
00308         }
00309 
00310 CActiveConsole::~CActiveConsole()
00311         {
00312         // Make sure we're cancelled
00313         Cancel();
00314         }
00315 
00316 void  CActiveConsole::DoCancel()
00317         {
00318         iConsole->ReadCancel();
00319         }
00320 
00321 void  CActiveConsole::RunL()
00322         {
00323           // Handle completed request
00324         ProcessKeyPress(TChar(iConsole->KeyCode()));
00325         }
00326 
00327 void CActiveConsole::RequestCharacter()
00328         {
00329           // A request is issued to the CConsoleBase to accept a
00330           // character from the keyboard.
00331         iConsole->Read(iStatus); 
00332         SetActive();
00333         }
00334 
00335 
00337 //
00338 // -----> CWriteKeyProcessor (implementation)
00339 //
00341 CWriteKeyProcessor::CWriteKeyProcessor(CConsoleBase* aConsole)
00342         : CActiveConsole(aConsole)
00343           
00344         {};
00345 
00346 CWriteKeyProcessor* CWriteKeyProcessor::NewLC(CConsoleBase* aConsole)
00347         {
00348         CWriteKeyProcessor* self=new (ELeave) CWriteKeyProcessor(aConsole);
00349         CleanupStack::PushL(self);
00350         self->ConstructL();
00351         return self;
00352         }
00353 
00354 CWriteKeyProcessor* CWriteKeyProcessor::NewL(CConsoleBase* aConsole)
00355         {
00356         CWriteKeyProcessor* self=NewLC(aConsole);
00357         CleanupStack::Pop();
00358         return self;
00359         }
00360 
00361 void CWriteKeyProcessor::ProcessKeyPress(TChar aChar)
00362         {
00363           // "Esc" character prints a new line and stops the scheduler
00364         if (aChar == EKeyEscape)
00365                 {
00366                 iConsole->Printf(KTextEsc);
00367                 CActiveScheduler::Stop();
00368                 return;
00369                 }
00370 
00371           // "Enter" prints a new line character
00372           // An alphabetic or space is printed as a character;
00373           // anything else is printed as an integer.
00374         if (aChar == EKeyEnter)
00375                 iConsole->Printf(KTextEsc);
00376         else
00377                 {
00378                 _LIT(KFormatString2,"%c");
00379                 _LIT(KFormatString3,"%d");
00380                 if (aChar.IsAlphaDigit()|| aChar.IsSpace())
00381                         iConsole->Printf(KFormatString2,TUint(aChar));
00382                 else
00383                         iConsole->Printf(KFormatString3,TUint(aChar));
00384                 }
00385 
00386           // Issue another request 
00387         RequestCharacter();
00388         }
00389 
00390 
00392 //
00393 // -----> CMessageKeyProcessor (definition)
00394 //
00395 // This class is derived from CActiveConsole. 
00396 // Request handling:
00397 //   if key is "m", a message timer request is issued.
00398 //   if key is "c", any outstanding message timer request is cancelled.
00399 //   If key is ESC, the wait loop is terminated.
00400 //
00402 class CMessageKeyProcessor : public CActiveConsole
00403         {
00404 public:
00405           // Construction
00406         CMessageKeyProcessor(CConsoleBase* aConsole, CTimedMessenger* iMessenger);
00407         void ConstructL();
00408 
00409 public:
00410           // Static construction
00411         static CMessageKeyProcessor* NewLC(CConsoleBase* aConsole,
00412                                                CTimedMessenger* iMessenger
00413                                                                           );
00414         static CMessageKeyProcessor* NewL(CConsoleBase* aConsole,
00415                                               CTimedMessenger* iMessenger
00416                                                                          );
00417 
00418 public:
00419           // service request
00420         void ProcessKeyPress(TChar aChar);
00421 
00422 private:
00423           // Data members defined by this class
00424         CTimedMessenger* iMessenger;
00425         };
00426 
00428 //
00429 // -----> CMessageKeyProcessor (implementation)
00430 //
00432 CMessageKeyProcessor::CMessageKeyProcessor(CConsoleBase* aConsole,
00433                                                                                    CTimedMessenger* aMessenger
00434                                                                                   )
00435         : CActiveConsole(aConsole)
00436           // construct zero-priority active object
00437         {
00438         iMessenger = aMessenger;
00439         } 
00440 
00441 CMessageKeyProcessor* CMessageKeyProcessor::NewLC(CConsoleBase* aConsole,
00442                                                                                                   CTimedMessenger* aMessenger
00443                                                                                                  )
00444         {
00445         CMessageKeyProcessor* self=new (ELeave) CMessageKeyProcessor(aConsole,
00446                                                                          aMessenger
00447                                                                                                                                 );
00448         CleanupStack::PushL(self);
00449         self->ConstructL();
00450         return self;
00451         }
00452 
00453 CMessageKeyProcessor* CMessageKeyProcessor::NewL(CConsoleBase* aConsole,
00454                                                                                                  CTimedMessenger* aMessenger
00455                                                                                                 )
00456         {
00457         CMessageKeyProcessor* self = NewLC(aConsole, aMessenger);
00458         CleanupStack::Pop();
00459         return self;
00460         }
00461 
00462 void CMessageKeyProcessor::ConstructL()
00463         {
00464           // Add to active scheduler
00465         CActiveScheduler::Add(this);
00466         }
00467 
00468 void CMessageKeyProcessor::ProcessKeyPress(TChar aChar)
00469         {
00470           // if key is ESC 
00471           //   cancel any outstanding request
00472           //   stop the scheduler
00473         if (aChar == EKeyEscape)
00474                 {
00475                 iMessenger->Cancel();
00476                 CActiveScheduler::Stop();
00477                 return;
00478                 }
00479 
00480           // If key is "m" or "M"
00481           //   cancel any outstanding request
00482           //   reset the tick counter
00483           //   issue a message timer request.
00484         if (aChar == 'm' || aChar == 'M') 
00485                 {
00486                 _LIT(KMsgStarting,"Starting Messenger....  \n");
00487                 iConsole->Printf(KMsgStarting);
00488                 iMessenger->Cancel();
00489                 iMessenger ->IssueRequest();
00490                 }
00491 
00492       // If key is "c" or "C" 
00493           //    cancel any outstanding request  
00494         if (aChar == 'c' || aChar == 'C')
00495                 iMessenger->Cancel();
00496         
00497           // Ask for another character.
00498         RequestCharacter();
00499         }
00500 
00501 
00503 //
00504 // Do the example
00505 //
00507 LOCAL_C void doExampleL()
00508     {
00509           // Construct and install the active scheduler
00510         CExampleScheduler*  exampleScheduler = new (ELeave) CExampleScheduler;
00511 
00512           // Push onto the cleanup stack
00513         CleanupStack::PushL(exampleScheduler);
00514          
00515           // Install as the active scheduler
00516         CActiveScheduler::Install(exampleScheduler);
00517 
00518           // Create a CTimedMessenger active object which will emit
00519           // 3 messages with an interval of 2 seconds between messages.
00520         _LIT(KMsgGoodMorning,"Good Morning!");
00521         CTimedMessenger* messenger = CTimedMessenger::NewLC(KMsgGoodMorning, 3, 2);
00522 
00523           // Create aCMessageKeyProcessor active object.
00524         _LIT(KMsgTitleA,"A single CKeyMessengerProcessor active object which contains a CMessageTimer.\n");
00525         console->Printf(KMsgTitleA);
00526         _LIT(KMsgTitleB,"Press 'm' to activate messenger; Press 'c' to cancel it.\nPress ESC to end.\n\n");
00527         console->Printf(KMsgTitleB);
00528         CMessageKeyProcessor* keyProcesser = CMessageKeyProcessor::NewLC(console,
00529                                                                              messenger
00530                                                                                                                                          );
00531           
00532           // Issue the first request
00533         keyProcesser->RequestCharacter();
00534         
00535           // Main part of the program is a wait loop
00536         CActiveScheduler::Start();
00537 
00538         // Remove from the cleanup stack and destroy:
00539         // 1. the CTimedMessenger active object
00540         // 2. the CMessageKeyProcessor active object.
00541         // 3. exampleScheduler
00542         CleanupStack::PopAndDestroy(3); 
00543         }
00544 

Generated by  doxygen 1.6.2