Symbian os basic
* BASIC OPERATION
* PROGRAM MODULE
* CLASS
symbian os is object oriented and use c++ , only in the deepest layer , use asm
? symbian support mutiple inherite?
? c++ have no idea of DLL , and NOT strict demand the type's bytes
? symbian focus on the system design and ( error process and clear ) , arrange using the ROM and RAM TO slove it
OBJECT CRAETE AND DESTORY
%heap
? every thread has a 关联堆 (默认堆)
almost object initial in heap is inherite the CBase class
CBase
零初始化
虚析构函数
one style:
CMyClass* myPtr = new CMyClass;
if (myPtr)
{
myPtr->Fpp();
}
delete myPtr;
now the style is :
CMyClass* myPtr=new(ELeave)CMyClass;
myPtr->Foo();
delete myPtr;
this means if the new operation fails , program operate an "EXIT" , NOT just return the NULL.
? How TO manage the EXIT?
double assign ... will cause memory leak
double delete ... hard TO debug ...and crash in a while
if you use "delete" aboard the dtor you must set the pointer NULL
%stack
fit for the fixed size object .
creater function's life is the same with the object's life
a ecellente exp is : if any string is longer than the MAX length of the file name , put them in the heap .
use .mmp file which create .exe file TO control .exe file's stack , with the key word epocstacksize
this method is applicable TO the control panel's program , not fit to GUI program
GUI program has only a small stack (20k) .
you should avoid creating a large stack , it will waste of the resourse
the objects we can put in the stack :
build in type
emun
class do NOT need dtor
TBuf<40> or TPtrC (only use pt NOT inclue , no need dtor)
_ERROR PROCESS AND CLEAR
symbian offer a framework TO deal WITH the error . and it will affect every line of your coding .
your program have TO face :
* your coding have TO be more efficien . don't waste your RAM
* you have TO release the Memory in time .
* you have TO deal WITH the ocassion of NOT enough memory
* when in that occasion ,you have TO protect the data FROM being lost
* if there are several operation in that occation ,you have TO ensure all these operation have released the resourse
we can use the framework TO deal WITH the input check
there is one error can NOT be dealed WITH , which is called panic , actually means program error .
&panic
User::Panic(KPanicCategory,aPanic)
one situation : check the pass arguments
another situation : check the program status
common style : use assert macro
__ASSERT_DEBUG
__ASSERT_ALWAYS
ex: __ASSERT_ALWAYS(aIndex>0,Panic(EMyAppIndexNagative));
&exception and trap harness
异常退出(Leave)
use trap harness's User::Leave() the activate the Leave Mechanism
compare WITH c++
TRAP() ---- try ... catch
User::Leave() ---- throw
funL() ---- fun() throw (...)
trap harness process
come across a Leave (causing BY User::Leave())
find a fun above include the TRAP() OR TRAPD() macro
POINT is :
TRAP() call a fun , according TO it's second arg
and return an 32 bit error code , according TO it's first arg
if no error occur , the error code would be KErrNone (0)
ex :
TRAPD(error,HandelKeyL());
if(error)
{
RevertUndoBuffer();
User::Leave(error);
}
a question :
when a Leave happen , the auto ptr ,which is holding a heap object , will lost the control on this object .
then a memory leak turns out .
&clearupstack
*when TO use CleanUpStack
control panel program have TO provide this stack
gui app has been provided BY GUI frame
error happens :
CX::UseL()
{
CY* y = new(ELeave) CY; //--> if Leave , x will not be released , memory leak !!!!
delete y;
}
CX* x = new(ELeave) CX; //--> if Leave , nothing wrong
x->UseL();
solution : (use CleanupStack)
CX* x = new(ELeave) CX;
CleanupStack::PushL(x);
x->UseL(); //--> if Leave , x will be released as a part of Leave
x->UseL();
x->UseL();
CleanupStack::PopAndDestroy();
c++ exception handle will call the object's dtor ,so it doesn't need the cleanupstack
more:
CX* x1 = new(ELeave) CX;
CleanupStack::PushL(x1);
CX* x2 = new(ELeave) CX;
CleanupStack::PushL(x2);
x1->UseL();
CleanupStack::PopAndDestroy(2); //2 means above 2 , can't larger than 2 , or will cause the panic
DO NOT OVER USE IT
IF A OBJECT IS A MEMBER VARIBLE DO NOT USE IT
we use CleanupStack only when the object will avoid executing it's dtor.
like the err above , when Leave happen , no object's dtor will be execute and no object will be clean in the stack
CleanupStatck is define in e32base.h
Once The pointer is copied TO one member of an object , it don't need to stay in cleanupstack any more ,cause
the object's dtor will delete the pointer .
*the chance when CleanUpStack Leave
Seldom
Usually , less 10 object in cleanupstack
And the design of CleanupStack is :
assgin several slots , one backup slot
give one slot TO an object, meanwhile check if the backup slot is ready
if ready , push success
if fail , cause Leave
so no chance happen the inaffecion slot(memory??)
*CBase and CleanUpStack
#auto varibel use CleanupStack
#member varible use dtor
#CBase's derives should not assign in stack , (it is only designed for heap)
零初始化 make no sense.
if they use in stack , what happens is unknew.
almose CBase's derives has it's private ctor (NewL() ,NewLC());
*Two Phases Construct
error :
CY::CY()
{iX = new(ELeave) CX;} // if Leave , y is not release
CY* y= new(ELeave)CY; //if Leave , OK!
CleanupStack::PushL(y);
y->iX->UseL(); //--> if Leave , OK!
CleanupStack::PopAndDestroy();
CAN'T PUSH OBJECT IN CLEANUPSTACK BETWEEN NEW() AND CTOR()
so DO NOT INLUDE FUNL() IN CTOR
common style :
class CZ : public CBase
{
public:
static CZ* NewL();
static CZ* NewLC();
void ConstructL(); //--> funL() write here
~CZ();
public:
CX *iX;
}
void CZ::ConstructL()
{
ix=new(ELeave) CX;
}
*Packeted the ConstructL() in NewL() and NewLC()
common style :
CZ* CZ::NewLC()
{
CZ* self = new(ELeave) CZ;
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
CZ* CZ::NewL()
{
CZ* self=CZ::NewLC();
CleanupsStack::PopAndDestroy();
return self;
}
after you use NewL() , you muse get in charge of the object ,cause is NOT in cleanupstack !!
this two fun work like factory function,a kind of static ctor
* other style of clean up
(do NOT understand )
NAME
%class
T --TdesC,TPoint-- like build in object , has NOT dtor , it can be assigned in stack or heap
C --CActive,CBase-- CBase's derive , can only be assigned in heap , use delete to release
R --RFile,RTimer-- Resource NOT in heap , usually AS member varible or auto varible , use Close() TO release
M --MGraphicsDeviceMap-- interface consis of virtual functions , Symbian only recommand the M class use mutiple inherite
static --User,Math-- can NOT be instantiation , work AS a library
structure --SEikControlInfo-- C style structure , but seldom use , use T class instead
%Data
E ---- Enumeration
K ---- Constant
i ---- member variable
a ---- pass argument
---- auto variable
%Function
NOT Leave ---- v.
Leave ---- L()
LC ---- lefe an item in cleanupstack
simple getter ---- n.
complex getter ---- Getxxx()
setter ---- Setxxx() or SetxxxL()
%Macro
XXXX_XX or __XXX or __XXXX__
DESCRIPTOR
%buffer descriptor
data is a part of descriptor , the whole descriptor can be pack INTO stack
TBuf , TBufC ---- char[]
ex:
__LIT(KTxtHelloWorld,"Hello World!");
TBuf<16> buffer(KTxtHelloWorld);
//remark TBuf<16> can contain 16 bytes data ,but do not mean it hold 16 bytes data .
// "Hello World!" length is 12 , and buffer doesn't need end of NULL
%pointer descriptor
data is apart FROM descriptor , descriptor can be in stack ,and the data can be in anywhere that is able TO address
it's useful when work as pass argument , 'cause it needn't copy the whole data . h
TPtr , TPtrC ---- const char*
templatelize , if the data is larger than assigned , it will return error // how it did it ?
two sytle TO create TPtrC
one :
void foo(TUnit16* aBuf , TInt aLenth) // whar TUnit16 means ????
{
TPtrC myPtr(aBuf,aLenth);
}
two :
__LIT(KTxtHelloWorld,"Hello World!");
TBuf<16> buffer(KTxtHelloWorld);
TPtrC myPtr(buffer); // the length will count automatically
%heap descriptor
like buffer , data is a part of descriptor , be the difference is ,it's in heap
HBufC ---- malloc()
actual assign size is base on the hardware unit ,so , maybe a little largerr than desire .
it's useful when data is too large for the descriptor , or data can't be known unitl the runtime
take care of the cleanup problem !!!
ex:
__LIT(KTxtHelloWorld,"Hello World!");
HBufC* buffer = HBufC::NewL(256); // object is not in cleanupstack !!! why not !???
*buffer = KTxtHelloWorld ;
Des() :
creat a TPtr
ex:
_LIT(KTxtFriends,"Friends !");
HBufC* buffer = HBuf::NewL(256);
*buffer = KTxtHelloWorld;
TPtr temp = buffer->Des();
temp.Replace(6,6,KTxtFriends);
Create HBufC FROM anther descriptor
_LIT(KTxtHelloWorld,"hello world");
myFunctionL(KTxtHelloWorld);
void myFunctionL(const TDesC& aBuffer)
{
HBufC* mydata = aBuffer.AllocLC();
}
How large is HBufC
base on the hardware , do NOT think the size is exactly equal TO your assignment
ReAllocL
_LIT(KTxtHelloWorld,"Hello World");
HBufC* myData = new HBufC::NewL(16);
*myData = KTxtHelloWorld; // HBufC can't be changed , what will happen when this line write twice ????
myData = myData->ReAllocL(256); //it will copy the old data to new address , and release the old one
//remember in this occasion , you must reset all the TPtr you get from Des() befroe.
%constant descriptor
C means could NOT be modify . can only be initialize . the only way TO change it is reassign it new data .
but it's not exactly like c++'s constant , it just doesn't contain the method to modify it's data .
nonC contain many methods TO change it's data within it's length
HBufC has TO use special method TO change it's data
%Base class
*TDesC -> TBufBase ->TBufC
->HBufC
-> TDes ->TBuf
->TPtr
-> TPtrC
TBufC: [TDesC][Data]
TBuf : [TDesC][TDes][Data][spaces]
TPtrC : [TDesC][Address]
TPtr : [TDesC][TDes][Address]
HBufC : [TDesC][Data]
%use abstract class in interface
const TDesC& : pass unchange data
TDes& : pass chengable data
ex:
void greeting(TDes& aGreeting, const TDesC& aEntity)
{
aGreeting.Append(aEntity);
}
%Macro
_LIT : create a TLitC object
_L : old style , less efficiency , inclue '\0' , be eliminated
work like TDesC:
_LIT(KHelloRom,"Hello");
const TDesC& helloDesC = KHelloRom;
& : return const TDesC*
(): return const TDesC&
%Funcetions
basic:
manage:
string:
format:
%use desriptor TO save binary data
TDesC16
TDesC8 : usful for communication program
ACTIVE OBJECT
asy service
req prog -> req -> do other things (another req)-> ... -> finally hold , waiting for reply -> os wake up this prog
-> other thread do the job -> finish |
single thread context non-preemptive multitasking
any time , only one event code can run . other event have TO be held
preemptive multitasking
symbian support this , but Active Object is NOT used TO work in this way
schedule
Active Scheduler ---contain many active object ---
active object ---contruct---> define the priority
---implement--> request function
---request----> according TO an event
---waiting---->
---schedule--
->one object left : run it
-> many objects : run the high prior
-> no fitable object : wait
---call object's RunL()
--- run ------>
--- finish ----
---schedure--
// active object (thread) -> recv events //??? active obj control the event's prior????
// -> run
// -> finish -> be controled BY activation schedule
// ->schedule -> one object left : run it
// -> many objects : run the high prior
// -> no fitable object : wait
in many system , multithread will be the first choice TO manager multitasking ,
but in Symbian , Active Objct is the first choice .
cooperative multitasking . (difference) active obj monopolize the os
??what's the relation between Active Object and Thread ???
in fact in UI frame , all event code is run BY one Active Object's RunL()