Symbian smart pointer

Source: Internet
Author: User
In the Symbian development process, because there is no deterministic structure, the most annoying thing is the cleanup stack operation. When using a local variable in a function,
Remember pushl, and then at the end of the function, you still need popanddestroy. There are a lot of variables, and you cannot find the north, often panic, and in the vc6 window
You can only perform one-step debugging until the program crash. Then you know that the last line is the problem.

The following is a smart pointer class I wrote (actually two, one cptr for C class, and one rptr for R class ), my own experience shows that 90% of cleanup stack operations can be exempted. (In fact, I have never used cleanupstack manually in the new Code)

For example, a simple code:
Void funl ()
{
Hbufc * wbuf = hbufc: newl (10 );
Cleanupstack: pushl (wbuf); // It is a bit of creation. hbufc: newlc should be used directly, just for example, because many classes only provide newl

Hbufc * wbuf2 = hbufc: newl (20 );
Cleanupstack: pushl (wbuf2 );

Rfs fs;
User: leaveiferor (FS. Connect ());
Cleanupclosepushl (FS );

Do_sth_maybe_leavelll ();

Cleanupstack: popanddestroy (3); // close the file FS, delete wbuf, wbuf2
}

If a new C object is added to the function, manually pushl it once, and remember to change popanddestroy (3) to 4 at the end.

The above code can be simplified:

Void funl ()
{
Using namespace SBL; // encapsulated in SBL

Cptr Cptr

Rptr <RFS> FS;
User: leaveiferor (FS-> connect (); // change fs. Connect () to FS-> connect ()

Do_sth_maybe_leavelll ();
}

You don't need to worry about anything in the future. Leave, leave, wbuf, and wbuf2 will eventually be deleted, and FS will be closed.

Remember:
1. Do not use cptr or rptr for member variables (you should know that member variables should not pushl themselves)
2. Do not mix cleanupstack and smart pointer classes in a function. Do not manually use pushl or hand it all over to smart pointers.
3. When initializing/assigning values to the cptr smart pointer, always call newl instead of calling CXXX: newlc (because newlc has pushl once.

In addition, with smart pointers, you basically don't need to provide newlc for your class, and the implementation in newl can be as follows:

/* Static */
Cfoo * cfoo: newl ()
{
Cptr <cfoo> Self (New (eleave) cfoo); // rest assured that cptr has pushl internally, protecting this self
Self-> constructl (); // No problem with leave. delete self is called.
Return self. Release (); // release releases the ownership so that the cptr structure will not delete self again.
}

Basically, you know auto_ptr in STL, and cptr. rptr is a little different. It is mainly used to use R class. Instead of T *, it puts T itself directly.

Another example of cptr is as follows:

Void Foo ()
{
Cptr * Wbuf = _ L ("Hello, world"); // assign a value to hbufc
Wbuf = 0; // release. Note that hbufc has been released, or reset (0) can be used.


Wbuf = hbufc: newl (20); // Memory Allocation
Wbuf = hbufc: newl (40); // oh, not enough. Release the allocated one. allocate a large memory.
* Wbuf = _ L ("long Hello, world ");
}

Basically, there is no difference between auto_ptr and STL. However, due to the cleanup mechanism of Symbian, cptr/rptr cannot be used as a member variable.

The following is the source code: (when using cptr, rptr is in SBL namespace, and assert of C library is used in debug)

# Include <e32base. h>

# Include <libc/assert. h>

# Include <libc/string. h>

Namespace SBL // SBL stands for Symbian Library
{
// A auto_ptr for any object can be free by "delete" Operator
// If you know STD: auto_ptr then no much thing you need to study
Template <class T>
Class cptr
{
Public:
// Take a raw pointer, this pointer must not been pushed into cleanup Stack
Explicit cptr (T * PTR = 0): PTR _ (PTR)
{
// No matter how we need a slot in cleanup Stack
Cleanuppushl ();
}

// Copy ctor, take ownership, just like STD: auto_ptr
Cptr (cptr <t> & other)
{
PTR _ = Other. Release ();
Cleanuppushl ();
}

// Assignment, take ownership, just like STD: auto_ptr
Cptr <t> & operator = (cptr <t> & other)
{
If (this! = & Other ){
Assert (PTR _! = Other. PTR _);
Reset (other. Release ());
}
Return * this;
}

Cptr <t> & operator = (T * PTR)
{
Reset (PTR );
Return * this;
}

/* Sorry, due to buggy vc6
Template <Class U>
Cptr (cptr <u> & other)
{
Cleanuppushl ();
PTR _ = Other. Release ();
}

Template <Class U>
Cptr <t> & operator = (cptr <u> & other)
{
Reset (other. Release ());
Reutrn * this;
}
*/
T & operator * () const
{
Assert (PTR _! = 0 );
Return * PTR _;
}

T * operator-> () const
{
Assert (PTR _! = 0 );
Return PTR _;
}

// Get the raw pointer explicitly
T * Get () const
{
Return PTR _;
}

Void reset (T * PTR = 0)
{
If (PTR! = PTR _)
{
Delete PTR _; // here we use "delete" to free resource
PTR _ = PTR;
}
}

// Release ownership
T * release ()
{
T * TMP = PTR _;
PTR _ = 0;
Return TMP;
}

// Normally exit, dispose
~ Cptr ()
{
Cleanupstack: popanddestroy (1, this); // remove from cleanup Stack
}

Typedef void (* safe_bool) (void * P );

// Used by if (c)
Operator safe_bool () const
{
Return PTR _? & Dispose: 0;
}

// Used by if (! C)
Bool Operator! () Const
{
Return safe_bool (* This) = 0;
}

PRIVATE:
T * PTR _;

Void cleanuppushl ()
{
Cleanupstack: pushl (tcleanupitem (onleave, this ));
}

Static void onleave (void * P );
};

// This function isn' t inline since cleanup stack want our function pointer
Template <class T>
Void cptr <t>: onleave (void * P)
{
Cptr * cptr = static_cast <cptr *> (P );
Cptr-> Reset (0 );
}

// Default R class uses close () to release resource
Template <class r>
Class rtrait
{
Public:
Static void dispose (R & R)
{
R. Close ();
}
Static bool connected (const R & R );
};

// Default R class check binary bits to determine if connected
Template <class r>
Bool rtrait <r >:: connected (const R & R)
{
Const char * Start = (const char *) & R;
Const char * end = start + sizeof (R );

For (; start! = End; Start ++)
{
If (* start! = 0)
Return true;
}
Return false;
}


Template <class R, class trait = rtrait <r>
Class rptr
{
Public:
Rptr ()
{
Assert (! Trait: connected (RES _));
Cleanupstack: pushl (tcleanupitem (onleave, this ));
}

Template <Class A1>
Rptr (const A1 & A): RES _ ()
{
Cleanupstack: pushl (tcleanupitem (onleave, this ));
}

/*
Template <Class A1, class A2>
Rptr (const A1 & A1, const A2 & A2): RES _ (a1, a2)
{
Cleanupstack: pushl (tcleanupitem (disposeinvoker, this ));
}

Template <Class A1, class A2, class A3>
Rptr (const A1 & A1, const A2 & A2, const A3 & A3): RES _ (A1, A2, A3)
{
Cleanupstack: pushl (tcleanupitem (disposeinvoker, this ));
}
*/

~ Rptr ()
{
Cleanupstack: popanddestroy (1, this); // remove from cleanup stack and delete
}

R * operator-> ()
{
Return & RES _;
}

R & operator *()
{
Return RES _;
}


R & get ()
{
Return RES _;
}

Operator R &()
{
Assert (safe_bool (* This ));
Return RES _;
}

Typedef void (* safe_bool) (void *);
// Used by if (r)
Operator safe_bool () const
{
Return trait: connected (RES _)? & Onleave: 0;
}

// Used by if (! R)
Bool Operator! () Const
{
Return safe_bool (* This) = 0;
}

PRIVATE:
R RES _;

Static void onleave (void * P );

// Noncopyable and assignable
Rptr & operator = (const rptr &);
Rptr (const rptr &);
};

Template <class R, class trait>
Void rptr <R, trait>: onleave (void * P)
{
Rptr <R, trait> * Self = static_cast <rptr <R, trait> *> (P );

// If (* Self) to check if the r class is connected
If (* Self ){
Trait: dispose (self-> RES _);
Assert (! Trait: connected (self-> RES _));
}
}

} // End of namespace

# Endif
 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.