📄 essentials.cpp
字号:
// Copyright (C) UIQ Technology AB, 2007
//
// This material is provided "as is" without any warranty to its performance or functionality.
// In no event shall UIQ Technology be liable for any damages whatsoever arising out of the
// use or inabilty to use this material.
#include <e32cons.h>
#include "essentials.h"
GLDEF_C TInt E32Main();
GLDEF_C CConsoleBase* console;
_LIT(KTextConsoleTitle, "Console");
_LIT(KTextFailed, "Failed with leave code = %d");
_LIT(KTextPressAnyKey, " [Press any key]\n");
// ****************************************************
// CleanupDeletePushL() example
// ****************************************************
MPolygon::~MPolygon()
{
_LIT(KMPolyDestruct, "MPolygon::~MPolygon\n");
console->Printf(KMPolyDestruct);
}
CSquare::CSquare()
{}
CSquare::~CSquare()
{
_LIT(KCSquareDestruct, "CSquare::~CSquare\n");
console->Printf(KCSquareDestruct);
}
/*static*/ CSquare* CSquare::NewL()
{
CSquare* me = new(ELeave) CSquare();
return (me);
}
TInt CSquare::CalculateNumberOfVerticesL()
{
return (4);
}
enum TPolygonType
{ ESquare };
LOCAL_C MPolygon* InstantiatePolygonL(TPolygonType aPolygon)
{
if (ESquare==aPolygon)
return (CSquare::NewL());
else
return (NULL);
}
void CleanupDeletePushLExampleL()
{
__UHEAP_MARK;
_LIT(KStarting, "CleanupDeletePushLExampleL()\n");
console->Printf(KStarting);
MPolygon* square = InstantiatePolygonL(ESquare);
// Try replacing the following line of code with CleanupStack::PushL()
// It will succeed, but when the CleanupStack::PopAndDestroy() call is made
// a User::42 panic occurs as described in Chapter 4
CleanupDeletePushL(square); // The correct way to push a M-class pointer to the cleanup stack
// CleanupStack::PushL(square); // The incorrect way
// ... leaving calls would go here
ASSERT(4==square->CalculateNumberOfVerticesL());
CleanupStack::PopAndDestroy(square);
_LIT(KEnding, "CleanupDeletePushLExampleL() - end\n");
console->Printf(KEnding);
__UHEAP_MARKEND;
}
// ****************************************************
// Change notification example for active objects
// ****************************************************
CNotifyChange::CNotifyChange() : CActive(EPriorityStandard)
{ CActiveScheduler::Add(this); }
void CNotifyChange::ConstructL(const TDesC& aPath)
{// Open a fileserver session
User::LeaveIfError(iFs.Connect());
iPath = aPath.AllocL();
}
CNotifyChange* CNotifyChange::NewL(const TDesC& aPath)
{
CNotifyChange* me = new(ELeave) CNotifyChange();
CleanupStack::PushL(me);
me->ConstructL(aPath);
CleanupStack::Pop(me);
return (me);
}
CNotifyChange::~CNotifyChange()
{
Cancel();
delete iPath;
iFs.Close();
}
void CNotifyChange::StartFilesystemMonitor()
{// Only allow one request to be submitted at a time
// The caller must call Cancel() before submitting another
// Panic them if they don't
if (IsActive())
{
_LIT(KAOExamplePanic, "CNotifyChange");
User::Panic(KAOExamplePanic, KErrInUse);
}
// Monitor for all changes
iFs.NotifyChange(ENotifyAll, iStatus, *iPath);
SetActive(); // Mark this object active
}
// Event handler method
void CNotifyChange::RunL()
{
// If an error occurred handle it in RunError()
User::LeaveIfError(iStatus.Int());
// Resubmit the request so as not to miss any future changes
iFs.NotifyChange(ENotifyAll, iStatus, *iPath);
SetActive();
// Process the event
_LIT(KChangeLog, "Change number: %d\n");
console->Printf(KChangeLog, ++iChanges); // Logs the fact that a change occurred
}
void CNotifyChange::DoCancel()
{// Cancel the timer
iFs.NotifyChangeCancel(iStatus);
}
TInt CNotifyChange::RunError(TInt aError)
{// Called if RunL() leaves, aError contains the leave code
_LIT(KErrorLog, "CNotifyChange::RunError %d\n");
console->Printf(KErrorLog, aError); // Logs the error
return (KErrNone); // Error has been handled
}
// This method is used to allow the active scheduler loop to run and process active objects
// that have received completion events. We need it in this test code to allow
// the active scheduler a chance to run and process outstanding completion events.
//
// You do NOT need to use this method if you are writing application code,
// because it is already event driven. It is used here purely as way to keep the
// example code simple, within a console example rather than the GUI framework.
LOCAL_C void RunIfReady(CActive::TPriority aPriorityLevel)
{
TInt completion;
TBool readyObjects;
do
{
readyObjects = CActiveScheduler::RunIfReady(completion, aPriorityLevel);
}
while (readyObjects);
}
LOCAL_C void ChangeNotificationExampleL()
{
__UHEAP_MARK;
_LIT(KStarting, "ChangeNotificationExampleL()\n");
console->Printf(KStarting);
RFs fs;
User::LeaveIfError(fs.Connect());
CleanupClosePushL(fs);
_LIT(KTestDir, "c:\\essentials\\");
User::LeaveIfError(fs.MkDir(KTestDir));
// Monitor for changes in the test directory
CNotifyChange* changeNotifier = CNotifyChange::NewL(KTestDir);
CleanupStack::PushL(changeNotifier);
changeNotifier->StartFilesystemMonitor();
RFile file;
_LIT(KTestFile, "c:\\essentials\\testfile");
// This will cause a change notification
User::LeaveIfError(file.Create(fs, KTestFile, EFileRead|EFileWrite));
file.Close();
RunIfReady(CActive::EPriorityStandard);
// This will cause a change notification
User::LeaveIfError(fs.Delete(KTestFile));
RunIfReady(CActive::EPriorityStandard);
// This will cause a change notification
fs.RmDir(KTestDir);
RunIfReady(CActive::EPriorityStandard);
CleanupStack::PopAndDestroy(2, &fs); // changeNotifier, fs
_LIT(KEnding, "ChangeNotificationExampleL() - end\n");
console->Printf(KEnding);
__UHEAP_MARKEND;
}
// ****************************************************
// Long running task example
// ****************************************************
_LIT(KLongRunningTaskExPanic, "Example Panic");
void TLongRunningCalculation::StartCalculation()
{// Flag a programming error if it's already running
__ASSERT_DEBUG(iState==EWaiting, User::Panic(KLongRunningTaskExPanic, KErrInUse));
iState=EBeginState;
}
void TLongRunningCalculation::DoTaskStep()
{// Do a short task step
switch (iState)
{
case (EWaiting):
iState = EBeginState;
console->Printf(_L("EWaiting -> EBeginState\n"));
// Task initialisation would go here
break;
case (EBeginState):
iState = EIntermediateState;
console->Printf(_L("EBeginState -> EIntermediateState\n"));
// Task code would go here
break;
case (EIntermediateState):
iState = EFinalState;
console->Printf(_L("EIntermediateState -> EFinalState\n"));
// Task termination would go here
break;
case (EFinalState):
iState = EWaiting;
console->Printf(_L("EFinalState -> EWaiting\n"));
// Task is finished
break;
default:
ASSERT(EFalse); // Panic! Should never get here
}
}
TBool TLongRunningCalculation::ContinueTask()
{
return (iState!=EWaiting);
}
CBackgroundTask* CBackgroundTask::NewLC()
{
CBackgroundTask* me = new (ELeave) CBackgroundTask();
CleanupStack::PushL(me);
return (me);
}
CBackgroundTask::CBackgroundTask() : CActive(EPriorityIdle) // Low priority task
{ CActiveScheduler::Add(this); }
// Issues a request to initiate a lengthy task
void CBackgroundTask::PerformRecalculation(TRequestStatus& aStatus)
{
iCallerStatus = &aStatus;
*iCallerStatus = KRequestPending;
__ASSERT_DEBUG(!IsActive(), User::Panic(KLongRunningTaskExPanic, KErrInUse));
iCalc.StartCalculation(); // Start the task
SelfComplete(); // Self-completion to generate an event
}
void CBackgroundTask::SelfComplete()
{// Generates an event on itself by completing on iStatus
TRequestStatus* status = &iStatus;
User::RequestComplete(status, KErrNone);
SetActive();
}
// Performs the background task in increments
void CBackgroundTask::RunL()
{// Resubmit request for next increment of the task or stop
if(iCalc.ContinueTask())
{
iCalc.DoTaskStep();
SelfComplete();
}
else
User::RequestComplete(iCallerStatus, iStatus.Int());
}
void CBackgroundTask::CancelTask()
{
Cancel();
}
void CBackgroundTask::DoCancel()
{// Give iCalc a chance to perform cleanup
iCalc.CancelCalculation();
if (iCallerStatus) // Notify the caller
User::RequestComplete(iCallerStatus, KErrCancel);
}
CExampleActive::CExampleActive(CBackgroundTask& aTask)
: CActive(EPriorityStandard),
iTask(aTask)
{
CActiveScheduler::Add(this);
}
CExampleActive* CExampleActive::NewLC(CBackgroundTask& aTask)
{
CExampleActive* me = new (ELeave) CExampleActive(aTask);
CleanupStack::PushL(me);
me->ConstructL();
return (me);
}
void CExampleActive::ConstructL()
{// Submit long running task instruction
iTask.PerformRecalculation(iStatus);
SetActive();
}
void CExampleActive::RunL()
{// Example is complete
// Nothing to do here
}
void CExampleActive::DoCancel()
{
iTask.CancelTask();
}
LOCAL_C void LongRunningTaskExampleL()
{
__UHEAP_MARK;
_LIT(KStarting, "LongRunningTaskExampleL()\n");
console->Printf(KStarting);
CBackgroundTask* backgroundTask = CBackgroundTask::NewLC();
// Construction an active object, which starts the task when it is instantiated
CExampleActive* example = CExampleActive::NewLC(*backgroundTask);
RunIfReady(CActive::EPriorityIdle);
CleanupStack::PopAndDestroy(2, backgroundTask); // example, backgroundTask
_LIT(KEnding, "LongRunningTaskExampleL() - ending\n");
console->Printf(KEnding);
__UHEAP_MARKEND;
}
// ****************************************************
// Entrypoint and main test controller function and helper code
// ****************************************************
LOCAL_C void DoStartL()
{
CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
CleanupStack::PushL(scheduler);
CActiveScheduler::Install(scheduler);
CleanupDeletePushLExampleL();
ChangeNotificationExampleL();
LongRunningTaskExampleL();
CleanupStack::PopAndDestroy(scheduler);
}
GLDEF_C TInt E32Main()
{
__UHEAP_MARK;
CTrapCleanup* cleanup = CTrapCleanup::New();
TRAPD(createError, console = Console::NewL(KTextConsoleTitle, TSize(KConsFullScreen,KConsFullScreen)));
if (createError)
return createError;
// Run application code inside TRAP harness, wait for key press then terminate
TRAPD(mainError, DoStartL());
if (mainError)
console->Printf(KTextFailed, mainError);
console->Printf(KTextPressAnyKey);
console->Getch();
delete console;
delete cleanup;
__UHEAP_MARKEND;
return KErrNone;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -