Monday, May 09, 2005

11. What is the layout of non-modifable descriptors?

First, let’s distinguish between descriptor literals, which are constant and can be built into ROM because their contents is fixed at build time, and non-modifable descriptors, whose contents are constant but not fixed at build time. Symbian OS, literals are treated a bit differently to the other descriptors, and I’ll discuss them separately in 22. What are literal descriptors?.

All (non-literal) descriptors derive from the base class TDesC (typedef’d to TDesC16 in e32std.h and defined in e32des16.h). The ‘C’ at the end of the class name indicates that the descriptor is non-modifiable. TDesC class has methods for determining the length of the descriptor and accessing its data, and implements other descriptor methods which access the descriptor data but do not modify it, such as data access, comparison and search functionality.

It is worth pointing out that all non-modifiable descriptor methods are implemented in this generic base class rather than overridden by each non-modifiable descriptor subclass (TBufC, TPtrC and HBufC). This is for memory efficiency. It’s done this way, rather than by use of virtual functions, because these would require each derived descriptor object to occupy an extra 4 bytes by adding a virtual pointer (vptr) for access to the virtual function table. This memory size overhead is undesirable, particularly for smaller strings, where the 4 bytes becomes a large percentage of the overall size.

And by keeping the descriptor methods in the base classes, the amount of code to implement a full set of string functionality is minimized too. This reuse is a benefit in terms of ROM size, and an illustration of C++ best practice for testing and maintenance. The subclasses only implement specific methods for construction and copy assignment.

The first 4 bytes of every descriptor object is the same: these hold the length of the data it currently contains. Well, actually, only 28 of these 32 bits are used to hold the length of the descriptor data; the top 4 bits are used to indicate the type of descriptor. The use of 4 bits to identify the type limits the number of different types of descriptor to 2^4 (=16), but since only six types have been necessary in all previous releases of Symbian OS (TBufC, TBuf, TPtrC, TPtr, HBufC and RBuf) , it seems unlikely that the range will need to be extended significantly in future. The use of the other 28 bits to store the data length, also means that the maximum number of byes a descriptor may occupy is limited to 2^28 bytes = 256 MB.

The rest of the layout of a descriptor object depends upon the implementation of each of the subclasses. Access to the descriptor data of each type goes through the (nonvirtual) Ptr() method of the TDesC base class, which uses a switch statement to identify the type of descriptor (using the top 4 bits of the beginning of the descriptor object) and return the correct address for the beginning of its data.

Of course, this requires that the TDesC base class has knowledge of the memory layout of its subclasses hardcoded into Ptr(). This means that you can’t create your own descriptor class, deriving from TDesC, and expect it to work.

Comments:
Hi Jo,

Talking about addition of new descriptor classes;
Could you comment on RBuf that was included from Symbian 8.0a here as that is recommended to be used instead of HBufC now. What are the reasons for this?

Cheers,
Nitin
 
Hi Nitin

Sure. I'm actually in the process of creating a post about RBuf at present, but haven't quite finished it - and I want to run it past Symbian first, since I've not used RBuf once and want to check my facts! So watch this space :o)

Thanks for your comment.

Jo
 
I've now put posted
here about RBuf. After checking with Symbian, I don't think there's an explicit deprecation of HBufC, but it is clear that RBuf is very useful if you need to modify a dynamically allocated descriptor, or want to manage your heap-based buffer via a stack based R class object.
 
I still don't understand why the non-modifyable descriptors are modifyable.

If the C means conceptually const then why even provide the Des() method in the first place? Why call it constant but then allow it to be modified?

And is Des() is provided for HBufC and TBufC then why not be consistent and also provide it for TPtrC? Why is TPtrC an exception to the contradiction?
 
Sorry, I've run out of time to answer you today, but will do so tomorrow. If you're "potassium" and want to contact me directly by e-mail, to give me some more context of your questions on descriptors, please feel free to do so (my e-mail address is on my WhoShavesTheBarber website). Maybe we can fix up a Skype session or something.

Otherwise, please watch this space...
 
"I still don't understand why the non-modifyable descriptors are modifyable.

If the C means conceptually const then why even provide the Des() method in the first place? Why call it constant but then allow it to be modified?"


It's a semantic thing. The type reflects that the descriptor contents should be constant. But it will always be possible to form another pointer descriptor over the data in the descriptor, so the class provides the way to do it. A bit like the C++ const, which can always be subverted. That's my interpretation, anyway.

"And is Des() is provided for HBufC and TBufC then why not be consistent and also provide it for TPtrC? Why is TPtrC an exception to the contradiction?"

It's a bit inconsistent, perhaps, but TPtrC is already a pointer descriptor over a separate block of data. The data can be modified directly by creating a TPtr over it, so there's no Des() to do so. Hmm, doesn't sound like a great explanation, but the best I can think of now...
 
i am a beginner to symbianos environment. can u give full description about descriptors?
 
What do you mean? What do you think this blog is all about?
 
Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?

Google
WWW Descriptors FAQ