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

Generated by  doxygen 1.6.2